wxWidgets/wxPython/wxSWIG/SWIG/newdoc.cxx
Robin Dunn c90f71dd8c Since I have made several changes to SWIG over the years to accomodate
special cases and other things in wxPython, and since I plan on making
several more, I've decided to put the SWIG sources in wxPython's CVS
instead of relying on maintaining patches.  This effectivly becomes a
fork of an obsolete version of SWIG, :-( but since SWIG 1.3 still
doesn't have some things I rely on in 1.1, not to mention that my
custom patches would all have to be redone, I felt that this is the
easier road to take.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15307 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2002-04-29 19:56:57 +00:00

608 lines
16 KiB
C++

/*******************************************************************************
* 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);
}