/home/dko/projects/mobilec/trunk/src/mxml-2.2.2/mxmldoc.c

Go to the documentation of this file.
00001 /* SVN FILE INFO
00002  * $Revision: 174 $ : Last Committed Revision
00003  * $Date: 2008年06月24日 10:50:29 -0700 (2008年6月24日) $ : Last Committed Date */
00004 /*
00005  * "$Id: mxmldoc.c,v 1.1 2007年05月23日 20:43:28 david_ko Exp $"
00006  *
00007  * Documentation generator using Mini-XML, a small XML-like file parsing
00008  * library.
00009  *
00010  * Copyright 2003-2005 by Michael Sweet.
00011  *
00012  * This program is free software; you can redistribute it and/or
00013  * modify it under the terms of the GNU Library General Public
00014  * License as published by the Free Software Foundation; either
00015  * version 2, or (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00020  * GNU General Public License for more details.
00021  *
00022  * Contents:
00023  *
00024  * main() - Main entry for test program.
00025  * add_variable() - Add a variable or argument.
00026  * safe_strcpy() - Copy a string allowing for overlapping strings.
00027  * scan_file() - Scan a source file.
00028  * sort_node() - Insert a node sorted into a tree.
00029  * update_comment() - Update a comment node.
00030  * write_documentation() - Write HTML documentation.
00031  * write_element() - Write an elements text nodes.
00032  * write_string() - Write a string, quoting XHTML special chars
00033  * as needed...
00034  * ws_cb() - Whitespace callback for saving.
00035  */
00036 
00037 /*
00038  * Include necessary headers...
00039  */
00040 
00041 #include "config.h"
00042 #include "mxml.h"
00043 
00044 
00045 /*
00046  * This program scans source and header files and produces public API
00047  * documentation for code that conforms to the CUPS Configuration
00048  * Management Plan (CMP) coding standards. Please see the following web
00049  * page for details:
00050  *
00051  * http://www.cups.org/cmp.html
00052  *
00053  * Using Mini-XML, this program creates and maintains an XML representation
00054  * of the public API code documentation which can then be converted to HTML
00055  * as desired. The following is a poor-man's schema:
00056  *
00057  * <?xml version="1.0"?>
00058  * <mxmldoc xmlns="http://www.easysw.com"
00059  * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
00060  * xsi:schemaLocation="http://www.easysw.com/~mike/mxml/mxmldoc.xsd">
00061  *
00062  * <namespace name=""> [optional...]
00063  * <constant name="">
00064  * <description>descriptive text</description>
00065  * </constant>
00066  * 
00067  * <enumeration name="">
00068  * <description>descriptive text</description>
00069  * <constant name="">...</constant>
00070  * </enumeration>
00071  * 
00072  * <typedef name="">
00073  * <description>descriptive text</description>
00074  * <type>type string</type>
00075  * </typedef>
00076  * 
00077  * <function name="" scope="">
00078  * <description>descriptive text</description>
00079  * <argument name="" direction="I|O|IO" default="">
00080  * <description>descriptive text</description>
00081  * <type>type string</type>
00082  * </argument>
00083  * <returnvalue>
00084  * <description>descriptive text</description>
00085  * <type>type string</type>
00086  * </returnvalue>
00087  * <seealso>function names separated by spaces</seealso>
00088  * </function>
00089  * 
00090  * <variable name="" scope="">
00091  * <description>descriptive text</description>
00092  * <type>type string</type>
00093  * </variable>
00094  * 
00095  * <struct name="">
00096  * <description>descriptive text</description>
00097  * <variable name="">...</variable>
00098  * <function name="">...</function>
00099  * </struct>
00100  * 
00101  * <union name="">
00102  * <description>descriptive text</description>
00103  * <variable name="">...</variable>
00104  * </union>
00105  * 
00106  * <class name="" parent="">
00107  * <description>descriptive text</description>
00108  * <class name="">...</class>
00109  * <enumeration name="">...</enumeration>
00110  * <function name="">...</function>
00111  * <struct name="">...</struct>
00112  * <variable name="">...</variable>
00113  * </class>
00114  * </namespace>
00115  * </mxmldoc>
00116  */
00117 
00118 
00119 /*
00120  * Basic states for file parser...
00121  */
00122 
00123 #define STATE_NONE 0 /* No state - whitespace, etc. */
00124 #define STATE_PREPROCESSOR 1 /* Preprocessor directive */
00125 #define STATE_C_COMMENT 2 /* Inside a C comment */
00126 #define STATE_CXX_COMMENT 3 /* Inside a C++ comment */
00127 #define STATE_STRING 4 /* Inside a string constant */
00128 #define STATE_CHARACTER 5 /* Inside a character constant */
00129 #define STATE_IDENTIFIER 6 /* Inside a keyword/identifier */
00130 
00131 
00132 /*
00133  * Local functions...
00134  */
00135 
00136 static mxml_node_t *add_variable(mxml_node_t *parent, const char *name,
00137 mxml_node_t *type);
00138 static void safe_strcpy(char *dst, const char *src);
00139 static int scan_file(const char *filename, FILE *fp,
00140 mxml_node_t *doc);
00141 static void sort_node(mxml_node_t *tree, mxml_node_t *func);
00142 static void update_comment(mxml_node_t *parent,
00143 mxml_node_t *comment);
00144 static void write_documentation(mxml_node_t *doc);
00145 static void write_element(mxml_node_t *doc, mxml_node_t *element);
00146 static void write_string(const char *s);
00147 static const char *ws_cb(mxml_node_t *node, int where);
00148 
00149 
00150 /*
00151  * 'main()' - Main entry for test program.
00152  */
00153 
00154 int /* O - Exit status */
00155 main(int argc, /* I - Number of command-line args */
00156 char *argv[]) /* I - Command-line args */
00157 {
00158 int i; /* Looping var */
00159 FILE *fp; /* File to read */
00160 mxml_node_t *doc; /* XML documentation tree */
00161 mxml_node_t *mxmldoc; /* mxmldoc node */
00162 
00163 
00164 /*
00165  * Check arguments...
00166  */
00167 
00168 if (argc < 2)
00169 {
00170 fputs("Usage: mxmldoc filename.xml [source files] >filename.html\n", stderr);
00171 return (1);
00172 }
00173 
00174 /*
00175  * Read the XML documentation file, if it exists...
00176  */
00177 
00178 if ((fp = fopen(argv[1], "r")) != NULL)
00179 {
00180 /*
00181  * Read the existing XML file...
00182  */
00183 
00184 doc = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
00185 
00186 fclose(fp);
00187 
00188 if (!doc)
00189 {
00190 mxmldoc = NULL;
00191 
00192 fprintf(stderr, "mxmldoc: Unable to read the XML documentation file \"%s\"!\n",
00193 argv[1]);
00194 }
00195 else if ((mxmldoc = mxmlFindElement(doc, doc, "mxmldoc", NULL,
00196 NULL, MXML_DESCEND)) == NULL)
00197 {
00198 fprintf(stderr, "mxmldoc: XML documentation file \"%s\" is missing <mxmldoc> node!!\n",
00199 argv[1]);
00200 
00201 mxmlDelete(doc);
00202 doc = NULL;
00203 }
00204 }
00205 else
00206 {
00207 doc = NULL;
00208 mxmldoc = NULL;
00209 }
00210 
00211 if (!doc)
00212 {
00213 /*
00214  * Create an empty XML documentation file...
00215  */
00216 
00217 doc = mxmlNewElement(NULL, "?xml version=\"1.0\"?");
00218 
00219 mxmldoc = mxmlNewElement(doc, "mxmldoc");
00220 
00221 #ifdef MXML_INCLUDE_SCHEMA
00222 /*
00223  * Currently we don't include the schema/namespace stuff with the
00224  * XML output since some validators don't seem to like it...
00225  */
00226 
00227 mxmlElementSetAttr(mxmldoc, "xmlns", "http://www.easysw.com");
00228 mxmlElementSetAttr(mxmldoc, "xmlns:xsi",
00229 "http://www.w3.org/2001/XMLSchema-instance");
00230 mxmlElementSetAttr(mxmldoc, "xsi:schemaLocation",
00231 "http://www.easysw.com/~mike/mxml/mxmldoc.xsd");
00232 #endif /* MXML_INCLUDE_SCHEMA */
00233 }
00234 
00235 /*
00236  * Loop through all of the source files...
00237  */
00238 
00239 for (i = 2; i < argc; i ++)
00240 if ((fp = fopen(argv[i], "r")) == NULL)
00241 {
00242 fprintf(stderr, "Unable to open source file \"%s\": %s\n", argv[i],
00243 strerror(errno));
00244 mxmlDelete(doc);
00245 return (1);
00246 }
00247 else if (scan_file(argv[i], fp, mxmldoc))
00248 {
00249 fclose(fp);
00250 mxmlDelete(doc);
00251 return (1);
00252 }
00253 else
00254 fclose(fp);
00255 
00256 if (argc > 2)
00257 {
00258 /*
00259  * Save the updated XML documentation file...
00260  */
00261 
00262 if ((fp = fopen(argv[1], "w")) != NULL)
00263 {
00264 /*
00265  * Write over the existing XML file...
00266  */
00267 
00268 if (mxmlSaveFile(doc, fp, ws_cb))
00269 {
00270 fprintf(stderr, "Unable to write the XML documentation file \"%s\": %s!\n",
00271 argv[1], strerror(errno));
00272 fclose(fp);
00273 mxmlDelete(doc);
00274 return (1);
00275 }
00276 
00277 fclose(fp);
00278 }
00279 else
00280 {
00281 fprintf(stderr, "Unable to create the XML documentation file \"%s\": %s!\n",
00282 argv[1], strerror(errno));
00283 mxmlDelete(doc);
00284 return (1);
00285 }
00286 }
00287 
00288 /*
00289  * Write HTML documentation...
00290  */
00291 
00292 write_documentation(mxmldoc);
00293 
00294 /*
00295  * Delete the tree and return...
00296  */
00297 
00298 mxmlDelete(doc);
00299 
00300 return (0);
00301 }
00302 
00303 
00304 /*
00305  * 'add_variable()' - Add a variable or argument.
00306  */
00307 
00308 static mxml_node_t * /* O - New variable/argument */
00309 add_variable(mxml_node_t *parent, /* I - Parent node */
00310 const char *name, /* I - "argument" or "variable" */
00311 mxml_node_t *type) /* I - Type nodes */
00312 {
00313 mxml_node_t *variable, /* New variable */
00314 *node, /* Current node */
00315 *next; /* Next node */
00316 char buffer[16384], /* String buffer */
00317 *bufptr; /* Pointer into buffer */
00318 
00319 
00320 /*
00321  * Range check input...
00322  */
00323 
00324 if (!type || !type->child)
00325 return (NULL);
00326 
00327 /*
00328  * Create the variable/argument node...
00329  */
00330 
00331 variable = mxmlNewElement(parent, name);
00332 
00333 /*
00334  * Check for a default value...
00335  */
00336 
00337 for (node = type->child; node; node = node->next)
00338 if (!strcmp(node->value.text.string, "="))
00339 break;
00340 
00341 if (node)
00342 {
00343 /*
00344  * Default value found, copy it and add as a "default" attribute...
00345  */
00346 
00347 for (bufptr = buffer; node; bufptr += strlen(bufptr))
00348 {
00349 if (node->value.text.whitespace && bufptr > buffer)
00350 *bufptr++ = ' ';
00351 
00352 strcpy(bufptr, node->value.text.string);
00353 
00354 next = node->next;
00355 mxmlDelete(node);
00356 node = next;
00357 }
00358 
00359 mxmlElementSetAttr(variable, "default", buffer);
00360 }
00361 
00362 /*
00363  * Extract the argument/variable name...
00364  */
00365 
00366 if (type->last_child->value.text.string[0] == ')')
00367 {
00368 /*
00369  * Handle "type (*name)(args)"...
00370  */
00371 
00372 for (node = type->child; node; node = node->next)
00373 if (node->value.text.string[0] == '(')
00374 break;
00375 
00376 for (bufptr = buffer; node; bufptr += strlen(bufptr))
00377 {
00378 if (node->value.text.whitespace && bufptr > buffer)
00379 *bufptr++ = ' ';
00380 
00381 strcpy(bufptr, node->value.text.string);
00382 
00383 next = node->next;
00384 mxmlDelete(node);
00385 node = next;
00386 }
00387 }
00388 else
00389 {
00390 /*
00391  * Handle "type name"...
00392  */
00393 
00394 strcpy(buffer, type->last_child->value.text.string);
00395 mxmlDelete(type->last_child);
00396 }
00397 
00398 /*
00399  * Set the name...
00400  */
00401 
00402 mxmlElementSetAttr(variable, "name", buffer);
00403 
00404 /*
00405  * Add the remaining type information to the variable node...
00406  */
00407 
00408 mxmlAdd(variable, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
00409 
00410 /*
00411  * Add new new variable node...
00412  */
00413 
00414 return (variable);
00415 }
00416 
00417 
00418 /*
00419  * 'safe_strcpy()' - Copy a string allowing for overlapping strings.
00420  */
00421 
00422 static void
00423 safe_strcpy(char *dst, /* I - Destination string */
00424 const char *src) /* I - Source string */
00425 {
00426 while (*src)
00427 *dst++ = *src++;
00428 
00429 *dst = '0円';
00430 }
00431 
00432 
00433 /*
00434  * 'scan_file()' - Scan a source file.
00435  */
00436 
00437 static int /* O - 0 on success, -1 on error */
00438 scan_file(const char *filename, /* I - Filename */
00439 FILE *fp, /* I - File to scan */
00440 mxml_node_t *tree) /* I - Function tree */
00441 {
00442 int state, /* Current parser state */
00443 braces, /* Number of braces active */
00444 parens; /* Number of active parenthesis */
00445 int ch; /* Current character */
00446 char buffer[65536], /* String buffer */
00447 *bufptr; /* Pointer into buffer */
00448 const char *scope; /* Current variable/function scope */
00449 mxml_node_t *comment, /* <comment> node */
00450 *constant, /* <constant> node */
00451 *enumeration, /* <enumeration> node */
00452 *function, /* <function> node */
00453 *fstructclass, /* function struct/class node */
00454 *structclass, /* <struct> or <class> node */
00455 *typedefnode, /* <typedef> node */
00456 *variable, /* <variable> or <argument> node */
00457 *returnvalue, /* <returnvalue> node */
00458 *type, /* <type> node */
00459 *description, /* <description> node */
00460 *node, /* Current node */
00461 *next; /* Next node */
00462 #if DEBUG > 1
00463 mxml_node_t *temp; /* Temporary node */
00464 int oldstate, /* Previous state */
00465 oldch; /* Old character */
00466 static const char *states[] = /* State strings */
00467 {
00468 "STATE_NONE",
00469 "STATE_PREPROCESSOR",
00470 "STATE_C_COMMENT",
00471 "STATE_CXX_COMMENT",
00472 "STATE_STRING",
00473 "STATE_CHARACTER",
00474 "STATE_IDENTIFIER"
00475 };
00476 #endif /* DEBUG > 1 */
00477 
00478 
00479 #ifdef DEBUG
00480 fprintf(stderr, "scan_file(filename=\"%s\", fp=%p, tree=%p)\n", filename,
00481 fp, tree);
00482 #endif // DEBUG
00483 
00484 /*
00485  * Initialize the finite state machine...
00486  */
00487 
00488 state = STATE_NONE;
00489 braces = 0;
00490 parens = 0;
00491 bufptr = buffer;
00492 
00493 comment = mxmlNewElement(MXML_NO_PARENT, "temp");
00494 constant = NULL;
00495 enumeration = NULL;
00496 function = NULL;
00497 variable = NULL;
00498 returnvalue = NULL;
00499 type = NULL;
00500 description = NULL;
00501 typedefnode = NULL;
00502 structclass = NULL;
00503 fstructclass = NULL;
00504 
00505 if (!strcmp(tree->value.element.name, "class"))
00506 scope = "private";
00507 else
00508 scope = NULL;
00509 
00510 /*
00511  * Read until end-of-file...
00512  */
00513 
00514 while ((ch = getc(fp)) != EOF)
00515 {
00516 #if DEBUG > 1
00517 oldstate = state;
00518 oldch = ch;
00519 #endif /* DEBUG > 1 */
00520 
00521 switch (state)
00522 {
00523 case STATE_NONE : /* No state - whitespace, etc. */
00524 switch (ch)
00525 {
00526 case '/' : /* Possible C/C++ comment */
00527 ch = getc(fp);
00528 bufptr = buffer;
00529 
00530 if (ch == '*')
00531 state = STATE_C_COMMENT;
00532 else if (ch == '/')
00533 state = STATE_CXX_COMMENT;
00534 else
00535 {
00536 ungetc(ch, fp);
00537 
00538 if (type)
00539 {
00540 #ifdef DEBUG
00541 fputs("Identifier: <<<< / >>>\n", stderr);
00542 #endif /* DEBUG */
00543 ch = type->last_child->value.text.string[0];
00544 mxmlNewText(type, isalnum(ch) || ch == '_', "/");
00545 }
00546 }
00547 break;
00548 
00549 case '#' : /* Preprocessor */
00550 #ifdef DEBUG
00551 fputs(" #preprocessor...\n", stderr);
00552 #endif /* DEBUG */
00553 state = STATE_PREPROCESSOR;
00554 break;
00555 
00556 case '\'' : /* Character constant */
00557 state = STATE_CHARACTER;
00558 bufptr = buffer;
00559 *bufptr++ = ch;
00560 break;
00561 
00562 case '\"' : /* String constant */
00563 state = STATE_STRING;
00564 bufptr = buffer;
00565 *bufptr++ = ch;
00566 break;
00567 
00568 case '{' :
00569 #ifdef DEBUG
00570 fprintf(stderr, " open brace, function=%p, type=%p...\n",
00571 function, type);
00572 if (type)
00573 fprintf(stderr, " type->child=\"%s\"...\n",
00574 type->child->value.text.string);
00575 #endif /* DEBUG */
00576 
00577 if (function)
00578 {
00579 if (fstructclass)
00580 {
00581 sort_node(fstructclass, function);
00582 fstructclass = NULL;
00583 }
00584 else
00585 sort_node(tree, function);
00586 
00587 function = NULL;
00588 }
00589 else if (type && type->child &&
00590 ((!strcmp(type->child->value.text.string, "typedef") &&
00591 type->child->next &&
00592 (!strcmp(type->child->next->value.text.string, "struct") ||
00593 !strcmp(type->child->next->value.text.string, "union") ||
00594 !strcmp(type->child->next->value.text.string, "class"))) ||
00595 !strcmp(type->child->value.text.string, "union") ||
00596 !strcmp(type->child->value.text.string, "struct") ||
00597 !strcmp(type->child->value.text.string, "class")))
00598 {
00599 /*
00600  * Start of a class or structure...
00601  */
00602 
00603 if (!strcmp(type->child->value.text.string, "typedef"))
00604 {
00605 #ifdef DEBUG
00606 fputs(" starting typedef...\n", stderr);
00607 #endif /* DEBUG */
00608 
00609 typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
00610 mxmlDelete(type->child);
00611 }
00612 else
00613 typedefnode = NULL;
00614 
00615 structclass = mxmlNewElement(MXML_NO_PARENT,
00616 type->child->value.text.string);
00617 
00618 #ifdef DEBUG
00619 fprintf(stderr, "%c%s: <<<< %s >>>\n",
00620 toupper(type->child->value.text.string[0]),
00621 type->child->value.text.string + 1,
00622 type->child->next ?
00623 type->child->next->value.text.string : "(noname)");
00624 
00625 fputs(" type =", stderr);
00626 for (node = type->child; node; node = node->next)
00627 fprintf(stderr, " \"%s\"", node->value.text.string);
00628 putc('\n', stderr);
00629 
00630 fprintf(stderr, " scope = %s\n", scope ? scope : "(null)");
00631 #endif /* DEBUG */
00632 
00633 if (comment->last_child &&
00634 strstr(comment->last_child->value.text.string, "@private"))
00635 {
00636 mxmlDelete(type);
00637 type = NULL;
00638 
00639 if (typedefnode)
00640 {
00641 mxmlDelete(typedefnode);
00642 typedefnode = NULL;
00643 }
00644 
00645 mxmlDelete(structclass);
00646 structclass = NULL;
00647 
00648 braces ++;
00649 function = NULL;
00650 variable = NULL;
00651 break;
00652 }
00653 
00654 if (type->child->next)
00655 {
00656 mxmlElementSetAttr(structclass, "name",
00657 type->child->next->value.text.string);
00658 sort_node(tree, structclass);
00659 }
00660 
00661 if (typedefnode && type->child)
00662 type->child->value.text.whitespace = 0;
00663 else if (structclass && type->child &&
00664 type->child->next && type->child->next->next)
00665 {
00666 for (bufptr = buffer, node = type->child->next->next;
00667 node;
00668 bufptr += strlen(bufptr))
00669 {
00670 if (node->value.text.whitespace && bufptr > buffer)
00671 *bufptr++ = ' ';
00672 
00673 strcpy(bufptr, node->value.text.string);
00674 
00675 next = node->next;
00676 mxmlDelete(node);
00677 node = next;
00678 }
00679 
00680 mxmlElementSetAttr(structclass, "parent", buffer);
00681 
00682 mxmlDelete(type);
00683 type = NULL;
00684 }
00685 else
00686 {
00687 mxmlDelete(type);
00688 type = NULL;
00689 }
00690 
00691 if (typedefnode && comment->last_child)
00692 {
00693 /*
00694  * Copy comment for typedef as well as class/struct/union...
00695  */
00696 
00697 mxmlNewText(comment, 0,
00698 comment->last_child->value.text.string);
00699 description = mxmlNewElement(typedefnode, "description");
00700 #ifdef DEBUG
00701 fputs(" duplicating comment for typedef...\n", stderr);
00702 #endif /* DEBUG */
00703 update_comment(typedefnode, comment->last_child);
00704 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
00705 comment->last_child);
00706 }
00707 
00708 description = mxmlNewElement(structclass, "description");
00709 #ifdef DEBUG
00710 fprintf(stderr, " adding comment to %s...\n",
00711 structclass->value.element.name);
00712 #endif /* DEBUG */
00713 update_comment(structclass, comment->last_child);
00714 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
00715 comment->last_child);
00716 
00717 if (scan_file(filename, fp, structclass))
00718 {
00719 mxmlDelete(comment);
00720 return (-1);
00721 }
00722 
00723 #ifdef DEBUG
00724 fputs(" ended typedef...\n", stderr);
00725 #endif /* DEBUG */
00726 structclass = NULL;
00727 break;
00728 }
00729 else if (type && type->child && type->child->next &&
00730 (!strcmp(type->child->value.text.string, "enum") ||
00731 (!strcmp(type->child->value.text.string, "typedef") &&
00732 !strcmp(type->child->next->value.text.string, "enum"))))
00733 {
00734 /*
00735  * Enumeration type...
00736  */
00737 
00738 if (!strcmp(type->child->value.text.string, "typedef"))
00739 {
00740 #ifdef DEBUG
00741 fputs(" starting typedef...\n", stderr);
00742 #endif /* DEBUG */
00743 
00744 typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
00745 mxmlDelete(type->child);
00746 }
00747 else
00748 typedefnode = NULL;
00749 
00750 enumeration = mxmlNewElement(MXML_NO_PARENT, "enumeration");
00751 
00752 #ifdef DEBUG
00753 fprintf(stderr, "Enumeration: <<<< %s >>>\n",
00754 type->child->next ?
00755 type->child->next->value.text.string : "(noname)");
00756 #endif /* DEBUG */
00757 
00758 if (type->child->next)
00759 {
00760 mxmlElementSetAttr(enumeration, "name",
00761 type->child->next->value.text.string);
00762 sort_node(tree, enumeration);
00763 }
00764 
00765 if (typedefnode && type->child)
00766 type->child->value.text.whitespace = 0;
00767 else
00768 {
00769 mxmlDelete(type);
00770 type = NULL;
00771 }
00772 
00773 if (typedefnode && comment->last_child)
00774 {
00775 /*
00776  * Copy comment for typedef as well as class/struct/union...
00777  */
00778 
00779 mxmlNewText(comment, 0,
00780 comment->last_child->value.text.string);
00781 description = mxmlNewElement(typedefnode, "description");
00782 #ifdef DEBUG
00783 fputs(" duplicating comment for typedef...\n", stderr);
00784 #endif /* DEBUG */
00785 update_comment(typedefnode, comment->last_child);
00786 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
00787 comment->last_child);
00788 }
00789 
00790 description = mxmlNewElement(enumeration, "description");
00791 #ifdef DEBUG
00792 fputs(" adding comment to enumeration...\n", stderr);
00793 #endif /* DEBUG */
00794 update_comment(enumeration, comment->last_child);
00795 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
00796 comment->last_child);
00797 }
00798 else if (type && type->child &&
00799 !strcmp(type->child->value.text.string, "extern"))
00800 {
00801 if (scan_file(filename, fp, tree))
00802 {
00803 mxmlDelete(comment);
00804 return (-1);
00805 }
00806 }
00807 else if (type)
00808 {
00809 mxmlDelete(type);
00810 type = NULL;
00811 }
00812 
00813 braces ++;
00814 function = NULL;
00815 variable = NULL;
00816 break;
00817 
00818 case '}' :
00819 #ifdef DEBUG
00820 fputs(" close brace...\n", stderr);
00821 #endif /* DEBUG */
00822 
00823 if (structclass)
00824 scope = NULL;
00825 
00826 enumeration = NULL;
00827 constant = NULL;
00828 structclass = NULL;
00829 
00830 if (braces > 0)
00831 braces --;
00832 else
00833 {
00834 mxmlDelete(comment);
00835 return (0);
00836 }
00837 break;
00838 
00839 case '(' :
00840 if (type)
00841 {
00842 #ifdef DEBUG
00843 fputs("Identifier: <<<< ( >>>\n", stderr);
00844 #endif /* DEBUG */
00845 mxmlNewText(type, 0, "(");
00846 }
00847 
00848 parens ++;
00849 break;
00850 
00851 case ')' :
00852 if (parens > 0)
00853 parens --;
00854 
00855 if (type && parens)
00856 {
00857 #ifdef DEBUG
00858 fputs("Identifier: <<<< ) >>>\n", stderr);
00859 #endif /* DEBUG */
00860 mxmlNewText(type, 0, ")");
00861 }
00862 
00863 if (function && type && !parens)
00864 {
00865 variable = add_variable(function, "argument", type);
00866 type = NULL;
00867 }
00868 break;
00869 
00870 case ';' :
00871 #ifdef DEBUG
00872 fputs("Identifier: <<<< ; >>>\n", stderr);
00873 fprintf(stderr, " function=%p, type=%p\n", function, type);
00874 #endif /* DEBUG */
00875 
00876 if (function)
00877 {
00878 if (!strcmp(tree->value.element.name, "class"))
00879 {
00880 #ifdef DEBUG
00881 fputs(" ADDING FUNCTION TO CLASS\n", stderr);
00882 #endif /* DEBUG */
00883 sort_node(tree, function);
00884 }
00885 else
00886 mxmlDelete(function);
00887 
00888 function = NULL;
00889 variable = NULL;
00890 }
00891 
00892 if (type)
00893 {
00894 mxmlDelete(type);
00895 type = NULL;
00896 }
00897 break;
00898 
00899 case ':' :
00900 if (type)
00901 {
00902 #ifdef DEBUG
00903 fputs("Identifier: <<<< : >>>\n", stderr);
00904 #endif /* DEBUG */
00905 mxmlNewText(type, 1, ":");
00906 }
00907 break;
00908 
00909 case '*' :
00910 if (type)
00911 {
00912 #ifdef DEBUG
00913 fputs("Identifier: <<<< * >>>\n", stderr);
00914 #endif /* DEBUG */
00915 ch = type->last_child->value.text.string[0];
00916 mxmlNewText(type, isalnum(ch) || ch == '_', "*");
00917 }
00918 break;
00919 
00920 case '&' :
00921 if (type)
00922 {
00923 #ifdef DEBUG
00924 fputs("Identifier: <<<< & >>>\n", stderr);
00925 #endif /* DEBUG */
00926 mxmlNewText(type, 1, "&");
00927 }
00928 break;
00929 
00930 case '+' :
00931 if (type)
00932 {
00933 #ifdef DEBUG
00934 fputs("Identifier: <<<< + >>>\n", stderr);
00935 #endif /* DEBUG */
00936 ch = type->last_child->value.text.string[0];
00937 mxmlNewText(type, isalnum(ch) || ch == '_', "+");
00938 }
00939 break;
00940 
00941 case '-' :
00942 if (type)
00943 {
00944 #ifdef DEBUG
00945 fputs("Identifier: <<<< - >>>\n", stderr);
00946 #endif /* DEBUG */
00947 ch = type->last_child->value.text.string[0];
00948 mxmlNewText(type, isalnum(ch) || ch == '_', "-");
00949 }
00950 break;
00951 
00952 case '=' :
00953 if (type)
00954 {
00955 #ifdef DEBUG
00956 fputs("Identifier: <<<< = >>>\n", stderr);
00957 #endif /* DEBUG */
00958 ch = type->last_child->value.text.string[0];
00959 mxmlNewText(type, isalnum(ch) || ch == '_', "=");
00960 }
00961 break;
00962 
00963 default : /* Other */
00964 if (isalnum(ch) || ch == '_' || ch == '.' || ch == ':' || ch == '~')
00965 {
00966 state = STATE_IDENTIFIER;
00967 bufptr = buffer;
00968 *bufptr++ = ch;
00969 }
00970 break;
00971 }
00972 break;
00973 
00974 case STATE_PREPROCESSOR : /* Preprocessor directive */
00975 if (ch == '\n')
00976 state = STATE_NONE;
00977 else if (ch == '\\')
00978 getc(fp);
00979 break;
00980 
00981 case STATE_C_COMMENT : /* Inside a C comment */
00982 switch (ch)
00983 {
00984 case '\n' :
00985 while ((ch = getc(fp)) != EOF)
00986 if (ch == '*')
00987 {
00988 ch = getc(fp);
00989 
00990 if (ch == '/')
00991 {
00992 *bufptr = '0円';
00993 
00994 if (comment->child != comment->last_child)
00995 {
00996 #ifdef DEBUG
00997 fprintf(stderr, " removing comment %p, last comment %p...\n",
00998 comment->child, comment->last_child);
00999 #endif /* DEBUG */
01000 mxmlDelete(comment->child);
01001 #ifdef DEBUG
01002 fprintf(stderr, " new comment %p, last comment %p...\n",
01003 comment->child, comment->last_child);
01004 #endif /* DEBUG */
01005 }
01006 
01007 #ifdef DEBUG
01008 fprintf(stderr, " processing comment, variable=%p, constant=%p, tree=\"%s\"\n",
01009 variable, constant, tree->value.element.name);
01010 #endif /* DEBUG */
01011 
01012 if (variable)
01013 {
01014 description = mxmlNewElement(variable, "description");
01015 #ifdef DEBUG
01016 fputs(" adding comment to variable...\n", stderr);
01017 #endif /* DEBUG */
01018 update_comment(variable,
01019 mxmlNewText(description, 0, buffer));
01020 variable = NULL;
01021 }
01022 else if (constant)
01023 {
01024 description = mxmlNewElement(constant, "description");
01025 #ifdef DEBUG
01026 fputs(" adding comment to constant...\n", stderr);
01027 #endif /* DEBUG */
01028 update_comment(constant,
01029 mxmlNewText(description, 0, buffer));
01030 constant = NULL;
01031 }
01032 else if (typedefnode)
01033 {
01034 description = mxmlNewElement(typedefnode, "description");
01035 #ifdef DEBUG
01036 fprintf(stderr, " adding comment to typedef %s...\n",
01037 mxmlElementGetAttr(typedefnode, "name"));
01038 #endif /* DEBUG */
01039 update_comment(typedefnode,
01040 mxmlNewText(description, 0, buffer));
01041 }
01042 else if (strcmp(tree->value.element.name, "mxmldoc") &&
01043 !mxmlFindElement(tree, tree, "description",
01044 NULL, NULL, MXML_DESCEND_FIRST))
01045 {
01046 description = mxmlNewElement(tree, "description");
01047 #ifdef DEBUG
01048 fputs(" adding comment to parent...\n", stderr);
01049 #endif /* DEBUG */
01050 update_comment(tree,
01051 mxmlNewText(description, 0, buffer));
01052 }
01053 else
01054 {
01055 #ifdef DEBUG
01056 fprintf(stderr, " before adding comment, child=%p, last_child=%p\n",
01057 comment->child, comment->last_child);
01058 #endif /* DEBUG */
01059 mxmlNewText(comment, 0, buffer);
01060 #ifdef DEBUG
01061 fprintf(stderr, " after adding comment, child=%p, last_child=%p\n",
01062 comment->child, comment->last_child);
01063 #endif /* DEBUG */
01064 }
01065 #ifdef DEBUG
01066 fprintf(stderr, "C comment: <<<< %s >>>\n", buffer);
01067 #endif /* DEBUG */
01068 
01069 state = STATE_NONE;
01070 break;
01071 }
01072 else
01073 ungetc(ch, fp);
01074 }
01075 else if (ch == '\n' && bufptr > buffer &&
01076 bufptr < (buffer + sizeof(buffer) - 1))
01077 *bufptr++ = ch;
01078 else if (!isspace(ch))
01079 break;
01080 
01081 if (ch != EOF)
01082 ungetc(ch, fp);
01083 
01084 if (bufptr > buffer && bufptr < (buffer + sizeof(buffer) - 1))
01085 *bufptr++ = '\n';
01086 break;
01087 
01088 case '/' :
01089 if (ch == '/' && bufptr > buffer && bufptr[-1] == '*')
01090 {
01091 while (bufptr > buffer &&
01092 (bufptr[-1] == '*' || isspace(bufptr[-1] & 255)))
01093 bufptr --;
01094 *bufptr = '0円';
01095 
01096 if (comment->child != comment->last_child)
01097 {
01098 #ifdef DEBUG
01099 fprintf(stderr, " removing comment %p, last comment %p...\n",
01100 comment->child, comment->last_child);
01101 #endif /* DEBUG */
01102 mxmlDelete(comment->child);
01103 #ifdef DEBUG
01104 fprintf(stderr, " new comment %p, last comment %p...\n",
01105 comment->child, comment->last_child);
01106 #endif /* DEBUG */
01107 }
01108 
01109 if (variable)
01110 {
01111 description = mxmlNewElement(variable, "description");
01112 #ifdef DEBUG
01113 fputs(" adding comment to variable...\n", stderr);
01114 #endif /* DEBUG */
01115 update_comment(variable,
01116 mxmlNewText(description, 0, buffer));
01117 variable = NULL;
01118 }
01119 else if (constant)
01120 {
01121 description = mxmlNewElement(constant, "description");
01122 #ifdef DEBUG
01123 fputs(" adding comment to constant...\n", stderr);
01124 #endif /* DEBUG */
01125 update_comment(constant,
01126 mxmlNewText(description, 0, buffer));
01127 constant = NULL;
01128 }
01129 else if (typedefnode)
01130 {
01131 description = mxmlNewElement(typedefnode, "description");
01132 #ifdef DEBUG
01133 fprintf(stderr, " adding comment to typedef %s...\n",
01134 mxmlElementGetAttr(typedefnode, "name"));
01135 #endif /* DEBUG */
01136 update_comment(typedefnode,
01137 mxmlNewText(description, 0, buffer));
01138 }
01139 else if (strcmp(tree->value.element.name, "mxmldoc") &&
01140 !mxmlFindElement(tree, tree, "description",
01141 NULL, NULL, MXML_DESCEND_FIRST))
01142 {
01143 description = mxmlNewElement(tree, "description");
01144 #ifdef DEBUG
01145 fputs(" adding comment to parent...\n", stderr);
01146 #endif /* DEBUG */
01147 update_comment(tree,
01148 mxmlNewText(description, 0, buffer));
01149 }
01150 else
01151 mxmlNewText(comment, 0, buffer);
01152 
01153 #ifdef DEBUG
01154 fprintf(stderr, "C comment: <<<< %s >>>\n", buffer);
01155 #endif /* DEBUG */
01156 
01157 state = STATE_NONE;
01158 break;
01159 }
01160 
01161 default :
01162 if (ch == ' ' && bufptr == buffer)
01163 break;
01164 
01165 if (bufptr < (buffer + sizeof(buffer) - 1))
01166 *bufptr++ = ch;
01167 break;
01168 }
01169 break;
01170 
01171 case STATE_CXX_COMMENT : /* Inside a C++ comment */
01172 if (ch == '\n')
01173 {
01174 state = STATE_NONE;
01175 *bufptr = '0円';
01176 
01177 if (comment->child != comment->last_child)
01178 {
01179 #ifdef DEBUG
01180 fprintf(stderr, " removing comment %p, last comment %p...\n",
01181 comment->child, comment->last_child);
01182 #endif /* DEBUG */
01183 mxmlDelete(comment->child);
01184 #ifdef DEBUG
01185 fprintf(stderr, " new comment %p, last comment %p...\n",
01186 comment->child, comment->last_child);
01187 #endif /* DEBUG */
01188 }
01189 
01190 if (variable)
01191 {
01192 description = mxmlNewElement(variable, "description");
01193 #ifdef DEBUG
01194 fputs(" adding comment to variable...\n", stderr);
01195 #endif /* DEBUG */
01196 update_comment(variable,
01197 mxmlNewText(description, 0, buffer));
01198 variable = NULL;
01199 }
01200 else if (constant)
01201 {
01202 description = mxmlNewElement(constant, "description");
01203 #ifdef DEBUG
01204 fputs(" adding comment to constant...\n", stderr);
01205 #endif /* DEBUG */
01206 update_comment(constant,
01207 mxmlNewText(description, 0, buffer));
01208 constant = NULL;
01209 }
01210 else if (typedefnode)
01211 {
01212 description = mxmlNewElement(typedefnode, "description");
01213 #ifdef DEBUG
01214 fprintf(stderr, " adding comment to typedef %s...\n",
01215 mxmlElementGetAttr(typedefnode, "name"));
01216 #endif /* DEBUG */
01217 update_comment(typedefnode,
01218 mxmlNewText(description, 0, buffer));
01219 }
01220 else if (strcmp(tree->value.element.name, "mxmldoc") &&
01221 !mxmlFindElement(tree, tree, "description",
01222 NULL, NULL, MXML_DESCEND_FIRST))
01223 {
01224 description = mxmlNewElement(tree, "description");
01225 #ifdef DEBUG
01226 fputs(" adding comment to parent...\n", stderr);
01227 #endif /* DEBUG */
01228 update_comment(tree,
01229 mxmlNewText(description, 0, buffer));
01230 }
01231 else
01232 mxmlNewText(comment, 0, buffer);
01233 
01234 #ifdef DEBUG
01235 fprintf(stderr, "C++ comment: <<<< %s >>>\n", buffer);
01236 #endif /* DEBUG */
01237 }
01238 else if (ch == ' ' && bufptr == buffer)
01239 break;
01240 else if (bufptr < (buffer + sizeof(buffer) - 1))
01241 *bufptr++ = ch;
01242 break;
01243 
01244 case STATE_STRING : /* Inside a string constant */
01245 *bufptr++ = ch;
01246 
01247 if (ch == '\\')
01248 *bufptr++ = getc(fp);
01249 else if (ch == '\"')
01250 {
01251 *bufptr = '0円';
01252 
01253 if (type)
01254 mxmlNewText(type, type->child != NULL, buffer);
01255 
01256 state = STATE_NONE;
01257 }
01258 break;
01259 
01260 case STATE_CHARACTER : /* Inside a character constant */
01261 *bufptr++ = ch;
01262 
01263 if (ch == '\\')
01264 *bufptr++ = getc(fp);
01265 else if (ch == '\'')
01266 {
01267 *bufptr = '0円';
01268 
01269 if (type)
01270 mxmlNewText(type, type->child != NULL, buffer);
01271 
01272 state = STATE_NONE;
01273 }
01274 break;
01275 
01276 case STATE_IDENTIFIER : /* Inside a keyword or identifier */
01277 if (isalnum(ch) || ch == '_' || ch == '[' || ch == ']' ||
01278 (ch == ',' && parens > 1) || ch == ':' || ch == '.' || ch == '~')
01279 {
01280 if (bufptr < (buffer + sizeof(buffer) - 1))
01281 *bufptr++ = ch;
01282 }
01283 else
01284 {
01285 ungetc(ch, fp);
01286 *bufptr = '0円';
01287 state = STATE_NONE;
01288 
01289 #ifdef DEBUG
01290 fprintf(stderr, " braces=%d, type=%p, type->child=%p, buffer=\"%s\"\n",
01291 braces, type, type ? type->child : NULL, buffer);
01292 #endif /* DEBUG */
01293 
01294 if (!braces)
01295 {
01296 if (!type || !type->child)
01297 {
01298 if (!strcmp(tree->value.element.name, "class"))
01299 {
01300 if (!strcmp(buffer, "public") ||
01301 !strcmp(buffer, "public:"))
01302 {
01303 scope = "public";
01304 #ifdef DEBUG
01305 fputs(" scope = public\n", stderr);
01306 #endif /* DEBUG */
01307 break;
01308 }
01309 else if (!strcmp(buffer, "private") ||
01310 !strcmp(buffer, "private:"))
01311 {
01312 scope = "private";
01313 #ifdef DEBUG
01314 fputs(" scope = private\n", stderr);
01315 #endif /* DEBUG */
01316 break;
01317 }
01318 else if (!strcmp(buffer, "protected") ||
01319 !strcmp(buffer, "protected:"))
01320 {
01321 scope = "protected";
01322 #ifdef DEBUG
01323 fputs(" scope = protected\n", stderr);
01324 #endif /* DEBUG */
01325 break;
01326 }
01327 }
01328 }
01329 
01330 if (!type)
01331 type = mxmlNewElement(MXML_NO_PARENT, "type");
01332 
01333 #ifdef DEBUG
01334 fprintf(stderr, " function=%p (%s), type->child=%p, ch='%c', parens=%d\n",
01335 function,
01336 function ? mxmlElementGetAttr(function, "name") : "null",
01337 type->child, ch, parens);
01338 #endif /* DEBUG */
01339 
01340 if (!function && ch == '(')
01341 {
01342 if (type->child &&
01343 !strcmp(type->child->value.text.string, "extern"))
01344 {
01345 /*
01346  * Remove external declarations...
01347  */
01348 
01349 mxmlDelete(type);
01350 type = NULL;
01351 break;
01352 }
01353 
01354 if (type->child &&
01355 !strcmp(type->child->value.text.string, "static") &&
01356 !strcmp(tree->value.element.name, "mxmldoc"))
01357 {
01358 /*
01359  * Remove static functions...
01360  */
01361 
01362 mxmlDelete(type);
01363 type = NULL;
01364 break;
01365 }
01366 
01367 function = mxmlNewElement(MXML_NO_PARENT, "function");
01368 if ((bufptr = strchr(buffer, ':')) != NULL && bufptr[1] == ':')
01369 {
01370 *bufptr = '0円';
01371 bufptr += 2;
01372 
01373 if ((fstructclass =
01374 mxmlFindElement(tree, tree, "class", "name", buffer,
01375 MXML_DESCEND_FIRST)) == NULL)
01376 fstructclass =
01377 mxmlFindElement(tree, tree, "struct", "name", buffer,
01378 MXML_DESCEND_FIRST);
01379 }
01380 else
01381 bufptr = buffer;
01382 
01383 mxmlElementSetAttr(function, "name", bufptr);
01384 
01385 if (scope)
01386 mxmlElementSetAttr(function, "scope", scope);
01387 
01388 #ifdef DEBUG
01389 fprintf(stderr, "function: %s\n", buffer);
01390 fprintf(stderr, " scope = %s\n", scope ? scope : "(null)");
01391 fprintf(stderr, " comment = %p\n", comment);
01392 fprintf(stderr, " child = (%p) %s\n",
01393 comment->child,
01394 comment->child ?
01395 comment->child->value.text.string : "(null)");
01396 fprintf(stderr, " last_child = (%p) %s\n",
01397 comment->last_child,
01398 comment->last_child ?
01399 comment->last_child->value.text.string : "(null)");
01400 #endif /* DEBUG */
01401 
01402 if (type->last_child &&
01403 strcmp(type->last_child->value.text.string, "void"))
01404 {
01405 returnvalue = mxmlNewElement(function, "returnvalue");
01406 
01407 mxmlAdd(returnvalue, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
01408 
01409 description = mxmlNewElement(returnvalue, "description");
01410 #ifdef DEBUG
01411 fputs(" adding comment to returnvalue...\n", stderr);
01412 #endif /* DEBUG */
01413 update_comment(returnvalue, comment->last_child);
01414 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
01415 comment->last_child);
01416 }
01417 else
01418 mxmlDelete(type);
01419 
01420 description = mxmlNewElement(function, "description");
01421 #ifdef DEBUG
01422 fputs(" adding comment to function...\n", stderr);
01423 #endif /* DEBUG */
01424 update_comment(function, comment->last_child);
01425 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
01426 comment->last_child);
01427 
01428 type = NULL;
01429 }
01430 else if (function && ((ch == ')' && parens == 1) || ch == ','))
01431 {
01432 /*
01433  * Argument definition...
01434  */
01435 
01436 mxmlNewText(type, type->child != NULL &&
01437 type->last_child->value.text.string[0] != '(' &&
01438 type->last_child->value.text.string[0] != '*',
01439 buffer);
01440 
01441 #ifdef DEBUG
01442 fprintf(stderr, "Argument: <<<< %s >>>\n", buffer);
01443 #endif /* DEBUG */
01444 
01445 variable = add_variable(function, "argument", type);
01446 type = NULL;
01447 }
01448 else if (type->child && !function && (ch == ';' || ch == ','))
01449 {
01450 #ifdef DEBUG
01451 fprintf(stderr, " got semicolon, typedefnode=%p, structclass=%p\n",
01452 typedefnode, structclass);
01453 #endif /* DEBUG */
01454 
01455 if (typedefnode || structclass)
01456 {
01457 #ifdef DEBUG
01458 fprintf(stderr, "Typedef/struct/class: <<<< %s >>>>\n", buffer);
01459 #endif /* DEBUG */
01460 
01461 if (typedefnode)
01462 {
01463 mxmlElementSetAttr(typedefnode, "name", buffer);
01464 
01465 sort_node(tree, typedefnode);
01466 }
01467 
01468 if (structclass && !mxmlElementGetAttr(structclass, "name"))
01469 {
01470 #ifdef DEBUG
01471 fprintf(stderr, "setting struct/class name to %s!\n",
01472 type->last_child->value.text.string);
01473 #endif /* DEBUG */
01474 mxmlElementSetAttr(structclass, "name", buffer);
01475 
01476 sort_node(tree, structclass);
01477 structclass = NULL;
01478 }
01479 
01480 if (typedefnode)
01481 mxmlAdd(typedefnode, MXML_ADD_BEFORE, MXML_ADD_TO_PARENT,
01482 type);
01483 else
01484 mxmlDelete(type);
01485 
01486 type = NULL;
01487 typedefnode = NULL;
01488 }
01489 else if (type->child &&
01490 !strcmp(type->child->value.text.string, "typedef"))
01491 {
01492 /*
01493  * Simple typedef...
01494  */
01495 
01496 #ifdef DEBUG
01497 fprintf(stderr, "Typedef: <<<< %s >>>\n", buffer);
01498 #endif /* DEBUG */
01499 
01500 typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
01501 mxmlElementSetAttr(typedefnode, "name", buffer);
01502 mxmlDelete(type->child);
01503 
01504 sort_node(tree, typedefnode);
01505 
01506 if (type->child)
01507 type->child->value.text.whitespace = 0;
01508 
01509 mxmlAdd(typedefnode, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
01510 type = NULL;
01511 }
01512 else if (!parens)
01513 {
01514 /*
01515  * Variable definition...
01516  */
01517 
01518 if (type->child &&
01519 !strcmp(type->child->value.text.string, "static") &&
01520 !strcmp(tree->value.element.name, "mxmldoc"))
01521 {
01522 /*
01523  * Remove static functions...
01524  */
01525 
01526 mxmlDelete(type);
01527 type = NULL;
01528 break;
01529 }
01530 
01531 mxmlNewText(type, type->child != NULL &&
01532 type->last_child->value.text.string[0] != '(' &&
01533 type->last_child->value.text.string[0] != '*',
01534 buffer);
01535 
01536 #ifdef DEBUG
01537 fprintf(stderr, "Variable: <<<< %s >>>>\n", buffer);
01538 fprintf(stderr, " scope = %s\n", scope ? scope : "(null)");
01539 #endif /* DEBUG */
01540 
01541 variable = add_variable(MXML_NO_PARENT, "variable", type);
01542 type = NULL;
01543 
01544 sort_node(tree, variable);
01545 
01546 if (scope)
01547 mxmlElementSetAttr(variable, "scope", scope);
01548 }
01549 }
01550 else
01551 {
01552 #ifdef DEBUG
01553 fprintf(stderr, "Identifier: <<<< %s >>>>\n", buffer);
01554 #endif /* DEBUG */
01555 
01556 mxmlNewText(type, type->child != NULL &&
01557 type->last_child->value.text.string[0] != '(' &&
01558 type->last_child->value.text.string[0] != '*',
01559 buffer);
01560 }
01561 }
01562 else if (enumeration && !isdigit(buffer[0] & 255))
01563 {
01564 #ifdef DEBUG
01565 fprintf(stderr, "Constant: <<<< %s >>>\n", buffer);
01566 #endif /* DEBUG */
01567 
01568 constant = mxmlNewElement(MXML_NO_PARENT, "constant");
01569 mxmlElementSetAttr(constant, "name", buffer);
01570 sort_node(enumeration, constant);
01571 }
01572 else if (type)
01573 {
01574 mxmlDelete(type);
01575 type = NULL;
01576 }
01577 }
01578 break;
01579 }
01580 
01581 #if DEBUG > 1
01582 if (state != oldstate)
01583 {
01584 fprintf(stderr, " changed states from %s to %s on receipt of character '%c'...\n",
01585 states[oldstate], states[state], oldch);
01586 fprintf(stderr, " variable = %p\n", variable);
01587 if (type)
01588 {
01589 fputs(" type =", stderr);
01590 for (temp = type->child; temp; temp = temp->next)
01591 fprintf(stderr, " \"%s\"", temp->value.text.string);
01592 fputs("\n", stderr);
01593 }
01594 }
01595 #endif /* DEBUG > 1 */
01596 }
01597 
01598 mxmlDelete(comment);
01599 
01600 /*
01601  * All done, return with no errors...
01602  */
01603 
01604 return (0);
01605 }
01606 
01607 
01608 /*
01609  * 'sort_node()' - Insert a node sorted into a tree.
01610  */
01611 
01612 static void
01613 sort_node(mxml_node_t *tree, /* I - Tree to sort into */
01614 mxml_node_t *node) /* I - Node to add */
01615 {
01616 mxml_node_t *temp; /* Current node */
01617 const char *tempname, /* Name of current node */
01618 *nodename, /* Name of node */
01619 *scope; /* Scope */
01620 
01621 
01622 #if DEBUG > 1
01623 fprintf(stderr, " sort_node(tree=%p, node=%p)\n", tree, node);
01624 #endif /* DEBUG > 1 */
01625 
01626 /*
01627  * Range check input...
01628  */
01629 
01630 if (!tree || !node || node->parent == tree)
01631 return;
01632 
01633 /*
01634  * Get the node name...
01635  */
01636 
01637 if ((nodename = mxmlElementGetAttr(node, "name")) == NULL)
01638 return;
01639 
01640 #if DEBUG > 1
01641 fprintf(stderr, " nodename=%p (\"%s\")\n", nodename, nodename);
01642 #endif /* DEBUG > 1 */
01643 
01644 /*
01645  * Delete any existing definition at this level, if one exists...
01646  */
01647 
01648 if ((temp = mxmlFindElement(tree, tree, node->value.element.name,
01649 "name", nodename, MXML_DESCEND_FIRST)) != NULL)
01650 {
01651 /*
01652  * Copy the scope if needed...
01653  */
01654 
01655 if ((scope = mxmlElementGetAttr(temp, "scope")) != NULL &&
01656 mxmlElementGetAttr(node, "scope") == NULL)
01657 {
01658 #ifdef DEBUG
01659 fprintf(stderr, " copying scope %s for %s\n", scope, nodename);
01660 #endif /* DEBUG */
01661 
01662 mxmlElementSetAttr(node, "scope", scope);
01663 }
01664 
01665 mxmlDelete(temp);
01666 }
01667 
01668 /*
01669  * Add the node into the tree at the proper place...
01670  */
01671 
01672 for (temp = tree->child; temp; temp = temp->next)
01673 {
01674 #if DEBUG > 1
01675 fprintf(stderr, " temp=%p\n", temp);
01676 #endif /* DEBUG > 1 */
01677 
01678 if ((tempname = mxmlElementGetAttr(temp, "name")) == NULL)
01679 continue;
01680 
01681 #if DEBUG > 1
01682 fprintf(stderr, " tempname=%p (\"%s\")\n", tempname, tempname);
01683 #endif /* DEBUG > 1 */
01684 
01685 if (strcmp(nodename, tempname) < 0)
01686 break;
01687 }
01688 
01689 if (temp)
01690 mxmlAdd(tree, MXML_ADD_BEFORE, temp, node);
01691 else
01692 mxmlAdd(tree, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
01693 }
01694 
01695 
01696 /*
01697  * 'update_comment()' - Update a comment node.
01698  */
01699 
01700 static void
01701 update_comment(mxml_node_t *parent, /* I - Parent node */
01702 mxml_node_t *comment) /* I - Comment node */
01703 {
01704 char *ptr; /* Pointer into comment */
01705 
01706 
01707 #ifdef DEBUG
01708 fprintf(stderr, "update_comment(parent=%p, comment=%p)\n",
01709 parent, comment);
01710 #endif /* DEBUG */
01711 
01712 /*
01713  * Range check the input...
01714  */
01715 
01716 if (!parent || !comment)
01717 return;
01718 
01719 /*
01720  * Update the comment...
01721  */
01722 
01723 ptr = comment->value.text.string;
01724 
01725 if (*ptr == '\'')
01726 {
01727 /*
01728  * Convert "'name()' - description" to "description".
01729  */
01730 
01731 for (ptr ++; *ptr && *ptr != '\''; ptr ++);
01732 
01733 if (*ptr == '\'')
01734 {
01735 ptr ++;
01736 while (isspace(*ptr & 255))
01737 ptr ++;
01738 
01739 if (*ptr == '-')
01740 ptr ++;
01741 
01742 while (isspace(*ptr & 255))
01743 ptr ++;
01744 
01745 safe_strcpy(comment->value.text.string, ptr);
01746 }
01747 }
01748 else if (!strncmp(ptr, "I ", 2) || !strncmp(ptr, "O ", 2) ||
01749 !strncmp(ptr, "IO ", 3))
01750 {
01751 /*
01752  * 'Convert "I - description", "IO - description", or "O - description"
01753  * to description + directory attribute.
01754  */
01755 
01756 ptr = strchr(ptr, ' ');
01757 *ptr++ = '0円';
01758 
01759 if (!strcmp(parent->value.element.name, "argument"))
01760 mxmlElementSetAttr(parent, "direction", comment->value.text.string);
01761 
01762 while (isspace(*ptr & 255))
01763 ptr ++;
01764 
01765 if (*ptr == '-')
01766 ptr ++;
01767 
01768 while (isspace(*ptr & 255))
01769 ptr ++;
01770 
01771 safe_strcpy(comment->value.text.string, ptr);
01772 }
01773 
01774 /*
01775  * Eliminate leading and trailing *'s...
01776  */
01777 
01778 for (ptr = comment->value.text.string; *ptr == '*'; ptr ++);
01779 for (; isspace(*ptr & 255); ptr ++);
01780 if (ptr > comment->value.text.string)
01781 safe_strcpy(comment->value.text.string, ptr);
01782 
01783 for (ptr = comment->value.text.string + strlen(comment->value.text.string) - 1;
01784 ptr > comment->value.text.string && *ptr == '*';
01785 ptr --)
01786 *ptr = '0円';
01787 for (; ptr > comment->value.text.string && isspace(*ptr & 255); ptr --)
01788 *ptr = '0円';
01789 
01790 #ifdef DEBUG
01791 fprintf(stderr, " updated comment = %s\n", comment->value.text.string);
01792 #endif /* DEBUG */
01793 }
01794 
01795 
01796 /*
01797  * 'write_documentation()' - Write HTML documentation.
01798  */
01799 
01800 static void
01801 write_documentation(mxml_node_t *doc) /* I - XML documentation */
01802 {
01803 int i; /* Looping var */
01804 mxml_node_t *function, /* Current function */
01805 *scut, /* Struct/class/union/typedef */
01806 *arg, /* Current argument */
01807 *description, /* Description of function/var */
01808 *type; /* Type for argument */
01809 const char *name, /* Name of function/type */
01810 *cname, /* Class name */
01811 *defval, /* Default value */
01812 *parent; /* Parent class */
01813 int inscope; /* Variable/method scope */
01814 char prefix; /* Prefix character */
01815 static const char * const scopes[] = /* Scope strings */
01816 {
01817 "private",
01818 "protected",
01819 "public"
01820 };
01821 
01822 
01823 /*
01824  * Standard header...
01825  */
01826 
01827 puts("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
01828 "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
01829 "<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"
01830 "<head>\n"
01831 "\t<title>Documentation</title>\n"
01832 "\t<meta name='creator' content='" MXML_VERSION "'/>\n"
01833 "\t<style><!--\n"
01834 "\th1, h2, h3, p { font-family: sans-serif; text-align: justify; }\n"
01835 "\ttt, pre a:link, pre a:visited, tt a:link, tt a:visited { font-weight: bold; color: #7f0000; }\n"
01836 "\tpre { font-weight: bold; color: #7f0000; margin-left: 2em; }\n"
01837 "\t--></style>\n"
01838 "</head>\n"
01839 "<body>");
01840 
01841 /*
01842  * Table of contents...
01843  */
01844 
01845 puts("<h2>Contents</h2>");
01846 puts("<ul>");
01847 if (mxmlFindElement(doc, doc, "class", NULL, NULL, MXML_DESCEND_FIRST))
01848 puts("\t<li><a href='#_classes'>Classes</a></li>");
01849 if (mxmlFindElement(doc, doc, "enumeration", NULL, NULL, MXML_DESCEND_FIRST))
01850 puts("\t<li><a href='#_enumerations'>Enumerations</a></li>");
01851 if (mxmlFindElement(doc, doc, "function", NULL, NULL, MXML_DESCEND_FIRST))
01852 puts("\t<li><a href='#_functions'>Functions</a></li>");
01853 if (mxmlFindElement(doc, doc, "struct", NULL, NULL, MXML_DESCEND_FIRST))
01854 puts("\t<li><a href='#_structures'>Structures</a></li>");
01855 if (mxmlFindElement(doc, doc, "typedef", NULL, NULL, MXML_DESCEND_FIRST))
01856 puts("\t<li><a href='#_types'>Types</a></li>");
01857 if (mxmlFindElement(doc, doc, "union", NULL, NULL, MXML_DESCEND_FIRST))
01858 puts("\t<li><a href='#_unions'>Unions</a></li>");
01859 if (mxmlFindElement(doc, doc, "variable", NULL, NULL, MXML_DESCEND_FIRST))
01860 puts("\t<li><a href='#_variables'>Variables</a></li>");
01861 puts("</ul>");
01862 
01863 /*
01864  * List of classes...
01865  */
01866 
01867 if (mxmlFindElement(doc, doc, "class", NULL, NULL, MXML_DESCEND_FIRST))
01868 {
01869 puts("<!-- NEW PAGE -->\n"
01870 "<h2><a name='_classes'>Classes</a></h2>\n"
01871 "<ul>");
01872 
01873 for (scut = mxmlFindElement(doc, doc, "class", NULL, NULL,
01874 MXML_DESCEND_FIRST);
01875 scut;
01876 scut = mxmlFindElement(scut, doc, "class", NULL, NULL,
01877 MXML_NO_DESCEND))
01878 {
01879 name = mxmlElementGetAttr(scut, "name");
01880 printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
01881 }
01882 
01883 puts("</ul>");
01884 
01885 for (scut = mxmlFindElement(doc, doc, "class", NULL, NULL,
01886 MXML_DESCEND_FIRST);
01887 scut;
01888 scut = mxmlFindElement(scut, doc, "class", NULL, NULL,
01889 MXML_NO_DESCEND))
01890 {
01891 cname = mxmlElementGetAttr(scut, "name");
01892 printf("<!-- NEW PAGE -->\n"
01893 "<h3><a name='%s'>%s</a></h3>\n"
01894 "<hr noshade/>\n", cname, cname);
01895 
01896 description = mxmlFindElement(scut, scut, "description", NULL,
01897 NULL, MXML_DESCEND_FIRST);
01898 if (description)
01899 {
01900 fputs("<h4>Description</h4>\n"
01901 "<p>", stdout);
01902 write_element(NULL, description);
01903 puts("</p>");
01904 }
01905 
01906 printf("<h4>Definition</h4>\n"
01907 "<pre>\n"
01908 "class %s", cname);
01909 if ((parent = mxmlElementGetAttr(scut, "parent")) != NULL)
01910 printf(" %s", parent);
01911 puts("\n{");
01912 
01913 for (i = 0; i < 3; i ++)
01914 {
01915 inscope = 0;
01916 
01917 for (arg = mxmlFindElement(scut, scut, "variable", "scope", scopes[i],
01918 MXML_DESCEND_FIRST);
01919 arg;
01920 arg = mxmlFindElement(arg, scut, "variable", "scope", scopes[i],
01921 MXML_NO_DESCEND))
01922 {
01923 if (!inscope)
01924 {
01925 inscope = 1;
01926 printf(" %s:\n", scopes[i]);
01927 }
01928 
01929 printf(" ");
01930 write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
01931 NULL, MXML_DESCEND_FIRST));
01932 printf(" %s;\n", mxmlElementGetAttr(arg, "name"));
01933 }
01934 
01935 for (function = mxmlFindElement(scut, scut, "function", "scope", scopes[i],
01936 MXML_DESCEND_FIRST);
01937 function;
01938 function = mxmlFindElement(function, scut, "function", "scope", scopes[i],
01939 MXML_NO_DESCEND))
01940 {
01941 if (!inscope)
01942 {
01943 inscope = 1;
01944 printf(" %s:\n", scopes[i]);
01945 }
01946 
01947 name = mxmlElementGetAttr(function, "name");
01948 
01949 printf(" ");
01950 
01951 arg = mxmlFindElement(function, function, "returnvalue", NULL,
01952 NULL, MXML_DESCEND_FIRST);
01953 
01954 if (arg)
01955 {
01956 write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
01957 NULL, MXML_DESCEND_FIRST));
01958 putchar(' ');
01959 }
01960 else if (strcmp(cname, name) && strcmp(cname, name + 1))
01961 fputs("void ", stdout);
01962 
01963 printf("<a href='#%s.%s'>%s</a>", cname, name, name);
01964 
01965 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
01966 MXML_DESCEND_FIRST), prefix = '(';
01967 arg;
01968 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
01969 MXML_NO_DESCEND), prefix = ',')
01970 {
01971 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
01972 MXML_DESCEND_FIRST);
01973 
01974 putchar(prefix);
01975 if (prefix == ',')
01976 putchar(' ');
01977 
01978 if (type->child)
01979 {
01980 write_element(doc, type);
01981 putchar(' ');
01982 }
01983 fputs(mxmlElementGetAttr(arg, "name"), stdout);
01984 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
01985 printf(" %s", defval);
01986 }
01987 
01988 if (prefix == '(')
01989 puts("(void);");
01990 else
01991 puts(");");
01992 }
01993 }
01994 
01995 puts("};\n</pre>\n"
01996 "<h4>Members</h4>\n"
01997 "<p class='table'><table align='center' border='1' "
01998 "cellpadding='5' cellspacing='0' width='80%'>\n"
01999 "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
02000 "<tbody>");
02001 
02002 for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
02003 MXML_DESCEND_FIRST);
02004 arg;
02005 arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
02006 MXML_NO_DESCEND))
02007 {
02008 printf("<tr><td><tt>%s</tt></td><td>", mxmlElementGetAttr(arg, "name"));
02009 
02010 write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
02011 NULL, MXML_DESCEND_FIRST));
02012 
02013 puts("</td></tr>");
02014 }
02015 
02016 for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
02017 MXML_DESCEND_FIRST);
02018 function;
02019 function = mxmlFindElement(function, scut, "function", NULL, NULL,
02020 MXML_NO_DESCEND))
02021 {
02022 name = mxmlElementGetAttr(function, "name");
02023 
02024 printf("<tr><td><tt><a name='%s.%s'>%s()</a></tt></td><td>",
02025 cname, name, name);
02026 
02027 description = mxmlFindElement(function, function, "description", NULL,
02028 NULL, MXML_DESCEND_FIRST);
02029 if (description)
02030 write_element(NULL, description);
02031 
02032 arg = mxmlFindElement(function, function, "returnvalue", NULL,
02033 NULL, MXML_DESCEND_FIRST);
02034 
02035 if (arg)
02036 {
02037 fputs("\n<i>Returns:</i> ", stdout);
02038 write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
02039 NULL, MXML_DESCEND_FIRST));
02040 }
02041 
02042 puts("</td></tr>");
02043 }
02044 
02045 puts("</tbody></table></p>");
02046 }
02047 }
02048 
02049 /*
02050  * List of enumerations...
02051  */
02052 
02053 if (mxmlFindElement(doc, doc, "enumeration", NULL, NULL, MXML_DESCEND_FIRST))
02054 {
02055 puts("<!-- NEW PAGE -->\n"
02056 "<h2><a name='_enumerations'>Enumerations</a></h2>\n"
02057 "<ul>");
02058 
02059 for (scut = mxmlFindElement(doc, doc, "enumeration", NULL, NULL,
02060 MXML_DESCEND_FIRST);
02061 scut;
02062 scut = mxmlFindElement(scut, doc, "enumeration", NULL, NULL,
02063 MXML_NO_DESCEND))
02064 {
02065 name = mxmlElementGetAttr(scut, "name");
02066 printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
02067 }
02068 
02069 puts("</ul>");
02070 
02071 for (scut = mxmlFindElement(doc, doc, "enumeration", NULL, NULL,
02072 MXML_DESCEND_FIRST);
02073 scut;
02074 scut = mxmlFindElement(scut, doc, "enumeration", NULL, NULL,
02075 MXML_NO_DESCEND))
02076 {
02077 name = mxmlElementGetAttr(scut, "name");
02078 printf("<!-- NEW PAGE -->\n"
02079 "<h3><a name='%s'>%s</a></h3>\n"
02080 "<hr noshade/>\n", name, name);
02081 
02082 description = mxmlFindElement(scut, scut, "description", NULL,
02083 NULL, MXML_DESCEND_FIRST);
02084 if (description)
02085 {
02086 fputs("<h4>Description</h4>\n"
02087 "<p>", stdout);
02088 write_element(NULL, description);
02089 puts("</p>");
02090 }
02091 
02092 puts("<h4>Values</h4>\n"
02093 "<p class='table'><table align='center' border='1' width='80%' "
02094 "cellpadding='5' cellspacing='0' width='80%'>\n"
02095 "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
02096 "<tbody>");
02097 
02098 for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
02099 MXML_DESCEND_FIRST);
02100 arg;
02101 arg = mxmlFindElement(arg, scut, "constant", NULL, NULL,
02102 MXML_NO_DESCEND))
02103 {
02104 printf("<tr><td><tt>%s</tt></td><td>", mxmlElementGetAttr(arg, "name"));
02105 
02106 write_element(doc, mxmlFindElement(arg, arg, "description", NULL,
02107 NULL, MXML_DESCEND_FIRST));
02108 
02109 puts("</td></tr>");
02110 }
02111 
02112 puts("</tbody></table></p>");
02113 }
02114 }
02115 
02116 /*
02117  * List of functions...
02118  */
02119 
02120 if (mxmlFindElement(doc, doc, "function", NULL, NULL, MXML_DESCEND_FIRST))
02121 {
02122 puts("<!-- NEW PAGE -->\n"
02123 "<h2><a name='_functions'>Functions</a></h2>\n"
02124 "<ul>");
02125 
02126 for (function = mxmlFindElement(doc, doc, "function", NULL, NULL,
02127 MXML_DESCEND_FIRST);
02128 function;
02129 function = mxmlFindElement(function, doc, "function", NULL, NULL,
02130 MXML_NO_DESCEND))
02131 {
02132 name = mxmlElementGetAttr(function, "name");
02133 printf("\t<li><a href='#%s'><tt>%s()</tt></a></li>\n", name, name);
02134 }
02135 
02136 puts("</ul>");
02137 
02138 for (function = mxmlFindElement(doc, doc, "function", NULL, NULL,
02139 MXML_DESCEND_FIRST);
02140 function;
02141 function = mxmlFindElement(function, doc, "function", NULL, NULL,
02142 MXML_NO_DESCEND))
02143 {
02144 name = mxmlElementGetAttr(function, "name");
02145 printf("<!-- NEW PAGE -->\n"
02146 "<h3><a name='%s'>%s()</a></h3>\n"
02147 "<hr noshade/>\n", name, name);
02148 
02149 description = mxmlFindElement(function, function, "description", NULL,
02150 NULL, MXML_DESCEND_FIRST);
02151 if (description)
02152 {
02153 fputs("<h4>Description</h4>\n"
02154 "<p>", stdout);
02155 write_element(NULL, description);
02156 puts("</p>");
02157 }
02158 
02159 puts("<h4>Syntax</h4>\n"
02160 "<pre>");
02161 
02162 arg = mxmlFindElement(function, function, "returnvalue", NULL,
02163 NULL, MXML_DESCEND_FIRST);
02164 
02165 if (arg)
02166 write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
02167 NULL, MXML_DESCEND_FIRST));
02168 else
02169 fputs("void", stdout);
02170 
02171 printf("\n%s", name);
02172 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
02173 MXML_DESCEND_FIRST), prefix = '(';
02174 arg;
02175 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
02176 MXML_NO_DESCEND), prefix = ',')
02177 {
02178 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
02179 MXML_DESCEND_FIRST);
02180 
02181 printf("%c\n ", prefix);
02182 if (type->child)
02183 {
02184 write_element(doc, type);
02185 putchar(' ');
02186 }
02187 fputs(mxmlElementGetAttr(arg, "name"), stdout);
02188 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
02189 printf(" %s", defval);
02190 }
02191 
02192 if (prefix == '(')
02193 puts("(void);\n</pre>");
02194 else
02195 puts(");\n</pre>");
02196 
02197 puts("<h4>Arguments</h4>");
02198 
02199 if (prefix == '(')
02200 puts("<p>None.</p>");
02201 else
02202 {
02203 puts("<p class='table'><table align='center' border='1' width='80%' "
02204 "cellpadding='5' cellspacing='0' width='80%'>\n"
02205 "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
02206 "<tbody>");
02207 
02208 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
02209 MXML_DESCEND_FIRST);
02210 arg;
02211 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
02212 MXML_NO_DESCEND))
02213 {
02214 printf("<tr><td><tt>%s</tt></td><td>", mxmlElementGetAttr(arg, "name"));
02215 
02216 write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
02217 NULL, MXML_DESCEND_FIRST));
02218 
02219 puts("</td></tr>");
02220 }
02221 
02222 puts("</tbody></table></p>");
02223 }
02224 
02225 puts("<h4>Returns</h4>");
02226 
02227 arg = mxmlFindElement(function, function, "returnvalue", NULL,
02228 NULL, MXML_DESCEND_FIRST);
02229 
02230 if (!arg)
02231 puts("<p>Nothing.</p>");
02232 else
02233 {
02234 fputs("<p>", stdout);
02235 write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
02236 NULL, MXML_DESCEND_FIRST));
02237 puts("</p>");
02238 }
02239 }
02240 }
02241 
02242 /*
02243  * List of structures...
02244  */
02245 
02246 if (mxmlFindElement(doc, doc, "struct", NULL, NULL, MXML_DESCEND_FIRST))
02247 {
02248 puts("<!-- NEW PAGE -->\n"
02249 "<h2><a name='_structures'>Structures</a></h2>\n"
02250 "<ul>");
02251 
02252 for (scut = mxmlFindElement(doc, doc, "struct", NULL, NULL,
02253 MXML_DESCEND_FIRST);
02254 scut;
02255 scut = mxmlFindElement(scut, doc, "struct", NULL, NULL,
02256 MXML_NO_DESCEND))
02257 {
02258 name = mxmlElementGetAttr(scut, "name");
02259 printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
02260 }
02261 
02262 puts("</ul>");
02263 
02264 for (scut = mxmlFindElement(doc, doc, "struct", NULL, NULL,
02265 MXML_DESCEND_FIRST);
02266 scut;
02267 scut = mxmlFindElement(scut, doc, "struct", NULL, NULL,
02268 MXML_NO_DESCEND))
02269 {
02270 cname = mxmlElementGetAttr(scut, "name");
02271 printf("<!-- NEW PAGE -->\n"
02272 "<h3><a name='%s'>%s</a></h3>\n"
02273 "<hr noshade/>\n", cname, cname);
02274 
02275 description = mxmlFindElement(scut, scut, "description", NULL,
02276 NULL, MXML_DESCEND_FIRST);
02277 if (description)
02278 {
02279 fputs("<h4>Description</h4>\n"
02280 "<p>", stdout);
02281 write_element(NULL, description);
02282 puts("</p>");
02283 }
02284 
02285 printf("<h4>Definition</h4>\n"
02286 "<pre>\n"
02287 "struct %s\n{\n", cname);
02288 for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
02289 MXML_DESCEND_FIRST);
02290 arg;
02291 arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
02292 MXML_NO_DESCEND))
02293 {
02294 printf(" ");
02295 write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
02296 NULL, MXML_DESCEND_FIRST));
02297 printf(" %s;\n", mxmlElementGetAttr(arg, "name"));
02298 }
02299 
02300 for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
02301 MXML_DESCEND_FIRST);
02302 function;
02303 function = mxmlFindElement(function, scut, "function", NULL, NULL,
02304 MXML_NO_DESCEND))
02305 {
02306 name = mxmlElementGetAttr(function, "name");
02307 
02308 printf(" ");
02309 
02310 arg = mxmlFindElement(function, function, "returnvalue", NULL,
02311 NULL, MXML_DESCEND_FIRST);
02312 
02313 if (arg)
02314 {
02315 write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
02316 NULL, MXML_DESCEND_FIRST));
02317 putchar(' ');
02318 }
02319 else if (strcmp(cname, name) && strcmp(cname, name + 1))
02320 fputs("void ", stdout);
02321 
02322 printf("<a href='#%s.%s'>%s</a>", cname, name, name);
02323 
02324 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
02325 MXML_DESCEND_FIRST), prefix = '(';
02326 arg;
02327 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
02328 MXML_NO_DESCEND), prefix = ',')
02329 {
02330 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
02331 MXML_DESCEND_FIRST);
02332 
02333 putchar(prefix);
02334 if (prefix == ',')
02335 putchar(' ');
02336 
02337 if (type->child)
02338 {
02339 write_element(doc, type);
02340 putchar(' ');
02341 }
02342 fputs(mxmlElementGetAttr(arg, "name"), stdout);
02343 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
02344 printf(" %s", defval);
02345 }
02346 
02347 if (prefix == '(')
02348 puts("(void);");
02349 else
02350 puts(");");
02351 }
02352 
02353 puts("};\n</pre>\n"
02354 "<h4>Members</h4>\n"
02355 "<p class='table'><table align='center' border='1' width='80%' "
02356 "cellpadding='5' cellspacing='0' width='80%'>\n"
02357 "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
02358 "<tbody>");
02359 
02360 for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
02361 MXML_DESCEND_FIRST);
02362 arg;
02363 arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
02364 MXML_NO_DESCEND))
02365 {
02366 printf("<tr><td><tt>%s</tt></td><td>", mxmlElementGetAttr(arg, "name"));
02367 
02368 write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
02369 NULL, MXML_DESCEND_FIRST));
02370 
02371 puts("</td></tr>");
02372 }
02373 
02374 for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
02375 MXML_DESCEND_FIRST);
02376 function;
02377 function = mxmlFindElement(function, scut, "function", NULL, NULL,
02378 MXML_NO_DESCEND))
02379 {
02380 name = mxmlElementGetAttr(function, "name");
02381 
02382 printf("<tr><td><tt><a name='%s.%s'>%s()</a></tt></td><td>",
02383 cname, name, name);
02384 
02385 description = mxmlFindElement(function, function, "description", NULL,
02386 NULL, MXML_DESCEND_FIRST);
02387 if (description)
02388 write_element(NULL, description);
02389 
02390 arg = mxmlFindElement(function, function, "returnvalue", NULL,
02391 NULL, MXML_DESCEND_FIRST);
02392 
02393 if (arg)
02394 {
02395 fputs("\n<i>Returns:</i> ", stdout);
02396 write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
02397 NULL, MXML_DESCEND_FIRST));
02398 }
02399 
02400 puts("</td></tr>");
02401 }
02402 
02403 puts("</tbody></table></p>");
02404 }
02405 }
02406 
02407 /*
02408  * List of types...
02409  */
02410 
02411 if (mxmlFindElement(doc, doc, "typedef", NULL, NULL, MXML_DESCEND_FIRST))
02412 {
02413 puts("<!-- NEW PAGE -->\n"
02414 "<h2><a name='_types'>Types</a></h2>\n"
02415 "<ul>");
02416 
02417 for (scut = mxmlFindElement(doc, doc, "typedef", NULL, NULL,
02418 MXML_DESCEND_FIRST);
02419 scut;
02420 scut = mxmlFindElement(scut, doc, "typedef", NULL, NULL,
02421 MXML_NO_DESCEND))
02422 {
02423 name = mxmlElementGetAttr(scut, "name");
02424 printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
02425 }
02426 
02427 puts("</ul>");
02428 
02429 for (scut = mxmlFindElement(doc, doc, "typedef", NULL, NULL,
02430 MXML_DESCEND_FIRST);
02431 scut;
02432 scut = mxmlFindElement(scut, doc, "typedef", NULL, NULL,
02433 MXML_NO_DESCEND))
02434 {
02435 name = mxmlElementGetAttr(scut, "name");
02436 printf("<!-- NEW PAGE -->\n"
02437 "<h3><a name='%s'>%s</a></h3>\n"
02438 "<hr noshade/>\n", name, name);
02439 
02440 description = mxmlFindElement(scut, scut, "description", NULL,
02441 NULL, MXML_DESCEND_FIRST);
02442 if (description)
02443 {
02444 fputs("<h4>Description</h4>\n"
02445 "<p>", stdout);
02446 write_element(NULL, description);
02447 puts("</p>");
02448 }
02449 
02450 fputs("<h4>Definition</h4>\n"
02451 "<pre>\n"
02452 "typedef ", stdout);
02453 write_element(doc, mxmlFindElement(scut, scut, "type", NULL,
02454 NULL, MXML_DESCEND_FIRST));
02455 printf(" %s;\n</pre>\n", name);
02456 }
02457 }
02458 
02459 /*
02460  * List of unions...
02461  */
02462 
02463 if (mxmlFindElement(doc, doc, "union", NULL, NULL, MXML_DESCEND_FIRST))
02464 {
02465 puts("<!-- NEW PAGE -->\n"
02466 "<h2><a name='_unions'>Unions</a></h2>\n"
02467 "<ul>");
02468 
02469 for (scut = mxmlFindElement(doc, doc, "union", NULL, NULL,
02470 MXML_DESCEND_FIRST);
02471 scut;
02472 scut = mxmlFindElement(scut, doc, "union", NULL, NULL,
02473 MXML_NO_DESCEND))
02474 {
02475 name = mxmlElementGetAttr(scut, "name");
02476 printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
02477 }
02478 
02479 puts("</ul>");
02480 
02481 for (scut = mxmlFindElement(doc, doc, "union", NULL, NULL,
02482 MXML_DESCEND_FIRST);
02483 scut;
02484 scut = mxmlFindElement(scut, doc, "union", NULL, NULL,
02485 MXML_NO_DESCEND))
02486 {
02487 name = mxmlElementGetAttr(scut, "name");
02488 printf("<!-- NEW PAGE -->\n"
02489 "<h3><a name='%s'>%s</a></h3>\n"
02490 "<hr noshade/>\n", name, name);
02491 
02492 description = mxmlFindElement(scut, scut, "description", NULL,
02493 NULL, MXML_DESCEND_FIRST);
02494 if (description)
02495 {
02496 fputs("<h4>Description</h4>\n"
02497 "<p>", stdout);
02498 write_element(NULL, description);
02499 puts("</p>");
02500 }
02501 
02502 printf("<h4>Definition</h4>\n"
02503 "<pre>\n"
02504 "union %s\n{\n", name);
02505 for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
02506 MXML_DESCEND_FIRST);
02507 arg;
02508 arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
02509 MXML_NO_DESCEND))
02510 {
02511 printf(" ");
02512 write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
02513 NULL, MXML_DESCEND_FIRST));
02514 printf(" %s;\n", mxmlElementGetAttr(arg, "name"));
02515 }
02516 
02517 puts("};\n</pre>\n"
02518 "<h4>Members</h4>\n"
02519 "<p class='table'><table align='center' border='1' width='80%' "
02520 "cellpadding='5' cellspacing='0' width='80%'>\n"
02521 "<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>\n"
02522 "<tbody>");
02523 
02524 for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
02525 MXML_DESCEND_FIRST);
02526 arg;
02527 arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
02528 MXML_NO_DESCEND))
02529 {
02530 printf("<tr><td><tt>%s</tt></td><td>", mxmlElementGetAttr(arg, "name"));
02531 
02532 write_element(NULL, mxmlFindElement(arg, arg, "description", NULL,
02533 NULL, MXML_DESCEND_FIRST));
02534 
02535 puts("</td></tr>");
02536 }
02537 
02538 puts("</tbody></table></p>");
02539 }
02540 }
02541 
02542 /*
02543  * Variables...
02544  */
02545 
02546 if (mxmlFindElement(doc, doc, "variable", NULL, NULL, MXML_DESCEND_FIRST))
02547 {
02548 puts("<!-- NEW PAGE -->\n"
02549 "<h2><a name='_variables'>Variables</a></h2>\n"
02550 "<ul>");
02551 
02552 for (arg = mxmlFindElement(doc, doc, "variable", NULL, NULL,
02553 MXML_DESCEND_FIRST);
02554 arg;
02555 arg = mxmlFindElement(arg, doc, "variable", NULL, NULL,
02556 MXML_NO_DESCEND))
02557 {
02558 name = mxmlElementGetAttr(arg, "name");
02559 printf("\t<li><a href='#%s'><tt>%s</tt></a></li>\n", name, name);
02560 }
02561 
02562 puts("</ul>");
02563 
02564 for (arg = mxmlFindElement(doc, doc, "variable", NULL, NULL,
02565 MXML_DESCEND_FIRST);
02566 arg;
02567 arg = mxmlFindElement(arg, doc, "variable", NULL, NULL,
02568 MXML_NO_DESCEND))
02569 {
02570 name = mxmlElementGetAttr(arg, "name");
02571 printf("<!-- NEW PAGE -->\n"
02572 "<h3><a name='%s'>%s</a></h3>\n"
02573 "<hr noshade/>", name, name);
02574 
02575 description = mxmlFindElement(arg, arg, "description", NULL,
02576 NULL, MXML_DESCEND_FIRST);
02577 if (description)
02578 {
02579 fputs("<h4>Description</h4>\n"
02580 "<p>", stdout);
02581 write_element(NULL, description);
02582 puts("</p>");
02583 }
02584 
02585 puts("<h4>Definition</h4>\n"
02586 "<pre>");
02587 
02588 write_element(doc, mxmlFindElement(arg, arg, "type", NULL,
02589 NULL, MXML_DESCEND_FIRST));
02590 printf(" %s", mxmlElementGetAttr(arg, "name"));
02591 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
02592 printf(" %s", defval);
02593 puts(";\n</pre>");
02594 }
02595 }
02596 
02597 /*
02598  * Standard footer...
02599  */
02600 
02601 puts("</body>\n"
02602 "</html>");
02603 }
02604 
02605 
02606 /*
02607  * 'write_element()' - Write an element's text nodes.
02608  */
02609 
02610 static void
02611 write_element(mxml_node_t *doc, /* I - Document tree */
02612 mxml_node_t *element) /* I - Element to write */
02613 {
02614 mxml_node_t *node; /* Current node */
02615 
02616 
02617 if (!element)
02618 return;
02619 
02620 for (node = element->child;
02621 node;
02622 node = mxmlWalkNext(node, element, MXML_NO_DESCEND))
02623 if (node->type == MXML_TEXT)
02624 {
02625 if (node->value.text.whitespace)
02626 putchar(' ');
02627 
02628 if (mxmlFindElement(doc, doc, "class", "name", node->value.text.string,
02629 MXML_DESCEND) ||
02630 mxmlFindElement(doc, doc, "enumeration", "name",
02631 node->value.text.string, MXML_DESCEND) ||
02632 mxmlFindElement(doc, doc, "struct", "name", node->value.text.string,
02633 MXML_DESCEND) ||
02634 mxmlFindElement(doc, doc, "typedef", "name", node->value.text.string,
02635 MXML_DESCEND) ||
02636 mxmlFindElement(doc, doc, "union", "name", node->value.text.string,
02637 MXML_DESCEND))
02638 {
02639 printf("<a href='#");
02640 write_string(node->value.text.string);
02641 printf("'>");
02642 write_string(node->value.text.string);
02643 printf("</a>");
02644 }
02645 else
02646 write_string(node->value.text.string);
02647 }
02648 }
02649 
02650 
02651 /*
02652  * 'write_string()' - Write a string, quoting XHTML special chars as needed...
02653  */
02654 
02655 static void
02656 write_string(const char *s) /* I - String to write */
02657 {
02658 while (*s)
02659 {
02660 if (*s == '&')
02661 fputs("&amp;", stdout);
02662 else if (*s == '<')
02663 fputs("&lt;", stdout);
02664 else if (*s == '>')
02665 fputs("&gt;", stdout);
02666 else if (*s == '\"')
02667 fputs("&quot;", stdout);
02668 else if (*s & 128)
02669 {
02670 /*
02671  * Convert UTF-8 to Unicode constant...
02672  */
02673 
02674 int ch; /* Unicode character */
02675 
02676 
02677 ch = *s & 255;
02678 
02679 if ((ch & 0xe0) == 0xc0)
02680 {
02681 ch = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
02682 s ++;
02683 }
02684 else if ((ch & 0xf0) == 0xe0)
02685 {
02686 ch = ((((ch * 0x0f) << 6) | (s[1] & 0x3f)) << 6) | (s[2] & 0x3f);
02687 s += 2;
02688 }
02689 
02690 if (ch == 0xa0)
02691 {
02692 /*
02693  * Handle non-breaking space as-is...
02694  */
02695 
02696 fputs("&nbsp;", stdout);
02697 }
02698 else
02699 printf("&#x%x;", ch);
02700 }
02701 else
02702 putchar(*s);
02703 
02704 s ++;
02705 }
02706 }
02707 
02708 
02709 /*
02710  * 'ws_cb()' - Whitespace callback for saving.
02711  */
02712 
02713 static const char * /* O - Whitespace string or NULL for none */
02714 ws_cb(mxml_node_t *node, /* I - Element node */
02715 int where) /* I - Where value */
02716 {
02717 const char *name; /* Name of element */
02718 int depth; /* Depth of node */
02719 static const char *spaces = " ";
02720 /* Whitespace (40 spaces) for indent */
02721 
02722 
02723 name = node->value.element.name;
02724 
02725 switch (where)
02726 {
02727 case MXML_WS_BEFORE_CLOSE :
02728 if (strcmp(name, "argument") &&
02729 strcmp(name, "class") &&
02730 strcmp(name, "constant") &&
02731 strcmp(name, "enumeration") &&
02732 strcmp(name, "function") &&
02733 strcmp(name, "mxmldoc") &&
02734 strcmp(name, "namespace") &&
02735 strcmp(name, "returnvalue") &&
02736 strcmp(name, "struct") &&
02737 strcmp(name, "typedef") &&
02738 strcmp(name, "union") &&
02739 strcmp(name, "variable"))
02740 return (NULL);
02741 
02742 for (depth = -4; node; node = node->parent, depth += 2);
02743 if (depth > 40)
02744 return (spaces);
02745 else if (depth < 2)
02746 return (NULL);
02747 else
02748 return (spaces + 40 - depth);
02749 
02750 case MXML_WS_AFTER_CLOSE :
02751 return ("\n");
02752 
02753 case MXML_WS_BEFORE_OPEN :
02754 for (depth = -4; node; node = node->parent, depth += 2);
02755 if (depth > 40)
02756 return (spaces);
02757 else if (depth < 2)
02758 return (NULL);
02759 else
02760 return (spaces + 40 - depth);
02761 
02762 default :
02763 case MXML_WS_AFTER_OPEN :
02764 if (strcmp(name, "argument") &&
02765 strcmp(name, "class") &&
02766 strcmp(name, "constant") &&
02767 strcmp(name, "enumeration") &&
02768 strcmp(name, "function") &&
02769 strcmp(name, "mxmldoc") &&
02770 strcmp(name, "namespace") &&
02771 strcmp(name, "returnvalue") &&
02772 strcmp(name, "struct") &&
02773 strcmp(name, "typedef") &&
02774 strcmp(name, "union") &&
02775 strcmp(name, "variable"))
02776 return (NULL);
02777 else
02778 return ("\n");
02779 }
02780 }
02781 
02782 
02783 /*
02784  * End of "$Id: mxmldoc.c,v 1.1 2007年05月23日 20:43:28 david_ko Exp $".
02785  */

Generated on Tue Oct 28 17:03:22 2008 for Mobile-C by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /