Newer
Older
// $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;
string globalbase;
object windex;
// Conversion table:
//
// "*" "\\(**"
// "\\" "\\e"
// "()" "(\\|)"
// " - " " \\- "
// "..." "\\&.\\|.\\|."
// ".." "\\&.\\|"
Henrik (Grubba) Grubbström
committed
string quote_text(string s)
{
s=replace(s,({">","&","<"}),
({">","&","<"}));
return(replace(s, ({ "*", "\\", "()", " - ", "...", ".." }),
({ "\\(**", "\\e", "(\\|)", " \\- ",
"\\&.\\|.\\|.", "\\&.\\|." })));
Henrik (Grubba) Grubbström
committed
}
// 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);
}
}
string make_manpage(string base, string|SGML data, string ind, string fbase)
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 (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":
Henrik (Grubba) Grubbström
committed
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":
if (tag->params->keep_ws) {
stripws = 0;
} else {
stripws=1;
}
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":
res+="\\f3"+make_manpage(base,tag->data,ind,fbase)+"\\f1";
continue;
int ows = stripws;
stripws = 0;
// Should specify a fixed width font.
res += make_manpage(base,tag->data,ind,fbase);
stripws = ows;
continue;
case "pre":
// Ought to specify a fixed width font.
res+="\n.nf\n"+
make_manpage(base,tag->data,ind,fbase)+
"\n.fi\n";
stripws = ows;
Henrik (Grubba) Grubbström
committed
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);
}
Henrik (Grubba) Grubbström
committed
stripws=0;
Henrik (Grubba) Grubbström
committed
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);
},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]*".";
}
if (tag->params->mansuffix)
{
base+=tag->params->mansuffix;
fbase=(tag->params->name/",")[0];
// mkdirhier(globalbase+base);
// verbose = ((names*",") == "Thread.Mutex");
Henrik (Grubba) Grubbström
committed
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] + "\""
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*", ")));
}
Henrik (Grubba) Grubbström
committed
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();