//Source browser by Wodan #include <http.h> #include <nroff.h> #include <assert.h> #include <player_handler.h> string this_file; string *simuls; string *defs; mixed *funcs; string last_file; object file_ob; int use_defs = 0; string function_tag(string file, string exp, string match, object ob); void create(){ simuls = functions((find_object("/secure/simul_efun"))); this_file = __FILE__[strsrch(__FILE__, "/", - 1) + 1..]; } string get_inc_path(string file){ string ret; while(file[0] == ' ') file = file[1..]; if(file[0] == '<'){ ret = "/include/"; file = file[1..]; } else if(file[0] == '"'){ if(file[1] == '/') ret = ""; else ret = "/" + implode(explode(last_file, "/")[0..<2], "/") + "/"; file = file[1..]; } else error(file); while(file[<1] == ' ') file = file[0..<2]; file = file[0..<2]; if(file_size(ret + file) < 0) return get_inc_path(sprintf("<%s>", file)); return ret + file; } string expand_macros(string ins){ int i, changed; int *allowed = ({' ','\t','+','-',',','(','\"','['}); do{ changed = 0; for(i=0; i<sizeof(defs); i+=2){ int off; if((off = strsrch(ins, defs[i])) != -1){ if(!off || member_array(ins[off-1], allowed) >= 0){ ins = replace_string(ins, defs[i], defs[i+1]); changed = 1; } } } } while(changed); return ins; } string strip_junk(string stuff){ stuff = replace(stuff, ({" ", "", "+", ""})); return replace_string(stuff, "\"\"", ""); } void defines(){ string *lines = ({"#include <all_inc.h>"}) + regexp(explode(read_file(last_file), "\n"), "^#[ ]*(include|define)"); string line; string infile = last_file; if(defs) lines = lines[1..]; foreach(line in lines){ int off; string tmp, tmp2; if(off = strsrch(line, "include") != -1){ string file; tmp = line[off+7..]; file = get_inc_path(tmp); last_file = file; defines(); last_file = infile; } else { int i = 0, j, nest = 0, macro = 0; off = strsrch(line, "define"); tmp = line[off+6..]; while(tmp[0] == ' ') tmp = tmp[1..]; while((tmp[++i] != ' ' || nest) && i <= (sizeof(tmp) - 1)){ if(tmp[i] == '('){ nest++; macro = 1; } else if(tmp[i] == ')') nest--; } j = i; if(j != (sizeof(tmp))){ while(tmp[++j] == ' ' && j <= (sizeof(tmp) - 1)); } tmp2 = tmp[j..]; tmp = tmp[0..i-1]; if(!macro) tmp2 = strip_junk(expand_macros(tmp2)); defs += ({tmp, tmp2}); } } } string get_function(string func){ mixed tmp; int i=0, j=0; tmp = reg_assoc(read_file(last_file), ({"\n[a-z_ \t]*[\\* ][ \t]*" + func + "[ \t]*\\([a-zA-Z0-9, _\\*\n\t]*(...)?[ \t]*\\)[ \t\n]*{" , "\n}"}) , ({1, 2})); j = member_array(1, tmp[1]) + 1; assert(j); while(tmp[0][j][i] != '\n'){ if(tmp[0][j][i] == '}') return sprintf("%s%s", tmp[0][j - 1], tmp[0][j][0..i]); i++; } return sprintf("%s%s%s", tmp[0][j - 1], tmp[0][j], tmp[0][j + 1]); } string function_tag(string file, string exp, string match, object ob){ string html, infile, func; assert(stringp(file)); assert(stringp(exp)); assert(stringp(match)); assert(objectp(ob)); func = match[0..<2]; if(member_array(func, simuls) >= 0){ file = "/secure/simul_efun"; ob = find_object(file); exp = ""; } if((infile = (function_exists(func, ob, 1) + ".c")) == file){ html = sprintf("<B><A HREF=\"%s?file=%s&funcs=%s/%s#%s\">%s</A></B>", this_file, file, exp, func, func, func); } else { html = (infile == "0.c")?func: (sprintf("<B><A HREF=\"%s?file=%s&funcs=%s#%s\">%s</A></B>", this_file, infile, func, func, func)); } return sprintf("%s(", html); } string inherited_function_tag(string file, string match, object ob){ string html, infile, func, filep; assert(stringp(file)); assert(stringp(match)); assert(objectp(ob)); sscanf(match[0..<2], "%s::%s", filep, func); if(sizeof(filep)) filep +=".c"; foreach(file in inherit_list(ob)){ string tmp = function_exists(func, (ob = load_object(file)), 1); if(tmp && file[<sizeof(filep)..] == filep) break; } infile = (function_exists(func, ob, 1) + ".c"); html = (infile == "0.c")?match[0..<2]: (sprintf("<B><A HREF=\"%s?file=%s&funcs=%s#%s\">%s</A></B>", this_file, infile, func, func, match[0..<2])); return sprintf("%s(", html); } string parse_function(string funct, string *expand){ string ret; int i; mixed *tmp; if(!sizeof(defs)){ defs = ({}); if(use_defs) defines(); } ret = funct; if(use_defs) while(ret != (funct = expand_macros(funct))) ret = funct; tmp = reg_assoc(funct, ({"[a-zA-Z_0-9][a-zA-Z_0-9]*\\(", "[a-z_]*::[a-zA-Z_0-9][a-zA-Z_0-9]*\\("}), ({(:function_tag($(last_file), $(implode(expand, "/")), $1, $(file_ob)):), (:inherited_function_tag($(last_file), $1, $(file_ob)):)}), (:HTTPD->escape_html($1):)); ret = ""; for(i = 0; i < sizeof(tmp[1]); i++){ ret += evaluate(tmp[1][i], tmp[0][i]); } return ret; } string make_func(string *expand, int can_read, string done, mixed *func){ string tmp; reset_eval_cost(); done += "<a name=\"" + func[0] + "\"><a>"; if(member_array(func[0], expand) == -1){ string proto = func[2] + func[0]; return done + sprintf("<B><A HREF=\"%s?file=%s&funcs=%s/%s#%s\"" ">%s(%s);</A></B><br>", this_file, last_file, implode(expand, "/"), func[0], func[0], proto, implode(func[3..], ",")); } if(tmp = "/obj/handlers/autodoc/autodoc_handler"->query_help_on(last_file, func[0])){ string help; if (tmp[<3..] == ".o") { help = NROFF_HAND->html_file(tmp); } else { help = read_file(tmp, 0, 2); if (help[0] == '.') { NROFF_HAND->create_nroff(tmp, "/tmp/00000bing"); help = NROFF_HAND->html_file("/tmp/00000bing", tmp); rm("/tmp/00000bing"); } } done += help; } if(can_read) return done + sprintf("<pre>%s</pre><br>", parse_function(get_function(func[0]), expand)); return done + sprintf("<br>Can't read function: %s, no read permission to: %s<br>", func[0], last_file); } string *inherits_list(string ob){ mixed *tmp; tmp = objects((:!clonep($1) && inherits($(ob), $1) && (member_array($(ob), inherit_list($1)) != -1):)); tmp = map(tmp, (:file_name($1) + ".c":)); tmp = filter(tmp, (: $1[0..1] != "/w" :)); if(sizeof(tmp) > 10){ tmp = sort_array(tmp, (: reset_eval_cost(), $1[0..1] == "/d"? 1 : -1 :)); return tmp[0..9]; } return tmp; } string make_inherit_list(string done, string file){ return sprintf("%s<B><A HREF=\"%s?file=%s\">%s</A></B><br> ", done, this_file, file, file); } mixed *filter_funcs(mixed *ret, mixed *item){ mixed *present = map(ret, (:$1[0]:)); if(member_array(item[0], present) == -1) return ret + ({item}); return ret; } string www_request(string, mapping args, class http_request req){ string *expand; string ret; if(!args["funcs"]) args["funcs"] = ""; expand = explode(args["funcs"], "/"); use_defs = args["defs"]?1:0; if(sizeof(args["file"])>2){ if(args["file"][<2..] != ".c") args["file"] += ".c"; if(file_size(args["file"]) > 0){ catch{ int can_read; if(last_file != args["file"] || !file_ob){ last_file = args["file"]; file_ob = 0; file_ob = load_object(args["file"]); funcs = 0; defs = 0; } if(!req->user) { ret = "Try help coffee_table"; throw("no user"); } if(!PLAYER_HANDLER->test_creator(req->user)){ ret = "You are not a creator!"; throw("not a cre"); } can_read = unguarded((: master()->valid_read($(last_file), $(req->user), "cat"):)); if(!funcs){ funcs = filter(functions(file_ob, 1), (:(function_exists($1[0], $(file_ob), 1) + ".c") == $(last_file):)); funcs = implode(funcs, (:filter_funcs:), ({})); funcs = sort_array(funcs, 1); } if(args["funcs"] == "all") expand = map(funcs, (:$1[0]:)); ret = sprintf(@END <html> <head> <title> Browsing %s</title> </head> <body bgcolor="#ffffff" TEXT="#000030" LINK="#4a529c" VLINK="#b57339"> <font face="arial,helvetica"> <IMG ALIGN=LEFT SRC="/pics/dw3.gif"><h2>Source Browser</h2><h3><i>Froginess for all.</I></h3><BR clear=left><HR> <h3>File: %s</h3> <dl> <dt><strong>Inherits:</strong> <dd>%s<BR> <dt><strong>Inherited by:</strong> <dd>%s<BR> <dt><strong>Functions:</strong><b><a href="%s?file=%s">Fold all</a></b> <b><a href="%s?file=%s&funcs=all">Expand all</a></b> <b><a href="%s?file=%s&funcs=%s&defs=1">Expand defines</a></b><BR><BR> END , last_file, last_file , implode(inherit_list(file_ob), (:make_inherit_list:), "<br>") , implode(inherits_list(last_file), (:make_inherit_list:), "<br>") , this_file, last_file, this_file, last_file, this_file, last_file , args["funcs"]) + unguarded((: implode($(funcs), (:make_func, $(expand), $(can_read):), ""):)) + "<BR>" + sprintf(@END </dl> <hr><form action="%s" METHOD=GET> <b>File:</b> <input type="text" name="file" size=62><p> <p> <input type="submit" value="Get file"> <input type="reset" value="Reset"> </form> <hr> %s<br> <i><a href="mailto:wodan.discworld@wodan.net">wodan.discworld@wodan.net</font></a></i><br> </body> </html> END , this_file , "/www/footer"->www_function("footer", ([ ]), req, 0, 1)); }; } } if(ret) return ret; return sprintf("No such (loadable) file, or no file selected." "<hr><form action=\"%s\" METHOD=GET>" "<b>File:</b> <input type=\"text\" name=\"file\" size=62><p>" "<p>" "<input type=\"submit\" value=\"Get file\">" "<input type=\"reset\" value=\"Reset\">" "</form><br><b><a HREF=\"file_browser.c?" "action=/secure/%s,check_file," "%s,file\">Browse</a>", allocate(3, this_file) ...); } int check_file(string file){ if(sizeof(file) < 3) return 0; return file[<2..] == ".c"; }