michaelrsweet / mxml

Tiny XML library.
https://www.msweet.org/mxml
Apache License 2.0
428 stars 157 forks source link

mxml v2.0.1 - some bug fixes #2

Closed michaelrsweet closed 19 years ago

michaelrsweet commented 20 years ago

Version: 2.0rc1 Original reporter: Michael Sweet

Hello Michael,

according to your request...


Hello Michael,

I've fixed some bugs for which I've appended a small unified diff. The diff is commented, so I'll give you just a few notes here:

Greetings from Germany.

CU Tom. (Thomas M.Ott)

michaelrsweet commented 20 years ago

Original reporter: Michael Sweet

What OS, compiler, etc. are you using?

The "getc() | (getc() << 8)" construct is safe since I am using the bitwise OR operator. Only the logical operators (||, &&) are defined such that a compiler could safely optimize part of the test away.

vsnprintf(), for ANSI C and for POSIX anyways, is defined to return the total number of characters required, so it would be interesting to know which OS you are using which is not compliant - I'll probably write a test or always use mxml_vsnprintf()...

Will look through the patch and add any addition comments I come up with. Please let me know what OS, compiler, etc. you are using...

Thanks!

michaelrsweet commented 20 years ago

Original reporter: Michael Sweet

Some more notes on your patch:

  1. The coding style doesn't match the one I use; I'll update things as I go along, but please keep this in mind if you provide patches in the future.

  2. Passing NULL to realloc() is undefined in all but C99, IIRC. I know that most commercial UNIX's will blow up if you use it.

  3. sprintf() is void on some pre-ANSI platforms; I can add a test for this or use snprintf() to get a guaranteed return value instead of using slen, but that part of the part isn't portable.

  4. I like the changes to mxml_file_putc() and will incorporate them.

  5. The changes in the main() function of mxmldoc (using %ste and fprintf instead of fputs) are unnecessary and actually make the code less efficient.

  6. The changes in the add_variable() function of mxmldoc (manual string copy instead of strcpy and strlen calls) may or may not be more efficient - strlen and strcpy are heavily optimized on some platforms, which may make them faster than the manual code method. I will do some benchmarking to see if there is any perceptable difference.

  7. Similarly, the changes to use your scan4word() function may or may not provide a measurable improvement; will try things out and see if there is any.

  8. The big printf() calls replacing the multiple puts() calls should be OK, although since no format replacements are being done we can use puts() for the combined strings. I will verify that the strings aren't over 32k (should be, but that is a common limit on older platforms/compilers) and apply this change.

  9. The mass conversion of all puts() calls to printf() calls will actually slow things down substantially - printf() has a lot more overhead than puts(). Given the limited potential savings in code space, I'd rather have mxmldoc run faster.

  10. printf is slower by far than puts, fputs, fputc, and putc. It makes sense to replace putc, print, putc and similar sequences with a single printf, however I won't replace everything with a printf.

I will post a proposed patch against 2.0rc1 that incorporates some of your changes later today.

michaelrsweet commented 20 years ago

Original reporter: Michael Sweet

OK, I've attached my proposed patch which includes many of your optimizations and bug fixes. Please let me know if I have missed any bug fixes, as well as your system and compiler info.

Thanks!

michaelrsweet commented 19 years ago

Original reporter: Michael Sweet

This STR has not been updated by the submitter for two or more weeks and has been closed as required by the Mini-XML Configuration Management Plan. If the issue still requires resolution, please re-submit a new STR.

michaelrsweet commented 20 years ago

"thommy.diff":

--- mxml-2.0rc1/mxml-attr.c.orig    Sun May  2 18:04:40 2004
+++ mxml-2.0rc1/mxml-attr.c Mon May 31 10:34:29 2004
@@ -90,6 +90,7 @@
 {
   int      i;          /* Looping var */
   mxml_attr_t  *attr;          /* New attribute */
+  char     *newval;

 #ifdef DEBUG
@@ -104,6 +105,16 @@
   if (!node || node->type != MXML_ELEMENT || !name)
     return;

+  /* check it once -- (ThMO) */
+  if ( value == NULL)
+    newval= NULL;
+  else if ( ( newval= strdup( value)) == NULL)
+    {
+      mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
+                 name, node->value.element.name);
+      return;
+    }
+
  /*
   * Look for the attribute...
   */
@@ -117,13 +128,10 @@
       * Replace the attribute value and return...
       */

-      free(attr->value);
-
-      if (value)
-   attr->value = strdup(value);
-      else
-        attr->value = NULL;
+      if ( attr->value != NULL)    /* check added -- (ThMO) */
+   free(attr->value);

+      attr->value= newval; /* formerly no check after strdup() -- (ThMO) */
       return;
     }

@@ -131,11 +139,12 @@
   * Attribute not found, so add a new one...
   */

-  if (node->value.element.num_attrs == 0)
-    attr = malloc(sizeof(mxml_attr_t));
-  else
-    attr = realloc(node->value.element.attrs,
-                   (node->value.element.num_attrs + 1) * sizeof(mxml_attr_t));
+  /* realloc() works even if attrs == NULL - that way fixing a memory hole
+   * where the 1st malloc()d attrs would get lost if allocating the name
+   * failed later and calling this function again... -- (ThMO)
+   */
+  attr = realloc(node->value.element.attrs,
+                 (node->value.element.num_attrs + 1) * sizeof(mxml_attr_t));

   if (!attr)
   {
@@ -147,17 +156,9 @@
   node->value.element.attrs = attr;
   attr += node->value.element.num_attrs;

-  attr->name = strdup(name);
-  if (value)
-    attr->value = strdup(value);
-  else
-    attr->value = NULL;
-
-  if (!attr->name || (!attr->value && value))
+  attr->value= newval;
+  if ( ( attr->name= strdup( name)) == NULL)
   {
-    if (attr->name)
-      free(attr->name);
-
     if (attr->value)
       free(attr->value);

--- mxml-2.0rc1/mxml-entity.c.orig  Sun May 16 07:25:38 2004
+++ mxml-2.0rc1/mxml-entity.c   Mon May 31 10:35:12 2004
@@ -67,6 +67,11 @@
     callbacks[num_callbacks] = cb;
     num_callbacks ++;
   }
+  else /* do fail -- (ThMO) */
+    {
+      mxml_error("Unable to add callback - aborting");
+      exit( EXIT_FAILURE);
+    }
 }

--- mxml-2.0rc1/mxml-file.c.orig    Sun May 16 23:54:47 2004
+++ mxml-2.0rc1/mxml-file.c Mon May 31 10:37:03 2004
@@ -171,16 +171,6 @@
   if (bytes <= 0)
     return (NULL);

-  if (bytes < (int)(sizeof(buffer) - 1))
-  {
-   /*
-    * Node fit inside the buffer, so just duplicate that string and
-    * return...
-    */
-
-    return (strdup(buffer));
-  }
-
  /*
   * Allocate a buffer of the required size and save the node to the
   * new buffer...
@@ -189,7 +179,10 @@
   if ((s = malloc(bytes + 1)) == NULL)
     return (NULL);

-  mxmlSaveString(node, s, bytes + 1, cb);
+  if ( bytes < sizeof( buffer)- 1)
+    memcpy( s, buffer, bytes+ 1);  /* faster as size is known -- (ThMO) */
+  else
+    mxmlSaveString(node, s, bytes + 1, cb);

  /*
   * Return the allocated string...
@@ -225,8 +218,7 @@
   if ((col = mxml_write_node(node, fp, cb, 0, mxml_file_putc)) < 0)
     return (-1);

-  if (col > 0)
-    if (putc('\n', fp) < 0)
+  if (col > 0 && fprintf( fp, "\n") != 1)
       return (-1);

  /*
@@ -557,7 +549,10 @@
      * Multi-word UTF-16 char...
      */

-          int lch = (getc(fp) << 8) | getc(fp);
+          /* the former construction wasn't save... -- (ThMO) */
+          int  lch;
+          lch= getc(fp) << 8,
+          lch |= getc(fp);

           if (ch < 0xdc00 || ch >= 0xdfff)
        return (EOF);
@@ -579,7 +574,10 @@
      * Multi-word UTF-16 char...
      */

-          int lch = getc(fp) | (getc(fp) << 8);
+          /* the former construction wasn't save... -- (ThMO) */
+          int  lch;
+          lch= getc(fp),
+          lch |= getc(fp) << 8;

           if (ch < 0xdc00 || ch >= 0xdfff)
        return (EOF);
@@ -601,18 +599,21 @@
 mxml_file_putc(int  ch,            /* I - Character to write */
                void *p)            /* I - Pointer to file */
 {
+  char  buffer[ 4], *bufp;
+  int   buflen;
+
+  /* output chars once -- (ThMO) */
+  bufp= buffer;
   if (ch < 128)
-    return (putc(ch, (FILE *)p));
+    *bufp++= ch;
   else if (ch < 2048)
   {
    /*
     * Two-byte UTF-8 character...
     */

-    if (putc(0xc0 | (ch >> 6), (FILE *)p) < 0)
-      return (-1);
-    else
-      return (putc(0x80 | (ch & 0x3f), (FILE *)p));
+    *bufp++= 0xc0 | (ch >> 6),
+    *bufp++= 0x80 | (ch & 0x3f);
   }
   else if (ch < 65536)
   {
@@ -620,12 +621,9 @@
     * Three-byte UTF-8 character...
     */

-    if (putc(0xe0 | (ch >> 12), (FILE *)p) < 0)
-      return (-1);
-    else if (putc(0x80 | ((ch >> 6) & 0x3f), (FILE *)p) < 0)
-      return (-1);
-    else
-      return (putc(0x80 | (ch & 0x3f), (FILE *)p));
+    *bufp++= 0xe0 | (ch >> 12),
+    *bufp++= 0x80 | ((ch >> 6) & 0x3f),
+    *bufp++= 0x80 | (ch & 0x3f);
   }
   else
   {
@@ -633,15 +631,14 @@
     * Four-byte UTF-8 character...
     */

-    if (putc(0xf0 | (ch >> 18), (FILE *)p) < 0)
-      return (-1);
-    else if (putc(0x80 | ((ch >> 12) & 0x3f), (FILE *)p) < 0)
-      return (-1);
-    else if (putc(0x80 | ((ch >> 6) & 0x3f), (FILE *)p) < 0)
-      return (-1);
-    else
-      return (putc(0x80 | (ch & 0x3f), (FILE *)p));
-  }
+    *bufp++= 0xf0 | (ch >> 18),
+    *bufp++= 0x80 | ((ch >> 12) & 0x3f),
+    *bufp++= 0x80 | ((ch >> 6) & 0x3f),
+    *bufp++= 0x80 | (ch & 0x3f);
+  }
+  buflen= bufp- buffer;
+  return( fwrite( buffer, sizeof( char), buflen, (FILE *)p) != buflen
+       ? -1 : buflen);
 }

@@ -1633,6 +1630,7 @@
        width;          /* Width of attr + value */
   mxml_attr_t  *attr;          /* Current attribute */
   char     s[255];         /* Temporary string */
+  int      slen;

   while (node != NULL)
@@ -1779,11 +1777,11 @@
          col ++;
           }

-          sprintf(s, "%d", node->value.integer);
+          slen= sprintf(s, "%d", node->value.integer);
      if (mxml_write_string(s, p, putc_cb) < 0)
        return (-1);

-     col += strlen(s);
+     col += slen;
           break;

       case MXML_OPAQUE :
@@ -1809,11 +1807,11 @@
          col ++;
           }

-          sprintf(s, "%f", node->value.real);
+          slen= sprintf(s, "%f", node->value.real);
      if (mxml_write_string(s, p, putc_cb) < 0)
        return (-1);

-     col += strlen(s);
+     col += slen;
           break;

       case MXML_TEXT :
--- mxml-2.0rc1/mxml-index.c.orig   Sun May 16 20:25:20 2004
+++ mxml-2.0rc1/mxml-index.c    Mon May 31 09:34:25 2004
@@ -339,10 +339,8 @@
   {
     if (ind->num_nodes >= ind->alloc_nodes)
     {
-      if (!ind->alloc_nodes)
-        temp = malloc(64 * sizeof(mxml_node_t *));
-      else
-        temp = realloc(ind->nodes, (ind->alloc_nodes + 64) * sizeof(mxml_node_t *));
+      /* realloc handles nodes == NULL -- (ThMO) */
+      temp = realloc(ind->nodes, (ind->alloc_nodes + 64) * sizeof(mxml_node_t *));

       if (!temp)
       {
@@ -584,6 +582,8 @@
   * Sort the pivot in the current partition...
   */

+  do
+    {  /* removed end-recursion -- (ThMO) */
   pivot = ind->nodes[left];

   for (templ = left, tempr = right; templ < tempr;)
@@ -634,8 +634,8 @@
   if (left < (tempr - 1))
     index_sort(ind, left, tempr - 1);

-  if (right > (tempr + 1))
-    index_sort(ind, tempr + 1, right);
+    }  /* removed end-recursion -- (ThMO) */
+  while ( right > ( left= tempr+ 1));
 }

--- mxml-2.0rc1/mxml-private.c.orig Sun May  2 18:04:40 2004
+++ mxml-2.0rc1/mxml-private.c  Mon May 31 09:39:50 2004
@@ -74,11 +74,7 @@
   if (mxml_error_cb)
     (*mxml_error_cb)(s);
   else
-  {
-    fputs("mxml: ", stderr);
-    fputs(s, stderr);
-    putc('\n', stderr);
-  }
+    fprintf( stderr, "mxml: %s\n", s); /* 1 instr. -- (ThMO) */

  /*
   * Free the string...
--- mxml-2.0rc1/mxml-string.c.orig  Sun May  2 18:04:40 2004
+++ mxml-2.0rc1/mxml-string.c   Mon May 31 11:41:15 2004
@@ -27,7 +27,7 @@
  */

 #include "config.h"
-
+#include "mxml.h"  /* for mxml_error() -- (ThMO) */

 /*
  * 'mxml_strdup()' - Duplicate a string.
@@ -61,38 +61,37 @@
 {
   int  bytes;              /* Number of bytes required */
   char *buffer,            /* String buffer */
-   temp[256];          /* Small buffer for first vsnprintf */
-
+   *newbuf;
+  int   bufsize;

  /*
   * First format with a tiny buffer; this will tell us how many bytes are
   * needed...
   */

-  bytes = vsnprintf(temp, sizeof(temp), format, ap);
-
-  if (bytes < sizeof(temp))
-  {
-   /*
-    * Hey, the formatted string fits in the tiny buffer, so just dup that...
-    */
-
-    return (strdup(temp));
-  }
-
- /*
-  * Allocate memory for the whole thing and reformat to the new, larger
-  * buffer...
-  */
-
-  if ((buffer = calloc(1, bytes + 1)) != NULL)
-    vsnprintf(buffer, bytes + 1, format, ap);
-
- /*
-  * Return the new string...
-  */
-
-  return (buffer);
+  /* this is *wrong* - [v]snprintf() will return -1, if the buffer isn't
+   * large enough to hold the result... -- (ThMO)
+   */
+  for ( buffer= NULL, bufsize= 256/ 2;  ;  )
+    {
+      if ( ( newbuf= realloc( buffer, bufsize *= 2)) == NULL)
+        {
+          if ( buffer != NULL)
+            free( buffer);
+          mxml_error("mxml_strdupf(): unable to allocate %d bytes", bufsize);
+          return( NULL);
+        }
+      if ( ( bytes= vsnprintf( buffer= newbuf, bufsize, format, ap)) >= 0)
+        break;
+    }
+  if ( bytes == 0)
+    {
+      free( buffer);
+      newbuf= NULL;
+    }
+  else if ( ( newbuf= realloc( buffer, bytes+ 1)) == NULL)
+    newbuf= buffer;
+  return( newbuf);
 }

--- mxml-2.0rc1/mxmldoc.c.orig  Mon May  3 00:02:36 2004
+++ mxml-2.0rc1/mxmldoc.c   Mon May 31 11:39:13 2004
@@ -143,6 +143,8 @@
 static void        write_string(const char *s);
 static const char  *ws_cb(mxml_node_t *node, int where);

+static int
+  scan4word( const char *str, const char *word);

 /*
  * 'main()' - Main entry for test program.
@@ -164,7 +166,8 @@

   if (argc < 2)
   {
-    fputs("Usage: mxmldoc filename.xml [source files] >filename.html\n", stderr);
+    fprintf( stderr,
+             "Usage: mxmldoc filename.xml [source files] >filename.html\n");
     return (1);
   }

@@ -265,8 +268,8 @@

       if (mxmlSaveFile(doc, fp, ws_cb))
       {
-   fprintf(stderr, "Unable to write the XML documentation file \"%s\": %s!\n",
-           argv[1], strerror(errno));
+   fprintf(stderr, "Unable to %ste the XML documentation file \"%s\": %s!\n",
+           "wri", argv[1], strerror(errno));
    fclose(fp);
    mxmlDelete(doc);
    return (1);
@@ -276,8 +279,8 @@
     }
     else
     {
-      fprintf(stderr, "Unable to create the XML documentation file \"%s\": %s!\n",
-              argv[1], strerror(errno));
+      fprintf(stderr, "Unable to %ste the XML documentation file \"%s\": %s!\n",
+              "crea", argv[1], strerror(errno));
       mxmlDelete(doc);
       return (1);
     }
@@ -312,7 +315,8 @@
        *node,          /* Current node */
        *next;          /* Next node */
   char     buffer[16384],      /* String buffer */
-       *bufptr;        /* Pointer into buffer */
+       *bufptr,        /* Pointer into buffer */
+       *s;

  /*
@@ -333,8 +337,9 @@
   */

   for (node = type->child; node; node = node->next)
-    if (!strcmp(node->value.text.string, "="))
-      break;
+    if ( *node->value.text.string == '='
+         && node->value.text.string[ 1] == '\0')
+      break;   /* strcmp() eliminated -- (ThMO) */

   if (node)
   {
@@ -342,17 +347,22 @@
     * Default value found, copy it and add as a "default" attribute...
     */

-    for (bufptr = buffer; node; bufptr += strlen(bufptr))
+    bufptr= buffer;
+    do
     {
       if (node->value.text.whitespace && bufptr > buffer)
    *bufptr++ = ' ';

-      strcpy(bufptr, node->value.text.string);
+      /* don't run string twice -- (ThMO) */
+      s= node->value.text.string;
+      while ( ( *bufptr= *s++) != '\0')
+        bufptr++;

       next = node->next;
       mxmlDelete(node);
       node = next;
     }
+    while ( node != NULL);

     mxmlElementSetAttr(variable, "default", buffer);
   }
@@ -371,12 +381,15 @@
       if (node->value.text.string[0] == '(')
    break;

-    for (bufptr = buffer; node; bufptr += strlen(bufptr))
+    for (bufptr = buffer; node; )
     {
       if (node->value.text.whitespace && bufptr > buffer)
    *bufptr++ = ' ';

-      strcpy(bufptr, node->value.text.string);
+      /* don't run string twice -- (ThMO) */
+      s= node->value.text.string;
+      while ( ( *bufptr= *s++) != '\0')
+        bufptr++;

       next = node->next;
       mxmlDelete(node);
@@ -442,7 +455,8 @@
        parens;         /* Number of active parenthesis */
   int      ch;         /* Current character */
   char     buffer[65536],      /* String buffer */
-       *bufptr;        /* Pointer into buffer */
+       *bufptr,        /* Pointer into buffer */
+       *s;
   const char   *scope;         /* Current variable/function scope */
   mxml_node_t  *comment,       /* <comment> node */
        *constant,      /* <constant> node */
@@ -642,12 +656,15 @@
          {
            for (bufptr = buffer, node = type->child->next->next;
                 node;
-            bufptr += strlen(bufptr))
+            )
            {
              if (node->value.text.whitespace && bufptr > buffer)
            *bufptr++ = ' ';

-             strcpy(bufptr, node->value.text.string);
+             /* don't run string twice -- (ThMO) */
+             s= node->value.text.string;
+             while ( ( *bufptr= *s++) != '\0')
+           bufptr++;

              next = node->next;
              mxmlDelete(node);
@@ -1264,8 +1281,7 @@
          {
        if (!strcmp(tree->value.element.name, "class"))
        {
-         if (!strcmp(buffer, "public") ||
-                 !strcmp(buffer, "public:"))
+         if ( scan4word(buffer, "public"))
          {
            scope = "public";
 #ifdef DEBUG
@@ -1273,8 +1289,7 @@
 #endif /* DEBUG */
            break;
          }
-         else if (!strcmp(buffer, "private") ||
-                      !strcmp(buffer, "private:"))
+         else if ( scan4word(buffer, "private"))
          {
            scope = "private";
 #ifdef DEBUG
@@ -1282,8 +1297,7 @@
 #endif /* DEBUG */
            break;
          }
-         else if (!strcmp(buffer, "protected") ||
-                      !strcmp(buffer, "protected:"))
+         else if ( scan4word(buffer, "protected"))
          {
            scope = "protected";
 #ifdef DEBUG
@@ -1558,6 +1572,18 @@
   return (0);
 }

+static int
+scan4word( const char *str, const char *word)
+{
+  int  wlen;
+
+  /* do a strcmp() once -- (ThMO) */
+  wlen= strlen( word);
+  return( strncmp( str, word, wlen) == 0
+     && ( str[ wlen] == '\0'
+          || ( str[ wlen] == ':' && str[ wlen+ 1] == '\0'))
+       ? 1 : 0);
+}

 /*
  * 'sort_node()' - Insert a node sorted into a tree.
@@ -1778,42 +1804,42 @@
   * Standard header...
   */

-  puts("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
-       "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
-  puts("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>");
-  puts("<head>");
-  puts("\t<title>Documentation</title>");
-  puts("\t<meta name='creator' content='" MXML_VERSION "'/>");
-  puts("\t<style><!--");
-  puts("\th1, h2, h3, p { font-family: sans-serif; text-align: justify; }");
-  puts("\ttt, pre a:link, pre a:visited, tt a:link, tt a:visited { font-weight: bold; color: #7f0000; }");
-  puts("\tpre { font-weight: bold; color: #7f0000; margin-left: 2em; }");
-  puts("\t--></style>");
-  puts("</head>");
-  puts("<body>");
+  printf("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
+    "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
+    "<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"
+    "<head>\n"
+    "\t<title>Documentation</title>\n"
+    "\t<meta name='creator' content='" MXML_VERSION "'/>\n"
+    "\t<style><!--\n"
+    "\th1, h2, h3, p { font-family: sans-serif; text-align: justify; }\n"
+    "\ttt, pre a:link, pre a:visited, tt a:link, tt a:visited { font-weight: bold; color: #7f0000; }\n"
+    "\tpre { font-weight: bold; color: #7f0000; margin-left: 2em; }\n"
+    "\t--></style>\n"
+    "</head>\n"
+    "<body>\n"
+    "<h2>Contents</h2>\n"
+    "<ul>\n");

  /*
   * Table of contents...
   */

-  puts("<h2>Contents</h2>");
-  puts("<ul>");
   if (mxmlFindElement(doc, doc, "class", NULL, NULL, MXML_DESCEND_FIRST))
-    puts("\t<li><a href='#_classes'>Classes</a></li>");
+    printf("\t<li><a href='#_classes'>Classes</a></li>\n");
   if (mxmlFindElement(doc, doc, "enumeration", NULL, NULL, MXML_DESCEND_FIRST))
-    puts("\t<li><a href='#_enumerations'>Enumerations</a></li>");
+    printf("\t<li><a href='#_enumerations'>Enumerations</a></li>\n");
   if (mxmlFindElement(doc, doc, "function", NULL, NULL, MXML_DESCEND_FIRST))
-    puts("\t<li><a href='#_functions'>Functions</a></li>");
+    printf("\t<li><a href='#_functions'>Functions</a></li>\n");
   if (mxmlFindElement(doc, doc, "struct", NULL, NULL, MXML_DESCEND_FIRST))
-    puts("\t<li><a href='#_structures'>Structures</a></li>");
+    printf("\t<li><a href='#_structures'>Structures</a></li>\n");
   if (mxmlFindElement(doc, doc, "typedef", NULL, NULL, MXML_DESCEND_FIRST))
-    puts("\t<li><a href='#_types'>Types</a></li>");
+    printf("\t<li><a href='#_types'>Types</a></li>\n");
   if (mxmlFindElement(doc, doc, "union", NULL, NULL, MXML_DESCEND_FIRST))
-    puts("\t<li><a href='#_unions'>Unions</a></li>");
+    printf("\t<li><a href='#_unions'>Unions</a></li>\n");
   if (mxmlFindElement(doc, doc, "variable", NULL, NULL, MXML_DESCEND_FIRST))
-    puts("\t<li><a href='#_variables'>Variables</a></li>");
-  puts("</ul>");
+    printf("\t<li><a href='#_variables'>Variables</a></li>\n");
+  printf("</ul>\n");

  /*
   * List of classes...
@@ -1821,9 +1847,9 @@

   if (mxmlFindElement(doc, doc, "class", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_classes'>Classes</a></h2>");
-    puts("<ul>");
+    printf("<!-- NEW PAGE -->\n"
+      "<h2><a name='_classes'>Classes</a></h2>\n"
+      "<ul>\n");

     for (scut = mxmlFindElement(doc, doc, "class", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -1835,7 +1861,7 @@
       printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
     }

-    puts("</ul>");
+    printf("</ul>\n");

     for (scut = mxmlFindElement(doc, doc, "class", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -1844,27 +1870,22 @@
                            MXML_NO_DESCEND))
     {
       cname = mxmlElementGetAttr(scut, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", cname, cname);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n" "<h3><a name='%s'>%s</a></h3>\n"
+        "<hr noshade/>\n", cname, cname);

       description = mxmlFindElement(scut, scut, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        printf("<h4>Description</h4>\n<p>");
    write_element(NULL, description);
-   puts("</p>");
+   printf("</p>\n");
       }

-      puts("<h4>Definition</h4>");
-      puts("<pre>");
-
-      printf("class %s", cname);
+      printf("<h4>Definition</h4>\n<pre>\n" "class %s", cname);
       if ((parent = mxmlElementGetAttr(scut, "parent")) != NULL)
         printf(" %s", parent);
-      puts("\n{");
+      printf("\n{\n");

       for (i = 0; i < 3; i ++)
       {
@@ -1911,10 +1932,10 @@
      {
        write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
                                                NULL, MXML_DESCEND_FIRST));
-       putchar(' ');
+       printf( " ");
      }
      else if (strcmp(cname, name) && strcmp(cname, name + 1))
-       fputs("void ", stdout);
+       printf("void ");

      printf("<a href='#%s.%s'>%s</a>", cname, name, name);

@@ -1927,35 +1948,32 @@
        type = mxmlFindElement(arg, arg, "type", NULL, NULL,
                           MXML_DESCEND_FIRST);

-       putchar(prefix);
+       printf( "%c", prefix);
        if (prefix == ',')
-         putchar(' ');
+         printf(" ");

        if (type->child)
        {
          write_element(doc, type);
-         putchar(' ');
+         printf(" ");
        }
-       fputs(mxmlElementGetAttr(arg, "name"), stdout);
+       printf( "%s", mxmlElementGetAttr(arg, "name"));
             if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
          printf(" %s", defval);
      }

      if (prefix == '(')
-       puts("(void);");
+       printf("(void);\n");
      else
-       puts(");");
+       printf(");\n");
    }
       }

-      puts("};\n</pre>");
-
-      puts("<h4>Members</h4>");
-
-      puts("<p class='table'><table align='center' border='1' "
-           "cellpadding='5' cellspacing='0' width='80%'>");
-      puts("<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>");
-      puts("<tbody>");
+      printf("};\n</pre>\n" "<h4>Members</h4>\n"
+        "<p class='table'><table align='center' border='1' "
+        "cellpadding='5' cellspacing='0' width='80%%'>\n"
+        "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
+        "<tbody>\n");

       for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
                             MXML_DESCEND_FIRST);
@@ -1968,7 +1986,7 @@
    write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
                                             NULL, MXML_DESCEND_FIRST));

-   puts("</td></tr>");
+   printf("</td></tr>\n");
       }

       for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
@@ -1992,15 +2010,15 @@

    if (arg)
    {
-     fputs("\n<i>Returns:</i> ", stdout);
+     printf("\n<i>Returns:</i> ");
      write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
                                               NULL, MXML_DESCEND_FIRST));
    }

-   puts("</td></tr>");
+   printf("</td></tr>\n");
       }

-      puts("</tbody></table></p>");
+      printf("</tbody></table></p>\n");

     }
   }
@@ -2011,9 +2029,9 @@

   if (mxmlFindElement(doc, doc, "enumeration", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_enumerations'>Enumerations</a></h2>");
-    puts("<ul>");
+    printf("<!-- NEW PAGE -->\n"
+      "<h2><a name='_enumerations'>Enumerations</a></h2>\n"
+      "<ul>\n");

     for (scut = mxmlFindElement(doc, doc, "enumeration", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2025,7 +2043,7 @@
       printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
     }

-    puts("</ul>");
+    printf("</ul>\n");

     for (scut = mxmlFindElement(doc, doc, "enumeration", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2034,26 +2052,23 @@
                            MXML_NO_DESCEND))
     {
       name = mxmlElementGetAttr(scut, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", name, name);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n" "<h3><a name='%s'>%s</a></h3>\n"
+        "<hr noshade/>\n", name, name);

       description = mxmlFindElement(scut, scut, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        printf("<h4>Description</h4>\n<p>");
    write_element(NULL, description);
-   puts("</p>");
+   printf("</p>\n");
       }

-      puts("<h4>Values</h4>");
-
-      puts("<p class='table'><table align='center' border='1' width='80%' "
-           "cellpadding='5' cellspacing='0' width='80%'>");
-      puts("<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>");
-      puts("<tbody>");
+      printf("<h4>Values</h4>\n" 
+        "<p class='table'><table align='center' border='1' width='80%%' "
+        "cellpadding='5' cellspacing='0' width='80%%'>\n"
+        "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
+        "<tbody>\n");

       for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
                             MXML_DESCEND_FIRST);
@@ -2066,10 +2081,10 @@
    write_element(doc, mxmlFindElement(arg, arg, "description", NULL,
                                            NULL, MXML_DESCEND_FIRST));

-   puts("</td></tr>");
+   printf("</td></tr>\n");
       }

-      puts("</tbody></table></p>");
+      printf("</tbody></table></p>\n");
     }
   }

@@ -2079,9 +2094,8 @@

   if (mxmlFindElement(doc, doc, "function", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_functions'>Functions</a></h2>");
-    puts("<ul>");
+    printf("<!-- NEW PAGE -->\n" "<h2><a name='_functions'>Functions</a></h2>\n"
+      "<ul>\n");

     for (function = mxmlFindElement(doc, doc, "function", NULL, NULL,
                                     MXML_DESCEND_FIRST);
@@ -2093,7 +2107,7 @@
       printf("\t<li><a href='#%s'><tt>%s()</tt></a></li>\n", name, name);
     }

-    puts("</ul>");
+    printf("</ul>\n");

     for (function = mxmlFindElement(doc, doc, "function", NULL, NULL,
                                     MXML_DESCEND_FIRST);
@@ -2102,22 +2116,19 @@
                                     MXML_NO_DESCEND))
     {
       name = mxmlElementGetAttr(function, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s()</a></h3>\n", name, name);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n" "<h3><a name='%s'>%s()</a></h3>\n"
+        "<hr noshade/>\n", name, name);

       description = mxmlFindElement(function, function, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        printf("<h4>Description</h4>\n<p>");
    write_element(NULL, description);
-   puts("</p>");
+   printf("</p>\n");
       }

-      puts("<h4>Syntax</h4>");
-      puts("<pre>");
+      printf("<h4>Syntax</h4>\n<pre>\n");

       arg = mxmlFindElement(function, function, "returnvalue", NULL,
                             NULL, MXML_DESCEND_FIRST);
@@ -2126,7 +2137,7 @@
    write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
                                            NULL, MXML_DESCEND_FIRST));
       else
-   fputs("void", stdout);
+   printf("void");

       printf("\n%s", name);
       for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
@@ -2142,28 +2153,23 @@
    if (type->child)
    {
      write_element(doc, type);
-     putchar(' ');
+     printf( " ");
    }
    fputs(mxmlElementGetAttr(arg, "name"), stdout);
         if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
      printf(" %s", defval);
       }

-      if (prefix == '(')
-   puts("(void);\n</pre>");
-      else
-   puts(");\n</pre>");
-
-      puts("<h4>Arguments</h4>");
+      printf( &"(void);\n</pre>\n<h4>Arguments</h4>\n"[ prefix == '(' ? 0 : 5]);

       if (prefix == '(')
-   puts("<p>None.</p>");
+   printf("<p>None.</p>\n");
       else
       {
-   puts("<p class='table'><table align='center' border='1' width='80%' "
-             "cellpadding='5' cellspacing='0' width='80%'>");
-   puts("<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>");
-   puts("<tbody>");
+   printf("<p class='table'><table align='center' border='1' width='80%%' "
+          "cellpadding='5' cellspacing='0' width='80%%'>\n"
+          "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
+          "<tbody>\n");

    for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
                               MXML_DESCEND_FIRST);
@@ -2176,25 +2182,25 @@
      write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
                                              NULL, MXML_DESCEND_FIRST));

-          puts("</td></tr>");
+          printf("</td></tr>\n");
    }

-   puts("</tbody></table></p>");
+   printf("</tbody></table></p>\n");
       }

-      puts("<h4>Returns</h4>");
+      printf("<h4>Returns</h4>\n");

       arg = mxmlFindElement(function, function, "returnvalue", NULL,
                             NULL, MXML_DESCEND_FIRST);

       if (!arg)
-   puts("<p>Nothing.</p>");
+   printf("<p>Nothing.</p>\n");
       else
       {
-   fputs("<p>", stdout);
+   printf("<p>");
    write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
                                             NULL, MXML_DESCEND_FIRST));
-   puts("</p>");
+   printf("</p>\n");
       }
     }
   }
@@ -2205,9 +2211,8 @@

   if (mxmlFindElement(doc, doc, "struct", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_structures'>Structures</a></h2>");
-    puts("<ul>");
+    printf("<!-- NEW PAGE -->\n"
+      "<h2><a name='_structures'>Structures</a></h2>\n" "<ul>\n");

     for (scut = mxmlFindElement(doc, doc, "struct", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2219,7 +2224,7 @@
       printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
     }

-    puts("</ul>");
+    printf("</ul>\n");

     for (scut = mxmlFindElement(doc, doc, "struct", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2228,24 +2233,19 @@
                            MXML_NO_DESCEND))
     {
       cname = mxmlElementGetAttr(scut, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", cname, cname);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n" "<h3><a name='%s'>%s</a></h3>\n"
+        "<hr noshade/>\n", cname, cname);

       description = mxmlFindElement(scut, scut, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        printf("<h4>Description</h4>\n<p>");
    write_element(NULL, description);
-   puts("</p>");
+   printf("</p>\n");
       }

-      puts("<h4>Definition</h4>");
-      puts("<pre>");
-
-      printf("struct %s\n{\n", cname);
+      printf("<h4>Definition</h4>\n<pre>\n" "struct %s\n{\n", cname);
       for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
                             MXML_DESCEND_FIRST);
       arg;
@@ -2275,10 +2275,10 @@
    {
      write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
                                              NULL, MXML_DESCEND_FIRST));
-     putchar(' ');
+     printf( " ");
    }
    else if (strcmp(cname, name) && strcmp(cname, name + 1))
-     fputs("void ", stdout);
+     printf("void ");

    printf("<a href='#%s.%s'>%s</a>", cname, name, name);

@@ -2291,34 +2291,31 @@
      type = mxmlFindElement(arg, arg, "type", NULL, NULL,
                         MXML_DESCEND_FIRST);

-     putchar(prefix);
+     printf( "%c", prefix);
      if (prefix == ',')
-       putchar(' ');
+       printf( " ");

      if (type->child)
      {
        write_element(doc, type);
-       putchar(' ');
+       printf( " ");
      }
-     fputs(mxmlElementGetAttr(arg, "name"), stdout);
+     printf( "%s", mxmlElementGetAttr(arg, "name"));
           if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
        printf(" %s", defval);
    }

    if (prefix == '(')
-     puts("(void);");
+     printf("(void);\n");
    else
-     puts(");");
+     printf(");\n");
       }

-      puts("};\n</pre>");
-
-      puts("<h4>Members</h4>");
-
-      puts("<p class='table'><table align='center' border='1' width='80%' "
-           "cellpadding='5' cellspacing='0' width='80%'>");
-      puts("<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>");
-      puts("<tbody>");
+      printf("};\n</pre>\n" "<h4>Members</h4>\n"
+        "<p class='table'><table align='center' border='1' width='80%%' "
+        "cellpadding='5' cellspacing='0' width='80%%'>\n"
+        "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
+        "<tbody>\n");

       for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
                             MXML_DESCEND_FIRST);
@@ -2331,7 +2328,7 @@
    write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
                                             NULL, MXML_DESCEND_FIRST));

-   puts("</td></tr>");
+   printf("</td></tr>\n");
       }

       for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
@@ -2355,15 +2352,15 @@

    if (arg)
    {
-     fputs("\n<i>Returns:</i> ", stdout);
+     printf("\n<i>Returns:</i> ");
      write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
                                               NULL, MXML_DESCEND_FIRST));
    }

-   puts("</td></tr>");
+   printf("</td></tr>\n");
       }

-      puts("</tbody></table></p>");
+      printf("</tbody></table></p>\n");
     }
   }

@@ -2373,9 +2370,8 @@

   if (mxmlFindElement(doc, doc, "typedef", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_types'>Types</a></h2>");
-    puts("<ul>");
+    printf("<!-- NEW PAGE -->\n" "<h2><a name='_types'>Types</a></h2>\n"
+      "<ul>\n");

     for (scut = mxmlFindElement(doc, doc, "typedef", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2387,7 +2383,7 @@
       printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
     }

-    puts("</ul>");
+    printf("</ul>\n");

     for (scut = mxmlFindElement(doc, doc, "typedef", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2396,24 +2392,19 @@
                            MXML_NO_DESCEND))
     {
       name = mxmlElementGetAttr(scut, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", name, name);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n" "<h3><a name='%s'>%s</a></h3>\n"
+        "<hr noshade/>\n", name, name);

       description = mxmlFindElement(scut, scut, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        printf("<h4>Description</h4>\n<p>");
    write_element(NULL, description);
-   puts("</p>");
+   printf("</p>\n");
       }

-      puts("<h4>Definition</h4>");
-      puts("<pre>");
-
-      printf("typedef ");
+      printf("<h4>Definition</h4>\n<pre>\n" "typedef ");
       write_element(doc, mxmlFindElement(scut, scut, "type", NULL,
                                          NULL, MXML_DESCEND_FIRST));
       printf(" %s;\n</pre>\n", name);
@@ -2426,9 +2417,8 @@

   if (mxmlFindElement(doc, doc, "union", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_unions'>Unions</a></h2>");
-    puts("<ul>");
+    printf("<!-- NEW PAGE -->\n" "<h2><a name='_unions'>Unions</a></h2>\n"
+      "<ul>\n");

     for (scut = mxmlFindElement(doc, doc, "union", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2440,7 +2430,7 @@
       printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
     }

-    puts("</ul>");
+    printf("</ul>\n");

     for (scut = mxmlFindElement(doc, doc, "union", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2449,24 +2439,19 @@
                            MXML_NO_DESCEND))
     {
       name = mxmlElementGetAttr(scut, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", name, name);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n" "<h3><a name='%s'>%s</a></h3>\n"
+        "<hr noshade/>\n", name, name);

       description = mxmlFindElement(scut, scut, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        printf("<h4>Description</h4>\n<p>");
    write_element(NULL, description);
-   puts("</p>");
+   printf("</p>\n");
       }

-      puts("<h4>Definition</h4>");
-      puts("<pre>");
-
-      printf("union %s\n{\n", name);
+      printf("<h4>Definition</h4>\n<pre>" "union %s\n{\n", name);
       for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
                             MXML_DESCEND_FIRST);
       arg;
@@ -2479,14 +2464,11 @@
    printf(" %s;\n", mxmlElementGetAttr(arg, "name"));
       }

-      puts("};\n</pre>");
-
-      puts("<h4>Members</h4>");
-
-      puts("<p class='table'><table align='center' border='1' width='80%' "
-           "cellpadding='5' cellspacing='0' width='80%'>");
-      puts("<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>");
-      puts("<tbody>");
+      printf("};\n</pre>\n" "<h4>Members</h4>\n"
+        "<p class='table'><table align='center' border='1' width='80%%' "
+        "cellpadding='5' cellspacing='0' width='80%%'>\n"
+        "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
+        "<tbody>\n");

       for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
                             MXML_DESCEND_FIRST);
@@ -2499,10 +2481,10 @@
    write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
                                             NULL, MXML_DESCEND_FIRST));

-   puts("</td></tr>");
+   printf("</td></tr>\n");
       }

-      puts("</tbody></table></p>");
+      printf("</tbody></table></p>\n");
     }
   }

@@ -2512,9 +2494,8 @@

   if (mxmlFindElement(doc, doc, "variable", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_variables'>Variables</a></h2>");
-    puts("<ul>");
+    printf("<!-- NEW PAGE -->\n" "<h2><a name='_variables'>Variables</a></h2>\n"
+      "<ul>\n");

     for (arg = mxmlFindElement(doc, doc, "variable", NULL, NULL,
                                MXML_DESCEND_FIRST);
@@ -2526,7 +2507,7 @@
       printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
     }

-    puts("</ul>");
+    printf("</ul>\n");

     for (arg = mxmlFindElement(doc, doc, "variable", NULL, NULL,
                                MXML_DESCEND_FIRST);
@@ -2535,29 +2516,26 @@
                                MXML_NO_DESCEND))
     {
       name = mxmlElementGetAttr(arg, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", name, name);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n" "<h3><a name='%s'>%s</a></h3>\n"
+        "<hr noshade/>\n", name, name);

       description = mxmlFindElement(arg, arg, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        printf("<h4>Description</h4>\n<p>");
    write_element(NULL, description);
-   puts("</p>");
+   printf("</p>\n");
       }

-      puts("<h4>Definition</h4>");
-      puts("<pre>");
+      printf("<h4>Definition</h4>\n<pre>\n");

       write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
                                          NULL, MXML_DESCEND_FIRST));
       printf(" %s", mxmlElementGetAttr(arg, "name"));
       if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
    printf(" %s", defval);
-      puts(";\n</pre>");
+      printf(";\n</pre>\n");
     }
   }

@@ -2565,8 +2543,7 @@
   * Standard footer...
   */

-  puts("</body>");
-  puts("</html>");
+  printf("</body>\n" "</html>\n");
 }

@@ -2590,7 +2567,7 @@
     if (node->type == MXML_TEXT)
     {
       if (node->value.text.whitespace)
-   putchar(' ');
+   printf( " ");

       if (mxmlFindElement(doc, doc, "class", "name", node->value.text.string,
                           MXML_DESCEND) ||
@@ -2625,13 +2602,13 @@
   while (*s)
   {
     if (*s == '&')
-      fputs("&amp;", stdout);
+      printf("&amp;");
     else if (*s == '<')
-      fputs("&lt;", stdout);
+      printf("&lt;");
     else if (*s == '>')
-      fputs("&gt;", stdout);
+      printf("&gt;");
     else if (*s == '\"')
-      fputs("&quot;", stdout);
+      printf("&quot;");
     else if (*s & 128)
     {
      /*
@@ -2660,13 +2637,13 @@
         * Handle non-breaking space as-is...
    */

-        fputs("&nbsp;", stdout);
+        printf("&nbsp;");
       }
       else
         printf("&#x%x;", ch);
     }
     else
-      putchar(*s);
+      printf( "%c", *s);

     s ++;
   }
michaelrsweet commented 20 years ago

"str2.patch":

Index: mxml-attr.c
===================================================================
RCS file: /development/cvs/mxml/mxml-attr.c,v
retrieving revision 1.8
diff -u -r1.8 mxml-attr.c
--- mxml-attr.c 2 May 2004 16:04:40 -0000   1.8
+++ mxml-attr.c 1 Jun 2004 20:13:53 -0000
@@ -117,10 +117,15 @@
       * Replace the attribute value and return...
       */

-      free(attr->value);
+      if (attr->value)
+        free(attr->value);

       if (value)
-   attr->value = strdup(value);
+      {
+   if ((attr->value = strdup(value)) == NULL)
+     mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
+                     name, node->value.element.name);
+      }
       else
         attr->value = NULL;

Index: mxml-entity.c
===================================================================
RCS file: /development/cvs/mxml/mxml-entity.c,v
retrieving revision 1.4
diff -u -r1.4 mxml-entity.c
--- mxml-entity.c   16 May 2004 05:25:38 -0000  1.4
+++ mxml-entity.c   1 Jun 2004 20:13:53 -0000
@@ -58,7 +58,7 @@
  * 'mxmlEntityAddCallback()' - Add a callback to convert entities to Unicode.
  */

-void
+int                    /* O - 0 on success, -1 on failure */
 mxmlEntityAddCallback(int (*cb)(const char *name))
                    /* I - Callback function to add */
 {
@@ -66,6 +66,14 @@
   {
     callbacks[num_callbacks] = cb;
     num_callbacks ++;
+
+    return (0);
+  }
+  else
+  {
+    mxml_error("Unable to add entity callback!");
+
+    return (-1);
   }
 }

Index: mxml-file.c
===================================================================
RCS file: /development/cvs/mxml/mxml-file.c,v
retrieving revision 1.31
diff -u -r1.31 mxml-file.c
--- mxml-file.c 16 May 2004 21:54:47 -0000  1.31
+++ mxml-file.c 1 Jun 2004 20:13:53 -0000
@@ -601,18 +601,24 @@
 mxml_file_putc(int  ch,            /* I - Character to write */
                void *p)            /* I - Pointer to file */
 {
+  char buffer[4],          /* Buffer for character */
+   *bufptr;            /* Pointer into buffer */
+  int  buflen;             /* Number of bytes to write */
+
+
   if (ch < 128)
-    return (putc(ch, (FILE *)p));
-  else if (ch < 2048)
+    return (putc(ch, (FILE *)p) == EOF ? -1 : 0);
+
+  bufptr = buffer;
+
+  if (ch < 2048)
   {
    /*
     * Two-byte UTF-8 character...
     */

-    if (putc(0xc0 | (ch >> 6), (FILE *)p) < 0)
-      return (-1);
-    else
-      return (putc(0x80 | (ch & 0x3f), (FILE *)p));
+    *bufptr++ = 0xc0 | (ch >> 6);
+    *bufptr++ = 0x80 | (ch & 0x3f);
   }
   else if (ch < 65536)
   {
@@ -620,12 +626,9 @@
     * Three-byte UTF-8 character...
     */

-    if (putc(0xe0 | (ch >> 12), (FILE *)p) < 0)
-      return (-1);
-    else if (putc(0x80 | ((ch >> 6) & 0x3f), (FILE *)p) < 0)
-      return (-1);
-    else
-      return (putc(0x80 | (ch & 0x3f), (FILE *)p));
+    *bufptr++ = 0xe0 | (ch >> 12);
+    *bufptr++ = 0x80 | ((ch >> 6) & 0x3f);
+    *bufptr++ = 0x80 | (ch & 0x3f);
   }
   else
   {
@@ -633,15 +636,15 @@
     * Four-byte UTF-8 character...
     */

-    if (putc(0xf0 | (ch >> 18), (FILE *)p) < 0)
-      return (-1);
-    else if (putc(0x80 | ((ch >> 12) & 0x3f), (FILE *)p) < 0)
-      return (-1);
-    else if (putc(0x80 | ((ch >> 6) & 0x3f), (FILE *)p) < 0)
-      return (-1);
-    else
-      return (putc(0x80 | (ch & 0x3f), (FILE *)p));
+    *bufptr++ = 0xf0 | (ch >> 18);
+    *bufptr++ = 0x80 | ((ch >> 12) & 0x3f);
+    *bufptr++ = 0x80 | ((ch >> 6) & 0x3f);
+    *bufptr++ = 0x80 | (ch & 0x3f);
   }
+
+  buflen = bufptr - buffer;
+
+  return (fwrite(buffer, 1, buflen, (FILE *)p) < buflen ? -1 : 0);
 }

@@ -1633,6 +1636,7 @@
        width;          /* Width of attr + value */
   mxml_attr_t  *attr;          /* Current attribute */
   char     s[255];         /* Temporary string */
+  int      slen;           /* Length of temporary string */

   while (node != NULL)
@@ -1779,11 +1783,11 @@
          col ++;
           }

-          sprintf(s, "%d", node->value.integer);
+          slen = snprintf(s, sizeof(s), "%d", node->value.integer);
      if (mxml_write_string(s, p, putc_cb) < 0)
        return (-1);

-     col += strlen(s);
+     col += slen;
           break;

       case MXML_OPAQUE :
@@ -1809,11 +1813,11 @@
          col ++;
           }

-          sprintf(s, "%f", node->value.real);
+          slen = snprintf(s, sizeof(s), "%f", node->value.real);
      if (mxml_write_string(s, p, putc_cb) < 0)
        return (-1);

-     col += strlen(s);
+     col += slen;
           break;

       case MXML_TEXT :
Index: mxml-index.c
===================================================================
RCS file: /development/cvs/mxml/mxml-index.c,v
retrieving revision 1.4
diff -u -r1.4 mxml-index.c
--- mxml-index.c    16 May 2004 18:25:20 -0000  1.4
+++ mxml-index.c    1 Jun 2004 20:13:53 -0000
@@ -581,61 +581,66 @@

  /*
-  * Sort the pivot in the current partition...
+  * Loop until we have sorted all the way to the right...
   */

-  pivot = ind->nodes[left];
-
-  for (templ = left, tempr = right; templ < tempr;)
+  do
   {
    /*
-    * Move left while left node <= pivot node...
+    * Sort the pivot in the current partition...
     */

-    while ((templ < right) &&
-           index_compare(ind, ind->nodes[templ], pivot) <= 0)
-      templ ++;
-
-   /*
-    * Move right while right node > pivot node...
-    */
+    pivot = ind->nodes[left];

-    while ((tempr > left) &&
-           index_compare(ind, ind->nodes[tempr], pivot) > 0)
-      tempr --;
+    for (templ = left, tempr = right; templ < tempr;)
+    {
+     /*
+      * Move left while left node <= pivot node...
+      */
+
+      while ((templ < right) &&
+             index_compare(ind, ind->nodes[templ], pivot) <= 0)
+   templ ++;
+
+     /*
+      * Move right while right node > pivot node...
+      */
+
+      while ((tempr > left) &&
+             index_compare(ind, ind->nodes[tempr], pivot) > 0)
+   tempr --;
+
+     /*
+      * Swap nodes if needed...
+      */
+
+      if (templ < tempr)
+      {
+   temp              = ind->nodes[templ];
+   ind->nodes[templ] = ind->nodes[tempr];
+   ind->nodes[tempr] = temp;
+      }
+    }

    /*
-    * Swap nodes if needed...
+    * When we get here, the right (tempr) node is the new position for the
+    * pivot node...
     */

-    if (templ < tempr)
+    if (index_compare(ind, pivot, ind->nodes[tempr]) > 0)
     {
-      temp              = ind->nodes[templ];
-      ind->nodes[templ] = ind->nodes[tempr];
-      ind->nodes[tempr] = temp;
+      ind->nodes[left]  = ind->nodes[tempr];
+      ind->nodes[tempr] = pivot;
     }
-  }

- /*
-  * When we get here, the right (tempr) node is the new position for the
-  * pivot node...
-  */
+   /*
+    * Recursively sort the left partition as needed...
+    */

-  if (index_compare(ind, pivot, ind->nodes[tempr]) > 0)
-  {
-    ind->nodes[left]  = ind->nodes[tempr];
-    ind->nodes[tempr] = pivot;
+    if (left < (tempr - 1))
+      index_sort(ind, left, tempr - 1);
   }
-
- /*
-  * Recursively sort the left and right partitions as needed...
-  */
-
-  if (left < (tempr - 1))
-    index_sort(ind, left, tempr - 1);
-
-  if (right > (tempr + 1))
-    index_sort(ind, tempr + 1, right);
+  while (right > (left = tempr + 1));
 }

Index: mxml-private.c
===================================================================
RCS file: /development/cvs/mxml/mxml-private.c,v
retrieving revision 1.4
diff -u -r1.4 mxml-private.c
--- mxml-private.c  2 May 2004 16:04:40 -0000   1.4
+++ mxml-private.c  1 Jun 2004 20:13:53 -0000
@@ -74,11 +74,7 @@
   if (mxml_error_cb)
     (*mxml_error_cb)(s);
   else
-  {
-    fputs("mxml: ", stderr);
-    fputs(s, stderr);
-    putc('\n', stderr);
-  }
+    fprintf(stderr, "mxml: %s\n", s);

  /*
   * Free the string...
Index: mxml.h
===================================================================
RCS file: /development/cvs/mxml/mxml.h,v
retrieving revision 1.20
diff -u -r1.20 mxml.h
--- mxml.h  16 May 2004 05:25:38 -0000  1.20
+++ mxml.h  1 Jun 2004 20:13:53 -0000
@@ -146,7 +146,7 @@
 extern const char  *mxmlElementGetAttr(mxml_node_t *node, const char *name);
 extern void        mxmlElementSetAttr(mxml_node_t *node, const char *name,
                               const char *value);
-extern void        mxmlEntityAddCallback(int (*cb)(const char *name));
+extern int     mxmlEntityAddCallback(int (*cb)(const char *name));
 extern const char  *mxmlEntityGetName(int val);
 extern int     mxmlEntityGetValue(const char *name);
 extern void        mxmlEntityRemoveCallback(int (*cb)(const char *name));
Index: mxmldoc.c
===================================================================
RCS file: /development/cvs/mxml/mxmldoc.c,v
retrieving revision 1.36
diff -u -r1.36 mxmldoc.c
--- mxmldoc.c   2 May 2004 22:02:36 -0000   1.36
+++ mxmldoc.c   1 Jun 2004 20:13:53 -0000
@@ -1779,19 +1779,18 @@
   */

   puts("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
-       "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
-  puts("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>");
-  puts("<head>");
-  puts("\t<title>Documentation</title>");
-  puts("\t<meta name='creator' content='" MXML_VERSION "'/>");
-  puts("\t<style><!--");
-  puts("\th1, h2, h3, p { font-family: sans-serif; text-align: justify; }");
-  puts("\ttt, pre a:link, pre a:visited, tt a:link, tt a:visited { font-weight: bold; color: #7f0000; }");
-  puts("\tpre { font-weight: bold; color: #7f0000; margin-left: 2em; }");
-  puts("\t--></style>");
-  puts("</head>");
-  puts("<body>");
-
+       "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
+       "<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"
+       "<head>\n"
+       "\t<title>Documentation</title>\n"
+       "\t<meta name='creator' content='" MXML_VERSION "'/>\n"
+       "\t<style><!--\n"
+       "\th1, h2, h3, p { font-family: sans-serif; text-align: justify; }\n"
+       "\ttt, pre a:link, pre a:visited, tt a:link, tt a:visited { font-weight: bold; color: #7f0000; }\n"
+       "\tpre { font-weight: bold; color: #7f0000; margin-left: 2em; }\n"
+       "\t--></style>\n"
+       "</head>\n"
+       "<body>");

  /*
   * Table of contents...
@@ -1821,9 +1820,9 @@

   if (mxmlFindElement(doc, doc, "class", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_classes'>Classes</a></h2>");
-    puts("<ul>");
+    puts("<!-- NEW PAGE -->\n"
+         "<h2><a name='_classes'>Classes</a></h2>\n"
+         "<ul>");

     for (scut = mxmlFindElement(doc, doc, "class", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -1844,24 +1843,23 @@
                            MXML_NO_DESCEND))
     {
       cname = mxmlElementGetAttr(scut, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", cname, cname);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n"
+             "<h3><a name='%s'>%s</a></h3>\n"
+             "<hr noshade/>\n", cname, cname);

       description = mxmlFindElement(scut, scut, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        fputs("<h4>Description</h4>\n"
+         "<p>", stdout);
    write_element(NULL, description);
    puts("</p>");
       }

-      puts("<h4>Definition</h4>");
-      puts("<pre>");
-
-      printf("class %s", cname);
+      printf("<h4>Definition</h4>\n"
+             "<pre>\n"
+             "class %s", cname);
       if ((parent = mxmlElementGetAttr(scut, "parent")) != NULL)
         printf(" %s", parent);
       puts("\n{");
@@ -1948,14 +1946,12 @@
    }
       }

-      puts("};\n</pre>");
-
-      puts("<h4>Members</h4>");
-
-      puts("<p class='table'><table align='center' border='1' "
-           "cellpadding='5' cellspacing='0' width='80%'>");
-      puts("<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>");
-      puts("<tbody>");
+      puts("};\n</pre>\n"
+           "<h4>Members</h4>\n"
+           "<p class='table'><table align='center' border='1' "
+           "cellpadding='5' cellspacing='0' width='80%'>\n"
+           "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
+           "<tbody>");

       for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
                             MXML_DESCEND_FIRST);
@@ -2001,7 +1997,6 @@
       }

       puts("</tbody></table></p>");
-
     }
   }

@@ -2011,9 +2006,9 @@

   if (mxmlFindElement(doc, doc, "enumeration", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_enumerations'>Enumerations</a></h2>");
-    puts("<ul>");
+    puts("<!-- NEW PAGE -->\n"
+         "<h2><a name='_enumerations'>Enumerations</a></h2>\n"
+         "<ul>");

     for (scut = mxmlFindElement(doc, doc, "enumeration", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2034,26 +2029,25 @@
                            MXML_NO_DESCEND))
     {
       name = mxmlElementGetAttr(scut, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", name, name);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n"
+             "<h3><a name='%s'>%s</a></h3>\n"
+             "<hr noshade/>\n", name, name);

       description = mxmlFindElement(scut, scut, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        fputs("<h4>Description</h4>\n"
+         "<p>", stdout);
    write_element(NULL, description);
    puts("</p>");
       }

-      puts("<h4>Values</h4>");
-
-      puts("<p class='table'><table align='center' border='1' width='80%' "
-           "cellpadding='5' cellspacing='0' width='80%'>");
-      puts("<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>");
-      puts("<tbody>");
+      puts("<h4>Values</h4>\n"
+           "<p class='table'><table align='center' border='1' width='80%' "
+           "cellpadding='5' cellspacing='0' width='80%'>\n"
+           "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
+           "<tbody>");

       for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
                             MXML_DESCEND_FIRST);
@@ -2079,9 +2073,9 @@

   if (mxmlFindElement(doc, doc, "function", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_functions'>Functions</a></h2>");
-    puts("<ul>");
+    puts("<!-- NEW PAGE -->\n"
+         "<h2><a name='_functions'>Functions</a></h2>\n"
+         "<ul>");

     for (function = mxmlFindElement(doc, doc, "function", NULL, NULL,
                                     MXML_DESCEND_FIRST);
@@ -2102,22 +2096,22 @@
                                     MXML_NO_DESCEND))
     {
       name = mxmlElementGetAttr(function, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s()</a></h3>\n", name, name);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n"
+             "<h3><a name='%s'>%s()</a></h3>\n"
+             "<hr noshade/>\n", name, name);

       description = mxmlFindElement(function, function, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        fputs("<h4>Description</h4>\n"
+         "<p>", stdout);
    write_element(NULL, description);
    puts("</p>");
       }

-      puts("<h4>Syntax</h4>");
-      puts("<pre>");
+      puts("<h4>Syntax</h4>\n"
+           "<pre>");

       arg = mxmlFindElement(function, function, "returnvalue", NULL,
                             NULL, MXML_DESCEND_FIRST);
@@ -2161,9 +2155,9 @@
       else
       {
    puts("<p class='table'><table align='center' border='1' width='80%' "
-             "cellpadding='5' cellspacing='0' width='80%'>");
-   puts("<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>");
-   puts("<tbody>");
+             "cellpadding='5' cellspacing='0' width='80%'>\n"
+        "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
+        "<tbody>");

    for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
                               MXML_DESCEND_FIRST);
@@ -2205,9 +2199,9 @@

   if (mxmlFindElement(doc, doc, "struct", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_structures'>Structures</a></h2>");
-    puts("<ul>");
+    puts("<!-- NEW PAGE -->\n"
+         "<h2><a name='_structures'>Structures</a></h2>\n"
+         "<ul>");

     for (scut = mxmlFindElement(doc, doc, "struct", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2228,24 +2222,23 @@
                            MXML_NO_DESCEND))
     {
       cname = mxmlElementGetAttr(scut, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", cname, cname);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n"
+             "<h3><a name='%s'>%s</a></h3>\n"
+        "<hr noshade/>\n", cname, cname);

       description = mxmlFindElement(scut, scut, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        fputs("<h4>Description</h4>\n"
+         "<p>", stdout);
    write_element(NULL, description);
    puts("</p>");
       }

-      puts("<h4>Definition</h4>");
-      puts("<pre>");
-
-      printf("struct %s\n{\n", cname);
+      printf("<h4>Definition</h4>\n"
+             "<pre>\n"
+        "struct %s\n{\n", cname);
       for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
                             MXML_DESCEND_FIRST);
       arg;
@@ -2311,14 +2304,12 @@
      puts(");");
       }

-      puts("};\n</pre>");
-
-      puts("<h4>Members</h4>");
-
-      puts("<p class='table'><table align='center' border='1' width='80%' "
-           "cellpadding='5' cellspacing='0' width='80%'>");
-      puts("<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>");
-      puts("<tbody>");
+      puts("};\n</pre>\n"
+           "<h4>Members</h4>\n"
+           "<p class='table'><table align='center' border='1' width='80%' "
+           "cellpadding='5' cellspacing='0' width='80%'>\n"
+           "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
+           "<tbody>");

       for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
                             MXML_DESCEND_FIRST);
@@ -2373,9 +2364,9 @@

   if (mxmlFindElement(doc, doc, "typedef", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_types'>Types</a></h2>");
-    puts("<ul>");
+    puts("<!-- NEW PAGE -->\n"
+         "<h2><a name='_types'>Types</a></h2>\n"
+         "<ul>");

     for (scut = mxmlFindElement(doc, doc, "typedef", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2396,24 +2387,23 @@
                            MXML_NO_DESCEND))
     {
       name = mxmlElementGetAttr(scut, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", name, name);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n"
+             "<h3><a name='%s'>%s</a></h3>\n"
+        "<hr noshade/>\n", name, name);

       description = mxmlFindElement(scut, scut, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        fputs("<h4>Description</h4>\n"
+         "<p>", stdout);
    write_element(NULL, description);
    puts("</p>");
       }

-      puts("<h4>Definition</h4>");
-      puts("<pre>");
-
-      printf("typedef ");
+      fputs("<h4>Definition</h4>\n"
+            "<pre>\n"
+       "typedef ", stdout);
       write_element(doc, mxmlFindElement(scut, scut, "type", NULL,
                                          NULL, MXML_DESCEND_FIRST));
       printf(" %s;\n</pre>\n", name);
@@ -2426,9 +2416,9 @@

   if (mxmlFindElement(doc, doc, "union", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_unions'>Unions</a></h2>");
-    puts("<ul>");
+    puts("<!-- NEW PAGE -->\n"
+         "<h2><a name='_unions'>Unions</a></h2>\n"
+         "<ul>");

     for (scut = mxmlFindElement(doc, doc, "union", NULL, NULL,
                            MXML_DESCEND_FIRST);
@@ -2449,24 +2439,23 @@
                            MXML_NO_DESCEND))
     {
       name = mxmlElementGetAttr(scut, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", name, name);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n"
+             "<h3><a name='%s'>%s</a></h3>\n"
+        "<hr noshade/>\n", name, name);

       description = mxmlFindElement(scut, scut, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        fputs("<h4>Description</h4>\n"
+         "<p>", stdout);
    write_element(NULL, description);
    puts("</p>");
       }

-      puts("<h4>Definition</h4>");
-      puts("<pre>");
-
-      printf("union %s\n{\n", name);
+      printf("<h4>Definition</h4>\n"
+             "<pre>\n"
+        "union %s\n{\n", name);
       for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
                             MXML_DESCEND_FIRST);
       arg;
@@ -2479,14 +2468,12 @@
    printf(" %s;\n", mxmlElementGetAttr(arg, "name"));
       }

-      puts("};\n</pre>");
-
-      puts("<h4>Members</h4>");
-
-      puts("<p class='table'><table align='center' border='1' width='80%' "
-           "cellpadding='5' cellspacing='0' width='80%'>");
-      puts("<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>");
-      puts("<tbody>");
+      puts("};\n</pre>\n"
+           "<h4>Members</h4>\n"
+           "<p class='table'><table align='center' border='1' width='80%' "
+           "cellpadding='5' cellspacing='0' width='80%'>\n"
+           "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
+           "<tbody>");

       for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
                             MXML_DESCEND_FIRST);
@@ -2512,9 +2499,9 @@

   if (mxmlFindElement(doc, doc, "variable", NULL, NULL, MXML_DESCEND_FIRST))
   {
-    puts("<!-- NEW PAGE -->");
-    puts("<h2><a name='_variables'>Variables</a></h2>");
-    puts("<ul>");
+    puts("<!-- NEW PAGE -->\n"
+         "<h2><a name='_variables'>Variables</a></h2>\n"
+         "<ul>");

     for (arg = mxmlFindElement(doc, doc, "variable", NULL, NULL,
                                MXML_DESCEND_FIRST);
@@ -2535,22 +2522,22 @@
                                MXML_NO_DESCEND))
     {
       name = mxmlElementGetAttr(arg, "name");
-      puts("<!-- NEW PAGE -->");
-      printf("<h3><a name='%s'>%s</a></h3>\n", name, name);
-      puts("<hr noshade/>");
+      printf("<!-- NEW PAGE -->\n"
+             "<h3><a name='%s'>%s</a></h3>\n"
+        "<hr noshade/>", name, name);

       description = mxmlFindElement(arg, arg, "description", NULL,
                                     NULL, MXML_DESCEND_FIRST);
       if (description)
       {
-        puts("<h4>Description</h4>");
-   fputs("<p>", stdout);
+        fputs("<h4>Description</h4>\n"
+         "<p>", stdout);
    write_element(NULL, description);
    puts("</p>");
       }

-      puts("<h4>Definition</h4>");
-      puts("<pre>");
+      puts("<h4>Definition</h4>\n"
+           "<pre>");

       write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
                                          NULL, MXML_DESCEND_FIRST));
@@ -2565,8 +2552,8 @@
   * Standard footer...
   */

-  puts("</body>");
-  puts("</html>");
+  puts("</body>\n"
+       "</html>");
 }