--- /dev/null
+/*******************************************************************************
+ * Simplified Wrapper and Interface Generator (SWIG)
+ *
+ * Author : David Beazley
+ *
+ * Department of Computer Science
+ * University of Chicago
+ * 1100 E 58th Street
+ * Chicago, IL 60637
+ * beazley@cs.uchicago.edu
+ *
+ * Please read the file LICENSE for the copyright and terms by which SWIG
+ * can be used and distributed.
+ *******************************************************************************/
+/***********************************************************************
+ * $Header$
+ *
+ * newdoc.cxx
+ *
+ * SWIG Documentation system. (2nd attempt)
+ *
+ * SWIG organizes documentation as a tree structure where each node is a
+ * documentation entry (DocEntry) of some kind. To generate documentation,
+ * we simply traverse the tree and call output methods.
+ *
+ * A sample documentation tree looks something like the following :
+ *
+ * TITLE ----> SECTION 1 ----> func1
+ * ----> func2
+ * ----> func3
+ * ----> class ---> func1
+ * ---> func2
+ * ---> var1
+ * ----> func4
+ *
+ * ----> SECTION 2 ----> func1
+ * ----> var1
+ *
+ * and so on.
+ *
+ * This structure makes it possible to organize C++ classes and more
+ * complicated structures. Hopefully this will provide enough structure
+ * for later versions of SWIG.
+ *
+ *************************************************************************/
+
+#include "internal.h"
+#include <ctype.h>
+
+extern char *get_time();
+static char *last_name = 0;
+
+DocEntry *DocEntry::dead_entries = 0;
+
+// Utility function for converting a string to upper case
+
+static void str_toupper(char *str) {
+ char *c;
+ c = str;
+ while (*c) {
+ *c = toupper(*c);
+ c++;
+ }
+}
+
+// --------------------------------------------------------------------
+// DocEntry::~DocEntry
+//
+// Destroy a documentation entry. Destroys this entry and all of
+// its children.
+// --------------------------------------------------------------------
+
+DocEntry::~DocEntry() {
+ DocEntry *de, *de1;
+
+ if (name) delete name;
+
+ // Now kill all of the children (well, figuratively speaking)
+
+ de = child;
+ while (de) {
+ de1 = de->next;
+ delete de;
+ de = de1;
+ }
+}
+
+// --------------------------------------------------------------------
+// void DocEntry::sort_children()
+//
+// Sort children by name (not height). This function gathers all
+// of the children up into an array of pointers. Then we do an
+// insertion sort on it and place the children back in order.
+// --------------------------------------------------------------------
+
+void DocEntry::sort_children() {
+
+ int count = 0;
+ int i,j;
+ DocEntry *d;
+ DocEntry **list;
+ DocEntry *v;
+
+ if (!child) return; // Nothing to sort
+
+ d = child;
+ while (d) {
+ count++;
+ d = d->next;
+ }
+
+ // allocate a temporary array for sorting everything
+
+ list = new DocEntry *[count+2];
+
+ // Now put pointers into list
+
+ d = child;
+ i = 0;
+ while (d) {
+ list[i] = d;
+ d = d->next;
+ i++;
+ }
+
+ // Do an insertion sort by name
+
+ for (i = 1; i < count; i++) {
+ v = list[i];
+ j = i;
+ while((j > 0) && (strcmp(list[j-1]->name,v->name) > 0)) {
+ list[j] = list[j-1];
+ j--;
+ }
+ list[j] = v;
+ }
+
+ // Now, we're going to reorganize the children in order
+
+ list[count] = 0;
+ child = list[0]; // Our child is the first one in the list
+ d = child;
+ for (i = 0; i < count; i++) {
+ d->next = list[i+1];
+ d = d->next;
+ }
+ delete list;
+}
+
+// --------------------------------------------------------------------
+// void DocEntry::output()
+//
+// Output this entry
+// --------------------------------------------------------------------
+
+void DocEntry::output(Documentation *) {
+ fprintf(stderr,"SWIG (internal) : No output method defined for DocEntry.\n");
+}
+
+// --------------------------------------------------------------------
+// DocEntry::add(DocEntry *de)
+//
+// Adds a new DocEntry as a sibling. Basically we just walk down the
+// linked list and append ourselves to the end. The documentation
+// Entry we're adding may, in fact, have siblings too, but this function
+// Should still work.
+// --------------------------------------------------------------------
+
+void DocEntry::add(DocEntry *de) {
+ DocEntry *d,*d1;
+ d = next;
+ d1 = this;
+ while (d) {
+ d1 = d;
+ d = d->next;
+ }
+ d1->next = de;
+ de->previous = d1; // Set up the previous list member
+}
+
+
+// --------------------------------------------------------------------
+// DocEntry::addchild(DocEntry *de)
+//
+// Adds a new DocEntry as a child. If we're in Ignore mode, the
+// documentation entry is still created, but we simply abandon it.
+// --------------------------------------------------------------------
+
+void DocEntry::addchild(DocEntry *de) {
+ if (!IgnoreDoc) {
+ if (child) child->add(de);
+ else child = de;
+ } else {
+ if (dead_entries) dead_entries->add(de);
+ else dead_entries = de;
+ }
+}
+
+// -------------------------------------------------------------------
+// DocEntry::remove()
+//
+// Removes a documentation entry from the tree and places it on
+// the dead_entries list
+// -------------------------------------------------------------------
+
+void DocEntry::remove() {
+
+ if (previous) {
+ if (next)
+ previous->next = next; // Take out of the linked list
+ else
+ previous->next = 0;
+ } else { // Make sure our parent isn't pointing to us
+ if (parent)
+ parent->child = next;
+ }
+
+ previous = 0;
+ next = 0;
+
+ if (!dead_entries) dead_entries = this;
+ else dead_entries->add(this);
+
+}
+
+// -------------------------------------------------------------------
+// void DocEntry::style(char *name, char *value)
+//
+// Set style parameters of a documentation entry
+// -------------------------------------------------------------------
+
+void DocEntry::style(char *pname, char *) {
+ if (strcmp(pname,"sort") == 0) {
+ sorted = 1;
+ } else if (strcmp(pname,"nosort") == 0) {
+ sorted = 0;
+ } else if (strcmp(pname,"info") == 0) {
+ print_info = 1;
+ } else if (strcmp(pname,"noinfo") == 0) {
+ print_info = 0;
+ } else if (strcmp(pname,"pre") == 0) {
+ format = 0;
+ } else if (strcmp(pname,"format") == 0) {
+ format = 1;
+ }
+}
+
+// -------------------------------------------------------------------
+// void DocEntry::parse_args(int argc, char **argv)
+//
+// Take command line options and process them. This really only
+// applies to the top-level documentation entry.
+// -------------------------------------------------------------------
+
+static char *doc_usage = "\
+Documentation Processing : \n\
+ -Sformat - Reformat comment text\n\
+ -Sinfo - Print C formatting information (the default)\n\
+ -Snoinfo - Omit C formatting information.\n\
+ -Snosort - Print everything in order (the default)\n\
+ -Spre - Assume comments are pre-formatted (the default)\n\
+ -Ssort - Sort documentation alphabetically\n\n";
+
+void DocEntry::parse_args(int argc, char **argv) {
+ int i;
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i],"-Ssort") == 0) {
+ this->style("sort",0);
+ mark_arg(i);
+ } else if (strcmp(argv[i],"-Snosort") == 0) {
+ this->style("nosort",0);
+ mark_arg(i);
+ } else if (strcmp(argv[i],"-Sinfo") == 0) {
+ this->style("info",0);
+ mark_arg(i);
+ } else if (strcmp(argv[i],"-Snoinfo") == 0) {
+ this->style("noinfo",0);
+ mark_arg(i);
+ } else if (strcmp(argv[i],"-Spre") == 0) {
+ this->style("pre",0);
+ mark_arg(i);
+ } else if (strcmp(argv[i],"-Sformat") == 0) {
+ this->style("format",0);
+ mark_arg(i);
+ } else if (strcmp(argv[i],"-help") == 0) {
+ fputs(doc_usage,stderr);
+ }
+ }
+ }
+}
+
+
+// -------------------------------------------------------------------
+// DocTitle::DocTitle(char *title, DocEntry *_parent);
+//
+// Create a new title documentation entry. The name of the entry
+// is the title.
+//
+// The body text is optional, but may be filled in with a description
+// as well.
+// -------------------------------------------------------------------
+
+DocTitle::DocTitle(char *title, DocEntry *_parent) {
+ name = copy_string(title);
+ str_toupper(name);
+ parent = _parent;
+ child = 0;
+ next = 0;
+ previous = 0;
+ usage << title << "\n";
+ counter = 1;
+ is_separator = 1;
+ line_number = ::start_line;
+ end_line = ::line_number;
+ file = copy_string(input_file);
+ if (_parent) {
+ sorted = _parent->sorted;
+ format = _parent->format;
+ print_info = _parent->print_info;
+ } else {
+ sorted = SWIGDEFAULT_SORT;
+ format = SWIGDEFAULT_FORMAT;
+ print_info = SWIGDEFAULT_INFO;
+ }
+ comment_handler->set_entry(this);
+ if (last_name) delete last_name;
+ last_name = 0;
+}
+// --------------------------------------------------------------------
+// DocTitle::output(Documentation *d)
+//
+// Output a title to the Documentation module
+// --------------------------------------------------------------------
+
+void DocTitle::output(Documentation *d) {
+ DocEntry *de;
+
+ d->title(this);
+ if (sorted) {
+ sort_children();
+ }
+
+ // Now output my children
+
+ de = child;
+ while (de) {
+ de->output(d);
+ de = de->next;
+ }
+}
+
+// -------------------------------------------------------------------
+// DocSection::DocSection(char *section, DocEntry *_parent);
+//
+// Create a new documentation section. The name and description is
+// set to the name of the section. The text field is optional
+// but could contain a more complete description.
+//
+// The sorted field indicates whether members of this section are
+// sorted or not.
+// -------------------------------------------------------------------
+
+DocSection::DocSection(char *section, DocEntry *_parent) {
+ name = copy_string(section);
+ str_toupper(name);
+ parent = _parent;
+ child = 0;
+ next = 0;
+ previous = 0;
+ usage << section;
+ counter = 1;
+ is_separator = 1;
+ if (_parent) _parent->addchild(this);
+ line_number = ::start_line;
+ end_line = ::line_number;
+ file = copy_string(input_file);
+ if (_parent) {
+ sorted = _parent->sorted;
+ format = _parent->format;
+ print_info = _parent->print_info;
+ } else {
+ sorted = SWIGDEFAULT_SORT;
+ format = SWIGDEFAULT_FORMAT;
+ print_info = SWIGDEFAULT_INFO;
+ }
+ comment_handler->set_entry(this);
+ if (last_name) delete last_name;
+ last_name = 0;
+}
+
+// --------------------------------------------------------------------
+// DocSection::output(Documentation *d)
+//
+// Output a section to the documentation module
+// --------------------------------------------------------------------
+
+void DocSection::output(Documentation *d) {
+ DocEntry *de;
+
+ // Make a new section
+
+ d->newsection(this,this->parent->counter++); // Make a new section
+
+ // Sort the children if necessary
+
+ if (sorted) {
+ sort_children();
+ }
+
+ // Now output my children
+
+ de = child;
+ while (de) {
+ de->output(d);
+ de = de->next;
+ }
+
+ // End this section
+
+ d->endsection();
+
+}
+
+
+// -------------------------------------------------------------------
+// DocDecl::DocDecl(char *fname, DocEntry *_parent);
+//
+// Create documentation for a function declaration.
+// -------------------------------------------------------------------
+
+DocDecl::DocDecl(char *fname, DocEntry *_parent) {
+ name = copy_string(fname);
+ str_toupper(name);
+ parent = _parent;
+ child = 0;
+ next = 0;
+ previous = 0;
+ is_separator = 0;
+ if (_parent) _parent->addchild(this);
+ line_number = ::start_line;
+ end_line = ::line_number;
+ file = copy_string(input_file);
+ if (_parent) {
+ sorted = _parent->sorted;
+ format = _parent->format;
+ print_info = _parent->print_info;
+ } else {
+ sorted = SWIGDEFAULT_SORT;
+ format = SWIGDEFAULT_FORMAT;
+ print_info = SWIGDEFAULT_INFO;
+ }
+ comment_handler->set_entry(this);
+ if (last_name) delete last_name;
+ last_name = copy_string(name);
+}
+
+
+// --------------------------------------------------------------------
+// DocDecl::DocDecl(DocEntry *de, DocEntry *_parent)
+//
+// Make a new declaration entry, but copy attributes from someone else
+// --------------------------------------------------------------------
+
+DocDecl::DocDecl(DocEntry *de, DocEntry *_parent) {
+ name = copy_string(de->name);
+ usage = de->usage.get();
+ cinfo = de->cinfo.get();
+ text = de->text.get();
+ line_number = de->line_number;
+ end_line = de->end_line;
+ file = copy_string(de->file);
+ print_info = de->print_info;
+ format = de->format;
+ if (_parent) {
+ _parent->addchild(this);
+ }
+}
+
+// --------------------------------------------------------------------
+// DocDecl::output(Documentation *d)
+//
+// Output a function to the documentation module
+// --------------------------------------------------------------------
+
+void DocDecl::output(Documentation *d) {
+ d->print_decl(this);
+}
+
+// -------------------------------------------------------------------
+// DocClass::DocClass(char *classname, DocEntry *_parent);
+//
+// Create a new class section. Classes are created as funny sorts of
+// sections.
+//
+// The sorted field indicates whether members of this section are
+// sorted or not.
+// -------------------------------------------------------------------
+
+DocClass::DocClass(char *classname, DocEntry *_parent) {
+ name = copy_string(classname);
+ str_toupper(name);
+ parent = _parent;
+ child = 0;
+ next = 0;
+ previous = 0;
+ usage << classname<< "\n";
+ counter = 1;
+ is_separator = 1;
+ if (_parent) _parent->addchild(this);
+ line_number = ::start_line;
+ end_line = ::line_number;
+ file = copy_string(input_file);
+ if (_parent) {
+ sorted = _parent->sorted;
+ format = _parent->format;
+ print_info = _parent->print_info;
+ } else {
+ sorted = SWIGDEFAULT_SORT;
+ format = SWIGDEFAULT_FORMAT;
+ print_info = SWIGDEFAULT_INFO;
+ }
+ comment_handler->set_entry(this);
+ if (last_name) delete last_name;
+ last_name = copy_string(name);
+
+}
+
+// --------------------------------------------------------------------
+// DocClass::output(Documentation *d)
+//
+// Output a section to the documentation module
+// --------------------------------------------------------------------
+
+void DocClass::output(Documentation *d) {
+ DocEntry *de;
+
+ // Make a new section
+
+ d->newsection(this,this->parent->counter++); // Make a subsection for this
+
+ // Sort the children if necessary
+
+ if (sorted) {
+ sort_children();
+ }
+
+ // Now output my children
+
+ de = child;
+ while (de) {
+ de->output(d);
+ de = de->next;
+ }
+
+ // End this section
+
+ d->endsection();
+
+ // We now check to see if the next thing is a separator. If not, we'll
+ // emit a separator
+
+ if (next) {
+ if (!next->is_separator)
+ d->separator();
+ }
+}
+
+// -------------------------------------------------------------------
+// DocText::DocText(char *_text, DocEntry *_parent);
+//
+// Create documentation for a function declaration.
+// -------------------------------------------------------------------
+
+DocText::DocText(char *_text, DocEntry *_parent) {
+ if (!last_name)
+ name = copy_string(""); // There is no name for text
+ else
+ name = copy_string(last_name);
+ parent = _parent;
+ child = 0;
+ next = 0;
+ previous = 0;
+ text << _text;
+ is_separator = 0;
+ if (_parent) _parent->addchild(this);
+ if (_parent) {
+ sorted = _parent->sorted;
+ format = _parent->format;
+ print_info = _parent->print_info;
+ } else {
+ sorted = SWIGDEFAULT_SORT;
+ format = SWIGDEFAULT_FORMAT;
+ print_info = SWIGDEFAULT_INFO;
+ }
+}
+
+// --------------------------------------------------------------------
+// DocText::output(Documentation *d)
+//
+// Output a function to the documentation module
+// --------------------------------------------------------------------
+
+void DocText::output(Documentation *d) {
+ d->print_text(this);
+}
+