/* -*- LPC -*- */ /* * $Locker: $ * $Id: autodoc_html.c,v 1.14 2000/06/29 01:08:31 pinkfish Exp $ * $Log: autodoc_html.c,v $ * Revision 1.14 2000/06/29 01:08:31 pinkfish * Make it use a config define for it's address... * * Revision 1.13 2000/05/19 22:56:04 pinkfish * Fix it up to point to the right directory. * * Revision 1.12 2000/04/19 18:14:02 pinkfish * Fix up an error that was causing the code to runtime. * * Revision 1.11 1999/10/25 23:07:02 pinkfish * Fix up an output issue. * * Revision 1.10 1999/06/22 02:06:01 pinkfish * Update to use less writes when creating a file. * * Revision 1.9 1999/05/05 00:37:26 pinkfish * Fix up how the class names are output. * * Revision 1.8 1999/02/10 09:15:08 pinkfish * Fix up to use classes. * * Revision 1.7 1998/05/13 15:29:54 pinkfish * Fixed up the args printing stuff. * * Revision 1.6 1998/02/23 06:12:13 pinkfish * Put the different index types at the top of the main generated files. * * Revision 1.5 1998/02/23 05:53:41 pinkfish * Fixed up problems with the Change history stuff. * * Revision 1.4 1998/02/23 05:38:13 pinkfish * Make a standard index file... * * Revision 1.3 1998/02/23 05:30:09 pinkfish * Brinke the index up into creatro, effect and main lindexes. * Easier to find stuff... * * Revision 1.2 1998/02/22 13:00:53 pinkfish * changes to make the html a bit nicer and some biug fixing. * * Revision 1.1 1998/01/06 05:04:22 ceres * Initial revision * */ /** * This creates an html document from the generated automatic documentation. * * @see /obj/handlers/autodoc/autodoc_handler * @author Pinkfish * @started Tue Oct 28 11:39:47 EST 1997 */ #include <autodoc.h> #include <config.h> private string query_func_def(mixed *stuff, string func); private string query_methods(string *funcs, function data, int prot); private string query_method_description(mapping docs); private string create_href(string str); private string query_method_summary(string *funcs, object file); private string query_defines(string *defs, mapping docs); private string query_class_summary(mapping classes); private string query_classes(mapping classes); private string query_class_def(mixed *stuff, string name); private string query_class_description(mapping docs); void create() { seteuid(getuid()); } /* create() */ /** * Writes the data from the autodoc file object out to a file in html * format. * * @param file the autodoc file object * @param output the output file to write to * * @see /obj/handlers/autodoc/autodoc_handler */ void create_html_file(object file, string output) { int i; mapping stuff; string *pub_funcs; string *pro_funcs; string *defs; string *bits; string name; string bing; /* * Ok, we do the alphabetised list, first a short list with the * first sentance of each description, then a longer expanded list.. */ bits = explode(file->query_file_name(), "/"); name = bits[sizeof(bits)-1]; bing = "<html><head><title>"; bing += "File " + name + "\n</title></head><body bgcolor=\"#ffffff\" TEXT=\"#000030\" LINK=\"#4a529c\" VLINK=\"#b57339\">"; bing += "[ <a href=\"index.html\">Package Index</a></code> | "; bing += "<a href=\"index_std.html\">Mudlib Index</a></code> | "; bing += "<a href=\"index_eff.html\">Effect Index</a></code> ]<br>"; stuff = file->query_main_docs(); if (stuff["main"]) { bing += "<h2>File " + file->query_file_name() + "</h2>"; bing += implode(stuff["main"], " "); if (stuff["see"]) { bing += "<p><b>See also:</b><br>" + query_multiple_short( map(stuff["see"], (: create_href($1) :))); } if (stuff["author"]) { bing += "<p>Written by " + query_multiple_short(stuff["author"]); } if (stuff["started"]) { bing += "<p>Started " + query_multiple_short(stuff["started"]); } if (stuff["example"]) { if (sizeof(stuff["example"]) > 1) { for (i = 0; i < sizeof(stuff["example"]); i++) { bing += "<h3>Example " + (i + 1) + "</h3>\n"; bing += "<pre>"+stuff["example"][i]+"</pre>\n"; } } else { bing += "<h3>Example</h3>\n<pre>" + stuff["example"][0] + "</pre>\n"; } } if (stuff["changed"]) { bing += "<h3>Change history</h3>\n<dl>" + implode(map(stuff["changed"], function (string str) { string start; string rest; if (sscanf(str, "%s\n%s", start, rest) == 2) { return "<dt>" + start + "<dd>" + rest; } return "<dd>" + str; } ), "\n") + "</dl>\n"; } } if (sizeof(file->query_inherits())) { bing += "<hr><h2>Inherits</h2>\n"; bing += "This class inherits the following classes " + query_multiple_short( map(keys(file->query_inherits()), (: create_href :))); } if (sizeof(file->query_includes())) { bing += "<hr><h2>Includes</h2>\n"; bing += "This class includes the following files " + query_multiple_short( map(file->query_includes(), (: create_href :))); } if (sizeof(file->query_class_docs())) { bing += query_class_summary(file->query_class_docs()); } /* * Filter out create and setup as they are not real useful functions * to document :) */ pub_funcs = keys(file->query_public_functions()); pro_funcs = keys(file->query_protected_functions()); /* * Create a summary list of the methods at the top of the file. * with pointers to a more indepth explantion. */ bing += query_method_summary(pub_funcs + pro_funcs, file); /* * Create the more indepth explanation. */ if (sizeof(pub_funcs)) { bing += "<hr><h2>Public Functions</h2>\n"; bing += "These are functions that everyone can " "access.<p><dl>\n."; bing += query_methods(pub_funcs, (: $(file)->query_public_functions()[$1] :), 0); bing += "</dl>\n"; } if (sizeof(pro_funcs)) { bing += "<hr><h2>Protected Functions</h2>\n"; bing += "These are functions that only " "objects inheriting the class can access.<p>\n"; bing += query_methods(pro_funcs, (: $(file)->query_protected_functions()[$1] :), 1); bing += "\n"; } /* If it is an include file. Do fun stuff with defines. */ if (sscanf(name, "%*s.h") == 1 && sizeof(file->query_define_docs())) { defs = sort_array(keys(file->query_define_docs()), (: strcasecmp($1, $2) :)); bing += "<hr><h2>Defines</h2>\n"; query_defines(defs, file->query_define_docs()); bing = ""; } if (sizeof(file->query_class_docs())) { bing += "<hr><h2>Classes</h2>\n"; bing += "These are nice data types for dealing with... Data!" "<p>\n"; bing += query_classes(file->query_class_docs()); } write_file(output, bing, 1); /* Ignore private functions, because they are less than useful anyway. */ bing = "/www/footer"->www_function(output); write_file(output, bing + "</body></html>"); } /* create_html_file() */ /** * 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) { int i; string name; string bing; bing = "<html><head><title>\nIndex of " + letter + "\n</title></head><body bgcolor=\"#ffffff\" TEXT=\"#000030\" LINK=\"#4a529c\" VLINK=\"#b57339\">\n"; bing += "<img align=left src=\"" + CONFIG_EXTERNAL_WEB_ADDRESS + "pics/dw4.gif\">\n" "<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]) :) ); for (i = 0; i < sizeof(index); i++) { name = replace(index[i][AUTO_INDEX_FILE_NAME], "/", "."); if (name[0] == '.') { name = name[1..]; } if (sscanf(index[i][AUTO_INDEX_NAME], "%*s.%*s") == 2) { bing += "<dt><img src=\"images/magenta-ball-small.gif\" " "height=6 width=6 alt=\" . \"><b><a href=\"" + name + ".html\">" + index[i][AUTO_INDEX_NAME] + "</a></b>.\n"; } else { bing += "<dt><img src=\"images/magenta-ball-small.gif\" " "height=6 width=6 alt=\" . \"><b><a href=\"" + name + ".html#" + index[i][AUTO_INDEX_NAME] + "\">" + index[i][AUTO_INDEX_NAME] + "</a></b>" + index[i][AUTO_INDEX_ARGS] + "; <a href=\"" + name + ".html\">" + index[i][AUTO_INDEX_FILE_NAME] + "</a>\n"; } if (index[i][AUTO_INDEX_SUMMARY]) { bing += "<dd>"+index[i][AUTO_INDEX_SUMMARY]+"\n"; } reset_eval_cost(); } write_file(output, bing + "</dl>", 1); write_file(output, "/www/footer"->www_function(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; string output_eff; string output_cre; //string output_file; string *files; mixed *stuff; string str; string fname; string *index; mapping summaries; function write_all; string bing_file; string fluff; summaries = AUTODOC_HANDLER->query_summary_map(); output_index = output_dir + "index_std.html"; output_eff = output_dir + "index_eff.html"; output_cre = output_dir + "index_cre.html"; bing_cre = ""; bing_eff = ""; bing_file = ""; bing_index = ""; /* Rm the files so we write new ones... */ rm (output_eff); rm (output_index); rm (output_cre); write_all = (: bing_eff += $1, bing_cre += $1, bing_index += $1 :); evaluate(write_all, "<html><head><title>\n"); evaluate(write_all, "" + mud_name() + " autodoc index\n</title></head>\n" "<body bgcolor=\"#ffffff\" TEXT=\"#000030\" " "LINK=\"#4a529c\" VLINK=\"#b57339\">\n"); bing_index += "<img align=left src=\"" + CONFIG_EXTERNAL_WEB_ADDRESS + "/pics/dw4.gif\">\n" "<h2>" + mud_name() + " Documentation</h2>\n" "<h3><i>Where cabbages evaporate in the sun</i></h3>\n" "<br clear=both>\n"; bing_eff += "<img align=left src=\"" + CONFIG_EXTERNAL_WEB_ADDRESS + "/pics/dw4.gif\">\n" "<h2>" + mud_name() + " Effect Documentation</h2>\n" "<h3><i>Where your consequences are vanquished</i></h3>\n" "<br clear=both>\n"; bing_cre += "<img align=left src=\"" + CONFIG_EXTERNAL_WEB_ADDRESS + "pics/dw4.gif\">\n" "<h2>" + mud_name() + " Creator Documentation</h2>\n" "<h3><i>Blue fluff? No red and scruffy!</i></h3>\n" "<br clear=both>\n"; evaluate(write_all, "<h2>Function index</h2>\n"); files = AUTODOC_HANDLER->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)] :)); for (i = 0; i < sizeof(stuff); i++) { str = stuff[i][0][0..strsrch(stuff[i][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"); for (i = 0; i < sizeof(stuff); i++) { fluff = ""; str = stuff[i][0][0..strsrch(stuff[i][0], "/", -1)]; fluff += "<h2><a name=\"" + str + "\">" + str + "</a></h2>\n<dl>\n"; reset_eval_cost(); foreach (str in stuff[i]) { fname = replace(str, "/", ".")[1..]; fluff += "<dt><img src=\"images/cyan-ball-small.gif\" " "height=6 width=6><a href=\"" + fname + ".html\">" + str[strsrch(str, "/", -1) + 1..] + "</a>\n"; if (summaries[str]) { fluff += "<dd>" + summaries[str] + "\n"; } } fluff += "</dl>\n"; if (stuff[i][0][0..12] == "/std/effects/") { bing_eff += fluff; } else if (stuff[i][0][0..2] == "/w/") { bing_cre += fluff; } else { bing_index += fluff; } } //evaluate(write_all, "@@/footer:footer@@</body></html>\n"); write_file(output_eff, bing_eff, 1); write_file(output_eff, "/www/footer"->www_function(output_eff) + "</body></html"); write_file(output_index, bing_index, 1); write_file(output_index, "/www/footer"->www_function(output_index) + "</body></html"); write_file(output_cre, bing_cre, 1); write_file(output_cre, "/www/footer"->www_function(output_cre) + "</body></html"); } /* create_main_index() */ private string query_classes(mapping classes) { string name; string *names; string bing; names = sort_array(keys(classes), (: strcasecmp :) ); bing = "<dl>\n"; foreach (name in names) { reset_eval_cost(); bing += "<dt><a name=\"class_" + name + "\">\n"; bing += "<img src=\"images/cyan-ball.gif\" width=12 " "height=12 alt=\" * \">"; bing += "<b>" + name + "</b></a><pre>\n" + query_class_def(classes[name], name) + "\n</pre>"; if (classes[name][AUTO_CLASS_DOCS]["main"]) { bing += query_class_description(classes[name][AUTO_CLASS_DOCS]); } bing += "\n"; } return bing + "</dl>\n"; } /* query_classes() */ private string query_methods(string *funcs, function data, int prot) { int i; mixed *stuff; string bing; funcs = sort_array(funcs, (: strcasecmp($1, $2) :)); bing = ""; for (i = 0; i < sizeof(funcs); i++) { reset_eval_cost(); stuff = evaluate(data, funcs[i]); bing += "<dt><a name=\"" + funcs[i] + "\">\n"; if (prot) { bing += "<img src=\"images/magenta-ball.gif\" width=12 " "height=12 alt=\" * \">"; } else { bing += "<img src=\"images/cyan-ball.gif\" width=12 " "height=12 alt=\" * \">"; } bing += "<b>" + funcs[i] + "</b></a><pre>\n" + query_func_def(stuff, funcs[i]) + "\n</pre>"; if (stuff[AUTO_DOCS]["main"]) { bing += query_method_description(stuff[AUTO_DOCS]); } bing += "\n"; } return bing; } /* query_methods() */ private string query_func_def(mixed *stuff, string func) { string ret; int i; int 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; } /* query_func_def() */ private string query_class_def(mixed *stuff, string name) { string ret; int pad; int i; ret = "class " + name + " {\n"; pad = strlen(ret); for (i = 0; i < sizeof(stuff[AUTO_CLASS_MEMBERS]); i++) { ret += sprintf("%-" + pad + "s", ""); ret += implode(stuff[AUTO_CLASS_MEMBERS][i][AUTO_CLASS_TYPE], " ") + " " + stuff[AUTO_CLASS_MEMBERS][i][AUTO_CLASS_NAME] + ";\n"; } ret += "}\n"; return ret; } /* query_class_def() */ private string query_method_description(mapping docs) { int i; string name; string desc; string bing; 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"; for (i = 0; i < sizeof(docs["param"]); i++) { if (sscanf(docs["param"][i], "%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() */ private string query_class_description(mapping docs) { int i; string name; string desc; string bing; 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"; for (i = 0; i < sizeof(docs["member"]); i++) { if (sscanf(docs["member"][i], "%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() */ /* * This creates a reference string from the input reference... */ private string create_href(string str) { string name; string ref_name; string func; if (sscanf(str, "%s#%s", name, func) == 2) { ref_name = replace(name, "/", "."); if (ref_name[0] == '.') { ref_name = ref_name[1..]; } return "<a href=\"" + ref_name + ".c.html#" + func + "\">" + name + "->" + func + "()</a>"; } else if (sscanf(str, "%s->%s", name, func) == 2) { sscanf(func, "%s(%*s)", func); ref_name = replace(name, "/", "."); if (ref_name[0] == '.') { ref_name = ref_name[1..]; } return "<a href=\"" + ref_name + ".c.html#" + func + "\">" + str + "</a>"; } else if (sscanf(str, "%s()", func) == 1) { return "<a href=\"#" + func + "\">" + str + "</a>"; } else if (str[0..4] == "http:") { return "<a href=\"" + str + "\">" + str + "</a>"; } else { ref_name = replace(str, "/", "."); if (ref_name[0] == '.') { ref_name = ref_name[1..]; } if (sscanf(str, "%*s.%*s") != 2) { ref_name += ".c"; str += ".c"; } if (member_array(str, AUTODOC_HANDLER->query_files()) != -1) { /* Its an object reference */ return "<a href=\"" + ref_name + ".html\">" + str + "</a>"; } return str; } } /* create_href() */ private string query_short_args_def(mixed *args) { string ret; int i; ret = ""; for (i = 0; i < sizeof(args); i += 2) { if (i != 0) { ret += ", "; } ret += implode(args[i + AUTO_ARGS_TYPE], " "); } return "(" + ret + ")"; } /* query_short_args_def() */ private string query_short_desc(mapping docs) { mixed main; int pos; int tmp_pos; main = docs["main"]; if (!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() */ private string query_class_summary(mapping classes) { string *names; string name; string short_desc; string bing; names = sort_array(keys(classes), (: strcasecmp :)); bing = "<hr><h2>Class Index</h2>\n"; bing += "<dl>"; foreach (name in names) { bing += "<dt><img src=\"images/cyan-ball-small.gif\" " "height=6 width=6 alt=\" o \">\n"; bing += "<a href=\"#class_" + name + "\"><b>" + name + "</b></a>\n"; short_desc = query_short_desc(classes[name][AUTO_CLASS_DOCS]); if (short_desc) { bing += "<dd>" + short_desc + "\n"; } } bing += "</dl>"; return bing; } /* query_class_summary() */ private string query_method_summary(string *funcs, object file) { int i; mixed *stuff; string short_desc; int prot; string bing; bing = ""; if (sizeof(funcs)) { bing += "<hr><h2>Method index</h2>\n<dl>"; funcs = sort_array(funcs, (: strcasecmp :) ); for (i = 0; i < sizeof(funcs); i++) { if (file->query_public_functions()[funcs[i]]) { stuff = file->query_public_functions()[funcs[i]]; prot = 0; } else if (file->query_protected_functions()[funcs[i]]) { stuff = file->query_protected_functions()[funcs[i]]; prot = 1; } if (prot) { bing += "<dt><img src=\"images/magenta-ball-small.gif\" " "height=6 width=6 alt=\" o \">\n"; } else { bing += "<dt><img src=\"images/cyan-ball-small.gif\" " "height=6 width=6 alt=\" o \">\n"; } bing += "<a href=\"#" + funcs[i] + "\"><b>" + funcs[i] + "</b></a>" + query_short_args_def(stuff[AUTO_ARGS]) ; short_desc = query_short_desc(stuff[AUTO_DOCS]); if (short_desc) { bing += "<dd>" + short_desc + "\n"; } } bing += "</dl>"; } return bing; } /* query_method_summary() */ private string query_defines(string *defs, mapping docs) { int i; string bing; bing = ""; for (i = 0; i < sizeof(defs); i++) { bing += "<dt><a name=\"" + defs[i] + "\">\n"; bing += "<img src=\"images/red-ball.gif\" width=12 " "height=12 alt=\" * \"><b>" + defs[i] + "</b></a>\n"; if (docs[defs[i]]["main"]) { bing += query_method_description(docs[defs[i]]); } } return bing; } /* query_defines() */