00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 #include "config.h"
00042 #include "mxml.h"
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117  
00118 
00119 
00120 
00121 
00122 
00123 #define STATE_NONE              0       
00124 #define STATE_PREPROCESSOR      1       
00125 #define STATE_C_COMMENT         2       
00126 #define STATE_CXX_COMMENT       3       
00127 #define STATE_STRING            4       
00128 #define STATE_CHARACTER         5       
00129 #define STATE_IDENTIFIER        6       
00130 
00131 
00132 
00133 
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 
00152 
00153 
00154 int                                     
00155 main(int  argc,                         
00156      char *argv[])                      
00157 {
00158   int           i;                      
00159   FILE          *fp;                    
00160   mxml_node_t   *doc;                   
00161   mxml_node_t   *mxmldoc;               
00162 
00163 
00164  
00165 
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 
00176 
00177 
00178   if ((fp = fopen(argv[1], "r")) != NULL)
00179   {
00180    
00181 
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 
00215 
00216 
00217     doc = mxmlNewElement(NULL, "?xml version=\"1.0\"?");
00218 
00219     mxmldoc = mxmlNewElement(doc, "mxmldoc");
00220 
00221 #ifdef MXML_INCLUDE_SCHEMA
00222    
00223 
00224 
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 
00233   }
00234 
00235  
00236 
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 
00260 
00261 
00262     if ((fp = fopen(argv[1], "w")) != NULL)
00263     {
00264      
00265 
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 
00290 
00291 
00292   write_documentation(mxmldoc);
00293 
00294  
00295 
00296 
00297 
00298   mxmlDelete(doc);
00299 
00300   return (0);
00301 }
00302 
00303 
00304 
00305 
00306 
00307 
00308 static mxml_node_t *                    
00309 add_variable(mxml_node_t *parent,       
00310              const char  *name,         
00311              mxml_node_t *type)         
00312 {
00313   mxml_node_t   *variable,              
00314                 *node,                  
00315                 *next;                  
00316   char          buffer[16384],          
00317                 *bufptr;                
00318 
00319 
00320  
00321 
00322 
00323 
00324   if (!type || !type->child)
00325     return (NULL);
00326 
00327  
00328 
00329 
00330 
00331   variable = mxmlNewElement(parent, name);
00332 
00333  
00334 
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 
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 
00364 
00365 
00366   if (type->last_child->value.text.string[0] == ')')
00367   {
00368    
00369 
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 
00392 
00393 
00394     strcpy(buffer, type->last_child->value.text.string);
00395     mxmlDelete(type->last_child);
00396   }
00397 
00398  
00399 
00400 
00401 
00402   mxmlElementSetAttr(variable, "name", buffer);
00403 
00404  
00405 
00406 
00407 
00408   mxmlAdd(variable, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
00409 
00410  
00411 
00412 
00413 
00414   return (variable);
00415 }
00416 
00417 
00418 
00419 
00420 
00421 
00422 static void
00423 safe_strcpy(char       *dst,            
00424             const char *src)            
00425 {
00426   while (*src)
00427     *dst++ = *src++;
00428 
00429   *dst = '\0';
00430 }
00431 
00432 
00433 
00434 
00435 
00436 
00437 static int                              
00438 scan_file(const char  *filename,        
00439           FILE        *fp,              
00440           mxml_node_t *tree)            
00441 {
00442   int           state,                  
00443                 braces,                 
00444                 parens;                 
00445   int           ch;                     
00446   char          buffer[65536],          
00447                 *bufptr;                
00448   const char    *scope;                 
00449   mxml_node_t   *comment,               
00450                 *constant,              
00451                 *enumeration,           
00452                 *function,              
00453                 *fstructclass,          
00454                 *structclass,           
00455                 *typedefnode,           
00456                 *variable,              
00457                 *returnvalue,           
00458                 *type,                  
00459                 *description,           
00460                 *node,                  
00461                 *next;                  
00462 #if DEBUG > 1
00463   mxml_node_t   *temp;                  
00464   int           oldstate,               
00465                 oldch;                  
00466   static const char *states[] =         
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 
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 
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 
00512 
00513 
00514   while ((ch = getc(fp)) != EOF)
00515   {
00516 #if DEBUG > 1
00517     oldstate = state;
00518     oldch    = ch;
00519 #endif 
00520 
00521     switch (state)
00522     {
00523       case STATE_NONE :                 
00524           switch (ch)
00525           {
00526             case '/' :                  
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 
00543                     ch = type->last_child->value.text.string[0];
00544                     mxmlNewText(type, isalnum(ch) || ch == '_', "/");
00545                   }
00546                 }
00547                 break;
00548 
00549             case '#' :                  
00550 #ifdef DEBUG
00551                 fputs("    #preprocessor...\n", stderr);
00552 #endif 
00553                 state = STATE_PREPROCESSOR;
00554                 break;
00555 
00556             case '\'' :                 
00557                 state = STATE_CHARACTER;
00558                 bufptr = buffer;
00559                 *bufptr++ = ch;
00560                 break;
00561 
00562             case '\"' :                 
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 
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 
00601 
00602 
00603                   if (!strcmp(type->child->value.text.string, "typedef"))
00604                   {
00605 #ifdef DEBUG
00606                     fputs("    starting typedef...\n", stderr);
00607 #endif 
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 
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 
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 
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 
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 
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 
00736 
00737 
00738                   if (!strcmp(type->child->value.text.string, "typedef"))
00739                   {
00740 #ifdef DEBUG
00741                     fputs("    starting typedef...\n", stderr);
00742 #endif 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
00905                   mxmlNewText(type, 1, ":");
00906                 }
00907                 break;
00908 
00909             case '*' :
00910                 if (type)
00911                 {
00912 #ifdef DEBUG
00913                   fputs("Identifier: <<<< * >>>\n", stderr);
00914 #endif 
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 
00926                   mxmlNewText(type, 1, "&");
00927                 }
00928                 break;
00929 
00930             case '+' :
00931                 if (type)
00932                 {
00933 #ifdef DEBUG
00934                   fputs("Identifier: <<<< + >>>\n", stderr);
00935 #endif 
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 
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 
00958                   ch = type->last_child->value.text.string[0];
00959                   mxmlNewText(type, isalnum(ch) || ch == '_', "=");
00960                 }
00961                 break;
00962 
00963             default :                   
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 :         
00975           if (ch == '\n')
00976             state = STATE_NONE;
00977           else if (ch == '\\')
00978             getc(fp);
00979           break;
00980 
00981       case STATE_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 
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 
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 
01011 
01012                       if (variable)
01013                       {
01014                         description = mxmlNewElement(variable, "description");
01015 #ifdef DEBUG
01016                         fputs("    adding comment to variable...\n", stderr);
01017 #endif 
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 
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 
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 
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 
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 
01064                       }
01065 #ifdef DEBUG
01066                       fprintf(stderr, "C comment: <<<< %s >>>\n", buffer);
01067 #endif 
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 
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 
01107                   }
01108 
01109                   if (variable)
01110                   {
01111                     description = mxmlNewElement(variable, "description");
01112 #ifdef DEBUG
01113                     fputs("    adding comment to variable...\n", stderr);
01114 #endif 
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 
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 
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 
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 
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 :          
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 
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 
01188             }
01189 
01190             if (variable)
01191             {
01192               description = mxmlNewElement(variable, "description");
01193 #ifdef DEBUG
01194               fputs("    adding comment to variable...\n", stderr);
01195 #endif 
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 
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 
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 
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 
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 :               
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 :            
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 :           
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 
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 
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 
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 
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 
01339 
01340               if (!function && ch == '(')
01341               {
01342                 if (type->child &&
01343                     !strcmp(type->child->value.text.string, "extern"))
01344                 {
01345                  
01346 
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 
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 
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 
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 
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 
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 
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 
01454 
01455                 if (typedefnode || structclass)
01456                 {
01457 #ifdef DEBUG
01458                   fprintf(stderr, "Typedef/struct/class: <<<< %s >>>>\n", buffer);
01459 #endif 
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 
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 
01494 
01495 
01496 #ifdef DEBUG
01497                   fprintf(stderr, "Typedef: <<<< %s >>>\n", buffer);
01498 #endif 
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 
01516 
01517 
01518                   if (type->child &&
01519                       !strcmp(type->child->value.text.string, "static") &&
01520                       !strcmp(tree->value.element.name, "mxmldoc"))
01521                   {
01522                    
01523 
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 
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 
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 
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 
01596   }
01597 
01598   mxmlDelete(comment);
01599 
01600  
01601 
01602 
01603 
01604   return (0);
01605 }
01606 
01607 
01608 
01609 
01610 
01611 
01612 static void
01613 sort_node(mxml_node_t *tree,            
01614           mxml_node_t *node)            
01615 {
01616   mxml_node_t   *temp;                  
01617   const char    *tempname,              
01618                 *nodename,              
01619                 *scope;                 
01620 
01621 
01622 #if DEBUG > 1
01623   fprintf(stderr, "    sort_node(tree=%p, node=%p)\n", tree, node);
01624 #endif 
01625 
01626  
01627 
01628 
01629 
01630   if (!tree || !node || node->parent == tree)
01631     return;
01632 
01633  
01634 
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 
01643 
01644  
01645 
01646 
01647 
01648   if ((temp = mxmlFindElement(tree, tree, node->value.element.name,
01649                               "name", nodename, MXML_DESCEND_FIRST)) != NULL)
01650   {
01651    
01652 
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 
01661 
01662       mxmlElementSetAttr(node, "scope", scope);
01663     }
01664 
01665     mxmlDelete(temp);
01666   }
01667 
01668  
01669 
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 
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 
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 
01698 
01699 
01700 static void
01701 update_comment(mxml_node_t *parent,     
01702                mxml_node_t *comment)    
01703 {
01704   char  *ptr;                           
01705 
01706 
01707 #ifdef DEBUG
01708   fprintf(stderr, "update_comment(parent=%p, comment=%p)\n",
01709           parent, comment);
01710 #endif 
01711 
01712  
01713 
01714 
01715 
01716   if (!parent || !comment)
01717     return;
01718  
01719  
01720 
01721 
01722 
01723   ptr = comment->value.text.string;
01724 
01725   if (*ptr == '\'')
01726   {
01727    
01728 
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 
01753 
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 
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 
01793 }
01794 
01795 
01796 
01797 
01798 
01799 
01800 static void
01801 write_documentation(mxml_node_t *doc)   
01802 {
01803   int           i;                      
01804   mxml_node_t   *function,              
01805                 *scut,                  
01806                 *arg,                   
01807                 *description,           
01808                 *type;                  
01809   const char    *name,                  
01810                 *cname,                 
01811                 *defval,                
01812                 *parent;                
01813   int           inscope;                
01814   char          prefix;                 
01815   static const char * const scopes[] =  
01816                 {
01817                   "private",
01818                   "protected",
01819                   "public"
01820                 };
01821 
01822 
01823  
01824 
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 
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 
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 
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 
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 
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 
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 
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 
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 
02599 
02600 
02601   puts("</body>\n"
02602        "</html>");
02603 }
02604 
02605 
02606 
02607 
02608 
02609 
02610 static void
02611 write_element(mxml_node_t *doc,         
02612               mxml_node_t *element)     
02613 {
02614   mxml_node_t   *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 
02653 
02654 
02655 static void
02656 write_string(const char *s)             
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 
02672 
02673 
02674       int       ch;                     
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 
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 
02711 
02712 
02713 static const char *                     
02714 ws_cb(mxml_node_t *node,                
02715       int         where)                
02716 {
02717   const char *name;                     
02718   int   depth;                          
02719   static const char *spaces = "                                        ";
02720                                         
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 
02785