📄 mxmldoc.c
字号:
/* * "$Id: mxmldoc.c 342 2008-01-29 05:28:31Z mike $" * * Documentation generator using Mini-XML, a small XML-like file parsing * library. * * Copyright 2003-2008 by Michael Sweet. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Contents: * * main() - Main entry for test program. * add_variable() - Add a variable or argument. * find_public() - Find a public function, type, etc. * get_comment_info() - Get info from comment. * get_text() - Get the text for a node. * load_cb() - Set the type of child nodes. * new_documentation() - Create a new documentation tree. * safe_strcpy() - Copy a string allowing for overlapping strings. * scan_file() - Scan a source file. * sort_node() - Insert a node sorted into a tree. * update_comment() - Update a comment node. * usage() - Show program usage... * write_description() - Write the description text. * write_element() - Write an element's text nodes. * write_file() - Copy a file to the output. * write_function() - Write documentation for a function. * write_html() - Write HTML documentation. * write_html_head() - Write the standard HTML header. * write_man() - Write manpage documentation. * write_scu() - Write a structure, class, or union. * write_string() - Write a string, quoting HTML special chars as * needed... * write_toc() - Write a table-of-contents. * ws_cb() - Whitespace callback for saving. *//* * Include necessary headers... */#include "config.h"#include "mxml.h"#include <time.h>/* * This program scans source and header files and produces public API * documentation for code that conforms to the CUPS Configuration * Management Plan (CMP) coding standards. Please see the following web * page for details: * * http://www.cups.org/cmp.html * * Using Mini-XML, this program creates and maintains an XML representation * of the public API code documentation which can then be converted to HTML * as desired. The following is a poor-man's schema: * * <?xml version="1.0"?> * <mxmldoc xmlns="http://www.easysw.com" * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" * xsi:schemaLocation="http://www.minixml.org/mxmldoc.xsd"> * * <namespace name=""> [optional...] * <constant name=""> * <description>descriptive text</description> * </constant> * * <enumeration name=""> * <description>descriptive text</description> * <constant name="">...</constant> * </enumeration> * * <typedef name=""> * <description>descriptive text</description> * <type>type string</type> * </typedef> * * <function name="" scope=""> * <description>descriptive text</description> * <argument name="" direction="I|O|IO" default=""> * <description>descriptive text</description> * <type>type string</type> * </argument> * <returnvalue> * <description>descriptive text</description> * <type>type string</type> * </returnvalue> * <seealso>function names separated by spaces</seealso> * </function> * * <variable name="" scope=""> * <description>descriptive text</description> * <type>type string</type> * </variable> * * <struct name=""> * <description>descriptive text</description> * <variable name="">...</variable> * <function name="">...</function> * </struct> * * <union name=""> * <description>descriptive text</description> * <variable name="">...</variable> * </union> * * <class name="" parent=""> * <description>descriptive text</description> * <class name="">...</class> * <enumeration name="">...</enumeration> * <function name="">...</function> * <struct name="">...</struct> * <variable name="">...</variable> * </class> * </namespace> * </mxmldoc> */ /* * Basic states for file parser... */#define STATE_NONE 0 /* No state - whitespace, etc. */#define STATE_PREPROCESSOR 1 /* Preprocessor directive */#define STATE_C_COMMENT 2 /* Inside a C comment */#define STATE_CXX_COMMENT 3 /* Inside a C++ comment */#define STATE_STRING 4 /* Inside a string constant */#define STATE_CHARACTER 5 /* Inside a character constant */#define STATE_IDENTIFIER 6 /* Inside a keyword/identifier *//* * Output modes... */#define OUTPUT_NONE 0 /* No output */#define OUTPUT_HTML 1 /* Output HTML */#define OUTPUT_MAN 2 /* Output nroff/man *//* * Local functions... */static mxml_node_t *add_variable(mxml_node_t *parent, const char *name, mxml_node_t *type);static mxml_node_t *find_public(mxml_node_t *node, mxml_node_t *top, const char *name);static char *get_comment_info(mxml_node_t *description);static char *get_text(mxml_node_t *node, char *buffer, int buflen);static mxml_type_t load_cb(mxml_node_t *node);static mxml_node_t *new_documentation(mxml_node_t **mxmldoc);static void safe_strcpy(char *dst, const char *src);static int scan_file(const char *filename, FILE *fp, mxml_node_t *doc);static void sort_node(mxml_node_t *tree, mxml_node_t *func);static void update_comment(mxml_node_t *parent, mxml_node_t *comment);static void usage(const char *option);static void write_description(FILE *out, mxml_node_t *description, const char *element, int summary);static void write_element(FILE *out, mxml_node_t *doc, mxml_node_t *element, int mode);static void write_file(FILE *out, const char *file);static void write_function(FILE *out, mxml_node_t *doc, mxml_node_t *function, int level);static void write_html(const char *section, const char *title, const char *footerfile, const char *headerfile, const char *introfile, const char *cssfile, const char *framefile, mxml_node_t *doc);static void write_html_head(FILE *out, const char *section, const char *title, const char *cssfile);static void write_man(const char *man_name, const char *section, const char *title, const char *headerfile, const char *footerfile, const char *introfile, mxml_node_t *doc);static void write_scu(FILE *out, mxml_node_t *doc, mxml_node_t *scut);static void write_string(FILE *out, const char *s, int mode);static void write_toc(FILE *out, mxml_node_t *doc, const char *introfile, const char *target);static const char *ws_cb(mxml_node_t *node, int where);/* * 'main()' - Main entry for test program. */int /* O - Exit status */main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line args */{ int i; /* Looping var */ int len; /* Length of argument */ FILE *fp; /* File to read */ mxml_node_t *doc; /* XML documentation tree */ mxml_node_t *mxmldoc; /* mxmldoc node */ const char *section; /* Section/keywords of documentation */ const char *title; /* Title of documentation */ const char *cssfile; /* CSS stylesheet file */ const char *footerfile; /* Footer file */ const char *framefile; /* Framed HTML basename */ const char *headerfile; /* Header file */ const char *introfile; /* Introduction file */ const char *xmlfile; /* XML file */ const char *name; /* Name of manpage */ int update; /* Updated XML file */ int mode; /* Output mode */ /* * Check arguments... */ name = NULL; section = NULL; title = NULL; cssfile = NULL; footerfile = NULL; framefile = NULL; headerfile = NULL; introfile = NULL; xmlfile = NULL; update = 0; doc = NULL; mxmldoc = NULL; mode = OUTPUT_HTML; for (i = 1; i < argc; i ++) if (!strcmp(argv[i], "--help")) { /* * Show help... */ usage(NULL); } else if (!strcmp(argv[i], "--css") && !cssfile) { /* * Set CSS stylesheet file... */ i ++; if (i < argc) cssfile = argv[i]; else usage(NULL); } else if (!strcmp(argv[i], "--footer") && !footerfile) { /* * Set footer file... */ i ++; if (i < argc) footerfile = argv[i]; else usage(NULL); } else if (!strcmp(argv[i], "--framed") && !framefile) { /* * Set base filename for framed HTML output... */ i ++; if (i < argc) framefile = argv[i]; else usage(NULL); } else if (!strcmp(argv[i], "--header") && !headerfile) { /* * Set header file... */ i ++; if (i < argc) headerfile = argv[i]; else usage(NULL); } else if (!strcmp(argv[i], "--intro") && !introfile) { /* * Set intro file... */ i ++; if (i < argc) introfile = argv[i]; else usage(NULL); } else if (!strcmp(argv[i], "--man") && !name) { /* * Output manpage... */ i ++; if (i < argc) { mode = OUTPUT_MAN; name = argv[i]; } else usage(NULL); } else if (!strcmp(argv[i], "--no-output")) mode = OUTPUT_NONE; else if (!strcmp(argv[i], "--section") && !section) { /* * Set section/keywords... */ i ++; if (i < argc) section = argv[i]; else usage(NULL); } else if (!strcmp(argv[i], "--title") && !title) { /* * Set title... */ i ++; if (i < argc) title = argv[i]; else usage(NULL); } else if (argv[i][0] == '-') { /* * Unknown/bad option... */ usage(argv[i]); } else { /* * Process XML or source file... */ len = (int)strlen(argv[i]); if (len > 4 && !strcmp(argv[i] + len - 4, ".xml")) { /* * Set XML file... */ if (xmlfile) usage(NULL); xmlfile = argv[i]; if (!doc) { if ((fp = fopen(argv[i], "r")) != NULL) { /* * Read the existing XML file... */ doc = mxmlLoadFile(NULL, fp, load_cb); fclose(fp); if (!doc) { mxmldoc = NULL; fprintf(stderr, "mxmldoc: Unable to read the XML documentation file " "\"%s\"!\n", argv[i]); } else if ((mxmldoc = mxmlFindElement(doc, doc, "mxmldoc", NULL, NULL, MXML_DESCEND)) == NULL) { fprintf(stderr, "mxmldoc: XML documentation file \"%s\" is missing " "<mxmldoc> node!!\n", argv[i]); mxmlDelete(doc); doc = NULL; } } else { doc = NULL; mxmldoc = NULL; } if (!doc) doc = new_documentation(&mxmldoc); } } else { /* * Load source file... */ update = 1; if (!doc) doc = new_documentation(&mxmldoc); if ((fp = fopen(argv[i], "r")) == NULL) { fprintf(stderr, "mxmldoc: Unable to open source file \"%s\": %s\n", argv[i], strerror(errno)); mxmlDelete(doc); return (1); } else if (scan_file(argv[i], fp, mxmldoc)) { fclose(fp); mxmlDelete(doc); return (1); } else fclose(fp); } } if (update && xmlfile) { /* * Save the updated XML documentation file... */ if ((fp = fopen(xmlfile, "w")) != NULL) { /* * Write over the existing XML file... */ if (mxmlSaveFile(doc, fp, ws_cb)) { fprintf(stderr, "mxmldoc: Unable to write the XML documentation file \"%s\": " "%s!\n", xmlfile, strerror(errno)); fclose(fp); mxmlDelete(doc); return (1); } fclose(fp); } else { fprintf(stderr, "mxmldoc: Unable to create the XML documentation file \"%s\": " "%s!\n", xmlfile, strerror(errno)); mxmlDelete(doc); return (1); } } switch (mode) { case OUTPUT_HTML : /* * Write HTML documentation... */ write_html(section, title ? title : "Documentation", footerfile, headerfile, introfile, cssfile, framefile, mxmldoc); break; case OUTPUT_MAN : /* * Write manpage documentation... */ write_man(name, section, title, footerfile, headerfile, introfile, mxmldoc); break; } /* * Delete the tree and return... */ mxmlDelete(doc); return (0);}/* * 'add_variable()' - Add a variable or argument. */static mxml_node_t * /* O - New variable/argument */add_variable(mxml_node_t *parent, /* I - Parent node */ const char *name, /* I - "argument" or "variable" */ mxml_node_t *type) /* I - Type nodes */{ mxml_node_t *variable, /* New variable */ *node, /* Current node */ *next; /* Next node */ char buffer[16384], /* String buffer */ *bufptr; /* Pointer into buffer */#ifdef DEBUG fprintf(stderr, "add_variable(parent=%p, name=\"%s\", type=%p)\n", parent, name, type);#endif /* DEBUG */ /* * Range check input... */ if (!type || !type->child) return (NULL); /* * Create the variable/argument node...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -