Home
Manual
Packages
Global Index
Keywords
Quick Reference
|
/*
MKDOC.I
Alphabetize DOCUMENT comments and prepare for line printer.
$Id: mkdoc.i,v 1.1 1993/08/27 18:50:06 munro Exp $
*/
/* Copyright (c) 1994. The Regents of the University of California.
All rights reserved. */
func mkdoc (filename, outname, lpp)
/* DOCUMENT mkdoc, filename
or mkdoc, filename, outname, lpp
alphabetizes and indexes the DOCUMENT comments in FILENAME, and
formats into "dictionary-like" pages for printing. If OUTNAME
is not given or nil, the output file will be FILENAME with ".doc"
replacing the ".i". If LPP is not given, it defaults to 58 --
the maximum number of available lines per page of output.
(Use 55 to be able to print with "lpr -p" style page headings.)
FILENAME can be an array of strings to combine several include
files into a single document.
SEE ALSO: help
*/
{
extern mkdoc_lpp;
if (is_void(lpp)) mkdoc_lpp= 58;
else mkdoc_lpp= lpp;
name_list= doc_list= oname= [];
inames= filename;
for (ii=1 ; ii<=numberof(filename) ; ii++) {
f= open(filename(ii));
/* strip off non-directory part of filename */
name= [string(0), filename(ii)];
do {
name= strtok(name(2), "/\:");
} while (name(2));
name= name(1);
inames(ii)= name;
/* get output file name */
if (is_void(oname)) {
if (is_void(outname)) {
oname= name;
if (strpart(oname, -1:0)==".i") oname= strpart(oname, 1:-2);
oname+= ".doc";
} else {
oname= outname;
}
}
/* scan the file to accumulate lists of function/variable/keyword names
and the corresponding document strings */
mkdoc_scan, f;
close, f;
}
/* alphabetize the lists */
order= sort(name_list);
name_list= name_list(order);
doc_list= doc_list(order);
/* make the title page */
f= open(oname, "w");
mkdoc_title, f, inames, name_list;
n= numberof(name_list);
fragment= [];
/* loop on output pages */
while ((nlines= numberof(fragment)) || n) {
nleft= mkdoc_lpp-3; /* leave 3 lines for heading */
if (nlines) {
/* part of the last entry has spilled onto the new page */
if (nlines < nleft) {
/* ...it fits on this page */
page= fragment;
fragment= [];
nleft-= nlines;
} else {
/* ...it fills this page completely, too --
be sure at least 6 lines on next page */
if (nlines < nleft+6) {
page= fragment(1:-6);
fragment= fragment(-5:0);
} else {
page= fragment(1:nleft);
fragment= fragment(nleft+1:0);
}
mkdoc_page, f, name, name, page;
continue;
}
fname= name;
not_top= 1;
} else {
page= [];
fname= name_list(1);
not_top= 0;
}
/* loop on entries for this page */
while (n) {
oname= name;
name= name_list(1);
fragment= *doc_list(1);
nlines= 1+numberof(fragment);
if (nleft >= nlines+not_top) {
/* this entire entry fits on this page */
if (not_top) grow, page, "";
grow, page, swrite(format="%75s", name), fragment;
fragment= [];
nleft-= nlines+not_top;
} else if (nlines+not_top>7 && nleft>7 &&
(nlines-nleft>=6 || nlines>12)) {
/* this entry runs over onto following pages */
if (not_top) grow, page, "";
nleft-= 1+not_top;
if (nlines-nleft<6) nlines-= 6;
else nlines= nleft;
grow, page, swrite(format="%75s", name), fragment(1:nlines);
fragment= fragment(nlines+1:);
nleft= 0;
} else {
/* this entire entry goes on next page */
name= oname;
fragment= [];
break;
}
if (--n) {
name_list= name_list(2:);
doc_list= doc_list(2:);
}
if (nleft<3 || numberof(fragment)) break;
not_top= 1;
}
/* output this page with dictionary headings */
mkdoc_page, f, fname, name, page;
}
close, f;
}
func mkdoc_scan (f)
{
/* Add extern, local, func, and struct declaration/definition names to
the name_list. For extern and func, add the DOCUMENT comment to the
doc_list. If no DOCUMENT comment appears within 10 non-blank lines,
skip to the next extern or func. If subsequent extern lines precede
the DOCUMENT comment, generate a cross-reference SEE ... to the
first extern of the group. For struct, the entire struct definition,
which is presumably commented, becomes the documentation text. */
extern name_list, doc_list;
while (line= rdline(f)) {
split= strtok(line);
doctext= [];
if (split(1)=="func" || split(1)=="extern" || split(1)=="local") {
name= strtok(split(2), " \t(,;");
if (split(1)!="local") crossref= [];
else crossref= mkdoc_cross(1, name(2), []);
name= name(1);
count= 10; /* like help_worker function defined in std.i */
while ((line= rdline(f)) && count--) {
split= strtok(line);
if (!split(1)) break;
if (strmatch(line, "/* DOCUMENT")) {
do {
grow, doctext, [line];
if (strmatch(line, "*/")) break;
} while (line= rdline(f));
} else if (split(1)=="extern") {
crossref= mkdoc_cross(0, split(2), crossref);
if (count==9) count= 10;
} else if (split(1)=="local") {
crossref= mkdoc_cross(1, split(2), crossref);
if (count==9) count= 10;
}
}
} else if (split(1)=="struct") {
name= strtok(split(2), " \t(,;")(1);
gotopen= 0;
do {
grow, doctext, [line];
if (!gotopen) gotopen= strmatch(line, "{");
if (gotopen && strmatch(line, "}")) break;
} while (line= rdline(f));
crossref= [];
}
if (!is_void(doctext)) {
grow, name_list, [name];
grow, doc_list, [&doctext];
n= numberof(crossref);
for (i=1 ; i<=n ; i++) {
grow, name_list, crossref(i);
grow, doc_list, &[" /* SEE "+name+" */"];
}
}
}
}
func mkdoc_cross (loc, names, crossref)
{
split= strtok(names, " \t,;");
cross= crossref;
while (split(1) && !strmatch(split(1), "/*")) {
grow, cross, split(1:1);
if (!loc) break;
split= strtok(split(2), " \t,;");
}
return cross;
}
func mkdoc_title (f, inames, name_list)
{
extern mkdoc_lpp;
write, f, format="\n\n\n"+
" Yorick Documentation\n"+
" for functions, variables, and structures\n"+
" defined in file %s\n"+
" Printed: %s\n", inames(1), timestamp();
write, f, format="\n %s\n\n", "Contents:";
nleft= mkdoc_lpp-10;
n= numberof(name_list);
ncols= 1;
while (n/ncols > nleft-3) ncols++;
width= 80/ncols;
len= max(strlen(name_list));
if (len > width-3) {
/* Contents will overflow onto subsequent page(s). Hopefully rare. */
ncols= 80/(len+3);
width= 80/ncols;
}
format= (width-len)/2 + 1;
width-= format;
format= swrite(format="%"+print(format)(1)+"s", ""); /* leading blanks */
format= format+"%-"+print(width)(1)+"s"; /* e.g.- " %-12s" */
len= (n-1)/ncols + 1;
for (i=1 ; i<=len ; i++) {
line= "";
for (j=i ; j<=n ; j+= len) line+= swrite(format=format, name_list(j));
j= strlen(line);
while (strpart(line, j:j)==" ") j--;
write, f, format="%s", strpart(line, 1:j)+"\n";
}
}
func mkdoc_page (f, fname, name, page)
{
extern mkdoc_lpp;
write, f, format="\f\n%75s\n\n", swrite(format="FROM %s TO %s",
fname, name);
n= numberof(page);
for (i=1 ; i<=n ; i++) write, f, format="%s\n", page(i);
}
|