/**
* This creates an html document from the generated automatic documentation.
* @see /handlers/autodoc/autodoc_handler
* @author Pinkfish
* @started Tue Oct 28 11:39:47 EST 1997
* @change Sandoz 27 Apr 2002 - Changed to generate html code on the
* fly from autodoc save files, so we won't have a separate html file
* for each file.
*/
#include <autodoc.h>
#include <runtime_config.h>
#define SMALL_IMAGE "http://divided-sky.com:7303/images/divided_sky_small.jpg"
#define LARGE_IMAGE "http://divided-sky.com:7303/images/divided_sky.jpg"
#define COLOURS "bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" "\
"vlink=\"#0033CC\" alink=\"#0033CC\""
#define RED_BALL "<img src=\"images/red-ball.gif\" width=\"12\" " \
"height=\"12\" border=\"0\">"
mapping public_functions,
protected_functions,
inherits,
main_docs,
define_docs,
includes,
class_docs;
string file_name;
/** @ignore yes */
private void setup() {
main_docs = 0;
file_name = "";
public_functions = ([ ]);
protected_functions = ([ ]);
inherits = ([ ]);
define_docs = ([ ]);
includes = ([ ]);
class_docs = ([ ]);
} /* setup() */
/** @ignore yes */
void create() {
seteuid(getuid());
setup();
} /* create() */
/**
* Creates a html index file from the input index information.
* This will contain all the functions starting with a certain letter
* and the corresponding files they are mentioned in.
*
* @param index the values in the index
* @param letter the letter this is an index of
* @param output the file to write the output to
*/
void create_html_index_file( string *index, string letter, string output ) {
string name, bing;
mixed tmp;
bing = "<html><head><title>\nIndex of " + letter +
"\n</title></head><body " + COLOURS + ">\n";
bing += "<img align=left src=\"" + SMALL_IMAGE + "\">\n";
bing += "<p align=right><code><a href=\"index.html\">"
"Main Index</a></code></p>\n"
"<h2>Index of " + letter + "</h2>\n"
"<h3><i>Letters can change the world, remove the l "
"from world and you have word</i></h3>\n"
"<br clear=both>\n"
"<hr><dl>\n";
index = sort_array(index, (: strcasecmp($1[0], $2[0]) ?
strcasecmp($1[0], $2[0]) :
strcasecmp($1[1], $2[1]) :) );
rm( output );
foreach( tmp in index ) {
name = tmp[AUTO_INDEX_FILE_NAME];
if( sscanf( tmp[AUTO_INDEX_NAME], "%*s.%*s") == 2 ) {
bing += "<dt><img src=\"images/magenta-ball-small.gif\" "
"height=6 width=6 alt=\" . \"><b><a href=\""
"../../secure/autodoc.c?file="+name+"\">"+
tmp[AUTO_INDEX_NAME]+"</a></b>.\n";
} else {
bing += "<dt><img src=\"images/magenta-ball-small.gif\" "
"height=6 width=6 alt=\" . \"><b><a href=\""+
"../../secure/autodoc.c?file="+
name+"#"+tmp[AUTO_INDEX_NAME]+"\">"+
tmp[AUTO_INDEX_NAME]+"</a></b>"+
tmp[AUTO_INDEX_ARGS]+"; <a href=\""+
name+"\">"+tmp[AUTO_INDEX_FILE_NAME]+"</a>\n";
}
if( tmp[AUTO_INDEX_SUMMARY] )
bing += "<dd>"+tmp[AUTO_INDEX_SUMMARY]+"\n";
// Safety measure, this string can get VERY long, and crash us.
if( strlen(bing) > 75 * get_config( __MAX_STRING_LENGTH__ ) / 100 ) {
write_file( output, bing );
bing = "";
}
}
write_file( output, bing + "</dl>" );
write_file( output, "</body></html>");
} /* create_html_index_file() */
// Move these out to let us use function pointers on them.
private string bing_cre;
private string bing_eff;
private string bing_index;
/**
* Creates the basic index file which points to all the other index
* files... The input letters array is a paired array, the first element
* is the letter and the second is the file name.
*
* @param letters the names of all the other index files
* @param output_dir the directory to write stuff to
*/
void create_main_index( mapping chars, string output_dir ) {
int i;
string output_index, output_eff, output_cre, output_main;
string str, fname, fluff, bing_main;
string *files, *index, *tmp;
mixed stuff;
mapping summaries;
function write_all;
summaries = AUTODOC_H->query_summary_map();
output_index = output_dir + "index_std.html";
output_eff = output_dir + "index_eff.html";
output_cre = output_dir + "index_cre.html";
output_main = output_dir + "index.html";
bing_cre = "";
bing_eff = "";
bing_index = "";
bing_main = "";
/* Rm the files so we write new ones... */
rm( output_eff );
rm( output_index );
rm( output_cre );
rm( output_main );
bing_main += "<html><head><title>"+mud_name()+" Autodoc Index</title></head>\n"
"<body " + COLOURS + ">\n";
bing_main += "<img align=\"middle\" src=\"" + LARGE_IMAGE + "\">\n";
bing_main += "<h2>"+mud_name()+" Autodoc Index</h2>\n"
"<h3><i>Where even death is nervous</i></h3>\n"
"<br clear=both>\n";
bing_main += "<h2>Function Index</h2>\n";
bing_main += "<p>";
files = sort_array( keys(chars), 1 );
for( i = 0; i < sizeof(files); i++ ) {
if( i > 0 )
bing_main += ", ";
bing_main += "<a href=\""+chars[files[i]]+"\">"+files[i]+"</a>\n";
}
bing_main += "</p>\n";
bing_main += "<h2>Packages</h2>\n";
bing_main += "<dl>\n";
bing_main += "<dt>"+RED_BALL+"\n"
"<a href=\"index_std.html\">Standard Mudlib Documentation</a>\n";
bing_main += "<dt>"+RED_BALL+"\n"
"<a href=\"index_eff.html\">Effect Documentation</a>\n";
bing_main += "<dt>"+RED_BALL+"\n"
"<a href=\"index_cre.html\">Creator Created Documentation</a>\n";
bing_main += "</dl></body></html>";
write_file( output_main, bing_main, 1 );
write_all = (: bing_eff += $1,
bing_cre += $1,
bing_index += $1 :);
evaluate( write_all, "<html><head><title>\n");
evaluate( write_all, "Autodoc index\n</title></head>\n"
"<body " + COLOURS + ">\n");
bing_index += "<img align=left src=\"" + SMALL_IMAGE + "\">\n";
bing_index += "<h2>Creator Documentation</h2>\n"
"<h3><i>Where death looks over his shoulder</i></h3>\n"
"<br clear=both>\n";
bing_eff += "<img align=left src=\"" + SMALL_IMAGE + "\">\n";
bing_eff += "<h2>Creator Effect Documentation</h2>\n"
"<h3><i>Where your consequences are vanquished</i></h3>\n"
"<br clear=both>\n";
bing_cre += "<img align=left src=\"" + SMALL_IMAGE+"\">\n";
bing_cre += "<h2>Creator Documentation</h2>\n"
"<h3><i>Code, create and well...code some more</i></h3>\n"
"<br clear=both>\n";
evaluate( write_all, "<h2>Function index</h2>\n");
files = AUTODOC_H->query_files();
files = sort_array( files, (: strcasecmp :) );
index = sort_array( keys(chars), (: strcasecmp :) );
for( i = 0; i < sizeof(index); i++ ) {
if( i > 0 )
evaluate( write_all, ", ");
evaluate( write_all, "<a href=\""+chars[index[i]]+"\">"+
index[i]+"</a>\n");
}
/* Main index */
bing_index += ", <a href=\"index_eff.html\">Effects</a>";
bing_index += ", <a href=\"index_cre.html\">Creator</a>";
/* Effect index */
bing_eff += ", <a href=\"index.html\">Main</a>";
bing_eff += ", <a href=\"index_cre.html\">Creator</a>";
/* Creator index */
bing_cre += ", <a href=\"index.html\">Main</a>";
bing_cre += ", <a href=\"index_eff.html\">Effects</a>";
evaluate( write_all, "<hr><h2>Class index</h2>\n");
evaluate( write_all, "<dl>\n");
stuff = unique_array( files, (: $1[0..strsrch( $1, "/", -1 )] :) );
foreach( tmp in stuff ) {
str = tmp[0][0..strsrch(tmp[0], "/", -1 )];
if( str[0..12] == "/std/effects/" ) {
bing_eff += "<dt><img src=\"images/cyan-ball.gif\" height=12 "
"width=12><b><a href=\"#"+str+"\">"+str+"</a></b>\n";
} else if( str[0..2] == "/w/" ) {
bing_cre += "<dt><img src=\"images/cyan-ball.gif\" height=12 "
"width=12><b><a href=\"#"+str+"\">"+str+"</a></b>\n";
} else {
bing_index += "<dt><img src=\"images/cyan-ball.gif\" height=12 "
"width=12><b><a href=\"#"+str+"\">"+str+"</a></b>\n";
}
}
evaluate( write_all, "</dl>\n");
foreach( tmp in stuff ) {
fluff = "";
str = tmp[0][0..strsrch(tmp[0], "/", -1 )];
fluff += "<h2><a name=\""+str+"\">"+str+"</a></h2>\n<dl>\n";
reset_eval_cost();
foreach( fname in tmp ) {
fluff += "<dt><img src=\"images/cyan-ball-small.gif\" height=6 "
"width=6><a href=\"../../secure/autodoc.c?file="+fname+"\">"+
fname[strsrch( fname, "/", -1 )+1..]+"</a>\n";
if( summaries[fname] )
fluff += "<dd>"+summaries[fname]+"\n";
}
fluff += "</dl>\n";
if( tmp[0][0..12] == "/std/effects/")
bing_eff += fluff;
else if( tmp[0][0..2] == "/w/")
bing_cre += fluff;
else
bing_index += fluff;
}
evaluate( write_all, "</body></html>\n");
write_file( output_eff, bing_eff, 1 );
write_file( output_eff, "</body></html>\n");
write_file( output_index, bing_index, 1 );
write_file( output_index, "</body></html>\n");
write_file( output_cre, bing_cre, 1 );
write_file( output_cre, "</body></html>\n");
} /* create_main_index() */
/*
* This method creates a reference string from the input reference.
* @param str the string to create a reference for
* @return the reference string
*/
private string create_href( string str ) {
string name, func;
if( sscanf( str, "%s#%s", name, func ) == 2 )
return "<a href=\"autodoc.c?file="+name+"#"+func+"\">"+name+"->"+
func+"()</a>";
if( sscanf( str, "%s->%s", name, func ) == 2 ) {
sscanf( func, "%s(%*s)", func );
return "<a href=\"autodoc.c?file="+name+"#"+func+"\">"+str+"</a>";
}
if( sscanf( str, "%s()", func ) == 1 )
return "<a href=\"#"+func+"\">"+str+"</a>";
if( str[0..4] == "http:" )
return "<a href=\""+str+"\">"+str+"</a>";
if( AUTODOC_H->is_autodoc_file( str ) )
return "<a href=\"autodoc.c?file="+str+"\">"+str+"</a>";
return str;
} /* create_href() */
/** @ignore yes */
private string query_func_def( mixed stuff, string func ) {
string ret;
int i, pad;
ret = implode( stuff[AUTO_TYPE], " ") + " " + func+"(";
pad = strlen(ret);
for( i = 0; i < sizeof(stuff[AUTO_ARGS]); i += 2 ) {
if( i )
ret += sprintf(",\n%-"+pad+"s", "");
ret += implode(stuff[AUTO_ARGS][i + AUTO_ARGS_TYPE], " ") + " " +
stuff[AUTO_ARGS][i + AUTO_ARGS_NAME];
}
return ret + ")";
} /* query_func_def() */
/** @ignore yes */
private string query_method_description( mapping docs ) {
string name, desc, bing, tmp;
bing = "";
if( docs["main"] )
bing += "<dd>"+implode( docs["main"], " ")+"<p>\n";
if( docs["param"] || docs["return"] || docs["see"] || docs["example"] )
bing += "<dd><dl>\n";
if( docs["param"] ) {
bing += "<dt><b>Parameters:</b>\n";
foreach( tmp in docs["param"] ) {
if( sscanf( tmp, "%s %s", name, desc ) == 2 )
bing += "<dd>"+name+" - "+(desc)+"\n";
}
}
if( docs["return"] )
bing += "<dt><b>Returns:</b>\n<dd>"+implode(docs["return"], " ")+"\n";
if( docs["see"] )
bing += "<dt><b>See also:</b>\n<dd>"+query_multiple_short(
map(docs["see"], (: create_href($1) :) ) );
if( docs["example"] )
bing += "<dt><b>Example:</b>\n<dd><pre>"+implode( docs["example"],
"</pre><dd><pre>\n")+"</pre>";
if( docs["param"] || docs["return"] || docs["see"] || docs["example"] )
bing += "</dl>\n";
return bing;
} /* query_method_description() */
/** @ignore yes */
private string query_methods( int prot ) {
mixed stuff;
string bing, *funcs, func;
function f;
funcs = keys( prot ? protected_functions : public_functions );
funcs = sort_array( funcs, (: strcasecmp( $1, $2 ) :) );
f = function( mixed stuff, string func ) {
string ret;
int i, pad;
ret = implode( stuff[AUTO_TYPE], " ")+" "+func+"(";
pad = strlen(ret);
for( i = 0; i < sizeof(stuff[AUTO_ARGS]); i += 2 ) {
if( i )
ret += sprintf(",\n%-"+pad+"s", "");
ret += implode( stuff[AUTO_ARGS][i + AUTO_ARGS_TYPE], " ")+
" "+stuff[AUTO_ARGS][i + AUTO_ARGS_NAME];
}
ret += ")";
return ret;
};
bing = "";
foreach( func in funcs ) {
stuff = ( prot ? protected_functions : public_functions )[func];
bing += "<dt><a name=\""+func+"\">\n";
bing += "<dt><img src=\"autodoc/images/"+( prot ? "magenta" : "cyan")+
"-ball.gif\" height=12 width=12 alt=\" * \">";
bing += "<b>"+func+"</b></a><pre>\n"+evaluate( f, stuff, func )+
"\n</pre>";
if( stuff[AUTO_DOCS]["main"] )
bing += query_method_description( stuff[AUTO_DOCS] );
bing += "\n";
}
return bing;
} /* query_methods() */
/** @ignore yes */
private string query_class_def( mixed stuff, string name ) {
string ret;
int pad;
mixed member;
ret = "class "+name+" {\n";
pad = strlen(ret);
foreach( member in stuff[AUTO_CLASS_MEMBERS] ) {
ret += sprintf("%-"+pad+"s", "");
ret += implode( member[AUTO_CLASS_TYPE], " ")+" "+
member[AUTO_CLASS_NAME]+";\n";
}
return ret+"}\n";
} /* query_class_def() */
/** @ignore yes */
private string query_class_description( mapping docs ) {
string name, desc, bing, tmp;
bing = "";
if( docs["main"] )
bing += "<dd>"+implode( docs["main"], " ")+"<p>\n";
if( docs["member"] || docs["see"] )
bing += "<dl>\n";
if( docs["member"] ) {
bing += "<dt><b>Members:</b>\n";
foreach( tmp in docs["member"] ) {
if( sscanf( tmp, "%s %s", name, desc ) == 2 )
bing += "<dd>"+name+" - "+(desc)+"\n";
}
}
if( docs["see"] )
bing += "<dt><b>See also:</b>\n<dd>"+query_multiple_short(
map(docs["see"], (: create_href($1) :) ) );
if( docs["member"] || docs["see"] )
bing += "</dl>\n";
return bing;
} /* query_class_description() */
/** @ignore yes */
private string query_short_desc( mapping docs ) {
mixed main;
int pos, tmp_pos;
if( !main = docs["main"] )
return 0;
/* Look for the first sentance... */
main = implode( main, " ");
pos = strlen(main);
tmp_pos = strsrch( main, ".");
if( tmp_pos < pos && tmp_pos != -1 )
pos = tmp_pos;
tmp_pos = strsrch( main, "?");
if( tmp_pos < pos && tmp_pos != -1 )
pos = tmp_pos;
tmp_pos = strsrch( main, "!");
if( tmp_pos < pos && tmp_pos != -1 )
pos = tmp_pos;
return main[0..pos];
} /* query_short_desc() */
/** @ignore yes */
private string query_short_args_def( mixed args ) {
string ret;
int i;
ret = "";
for( i = 0; i < sizeof(args); i += 2 ) {
if( i )
ret += ", ";
ret += implode( args[i + AUTO_ARGS_TYPE], " ");
}
return "(" + ret + ")";
} /* query_short_args_def() */
/**
* This method returns the html code for the autodoc page
* for the specified file.
* @param file the file to process
* @see /handlers/autodoc/autodoc_handler
*/
string create_html_docs( string file ) {
int i;
string *bits;
string name, ret, tmp;
file_name = file;
name = AUTODOC_SAVE_DIR + replace_string( file_name, "/", ".");
if( name[<2..] == ".c" )
name = name[0..<3];
if( !unguarded( (: file_exists( $(name)+".o" ) :) ) )
return "Sorry, there is no documentation available for "+file+".";
unguarded( (: restore_object( $(name) ) :) );
if( !main_docs )
main_docs = ([ ]);
if( !public_functions )
public_functions = ([ ]);
if( !protected_functions )
protected_functions = ([ ]);
if( !inherits )
inherits = ([ ]);
if( !define_docs )
define_docs = ([ ]);
if( !includes )
includes = ([ ]);
if( !class_docs )
class_docs = ([ ]);
/*
* Ok, we do the alphabetised list, first a short list with the
* first sentence of each description, then a longer expanded list..
*/
bits = explode( file_name, "/" );
name = bits[sizeof(bits)-1];
ret = "<html><head><title>File "+name+"</title></head><body "+COLOURS+">";
ret += "[ <a href=\"autodoc/index.html\">Package Index</a></code> | ";
ret += "<a href=\"autodoc/index_std.html\">Mudlib Index</a></code> | ";
ret += "<a href=\"autodoc/index_eff.html\">Effect Index</a></code> ]<br>";
if( main_docs["main"]) {
ret += "<h2>File "+file_name+"</h2>"+implode( main_docs["main"], " ");
if( main_docs["see"] )
ret += "<p><b>See also:</b><br>"+query_multiple_short( map(
main_docs["see"], (: create_href($1) :) ) );
if( main_docs["author"] )
ret += "<p>Written by "+query_multiple_short(main_docs["author"]);
if( main_docs["started"] )
ret += "<p>Started "+query_multiple_short(main_docs["started"]);
if( main_docs["example"] ) {
if( sizeof( main_docs["example"] ) > 1 ) {
for( i = 0; i < sizeof( main_docs["example"] ); i++ ) {
ret += "<h3>Example "+( i + 1 )+"</h3>\n";
ret += "<pre>"+main_docs["example"][i]+"</pre>\n";
}
} else {
ret += "<h3>Example</h3>\n<pre>"+main_docs["example"][0]+
"</pre>\n";
}
}
if( main_docs["changed"] ) {
ret += "<h3>Change history</h3>\n<dl>"+implode( map(
main_docs["changed"], function( string str ) {
string start, rest;
if( sscanf( str, "%s\n%s", start, rest ) == 2 )
return "<dt>"+start+"<dd>"+rest;
return "<dd>"+str;
} ), "\n")+"</dl>\n";
}
}
if( sizeof( inherits ) ) {
ret += "<hr><h2>Inherits</h2>\n";
ret += "This class inherits the following classes "+
query_multiple_short( map( keys( inherits ),
(: create_href($1) :) ) );
}
if( sizeof( includes ) ) {
ret += "<hr><h2>Includes</h2>\n";
ret += "This class includes the following files "+
query_multiple_short( map( keys( includes ),
(: create_href($1) :) ) );
}
if( sizeof( class_docs ) ) {
string short_desc;
bits = sort_array( keys(class_docs), (: strcasecmp :) );
ret += "<hr><h2>Class Index</h2>\n<dl>";
foreach( tmp in bits ) {
ret += "<dt><img src=\"autodoc/images/cyan-ball-small.gif\" "
"height=6 width=6 alt=\" o \">\n";
ret += "<a href=\"#class_"+tmp+"\"><b>"+tmp+"</b></a>\n";
short_desc = query_short_desc( class_docs[tmp][AUTO_CLASS_DOCS] );
if( short_desc )
ret += "<dd>" + short_desc + "\n";
}
ret += "</dl>";
}
/*
* Create a summary list of the methods at the top of the file.
* with pointers to a more indepth explantion.
*/
if( sizeof( bits = keys( public_functions + protected_functions ) ) ) {
string short_desc;
ret += "<hr><h2>Method index</h2>\n<dl>";
bits = sort_array( bits, (: strcasecmp :) );
foreach( tmp in bits ) {
if( public_functions[tmp] )
i = 0;
else if( protected_functions[tmp] )
i = 1;
ret += "<dt><img src=\"autodoc/images/"+( i ? "magenta" : "cyan")+
"-ball-small.gif\" height=6 width=6 alt=\" o \">\n";
ret += "<a href=\"#"+tmp+"\"><b>"+tmp+"</b></a>"+
query_short_args_def( ( i ? protected_functions :
public_functions )[tmp][AUTO_ARGS] );
short_desc = query_short_desc( ( i ? protected_functions :
public_functions )[tmp][AUTO_DOCS] );
if( short_desc )
ret += "<dd>"+short_desc+"\n";
}
ret += "</dl>";
}
/*
* Create the more indepth explanation.
*/
if( sizeof( public_functions ) ) {
ret += "<hr><h2>Public Functions</h2>\n";
ret += "These are functions that everyone can access.<p><dl>\n.";
ret += query_methods( 0 )+"</dl>\n";
}
if( sizeof( protected_functions ) ) {
ret += "<hr><h2>Protected Functions</h2>\n";
ret += "These are functions that only objects inheriting the "
"class can access.<p>\n";
ret += query_methods( 1 )+"\n";
}
/* If it is an include file. Do fun stuff with defines. */
if( sscanf( name, "%*s.h") == 1 && sizeof( define_docs ) ) {
bits = sort_array( keys(define_docs), (: strcasecmp( $1, $2 ) :) );
ret += "<hr><h2>Defines</h2>\n";
foreach( tmp in bits ) {
ret += "<dt><a name=\""+tmp+"\">\n";
ret += "<img src=\"autodoc/images/red-ball.gif\" width=12 height=12 "
"alt=\" * \"><b>"+tmp+"</b></a>\n";
if( define_docs[tmp]["main"] )
ret += query_method_description( define_docs[tmp] );
}
}
if( sizeof( class_docs ) ) {
ret += "<hr><h2>Classes</h2>\n";
ret += "These are nice data types for dealing with... Data!<p>\n";
bits = sort_array( keys(class_docs), (: strcasecmp :) );
ret += "<dl>\n";
foreach( tmp in bits ) {
ret += "<dt><a name=\"class_"+tmp+"\">\n";
ret += "<img src=\"autodoc/images/cyan-ball.gif\" width=12 height=12 "
"alt=\" * \"><b>"+tmp+"</b></a><pre>\n"+
query_class_def( class_docs[tmp], tmp )+"\n</pre>";
if( class_docs[tmp][AUTO_CLASS_DOCS]["main"] )
ret += query_class_description( class_docs[tmp][AUTO_CLASS_DOCS] );
ret += "\n";
}
ret += "</dl>\n";
}
setup();
return ret + "</body></html>";
} /* create_html_docs() */