// -*- Pike -*- // $Id: manpages,v 1.26 2000/02/29 20:35:12 neotron Exp $ #include "types.h" #if __VERSION__ >= 0.6 import "."; #endif /* __VERSION__ >= 0.6 */ inherit Stdio.File : out; int verbose = 0; string globalbase; object windex; object whatis; // Conversion table: // // "*" "\\(**" // "\\" "\\e" // "()" "(\\|)" // " - " " \\- " // "..." "\\&.\\|.\\|." // ".." "\\&.\\|" string quote_text(string s) { s=replace(s,({">","&","<"}), ({">","&","<"})); return(replace(s, ({ "*", "\\", "()", " - ", "...", ".." }), ({ "\\(**", "\\e", "(\\|)", " \\- ", "\\&.\\|.\\|.", "\\&.\\|." }))); } // Some versions of nroff don't like 8-bit chars at all. string strip_eightbit(string s) { return(s & String.strmult("\177", sizeof(s))); } string strip_empty_lines(string s) { return(Array.filter(s/"\n", lambda(string line) { return(replace(line, ({ "\t", " " }), ({ "", "" })) != ""); })*"\n"); } void make_page(string base, TAG tag, string ind, string fbase); void mkdirhier(string what) { string d="."; foreach (what/"/",string add) { d+="/"+add; mkdir(d); } } int stripws=1; string make_manpage(string base, string|SGML data, string ind, string fbase) { string res=""; if (verbose) { werror(sprintf("data:%O, stripws:%d\n", data, stripws)); } if (stringp(data)) { if (sizeof(data)) { if (stripws) { string d2 = data; sscanf(data,"%*[ \t\n\r]%s",data); if (stripws == -1) { stripws = 1; if (d2[0] == ' ') { // Keep a single whitespace. data = " " + data; } } } res+=quote_text(data); } } else if(arrayp(data)) { int n; for (n = 0; n < sizeof(data); n++) { TAG tag = data[n]; if (stripws && n) { // Keep a single whitespace between tags. stripws = -1; } if (objectp(tag)) { if (verbose) { werror(sprintf("tag:%O, params:%O\n", tag->tag, tag->params)); } switch (tag->tag) { case "method": case "function": case "constant": case "class": case "module": case "variable": make_page(base,tag,ind,fbase); continue; case "man_title": res+="\n.SH "+quote_text(tag->params->title)+"\n"; stripws=1; break; case "aarg": stripws = 1; res += "\n.br\n\\fB"+make_manpage(base,tag->data,ind,fbase)+"\\fR"; continue; case "adesc": stripws = 1; res += "\n.br\n.in +.8i .ll -.8i\n"+make_manpage(base,tag->data,ind,fbase) +"\n.in -.8i .ll +.8i\n"; continue; case "p": res+="\n.PP\n"; stripws=1; break; case "br": case "ex_br": res+="\n.br\n"; if (tag->params->keep_ws) { stripws = 0; } else { stripws=1; } break; case "ex_indent": res += " "; continue; case "link": case "i": case "emboss": // case "ex_identifier": res+="\\f2"+make_manpage(base,tag->data,ind,fbase)+"\\f1"; continue; case "b": case "strong": case "ex_keyword": res+="\\f3"+make_manpage(base,tag->data,ind,fbase)+"\\f1"; continue; case "tt": int ows = stripws; stripws = 0; // Should specify a fixed width font. res += make_manpage(base,tag->data,ind,fbase); stripws = ows; continue; case "pre": case "example": int ows = stripws; stripws=0; // Ought to specify a fixed width font. res+="\n.nf\n"+ make_manpage(base,tag->data,ind,fbase)+ "\n.fi\n"; stripws = ows; continue; } res+=make_manpage(base,tag->data,ind,fbase); } else if (stringp(tag)) { if (sizeof(tag)) { if (stripws) { string t2 = tag; sscanf(tag,"%*[ \t\n\r]%s",tag); if (stripws == -1) { stripws = 1; if (t2[0] == ' ') { // Keep a single whitespace. tag = " " + tag; } } } res+=quote_text(tag); } stripws=0; } } } return res; } int pages=0; void make_page(string base, TAG tag, string ind, string fbase) { // werror(ind+tag->tag+" "+tag->params->name+"\n"); werror("manpage "+(++pages)+"...\r"); mixed err = catch { string *outfiles,*names,*s_outfiles; string obase=base; string q; // werror(sprintf("%s %s %s %s \n", tag->params->name, fbase, globalbase, base)); outfiles=Array.map(names=tag->params->name/",", lambda(string s,string t,string u,string base) { s=replace(s,"->","."); // We want the man pages to be Image.image.foo for example... a man page for "create" is kinda uninteresting... // sscanf(s,t+".%s",s); return u+"/"+s+"."+base; },fbase,globalbase,base); // verbose = (names[0] == "Stdio.sendfile"); sscanf(outfiles[0],"%*s/man%*s/%s",q); if (q) { array(string) a = q/"."; if (sizeof(a) > 1) { q = a[..sizeof(a)-2]*"."; } } // werror("files: "+outfiles*", "+"\n"); if (tag->params->mansuffix) { base+=tag->params->mansuffix; fbase=(tag->params->name/",")[0]; // mkdirhier(globalbase+base); } // verbose = ((names*",") == "Thread.Mutex"); string page=strip_empty_lines(make_manpage(base,tag->data,ind+" ",fbase)); // werror("creating "+outfiles[0]+"...\n"); object f=Stdio.File(outfiles[0],"wtc"); string t=ctime(time()); f->write(strip_eightbit(".\\\" t\n" ".\\\" automatically generated from wmml\n" ".TH " + names*"," + " " + upper_case(obase) + " \"" + t[8..9] + t[3..7] + t[20..23] + "\"" " Pike \"Pike Manual\" Pike\n" + page + "\n")); f->close(); foreach (outfiles[1..], string s) { string name; sscanf(outfiles[0], "man/%s", name); // werror("creating "+s+" -> "+name+"...\n"); object f=Stdio.File(s, "wtc"); f->write(".so "+name+"\n"); f->close(); } foreach (({q})+names, string s) { windex->write(sprintf("%-15s %-15s - %s\n", s,q+" ("+obase+")", tag->params->title || (names*", "))); whatis->write(sprintf("%-23s - %s\n", s + " (" + obase + ")", tag->params->title || (names*", "))); } }; if (err) { werror("Error while making manpage for "+tag->name+" ("+base+"):\n" +master()->describe_backtrace(err)); } } void make_pages(string base, SGML data, string ind, string fbase) { if (arrayp(data)) foreach (data, TAG tag) if (objectp(tag)) if ((<"method","function","class","module">)[tag->tag]) make_page(base,tag,ind,fbase); else make_pages(base,tag->data,ind,fbase); } void output(string base, WMML data) { globalbase="man/man3"; // mkdirhier("man/man3p"); mkdirhier("man/man3"); windex=Stdio.File("man/windex", "wtc"); whatis=Stdio.File("man/whatis", "wtc"); // make_pages("3p", data->data, "", ""); make_pages("3p", data->data, "", ""); werror("\n"); // Used by Xman. // NB The Xman(1) man-page describes only the old file-format. // The format is either (old format) // <section suffix (one char)><section name><lf> // or // <section suffix><tab><section name>[<tab>suffix|fold|foldsuffix]<lf> // The latter is the only one usable for us. object mandesc = Stdio.File("man/mandesc", "wtc"); mandesc->write("3p\t(3P) Pike Library Functions\n" "3pi\t(3PI) Pike Image Module\n" "3pii\t(3PII) Pike Image.image Class\n"); mandesc->close(); } Sgml.Tag|string illustration(object o, mapping|void options) { return ""; } Sgml.Tag|string illustration_jpeg(object o, mapping|void options) { return ""; }