a268f31997-11-07Mirar (Pontus Hagland) /* $Id: mkdoc.pike,v 1.15 1997/11/07 06:12:12 mirar Exp $ */
7bd16b1997-06-01Henrik Grubbström (Grubba) 
f311411997-04-18Mirar (Pontus Hagland) import Stdio; import Array;
b9284c1997-04-09Mirar (Pontus Hagland)  mapping parse=([]);
2c8d131997-05-30Mirar (Pontus Hagland) int illustration_counter;
0bb5e31997-10-29Mirar (Pontus Hagland) object illustration_source;
2c8d131997-05-30Mirar (Pontus Hagland)  string illustration_code=read_bytes("illustration.pike"); object lena_image=Image.image()->fromppm(read_file("doc/lena.ppm"));
b9284c1997-04-09Mirar (Pontus Hagland)  /* module : mapping <- moduleM "desc" : text
f311411997-04-18Mirar (Pontus Hagland)  "see also" : array of references "note" : mapping of "desc": text
f6068f1997-10-27Mirar (Pontus Hagland)  "modules" : same as classes (below)
f311411997-04-18Mirar (Pontus Hagland)  "classes" : mapping class : mapping <- classM "see also" : array of references
b9284c1997-04-09Mirar (Pontus Hagland)  "desc" : text
f311411997-04-18Mirar (Pontus Hagland)  "note" : mapping of "desc": text
b9284c1997-04-09Mirar (Pontus Hagland)  "methods" : array of mappings <- methodM "decl" : array of textlines of declarations "desc" : text "returns" : textline "see also" : array of references
f311411997-04-18Mirar (Pontus Hagland)  "note" : mapping of "desc": text
15b5661997-05-05Mirar (Pontus Hagland)  "known bugs" : mapping of "desc": text
f311411997-04-18Mirar (Pontus Hagland)  "args" : array of mappings <- argM "args" : array of args names and types "desc" : description "names" : multiset of method name(s)
b9284c1997-04-09Mirar (Pontus Hagland)  */
f311411997-04-18Mirar (Pontus Hagland) mapping moduleM, classM, methodM, argM, nowM, descM; mapping focM(mapping dest,string name,int line) { return dest[name] || (dest[name]=(["_line":line])); } string stripws(string s) { sscanf(s,"%*[ \t\n\r]%s",s); s=reverse(s); sscanf(s,"%*[ \t\n\r]%s",s); return reverse(s); } mapping lower_nowM() { if (nowM && (nowM==parse || nowM==classM || nowM==methodM || nowM==moduleM)) return nowM; else return nowM=methodM; }
26001a1997-05-29Mirar (Pontus Hagland) void report(string s) { stderr->write(s+"\n"); }
f311411997-04-18Mirar (Pontus Hagland) #define complain(X) (X) mapping keywords= (["module":lambda(string arg,int line)
f6068f1997-10-27Mirar (Pontus Hagland)  { classM=descM=nowM=moduleM=focM(parse,stripws(arg),line); methodM=0; if (!nowM->classes) nowM->classes=([]); if (!nowM->modules) nowM->modules=([]); report("module "+arg); },
f311411997-04-18Mirar (Pontus Hagland)  "class":lambda(string arg,int line) { if (!moduleM) return complain("class w/o module");
a827cd1997-04-19Mirar (Pontus Hagland)  descM=nowM=classM=focM(moduleM->classes,stripws(arg),line);
26001a1997-05-29Mirar (Pontus Hagland)  methodM=0; report("class "+arg); },
f6068f1997-10-27Mirar (Pontus Hagland)  "submodule":lambda(string arg,int line) { if (!moduleM) return complain("submodule w/o module"); classM=descM=nowM=moduleM=focM(moduleM->modules,stripws(arg),line); methodM=0; if (!nowM->classes) nowM->classes=([]); if (!nowM->modules) nowM->modules=([]); report("submodule "+arg); },
f311411997-04-18Mirar (Pontus Hagland)  "method":lambda(string arg,int line) { if (!classM) return complain("method w/o class");
a827cd1997-04-19Mirar (Pontus Hagland)  if (!nowM || methodM!=nowM || methodM->desc || methodM->args || descM==methodM)
f311411997-04-18Mirar (Pontus Hagland)  { if (!classM->methods) classM->methods=({}); classM->methods+=({methodM=nowM=(["decl":({}),"_line":line])}); }
a827cd1997-04-19Mirar (Pontus Hagland)  methodM->decl+=({stripws(arg)}); descM=0; },
f311411997-04-18Mirar (Pontus Hagland)  "arg":lambda(string arg,int line) { if (!methodM) return complain("arg w/o method");
068c061997-04-30Mirar (Pontus Hagland)  if (!methodM->args) methodM->args=({}); methodM->args+=({argM=nowM=(["args":({}),"_line":line])});
a827cd1997-04-19Mirar (Pontus Hagland)  argM->args+=({arg}); descM=argM;
f311411997-04-18Mirar (Pontus Hagland)  }, "note":lambda(string arg,int line) { if (!lower_nowM()) return complain("note w/o method, class or module");
a827cd1997-04-19Mirar (Pontus Hagland)  descM=nowM->note||(nowM->note=(["_line":line]));
f311411997-04-18Mirar (Pontus Hagland)  },
15b5661997-05-05Mirar (Pontus Hagland)  "bugs":lambda(string arg,int line) { if (!lower_nowM()) return complain("bugs w/o method, class or module"); descM=nowM->bugs||(nowM->bugs=(["_line":line])); },
f311411997-04-18Mirar (Pontus Hagland)  "see":lambda(string arg,int line) { if (arg[0..4]!="also:") return complain("see w/o 'also:'\n"); if (!lower_nowM()) return complain("see also w/o method, class or module"); nowM["see also"]=map(arg[5..]/",",stripws); }, "returns":lambda(string arg) { if (!methodM) return complain("returns w/o method"); methodM->returns=stripws(arg);
a827cd1997-04-19Mirar (Pontus Hagland)  descM=0; nowM=0;
f311411997-04-18Mirar (Pontus Hagland)  } ]); string getridoftabs(string s) { string res=""; for (;;) { int i; if ((i=search(s,"\t"))==-1) return res+s; res+=s[0..i-1]; s=s[i+1..]; res+=" "[(strlen(res)%8)..7]; } } string addprefix(string suffix,string prefix) { return prefix+suffix; }
a827cd1997-04-19Mirar (Pontus Hagland) #define urlify(S) (replace((S),({"%","&","'","\"","`"}), \ ({"%25","%26","%27","%22","%60"}))) #define htmlify(S) (replace((S),({"&","\240"}),({"&amp;","&nbsp;"})))
f311411997-04-18Mirar (Pontus Hagland) string make_nice_reference(string refto,string my_prefix) {
a827cd1997-04-19Mirar (Pontus Hagland)  string my_module,my_class,link,s,t; if (sscanf(my_prefix,"%s.%s",my_module,my_class)==1) my_class=0;
a268f31997-11-07Mirar (Pontus Hagland)  switch ((search(refto,"->")!=-1)+(search(refto,".")!=-1)*2)
a827cd1997-04-19Mirar (Pontus Hagland)  {
a268f31997-11-07Mirar (Pontus Hagland)  case 0: if (refto!=my_module) link=my_prefix+"->"+refto;
a827cd1997-04-19Mirar (Pontus Hagland)  else link=refto; break;
a268f31997-11-07Mirar (Pontus Hagland)  case 1: if (refto) link=my_module+"."+refto; else link=my_module; break;
a827cd1997-04-19Mirar (Pontus Hagland)  case 2: case 3: link=refto; break; }
2081941997-11-02Mirar (Pontus Hagland)  s=0; t=0;
8b26b91997-11-03Mirar (Pontus Hagland)  sscanf(link,"%s.%s",link,s);
2081941997-11-02Mirar (Pontus Hagland)  sscanf(link,"%s.%s.%s",link,s,t); if (s) link+="."+s; if (t) link=link+".html#"+t; else
a268f31997-11-07Mirar (Pontus Hagland)  if (search(link,"->")!=-1) link=replace(link,"->",".html#");
2081941997-11-02Mirar (Pontus Hagland)  else link+=".html";
a268f31997-11-07Mirar (Pontus Hagland)  link=replace(link,"..",".");
8b26b91997-11-03Mirar (Pontus Hagland) 
a827cd1997-04-19Mirar (Pontus Hagland)  return "<tt><a href="+urlify(link)+">"+refto+"</a></tt>";
f311411997-04-18Mirar (Pontus Hagland) } object(File) make_file(string filename) { stdout->write("creating "+filename+"...\n"); if (file_size(filename)>0) { rm(filename+"~"); mv(filename,filename+"~"); } object f=File(); if (!f->open(filename,"wtc")) { stdout->write("failed."); exit(1); } return f; }
0bb5e31997-10-29Mirar (Pontus Hagland) mapping ills=([]);
f311411997-04-18Mirar (Pontus Hagland) string fixdesc(string s,string prefix) { s=stripws(s); string t,u,v;
2c8d131997-05-30Mirar (Pontus Hagland) 
f311411997-04-18Mirar (Pontus Hagland)  t=s; s=""; while (sscanf(t,"%s<ref>%s</ref>%s",t,u,v)==3) { s+=t+make_nice_reference(u,prefix); t=v; } s+=t;
2c8d131997-05-30Mirar (Pontus Hagland)  t=s; s=""; while (sscanf(t,"%s<illustration>%s</illustration>%s",t,u,v)==3) { s+=t;
0bb5e31997-10-29Mirar (Pontus Hagland) 
68b67c1997-05-30Mirar (Pontus Hagland)  array err=catch {
2c8d131997-05-30Mirar (Pontus Hagland)  object x=compile_string(replace(illustration_code,"***the string***",u))(); x->lena_image=lena_image;
0bb5e31997-10-29Mirar (Pontus Hagland)  u=x->doit("illustration_"+illustration_counter+++".gif", ills,illustration_source,u);
2c8d131997-05-30Mirar (Pontus Hagland)  }; if (err) { stderr->write("error while compiling and running\n"+u+"\n");
68b67c1997-05-30Mirar (Pontus Hagland)  stderr->write(master()->describe_backtrace(err)+"\n");
2c8d131997-05-30Mirar (Pontus Hagland)  } else s+=u; t=v; } s+=t;
a827cd1997-04-19Mirar (Pontus Hagland)  return htmlify(replace(s,"\n\n","\n\n<p>"));
f311411997-04-18Mirar (Pontus Hagland) } string standard_doc(mapping info,string myprefix) { string res=""; if (info->desc && stripws(info->desc)!="")
a827cd1997-04-19Mirar (Pontus Hagland)  res+="\n\n<blockquote>\n"+fixdesc(info->desc,myprefix)+ "\n</blockquote>\n";
f311411997-04-18Mirar (Pontus Hagland) 
068c061997-04-30Mirar (Pontus Hagland)  if (info->note && info->note->desc)
f311411997-04-18Mirar (Pontus Hagland)  res+="\n\n<h4>NOTE</h4>\n<blockquote>\n"+
a827cd1997-04-19Mirar (Pontus Hagland)  fixdesc(info->note->desc,myprefix)+"\n</blockquote>\n";
f311411997-04-18Mirar (Pontus Hagland) 
15b5661997-05-05Mirar (Pontus Hagland)  if (info->bugs && info->bugs->desc) res+="\n\n<h4>KNOWN BUGS</h4>\n<blockquote>\n"+ fixdesc(info->bugs->desc,myprefix)+"\n</blockquote>\n";
f311411997-04-18Mirar (Pontus Hagland)  if (info["see also"]) { res+= "\n\n<h4>SEE ALSO</h4>\n<blockquote> " + map(info["see also"],make_nice_reference,myprefix)*",\n " + "\n</blockquote>\n"; } return res; } multiset(string) get_method_names(string *decls) { string decl,name; multiset(string) names=(<>); foreach (decls,decl) { sscanf(decl,"%*s%*[\t ]%s%*[\t (]%*s",name); names[name]=1; } return names; } string synopsis_to_html(string s) { string type,name,arg; if (sscanf(s,"%s%*[ \t]%s(%s",type,name,arg)!=4) sscanf(s,"%s(%s",name,arg),type=""; return type+" <b>"+name+"</b>("+
a827cd1997-04-19Mirar (Pontus Hagland)  replace(arg,({","," "}),({", ","\240"}));
f311411997-04-18Mirar (Pontus Hagland) } void document_method(object(File) f, mapping method, string prefix) {
a827cd1997-04-19Mirar (Pontus Hagland)  string s;
f311411997-04-18Mirar (Pontus Hagland)  stdout->write("documenting "+prefix+" methods "+ sort(indices(method->names))*", "+"...\n");
a827cd1997-04-19Mirar (Pontus Hagland)  f->write("\n<hr>\n"); foreach (sort(indices(method->names)),s) f->write("<a name="+urlify(s)+"> </a>\n"); f->write("<h4>SYNOPSIS</h4>\n"
f311411997-04-18Mirar (Pontus Hagland)  "<blockquote>\n"
a827cd1997-04-19Mirar (Pontus Hagland)  "<tt>"+htmlify(map(method->decl,synopsis_to_html)* "<br>\n")+
f311411997-04-18Mirar (Pontus Hagland)  "</tt>\n</blockquote>\n\n"); if (method->desc && stripws(method->desc)!="") { f->write("<h4>DESCRIPTION</h4>\n" "\n\n<blockquote>\n"+ fixdesc(method->desc,prefix)+ "\n</blockquote>\n"); } if (method->args) { mapping arg; f->write("<h4>ARGUMENTS</h4>\n<blockquote><dl>\n"); foreach (method->args,arg) {
068c061997-04-30Mirar (Pontus Hagland)  if (arg->desc) f->write("<dt><tt>"+arg->args*"</tt>\n<dt><tt>"+ "</tt>\n <dd>"+ fixdesc(arg->desc,prefix)+"\n"); else f->write("<dt><tt>"+arg->args*"</tt>\n<dt><tt>"+ "</tt>\n");
f311411997-04-18Mirar (Pontus Hagland)  } f->write("</dl></blockquote>\n"); } if (method->returns) { f->write("<h4>RETURNS</h4>\n" "\n\n<blockquote>\n"+method->returns+"\n</blockquote>\n"); }
068c061997-04-30Mirar (Pontus Hagland)  if (method->note && method->note->desc)
f311411997-04-18Mirar (Pontus Hagland)  { f->write("\n\n<h4>NOTE</h4>\n<blockquote>\n"+
068c061997-04-30Mirar (Pontus Hagland)  fixdesc(method->note->desc,prefix)+"\n</blockquote>\n");
f311411997-04-18Mirar (Pontus Hagland)  }
15b5661997-05-05Mirar (Pontus Hagland)  if (method->bugs && method->bugs->desc) { f->write("\n\n<h4>KNOWN BUGS</h4>\n<blockquote>\n"+ fixdesc(method->bugs->desc,prefix)+"\n</blockquote>\n"); }
f311411997-04-18Mirar (Pontus Hagland)  if (method["see also"]) { f->write("\n\n<h4>SEE ALSO</h4>\n<blockquote> " + map(method["see also"], make_nice_reference,prefix)*",\n " + "\n</blockquote>\n"); } } void document_class(string title, string file, mapping info, string prefix) { stdout->write("documenting "+title+"...\n"); object(File) f=make_file(file); f->write("<title>Pike documentation: "+title+"</title>\n"+ "<h2>"+title+"</h2>\n"+ standard_doc(info,prefix)); // postprocess methods to get names multiset(string) method_names=(<>); string *method_names_arr,method_name; mapping method;
068c061997-04-30Mirar (Pontus Hagland)  if (info->methods) foreach (info->methods,method) method_names|=(method->names=get_method_names(method->decl));
f311411997-04-18Mirar (Pontus Hagland)  method_names_arr=sort(indices(method_names));
a827cd1997-04-19Mirar (Pontus Hagland) /* f->write("\n<hr>\n <i><tt>"+*/ /* map(method_names_arr,make_nice_reference,prefix)**/ /* "</tt></i><br>\n <i><tt>"+"</tt></i><br>\n\n");*/
f311411997-04-18Mirar (Pontus Hagland)  // alphabetically foreach (method_names_arr,method_name) if (method_names[method_name]) { // find it foreach (info->methods,method) if ( method->names[method_name] ) { document_method(f,method,prefix); method_names-=method->names; }
587b1d1997-04-18Mirar (Pontus Hagland)  if (method_names[method_name]) stderr->write("failed to find "+method_name+" again, wierd...\n");
f311411997-04-18Mirar (Pontus Hagland)  } f->close(); }
f6068f1997-10-27Mirar (Pontus Hagland) void make_an_index(string title, string file, mapping info, string prefix, string *refs) { object f=make_file(file); f->write("<title>Pike documentation: "+title+"</title>\n"+ "<h2>"+title+"</h2>\n"+ standard_doc(info,prefix)); // if (sizeof(refs)) // { // f->write("<h3>More documentation:</h3>\n <i>" + // map(map(refs,addprefix,prefix), // make_nice_reference,prefix)*"</tt></i><br>\n <i><tt>" + // "</i>\n\n"); // } // postprocess methods to get names multiset(string) method_names=(<>); string *method_names_arr,method_name; mapping method; if (info->methods) foreach (info->methods,method) method_names|=(method->names=get_method_names(method->decl)); method_names_arr=sort(indices(method_names)); /* f->write("\n<hr>\n <i><tt>"+*/ /* map(method_names_arr,make_nice_reference,prefix)**/ /* "</tt></i><br>\n <i><tt>"+"</tt></i><br>\n\n");*/ // alphabetically foreach (method_names_arr,method_name) if (method_names[method_name]) { // find it foreach (info->methods,method) if ( method->names[method_name] ) { document_method(f,method,prefix); method_names-=method->names; } if (method_names[method_name]) stderr->write("failed to find "+method_name+" again, wierd...\n"); } f->close(); } void document_module(mapping mod,string module,string dir) { string clas; make_an_index("module "+module, dir+module+".html", mod, module+".", sort(indices(mod->classes||([])))); stdout->write("module "+module+" class(es): "+ sort(indices(mod->classes||([])))*", "+"\n"); foreach (sort(indices(mod->classes||([]))),clas) document_class(module+"."+clas, dir+module+"."+clas+".html", mod->classes[clas], module+"."+clas); foreach (sort(indices(mod->modules||([]))),clas) document_module(mod->modules[clas],module+"."+clas,dir); }
f311411997-04-18Mirar (Pontus Hagland) void make_doc_files(string dir) { stdout->write("modules: "+sort(indices(parse))*", "+"\n");
0bb5e31997-10-29Mirar (Pontus Hagland)  illustration_source=File(); illustration_source->open(dir+"illustrations.html","wct");
f6068f1997-10-27Mirar (Pontus Hagland)  string module;
f311411997-04-18Mirar (Pontus Hagland)  foreach (sort(indices(parse)),module)
f6068f1997-10-27Mirar (Pontus Hagland)  document_module(parse[module],module,dir);
f311411997-04-18Mirar (Pontus Hagland) }
b9284c1997-04-09Mirar (Pontus Hagland) 
f6068f1997-10-27Mirar (Pontus Hagland) int main(int ac,string *files)
b9284c1997-04-09Mirar (Pontus Hagland) {
26001a1997-05-29Mirar (Pontus Hagland)  string s,t;
f311411997-04-18Mirar (Pontus Hagland)  int line;
26001a1997-05-29Mirar (Pontus Hagland)  string *ss=({""});
f6068f1997-10-27Mirar (Pontus Hagland)  object f; string currentfile;
f311411997-04-18Mirar (Pontus Hagland)  nowM=parse;
26001a1997-05-29Mirar (Pontus Hagland)  stdout->write("reading and parsing data...\n");
f311411997-04-18Mirar (Pontus Hagland) 
f6068f1997-10-27Mirar (Pontus Hagland)  files=files[1..];
26001a1997-05-29Mirar (Pontus Hagland)  for (;;)
f311411997-04-18Mirar (Pontus Hagland)  { int i;
26001a1997-05-29Mirar (Pontus Hagland) 
f6068f1997-10-27Mirar (Pontus Hagland)  if (!f) { if (!sizeof(files)) break; stdout->write("reading "+files[0]+"...\n"); f=File(); currentfile=files[0]; files=files[1..]; if (!f->open(currentfile,"r")) { f=0; continue; } t=0; ss=({""}); line=0; }
26001a1997-05-29Mirar (Pontus Hagland)  if (sizeof(ss)<2) {
f6068f1997-10-27Mirar (Pontus Hagland)  if (t=="") { f=0; continue; } t=f->read(8192);
26001a1997-05-29Mirar (Pontus Hagland)  s=ss[0]; ss=t/"\n"; ss[0]=s+ss[0]; } s=ss[0]; ss=ss[1..];
f311411997-04-18Mirar (Pontus Hagland)  line++; if ((i=search(s,"**!"))!=-1) { string kw,arg;
26001a1997-05-29Mirar (Pontus Hagland) 
f311411997-04-18Mirar (Pontus Hagland)  sscanf(s[i+3..],"%*[ \t]%s%*[ \t]%s",kw,arg); if (keywords[kw]) { string err;
f6068f1997-10-27Mirar (Pontus Hagland)  if ( (err=keywords[kw](arg,currentfile+" line "+line)) )
f311411997-04-18Mirar (Pontus Hagland)  {
f6068f1997-10-27Mirar (Pontus Hagland)  stderr->write(currentfile+" line "+line+": "+err+"\n");
f311411997-04-18Mirar (Pontus Hagland)  return 1; } } else {
f6068f1997-10-27Mirar (Pontus Hagland) // if (search(s,"$Id")!=-1) report("Id: "+s);
a827cd1997-04-19Mirar (Pontus Hagland)  if (!descM) descM=methodM; if (!descM)
f311411997-04-18Mirar (Pontus Hagland)  { stderr->write("Error on line "+line+": illegal description position\n"); return 1; }
a827cd1997-04-19Mirar (Pontus Hagland)  if (!descM->desc) descM->desc=""; else descM->desc+="\n";
f311411997-04-18Mirar (Pontus Hagland)  s=getridoftabs(s);
a827cd1997-04-19Mirar (Pontus Hagland)  descM->desc+=s[search(s,"**!")+3..];
f311411997-04-18Mirar (Pontus Hagland)  } } } // stderr->write(sprintf("%O",parse)); stdout->write("making docs...\n\n"); make_doc_files("doc/"); return 0;
b9284c1997-04-09Mirar (Pontus Hagland) }