1 /* ************************** htmldoc.i ***************** */
2 // $Id: htmldoc.i,v 1.8 2007-12-11 10:22:19 paumard Exp $
3
4 /* DOCUMENT htmldoc.i
5
6 html documentation tools. By default the function mkhtmldoc constructs
7 html pages from the installed i0 and i directories.
8 Document comments are extracted, and cross-referenced to each other and to
9 the original function definitions. Crude indexing is performed by matching
10 a list of keywords to the document comments.
11
12 Batch mode:
13 yorick -batch htmldoc.i [--quiet|-q] [--nosrc|-s] [--nofunc|-f] \
14 [--from=dir1:dir2,...] [--to=destdir] [--xref-dir=html_xref] \
15 [--keywords=keywords.txt] [--packinfo=packinfo.txt] \
16 [--aliases=aliases.txt] [--template=template.html] [--warn=warnfile]
17
18 In batch mode, mkhtmldoc() is automatically called. Each
19 mkhtmldoc() keyword has an equivalent long option form. The boolean
20 options also have a short option form.
21
22 SEE ALSO: mkhtmldoc, hdoc_read_template, hdoc_extract_embedded,
23 mktexi2html_init, hdoc_head, hdoc_tail, hdoc_headtail
24 */
25
26
27
28 /*
29 author: Robert Cannon, rcc1@soton.ac.uk, 15th May 98
30 revised by David Munro 19/Apr/01, T. Paumard Nov/07
31 Yorick's BSD license applies:
32 Copyright (c) 2005-2007, The Regents of the University of California.
33 */
34
35
36 func mkhtmldoc(from=, to=, xref_dir=,
37 keywords=, packinfo=, template=, aliases=, warn=,
38 nosrc=, nofunc=, quiet=)
39 /* DOCUMENT mkhtmldoc generate html documentation tree
40
41 mkhtmldoc, from=, to=, xref_dir=,
42 keywords=, packinfo=, aliases=, template=,
43 nosrc=, nofunc=, quiet=,
44 warn=
45 generates html documentation from yorick files in selected directories.
46 Without any arguments the subdirectories i0 and i
47 of Y_SITE are scanned for function definitions, and the documentation is
48 created in subdirectories of the current directory.
49
50 The page layout is defined in a template file, which defaults to
51 "template.html" if this file exists. A builtin fallback is used if
52 no file is provided. The template can also be set using
53 hdoc_read_template.
54
55 If specified, the 'from' keyword should be a string array of
56 directories to scan. The 'to' keyword can be used to set a
57 destination directory other than the current directory.
58 The cross-reference DOCUMENT comments are extracted into
59 TO/XREF_DIR, where XREF_DIR defaults to "html_xref".
60
61 A keyword keywords= can be used to specify a file containing a list
62 of keywords from which to create a crude index. If not specified, and
63 if there is a file keywords.txt in the current directory, then that is
64 used. Likewise, the packinfo= can be used to specify a file containing
65 further information on some or all of the files in the source directories.
66 It defaults to packinfo.txt if not specified. An "aliases" file can also be
67 specified to merge the functions from several .i files in a single .html
68 file. It defaults to aliases.txt in the current directory if this file
69 exists.
70
71 The keywords nosrc and nofunc, if non null cut out the slowest parts
72 of the document creation process - crossreferencing the source files,
73 and creating function pages. They can be useful when checking the
74 format of a source file without recreating the whole document set.
75 When source files do not match the formats mkhtmldoc is expecting,
76 warnings are printed to standard output, or to a file specified by
77 the warn keyword. Note that non-compliance with the expected format
78 is not necessarily an indication of errors in the source files - simply
79 that mkhtmldoc can't make sense of them. Generally, however, it is
80 far easier to make one's own files follow the format of the
81 yorick i0 files more closely than it is to modify mkhtmldoc
82 to cope with them.
83
84
85 The documentation tree is generated in five stages.
86 1 - read through all the source files, extracting function names
87 extern declarations of builtin functions, and document comments
88 2 - for each source file, compile a series of html pages of the document
89 comments for the functions in that file. One html file is generated
90 for each first letter.
91 3 - compile a series of html pages for all the functions together, again
92 grouped into pages according to first letters.
93 4 - if a keywords file is available, match keywords in the document
94 comments, and compile a keyword index pointing to all the matched
95 functions.
96 5 - if a packinfo file is available, match source file names with
97 the packinfo file and compile a package list with the corresponding
98 descriptions. Alternatively, if a document comments appears near
99 the top of a source files, unattached to a function, this will be used
100 instead.
101
102
103 Unless QUIET is set to 1, mkhtmldoc outputs a lot of information,
104 including warnings. These warnings can be redirected to a file
105 using the WARN keyword (it is the only way to get them if QUIET is
106 set).
107
108 KEYWORDS: keywords, packinfo, aliases, template, from, to, nosrc, nofunc,
109 quiet, warn, xref_dir
110
111 SEE ALSO: mkdoc, tagscan, srcanchor, hdoc_read_template,
112 mktexi2html_init, hdoc_extract_embedded
113 */
114
115 {
116 if (is_void (from)) {
117 if (Y_VERSION!="1.4")
118 from = Y_SITE + ["i0", "i"];
119 else
120 from = Y_SITE + ["startup", "include", "contrib"];
121 }
122 if (is_void (to)) to = get_cwd();
123 if (strpart (to, strlen(to):) != "/") to += "/";
124 if (is_void(xref_dir)) xref_dir="html_xref/";
125 if (strpart (xref_dir, strlen(xref_dir):) != "/") xref_dir += "/";
126 if (is_void (keywords)) {
127 if (open("keywords.txt","r",1)) keywords = "keywords.txt";
128 }
129 if (is_void (packinfo)) {
130 if (open("packinfo.txt","r",1)) packinfo = "packinfo.txt";
131 }
132 nwarn = 0;
133 if (warn) {
134 fwarn = open (warn, "w");
135 }
136
137 if (is_void(template)) template="template.html";
138 if (open(template,"r",1)) hdoc_read_template,template;
139
140 /* directories for html files: html_xref for alphabetical function
141 listings, create the directories manual and refcard to hold the
142 manual and reference cards. (for now will put simple
143 placeholder files in them)
144 */
145
146 dnames = [xref_dir];
147 // make these directories under the 'to' directory if they don't exist;
148 for (i = 1; i <= numberof (dnames); i++) {
149 todir = to + dnames(i);
150 if (!open(todir,"r",1)) system, "mkdir " + todir;
151 if (!open(todir,"r",1)) {
152 exit, "cant create directory " + todir;
153 }
154 }
155
156 // the _lsm1 function is unix xpecific - it gets a list of the files
157 // in its arguement;
158 ifiles = _lsm1 (from, ext = ".i", to=to);
159
160
161 /* STAGE 1 - get a list of all function declarations, their names,
162 file, directory, document comment and line in the file
163 based on the MKDOC function in mkdoc.i
164 */
165
166 maxtags = 256;
167 tags = array(string, 6, maxtags);
168 ntags = 0;
169 if (!quiet) write, "scanning files for function definitions";
170 for (i=1 ; i <= numberof(ifiles) ; i++) {
171 if (!quiet) write, format = "%s \n", ifiles(i) ;
172 newtags = tagscan(ifiles(i));
173 nt = numberof(newtags)/6;
174 if (nt) {
175 if (nt > maxtags-ntags) {
176 no = maxtags;
177 do {
178 maxtags *= 2;
179 } while (nt > maxtags-ntags);
180 grow, tags, array(string, 6, maxtags-no);
181 }
182 tags(,ntags+1:ntags+nt) = newtags;
183 ntags += nt;
184 }
185 }
186 if (ntags) {
187 tags = tags(,1:ntags);
188 tags = tags(,where(strlen(tags(6,))>6));
189 }
190 if (!quiet) write, "";
191
192 /* STAGE 2 - copy the files name.i to tmp_name_i.html in the directories
193 under 'to', html quoting the characters "<" and ">" and adding
194 anchors and cross references.
195 */
196 // this part is slow - set nosrc to 1 to skip it;
197 if (never_do && !nosrc) {
198 if (!quiet) write, "anchoring and linking source files";
199 for (i=1 ; i <= numberof(ifiles) ; i++) {
200 name= [".", ifiles(i)];
201 do {
202 rtdir = name(1);
203 rtname = name(2);
204 name= strtok(name(2), "/\:");
205 } while (name(2));
206 if (strpart(rtname, -1:0)==".i") rtname= strpart(rtname, 1:-2);
207
208 dest = to + "html_i/tmp_" + rtname +"_i.html";
209 finaldest = to + "html_i/" + rtname +"_i.html";
210 if (!quiet) write, format = "%s \n", ifiles(i) ;
211 srcanchor, ifiles(i), dest, tags, quiet=quiet, xref_dir=xref_dir;
212
213 hdoc_headtail, dest, finaldest, title = rtdir + "/" + rtname;
214 }
215 if (!quiet) write, "";
216 }
217
218 if (!nofunc) {
219 // STAGE 3 - function listings by file in which they are defined;
220
221 mask = strpart(tags(3,),-4:-1) == "test";
222 tags = tags(,where(!mask));
223 mask = strpart(tags(3,),-6:0) == "teststr";
224 tags = tags(,where(!mask));
225 mask = strpart(tags(3,),-5:0) == "testlp";
226 tags = tags(,where(!mask));
227 mask = strpart(tags(3,),-5:0) == "txpath";
228 tags = tags(,where(!mask));
229 mask = strpart(tags(1,),1:7) == "fitsAdd";
230 mask |= strpart(tags(1,),1:6) == "fitsRe";
231 mask |= tags(1,) == "fitsFixHeader";
232 mask |= tags(1,) == "fitsWrite";
233 mask |= tags(1,) == "fits_coordinate";
234 mask |= strpart(tags(1,),1:7) == "_numfmt";
235 mask |= tags(1,) == "system_orig";
236 mask |= tags(1,) == "rez_style";
237 mask |= strpart(tags(1,),1:5) == "_png_";
238 tags = tags(,where(!mask));
239
240 tags = tags(,sort(strcase(0,tags(1,))));
241
242 if (is_void(aliases)) aliases="aliases.txt";
243 if (fal=open(aliases,"r",1)) {
244 while (line=rdline(fal)) {
245 found=0;
246 if (strlen(line)==0) continue;
247 aka=pathsplit(line,delim=" ");
248 rname=aka(1);
249 if (strgrep("^#",rname)(2)==1) continue;
250 for (i=1;i<=numberof(aka);i++) {
251 list=where(strgrep(aka(i)+"$",tags(3,))(2,)!=-1);
252 if (numberof(list)) {
253 tags(3,list)=rname;
254 found=1;
255 grow,rtx,aka(i);
256 }
257 }
258 if (found) {
259 list=where(tags(3,)==rname);
260 if (!quiet) write, format = "writing index and doc pages for %s \n", rname;
261 hdoc_funcindex, rname, tags(,list), to, xref_dir;
262 hdoc_funcdocs, rname, tags(,list), tags, to, xref_dir, quiet=quiet;
263 }
264 }
265 close,fal;
266 // math fft matrix
267 // yorz png mpeg jpeg zlib
268 }
269
270 tags = tags(,sort(tags(3,)));
271 rtndx = (tags(3,2:0)!=tags(3,1:-1))(cum)+1;
272 rtname = array(string, rtndx(0));
273 rtname(rtndx) = tags(3,);
274 tags = tags(,sort(strcase(0,tags(1,))));
275 for (i=1;i<=numberof(rtx);i++) rtname = rtname(where(rtname!=rtx(i)));
276 for (i = 1; i <= numberof(rtname); i++) {
277 if (!quiet) write, format = "writing index and doc pages for %s \n",
278 rtname(i);
279 w = where(tags(3,)==rtname(i));
280 hdoc_funcindex, rtname(i), tags(,w), to, xref_dir;
281 hdoc_funcdocs, rtname(i), tags(,w), tags, to, xref_dir, quiet=quiet;
282 }
283 if (!quiet) write, "";
284 }
285
286
287 if (!nofunc) {
288 // STAGE 4 - function listings for all builtin and extern functions;
289 // w = where (tags(5,) != "local");
290 w = [];
291 if (!quiet) write, "writing global index and doc pages";
292 hdoc_funcindex, "global", tags(,w), to, xref_dir;
293 // hdoc_funcdocs, "global", tags(,w), tags, to, xref_dir;
294 }
295
296
297 // STAGE 5 - package listing;
298 if (!quiet) write, "making package listing";
299 hdoc_packagelist, from, tags, packinfo=packinfo, to=to, xref_dir=xref_dir;
300
301
302 //STAGE 6 - keywords
303 if (keywords) {
304 if (!quiet) write, "making keyword index ";
305 hdoc_keywordindex, tags, keywords, to, xref_dir;
306 }
307
308 //STAGE 7 - miscellaneous;
309 //hdoc_toptemplate, to;
310
311 // put a default background image in the images directory;
312 // f = open (to + "images/ydocbg.gif", "wb");
313 // a =
314 // [0x47,0x49,0x46,0x38,0x37,0x61,0xb7,0x04,0x01,0x00,0xf0,0x00,0x00,0x00,0x56,
315 // 0x00,0xff,0xea,0xc2,0x2c,0x00,0x00,0x00,0x00,0xb7,0x04,0x01,0x00,0x00,0x02,
316 // 0x2b,0x84,0x8f,0xa9,0xcb,0xed,0x0f,0xa3,0x9c,0x31,0xd8,0x8b,0xb3,0xde,0xbc,
317 // 0xfb,0x0f,0x86,0xe2,0x48,0x96,0xe6,0x89,0xa6,0xea,0xca,0xb6,0xee,0x0b,0xc7,
318 // 0xf2,0x4c,0xd7,0xf6,0x8d,0xe7,0xfa,0xce,0xf7,0xfe,0x0f,0x0c,0xee,0x0a,0x00,
319 // 0x3b];
320 // _write, f, 0, char(a);
321 // close, f;
322 }
323
324
325
326 func _lsm1 (from, ext=, to=) {
327 if (is_void (ext)) ext = "";
328 if (is_void (to)) to = "./";
329
330 ndir = numberof (from);
331 system, "ls -1 " + from(1) + "/*" + ext + " > " + to + "tmpflist.dat";
332 for (i = 2; i <= ndir; i++) {
333 system, "ls -1 " + from(i) + "/*" + ext + " >> " + to + "tmpflist.dat";
334 }
335 ifiles = hdoc_read_file(to + "tmpflist.dat");
336 remove, to + "tmpflist.dat";
337 if (ext==".i" && numberof(ifiles)) {
338 mask = strpart(ifiles,-7:0)!="collec.i";
339 mask &= strpart(ifiles,-7:0)!="custom.i";
340 mask &= strpart(ifiles,-6:0)!="legal.i";
341 mask &= strpart(ifiles,-7:0)!="prmtyp.i";
342 mask &= strpart(ifiles,-6:0)!="readn.i";
343 mask &= strpart(ifiles,-5:0)!="show.i";
344 mask &= strpart(ifiles,-5:0)!="stdx.i";
345 mask &= strpart(ifiles,-9:0)!="testfull.i";
346 ifiles = ifiles(where(mask));
347 }
348 return ifiles;
349 }
350
351
352
tagscan(fnm)353 func tagscan (fnm) {
354 /* DOCUMENT
355 tags = tagscan, filename
356 scan file filename for function declarations/definitions.
357 Returns a (6, nfunc) string array containing, for each function,
358 the function name, then the directory name, file name, and line
359 where it appears, its DOCUMENT comment and type. As with the mkdoc
360 function, if subsequent extern lines precede the DOCUMENT
361 comment, generate a cross-reference SEE ... to the first extern
362 of the group.
363 based on the mkdoc function in mkdoc.i
364
365 SEE ALSO: mkhtmldoc, mkdoc, srcanchor
366 */
367
368 /* strip off non-directory part of filename */
369 name= [".", fnm];
370 do {
371 rtdir = name(1);
372 rtfnm = name(2);
373 name= strtok(name(2), "/\:");
374 } while (name(2));
375 if (strpart(rtfnm, -1:0)==".i") rtfnm= strpart(rtfnm, 1:-2);
376 /* scan the file to accumulate lists of function/variable/keyword names
377 and the corresponding document strings */
378
379 tags = [];
380 ntags = maxtags = 0;
381 f = open (fnm);
382 pfunclev = funclev = 0;
383 iline = 0;
384 while (line= _myrdline(f)) {
385 split= strtok(line);
386 doctext= "";
387 gottag = 0;
388 if (pfunclev == 0 && (split(1)=="func" ||
389 split(1)=="extern" ||
390 split(1) == "local")) {
391 gottag = 1;
392 mytype = split(1);
393 name= strtok(split(2), " \t(,;");
394 if (name(1)=="junk" || name(1)=="op") continue;
395 if (split(1)!="local") crossref= [];
396 else crossref= _hdoc_cross(1, name(2), []);
397 name= name(1);
398 myline = iline;
399
400 // beginning of function definition;
401 count= 15; /* like help_worker function defined in std.i */
402 while ((line= _myrdline(f)) && count--) {
403
404 split= strtok(line);
405 if (!split(1) || split(1) == "}") break;
406 if (strmatch(line, "/* DOCUMENT")) {
407 do {
408 doctext += line + "\n";
409 if (strmatch(line, "*/")) break;
410 } while (line= _myrdline(f));
411 } else if (funclev == 0 && (split(1)=="extern" ||
412 split(1)=="func")) {
413 crossref= _hdoc_cross(0, split(2), crossref);
414 if (count==9) count= 10;
415 } else if (funclev == 0 && split(1)=="local") {
416 crossref= _hdoc_cross(1, split(2), crossref);
417 if (count==9) count= 10;
418 }
419 }
420
421 } else if (pfunclev == 0 && split(1)=="struct") {
422 gottag = 1;
423 mytype = split(1);
424 name= strtok(split(2), " \t(,;")(1);
425 myline = iline;
426 gotopen= 0;
427 do {
428 doctext += line + "\n";
429 if (!gotopen) gotopen= strmatch(line, "{");
430 if (gotopen && strmatch(line, "}")) break;
431 } while (line= _myrdline(f));
432 crossref= [];
433 }
434
435 // ignore things looking like tags but with one or fewer characters;
436 if (gottag && strlen (name) > 1) {
437 sline = strtrim(swrite (myline));
438 if (ntags == maxtags)
439 grow, tags, array(string, 6, (maxtags+=100));
440 ntags++;
441 tags(,ntags) = [name, rtdir, rtfnm, sline, mytype, doctext];
442
443 n= numberof(crossref);
444 for (i=1 ; i<=n ; i++) {
445 doctext = "/* SEE "+name+" */";
446 xname = crossref(i);
447 if (ntags == maxtags)
448 grow, tags, array(string, 6, (maxtags+=100));
449 ntags++;
450 tags(,ntags) = [xname, rtdir, rtfnm, sline, mytype, doctext];
451 }
452 }
453 }
454 close, f;
455 if (ntags) tags = tags(,1:ntags);
456 return tags;
457 }
458
459
_myrdline(f)460 func _myrdline(f) {
461 /* keep a record of whether we are between curly braces or not
462 so as to avoid picking up extern declarations of variables at
463 the top level.
464 */
465 iline++;
466 line = rdline(f);
467 extern pfunclev;
468 pfunclev = funclev;
469 if (strmatch (line, "{")) funclev++;
470 if (strmatch (line, "}")) funclev--;
471 if (strpart (line, 1:1) == "}") funclev = 0;
472 return line;
473 }
474
475
_hdoc_cross(loc,names,crossref)476 func _hdoc_cross(loc, names, crossref)
477 {
478 split= strtok(names, " \t,;()");
479 cross= crossref;
480 while (split(1) && !strmatch(split(1), "/*")) {
481 grow, cross, split(1:1);
482 if (!loc) break;
483 split= strtok(split(2), " \t,;");
484 }
485 return cross;
486 }
487
488
489
490
491
492
493 func srcanchor (infile, outfile, tags, quiet=, xref_dir=) {
494 /* DOCUMENT
495 srcanchor, infile, outfile, tags
496 convert yorick source to html
497 Copy infile to outfile quoting any html special characters, inserting
498 anchors at function definitions/declarations, and cross-referencing
499 function calls to definitions. Tags should be a two dimensional string
500 array containing in tags (1,) the function names, and in tags(2,),
501 tags(3,) and tags(4,) the directory, file, and line where each functions
502 is defined/declared.
503
504 SEE ALSO: mkhtmldoc, tagscan, mkdoc
505 */
506
507
508 tnames = tags(1,);
509 ttypes = tags (5,);
510 tnamesttypes = tnames + ttypes;
511 nfn = numberof (tnames);
512
513 f = open (infile);
514 g = open (outfile, "w");
515
516 wryte, g, "<pre>";
517 wryte, g, "<font SIZE=2 color=\"#000000\">";
518
519 funclev = 0;
520 nwsf = 0;
521 while (line = rdline(f)) {
522
523 // convert ">" and "<" to their html equivalents < and >
524 while (strmatch (line, ">")) {
525 split = strtok (line, ">");
526 line = split(1) + ">" + split(2);
527 }
528 while (strmatch (line, "<")) {
529 split = strtok (line, "<");
530 line = split(1) + "<" + split(2);
531 }
532
533 split = strtok (line);
534 type = split(1);
535 if (funclev == 0 && (type=="func" ||
536 type=="extern" ||
537 type=="local") ) {
538 name = (strtok(split(2), " \t(,;"))(1);
539 rest = strpart (split(2), strlen(name)+1:);
540
541 w = where (tnamesttypes == name + type);
542 if (numberof (w) != 1) {
543 if (strlen(name) > 1 && name != "junk" && name != "op") {
544 // silently ignore failed one character matches;
545 if (nwsf == 0 & !quiet) write, format = "\n %s", "";
546 nwsf++;
547 if (!quiet|!is_void(warn)) write, fwarn, format =
548 "warning: %i tag matches for %s \n",
549 numberof(w), name;
550 nwarn++;
551 }
552 wryte, g, line;
553 } else {
554 tagdat = tags(,w(1));
555
556 /* for the definition/declaration itself, put in an anchor and
557 a link back to the documentation tree */
558 wryte, g, ("<b>" + split(1) + " <a name = " + tagdat(1) +
559 " href = ../" + xref_dir + tagdat(3) +
560 "-doc.html" + "#" + tagdat(1) +
561 ">" + tagdat(1) + "</a></b> " + rest);
562 }
563 } else {
564 /* look for tags within this line and put in links to the
565 source tree */
566
567 // this is going to be pretty slow....;
568 rest = line;
569 newline = "";
570 while (rest && rest != "") {
571 tok = (strtok (rest, " ,+-*/=\(\)!&^:;"))(1);
572 if (!tok) {
573 newline += rest;
574 rest = string(0);
575 } else {
576 c = (*pointer(tok))(1);
577 ss= *pointer(rest);
578 i0 = (where(ss == c))(1);
579 if (i0 > 1) newline += strpart(rest, 1:i0-1);
580 rest = strpart (rest, i0 + strlen(tok):);
581
582 w = where (tnames == tok);
583 if (numberof (w) == 1) {
584 tagdat = tags (,w(1));
585
586 newline += ("<A HREF = ../html_i/" + tagdat(3) +
587 "_i.html#" + tagdat(1) +">" + tagdat(1) +
588 "</A>");
589 } else {
590 newline += tok;
591 }
592 }
593 }
594
595 wryte, g, newline;
596 }
597 if (strmatch (line, "{")) funclev++;
598 if (strmatch (line, "}")) funclev--;
599 /* just in case, reset block counting for closing braces at start
600 of line. As far as I'm aware, the above only fails once, on the line
601 if (anyof(['{','}',',','=']==cs)) {
602 in string.i */
603 if (strpart (line, 1:1) == "}") funclev = 0;
604 }
605 wryte, g, "</pre>";
606 close, f;
607 close, g;
608 }
609
610
611
_alphabsuffix(name)612 func _alphabsuffix (name) {
613 /* make a suffix from the first letter of name.
614 to cope with case insensitive systems, map eg "A" to "ac" and
615 "a" to "as" (for capital and small);
616 */
617 if (strpart(name, 1:1) == "_") {
618 suf = "-uscr";
619 } else {
620 ia = int (*pointer("a"))(1);
621 iA = int (*pointer("A"))(1);
622 ic = int (*pointer(name))(1);
623 icl = (ic >= ia ? ic : ic + ia - iA);
624 suf = "-" + string(&char(icl)) + (ic >= ia ? "s" : "c");
625 }
626 return suf;
627 }
628
629
hdoc_funcindex(rtname,tags,to,xref_dir)630 func hdoc_funcindex(rtname, tags, to, xref_dir) {
631 if (is_void(to)) to = ".";
632
633 name_list = tags(1:3:2,);
634 modnl = [];
635 n = numberof(name_list)/2;
636 fp = [];
637 for (i = 1; i <= n; i++) {
638 aa = name_list(,i);
639 if ((nfp = strcase(0,strpart (aa(1), 1:1))) != fp) {
640 grow, modnl, [[strcase(1,nfp) + ".", string(0)]];
641 fp = nfp;
642 }
643 grow, modnl, aa;
644 }
645
646 name_list = modnl(1,);
647 modnl = modnl(2,);
648
649 idxbg1 = "\"#bbddff\"";
650 idxbg2 = "\"#bbddff\"";
651 idxfg = "\"#000000\"";
652 idxbg0 = "\"#ffffff\"";
653
654 doc="xref";
655 f = open (to + xref_dir + rtname + "-index.html", "w");
656
657 if (rtname == "global") title="Yorick routines defined in all files";
658 else title="Yorick routines defined in file " + rtname + ".i";
659 hdoc_head, f, title, table=1, doc=doc;
660 wryte, f, "<center><h1>";
661 if (rtname == "global") wryte, f, "all routines";
662 else wryte, f, title;
663 wryte, f, "</h1></center>";
664 _hdoc_skip, f, 2;
665
666 n = numberof(name_list);
667 ncol = min(1+(n-1)/10, 4);
668 nrow = (n + ncol-1) / ncol;
669
670 wryte, f, "<table cellpadding=2 cellspacing = 0>";
671
672 for (ir = 1; ir <= nrow; ir++) {
673 wryte, f, "<tr>";
674 for (ic = 1; ic <= ncol; ic++) {
675 ielt = (ic-1) * nrow + ir;
676 ok = (ielt <= n);
677 s = (ok ? name_list(ielt) : " ");
678 lab = (strlen (s) == 2 && strpart(s, 2:2) == ".");
679
680 if (lab) {
681 wryte, f, "<td BGCOLOR=" + idxbg2 + ">";
682 wryte, f, "<font color=" + idxfg + "> " +
683 strpart(s,1:1) + " </font>";
684 wryte, f, "</td>";
685 } else {
686 wryte, f, "<td></td>";
687 }
688 wryte, f, "<td>";
689 if (ok && !lab) {
690 wryte, f, "<a href = " + modnl(ielt) + "-doc.html\#" +
691 s + ">" + s + "</a>";
692 } else if (ok) {
693 wryte, f, "<font color =" + idxbg1 + "> ------- </font>";
694 } else {
695 wryte, f, "<font color =" + idxbg0 + "> ------- </font>";
696 }
697 wryte, f, "</td>";
698 }
699 wryte, f, "</tr>";
700 }
701 wryte, f, "</table>";
702 hdoc_tail, f, title, table=1, doc=doc;
703 }
704
705
706
707 func hdoc_funcdocs (rtname, tags, atags, to, xref_dir, quiet=) {
708 if (is_void (to)) to = "./";
709 name_list =tags(1,);
710 doc_list = tags(6,);
711 anames = atags(1,);
712 nwsf = 0;
713 split_doc_list, name_list, doc_list, doc_def, doc_body, doc_see;
714 aprev = "";
715 f = [];
716 n = numberof (name_list);
717 doc="xref";
718 f = open(to+xref_dir+rtname+"-doc.html","w");
719 title = "section " + aprev + " of routines in " + rtname + ".i";
720 hdoc_head, f, title, table=1, doc=doc;
721 wryte, f, "<center><h1>";
722 if (rtname == "global") {
723 wryte, f, " all functions - " + aprev;
724 } else {
725 wryte, f, "functions in " + rtname + ".i - " + aprev;
726 }
727 wryte, f, "</h1></center>";
728
729 for (i = 1; i <= n; i++) {
730 name = name_list(i);
731 _hdoc_skip, f, 3;
732 wryte, f, "<table cellpadding = 0 border = 0 cellspacing = 0>";
733 wryte, f, "<tr>";
734 wryte, f, "<td valign = top width = 140 rowspan = 2>";
735 wryte, f, "<big><b>";
736 wryte, f, "<a name = " + name_list(i) + ">" + name_list(i) + "</a> <p>";
737 // wryte, f, name_list(i);
738 wryte, f, "</b></big>";
739 wryte, f, "</td>";
740
741 dd = *(doc_def(i));
742 db = *(doc_body(i));
743 dsa = *(doc_see(i));
744
745 myname = name_list(i);
746 w = where (anames == myname);
747 if (numberof(w) == 1) {
748 igl = w(1);
749 tagtyp = tags(5,i);
750 if (tagtyp == "extern") {
751 sdef = "builtin function, documented at ";
752 } else if (tagtyp == "func") {
753 sdef = "interpreted function, defined at ";
754 } else if (tagtyp == "struct") {
755 sdef = "structure, defined at ";
756 } else if (tagtyp == "local") {
757 sdef = "keyword, defined at ";
758 } else {
759 sdef = "unknown tag ";
760 }
761
762 sdef = (sdef + atags(2, igl) + "/" +
763 atags(3, igl) + ".i <a href = ../html_i/" +
764 atags(3, igl) + "_i.html#" + myname + ">" +
765 " line " + strtrim (swrite(atags(4, igl))) + "</a>");
766 /* grow, db, sdef; */
767 } else {
768 if (nwsf == 0 & !quiet) write, format = "\n %s", "";
769 if (!quiet) print, "zero or multiple names ", w, myname;
770 nwsf++;
771 }
772
773 if (!is_void (dd) || !is_void (db)) {
774
775 wryte, f, "<td colspan = 2>";
776 wryte, f, "<pre>";
777 wryte, f, ("<font SIZE=2 color=\"#000000\">");
778 if (!is_void (dd)) {
779 write, f, format = "<b> %s </b>\n", dd;
780 wryte, f, " ";
781 }
782 if (!is_void (db)) {
783 write, f, format = "%s \n", db;
784 }
785 wryte, f, "</pre>";
786 wryte, f, "</font>";
787 wryte, f, "</td></tr>";
788 }
789
790 if (!is_void (dsa)) {
791 nsa = numberof (dsa);
792 nsac = 5;
793 nsar = (nsa - 1 + nsac-1) / nsac;
794
795 wryte, f, "<tr>";
796 wryte, f, "<td width = 100 >";
797 wryte, f, ("<font SIZE=2 color=\"#00000\">");
798 wryte, f, dsa(1);
799 wryte, f, "</font>";
800 wryte, f, "</td>";
801
802 wryte, f, "<td width = 300>";
803 wryte, f, ("<font SIZE=3 color=\"#000000\">");
804 nchar = 0;
805 for (k = 2; k <= nsa; k++) {
806 ssa = dsa(k);
807 if (ssa == "get_ray-path") ssa = "get_ray";
808 nchar += strlen (ssa)+2;
809 if (nchar > 46) {
810 wryte, f, "<br>";
811 nchar = strlen(ssa);
812 }
813 defroot = "";
814 w = where (anames == ssa);
815 if (numberof(w) == 1) {
816 igl = w(1);
817 defroot = "../" + xref_dir + atags(3, igl);
818 } else {
819 if (nwsf == 0 & !quiet) write, format = "\n %s", "";
820 if (!quiet|!is_void(warn)) write, fwarn, format = " warning: %i tag matches for %s \n",
821 numberof (w), ssa;
822 nwsf++;
823 }
824 if (defroot != "") {
825 aaa = strpart (ssa, 1:1);
826 write, f, (" <a href = " + defroot +
827 "-doc.html#"+ssa + ">" + ssa + "</a>"+
828 ((k < nsa) ? ", " : " "));
829 } else {
830 write, f, (ssa + ((k < nsa) ? ", " : " "));
831 }
832 }
833 wryte, f, "</td>";
834 wryte, f, "</tr>";
835 }
836 wryte, f, "</table>";
837 }
838 hdoc_tail, f, title, table=1, doc=doc;
839 close, f;
840 }
841
842
843
844 func split_doc_list (name_list, doc_list, &doc_def, &doc_body, &doc_see)
845 {
846 n = numberof (doc_list);
847 doc_see = doc_body = doc_def = array (&[], n);
848
849 for (i = 1; i <= n; i++) {
850 sdoc = doc_list(i);
851 doc = [];
852 do {
853 split = strtok (sdoc, "\n");
854 grow, doc, [split(1)];
855 sdoc = split(2);
856 } while (sdoc && sdoc != "");
857 nl = numberof (doc);
858
859 dd = [];
860 db = [];
861 dsa = [];
862
863 k = 1;
864 if (nl > 0) {
865 fl = doc(k);
866 if ((ind = strmatch (fl, "DOCUMENT")) > 0) {
867 grow, dd, " " + strpart(fl, 12:strlen(fl));
868 k++;
869 fl = doc(k);
870 ta = strtok(fl);
871 if (ta(1)=="*") ta = strtok((fl = " "+ta(2)));
872 while (k <= nl && (ta(1) == "or" ||
873 strpart(fl,1:11) == " ")) {
874 grow, dd, fl;
875 k++;
876 fl = doc(k);
877 ta = strtok(fl);
878 if (ta(1)=="*") ta = strtok((fl = " "+ta(2)));
879 }
880 }
881
882 while (k <= nl) {
883 fl = doc(k);
884 if (strmatch (fl, "SEE ALSO:")) {
885 dsa = ["SEE ALSO:"];
886
887 for (j = k+1; j <= nl; j++) {
888 fl = fl + " " + doc(j);
889 }
890 ta = strtok (fl, " .,\n\t*");
891 while (ta(1) != string(0)) {
892 if (ta(1) != "SEE" && ta(1) != "ALSO:" &&
893 ta(1) != "/*" && ta(1) != "*/" && ta(1) != "*") {
894 if (strpart(ta(1),1:1)!="(" && strpart(ta(1),0:0)!=")")
895 grow, dsa, ta(1);
896 }
897 ta = strtok (ta(2), " .,\n\t");
898 }
899 k = nl+1;
900
901 } else if (strmatch (fl, " SEE ")) {
902 dsa = ["SEE"];
903 ta = strtok (fl, " .,\n\t");
904 while (ta(1) != string(0)) {
905 if (ta(1) != "SEE" && ta(1) != "/*" &&
906 ta(1) != "*/" && ta(1) != "*") {
907 grow, dsa, ta(1);
908 }
909 ta = strtok (ta(2));
910 }
911 k = nl+1;
912 } else {
913 ta = strtok (fl);
914 if (ta(1) == "*") fl = " "+ta(2);
915 if (ta(1) != "*/") grow, db, fl;
916 }
917 k++;
918 }
919 }
920 if (is_void(dd)) dd = name_list(i);
921 doc_def(i) = ⅆ
922 doc_body(i) = &db;
923 doc_see(i) = &dsa;
924 }
925 }
926
927
928
hdoc_toptemplate(to)929 func hdoc_toptemplate (to) {
930 _hdoc_indexbartags, htags, hfiles, toroot="";
931 // if index.html exists, don't overwrite it - put the template
932 // in index-raw.html instead
933
934 if (f = open(to + "index.html", "r", 1)) {
935 close, f;
936 f = open (to + "index-raw.html", "w");
937 } else {
938 f = open(to + "index.html", "w");
939 }
940 title = "yorick reference";
941 doc="index";
942 hdoc_head, f, title, table=1, toroot="", doc=doc;
943
944
945 wryte, f, "<h1><center>Yorick</center></h1>";
946 _hdoc_skip, f, 2;
947
948 wryte, f, "<blockquote>";
949 wryte, f, "<h1>";
950 wryte, f, "<ul>";
951 ntag = numberof (htags);
952 for (i = 2; i <= ntag; i++) {
953 wryte, f, "<li><a href = " + hfiles(i) + ">" + htags(i) + "</a>";
954 }
955 wryte, f, "</ul></h1>";
956 _hdoc_skip, f, 2;
957 wryte, f, "for a complete local copy of this documentation tree, download one of ";
958 wryte, f, "<pre>";
959 wryte, f, " <a href = ../../ydoc.tgz>ydoc.tgz</a>";
960 wryte, f, " <a href = ../../ydoc.zip>ydoc.zip</a>";
961 wryte, f, "</pre>";
962
963 _hdoc_skip, f, 2;
964
965 wryte, f, "<h2> Other sources of yorick information </h2>";
966 f = f;
967 wryte, f, "<ul>";
968 wryte, f, "<li>";
969 wryte, f, "<a href = http://yorick.sourceforge.net>the official yorick homepage</a>";
970
971 wryte, f, "<li>";
972 wryte, f, "<a href = http://www.maumae.net/yorick/doc/index.php>";
973 wryte, f, "the unofficial yorick homepage</a>";
974
975 wryte, f, "<li>";
976 wryte, f, "the <a href = http://yorick.sourceforge.net/yorickfaq.php>yorick faq</a>";
977 wryte, f, "</ul>";
978
979 wryte, f, "<hrule>";
980 _hdoc_skip, f, 2;
981 wryte, f, "This documentation was generated from the manual, README files, ";
982 wryte, f, "and code documents of Yorick written by David H. Munro. <p>";
983
984 wryte, f, "Yorick is free software, <a href=\"copyright.html\">copyright</a>";
985 wryte, f, "of the Regents of the University of California";
986
987 wryte, f, "<hrule>";
988
989 hdoc_tail, f, title, table=1, toroot="", doc=doc;
990
991 f = open (to + "copyright.html", "w");
992 title = "yorick copyright";
993 hdoc_head, f, title, table=1, toroot="";
994 wryte, f, "<center><h1>Yorick</h1></center>";
995 _hdoc_skip, f, 4;
996 _hdoc_copyright, f;
997 hdoc_tail, f, title, table=1, toroot="";
998 }
999
1000
1001
1002
1003 func hdoc_packagelist (from, tags, packinfo=, to=, xref_dir=) {
1004
1005 name_list = tags(1,);
1006 dir_list = tags (2,);
1007
1008 ifiles = _lsm1 (from, ext=".i", to=to);
1009
1010 /* read the first few lines from each file to extract any package
1011 description comments - DOCUMENT comments preceding the first
1012 function definition */
1013
1014 n = numberof (ifiles);
1015 filedoc = array (string, 3, n);
1016 for (i = 1; i <= n; i++) {
1017 fnm = ifiles(i);
1018 name= [".", fnm];
1019 do {
1020 rtdir = name(1);
1021 rtfnm = name(2);
1022 name= strtok(name(2), "/\:");
1023 } while (name(2));
1024 if (strpart(rtfnm, -1:0)==".i") rtfnm= strpart(rtfnm, 1:-2);
1025
1026 filedoc(1,i) = rtdir;
1027 filedoc(2,i) = rtfnm;
1028 doc = "";
1029 f = open (fnm);
1030 count= 10; /* like help_worker function defined in std.i */
1031 done = 0;
1032 while ((line= rdline(f)) && count-- && !done) {
1033 split= strtok(line);
1034 if (!split(1) || split(1) == "func" || split(1) == "extern") done=1;
1035 if (strmatch(line, "/* DOCUMENT")) {
1036 while ((line = rdline(f)) && !done) {
1037 if (strmatch(line, "*/")) {
1038 done = 1;
1039 } else {
1040 doc += line + "<br>";
1041 }
1042 }
1043 }
1044 }
1045 filedoc(3,i) = doc;
1046 close, f;
1047 }
1048
1049
1050 // if a packinfo file was provided, extract name-document pairs
1051 // from it
1052 pkey = [];
1053 ptext = [];
1054 if (!is_void(packinfo)) {
1055 f = open (packinfo, "r");
1056 while ((line = rdline (f))) {
1057 if (strpart(line, 1:1) == ":") {
1058 grow, pkey, [strtrim (strpart (line, 2:strlen(line)))];
1059
1060 about = "";
1061 while ((line = rdline (f)) && strpart(line,1:1) != ":") {
1062 //ss = strtrim (line);
1063 ss = line;
1064 if (ss != "") about += ss;
1065 }
1066 grow, ptext, [about];
1067 backup, f;
1068 }
1069 }
1070 }
1071
1072 if (!is_void(ptext)) {
1073 f = open (to + xref_dir + "packages.html", "w");
1074 title = "Yorick packages";
1075 doc="xref";
1076 hdoc_head, f, title, table=1, doc=doc;
1077
1078 was_entry = 0;
1079 wryte, f, ("<table cellspacing=0 border=0" +
1080 " cellpadding=2 width=100\%>");
1081 nf = numberof(pkey);
1082 wryte, f, "<tr><td width = 40 rowspan = " + swrite(nf+2) + ">";
1083 wryte, f, "</td>";
1084 wryte, f, ("<td colspan = 2> <h3> " + ptext(1) + " </h3>");
1085 wryte, f, "</td></tr>";
1086 for (i=2 ; i<=numberof(pkey) ; i++) {
1087 if (pkey(i)=="newsection") {
1088 //if (i>1) wryte, f, "</table> <br> <br> <br>";
1089 //wryte, f, ("<table cellspacing=0 border=0" +
1090 // " cellpadding=2 width=10\%>");
1091 //nf = where(pkey(i+1:0)=="newsection");
1092 //nf = numberof(nf)? nf(1) : numberof(pkey)+1-i;
1093 //wryte, f, "<tr><td width = 40 rowspan = " + swrite(nf+1) + ">";
1094 //wryte, f, "</td>";
1095 //wryte, f, ("<td colspan = 2> <h3> " + ptext(i) + " </h3>");
1096 //wryte, f, "</td></tr>";
1097 af = " <br> <br><h3> " + ptext(i);
1098 wryte, f, ("<tr><td colspan = 2> " + af + " </h3>");
1099 wryte, f, "</td></tr>";
1100 was_entry = 0;
1101 continue;
1102 } else if (pkey(i)=="newsubsection") {
1103 af = ptext(i);
1104 if (was_entry) af = " <br> <br>"+af;
1105 wryte, f, ("<tr><td colspan = 2><em>" + af +
1106 "</em></td></tr>");
1107 continue;
1108 }
1109 was_entry = 1;
1110
1111 af = pkey(i);
1112 fstr = ("<tr><td valign = top>" +
1113 "<a href = %s-index.html> %s</a> </td>\n");
1114 write, f, format = fstr, af, af;
1115
1116 wryte, f, "<td>";
1117 wryte, f, ptext(i);
1118 wryte, f, "</td>";
1119 wryte, f, "</tr>";
1120 }
1121 wryte, f, "</table> <br> <br> <br>";
1122
1123 hdoc_tail, f, title, table=1, doc=doc;
1124 close, f;
1125 }
1126 }
1127
1128
1129 func hdoc_extract_embedded (template_file,to=) {
1130 /* DOCUMENT hdoc_extract_embedded [,template_file, to=to]
1131
1132 extract documents embedded in the HTML documentation template.
1133
1134 If TEMPLATE_FILE is specified, load this file as a template
1135 first.
1136
1137 A template may have one or two line identical to
1138 "%content%". Everything above the first one is used as a header
1139 (see hdoc_head), everything after the last one as a footer (see
1140 hdoc_tail). Between these two line, it is possible to embed the
1141 content of one or several files. This function extract these
1142 files, setting their header and footer accordingly to the
1143 template.
1144
1145 The definition of each of these files starts with a line of the
1146 form:
1147 %embedded:file_name:doc:toroot%Nice Long Title
1148 and finishes with the beginning of the next embedded file or
1149 with the last %content% line.
1150
1151 The first '%' character must be the first character of the
1152 line. FILE_NAME is the actual filename to which the file will be
1153 extracted (as usual, TO is prepended to FILE_NAME. DOC is used
1154 for %onlydoc:doc% lines (see hdoc_read_template). TOROOT is the
1155 path from FILE_NAME to the root of the documentation tree.
1156
1157 Except for this special first line, each line of the embedded
1158 document is parsed for occurrences of e.g. %title% or %toroot%
1159 using hdoc_parse and written fo FILE_NAME.
1160
1161 SEE ALSO: hdoc_read_template, mktexi2html_init
1162 low level: hdoc_head, hdoc_tail, hdoc_parse
1163 */
1164 if (!is_void(template_file)) hdoc_read_template(template_file);
1165 ind=where(_hdoc_template=="%content%");
1166 if (is_void(to)) to="";
1167 if ((max(ind)-min(ind))<=1) return;
1168 scont=min(ind);
1169 contents=_hdoc_template(scont+1:max(ind)-1);
1170 ind=where(strgrep("^%embedded:",contents)(2,) != -1);
1171 if (numberof(ind)>1) indf=grow(ind(2:0)-1,numberof(contents));
1172 else indf=[numberof(contents)];
1173 for (n=1;n<=numberof(ind);n++) {
1174 col=strfind("%",contents(ind(n)),2)(1);
1175 title=strpart(contents(ind(n)),col+2:0);
1176 control=strpart(contents(ind(n)),2:col);
1177 control=pathsplit(control);
1178 fname=control(2);
1179 fname;
1180 doc=control(3);
1181 toroot=control(4);
1182 f=open(to+fname,"w");
1183 hdoc_head, f, title, table=1, toroot=toroot, doc=doc;
1184 hdoc_parse, f, scont+ind(n)+1:scont+indf(n), toroot=toroot,title=title,doc=doc;
1185 hdoc_tail, f, title, table=1, toroot=toroot, doc=doc;
1186 close, f;
1187 }
1188 }
1189
1190
1191
hdoc_keywordindex(tags,keywords,to,xref_dir)1192 func hdoc_keywordindex (tags, keywords, to, xref_dir) {
1193
1194 // read the list if keywords - assumed to be one per line, with
1195 // nothing else in the file
1196 f = open (keywords);
1197 kwl = [];
1198 while ((line = rdline(f)) != string(0)) {
1199 s = strtrim (line);
1200 if (s != "") grow, kwl, [s];
1201 }
1202 s = sort (kwl);
1203 kwl = kwl(s);
1204
1205 f = open (to + xref_dir + "keywords.html", "w");
1206 doc="xref";
1207 title = "Yorick keyword index";
1208 hdoc_head, f, title, table=1, doc=doc;
1209
1210 wryte, f, ("<table cellspacing=2 border=0" +
1211 " cellpadding=4 width=100\%>");
1212 wryte, f, "<tr>";
1213 for (i = 0; i < 26; i++) {
1214 ch = string (&(char('a' + i)));
1215 w = where (strpart (kwl, 1:1) == ch);
1216 if (!numberof(w)) continue;
1217 wryte, f, "<td>";
1218 wryte, f, "<a href = ../"+xref_dir+"keywords-"+ch+".html>"+ch+"</a>";
1219 wryte, f, "</td>"
1220 }
1221 wryte, f, "</tr></table>";
1222 _hdoc_skip, f, 2;
1223
1224 nw = numberof (kwl);
1225 ncol = 3;
1226 nrow = (nw+ncol-1) / ncol;
1227 wryte, f, ("<table cellspacing=0 border=0" +
1228 " cellpadding=1 width=100\%>");
1229 for (i = 1; i <= nrow; i++) {
1230 wryte, f, "<tr>";
1231 for (j = 1; j <= ncol; j++) {
1232 irc = (j-1) * nrow + i;
1233 if (irc <= nw) {
1234 myw = kwl(irc);
1235 suff = strcase(0, strpart (myw, 1:1));
1236 wryte, f, "<td>";
1237 wryte, f, ("<a href = ../"+xref_dir+"keywords-" + suff +
1238 ".html#" + strcomp(myw) + ">" + myw + "</a>");
1239 wryte, f, "</td>";
1240 } else {
1241 wryte, f, "<td> </td>";
1242 }
1243 }
1244 wryte, f, "</tr>";
1245 }
1246 wryte, f, "</table>";
1247 hdoc_tail, f, title, table=1, doc=doc;
1248 close, f;
1249
1250 for (i = 0; i < 26; i++) {
1251 ch = string (&(char('a' + i)));
1252 w = where (strpart (kwl, 1:1) == ch);
1253 if (!numberof(w)) continue;
1254 fnm = to+xref_dir+"keywords-" + ch + ".html";
1255 if (!quiet) write, format = "\n %s ", fnm;
1256 hdoc_keywordref, fnm, kwl(w), tags, xref_dir;
1257 }
1258 if (!quiet) write, "";
1259 }
1260
1261
1262
hdoc_keywordref(fnm,kwl,tags,xref_dir)1263 func hdoc_keywordref (fnm, kwl, tags, xref_dir) {
1264 name_list = tags(1,);
1265 file_list = tags (3,);
1266 doc_list = tags (6,);
1267
1268 f = open (fnm, "w");
1269 doc="xref";
1270 hdoc_head, f, fnm, table=1, doc=doc;
1271
1272 wryte, f, ("<table cellspacing=2 border=0" +
1273 " cellpadding=2 width=100\%>");
1274 wryte, f, "<tr>";
1275 for (i = 0; i < 26; i++) {
1276 ch = string (&(char(int(*pointer ("a"))(1) + i)));
1277 wryte, f, "<td>";
1278 wryte, f, "<a href = ../"+xref_dir+"keywords-" + ch + ".html>"+ch+"</a>";
1279 wryte, f, "</td>"
1280 }
1281 wryte, f, "</td></tr></table>";
1282 _hdoc_skip, f, 2;
1283
1284 nr = numberof (kwl);
1285 wryte, f, ("<table cellspacing=0 border=0" +
1286 " cellpadding=1 width=100\%>");
1287 for (i = 1; i <= nr; i++) {
1288 myk = kwl(i);
1289 wryte, f, "<tr>";
1290 wryte, f, "<td valign=top width=150><FONT face=\"Arial,Helvetica\"><b>";
1291 wryte, f, "<a name=\""+strcomp(myk)+"\"></a>" + myk;
1292 wryte, f, "</b></FONT></td><td>";
1293
1294 w = where (name_list == myk);
1295 if (numberof (w) > 0) {
1296 defroot = "../"+xref_dir + file_list(w(1));
1297 wryte, f, (" <b><a href=\"" + defroot +
1298 "-doc.html#"+myk + "\">" +
1299 myk + "</a></b> ");
1300 }
1301
1302 rel = array (1, numberof (name_list));
1303 wd = myk;
1304 while ((wd = strtok(wd))(1)) {
1305 rel = (rel & strmatch(doc_list, " " + wd(1) + " ", 1));
1306 wd = wd(2);
1307 }
1308 w = where (rel);
1309 if (numberof (w) > 0) {
1310 nsa = numberof (w);
1311 for (j = 1; j <= nsa; j++) {
1312 ssa = name_list(w(j));
1313 defroot = "../" + xref_dir + file_list(w(j));
1314 wryte, f, (" <a href=\"" + defroot +
1315 "-doc.html#"+ssa + "\">" + ssa + "</a>"+
1316 ((j < nsa) ? ", " : " "));
1317 }
1318 }
1319
1320 wryte, f, "</td></tr>";
1321 }
1322 wryte, f, "</table>";
1323 hdoc_tail, f,fnm, table=1, doc=doc;
1324 close, f;
1325 }
1326
1327
strcomp(s)1328 func strcomp (s) {
1329 a = "";
1330 while ((s = strtok(s))(1)) {
1331 a += s(1);
1332 s = s(2);
1333 }
1334 return a;
1335 }
1336
1337
1338
1339 /* various chunks of html which are used repeatedly */
_hdoc_startbody(f)1340 func _hdoc_startbody (f)
1341 {
1342 wryte, f, "<body text=\"#000000\" bgcolor=\"#ffffff\" link=\"#0000ff\" "+
1343 "vlink=\"#800080\" alink=\"#ff0000\">";
1344 }
1345
1346
1347 /* a simple page can be made with
1348 hdoc_head, f, title;
1349 ... write some html;
1350 hdoc_tail, f, title;
1351
1352 with the 'table' option set, it puts a margin on the left and
1353 the text is put inside a table - the left column is the margin,
1354 the right column contains evverything else. The layout can be
1355 customized using hdoc_read_template().
1356 */
1357
wryte(f,line)1358 func wryte(f, line)
1359 {
1360 write,format="%s\n", f, line;
1361 }
1362
hdoc_read_file(fname,block)1363 func hdoc_read_file(fname,block) {
1364 // returns the content of a text file FNAME in a string array.
1365 // Read BLOCK lines at a time (default=1024).
1366 if (is_void(block)) block=1024;
1367 f=open(fname,"r");
1368 lines=rdline(f,1024);
1369 while (lines(0)) grow,lines,rdline(f,1024);
1370 return lines(where(lines));
1371 }
1372
hdoc_read_template(fname)1373 func hdoc_read_template(fname) {
1374 /* DOCUMENT hdoc_read_template, fname
1375
1376 load an HTML template for htmldoc.i functions.
1377
1378 FNAME is the name of an HTML file, from which the layout of the
1379 documentation (navigation bars etc.) will be determined.
1380
1381 The functions in htmldoc.i treat certain strings in the template
1382 in a special way. The first few of them must e alone on the
1383 line, wihtout heading or trailing blank:
1384
1385 Either one or two lines must contain exactly the text
1386 "%content%". The content of each page will be placed there,
1387 replacing anything between the first and last line equal to
1388 "%content%". The space in-between can be used to embed
1389 documents, see hdoc_extract_embedded for details.
1390
1391 %startbody% will be replaced using _hdoc_startbody. This
1392 special line should be used at most once.
1393
1394 %indexbar% produces a simple index bar using _hdoc_indexbar.
1395
1396 %skip% skips a line (replaced with " <br>").
1397
1398 Certain patterns are recognized when they are found at the
1399 beginning of a line:
1400
1401 %onlydoc:doc% where DOC is a short document ID: the remaining
1402 of the line will appear only in files pertaining to the
1403 document DOC. Certain IDs are predefined: "index" for the main
1404 index and "xref" for most of the pages produced by
1405 mkhtmldoc. In addition, "manual" is used for the Yorick Manual
1406 (see mktexi2html_init) and "qref" is reserved for the
1407 reference card. You can use other IDs for use e.g. with your
1408 custom embedded documents (see hdoc_extract_embedded).
1409
1410 %embedded:....% is used to define embedded documents, see
1411 hdoc_extract_embedded.
1412
1413 Finally, a few patterns are recognized anywhere in the document:
1414
1415 %title% is replaced with the (long) document title. It should
1416 probably be used at least once, between <title> and </title>.
1417
1418 %toroot% is replaced with the path from the current file to
1419 the HTML root. It is often "../" and sometimes empty.
1420
1421 SEE ALSO: hdoc_extract_embedded, mktexi2html_init
1422 */
1423 extern _hdoc_template;
1424 _hdoc_template=hdoc_read_file(fname);
1425 }
1426
1427 extern _hdoc_template;
1428 _hdoc_template=
1429 ["<html> <head> <title>",
1430 "%title%",
1431 "</title> </head>",
1432 "%startbody%",
1433 "<TABLE border=\"0\" cellpadding=\"5\" cellspacing=\"0\" width=\"100%\">",
1434 "<TR><TD valign=\"TOP\" width=\"150\" bgcolor=\"#bbddff\"><BR>",
1435 "<IMG src=\"../images/ybanng.jpg\" border=\"0\" hspace=\"0\" vspace=\"0\"",
1436 " alt=\"yorick banner\">",
1437 " <FONT face=\"Arial,Helvetica\">",
1438 " <P><B><A href=\"../index.html\">Home</A></B></P>",
1439 " <P><B><A href=\"../manual/yorick.html\">Manual</A></B></P>",
1440 " <P><B><A href=\"../html_xref/packages.html\">Packages</A></B></P>",
1441 " <P><B><A href=\"../html_xref/global-index.html\">Global Index</A></B></P>",
1442 " <P><B><A href=\"../html_xref/keywords.html\">Keywords</A></B></P>",
1443 " <P><B><A href=\"../refcard/index.html\">Quick Reference</A></B></P>",
1444 " </FONT>",
1445 "</TD><TD valign=\"TOP\">",
1446 "%content%",
1447 "</td></tr>",
1448 "</table>",
1449 " <br>",
1450 " <br>",
1451 " <br>",
1452 "</body>",
1453 "</html>"];
1454
1455 func hdoc_parse (g, spec, toroot=,title=,doc=,text=) {
1456 /* DOCUMENT hdoc_parse, g, spec, title=title [, toroot=toroot, doc=docid, text=text]
1457
1458 Parse lines specified by index specification SPEC from the
1459 string array TEXT (defaults to currently loaded template) write
1460 them to file stream G.
1461
1462 TITLE has no default and must be set, TOROOT defaults to "../",
1463 DOC is the doc ID for %onlydoc:doc% matching: a line starting
1464 with "%onlydoc:line_doc_id" will be output only if LINE_DOC_ID
1465 == DOCID.
1466
1467 This function implements some of the special strings detailed in
1468 hdoc_read_template: %startbody%, %indexbar%, %skip%,
1469 %onlydoc:...%, %title% and %toroot%.
1470
1471 SEE ALSO: hdoc_read_template
1472 */
1473 if (is_void(toroot)) toroot = "../";
1474 if (is_void(doc)) doc = "";
1475 if (is_void(text)) lines=_hdoc_template(spec);
1476 else lines=text(spec);
1477 for (i=1;i<=numberof(lines);i++) {
1478 line=lines(i);
1479 if (line=="%startbody%") _hdoc_startbody, g;
1480 else {
1481 if (line=="%indexbar%") _hdoc_indexbar, g;
1482 else {
1483 if (line=="%skip%") _hdoc_skip, g, 1;
1484 else {
1485 if (strgrep("^%onlydoc:",line)(2)!=-1) {
1486 if (strgrep("^%onlydoc:"+doc+"%",line)(2)==-1) continue;
1487 line=strpart(line,strgrep("^%onlydoc:"+doc+"%",line)(2)+1:0);
1488 }
1489 line=streplace(line,strgrep("%title%",line),title);
1490 line=streplace(line,strgrep("%toroot%",line),toroot);
1491 wryte, g, line;
1492 }
1493 }
1494 }
1495 }
1496 }
1497
1498 func hdoc_head (g, title, table=, toroot=, doc=) {
1499 if (table) {
1500 last_line=min(where(_hdoc_template=="%content%"))-1;
1501 hdoc_parse, g, 1:last_line, toroot=toroot, title=title, doc=doc;
1502 } else {
1503 wryte, g, "<html> <head> <title>";
1504 wryte, g, title;
1505 wryte, g, "</title>";
1506 _hdoc_startbody, g;
1507 _hdoc_indexbar, g;
1508 _hdoc_skip, g, 3;
1509 }
1510 }
1511
1512 func hdoc_tail (g, title, table=, toroot=, doc=) {
1513 if (do_disclaimer) {
1514 wryte, g, "<P><HR><a href=\"http://www.llnl.gov/disclaimer.html\">";
1515 wryte, g, "<small>LLNL Disclaimers</small></a></P>";
1516 }
1517 if (table) {
1518 first_line=max(where(_hdoc_template=="%content%"))+1;
1519 hdoc_parse, g, first_line:0, toroot=toroot, title=title, doc=doc;
1520 } else {
1521 _hdoc_skip, g, 3;
1522 wryte, g, "</body>";
1523 wryte, g, "</html>";
1524 }
1525 }
1526
1527 func hdoc_headtail (src, dest, rm, title= , toroot=, doc=) {
1528 /* DOCUMENT hdoc_headtail, src, dest [, rm, title= , toroot=, doc=]
1529
1530 Adds HTML header and footer specified by currently loaded
1531 template to file SRC. Saves the result to DEST. Removes SRC
1532 unless "rm=0" is specified.
1533
1534 */
1535 if (is_void(rm)) rm=1;
1536 g = open (dest, "w");
1537 if (is_void(title)) title = dest;
1538 hdoc_head, g, title, table=1, toroot=toroot, doc=doc;
1539 line = hdoc_read_file(src);
1540 hdoc_parse, g, 1:0, text=line, toroot=toroot, doc=doc, title=title;
1541 hdoc_tail, g, title, table=1, toroot=toroot, doc=doc;
1542 close, g;
1543 if (rm) remove, src;
1544 }
1545
1546
_hdoc_skip(f,n)1547 func _hdoc_skip (f, n) {
1548 if (n) {
1549 for (i = 1; i <= n; i++) wryte, f, " <br>";
1550 } else {
1551 wryte, f, " <br> <br>";
1552 wryte, f, " <br> <br>";
1553 }
1554 }
1555
1556
1557
1558 func _hdoc_indexbartags (&htags, &hfiles, toroot=) {
1559 // this (obsolete) routine should be customized.
1560 if (is_void(toroot)) toroot="../";
1561 htags = ["home", "manual", "packages", "index", "keywords"];
1562 hfiles = toroot+["index.html", "manual/yorick.html",
1563 "html_xref/packages.html",
1564 "html_xref/global-index.html", "html_xref/keywords.html"];
1565 }
1566
_hdoc_indexbar(f)1567 func _hdoc_indexbar(f) {
1568 // this (obsolete) routine should be customized.
1569 _hdoc_indexbartags, htags, hfiles;
1570 hbg1 = "\"#bbddff\"";
1571 wryte, f, "<table border=0 cellpadding=5 cellspacing=0 width = 100\%>";
1572 wryte, f, "<tr>";
1573 _hdoc_margintable, f;
1574
1575 for (i = 1; i <= numberof (htags); i++) {
1576 wryte, f, "<td valign=\"TOP\" width=\"150\" bgcolor=" + hbg1 + ">";
1577 wryte, f, "<center>";
1578 wryte, f, "<a href = " + hfiles(i) + ">" + htags(i) + "</a>";
1579 wryte, f, "</center>";
1580 wryte, f, "</td>";
1581 }
1582 wryte, f, "</tr>";
1583 wryte, f, "</table>";
1584 }
1585
1586
_hdoc_margintable(f)1587 func _hdoc_margintable (f) {
1588 /* the best way to make a cell in a table of a particular width, which
1589 doesn't stretch or shrink depending on the size of the browser
1590 window seems to be to put a table inside the cell */
1591 wryte, f, "<td><table width = 150><tr>"+
1592 "<td valign=\"TOP\" width=\"150\" bgcolor=\"#bbddff\">";
1593 wryte, f, "<pre> </pre>";
1594 wryte, f, "</td></tr></table></td>";
1595 }
1596
1597
1598
1599 func hdoc_wrap (dir, quiet=) {
1600 tmpfile = "hdoc_tmp.tmp";
1601 fnms = _lsm1 (dir, ext = ".html");
1602 nfls = numberof (fnms);
1603 for (i = 1; i <= nfls; i++) {
1604 f = open (fnms(i));
1605 g = open ("hdoc_tmp.tmp", "w");
1606
1607 done = 0;
1608 gotbody = 0;
1609 while ((line = rdline(f)) && !done) {
1610 if (strmatch (line, "/body", 1)) {
1611 done = 1;
1612 } else {
1613 if (gotbody) {
1614 wryte, g, line;
1615 } else {
1616 if (strmatch (line, "<body", 1)) gotbody = 1;
1617 }
1618 }
1619 }
1620 close, g;
1621 close, f;
1622
1623 if (!gotbody) {
1624 if (!quiet) write, format = "html file %s contains no <BODY> statement ", fnm;
1625 if (!quiet) write, "- nothing done";
1626
1627 } else {
1628 hdoc_headtail, tmpfile, fnms(i);
1629 }
1630 }
1631 }
1632
1633
_hdoc_copyright(f)1634 func _hdoc_copyright (f) {
1635 wryte, f, "Copyright 1994. The Regents of the University of California";
1636 wryte, f, "All rights reserved";
1637 wryte, f, "<br><p>";
1638
1639 wryte, f, "Permission to use, copy, modify, and distribute this software ";
1640 wryte, f, "for any purpose without fee is hereby granted, provided that ";
1641 wryte, f, "this entire notice is included in all copies of any software ";
1642 wryte, f, "which is or includes a copy or modification of this software ";
1643 wryte, f, "and in all copies of the supporting documentation for such ";
1644 wryte, f, " software.";
1645 wryte, f, "<br><p>";
1646
1647 wryte, f, "This work was produced at the University of California, ";
1648 wryte, f, "Lawrence Livermore National Laboratory under contract ";
1649 wryte, f, "no. W-7405-ENG-48 between the U.S. Department of Energy ";
1650 wryte, f, "and The Regents of the University of California for the ";
1651 wryte, f, "operation of UC LLNL. ";
1652
1653 wryte, f, "<br><p>";
1654 wryte, f, " DISCLAIMER ";
1655 wryte, f, "<br><p>";
1656
1657 wryte, f, " This software was prepared as an account of work sponsored by an ";
1658 wryte, f, "agency of the United States Government. Neither the United States ";
1659 wryte, f, "Government nor the University of California nor any of their ";
1660 wryte, f, "employees, makes any warranty, express or implied, or assumes any ";
1661 wryte, f, "liability or responsibility for the accuracy, completeness, or ";
1662 wryte, f, "usefulness of any information, apparatus, product, or process ";
1663 wryte, f, "disclosed, or represents that its use would not infringe ";
1664 wryte, f, "privately-owned rights. Reference herein to any specific commercial ";
1665 wryte, f, "products, process, or service by trade name, trademark, manufacturer, ";
1666 wryte, f, "or otherwise, does not necessarily constitute or imply its ";
1667 wryte, f, "endorsement, recommendation, or favoring by the United States ";
1668 wryte, f, "Government or the University of California. The views and opinions of ";
1669 wryte, f, "authors expressed herein do not necessarily state or reflect those of ";
1670 wryte, f, "the United States Government or the University of California, and ";
1671 wryte, f, "shall not be used for advertising or product endorsement purposes. ";
1672
1673 }
1674
mktexi2html_init(infile,outfile)1675 func mktexi2html_init (infile,outfile) {
1676 /* DOCUMENT mktexi2html_init [, infile, outfile]
1677
1678 create a TeXi2HTML init file using the currently loaded HTML
1679 template (see hdoc_read_template).
1680
1681 mktexi2html_init will parse the hdoc template to fill these
1682 TeXi2HTML variables (see "info texi2html"):
1683 $EXTRA_HEAD, $AFTER_BODY_OPEN, $PRE_BODY_CLOSE.
1684
1685 mktexi2html_init needs an input file INFILE (default:
1686 "texi2html.tpl"), which is a complete, valid TeXi2HTML init file
1687 except that these three variables are defined with the following
1688 syntax:
1689
1690 $VARIABLE = <<'EOF';
1691 %variable%
1692 EOF
1693
1694 Therefore, OUTFILE is a copy of INFILE with the three special
1695 lines
1696 %extra_head%
1697 %after_body_open%
1698 %pre_body_close%
1699 have been replaced with parts of the hdoc template. These three
1700 lines must appear in that order.
1701
1702 mktexi2html_init works by detecting certain strings in the hdoc
1703 template.
1704
1705 EXTRA_HEAD is everything between </TITLE> and </HEAD>
1706
1707 AFTER_BODY_OPEN is everything between either %startbody% or
1708 <BODY ...>and %content%
1709
1710 PRE_BODY_CLOSE is everything between the last %content% and
1711 </BODY>
1712
1713 The case is not important for the HTML tags (but it is for the
1714 %...% special strings). The HTML tags must be alone on their
1715 line as any leading or trailing text will not be output (see
1716 below for a PHP trick, though). The entire <BODY ... > tag must
1717 be on a single line, but can contain complex definitions (these
1718 definitions will be ignored).
1719
1720 If your template does not contain these strings, for instance
1721 because your HTML code is really PHP, you can try to put
1722 something like "%onlydoc:never%</TITLE>" where you would like
1723 them to be (see hdoc_read_template). As long as you dont declare
1724 any embedded document with "never" as a short doc ID, these
1725 lines will never appear in any of the produced documentation,
1726
1727 Once mktexi2html_init has determined which lines to put in which
1728 variable, it does parse them for replacing the special strings
1729 such as %title%, %toroot% and %onlydoc:doc%. mktexi2html_init is
1730 meant for typesetting the Yorick Manual, so the doc ID it uses
1731 is "manual". Therefore, lines beginning with "%onlydoc:" will
1732 not be output, unless they actually start with
1733 "%onlydoc:manual%".
1734
1735 SEE ALSO: hdoc_read_template, hdoc_extract_embedded
1736 */
1737 if (is_void(infile)) infile="texi2html.tpl";
1738 if (is_void(outfile)) outfile="texi2html.init";
1739 toroot="../";
1740 title="The Yorick Manual";
1741 doc="manual";
1742 in=hdoc_read_file(infile);
1743 f = open (outfile, "w");
1744
1745 wryte, f, in(1:min(where(in=="%extra_head%"))-1);
1746 // EXTA_HEAD is everything between </TITLE> and </head>
1747 // find </TITLE>
1748 junk = strfind("</title>",_hdoc_template,case=0);
1749 linea = min (where(junk(2,) != -1));
1750 //columna = junk(2, linea);
1751 // find </head>
1752 junk = strfind("</head>",_hdoc_template,case=0);
1753 lineb = min (where(junk(2,) != -1));
1754 //columnb = junk(1, lineb);
1755 // write the end of line A, everything between line A and B, and the beginning of line B.
1756 // Warning: the bits of liine A and B are not parsed for toroot.
1757 //if (linea < lineb) {
1758 //if (columna < strlen(_hdoc_template(linea))) wryte, f, strpart(_hdoc_template(linea), columna+1:0);
1759 for (i=linea+1; i < lineb; i++) hdoc_parse, f, i, toroot=toroot, title=title, doc=doc;
1760 //if (columnb > 1) wryte, f, strpart(_hdoc_template(lineb), 1:columnb-1);
1761 //} else {
1762 // if (columna+1 < columnb) wryte, f, strpart(_hdoc_template(linea), columna+1:columnb-1);
1763 //}
1764
1765 wryte, f, in(min(where(in=="%extra_head%"))+1:min(where(in=="%after_body_open%"))-1);
1766 // AFTER_BODY_OPEN is everything between %startbody% and %content%
1767 if (anyof(_hdoc_template == "%startbody%" )) linea = min ( where ( _hdoc_template == "%startbody%" ) );
1768 else linea = min ( where ( strmatch(_hdoc_template, "<body", 1 ) ));
1769 lineb = min ( where ( _hdoc_template == "%content%" ) );
1770 for (i=linea+1; i < lineb; i++) hdoc_parse, f, i, toroot=toroot, title=title, doc=doc;
1771
1772 wryte, f, in(min(where(in=="%after_body_open%"))+1:min(where(in=="%pre_body_close%"))-1);
1773 // PRE_BODY_CLOSE is everything between %content% and </BODY>
1774 linea = max ( where ( _hdoc_template == "%content%" ) ) ;
1775 junk = strfind("</body>",_hdoc_template,case=0);
1776 lineb = min (where(junk(2,) != -1));
1777 //columnb = junk(1, lineb);
1778 for (i=linea+1; i < lineb; i++) hdoc_parse, f, i, toroot=toroot, title=title, doc=doc;
1779 //if (columnb > 1) wryte, f, strpart(_hdoc_template(lineb), 1:columnb-1);
1780
1781 wryte, f, in(min(where(in=="%pre_body_close%"))+1:0);
1782
1783 close, f;
1784 }
1785
1786 if (batch()) {
1787 args = get_argv();
1788 junk=args(where(strpart(args,1:1)!="-"));
1789 do_disclaimer = (numberof(junk)==2 && junk(2)=="llnl");
1790 if (anyof(strpart(args,1:1)=="-")) {
1791 junk=args(where(strpart(args,1:1)=="-"));
1792 for (i=1;i<=numberof(junk);i++) {
1793 if (junk(i)=="--quiet" | junk(i)=="-q")
1794 quiet=1;
1795 else if (junk(i)=="--nosrc" | junk(i)=="-s")
1796 nosrc=1;
1797 else if (junk(i)=="--nofunc" | junk(i)=="-f")
1798 nofunc=1;
1799 else if (junk(i)=="--llnl" | junk(i)=="-l")
1800 do_disclaimer=1;
1801 else if (strpart(junk(i),1:strlen("--warn="))=="--warn=")
1802 warn=strpart(junk(i),strlen("--warn=")+1:0);
1803 else if (strpart(junk(i),1:strlen("--from="))=="--from=")
1804 from=pathsplit(strpart(junk(i),strlen("--from=")+1:0),delim=":");
1805 else if (strpart(junk(i),1:strlen("--to="))=="--to=")
1806 to=strpart(junk(i),strlen("--to=")+1:0);
1807 else if (strpart(junk(i),1:strlen("--template="))=="--template=")
1808 template=strpart(junk(i),strlen("--template=")+1:0);
1809 else if (strpart(junk(i),1:strlen("--keywords="))=="--keywords=")
1810 keywords=strpart(junk(i),strlen("--keywords=")+1:0);
1811 else if (strpart(junk(i),1:strlen("--aliases="))=="--aliases=")
1812 aliases=strpart(junk(i),strlen("--aliases=")+1:0);
1813 else if (strpart(junk(i),1:strlen("--packinfo="))=="--packinfo=")
1814 packinfo=strpart(junk(i),strlen("--packinfo=")+1:0);
1815 else if (strpart(junk(i),1:strlen("--xref-dir="))=="--xref-dir=")
1816 xref_dir=strpart(junk(i),strlen("--xref-dir=")+1:0);
1817 else
1818 continue;
1819 }
1820 }
1821 if (!quiet) {
1822 if (!do_disclaimer) write, "creating yorick html document set";
1823 else write, "creating yorick html documents set (LLNL version)";
1824 }
1825 mkhtmldoc,from=from, to=to, keywords=keywords, packinfo=packinfo,
1826 template=template, aliases=aliases, nosrc=nosrc, nofunc=nofunc,
1827 warn=warn, quiet=quiet, xref_dir=xref_dir;
1828 }
1829