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("&", stdout); 02662 else if (*s == '<') 02663 fputs("<", stdout); 02664 else if (*s == '>') 02665 fputs(">", stdout); 02666 else if (*s == '\"') 02667 fputs(""", 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(" ", 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 */