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 &lt; and &gt;
524       while (strmatch (line, ">")) {
525 	 split = strtok (line, ">");
526 	 line = split(1) + "&gt;" + split(2);
527       }
528       while (strmatch (line, "<")) {
529 	 split = strtok (line, "<");
530 	 line = split(1) + "&lt;" + 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) ? ", &nbsp; " : " &nbsp; "));
829 	    } else {
830 	       write, f, (ssa + ((k < nsa) ? ", &nbsp; " : " &nbsp; "));
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) = &dd;
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> &nbsp;<br>&nbsp;<br>&nbsp;<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 = "&nbsp;<br>&nbsp;<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 = "&nbsp;<br>&nbsp;<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> &nbsp;<br>&nbsp;<br>&nbsp;<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> &nbsp;&nbsp;&nbsp;");
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) ? ", &nbsp; " : " &nbsp; "));
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 "&nbsp;<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  "&nbsp;<br>",
1450  "&nbsp;<br>",
1451  "&nbsp;<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, "&nbsp;<br>";
1550    } else {
1551       wryte, f, "&nbsp;<br>&nbsp;<br>";
1552       wryte, f, "&nbsp;<br>&nbsp;<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