diff options
author | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
---|---|---|
committer | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
commit | 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch) | |
tree | 4464880c571602d54f6ae114729bf62a89518057 /pkg/system | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/system')
194 files changed, 23532 insertions, 0 deletions
diff --git a/pkg/system/README b/pkg/system/README new file mode 100644 index 00000000..5567ce8b --- /dev/null +++ b/pkg/system/README @@ -0,0 +1,5 @@ + +This directory contains all CL-callable routines for the "system" package. +Included are routines for file manipulation, date and time, device access, +and so on. Certain of these routines are machine dependent; search for +the string "MACHDEP" to identify such files. diff --git a/pkg/system/bench.cl b/pkg/system/bench.cl new file mode 100644 index 00000000..e8de1036 --- /dev/null +++ b/pkg/system/bench.cl @@ -0,0 +1,143 @@ +#{ +# BENCH.CL +# +# A rough benchmark script for testing IRAF on different systems. +# + +procedure bench () + +begin + + string dum1, dum2, time1, time2 + real t0, t1, t2, t3, t4, tf, tsec, tmake, tproc, tcomb, tmed + + + # Load the needed tasks (if necessary) BEFORE timer starts. + if (!defpac("noao.artdata")) { + artdata + } + + reset imdir = "HDR$pix/" + + + print(" ") + time() | scan (dum1, time1, dum2) + print("Bench started at ",time1) + time() | scan (dum1, t0, dum2) + print(" ") + + print ("=====> Making images...") + print (" Making zero...") + mknoise ("zimage", + output="", title="zero image", ncols=2048, nlines=2048, + header="artdata$stdheader.dat", background=0., gain=1., rdnoise=2., + poisson=no, seed=1, cosrays="", ncosrays=100, energy=30000., radius=0.5, + pa=0., comments=yes) + + print (" Making flat...") + mknoise ("fimage", + output="", title="flat image", ncols=2048, nlines=2048, + header="artdata$stdheader.dat", background=30000., gain=1., rdnoise=1., + poisson=no, seed=1, cosrays="", ncosrays=0, energy=30000., radius=0.5, + pa=0., comments=yes) + + print (" Making 3 objs...") + mknoise ("o1image", + output="", title="obj image", ncols=2048, nlines=2048, + header="artdata$stdheader.dat", background=500., gain=1., rdnoise=5., + poisson=no, seed=1, cosrays="", ncosrays=100, energy=30000., radius=0.5, + pa=0., comments=yes) + + mknoise ("o2image", + output="", title="obj image", ncols=2048, nlines=2048, + header="artdata$stdheader.dat", background=500., gain=1., rdnoise=5., + poisson=no, seed=1, cosrays="", ncosrays=100, energy=30000., radius=0.5, + pa=0., comments=yes) + + mknoise ("o3image", + output="", title="obj image", ncols=2048, nlines=2048, + header="artdata$stdheader.dat", background=500., gain=1., rdnoise=5., + poisson=no, seed=1, cosrays="", ncosrays=100, energy=30000., radius=0.5, + pa=0., comments=yes) + + time() | scan (dum1, t1, dum2) + + + # PROC SIMULATION SECTION + # + # Flat normalization is usually done realtime in memory in ccdproc, + # but writing the image might be similar to the temp image in ccdproc + + print(" ") + print(" ") + print ("=====> Normalizing flat...") + imarith ("fimage", + "/", "30000.", "fimage", title="", divzero=1., hparams="", pixtype="", + calctype="", verbose=yes, noact=no) + + print(" ") + print(" ") + print ("=====> Subtracting zero from 3 images...") + imarith ("o1image,o2image,o3image", + "-", "zimage", "o1image,o2image,o3image", title="", + divzero=0., hparams="", pixtype="", calctype="", verbose=yes, noact=no) + + print(" ") + print(" ") + print ("=====> Dividing flat into 3 images...") + imarith ("o1image,o2image,o3image", + "/", "fimage", "o1image,o2image,o3image", title="", divzero=0., + hparams="", pixtype="", calctype="", verbose=yes, noact=no) + + # END of PROC SIMULATION SECTION + + time() | scan (dum1, t2, dum2) + + print(" ") + print(" ") + printf ("=====> Combining 3 images...") + imcombine ("o1image,o2image,o3image", + "ocimage", sigma="", logfile="STDOUT", combine="average", + reject="crreject", project=no, outtype="real", offsets="none", + masktype="none", maskvalue=0., blank=0., scale="none", zero="none", + weight="none", statsec="", expname="", lthreshold=INDEF, + hthreshold=INDEF, nlow=1, nhigh=1, nkeep=1, mclip=yes, lsigma=3., + hsigma=3., rdnoise="5", gain="1", snoise="0.", sigscale=0.1, + pclip=-0.5, grow=0) + + time() | scan (dum1, t3, dum2) + + print(" ") + print(" ") + print ("=====> Median filtering image...") + median ("ocimage", + "omimage", 9, 9, zloreject=INDEF, zhireject=INDEF, boundary="nearest", + constant=0., verbose=yes) + + time() | scan (dum1, t4, dum2) + + print(" ") + print ("=====> Deleting all images...") + imdel ("o1image,o2image,o3image,ocimage,omimage,zimage,fimage", + yes, verify=no, default_acti=yes) + + time() | scan (dum1, tf, dum2) + time() | scan (dum1, time2, dum2) + print(" ") + print("Bench started at ",time1) + print("Bench ended at ",time2) + print(" ") + + tsec = (tf - t0) * 3600. + tmake = (t1 - t0) * 3600. + tproc = (t2 - t1) * 3600. + tcomb = (t3 - t2) * 3600. + tmed = (t4 - t3) * 3600. + + + printf ("Total execution time = %7.1f seconds\n",tsec) + printf (" Total time Make 5 imgs Proc 3 imgs Combine 3 imgs Median 1 img\n") + printf (" %7.1f %7.1f %7.1f %7.1f %7.1f\n", + tsec, tmake, tproc, tcomb, tmed) + +end diff --git a/pkg/system/chkupdate.par b/pkg/system/chkupdate.par new file mode 100644 index 00000000..f6800a8d --- /dev/null +++ b/pkg/system/chkupdate.par @@ -0,0 +1,5 @@ +interval,i,h,0,,,Days between update checks (-1 to disable or 0 for always) +ref_file,s,h,"iraf$.release_date",,,reference file for times +release,s,h,)_.release,,,IRAF release version +baseurl,s,h,"http://iraf.noao.edu/ftp",,,base URL to release timestamp directory +verbose,b,h,yes,,,verbose output flag diff --git a/pkg/system/chkupdate.x b/pkg/system/chkupdate.x new file mode 100644 index 00000000..a45c6d44 --- /dev/null +++ b/pkg/system/chkupdate.x @@ -0,0 +1,178 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <fio.h> +include <fset.h> +include <finfo.h> +include <time.h> +include <syserr.h> + + + +# CHKUPDATE -- Check to see whether the current IRAF system is up to date +# relative to what's available on the NOAO server. + + +procedure t_chkupdate () + + +char version[SZ_FNAME], baseurl[SZ_FNAME], chkfile[SZ_LINE] +char netpath[SZ_LINE], arch[SZ_FNAME], tmpfile[SZ_FNAME] +char host[SZ_LINE], ref_file[SZ_LINE], release[SZ_LINE] +char buf[SZ_LINE] +pointer reply +bool verbose +long last, reldate, ndays, info[LEN_FINFO] +int ip, op, fd, nread, interval, tm[LEN_TMSTRUCT] + +int clgeti(), envgets(), access(), open(), url_get() +int strlen(), getline(), finfo() +bool clgetb() +long clktime(), ctol() + +define done_ 99 + +begin + # Initialize strings. + call aclrc (baseurl, SZ_LINE) + call aclrc (release, SZ_LINE) + call aclrc (ref_file, SZ_LINE) + call aclrc (chkfile, SZ_LINE) + call aclrc (tmpfile, SZ_FNAME) + call aclrc (arch, SZ_FNAME) + call aclrc (version, SZ_FNAME) + + call strcpy ("uparm$update", chkfile, SZ_LINE) + call mktemp ("tmp$url", tmpfile, SZ_FNAME) + if (envgets ("arch", arch, SZ_FNAME) == ERR) { + if (verbose) + call eprintf ("Error: cannot get architecture.\n") + return + } + + + # Get the task parameters. + call clgstr ("ref_file", ref_file, SZ_LINE) + call clgstr ("release", release, SZ_LINE) + call clgstr ("baseurl", baseurl, SZ_FNAME) + verbose = clgetb ("verbose") + interval = clgeti ("interval") + + + # See whether we're doing an update check. If the interval is less + # than zero it means the update is disabled. A zero value means we + # check at each login, otherwise we've specified the number of days + # since our last check. The check time is kept in the uparm$update + # file which is created the first time we run, and updated after each + # check. + if (interval < 0) { + return # nothing to do + + } else if (interval >= 0) { + # See if current time is more than N interval days since last + # check. + if (access (chkfile, 0, 0) == NO) { + # No update file found, create one and check for updates. + fd = open (chkfile, NEW_FILE, TEXT_FILE) + call fprintf (fd, "%d\n") + call pargl (clktime (0)) + call close (fd) + } else { + call aclrc (buf, SZ_LINE) + fd = open (chkfile, READ_ONLY, TEXT_FILE) + if (getline (fd, buf) != EOF) { + ip = 1 + if (ctol (buf, ip, last) > 0) { + ndays = (clktime(0) - last) / 86400 + if (ndays < interval) { + call close (fd) + return # too recent + } + } + } + call close (fd) + } + } + + + # Transform the CL version string to one we can use in the URL. + version[1] = 'v' ; op = 2 + for (ip=1; release[ip] != NULL && ip < SZ_LINE; ip=ip+1) { + if (release[ip] != '.') { + version[op] = release[ip] + op = op + 1 + } + } + + # Create the URL to the release timestamp file. + call sprintf (netpath, SZ_LINE, "%s/%s/releases/%s") + call pargstr (baseurl) + call pargstr (version) + call pargstr (arch[2]) + + + # Access the URL and get the reply. + call calloc (reply, SZ_LINE, TY_CHAR) + + if (url_get (netpath, tmpfile, reply) > 0) { + call aclrc (buf, SZ_LINE) + fd = open (tmpfile, READ_ONLY, TEXT_FILE) + if (getline (fd, buf) != EOF) { + ip = 1 + if (ctol (buf, ip, reldate) > 0) { + if (access (ref_file, 0, 0) == NO) { + if (verbose) + call eprintf ("Error: no release file\n") + call close (fd) + goto done_ + } + if (access (ref_file, 0, 0) == YES && + finfo (ref_file, info) != ERR) { + + call brktime (reldate, tm) + call printf (" *** Checking update status... ") + + # Add a 1-day offset to the release date to ensure + # the ref_file timestamp is less than the URL file, + # both of which are created during the packaging of + # a release. This avoids a case where we would + # *always* get an update notification. + reldate = reldate + 86400 + + if (FI_CTIME(info) < reldate) { + + call aclrc (release, SZ_LINE) + call strcpy (buf[ip+1], release, SZ_LINE) + release[strlen(release)] = NULL + + call printf ( + "IRAF %s update available on %d/%d/%d\n") + call pargstr (release) + call pargi (TM_MONTH(tm)) + call pargi (TM_MDAY(tm)) + call pargi (TM_YEAR(tm)) + call close (fd) + goto done_ + } else { + call printf ("Your IRAF system is up to date\n") + } + } + } + } + call close (fd) + + } else + ; # got a HTTP error code, quit + + + # Write the current check time to the update file to reset the + # interval. + fd = open (chkfile, READ_WRITE, TEXT_FILE) + call fprintf (fd, "%d\n") + call pargl (clktime (0)) + call close (fd) + + # Clean up. +done_ call mfree (reply, TY_CHAR) + if (access (tmpfile, 0, 0) == YES) + call delete (tmpfile) +end diff --git a/pkg/system/cmdstr.par b/pkg/system/cmdstr.par new file mode 100644 index 00000000..ba046633 --- /dev/null +++ b/pkg/system/cmdstr.par @@ -0,0 +1,2 @@ +task,s,a,,,,Task name +hidden,b,h,no,,,Print hidden parameters diff --git a/pkg/system/cmdstr.x b/pkg/system/cmdstr.x new file mode 100644 index 00000000..be4e965e --- /dev/null +++ b/pkg/system/cmdstr.x @@ -0,0 +1,157 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> + +define SZ_CMDSTR 4096 + +# CMDSTR -- Read the output of LPARAM and format a command string giving +# the values of all parameters. + +procedure t_cmdstr() + +bool hidden, hparam +pointer sp, ltask, pname, ibuf, obuf, ip, op, pp, nl, last +int getline(), gstrcpy(), strncmp() +bool clgetb() + +begin + call smark (sp) + call salloc (ltask, SZ_FNAME, TY_CHAR) + call salloc (pname, SZ_FNAME, TY_CHAR) + call salloc (ibuf, SZ_LINE, TY_CHAR) + call salloc (obuf, SZ_CMDSTR, TY_CHAR) + + # Get the task name and whether to print hidden parameters. + call clgstr ("task", Memc[ltask], SZ_FNAME) + hidden = clgetb ("hidden") + + op = obuf + gstrcpy (Memc[ltask], Memc[obuf], SZ_CMDSTR) + Memc[op] = ' '; op = op + 1 + Memc[op] = '('; op = op + 1 + + last = NULL + nl = NULL + + while (getline (STDIN, Memc[ibuf]) != EOF) { + ip = ibuf + + # Skip white space. + while (IS_WHITE (Memc[ip])) + ip = ip + 1 + + # Check if the parameter is hidden and skip it if desired. + if (Memc[ip] == '(') { + if (!hidden) + next + hparam = true + ip = ip + 1 + } else + hparam = false + + # Check if parameter name is "mode" and skip it. + if (strncmp (Memc[ip], "mode =", 6) == 0) + next + + # Copy or skip parameter name. + pp = pname + while (!IS_WHITE (Memc[ip])) { + if (hparam) { + Memc[op] = Memc[ip] + op = op + 1 + } + Memc[pp] = Memc[ip] + pp = pp + 1 + ip = ip + 1 + } + Memc[pp] = EOS + + # Copy or skip = and skip whitespace. + if (hparam) { + Memc[op] = '=' + op = op + 1 + } + ip = ip + 3 + + # Copy parameter value. It is an error if there is no value. + if (IS_WHITE (Memc[ip]) || (Memc[ip] == ')' && Memc[ip+1] != '_')) { + call sprintf (Memc[obuf], SZ_CMDSTR, + "Undefined parameter value (%s.%s)") + call pargstr (Memc[ltask]) + call pargstr (Memc[pname]) + call error (1, Memc[obuf]) + } + + # If the parameter is a quoted string copy until the closing quote, + # otherwise copy until whitespace or ). + + if (Memc[ip] == '"') { + Memc[op] = Memc[ip] + ip = ip + 1 + op = op + 1 + while (Memc[ip] != '"') { + Memc[op] = Memc[ip] + ip = ip + 1 + op = op + 1 + } + Memc[op] = Memc[ip] + ip = ip + 1 + op = op + 1 + + } else if (Memc[ip] == ')' && Memc[ip+1] == '_') { + # If the value is a redirection, e.g. ")_.foo", add quotes + # around the value and copy as a special case. + Memc[op] = '"' + op = op + 1 + + # Copy the opening paren. + Memc[op] = Memc[ip] + op = op + 1 + ip = ip + 1 + + # Copy the rest of the string. + while (!IS_WHITE(Memc[ip]) && (Memc[ip] != ')')) { + Memc[op] = Memc[ip] + ip = ip + 1 + op = op + 1 + } + + # Add the closing quote. + Memc[op] = '"' + op = op + 1 + + } else { + while (!IS_WHITE(Memc[ip]) && (Memc[ip] != ')')) { + Memc[op] = Memc[ip] + ip = ip + 1 + op = op + 1 + } + } + + # Add a comma and a space. + Memc[op] = ',' + op = op + 1 + Memc[op] = ' ' + op = op + 1 + + # Replace the last break with a new line if the line exceeds max. + if ((op - nl > 80) && (last > 0)) { + Memc[last] = '\n' + nl = last + } + last = op - 1 + } + + # Replace last comma and space by a parenthesis and EOS. + if (Memc[op-2] == ',') + op = op - 2 + + Memc[op] = ')' + op = op + 1 + Memc[op] = EOS + + # Print the command string and finish up. + call putline (STDOUT, Memc[obuf]) + call putci (STDOUT, '\n') + + call sfree (sp) +end diff --git a/pkg/system/concatenate.par b/pkg/system/concatenate.par new file mode 100644 index 00000000..533461dd --- /dev/null +++ b/pkg/system/concatenate.par @@ -0,0 +1,4 @@ +input_files,s,a,,,,list of files to be concatenated +output_file,f,a,,,,name of output file +out_type,s,h,"in_type",,,output file type (text|binary) +append,b,h,no,,,append to output file? diff --git a/pkg/system/concatenate.x b/pkg/system/concatenate.x new file mode 100644 index 00000000..7732150b --- /dev/null +++ b/pkg/system/concatenate.x @@ -0,0 +1,73 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# CONCATENATE -- Concatenate the named input files (or the standard input) to +# produce the output file. The input files must all be of the same type. +# The type of the output file (text|binary) defaults to the type of the first +# input file, or to text if reading from the standard input. The hidden +# parameter "out_type" may be used to force the file type of the copy operation. + +procedure t_concatenate() + +char infile[SZ_FNAME], outfile[SZ_FNAME] +char out_type_string[SZ_FNAME] +int in, out, list, out_type + +int clpopni(), clgfil() +int open(), access(), strmatch(), clgeti() +bool clgetb() + +begin + # Open the input file list, and read in the name of the first file + # (used to determine type of output file later). + + list = clpopni ("input_files") + if (clgfil (list, infile, SZ_FNAME) == EOF) { + call clpcls (list) + return + } + + # Determine whether the output file is text or binary, and open + # the file. + + call clgstr ("out_type", out_type_string, SZ_FNAME) + out_type = NULL + if (strmatch (out_type_string, "^#{b}") > 0) + out_type = BINARY_FILE + else if (strmatch (out_type_string, "^#{t}") > 0) + out_type = TEXT_FILE + + # Default to std output if output file not given on cmd line. + + if (clgeti ("$nargs") <= 1) + call strcpy ("STDOUT", outfile, SZ_FNAME) + else + call clgstr ("output_file", outfile, SZ_FNAME) + + # If the output file type has been specified (param "out_type"), + # use it, otherwise use type of first input file. + + if (out_type == NULL) { + if (strmatch (infile, "STDIN") > 0) + out_type = TEXT_FILE + else if (access (infile, 0, TEXT_FILE) == YES) + out_type = TEXT_FILE + else + out_type = BINARY_FILE + } + + # Finally, open the output file. + if (clgetb ("append")) + out = open (outfile, APPEND, out_type) + else + out = open (outfile, NEW_FILE, out_type) + + # Append the input files to the output file. + repeat { + in = open (infile, READ_ONLY, out_type) + call fcopyo (in, out) + call close (in) + } until (clgfil (list, infile, SZ_FNAME) == EOF) + + call close (out) + call clpcls (list) +end diff --git a/pkg/system/copy.par b/pkg/system/copy.par new file mode 100644 index 00000000..eb33a234 --- /dev/null +++ b/pkg/system/copy.par @@ -0,0 +1,3 @@ +input,s,a,,,,input file or file template +output,s,a,,,,output file or destination directory +verbose,b,h,no,,,print names of files as they are copied diff --git a/pkg/system/copy.x b/pkg/system/copy.x new file mode 100644 index 00000000..2a021516 --- /dev/null +++ b/pkg/system/copy.x @@ -0,0 +1,62 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> + +# COPY -- Copy a file, or copy a list of files to another directory. +# The number of input files is variable, but there can be only a single +# output file. If the output file is a directory, we copy the input files +# to that directory without changing their names. Otherwise there can +# be only one input file, and a copy is made with the new name. + +procedure t_copy() + +int list, root_len +bool verbose +pointer sp, infile, destination, outfile, junkstr, dirname +bool clgetb() +int clpopni(), clgfil(), clplen(), fnldir(), isdirectory() + +begin + call smark (sp) + call salloc (infile, SZ_FNAME, TY_CHAR) + call salloc (outfile, SZ_FNAME, TY_CHAR) + call salloc (destination, SZ_FNAME, TY_CHAR) + call salloc (dirname, SZ_PATHNAME, TY_CHAR) + call salloc (junkstr, SZ_FNAME, TY_CHAR) + + list = clpopni ("input") + call clgstr ("output", Memc[destination], SZ_FNAME) + verbose = clgetb ("verbose") + + # If the destination file is a directory, copy each file in the input + # list to the destination directory, else just copy the file and check + # that there is only one file in the input list. + + if (isdirectory (Memc[destination], Memc[dirname], SZ_PATHNAME) > 0) { + + while (clgfil (list, Memc[infile], SZ_FNAME) != EOF) { + call strcpy (Memc[dirname], Memc[outfile], SZ_PATHNAME) + root_len = fnldir (Memc[infile], Memc[junkstr], SZ_FNAME) + call strcat (Memc[infile+root_len], Memc[outfile], SZ_PATHNAME) + + if (verbose) { + call eprintf ("%s -> %s\n") + call pargstr (Memc[infile]) + call pargstr (Memc[outfile]) + } + + iferr (call fcopy (Memc[infile], Memc[outfile])) + call erract (EA_WARN) + } + + } else if (clgfil (list, Memc[infile], SZ_FNAME) != EOF) { + if (clplen (list) > 1) { + call clpcls (list) + call error (2, "cannot copy several files to a single file") + } + call fcopy (Memc[infile], Memc[destination]) + } + + call clpcls (list) + call sfree (sp) +end diff --git a/pkg/system/count.par b/pkg/system/count.par new file mode 100644 index 00000000..bc78c6ef --- /dev/null +++ b/pkg/system/count.par @@ -0,0 +1 @@ +files,s,a,,,,list of files to be counted diff --git a/pkg/system/count.x b/pkg/system/count.x new file mode 100644 index 00000000..9f9ef51c --- /dev/null +++ b/pkg/system/count.x @@ -0,0 +1,131 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include <chars.h> +include <error.h> + +define SZ_LUT 256 # "whitespace" lookup table +define CC_WHITE 1 # "white" character class +define CC_NONWHITE 0 # "word" character + +# COUNT -- Count the number of lines, words, and characters in the named text +# files, or in the standard input. Print the results on the standard output. +# +# output format (single file): +# +# nlines nwords nchars +# +# output format (several files): +# +# nlines nwords nchars filename1 +# nlines nwords nchars filename2 +# nlines nwords nchars Total + +procedure t_count() + +char fname[SZ_FNAME] +long nlines, nwords, nchars +long totlines, totwords, totchars +int nfiles, list +int clpopni(), clgfil() + +begin + totlines = 0 + totwords = 0 + totchars = 0 + nfiles = 0 + + list = clpopni ("files") + + while (clgfil (list, fname, SZ_FNAME) != EOF) { + iferr (call count_file (fname, nlines, nwords, nchars)) + call erract (EA_WARN) + else { + call print_stats (STDOUT, nlines, nwords, nchars, fname) + call flush (STDOUT) + } + + totlines = totlines + nlines + totwords = totwords + nwords + totchars = totchars + nchars + nfiles = nfiles + 1 + } + + call clpcls (list) + + if (nfiles > 1) + call print_stats (STDOUT, totlines, totwords, totchars, "Total") +end + + +# COUNT_FILE -- Open a file and count the number of lines, words, and +# characters in the file. + +procedure count_file (fname, nlines, nwords, nchars) + +char fname[SZ_FNAME], lbuf[SZ_LINE], ch, class[SZ_LUT] +long nlines, nwords, nchars +int first_time, state, fd, ip, open(), getline() +errchk open, getline +data first_time /YES/ + +begin + # Initialize the lookup table, used to count words. In this case, + # NEWLINE is considered to be whitespace. + + if (first_time == YES) { + do ip = 1, SZ_LUT + class[ip] = CC_NONWHITE + + class[BLANK] = CC_WHITE + class[TAB] = CC_WHITE + class[NEWLINE] = CC_WHITE + + first_time = NO + } + + fd = open (fname, READ_ONLY, TEXT_FILE) + + nwords = 0 + nchars = 0 + state = CC_WHITE + + # Increment word count at the beginning of every word. A "word" + # is defined as a sequence of characters delimited by whitespace. + # COUNT does not know anything about quoted strings. + + for (nlines=0; getline (fd, lbuf) != EOF; ) { + do ip = 1, SZ_LINE { + ch = lbuf[ip] + if (ch == EOS) + break + else if (class[ch] != state) { + nwords = nwords + state + state = class[ch] + } + } + nchars = nchars + ip - 1 + if (lbuf[ip-1] == '\n') + nlines = nlines + 1 + } + + call close (fd) +end + + +# PRINT_STATS -- Format the COUNT statistics summary line and print it on +# the named file. + +procedure print_stats (fd, nlines, nwords, nchars, fname) + +int fd +long nlines, nwords, nchars +char fname[ARB] + +begin + call fprintf (fd, "%7d %7d %7d %s\n") + call pargl (nlines) + call pargl (nwords) + call pargl (nchars) + call pargstr (fname) +end diff --git a/pkg/system/delete.par b/pkg/system/delete.par new file mode 100644 index 00000000..a33ed606 --- /dev/null +++ b/pkg/system/delete.par @@ -0,0 +1,6 @@ +files,s,a,,,,list of files to be deleted +verify,b,h,no,,,verify operation before deleting each file? +default_action,b,h,yes,,,default delete action for verify query +allversions,b,h,yes,,,delete all versions of each file +subfiles,b,h,yes,,,delete any subfiles of each file +go_ahead,b,q,yes,,," ?" diff --git a/pkg/system/delete.x b/pkg/system/delete.x new file mode 100644 index 00000000..0c15a2c4 --- /dev/null +++ b/pkg/system/delete.x @@ -0,0 +1,74 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> + +# DELETE -- Delete a list of files. If file cannot be deleted, warn but do +# not abort. Verify before deleting each file if user wishes. + +procedure t_delete() + +bool verify # verify before deleting +bool allversions # delete all versions of each file +bool subfiles # delete any subfiles of a file +char fname[SZ_FNAME] +int list +pointer tty + +bool clgetb() +int clpopns(), clgfil(), access(), btoi(), strncmp() +pointer ttyodes() + +begin + list = clpopns ("files") + verify = clgetb ("verify") + allversions = clgetb ("allversions") + subfiles = clgetb ("subfiles") + if (verify) + tty = ttyodes ("terminal") + + while (clgfil (list, fname, SZ_FNAME) != EOF) { + if (verify) { + # If file does not exist, warn user (since verify mode is + # in effect). + if (access (fname, 0, 0) == NO) { + call eprintf ("Warning: Nonexistent file '%s'\n") + call pargstr (fname) + next + } + + # Set default action of verify prompt (override learning of + # most recent response). + + call flush (STDOUT) + call clputb ("go_ahead", clgetb ("default_action")) + call eprintf ("Delete file ") + call ttyso (STDERR, tty, YES) + call eprintf ("'%s'") + call pargstr (fname) + call ttyso (STDERR, tty, NO) + call flush (STDERR) + + if (!clgetb ("go_ahead")) + next + } + + if (strncmp ("http:", fname, 5) == 0) { + call eprintf ("Cannot delete URL `%s'\n") + call pargstr (fname) + next + } + + iferr (call deletefg (fname, btoi(allversions), btoi(subfiles))) + call erract (EA_WARN) + } + + # Reset the go_ahead parameter, overiding learn mode, in case delete + # is subsequently called from the background. Close tty descriptor. + + if (verify) { + call clputb ("go_ahead", true) + call ttycdes (tty) + } + + call clpcls (list) +end diff --git a/pkg/system/devices.cl b/pkg/system/devices.cl new file mode 100644 index 00000000..660c91ec --- /dev/null +++ b/pkg/system/devices.cl @@ -0,0 +1,3 @@ +# DEVICES -- Print information on the locally available devices. + +help devices diff --git a/pkg/system/directory.par b/pkg/system/directory.par new file mode 100644 index 00000000..444fe325 --- /dev/null +++ b/pkg/system/directory.par @@ -0,0 +1,6 @@ +files,s,a,,,,files or directory to be listed +long,b,h,no,,,long format listing +ncols,i,h,0,0,,number of columns if multicolumn format +maxch,i,h,18,,,max filename chars to show if multicolumn format +sort,b,h,yes,,,sort the file list +all,b,h,no,,,list hidden files too diff --git a/pkg/system/directory.x b/pkg/system/directory.x new file mode 100644 index 00000000..37a1c397 --- /dev/null +++ b/pkg/system/directory.x @@ -0,0 +1,561 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <diropen.h> +include <protect.h> +include <finfo.h> +include <chars.h> +include <ctype.h> +include <fset.h> +include <time.h> + +# DIRECTORY -- List the files matching the given template. If no template is +# given list the contents of the current directory. Only existing files are +# listed, i.e., "dir file" may be used to test if "file" exists. There are +# two types of file listings: +# +# tabular multicolumn listing, "ncolumns" columns (default) +# long long form listing; prints more info for each file +# +# The template may be either the name of a file or directory, or a true +# filename template containing pattern matching metacharacters. + +define DEF_MAXFILES 256 # initial max file limit +define DEF_SZSBUF 4096 # initial string buffer size +define DEF_SCREENWIDTH 80 # default screen width if envgeti fails +define DEF_NCOLS 4 # default number of columns in table +define NLINES_FLUSH 4 # nlines flushed out at a time (quick) +define PATCHARS "*?[" + +define LEN_FLDES 6 # file list descriptor +define FL_NFILES Memi[$1] # number of files in list +define FL_NEXTOFF Memi[$1+1] # next offset in sbuf +define FL_OFFBP Memi[$1+2] # pointer to list of offsets +define FL_SBUFP Memi[$1+3] # pointer to string buffer +define FL_MAXFILES Memi[$1+4] # current length of offset array +define FL_SZSBUF Memi[$1+5] # current string buffer size + +define FL_OFFSET Memi[FL_OFFBP($1)+($2)-1] +define FL_FNAME Memc[FL_SBUFP($1)+(FL_OFFSET($1,$2))-1] + + +# T_DIRECTORY -- CL callable main routine for the directory program. + +procedure t_directory() + +pointer sp, files, fname, dirname, patp, fp, ip, op, ep +int ncols, maxch, dirmode, fd, n, i, patlen, len_dir +bool long_format, is_template, is_pattern, is_dir, sort_list, match_extension + +bool clgetb(), strne() +int clgeti(), fntopnb(), fntgfnb() +int diropen(), getline(), stridx(), strlen(), strncmp(), stridxs() +int isdirectory(), access(), envgeti(), btoi() +string patchars PATCHARS +define template_ 91 +define done_ 92 + +begin + call smark (sp) + call salloc (files, SZ_LINE, TY_CHAR) + call salloc (fname, SZ_PATHNAME, TY_CHAR) + call salloc (dirname, SZ_PATHNAME, TY_CHAR) + + # If directory is called without any arguments, list the contents + # of the current directory. Otherwise read in the file template. + + if (clgeti ("$nargs") == 0) + call strcpy (".", Memc[files], SZ_LINE) + else + call clgstr ("files", Memc[files], SZ_LINE) + + # Determine whether a long format listing is desired. + long_format = clgetb ("long") + + # If not long format listing, determine the number of columns for + # the multicolumn format listing. + + if (!long_format) + ncols = clgeti ("ncols") + + # Max chars of each filename to be shown. + maxch = clgeti ("maxch") + + # Sort files? + sort_list = clgetb ("sort") + + # Show hidden files? + if (clgetb ("all")) + dirmode = PASS_HIDDEN_FILES + else + dirmode = SKIP_HIDDEN_FILES + + # Allocate and initialize storage for the file list descriptor and + # assocated array storage. + + call calloc (fp, LEN_FLDES, TY_STRUCT) + call malloc (FL_OFFBP(fp), DEF_MAXFILES, TY_INT) + call malloc (FL_SBUFP(fp), DEF_SZSBUF, TY_CHAR) + + FL_MAXFILES(fp) = DEF_MAXFILES + FL_SZSBUF(fp) = DEF_SZSBUF + FL_NEXTOFF(fp) = 1 + + # The template is considered a filename template if it contains any + # of the metacharacters "*?[],", i.e., any string containing a comma + # is considered a filename template, since we don't want to mess with + # parsing comma delimited lists here. + + is_template = false + is_pattern = false + + for (ip=files; Memc[ip] != EOS; ip=ip+1) + if (IS_ALPHA (Memc[ip])) { + next + } else if (stridx (Memc[ip], patchars) > 0) { + if (ip == files || Memc[ip-1] != '\\') + is_pattern = true + } else if (Memc[ip] == ',' || Memc[ip] == '%') + if (ip == files || Memc[ip-1] != '\\') + is_template = true + + # Set IS_DIR flag, and get directory name if not fancy template. + + if (is_template) { + is_dir = false + + } else if (is_pattern) { + is_dir = true + patp = NULL + ep = NULL + + # Search for a valid directory prefix. + op = dirname + for (ip=files; Memc[ip] != EOS; ip=ip+1) { + Memc[op] = Memc[ip] + if (Memc[op] == FNLDIR_CHAR || Memc[op] == '//') + if (op == dirname || Memc[op-1] != '\\') { + patp = ip + 1 + ep = op + 1 + } + op = op + 1 + } + + # Must set patp and dirname before exiting. + if (patp == NULL) { + patp = files + call strcpy ("./", Memc[dirname], SZ_PATHNAME) + len_dir = 0 + } else { + Memc[ep] = EOS + len_dir = strlen (Memc[dirname]) + } + + } else + is_dir = (isdirectory (Memc[files],Memc[dirname],SZ_PATHNAME) > 0) + + # If sorting is not desired and we either don't have a template, or + # a simple unary match-pattern template, we can list the directory + # directly to the standard output as it is read. This is the fastest + # possible type of of directory listing, and is particularly useful + # for listing very large directories. + + if (is_dir && !sort_list && !long_format && !is_template) { + fd = diropen (Memc[dirname], dirmode) + call dir_quicklist (STDOUT, fd, Memc[patp], is_pattern, ncols) + call close (fd) + goto done_ + } + + # If `files' is a template, expand the template and read the file + # names into memory. If `files' is not a filename template, determine + # if it is the name of (or pathname to) a directory. If so, open the + # directory directly and read the file list into memory. If `files' is + # neither a template nor a directory, it must be a filename, so merely + # put its name in the file list. + + if (!is_template && is_dir) { + # Read file list from the named directory. + + # Set up the pattern matching code. We recognize selecting all + # files with a particular extension as a special case, since this + # case is very common and can be done more efficiently if we don't + # use the general pattern matching code. + + if (is_pattern) { + match_extension = (strncmp (Memc[patp], "*.", 2) == 0 && + stridxs (patchars, Memc[patp+2]) <= 0) + if (match_extension) + patlen = strlen (Memc[patp]) + else + goto template_ + } + + fd = diropen (Memc[dirname], dirmode) + + # Accumulate the file list in memory. + n = 0 + while (n != EOF) { + n = getline (fd, Memc[fname]) + if (n <= 1) + break + n = n - 1 + Memc[fname+n] = EOS # clobber the \n + + # Check if file matches the given pattern. + if (is_pattern) { + if (n < patlen) + next + ep = fname + n - 1 + for (ip=patp+patlen-1; ip > patp+1; ip=ip-1) { + if (Memc[ep] != Memc[ip]) + break + ep = ep - 1 + } + if (Memc[ip] != '.' || Memc[ep] != '.') + next + } + + call dir_putstr (fp, Memc[fname], n) + } + + call close (fd) + if (sort_list && FL_NFILES(fp) > 1) + call strsrt (FL_OFFSET(fp,1), Memc[FL_SBUFP(fp)], FL_NFILES(fp)) + + } else { + # Expand the given filename template and read the file list into + # memory. This also handles the cases of a single filename or + # a simple list of filenames. +template_ + fd = fntopnb (Memc[files], btoi(sort_list)) + + n = fntgfnb (fd, Memc[fname], SZ_PATHNAME) + while (n != EOF) { + ip = fname + if (!is_template && is_pattern) + ip = fname + len_dir; + if (is_pattern) + call dir_putstr (fp, Memc[ip], n) + else if (access (Memc[fname],0,0) == YES) + call dir_putstr (fp, Memc[ip], n) + n = fntgfnb (fd, Memc[fname], SZ_PATHNAME) + } + + call fntclsb (fd) + } + + # All done if no files were found. + if (FL_NFILES(fp) == 0) { + call printf ("no files found\n") + goto done_ + } + + # Format and output the file list in either long format (verbose) + # or in multicolumn format. A one column file list is treated as + # a special case of the multifile format. + + if (long_format || ncols == 1) { + for (i=1; i <= FL_NFILES(fp); i=i+1) { + # Get filename. + if (is_dir && strne (Memc[dirname], "./")) { + call sprintf (Memc[fname], SZ_PATHNAME, "%s%s") + call pargstr (Memc[dirname]) + call pargstr (FL_FNAME(fp,i)) + } else + call strcpy (FL_FNAME(fp,i), Memc[fname], SZ_PATHNAME) + + if (long_format) { + # Long format output, one line per file. + call dir_pfiledata (Memc[fname], STDOUT) + } else { + call printf ("%s\n") + call pargstr (Memc[fname]) + } + } + + } else { + # Print nice multicolumn table. + call strtbl (STDOUT, Memc[FL_SBUFP(fp)], FL_OFFSET(fp,1), + FL_NFILES(fp), 1, envgeti ("ttyncols"), maxch, ncols) + } +done_ + call mfree (FL_OFFBP(fp), TY_INT) + call mfree (FL_SBUFP(fp), TY_CHAR) + call mfree (fp, TY_STRUCT) + call sfree (sp) +end + + +# DIR_QUICKLIST -- List the directory directly to the standard output, without +# first reading and sorting the entire directory. This is the best type of +# listing algorithm for very large directories. + +procedure dir_quicklist (out, fd, pat, have_pattern, a_ncols) + +int out # output file +int fd # fd of directory being listed +char pat[ARB] # selection pattern, if any +bool have_pattern # do we have a pattern? +int a_ncols # number of columns out + +bool flushlines, match_extension +pointer sp, fname, obuf, patbuf, op, ep +int colwidth, patlen, ip, col, maxch, junk, lastch +int scrwidth, ncols, nfiles, nchars, nblanks, nlines, nflush +int fstati(), getline(), envgeti(), patmake(), patmatch() +int strncmp(), stridxs(), strlen() +errchk getline, ungetline, putline + +begin + call smark (sp) + call salloc (obuf, SZ_LINE, TY_CHAR) + call salloc (fname, SZ_PATHNAME, TY_CHAR) + call salloc (patbuf, SZ_LINE, TY_CHAR) + + # Initialization. + flushlines = (out == STDOUT && fstati (out, F_REDIR) == NO) + iferr (scrwidth = envgeti ("ttyncols")) + scrwidth = DEF_SCREENWIDTH + + ncols = a_ncols + if (ncols <= 0) + ncols = DEF_NCOLS + maxch = scrwidth / ncols + + nfiles = 0 + nchars = 0 + nlines = 0 + nflush = 1 + + # Set up the pattern matching code. We recognize selecting all files + # with a particular extension as a special case, since this case is + # very common and can be done much more efficiently if we don't use + # the general pattern matching code. + + if (have_pattern) { + match_extension = (strncmp (pat, "*.", 2) == 0 && + stridxs (PATCHARS, pat[3]) <= 0) + if (match_extension) + patlen = strlen (pat) + else { + # Convert file matching pattern into general pattern string. + Memc[fname] = '^' + op = fname + 1 + lastch = 0 + for (ip=1; pat[ip] != EOS; ip=ip+1) { + if (pat[ip] == '*' && lastch != '?' && lastch != ']') { + Memc[op] = '?' + op = op + 1 + } + lastch = pat[ip] + Memc[op] = lastch + op = op + 1 + } + Memc[op] = '$' + op = op + 1 + Memc[op] = EOS + + # Compile the pattern. + junk = patmake (Memc[fname], Memc[patbuf], SZ_LINE) + } + } + + # List the directory. + + while (nchars != EOF) { + # Compose the next line of the directory listing. + op = obuf + for (col=1; col <= ncols; ) { + nchars = getline (fd, Memc[fname]) + if (nchars <= 1) + break + + # Cancel the newline. + nchars = nchars - 1 + Memc[fname+nchars] = EOS + + # Check if file matches the given pattern. + if (have_pattern) + if (match_extension) { + if (nchars < patlen) + next + ep = fname + nchars - 1 + for (ip=patlen; ip > 2; ip=ip-1) { + if (Memc[ep] != pat[ip]) + break + ep = ep - 1 + } + if (pat[ip] != '.' || Memc[ep] != '.') + next + } else if (patmatch (Memc[fname], Memc[patbuf]) <= 0) + next + + if (op-obuf + nchars > scrwidth && col > 1) { + # Filename too long to fit in remainder of line. + call ungetline (fd, Memc[fname]) + break + + } else { + # Append filename to output line. + nfiles = nfiles + 1 + nchars = min (nchars, scrwidth - (op - obuf)) + + # Copy the filename. + do ip = 1, nchars { + Memc[op] = Memc[fname+ip-1] + op = op + 1 + } + + # Advance to the next column. + colwidth = maxch + while (col < ncols) { + nblanks = colwidth - nchars + if (nblanks < 1) { + col = col + 1 # grab another column + colwidth = colwidth + maxch + } else { + do ip = 1, nblanks { + Memc[op] = ' ' + op = op + 1 + } + break + } + } + } + + col = col + 1 + } + + # Output one line of the directory listing. + if (op > obuf) { + Memc[op] = '\n' + op = op + 1 + Memc[op] = EOS + + call putline (out, Memc[obuf]) + + nlines = nlines + 1 + if (flushlines && nlines >= nflush) { + call flush (out) + nflush = min (NLINES_FLUSH, nflush + 1) + nlines = 0 + } + } + } + + # Was the directory empty? + if (nfiles == 0) + call printf ("no files found\n") + + call sfree (sp) +end + + +# DIR_PUTSTR -- Put a string (filename) into the file list. If the buffer +# fills up allocate a larger buffer. + +procedure dir_putstr (fp, fname, nchars) + +pointer fp # file list pointer +char fname[ARB] # file name to be put in list +int nchars # nchars in file name + +int op +int fileno + +begin + # Increment file count. + fileno = FL_NFILES(fp) + 1 + FL_NFILES(fp) = fileno + + # Increase size of file list if it overflows. + if (fileno >= FL_MAXFILES(fp)) { + FL_MAXFILES(fp) = FL_MAXFILES(fp) * 2 + call realloc (FL_OFFBP(fp), FL_MAXFILES(fp), TY_INT) + } + + op = FL_NEXTOFF(fp) + FL_OFFSET(fp,fileno) = op + + # Increase size of string buffer if it overflows. + if (op + nchars + 1 >= FL_SZSBUF(fp)) { + FL_SZSBUF(fp) = FL_SZSBUF(fp) * 2 + call realloc (FL_SBUFP(fp), FL_SZSBUF(fp), TY_CHAR) + } + + call strcpy (fname, FL_FNAME(fp,fileno), nchars) + FL_NEXTOFF(fp) = op + nchars + 1 +end + + +# DIR_PFILEDATA -- Print file info in a UNIX like long directory format, on +# the output file OUT. Format, e.g.,: "-t-rwr-r- tody 5117 May 15 19:29 fio.x" + +procedure dir_pfiledata (fname, out) + +char fname[ARB] # file name +int out # output file + +pointer sp, date +long fi[LEN_FINFO] +int protected, ftypes[4], i +int finfo(), access(), bitupk(), protect() +data ftypes /'-', 'd', 'x', 's'/ + +begin + call smark (sp) + call salloc (date, SZ_DATE, TY_CHAR) + + # Get file directory information. + if (finfo (fname, fi) != OK) { + call eprintf ("Cannot get info on file `%s'\n") + call pargstr (fname) + call sfree (sp) + return + } + + # Query file protection. + protected = protect (fname, QUERY_PROTECTION) + + # Output file mode bit flags. + call dir_putci (out, ftypes[FI_TYPE(fi)], '-', YES) + call dir_putci (out, 't', 'b', access (fname,0,TEXT_FILE)) + call dir_putci (out, 'p', '-', protected) + + # Output user,group,world protections bit flags. + do i = 1, 5, 2 { + call dir_putci (out, 'r', '-', bitupk (int(FI_PERM(fi)),i,1)) + call dir_putci (out, 'w', '-', bitupk (int(FI_PERM(fi)),i+1,1)) + } + + # Output file owner, size, date, and name. + call cnvdate (FI_MTIME(fi), Memc[date], SZ_DATE) + call fprintf (out, " %-8.8s%8d %12.12s %-32.32s\n") + call pargstr (FI_OWNER(fi)) + call pargl (FI_SIZE(fi)) + call pargstr (Memc[date]) + call pargstr (fname) + + # This is slow so flush the output after each file to give the user + # some immediate gratification. + + call flush (out) + call sfree (sp) +end + + +# DIR_PUTCI -- Handy procedure used to generate --rw-r-r- type strings. + +procedure dir_putci (fd, ch_t, ch_f, condition) + +int fd # output file +int ch_t # character to output if condition is true +int ch_f # character to output if condition is false +int condition + +begin + if (condition == NO) + call putci (fd, ch_f) + else + call putci (fd, ch_t) +end diff --git a/pkg/system/doc/Sys.hlp b/pkg/system/doc/Sys.hlp new file mode 100644 index 00000000..89d66d7f --- /dev/null +++ b/pkg/system/doc/Sys.hlp @@ -0,0 +1,349 @@ +.help utilities Oct83 "IRAF System Utilities" +.sh +Description of the Standard Utility Routines + + Most of the system utilities are set up to read from either the +standard input or a list of files. If not reading from the standard +input, and the input file template is not given on the command line, +a prompt will be issued for the input file list. If the output is a +single file or directory, and output is not redirected, a prompt will +be issued for the output file. + +.ks +.ls 4 ALLOCATE device + +Allocate a device (i.e., a tape drive). Some devices must be allocated +before they can be accessed for i/o. Deallocation occurs automatically +upon logoff, or upon execution of DEALLOCATE. The following devices may +be allocated: + +.nf +Devices: + mta Magtape unit A. + mtb Magtape unit B. + ima Image display unit A. + imb Image display unit B. +.fi +.le +.ke + +.ks +.ls BEEP +Beep the terminal bell. Used as in "> munch;beep" to signal when a +lengthy command has finished. Otherwise, an IRAF program will only +ring the terminal bell when an error has occurred. +.le +.ke + +.ks +.ls CLEAR + +Clear the terminal screen. +.le +.ke + +.ks +.ls CONCATENATE files [,output_file] + +Concatenate the named input files to the standard output or to the named +output file if given. All input files should be of the same type (text or +binary). The default type of the output file is the same as that of the +first input file; this may be overridden by setting the hidden parameter +"out_type". The standard input is assumed to be a text file unless overridden +by setting out_type. If no output file is given on the command line, the +standard output is assumed. + +.nf +Hidden Parameters: + out_type string = "in_type" Output file type (text|binary) + append bool = no Append to output file +.fi +.le +.ke + +.ks +.ls COPY file|files, output_file|directory + +Copy the input file to the output file, or copy each file in the input list +to the directory given as the second argument. +.le +.ke + +.ks +.ls COUNT files + +Count the number of lines, words, and characters in each file +in the input list. Print the totals for each file and for all files. +.le +.ke + +.ks +.ls DEALLOCATE device + +Deallocate a previously allocated device (e.g., a tape drive). Devices +are automatically deallocated upon logoff if not explicitly deallocated +with the deallocate command. +.le +.ke + +.ks +.ls DELETE files + +Delete the named files. A warning message is printed if a file +cannot be deleted. It is not considered an error to attempt to +delete a file which does not exist. Protected files cannot be +deleted without first removing their protection. + +.nf +Hidden Parameters: + verify bool = no Generate query to verify that each + file should indeed be deleted. +.fi +.le +.ke + +.ks +.ls DEVSTATUS device + +Print status information (i.e., is the device allocated, to whom, etc.) +for the named device. +.le +.ke + +.ks +.ls DIRECTORY [files] [,op=string] + +Tabulate information on all files matching the template given as the +first argument on the standard output. If no template is given, the +contents of the current directory are displayed. The "long" format +gives file protection status, type (text, binary, directory, or executable), +access modes (owner, group, world), owner name, size in bytes, date of +last modify, and the file name. + +.nf +Hidden Parameters: + option string = "m" 1 one-column format + a use time of last access + c use time of creation + l long format + m multicolumn format (default) + s add size in Kb + t time sort + r reverse sort + +e.g.: > dir op=l (show current directory, long form) + > dir "*.x",op=lt (all ".x" files in current directory, long form) +.fi +.le +.ke + +.ks +.ls DISKSPACE + +Summarize the amount of disk space available on the local system. +This command and its output are machine dependent. This command +may not be available on all systems. +.le +.ke + +.ks +.ls HEAD files + +Print the first few lines of each of the named files on the standard +output. If more than one file is printed, a brief header is printed to +identify each file. + +.nf +hidden params: + nlines int = 12 number of lines to print +.fi +.le +.ke + +.ks +.ls LPRINT files + +The named text files (or the standard input) are printed on the standard +line printer device. If several files are to be printed, each file is +printed starting on a new page, and file pages are broken and printed +with numbered headers. If reading from the standard input, the input +stream is copied to the printer without pagination, though pages may still +be broken by embedding formfeed characters in the text. The map_cc +option may be used to turn off all control character mapping, if binary +data is to be sent to the printer. + +.nf +Hidden Parameters: + map_cc bool = yes Map control characters into a printable + sequence (^L, etc.) +.fi +.le +.ke + +.ks +.ls MATCH pattern, files + +Search each text file for the given pattern. Copy a line to the standard +output if the pattern can be matched. Match against the standard input +if no files are named. + +.nf +Hidden Parameters: + stop bool = no Stop matched lines and pass unmatched + lines to the output instead. +.fi +.le +.ke + +.ks +.ls NEWS + +Page through the system news file, starting with the most recent entries. +The system news file is a sort of electronic bulletin board, used to +post announcements and notes of general interest. +.le +.ke + +.ks +.ls PAGE files + +The named text files (or the standard input) are displayed a page at a +time on the standard output. If there is more than one input file, +a brief header is printed at the beginning of each file. + +.nf +Hidden Parameters: + map_cc bool = yes Map control characters into a printable + sequence (^L, etc.) +.fi +.le +.ke + +.ks +.ls PROTECT files + +Protect the named files from deletion or clobber, accidental or otherwise. +It is not considered an error to attempt to protect a file which is already +protected. Protecting a file prevents only deletion or clobber of the entire +file: the contents of the file may still be overwritten. +.le +.ke + +.ks +.ls RENAME file|files, output_file|directory + +Rename a file, or move each file in the input list to the directory +given as the second argument. +.le +.ke + +.ks +.ls SORT files + +Sort and/or merge the text files named in the list, or sort the standard +input if no list. Sorting is by line or column, alphabetically or +numerically, in forward or reverse order. + +.nf +Hidden Parameters: + numeric_sort bool = no Sort numerically instead of + alphabetically, if datum is + a number. + reverse_sort bool = no Reverse the sense of the sort. + column int = 0 If 0, sort the entire line, else + sort the indicated column. + ignore_whitespace bool = yes Ignore leading whitespace if + sorting full lines. + merge bool = no Merge the input files, which are + assumed to already have been + sorted. +.fi +.le +.ke + +.ks +.ls SPY + +Get information on who is using the system, what they are up to, how +much cpu time, etc., they have used, and so on. This command, and the +information it gives, are machine dependent. This command may not be +available on all systems. + +.nf +Hidden Parameters: + verbose bool = no Give more detailed information. +.fi +.le +.ke + +.ks +.ls STTY [terminal] + +Identify the type of terminal being used, if different than the system +default. This is necessary to tell the system the control sequence to +be used to clear the screen, the dimensions of the screen, etc. If no +arguments are given, the current terminal status is given. + +.nf +Hidden Parameters: + baud int = 0 If nonzero, the system takes the + argument as the new baud rate. + ncols int = 0 If nonzero, the argument becomes + the number of columns per screen. + nlines int = 0 If nonzero, the argument becomes + the number of lines per screen. +.fi +.le +.ke + +.ks +.ls TAIL files + +Print the last few lines of each of the named text files on the +standard output. + +.nf +Hidden Parameters: + nlines int = 12 Number of lines to print. +.fi +.le +.ke + +.ks +.ls TEE file + +Copy the standard input to the standard output, as well as to the named +output file. + +.nf +Hidden Parameters: + out_type string = "text" Type of output file (text|binary). + append bool = no Append to the output file. +.fi +.le +.ke + +.ks +.ls TIME + +Print the current time and date. +.le +.ke + +.ks +.ls TYPE files + +Copy the named text files to the standard output. If more than one file is +to be typed, a brief header is printed at the beginning of each file, +identifying the file. +.le +.ke + +.ks +.ls UNPROTECT files + +Remove delete protection from the named files. It is not considered +an error to attempt to remove protection from a file which is not protected. +.le +.ke +.endhelp diff --git a/pkg/system/doc/Sys_intro.hlp b/pkg/system/doc/Sys_intro.hlp new file mode 100644 index 00000000..03d7e797 --- /dev/null +++ b/pkg/system/doc/Sys_intro.hlp @@ -0,0 +1,137 @@ +.help system May83 "General Aspects of the System Package" +.sh +Basic IRAF System Utilities + + A number of standard utilities are available as part of the IRAF +user interface. These utilities, most of which operate on files, are +summarized later in this document. A general discussion of files in +the IRAF system follows. The reader is assumed to have some familiarity +with the IRAF command language (CL). + + +.sh +Virtual File Names + + File names may be specified in a machine independent fashion, or with +OS dependent pathnames. A Virtual File Name (VFN) has the following form: + + +.nf + ldir$root.extn + +where + + ldir logical directory or device name + root root or base file name + extn extension denoting the type of file +.fi + + +The LDIR and EXTN fields are optional. The ROOT and EXTN fields may contain +up to 20 characters selected from the set [a-zA-Z0-9_.+-#]. The EXTN field +may not exceed three characters. The EXTN field is separated from the ROOT +by the character "." (dot). If the ROOT field contains one or more occurrences +of the dot character, the final dot delimited field is understood to be +the extension. + +Logical directories are defined in the CL, using the SET command to associate +an OS dependent pathname with a keyword in the environment table. Logical +directory prefixes are recursively expanded. + +A number of standard logical directories and devices are defined by the CL +at startup time. Additional logical directories are defined by applications +packages upon entry, and become undefined when dictionary space is reclaimed +on exit from the package. The user may override environment definitions at +will, by issuing SET commands to redefine environment variables. + + +.sh +File List Templates + + Whenever it makes sense, the IRAF utilities are set up to process a list +of files, rather than a single file. In the descriptions of the standard +utilities in the next section, "files" is a template or pattern specifying +a list of files to be processed in some way. The template is a string type +parameter to the CL, which is expanded by a procedure (CLGFIL) in the +compiled systems or applications task into an EOF terminated list of files. + +A template may consist of one or more file names, directory names, +list file names, or patterns. List elements are delimited by commas. +A list file is denoted by prepending the character "@" to the pathname +of the list file. A pattern may be applied to the contents of either +a list file or a directory. The pattern is separated from the list file +or directory name by the character "$". A pattern all by itself is +applied to the current directory. Either logical or OS dependent +pathnames may be used. + +A list element may refer only to a single directory. Thus, one cannot +specify a pattern such as "*/*.x", as is possible in UNIX. + +Some examples of templates follow: + +.nf + file + "file1, file2" + "*.x" + "[A-Z]*, *.com, ../$, ../fio/$*.x, lib$*.h, file, @list$*.vs" + "sia1:[iraf.lib]$*.h, uparm$cl_*.par" +.fi + +The magic filenames "STDIN", "STDOUT", and "STDERR" have a special +meaning. Passing one of these special filenames to a task causes +the named stream to be "reopened", transparently to the applications +program. Thus, for example, one can reference "STDIN" in a template, +and the applications program will read from the standard input when +it opens the corresponding file in the template. + +For example, + + cl> concat "file1, @STDIN, STDIN, file2", > ofile + +concatenates the file "file1", the contents of the files named in the +standard input (until the first EOF), the contents of the standard input +itself (until the second EOF), and the contents of the file "file2", +placing the output in the file "ofile". + + +.sh +File Protection and Clobber + + The IRAF file interface (FIO) provides file protection and synchronization +facilities, under control of user definable environment variables. + +File "clobber" refers to the overwriting of an existing file when a new +file of the same name is created as an output file. If "clobber" is +defined as "no" in the environment, an IRAF task will abort if a new file +would clobber an existing file. If file clobber is enabled, FIO will try +to overwrite the old file, and will abort if it cannot do so. + + cl> set clobber = "yes" + +More explicit file protection is provided by the CL commands PROTECT and +UNPROTECT. A protected file cannot be deleted, accidentally or otherwise, +until the protection has been removed with the UNPROTECT command or system +call. + +A final form of file protection is provided to prevent a file from being +clobbered which is already open by a task. Thus, "COPY file,file" will +abort when FIO discovers that "file" is already opened for reading. This +holds even if file clobber is enabled. + + +.sh +File Synchronization + + File synchronization is useful when a process requires exclusive access +to a file which is already open for exclusive access by another process. +When this situation occurs, the second task may abort with a message stating +that it cannot access the file, or the task may wait for the file to become +available. File waiting is especially important for batch processes. + + cl> set file_wait = "yes" + +The file wait option is controlled by the "file_wait" variable in the +environment. If file waiting is enabled, and a process finds that it +has to wait to access a file, a warning message will be printed on the +standard error output before the affected process goes to sleep. +.endhelp diff --git a/pkg/system/doc/allocate.hlp b/pkg/system/doc/allocate.hlp new file mode 100644 index 00000000..66d3353f --- /dev/null +++ b/pkg/system/doc/allocate.hlp @@ -0,0 +1,52 @@ +.help allocate Jan86 system +.ih +NAME +allocate -- allocate a device +.ih +USAGE +allocate device +.ih +PARAMETERS +.ls device +The device to be allocated. +.le +.ih +DESCRIPTION +\fBAllocate\fR allocates a device for exclusive access by one user, and +readies the device for i/o by some other program. A list of the devices +available on the local system is maintained in the file \fBdev$tapecap\fR +which needs to be configured by the site manager before it can be used. +The status of given device may be obtained by calling \fIdevstatus\fR. +.ih +EXAMPLES + +1. Print a list of the allocatable devices. The logical device names are +given at the left in the output text; ignore the information to the right. +\fBNote\fR: The dev$devices file should be configured by the site manager +when new tape devices are installed. Beginning with V2.9 it is used for +informational purposes only. +.ks +.nf + cl> type dev$devices + mta ... + mtb ... + mtc ... + iis ... +.fi +.ke + + +2. Allocate a tape drive after checking its status. + +.ks +.nf + cl> devstatus mtb + device mtb is not currently allocated + cl> + cl> allocate mtb +.fi +.ke +.ih +SEE ALSO +deallocate, devstatus +.endhelp diff --git a/pkg/system/doc/bench.hlp b/pkg/system/doc/bench.hlp new file mode 100644 index 00000000..1e8b373e --- /dev/null +++ b/pkg/system/doc/bench.hlp @@ -0,0 +1,56 @@ +.help bench Dec2010 system +.ih +NAME +bench -- simple benchmark tool +.ih +USAGE +bench +.ih +DESCRIPTION +The BENCH task provides a simple benchmark meant to simulate CCD processing +of three images. The tasks used exercise both disk- and CPU-intensive +applications and offer a crude comparison of performance between machines, +but it is not intended to be a comprehensive benchmark. There are no +parameters. +.ih +EXAMPLES +1. Run the benchmark: + +.nf + ecl> bench + + Bench started at 09:45:58 + + =====> Making images... + Making zero... + Making flat... + Making 3 objs... + + =====> Normalizing flat... + : + + =====> Subtracting zero from 3 images... + : + + =====> Dividing flat into 3 images... + : + + =====> Combining 3 images... + : + + =====> Median filtering image... + : + + =====> Deleting all images... + + Bench started at 09:45:58 + Bench ended at 09:46:56 + + Total execution time = 58.0 seconds + Total time Make 5 imgs Proc 3 imgs Combine 3 imgs Median 1 img + 58.0 25.0 10.0 4.0 19.0 +.fi + +.ih +SEE ALSO +.endhelp diff --git a/pkg/system/doc/chkupdate.hlp b/pkg/system/doc/chkupdate.hlp new file mode 100644 index 00000000..c4209753 --- /dev/null +++ b/pkg/system/doc/chkupdate.hlp @@ -0,0 +1,72 @@ +.help chkupdate Oct13 system +.ih +NAME +chkupdate - Check for an available IRAF update +.ih +USAGE +chkupdate +.ih +PARAMETERS +.ls interval = 0 +Number of days between updates checks. A value less than zero will disable +the checks entirely, a value of zero will cause a check to be made with +each login. +.le +.ls ref_file = "iraf$.release_date" +.le +.ls release = ")_.release" +Current IRAF release version. This value is inherited from the CL 'release' +parameter by default. +.le +.ls baseurl = "http://iraf.noao.edu/ftp" +Base URL to the IRAF release timestamp directory. +.le +.ls verbose = yes +Print verbose output? +.le +.ih +DESCRIPTION +This task compares the currently installed IRAF version with what is +available from the NOAO servers and will indicate whether an update is +available. The task is executed from the login.cl each time you login +to the CL, however the comparison is only done if 1) the uparm$update +file used to indicate the time of last check does not exist, 2) the +\fIinterval\fR parameter is zero to indicate the check should be done +with each login, or 3) more than \fIinterval\fR days have passed since +the last time the servers were contacted. An \fIinterval\fR value less +that zero may be used to disable the version updates entirely. + +The update check is done by comparing the file timestamp of the file +named in the \fIref_file\fR parameter with a distribution timestamp file +on the NOAO servers. The URL to this file is constructed from the +\fIbaseurl\fR and \fIrelease\fR parameters in addition to the \fIarch\fR +environment value, yielding a unique URL for each version and each platform. +If the contents of the file contain a timestamp more recent than the +timestamp of the \fIref_file\fR value, a message is printed to indicate +an update is available, otherwise a message is printed indicating the +installed system is current. +.ih +EXAMPLES + +1. Check whether an IRAF update is available, regardless of when we last +checked. + +.nf + cl> chkupdate interval=0 +.fi + +2. Check for an IRAF update once a month. + +.nf + cl> chkupdate.interval = 30 +.fi + +.ih +NOTES +This task is called automatically from the login.cl file at startup. + +Modifying the timestamp information of the \fIref_file\fR parameter, e.g. +by moving the IRAF tree, may invalidate the output. +.ih +SEE ALSO +.endhelp diff --git a/pkg/system/doc/concatenate.hlp b/pkg/system/doc/concatenate.hlp new file mode 100644 index 00000000..e3cd4fdc --- /dev/null +++ b/pkg/system/doc/concatenate.hlp @@ -0,0 +1,82 @@ +.help concatenate Nov84 system +.ih +NAME +concatenate -- connect files together into one big file +.ih +USAGE +concatenate files [output_file] +.ih +PARAMETERS +.ls files +The list of input files. The standard input, STDIN, may be specified to +interactively enter a few lines of text rather than read from a disk file. +All input files should be of the same type (binary or text). +.le +.ls output_file +The name of the output file. If no file is explicitly specified the +standard output (STDOUT) is used. +.le +.ls out_type = in_type +The output file type is forced if this parameter is defined as "binary" +or "text". If "out_type" does not begin with a "b" (or "B"), or a +"t" ("T"), then the output type is either "text", if the output file is +the standard output, or is determined from the type of the first input file. +.le +.ls append = no +If set to "yes", "files" are appended to "output_file". +.le +.ih +DESCRIPTION +Each file in the input file list is appended to the output file. +If "output_file" is not the standard output, and if output redirection (">") +was not specified on the command line, the resulting stream of data is placed +in a file. The input can be STDIN, which makes for an easy way to enter a +few lines of text into a file (but \fItype\fR is usually more convenient). +If entering data via the standard input, type the end of file character, +e.g., <ctrl/z>, to terminate the input sequence. +.ih +EXAMPLES + +1. Write out file1, followed by file2, to the terminal screen. Note that +there must be no space after the comma. + +.nf + cl> concatenate file1,file2 +.fi + +2. Write out files file1 and file2 into the new file "outfile". + +.nf + cl> concatenate file1,file2 outfile +.fi + +3. Copy what you type (up to the end-of-file character) into the file junk. + +.nf + cl> concatenate STDIN junk +.fi + +4. Write out the contents of each of the files whose names are given in "list", +one per line, and append this data to "junk". + +.nf + cl> concatenate @list junk append+ +.fi + +5. Concatenation is also possible using \fItype\fR, e.g., the following +command will append the contents of "file" to the file "outfile", which will +be created if it does not already exist. + + cl> type file >> outfile + +The redirect-append operator ">>" may be used to append the output of any +task to a file. + +.ih +NOTES +All input files should be of the same type, either all "text" or all +"binary". +.ih +SEE ALSO +copy, type +.endhelp diff --git a/pkg/system/doc/copy.hlp b/pkg/system/doc/copy.hlp new file mode 100644 index 00000000..9c58566d --- /dev/null +++ b/pkg/system/doc/copy.hlp @@ -0,0 +1,47 @@ +.help copy Nov84 system +.ih +NAME +copy -- copy a file, or a set of files to a directory +.ih +USAGE +copy input output +.ih +PARAMETERS +.ls input +The input file or list of files to be copied. +.le +.ls output +The (new) output file when copying one file to another, or the destination +directory when copying a set of files. +.le +.ls verbose = no +If set to "yes", a line of the type " from -> to " is printed on the +terminal for each file copied to a directory. This parameter is not +used when copying one file to another. +.le +.ih +DESCRIPTION +Copy makes a copy of a single file, or it copies a set of files to a different +directory. +.ih +EXAMPLES + +1. Copy all files in the current directory with extension ".x" to the +directory "home$src". As each copy is made, the user is informed. + + cl> copy *.x home$src ver+ + +2. Make a copy "fred.BAK" of the file "fred". + + cl> copy fred fred.BAK + +3. Copy the "graphcap" file from the remote node "lyra" to the current node, +without changing the name of the file. Note that "." is a synonym for the +current directory. + + cl> copy lyra!dev$graphcap . + +.ih +SEE ALSO +concatenate, movefiles +.endhelp diff --git a/pkg/system/doc/count.hlp b/pkg/system/doc/count.hlp new file mode 100644 index 00000000..09601019 --- /dev/null +++ b/pkg/system/doc/count.hlp @@ -0,0 +1,44 @@ +.help count Nov84 system +.ih +NAME +count -- determine number of lines, words and characters in a file +.ih +USAGE +count files +.ih +PARAMETERS +.ls files +A template specifying the files to be examined. +.le +.ih +DESCRIPTION +For each file, count determines the number of lines, words, and +characters in the file. A word is defined as a sequence of characters +delimited by one or more blanks or tabs, or by the end of a line. +If \fIcount\fR is run on more than one file, each output line is identified +by the file name, and a final output line gives the total number +of lines, words, and characters in all files. +.ih +EXAMPLES + +1. Count the number of lines, words and characters in all files in the +current directory with the extensions ".x" and ".h". + + cl> count *.[xh] + +2. Count the number of .x files in the current directory. + + cl> dir *.x op=1 | count + +3. Count the number of \fIset\fR environment definitions. + + cl> set | count + +4. Count the number of references to the READ function in all .x files in +the current directory. + + cl> match "read#(" *.x | count +.ih +SEE ALSO +directory +.endhelp diff --git a/pkg/system/doc/deallocate.hlp b/pkg/system/doc/deallocate.hlp new file mode 100644 index 00000000..803c9d6a --- /dev/null +++ b/pkg/system/doc/deallocate.hlp @@ -0,0 +1,34 @@ +.help deallocate Jan86 system +.ih +NAME +deallocate -- deallocate a device +.ih +USAGE +deallocate device +.ih +PARAMETERS +.ls device +The device to be deallocated. +.le +.ls rewind = yes +Rewind the device before deallocating? +Ignored for devices other than magtape. +.le +.ih +DESCRIPTION +Deallocate a previously allocated device. The CL will print an error +message if one attempts to logout while devices are still allocated, +but if \fIlogout\fR is typed several times you will be allowed to logout +with the devices still allocated. The CL does not automatically +deallocate devices upon logout. +.ih +EXAMPLES + +1. Deallocate logical magtape drive B. + + cl> dealloc mtb + +.ih +SEE ALSO +allocate, devstatus, file dev$devices, dev$tapecap +.endhelp diff --git a/pkg/system/doc/delete.hlp b/pkg/system/doc/delete.hlp new file mode 100644 index 00000000..78ac7df3 --- /dev/null +++ b/pkg/system/doc/delete.hlp @@ -0,0 +1,57 @@ +.help delete Nov84 system +.ih +NAME +delete -- delete a file or files +.ih +USAGE +delete files +.ih +PARAMETERS +.ls files +The list of files to be deleted. +.le +.ls verify = no +Check with the user before deleting a file. If verify is enabled the file +name is printed and the user is queried before the default action is taken. +.le +.ls default_action = yes +This is the default action to take when operating in "verify" mode. +For example, if the default action is "yes", one need only type RETURN in +response to the verify prompt to delete the file. +.le +.ls allversions = yes +Delete all versions of a file. This parameter has no effect on systems like +UNIX which do not support multiple file versions. +.le +.ls subfiles = yes +Delete subfiles. Not currently used. +.le +.ih +DESCRIPTION +\fIDelete\fR destroys a file or files and returns the space they occupied to +the host system, to be reused for other files. Once a file has been deleted, +it is gone forever (unless a copy exists somewhere). Enabling \fIverify\fR +gives one the opportunity to say yes or no before each file is deleted; this +is particularly useful when \fIfiles\fR is a template. Note that +\fIprotect\fR can be used to protect files from deletion, accidental or +otherwise. Imagefiles are automatically protected by the system to remind +the user to use \fIimdelete\fR to delete images (this is necessary because +an image is stored in more than one physical file). +.ih +EXAMPLES + +1. Delete all files with extension ".x", verifying each file deletion before +it is performed. + + cl> delete *.x ver+ + +2. List all files in the current directory, deleting only those files for +which the user responds to the verify prompt with "yes" or "y". Note that +"delete *" is a very dangerous operation. + + cl> delete * ver+ def=no + +.ih +SEE ALSO +protect, unprotect, imdelete +.endhelp diff --git a/pkg/system/doc/devstatus.hlp b/pkg/system/doc/devstatus.hlp new file mode 100644 index 00000000..bccd7ffe --- /dev/null +++ b/pkg/system/doc/devstatus.hlp @@ -0,0 +1,57 @@ +.help devstatus Jan86 system +.ih +NAME +devstatus -- print status information for a device +.ih +USAGE +devstatus device +.ih +PARAMETERS +.ls device +The device for which status information is requested. +.le +.ls verbose = no +Print additional system dependent device information (may not be implemented +on all systems). +.le +.ih +DESCRIPTION +\fBDevstatus\fR tells whether the named device has been allocated. +In the case of a magtape drive allocated to the current user, additional +information is printed noting the tape position and the type of operation +last performed. If the device is not currently allocated, i.e., available +for allocation, or if the device has already been allocated by another user, +one of the following messages is printed: + +.nf + device is not currently allocated + device is allocated to XXXX +.fi + +A list of the allocatable devices, including the host system names for the +devices, can be obtained by paging the file \fBdev$devices\fR providing +that file has been properly configure by the Site Manager at installation +time. The dev$tapecap file is used to define the tape devices available +on the system. +.ih +EXAMPLES + +1. Get status information for the logical tape drive "mta", which we have +just allocated. Note that the tape position is printed only if we are the +owner of the drive. + +.nf + cl> dev mtb + # Magtape unit `mta' allocated to `smith' Fri 12:04:16 07-Jan-86 + file = 1 + record = 1 + unit just allocated: no i/o has yet occurred +.fi + +.ih +BUGS +Information can only be requested for a single device at a time. +.ih +SEE ALSO +allocate, deallocate +.endhelp diff --git a/pkg/system/doc/directory.hlp b/pkg/system/doc/directory.hlp new file mode 100644 index 00000000..8c4382e9 --- /dev/null +++ b/pkg/system/doc/directory.hlp @@ -0,0 +1,148 @@ +.help directory Mar87 system +.ih +NAME +directory -- list the contents of a file directory +.ih +USAGE +directory [files] +.ih +PARAMETERS +.ls files +A file template specifying the files to be listed, or the name of the directory +whose contents are to be listed. If omitted entirely, the contents of the +current directory are listed. +.le +.ls long = no +Long format listing. The long format listing lists each file on a separate +line, noting the file permissions, file type, file size, modify date, owner, +etc. of each file. +.le +.ls ncols = 0 +If nonzero, the number of columns of output in multicolumn format. +.le +.ls maxch = 18 +The maximum number of characters to be displayed in each filename. +Truncation may be desirable when listing a directory containing one or two +files with very long filenames. +.le +.ls sort = yes +Sort the file list alphabetically. If sorting is disabled the directory +program lists the files in the order in which they are read from the +directory, which may or may not be sorted. The directory listing is produced +line by line as files are read from the directory, rather than accumulating +the entire file list in memory before composing the table, hence this is the +fastest method of listing a directory, particularly if the directory is very +large. +.le +.ls all = no +List all files, including the hidden ("." prefixed) files, and files with +reserved filename extensions used internally by the VOS. +.le +.ih +DESCRIPTION +The \fBdirectory\fR task lists or prints information describing some subset +of the files in a directory or directories. If no name template is given, +"." is assumed, i.e., all files in the current directory are listed. + +The long format listing gives a file type string, followed by +the name of the owner of the file, the file size, date and time at which +the file was last modified, and lastly the file name. +The file type string has fields noting if the file is a directory file (d), +an executable file (x), a text or binary file (t or b), a protected file (p), +and summarizing the file permissions (read or write, r or b) for the owner, +the group, and the rest of the world. A minus sign indicates that the file +does not have that particular attribute. + +All file names are printed in the IRAF virtual filename syntax, which is the +same on all host machines. IRAF filenames may be up to 32 characters in +length, may contain any combination of alphanumeric characters, underscore, +or period, and are case sensitive. Some of the common filename extensions +are listed below; these are mapped to and from the host filename extensions +when a file is accessed, a directory is listed, or a filename template is +expanded. + +.nf + .a object library + .c C source file + .cl CL source file + .e executable (runnable) file + .f Fortran source file + .gX generic source file (X=[cx]) + .h global header file + .hlp help file + .o object file + .par CL parameter file + .s assembler source file + .x SPP source file +.fi + +When listing large directories, the time required to accumulate and sort the +entire directory in memory before producing the output listing may become +significant (i.e., more than a few seconds). If this happens, try setting +the \fIsort\fR option to \fIno\fR, and the directory listing should appear +immediately. +.ih +EXAMPLES + +1. List all the files in the current directory in tabular format. + + cl> dir + +2. Print detailed information on all files in the current directory. + +.nf + cl> dir l+ + -t-rwr-r- iraf 269 Oct 16 1983 README + dt-rwrwr- iraf 1024 Feb 7 12:48 doc + -t-rwr-r- iraf 60 Jan 30 1984 files.par + -t-rwr-r- iraf 420 Jan 30 1984 files.x + -b-rwrwr- system 187338 Jan 29 19:27 libpkg.a + xb-rwr-r- iraf 363520 Jan 29 19:29 x_system.e + -b-rwrwr- system 5037 Jan 19 22:15 x_system.o + -t-rwr-r- iraf 633 Jan 19 22:01 x_system.x +.fi + +3. Print a single column listing of all the files with extension ".h" +in the logical directory "lib$". + +.nf + cl> dir lib$*.h l+ + lib$chars.h + lib$clio.h + lib$clpopn.h + (etc) +.fi + +4. While in the "system" directory, print the contents of the parallel +directory "dataio". + +.nf + cl> cd pkg$system + cl> dir ../dataio +.fi + +5. Test if the file "alpha" exists in the current directory. In the example, +the output given indicates that the file was not found. + +.nf + cl> dir alpha + no files found +.fi + +6. Print the contents of the directory USR$2:[IRAF.LOCAL] on the remote VMS +node "draco" (requires IRAF network access to the remote node). + +.nf + cl> dir draco!usr\$2:\[iraf.local] +.fi +.ih +BUGS +There is no provision for wildcarding directories, e.g., "dir */*.x". +The long format listing can currently only be sorted by filename (although +the \fIsort\fR program may be used in a pipe). The file existence test will +not be performed if individual files are named as list elements within +a filename template. +.ih +SEE ALSO +files, pathnames +.endhelp diff --git a/pkg/system/doc/diskspace.hlp b/pkg/system/doc/diskspace.hlp new file mode 100644 index 00000000..538f308d --- /dev/null +++ b/pkg/system/doc/diskspace.hlp @@ -0,0 +1,33 @@ +.help diskspace Feb85 system +.ih +NAME +diskspace -- summarize disk space utilization +.ih +USAGE +diskspace +.ih +DESCRIPTION +\fIDiskspace\fR lists the disk devices available on the host system, +giving the name, capacity, and free space available on each device. +The format and contents of the output are host system dependent. +.ih +EXAMPLE + +1. Print the available diskspace (UNIX host). + +.nf + cl> disk + Filesystem kbytes used avail capacity Mounted on + /dev/hp0a 7421 5312 1366 80% / + /dev/hp0g 38430 5340 29246 15% /tmp + /dev/hp0h 51598 38848 7590 84% /usr + /dev/ra0a 8007 5657 1549 79% /mnt + /dev/ra0d 88179 46043 33318 58% /u1 + /dev/ra0e 54382 46694 2248 95% /local + /dev/ra0f 145435 93733 37158 72% /u2 + /dev/ra0g 28720 350 25497 1% /usr/spool + /dev/ra0h 79798 41696 30122 58% /iraf + /dev/ra1h 397102 306688 50702 86% /tmp2 + /dev/ra2h 397102 275010 82380 77% /tmp3 +.fi +.endhelp diff --git a/pkg/system/doc/fcache.hlp b/pkg/system/doc/fcache.hlp new file mode 100644 index 00000000..b5230307 --- /dev/null +++ b/pkg/system/doc/fcache.hlp @@ -0,0 +1,140 @@ +.help fcache Jun2011 system +.ih +NAME +fcache -- list, clean or manipulate the file cache +.ih +USAGE +fcache cmd +.ih +PARAMETERS +.ls cmd +Cache command to execute. A description of each command is given below. +.le +.ls pattern = "*" +Filename substring pattern to match when initializing the cache with +the \fIinit\fR command. +.le +.ls src = "" +Source string used to generate the cache filename. This is typically +the full path to a local file being cached or a URL. +.le +.ls fname = "" +Name of the file in the cache. +.le +.ls extn = "" +Cache filename extension. +.le +.ls age = -1 +Age of the file (in days) to be purged with the \fIpurge\fR command. A value +less than zero means that the \fIcache_age\fR environment variable should +is used to set the age, a value of zero means to delete all files in the +cache (same as the \fIinit\fR command), a value greater than zero means +that files older than this age will be deleted. +.le +.ls verbose = no +Print status information as the task processes the command. +.le +.ls wait = yes +Block on operation? If 'yes' then the task will block until the requested +file becomes available in the cache. +.le +.ls cache = "cache$" +Cache directory to be used. +.le + +.ih +DESCRIPTION +The \fIFCACHE\fR command is used to list or manage the system file cache +named by the \fIcache\fR parameter. If the \fIcache\fR directory does not +exist, it will be created when required. The \fIcache_age\fR environment +variable determines the default maximum age of files in the cache, older +files are automatically removed by the login.cl as part of the startup +process. + +The IRAF file cache is used primarily to cache local copies of URLs in the +system to prevent repeated downloads when accessing URLs from tasks. This +allows a URL to be passed to multiple tasks without explicitly requiring +the user to create a named (temporary) file themselves. + +The \fIcmd\fR parameter determines the action to take, other parameters are +used as needed depending on the command according to the following table: + +.nf + Command Input Pars Output Pars Action + ------- ---------- ----------- ------ + init pattern Initialize the cache + purge age Purge old files + destroy Destroy the cache + list List cache contents + lookup src fname,extn Lookup a file in the cache + access src Is file in cache? + add src extn fname Add file to the cache + delete src fname Delete file from cache + wait src Wait for access to file +.fi + +The \fIlookup\fR command works in two ways: If a \fIsrc\fR string is +provided then the \fIfname\fR parameter will contain the matching cached +file (and \fIextn\fR will contain the optional extension), if the \fIfanme\fR +parameter is specified then on output \fIsrc\fR will contain the original +filename/URL. + +.ih +EXAMPLES + +1. Remove all "url" files from the cache. +.nf + cl> fcache init pattern="url" +.fi + +2. List the contents of the file cache. +.nf + cl> fcache list +.fi + +3. Destroy a cache directory (i.e. remove it entirely). +.nf + cl> fcache destroy cache="/tmp/cache" +.fi + +4. Purge all cache files older than 7 days: +.nf + cl> fcache purge age=7 +.fi + +5. Determine if a URL is already in the cache: +.nf + cl> fcache add src="/tmp/dpix.fits" + cl> fcache list + f1128531670 1 /tmp/dpix.fits + f789045894 1 http://iraf.noao.edu/vao/dpix.fits + cl> fcache access src="/tmp/dpix.fits" + yes + cl> fcache access src="http://iraf.noao.edu/vao/dpix.fits" + yes +.fi + +6. Delete a cached URL: +.nf + cl> fcache delete src="http://iraf.noao.edu/vao/dpix.fits" +.fi + +7. Add a local file to the cache, then look it up: +.nf + cl> fcache add src="/tmp/test.fits" + cl> fcache lookup src="/tmp/test.fits" + cl> =fcache.fname + f1295587026 + cl> fcache lookup fname="f1295587026" + cl> =fcache.src + /tmp/test.fits +.fi + + +.ih +BUGS + +.ih +SEE ALSO +head +.endhelp diff --git a/pkg/system/doc/files.hlp b/pkg/system/doc/files.hlp new file mode 100644 index 00000000..f2a0996f --- /dev/null +++ b/pkg/system/doc/files.hlp @@ -0,0 +1,72 @@ +.help files Jun86 system +.ih +NAME +files -- expand a file name template into a list of files +.ih +USAGE +files template +.ih +PARAMETERS +.ls template +A file name template specifying the set of files to be listed. +.le +.ls sort = "yes" +Sort the file list. +.le +.ih +DESCRIPTION +\fIFiles\fR lists all files matching the given template. The existence of +the listed files is checked only if pattern matching is used, hence \fIfiles\fR +may also be used to parse a comma delimited list of strings which are not +necessarily filenames. \fIFiles\fR performs the same function as "dir l+" +but is simpler and more convenient to use when generating file lists. + +The \fIfiles\fR task and all other tasks which operate upon groups of files +use the \fBfile template\fR facility to specify the set of files to be +operated upon. This should not be confused with the \fBimage template\fR +facility, used by tasks which operate upon sets of images and which is +documented in the manual page for the \fIsections\fR task. + +Pattern matching in a file template is provided by the usual pattern matching +meta-characters "*?[]", documented in the CL User's Guide. Pattern matching +is used to select files from one or more directories. In addition, the +filename template notation provides two operators for generating new filenames +from the matched filenames. These are the \fBconcatenation\fR operator "//", +and the \fBstring substitution\fR operator "%chars%newchars%". +The concatenation operator concatenates either a prefix to a filename, +or a suffix to the root of a filename. The string substitution operator +uses the "chars" to match filenames, and then replaces the "chars" by the +"newchars" to generate the final output filename. Either string may be null +length to insert into or delete characters from a filename. +.ih +EXAMPLES + +1. Generate a single column list of files in the current directory, +sorted in ASCII collating sequence. + + cl> files + +2. Generate an unsorted single column list of files in logical directory +"lib$". Each entry in the output list is of the form "lib$...". + + cl> files lib$ sort- + +3. Generate a file list to be used to make a set of new files. The new file +names will be the old file names with "_1" concatenated to the root, e.g., +"root.x" would map to "root_1.x" and so on. + + cl> files root.*//_1 + +4. Generate a file list similar to that in [3], adding a directory prefix +to each filename. + + cl> files dir$//root.* + +5. Use string substitution to change the filename extension of a set of files +to ".y". + + cl> files root.%*%y% +.ih +SEE ALSO +directory, pathnames, images.sections +.endhelp diff --git a/pkg/system/doc/gripes.hlp b/pkg/system/doc/gripes.hlp new file mode 100644 index 00000000..3938e1ea --- /dev/null +++ b/pkg/system/doc/gripes.hlp @@ -0,0 +1,67 @@ +.help gripes Mar86 system +.ih +NAME +gripes -- send gripes or suggestions to the system +.ih +USAGE +gripes subject +.ih +PARAMETERS +.ls subject +The subject of the gripe; any string, usually the name of package or task +to which the gripe refers. +.le +.ls verbose = yes +Print instructions on how to enter text whenever \fIgripes\fR is run. +.le +.ih +DESCRIPTION +The \fBgripes\fR task is used to post complaints, suggestions, or any other +formal or informal comments regarding the IRAF system. Each gripe is +appended to the system gripesfile "hlib$gripesfile", a public file which +can be read by anyone by simply typing "page hlib$gripesfile" within IRAF. +Use \fBtail\fR instead of \fBpage\fR to read only the most recent gripes. +A copy of each gripe is also sent immediately to one or members of the IRAF +group via electronic mail, to insure that the gripe gets read promptly (this +feature is not available on all host systems). + +Gripe text is read from the standard input. A line containing only a period +terminates the gripe, as does the end of file character (e.g., <ctrl/z>). +If the line containing only "~e" is entered a text editor will be called up +to edit the text of the gripe. + +Users are encouraged to use the gripe facility at will. Be assured that +someone will at least read the gripe, although there is no guarantee that +any action will be taken. In many cases there will be no response from the +system, but nonetheless the gripe will be seen and it may well influence +the direction in which the system evolves. Do not avoid posting gripes for +fear that you do not understand something about the system; if enough users +find some aspect of the system or a program confusing then that is more +than sufficient reason for a gripe. +.ih +EXAMPLES + +1. The user has discovered some nasty features of the \fIimdelete\fR task +and enters the following gripe. Note the use of the "." to terminate +the text. + +.nf + cl> gripe + Subject: image deletion + Enter text of gripe. Type <eof> or '.' to quit: + + IMDEL * will delete non image files as well as images! + It should be possible to delete images with the normal + DELETE command. + . + cl> +.fi +.ih +BUGS +There is currently no provision for communicating gripes from a remote site +back to the site that wrote the software, unless some person manually mails +a gripe (or the accumulated gripesfile). +.ih +SEE ALSO +news +.endhelp diff --git a/pkg/system/doc/head.hlp b/pkg/system/doc/head.hlp new file mode 100644 index 00000000..0b2f6393 --- /dev/null +++ b/pkg/system/doc/head.hlp @@ -0,0 +1,39 @@ +.help head Nov84 system +.ih +NAME +head -- print the first few lines of the specified files +.ih +USAGE +head files +.ih +PARAMETERS +.ls files +The list of files to be dealt with, quite possibly given as +a template, such a "image*". +.le +.ls nlines = 12 +The number of lines to be printed. +.le +.ih +DESCRIPTION +\fIHead\fR prints, on the standard output, the first \fInlines\fR of each +file that matches the given file list. If the file list has more than one +name in it, a short header precedes each listing. +.ih +EXAMPLES + +1. Print the first 12 lines of each help file in the current directory. + + cl> head *.hlp + +2. Print the first line of each help file. + + cl> head *.hlp nl=1 + +3. Print the most recently defined \fIset\fR environment definitions. + + cl> set | head +.ih +SEE ALSO +tail, page +.endhelp diff --git a/pkg/system/doc/help.hlp b/pkg/system/doc/help.hlp new file mode 100644 index 00000000..74a53917 --- /dev/null +++ b/pkg/system/doc/help.hlp @@ -0,0 +1,599 @@ +.help help Oct01 system +.ih +NAME +help -- print online documentation for the named modules or packages +.ih +USAGE +help [template] +.ih +PARAMETERS +.ls template +A string listing the modules or packages for which help is desired. +Each list element may be a simple name or a pattern matching template. +Abbreviations are permitted. If \fItemplate\fR is omitted a long format +menu will be printed for the current package, listing each task (or +subpackage) and describing briefly what it is. +.le +.ls file_template = no +If this switch is set the template is interpreted as a filename matching +template, and all help blocks found in the named files are output. The help +database is not searched, hence manual pages can be printed or documents +may be formatted without entering the files into a help database. +In other words, "help file.hlp fi+" makes it possible to use \fIhelp\fR as +a conventional text formatter. +.le +.ls all = no +Print help for all help modules matching \fItemplate\fR, rather than only the +first one found. +.le +.ls parameter = "all" +If the value of this parameter is not "all", only the help text +for the given parameter will be printed. +.le +.ls section = "all" +If the value of this parameter is not "all", only the help text for the +given section (e.g. "usage", "description", "examples") will be printed. +.le +.ls option = help +The option parameter specifies the type of help desired, chosen from +the following: +.ls help +Print the full help block for the named module. +.le +.ls source +Print the source code for the module (which often contains additional +detailed comments). +.le +.ls sysdoc +Print the technical system documentation for the named module. +.le +.ls directory +Print a directory of all help blocks available for the named package. +.le +.ls alldoc +Print all help blocks in the file containing the help block for +the named procedure (i.e., both the user and system documentation). +.le +.ls files +Print the names of all help files associated with the named modules or +packages. +.le +.ls summary +Print only the titles and sizes of help blocks in referenced help files. +The contents of the blocks are skipped. Titles are printed for \fIall\fR +help blocks found in the file containing the help block for the named module. +.le +.le +.ls page = yes +Pause after every page of output text. Turning this off for large documents +speeds up output considerably. +.le +.ls nlpp = 59 +The number of lines per page if output is redirected, e.g., to \fIlprint\fR. +.le +.ls lmargin = 1 +Left margin on output. +.le +.ls rmargin = 72 +Right margin on output. +.le +.ls search = no +If enabled the +.hr #l_template template +is interpreted as a search string and the task +is started with the search panel open with the results of the search. The +.hr #l_file_template file_template +parameter is ignored with search turned on. +.le +.ls home = "" +The home page for the task. If not set and no +.hr #l_template template +is specified +the task will start with the online help in the main window, otherwise it +may be set to a filename to be displayed when the task starts. This file +may contain a text help block which will be formatted before display, or +it may be a valid HTML file. See below for a description of the format of +a homepage file which provides links to tasks. +.le +.ls printer = "printer" +Default hardcopy printer name. If the \fIvalue\fR of the parameter is the +reserved string "printer", the actual device is the value of the CL +environment variable \fIprinter\fR. +.le +.ls showtype = no +Add task-type suffix in package menus? +.le +.ls quickref = "uparm$quick.ref" +Name of the quick-reference file used for searching. This file is created +the first time the task is run in GUI mode or whenever it doesn't exist, +or when any help database file has been updated. +.le +.ls uifname = "lib$scr/help.gui" +The user interface file. This file is what defines the look and behavior +of all the graphical user interface elements. Experts may create variants +of this file. +.le +.ls helpdb = "helpdb" +The filename of the help database to be searched. If the \fIvalue\fR of the +parameter is the reserved string "helpdb", the actual filename is the value +of the CL environment variable \fIhelpdb\fR. +.le +.ls device = "terminal" +Output device if the standard output is not redirected. Allowable values +include: +.ls terminal +If the \fIvalue\fR of +the parameter is the reserved string "terminal", the actual device name is +the value of the CL environment variable \fIterminal\fR. +.le +.ls text +Output the formatted help page as plain text. +.le +.ls gui +Invoke the GUI for browsing the help system. This option will only work if +the \fIstdgraph\fR environment variable is set the \fIxgterm\fR, and the +user is running IRAF from an \fIXGterm\fR window. +.le +.ls html +Output the formatted help page as HTML text. +.le +.ls ps (or postscript) +Output the formatted help page as postscript. +.le +.le +.ih +BASIC USAGE +Despite the complex appearing hidden parameters, \fBhelp\fR is easy to use +for simple tasks. \fBHelp\fR is most commonly used to get help on the current +package, and to get help on a program named in a CL menu. To get help on +the current package one need only type \fBhelp\fR without any arguments. +For example, if the current package is \fBplot\fR, the command and its output +might appear as follows: + +.nf + pl> help + contour - Make a contour plot of an image + graph - Graph one or more image sections or lists + pcol - Plot a column of an image + pcols - Plot the average of a range of image columns + prow - Plot a line (row) of an image + prows - Plot the average of a range of image lines + surface - Make a surface plot of an image + pl> +.fi + +To get help on a module one supplies the module name as an argument, + + pl> help graph + +and the manual page for the \fBplot.graph\fR program will be printed on the +terminal. To get a hardcopy of the manual page on the printer, the output +may be redirected to the line printer, as follows: + + pl> help graph | lprint +.ih +DESCRIPTION +The function of the \fBhelp\fR program is to perform a depth first search +of the help database \fIhelpdb\fR, printing help for all packages and modules +matching the template. By default the standard IRAF help database is searched, +but any other help database may be searched if desired. A help database is +precompiled with the \fBmkhelpdb\fR program to speed up runtime searches for +help modules. The standard IRAF help database contains the documentation and +source for all CL programs and system and math library procedures installed +in IRAF. + +A help template is a string type parameter to the CL. The form of a template +is a list of patterns delimited by commas, i.e., + + "pattern1, pattern2, ..., patternN" + +The form of a pattern is + + package_pattern.module_pattern + +If the "." is omitted \fImodule_pattern\fR is assumed. The standard pattern +matching meta-characters, i.e., "*?[]", are permitted in patterns. +Simple patterns are assumed to be abbreviations. + +.ih +GUI OPERATION + +The GUI component of the task is a front-end to the IRAF +.hr system.help \fBhelp\fR +task which provides on-the-fly conversion of help documents to HTML for +presentation in the GUI or formatted PostScript for hardcopy. +The GUI is started by setting the +.hr #l_device \fIdevice\fR +parameter to the special value \fIgui\fR, it is only available when using +an XGterm window to start IRAF and assuming the \fIstdgraph\fR environment +variable is set to \fRxgterm\fR. + +Help pages may be loaded on the command line, through use of a +file browser, or by navigating the help databases using a familiar CL +package menu scheme. It also features a search capability similar to the +.hr system.references \fBreferences\fR +task and a complete history mechanism. + +When invoked with no command line arguments the task starts as a browser +and the user is presented with a GUI that has the toplevel CL package menu +in the upper navigation window. The main display window below will contain +any help page specified in the +.hr #l_template template +parameter or loaded on +the command line by specifying the +.hr #l_template template +and +.hr #l_file_template file_template +parameters. If the +.hr #l_search search +parameter is enabled the +.hr #l_template template +is taken to be a search phrase and the database is searched for tasks +matching the keyword and the GUI will appear with the search panel mapped +so the user can select the task help to +view. When no +.hr #l_template template +is given the main display window will start with the page specified by the +.hr #l_home home +parameter, this can be a user-defined HTML file giving links to specific tasks +(see below for details) or if +.hr #l_home home +is empty the display will contain the online help for the task. + +The first time the task is run, or whenever the help database is updated, +a quick reference file (specified by the task +.hr #l_quickref quickref +parameter) and package menu file will be created in the user's \fIuparm\fR +directory to speed up help searching and subsequent startups of the task. + +.ih +NAVIGATING THE HELP SYSTEM +When run as a GUI browser \fIHELP\fR works very much like any WWW browser. +The top panel is a list widget that will always contain a CL package listing, +at startup this will be the toplevel \fI"Home"\fR package menu one would see +when first logging into the CL containing the core system packages, NOAO +package, and any site-specific external package, or in the case of starting +with a specific task it will be the parent package for the task. Additionally, +system documents for the +.hr os \fBos\fR +HSI routines and the +.hr sys.imfort \fBimfort\fR +and +.hr math \fBmath\fR +interfaces will be available in the \fIHome\fR package although +these are programmatic interfaces and not tasks which can be executed. + +New packages or task help pages are loaded by selecting an item from the +package menu list using the left mouse button. If the requested item is a +package, the menu listing will change as though the package were loaded in +the CL, and the help display panel will contain a listing of the package +tasks with a one-line description for each task such as would be seen with +a \fI"help <package>"\fR command using the standard task. New items may then +be selected using either the menu list or links in the display panel. If the +item is a task, the help page for the task will appear in the display panel. +In either case new pages may be selected from the menu listing. + +Specific help documents may also be requested by entering the task/package +name in the \fBTopic\fR text widget above the menu list. As when selecting +from the package menu list, items selected this way will cause the menu +list to change to the package menu for the parent package if the item is a +task (displaying the help page in the display panel) or the package menu +if the item is a package (displaying the one-liner package listing in the +display panel). + +Using the \fBBack\fR button will revert to the previous page in the history +list which will either be the previously loaded package or help page. +Similarly, selecting the \fBForward\fR button will move the next page further +down in the history list, either button will become insensitive when the +end of the list on either end is reached. Selecting the \fBUp\fR button will +cause the browser to immediately jump up the previous package, skipping +over any help pages that were loaded in between. The \fBHome\fR button will +cause the default homepage (either the user-defined page if specified by the +task \fIhome\fR parameter or the online help) to be displayed. Browsing +in this way can also be done using the navigation menu created by hitting +the right mouse button while in the main display panel. + +Users can also jump to specific pages in the history list using the +\fBHistory\fR button on the main menubar. The right column of the menu +will indicate whether the item is a task, package, internal link or a text +file. The history list is truncated at about 40 entries in the menu but +the user may work back incrementally by selecting the last item of the +menu, after which the History button will display the previous 40 entries. +The history list may be cleared except for the current page by selecting +the \fIClear History\fR menu item. + +.ih +BROWSING A HELP DOCUMENT +Once a help page is loaded the middle menubar above the display panel +will change to activate widgets based on the position within the history +list and options available for a particular page. The left-most group +of buttons are the standard navigation buttons described above. +The middle group of buttons contains the \fBSections\fR and +\fBParameters\fR buttons which are used to browse within a help document. +The \fISections\fR button is a menu listing all of the sections found +within a help page, allowing the user to jump to a specific section +rather than scrolling through the entire document. The \fISections\fR +menu is also available using the middle mouse button from the +main display area. The \fIParameters\fR button is similarly a menu +listing of all task parameter help sections found within the document. +Both or either of these buttons will become insensitive when no section +or parameter information is found in the document. + +The right-most group of buttons represent the various help options available +for each page. The default is to get the task help, however help pages +may have an associated \fBsource\fR file or \fBsysdoc\fR (e.g. if the task is +a CL script there may be a pointer to the script source itself, or a package +may have a general overview document listed as the system document). Once +a help page is loaded these buttons will change become sensitive if that option +is available, simply select the button to view the option. Selecting the +\fBFiles\fR button will bring up a panel listing all the files associated +with a particular help topic. When a help topic is selected and an option is +defined but the file does not exist, the options button will display a yellow +diamond icon even if the button is insensitive, a green icon indicates the +currently selected option. This feature may be disabled by selecting the +"Show missing files" item from the main menubar \fBOptions\fR menu. + +.ih +SEARCHING +Searching the help database is done by selecting the \fBSearch\fR button +from the main menubar to bring up the search panel. Users may then enter +one or more keywords into the \fBTopic\fR field at the bottom of the panel +and initiate the search with either a carriage return or hitting the +\fISearch\fR button just beside it. The panel will then show a list of all +tasks and packages which match the search phrase along with a one-line +description of the task. Help pages may be displayed by selecting either the +task or package link with the left mouse button, in both case the package +menu list on the main help window will be updated to list the package +contents allowing other tasks from that package to be selected in the normal +way. + +By default the exact phrase entered in the topic window will be used for the +search. This can be relaxed by toggling the "Require exact match" button +at the top of the panel. For example, to search for all tasks matching +\fIeither\fR the keyword "flat" or "field" turn off the exact match +toggle and the search will return not only tasks matching "flat field" but +also any task description containing only one of the words such as the +VELVECT task which plots velocity \fIfield\fRs. + +Within a help document itself one can search for a string by selecting +the \fBFind\fR button from the main menubar to bring up a panel used to +enter the search string. When the text is entered the main display +window will reposition itself and highlight the text found within the +document. Searches can be repeated and will wrap around the document +automatically, searches can be done either forward or backward through +the text and may be case insensitive. + +.ih +USER_DEFINED HOME PAGES +By default the \fIhelp\fR GUI will start with the online help page displayed +in the main help window. The user can change this by setting the task +\fBhome\fR parameter to be a path to any valid file. This file may be plain +text, a help document in LROFF format which will be converted to HTML for +display, or a native HTML document. + +HTML files may contain URLs of the form +.nf + \fB<a href=\fI[package.]task\fB>\fIurl_text\fB</a> +.fi + +where \fIurl_text\fR is the text to appear in the window and the URL itself +consists of an optional package and task name delimited by a period. For +example, to create a link to the +.hr onedspec.splot \fBsplot\fR +task in a document one would use the URL +.nf + \fB<a href=onedspec.splot>splot</a>\fR +.fi + +In this way users can create a homepage which serves as a \fI"bookmark"\fR +file or index of shortcuts to the most commonly accessed help pages. + +.ih +LOADING FILES +Text files may be loaded on the command line when starting the task by +specifying the filename and setting the +.hr #l_file_template file_template +task parameter. The named file +will be searched for a \fI.help\fR LROFF directing indicating it contains +a help block that will be converted to HTML for display. If no help +block is found the file will be displayed as-is, meaning existing +HTML documents can be loaded and will be formatted correctly. + +Once the task is running users may load a file by selecting the \fBOpen +File...\fR menu item from the main menubar \fBFile\fR menu or the +right-mouse-button menu from within the main display area. This will +open a file browser allowing users to change directories by using the +navigation buttons at the top of the panel, or selecting items from the +leftmost directory listing. Selecting a file on the rightmost list will +cause it to be loaded and automatically formatted if it contains a help +block. The file list may be filtered to select only those files matching +a particular template by changing the \fBFilter\fR box at the top of +the panel. Filenames or directories may be entered directly using the +\fBSelection\fR box at the bottom of the panel. + +.ih +SAVING FILES +Once a file has been loaded in the browser it may be saved to disk as +either \fIsource\fR (i.e. the original LROFF file if that was converted +for the display, or whatever file is currently displayed regardless of +format), \fItext\fR to save formatted plain text such as that produced +by the standard \fBhelp\fR task, \fIHTML\fR to save the converted HTML +used in the display, or \fIPostScript\fR to save formatted PostScript of +the document such as that sent to the printer using the \fBPrint\fR +button. Not all options will be available depending on the format of the +input text, unavailable options will be insensitive in the GUI. + +The \fBSave\fR panel is opened by selecting the \fBSave As...\fR menu +item from the main menubar \fBFile\fR menu or the right-mouse-button +menu from within the main display area. The file browser operates the +same as when loading images, the only difference is that file selection +simply defines the filename to be used and does not cause the save to +occur automatically. Users can overwrite existing files by selecting the +\fIOptions\fR toggle at the bottom of the panel. + +.ih +HARDCOPY OUTPUT AND SAVING DISK FILES. +Help pages may be output to any configured IRAF printer by selecting the +main menubar \fBPrint\fR button to bring up the print panel. Task help pages +will be converted to formatted PostScript and may be sent to either a +printer or saved to disk depending on the selection made in the printer +panel. If the printer name is set to the special value \fI"printer"\fR then +the device named by the CL \fIprinter\fR environment variable will be used. +When saving to disk files the default action is to save to a filename whose +name is the task name plus a ".ps" extension. Either of these are changeable +within the GUI as is the default page size to be used when generating the +PostScript. + +The main menubar \fBFile\fR button can also be used to bring up the file +browser in order to save the current document to disk. Help pages may be +saved as either the origin LROFF source for the file, formatted text as you +would get from the standard help task, HTML as is displayed in the GUI, or +formatted PostScript. The choice of formats is dictated by the type of file +being displayed (e.g. you cannot save PostScript of a program source). + +.ih +LROFF DIRECTIVE EXTENSIONS FOR HTML +To better support HTML links within documents and to other help pages two +new directives have been added to the LROFF text formatter. These are +\fB.hr\fR to specify a link (an HTML \fIHREF\fR directive) and \fB.hn\fR +to specify a name (an HTML \fINAME\fR directive). The syntax for these are +as follows: +.nf + + \fB.hn\fI <name>\fR + \fB.hr\fI <link> <text> \fR +.fi + +where \fI<name>\fR is the destination name of an internal link, \fI<link>\fR +is the URL of the link to be created, and \fI<text>\fR is the text to be +displayed in the HTML. The URL syntax is either a '#' character followed +by a destination name, a simple \fItask\fR name or \fIpackage\fR name, +or a \fIpackage.task\fR pair giving a more precise task. For internal links +the current document is repositioned so the name is at the top of the display, +for task help links new help pages will be loaded in the browser. + +These directives are ignored when converting the LROFF to either formatted +plain text or PostScript. + +.hn examples_target +.ih +GUI EXAMPLES +1) Start \fIhelp\fR as a GUI browser: +.nf + + cl> help dev=gui +.fi + +2) Begin by searching for the phrase 'gauss', tasks and packages may be +selected from the search panel which will appear when the task starts: +.nf + + cl> help gauss dev=gui search+ +.fi + +3) Load an LROFF help page in the browser at startup +.nf + + cl> help mytask.hlp dev=gui file+ +.fi + +.ih +EXAMPLES + +1. Print the help text for the program \fIdelete\fR in the package +\fIsystem\fR (output will be directed to the terminal): + +.nf + cl> help system.delete +or + cl> help delete +or + cl> help del +.fi + +2. Print the help text on the line printer: +.nf + + cl> help delete | lprint +.fi + +3. Print help for the current package: +.nf + + cl> help +.fi + +4. Print the usage section of all modules in the package \fBimages\fR: +.nf + + cl> help images.* section=usage +.fi + +5. Print a directory of all help blocks in the packages \fBclpackage\fR +and \fBclio\fR (and any others whose names begin with the string "cl"): +.nf + + cl> help cl* op=dir +.fi + +6. Print a directory of each package in the database (useful for getting an +overview of the contents of a help database): +.nf + + cl> help * op=dir +.fi + +7. Print the source for all of the string utilities in the system library +package \fBfmtio\fR: +.nf + + cl> help fmtio.str* op=source +.fi + +8. Find all tasks that delete something: +.nf + + cl> help * | match delete +.fi + +9. Print the manual pages for the \fIhelp\fR and \fIlprint\fR tasks on the +default printer device: +.nf + + cl> help help,lprint | lpr +.fi + +10. Capture the manual page for task \fIhedit\fR in a text file, in a form +suitable for printing on any device. +.nf + + cl> help hedit dev=text > hedit.txt +.fi + +11. Print the manual page for task \fIhedit\fR as a Postscript file. +.nf + + cl> help hedit dev=ps | lprint +.fi + +.ih +BUGS +On some systems, typing the next command keystroke before the end-of-page +prompt is printed may result in the character being echoed (messing up the +output) and then ignored when raw mode is enabled for the prompt. + +.ih +SEE ALSO +.hr system.references references +, +.hr system.phelp phelp +, +.hr system.mkhelpdb mkhelpdb +, +.hr system.hdbexamine hdbexamine +, +.hr system.mkmanpage mkmanpage +, +.hr system.lroff lroff +, the online task help documents. +.endhelp diff --git a/pkg/system/doc/lprint.hlp b/pkg/system/doc/lprint.hlp new file mode 100644 index 00000000..33997b0e --- /dev/null +++ b/pkg/system/doc/lprint.hlp @@ -0,0 +1,65 @@ +.help lprint Nov84 system +.ih +NAME +lprint -- print a file or files +.ih +USAGE +lprint files +.ih +PARAMETERS +.ls files +A filename template specifying the files to be printed. +.le +.ls device = "printer" +The output device. If the value of \fIdevice\fR is the reserved string +"printer", the name of the actual printer device is taken from the value +of the environment variable "printer". +.le +.ls map_cc = yes +If set to "yes", any unprintable characters embedded in the text are printed +in the form "^X", where ^A is <ctrl/A> (ASCII 1), and so on. +.le +.ls paginate = "auto" +If \fIpaginate\fR is set to "auto" and the standard input is not redirected, +pages are broken and a header is printed at the top of each page. +If \fIpaginate\fR is set to "auto" and the standard input \fIis\fR redirected, +the input text is not paginated, allowing proper operation when \fIlprint\fR +is used in a pipe, e.g., taking input from \fIhelp\fR. +If "paginate" is set to "yes", pages are broken even if the input text +is being read from STDIN. +.le +.ls label = "STDIN" +If displaying a header with input from the standard input, use the +"label" string where the filename would appear in a normal header. +.le +.ih +DESCRIPTION +The named files, or the standard input, are printed on the standard +line printer device. Each file is printed starting at the top of a new +page, with a header giving the page number and the date of last modification +for the file. Pagination and headers are normally suppressed when reading +input from the standard input, but may be enabled if desired. +.ih +EXAMPLES + +1. Print all files with an extension of either ".x" or ".h", followed by +all files with the extension ".com". Note that filename sorting occurs only +within a comma delimited field of the filename template, hence the "*.[xh]" +files are printed in sort order, followed by the ".com" files. + + cl> lprint *.[xh],*.com + +2. Print the output of the \fIimstat\fR task on the versatec printer, +paginating the output with the given label on each page. Note that the +command may be broken after the "pipe" character without need for +explicit backslash continuation. + +.nf + cl> imstat nite1.* | + >>> lprint pag+ label="Image Statistics" device=versatec +.fi + +.ih +SEE ALSO +type +.endhelp diff --git a/pkg/system/doc/match.hlp b/pkg/system/doc/match.hlp new file mode 100644 index 00000000..3338af3d --- /dev/null +++ b/pkg/system/doc/match.hlp @@ -0,0 +1,77 @@ +.help match Nov84 system +.ih +NAME +match -- match a pattern against the lines in a file or files +.ih +USAGE +match pattern files +.ih +PARAMETERS +.ls pattern +The pattern to be matched. A pattern may contain any of the +pattern matching \fImeta-characters\fR described below. +.le +.ls files +A template specifying the file or files to be searched. Omitted if the +standard input is redirected. +.le +.ls meta-characters = yes +Set to "no" to disable the pattern matching meta-characters, e.g., when +you want to explicitly match one of the meta-characters as a regular character. +.le +.ls stop = no +If \fIstop\fR is enabled, lines with match the pattern are "stopped" (not +passed to the output), otherwise only those lines with match the pattern +are output. +.le +.ls print_file_names = yes +If more than one file is being searched, preface each printed line +with the "file_name: ". +.le +.ih +DESCRIPTION +The listed files are searched for the given pattern, copying each line that +matches to the standard output. If "stop" is set the action is reversed, +i.e., all lines are passed on to the output except those which match the +pattern. If no files are named text is read from the standard input. +The pattern matching meta-characters are described in the table below. + +.nf + ^ matches the beginning of a line + $ matches the end of a line + ? matches any single character + * matches zero or more of whatever is at the left + [12345] matches any single character in the given set + [1-5] matches any single character in a range + [^a-z] matches any character NOT in the range/set + # matches whitespace + {chars} turns off case sensitivity inside the braces + \ used to include a meta-character in the pattern +.fi + +If more than one file is being searched, each output line is prefixed +with its file name. +.ih +EXAMPLES + +1. From all the lines displayed by "set", print only those that have +the string "tty" somewhere in them. + + cl> set | match tty + +2. Find all tasks that delete something. + + cl> help * | match delete + +3. Delete all the "red" objects from the list file "catalog". + + cl> match red catalog stop+ > newcatalog + +4. Type out the file "spool", omitting all lines that end in a colon, +and paginating the output. + + cl> match ":$" spool stop+ | page +.ih +SEE ALSO +lcase, ucase, translit, sort, unique +.endhelp diff --git a/pkg/system/doc/mkdir.hlp b/pkg/system/doc/mkdir.hlp new file mode 100644 index 00000000..de7a03c4 --- /dev/null +++ b/pkg/system/doc/mkdir.hlp @@ -0,0 +1,34 @@ +.help mkdir May85 system +.ih +NAME +mkdir -- make a new directory +.ih +USAGE +mkdir newdir +.ih +PARAMETERS +.ls newdir +New directory or subdirectory to be made. +.le +.ih +DESCRIPTION +\fIMkdir\fR creates a new directory with the given name. +\fINewdir\fR may be an IRAF virtual directory name (not a logical name) +or a host directory name. +.ih +EXAMPLES + +1. Make a subdirectory named "sub1". + + cl> mkdir sub1 + +2. Make a subdirectory "sub2" below "sub1". The subdirectory "sub1" must +already exist. + + cl> mkdir sub1/sub2 + +3. Make a directory "blue" at the same level in the directory hierarchy as +the current directory (".." is a synonym for the previous directory). + + cl> mkdir ../blue +.endhelp diff --git a/pkg/system/doc/mkscript.hlp b/pkg/system/doc/mkscript.hlp new file mode 100644 index 00000000..5aa33204 --- /dev/null +++ b/pkg/system/doc/mkscript.hlp @@ -0,0 +1,161 @@ +.help mkscript Nov85 system +.ih +NAME +mkscript -- make a script for a command sequence to be run in batch +.ih +USAGE +mkscript script task submit +.ih +PARAMETERS +.ls script +Script file name. Commands will be successively added to this file. +.le +.ls task +Task name of command to be added to the script. If given on the command +line then only commands for this task may be added to the script. +If not given on the command line then the task will query for a task +name for each new command. Currently the task name must not be abbreviated. +.le +.ls submit +Submit the completed script as a background job as the last act of the task? +If not given on the command line the task will query before submitting the +script. +.le +.ls append = no +Append new commands to an existing script file? +If no the file will be deleted first. If \fIverify\fR = yes +the user will be asked to confirm the deletion. +.le +.ls hidden = yes +Include hidden parameters in each command? +.le +.ls verify = yes +Verify each command, any file deletions, and the final script? +.le +.ls logfile = "script.log" +Script log file name. When the script is submitted as a background job +by this task any command and error output is directed to this file. +.le +.ih +DESCRIPTION +A command script is created consisting of a number of commands to be +executed sequentially. The task assumes the responsibility of formatting +the command and placing it in the script file. The user sets the +parameter values using the parameter editor \fBeparam\fR. As an optional +final stage the task will optionally submit the script as a background job. + +The sequence of steps are outline as follows: +.ls (1) +If the script already exists and \fIappend\fR = no the script file +is deleted. When \fIverify\fR = yes the deletion is verified with the +user. +.le +.ls (2) +If the task is not specified on the command line then the user +is queried for a task name. +.ls (2a) +The task must be loaded. If it has not been loaded a message is printed +and the task query is repeated. +.le +.le +.ls (3) +\fBEparam\fR is now invoked to allow the user to set the task +parameters. +.le +.ls (4) +If \fIverify\fR = yes the command is printed and the user is asked if the +command is ok. If ok the command is added to the script. +.le +.ls (5) +The user is asked if another command is to be added to the script. While +the response is yes steps 2 to 5 are repeated. +.le +.ls (6) +If \fIverify\fR = yes the script is paged and the user is asked if the +script is ok. If not ok the script is deleted, with user confirmation, +and steps 2 to 6 are repeated. +.le +.ls (7) +If the submit parameter is not specified on the command line the user +is asked if the script should be submitted as a background job. +.le + +The parameter \fIhidden\fR is important for the following reason. If +the hidden parameters are not explicitly included in the script commands +then the values of the hidden parameters will be those in the parameter +file at the time of execution. Thus, in changes in the hidden parameters +with \fBeparam\fR or explicit changes may produce unexpected results. +However, if the hidden parameters are never changed then the commands +are more readable when the hidden parameters are not included. +.ih +EXAMPLES +One of the most common usages in data reductions is to create repeated +commands with different input data or parameters. + +.nf +cl> mkscript script.cl transform + +[\fIeparam\fR is called to set the parameter values for \fItransform\fR] + +transform ("n1r.008", "n1r.008a", "disp012,distort,disp013", +database="identify.db", interptype="spline3", x1=1., x2=256., dx=1., +nx=256., xlog=no, y1=4300., y2=6300., dy=INDEF, ny=800., ylog=no, +flux=yes, logfiles="STDOUT,logfile") + +Is the command ok? (yes): +Add another command? (yes): + +[\fIeparam\fR is called again for task \fItransform\fR] + +transform ("n1r.010", "n1r.010a", "disp013,distort", +database="identify.db", interptype="spline3", x1=1., x2=256., dx=1., +nx=256., xlog=no, y1=4300., y2=6300., dy=INDEF, ny=800., ylog=no, +flux=yes, logfiles="STDOUT,logfile") + +Is the command ok? (yes): +Add another command? (yes): no + +[The script is paged] + +Is the script ok? (yes): +Submit the script as a background job? (yes): +Script script.cl submitted at: +Fri 10:32:57 01-Nov-85 +[1] +.fi + +To combine several tasks: + +.nf +cl> mkscript script.cl ver- sub- hid- +Task name of command to be added to script: response + +[\fIeparam\fR is called for \fIresponse\fR and parameter values are set] + +Add another command? (yes): +Task name of command to be added to script: imarith +... +Add another command? (yes): no +.fi + +To run the command script as a foreground job: + +cl> cl < script.cl + +To run the command script as a background job: + +cl> cl < script.cl >& logfile & + +Note that the output including possible error output is redirected to a logfile. +.ih +BUGS +The current implementation is preliminary. It is done with a script which +makes it seem somewhat slow. The most important bug is that the command +formatter is based on the output of \fBlparam\fR. If a task parameter +name exceeds 12 characters it is truncated by \fBlparam\fR and is then +also truncated by the command formatter. The script will then fail when +executed! Also the task name may not be abbreviated. +.ih +SEE ALSO +eparam +.endhelp diff --git a/pkg/system/doc/movefiles.hlp b/pkg/system/doc/movefiles.hlp new file mode 100644 index 00000000..73374474 --- /dev/null +++ b/pkg/system/doc/movefiles.hlp @@ -0,0 +1,38 @@ +.help movefiles Nov84 system +.ih +NAME +movefiles -- move files to a directory +.ih +USAGE +movefiles files directory +.ih +PARAMETERS +.ls files +A template specifying the file or files to be moved. +.le +.ls directory +The directory to which the files are to be moved. +.le +.ls verbose = no +If set to "yes", tell user as each file is moved. +.le +.ih +DESCRIPTION +This routine moves the specified files to the named directory. +If a subdirectory and a logical directory both exist with the same +name as the destination directory, the subdirectory is used. +.ih +EXAMPLES + +1. Move all files whose names start with `im' and end with `ab' to +the directory `dir'. Since "verbose" defaults to "no", do the work silently. + + cl> movefiles im*ab dir + +2. Move all files in the current directory into the directory one level up. + + cl> move * .. +.ih +SEE ALSO +copy, rename +.endhelp diff --git a/pkg/system/doc/netstatus.hlp b/pkg/system/doc/netstatus.hlp new file mode 100644 index 00000000..059f6819 --- /dev/null +++ b/pkg/system/doc/netstatus.hlp @@ -0,0 +1,44 @@ +.help netstatus Feb86 system +.ih +NAME +netstatus -- print the status of the local network +.ih +USAGE +netstatus +.ih +PARAMETERS +None. +.ih +DESCRIPTION +\fINetstatus\fR prints the status of the local network as perceived by the +system process x_system.e (the network status may differ for each subprocess). +The status output identifies the local node, lists all nodes in the local +network, and lists all the aliases (recognized names) for each node. +A message will be printed if networking is disabled on the local machine. +The local network is defined by the table files "dev$hosts", "dev$uhosts", +and "dev$hostlogin". +.ih +EXAMPLES + +.nf +cl> netstatus +Local node `draco' (5), default node `draco', 12 nodes in local network + + NODE SERVER NREFS STATUS ALIASES + 1 0 0 00000 aquila vax1 a 1 class1 plot print + 2 0 0 00000 lyra vax2 b 2 class2 + 3 0 0 00000 vela vax3 3 v class3 + 4 0 0 00000 carina vax5 c 5 class5 + 5 0 0 00000 draco vax6 6 d class6 0 + 6 0 0 00000 tucana sun1 t + 7 0 0 00000 hydra sun2 h + 8 0 0 00000 mensa pc1 m + 9 0 0 00000 pictor pc2 + 10 0 0 00000 octans sun3 o + 11 0 0 00000 pavo mvax1 p + 12 0 0 00000 volans lsi1 +.fi + +.ih +SEE ALSO +.endhelp diff --git a/pkg/system/doc/news.hlp b/pkg/system/doc/news.hlp new file mode 100644 index 00000000..1b12f24c --- /dev/null +++ b/pkg/system/doc/news.hlp @@ -0,0 +1,58 @@ +.help news Mar90 system +.ih +NAME +news -- print the revisions summary for the current IRAF version +.ih +USAGE +news +.ih +DESCRIPTION +The \fInews\fR task uses the standard IRAF file pager to review a formatted +summary of the system revisions for the version of IRAF being run. +The revisions summaries for older versions of the system are also provided: +use the \fIN\fR and \fIP\fR pager keys to display the next or previous +system revisions summary. The revisions summary is given in the file +"doc$newsfile". + +For reasons of brevity, only the revisions summary is printed. For detailed +information on the revisions made to a particular science package, type + + cl> help <pkg>.revisions op=sys + +where "pkg" is the name of the CL package for which revisions information +is desired. For detailed information on the revisions to the system +software and programming interfaces, examine the system notes file, +given in the file "notes.*" in the directory "iraf$local". The system +notes files for older versions of the system will be found in the "doc" +directory. +.ih +BUGS +The revisions summary is often lengthy and may be easier to read if a +printed copy is made. + +Redirecting the output of \fInews\fR, e.g., to \fIlprint\fR, doesn't work +at present. +.ih +EXAMPLES +1. Page the revisions summary for the current IRAF release. + + cl> news + +2. Print the revisions summary. + + cl> lprint doc$newsfile + +3. Page the system notes file. Anyone who develops software for IRAF +should review this file with each new release, to see what has changed. +Documentation for new system facilities is often given in the system +notesfile. + + cl> page iraf$local/notes.* + +4. Review the revisions summary for the IMAGES package. + + cl> phelp images.revisions op=sys +.ih +SEE ALSO +help, phelp, page +.endhelp diff --git a/pkg/system/doc/page.hlp b/pkg/system/doc/page.hlp new file mode 100644 index 00000000..92cfd105 --- /dev/null +++ b/pkg/system/doc/page.hlp @@ -0,0 +1,146 @@ +.help page Nov86 system +.ih +NAME +page -- display a file or files one page at a time +.ih +USAGE +page files +.ih +PARAMETERS +.ls files +The list of files. If omitted, text is read from the standard input. +.le +.ls map_cc = yes +Map non-printing control characters into printable form, e.g., BEL +(ctrl/G, ASCII 7) is printed as "^G". +.le +.ls clear_screen = no +If set, the screen is cleared before each page is written. +.le +.ls first_page = 1 +The first page to be printed. Pages are defined by form feed characters +embedded in the text. +.le +.ls prompt = "" +Optional prompt string for the end-of-page prompt. If no prompt string is +given the name of the file being paged is used. +.le +.ls device = "terminal" +The output device. The special device \fItext\fR may be specified to +represent standout mode with upper case rather than reverse video characters. +.le +.ih +DESCRIPTION +\fIPage\fR displays a file on the terminal, one page of text at a time, +pausing between successive pages of output until a key is typed on the +terminal. Pages are normally broken when the screen fills, but may also +be delimited by form feed characters embedded in the input text. +A prompt is printed after each page of text naming the current file, +showing the percentage of the file which has been displayed, and the numeric +order of the file within the file list if a file template was given. + +When the end of page prompt is displayed any of the following command +keystrokes may be entered. Command keystrokes are input in raw mode, +i.e., no carriage return is required to pass the command to the program. + +.ks +.nf + . go to the beginning of the current file [BOF] + : colon escape (see below) + ? display a one-line command summary + G go to the end of the current file [EOF] + N,<ctrl/n> go to the next file + P,<ctrl/p> go back to the previous file + b back up one page + d scroll down half a page of text + e edit the current file + f,space advance to the next page + j,return scroll down one line + k back up one line + n search for the next occurrence of a pattern + q quit + u back up half a screen + + <ctrl/c> quit (interrupt) + <ctrl/z> quit (EOF) + <ctrl/d> quit (EOF) +.fi +.ke + +If an unrecognized keystroke is entered the terminal will beep. The following +colon commands are recognized in addition to the single keystroke commands +described above. + +.ks +.nf + :!<clcmd> send a command to the CL (:!! for host command) + :/<pattern> advance to line matching the given pattern + :file <fname> display file "fname" (may be abbreviated) + :help print summary of colon commands + :line [+/-]N goto line N (relative move if +/- given) + :spool <fname> spool output to the named file +.fi +.ke + +The \fI:clcmd\fR facility is used to send commands to the CL from within +the context of the pager. For example, ":!cl" will temporarily suspend the +pager, allowing CL commands to be entered until the command "bye" is entered, +causing execution of the pager to resume. Note that since the \fIpage\fR +task resides in the system process \fIx_system.e\fR, it will be necessary +for the CL to connect a second system process if the command issued calls +another task in the system package, since the first system process will +still be running, i.e., executing the \fIpage\fR task. This is harmless, +but the second process may be removed from the process cache with +\fIflprcache\fR if desired, after exiting the original \fIpage\fR task. + +The sequence ":/" followed by a pattern will cause the current input stream +to be searched for the next occurrence of the pattern given. A pattern once +entered is retained indefinitely and may be used in subsequent searches by +typing the single keystroke `n', without need to reenter the pattern. +Searching stops at the end of the current file, requiring a `.' to wrap back +around to the beginning of the file, or a `N' to advance to the next file. + +The \fI:file\fR command is used to change the current position within the +file list specified by \fIfiles\fR, and may not be used to page a file not +specified in the initial template. Note that the filename may be abbreviated, +and that searching stops with the first file lexically greater than or equal +to the given string (hence ":file x" might return file "y"). + +The \fI:line N\fR command may be used to randomly position to the indicated line +within the current file. If the line number argument N is preceded by a plus +or minus the argument is taken to be an offset from the current position. + +The \fI:spool\fR command is used to spool output to a file. Each time a +file line is printed on the screen, it is appended to the named file as well. +One can interactively position to the desired line of the file and then turn +on spooling to extract a portion of the file or stream being displayed. +A subsequent \fI:spool\fR command with no filename will turn spooling off. +Issuing a \fI:spool\fR to begin spooling on a new file when already spooling +to some other file will cause the old spool file to be closed. +.ih +EXAMPLES + +1. Page through all of the files in the directory "lib" which have +the extension ".h". + + cl> page lib$*.h + +2. Use \fIhelp\fR to format the text in the file "doc$spp.hlp", displaying +the formatted document beginning on page 5 (the entire document has to be +formatted first so it takes a minute or so to get any output). + + cl> help doc$spp.hlp fi+ | page first=5 + +3. Run \fIrfits\fR to print a long format listing of the headers of a series +of FITS images from a magnetic tape, directing the output through \fIpage\fR +so that it does not flash by when you aren't looking. + + cl> rfits mta make- long+ | page +.ih +BUGS +Since \fIpage\fR does not currently buffer any input text, backwards motions +and absolute line positioning are not permitted when paging the standard input. +.ih +SEE ALSO +type, match, head, tail +.endhelp diff --git a/pkg/system/doc/pathnames.hlp b/pkg/system/doc/pathnames.hlp new file mode 100644 index 00000000..3719fe28 --- /dev/null +++ b/pkg/system/doc/pathnames.hlp @@ -0,0 +1,42 @@ +.help pathnames Nov84 system +.ih +NAME +pathnames -- print the host pathnames for a set of files +.ih +USAGE +pathnames [template] +.ih +PARAMETERS +.ls template +A filename template specifying the set of files for which pathnames +are desired. If omitted, the pathname of the current working or default +directory is printed. The list of file names can come from the standard input. +.le +.ls sort = yes +Sort the output in ASCII collating sequence. +.le +.ih +DESCRIPTION +\fIPathnames\fR converts a list of IRAF virtual file names into their host +system equivalents. When called with no arguments, the function of +\fIpathnames\fR is to print the current default directory. +.ih +EXAMPLES + +1. Print the pathname of the current default directory (sample output for +a VMS host system). + +.nf + cl> path + draco!DRB1:[IRAF.SYS.FIO] +.fi + +2. Translate the file "vfiles", containing a list of virtual filenames, into +the equivalent list of host system filenames, e.g., for use as input to a +foreign task. + + cl> path @vfiles > hfiles +.ih +SEE ALSO +directory, files +.endhelp diff --git a/pkg/system/doc/phelp.hlp b/pkg/system/doc/phelp.hlp new file mode 100644 index 00000000..2230eb29 --- /dev/null +++ b/pkg/system/doc/phelp.hlp @@ -0,0 +1,61 @@ +.help phelp Mar90 system +.ih +NAME +phelp -- page the output of the HELP task +.ih +USAGE +phelp template +.ih +PARAMETERS +The \fIphelp\fR parameters are the same as for \fIhelp\fR except that +the \fIpage\fR and \fInlpp\fR parameters are omitted. +.ih +DESCRIPTION +The \fIphelp\fR task is a front end to \fIhelp\fR which spools the output +of \fIhelp\fR in a scratch file, then calls the file pager \fIpage\fR to +view the output text. The advantage is that while \fIhelp\fR pages its +output, one can only move forward through the output text. By using +\fIphelp\fR it is possible to randomly scan the spooled help text, e.g., +skipping forward to get a quick overview and then backing up to read the +details more carefully. This capability is especially useful when viewing +large multipage help pages, or when viewing a number of related help pages +all at once. +.ih +EXAMPLES +1. Page the help page for the \fImkpkg\fR task. + + cl> phelp mkpkg + +2. View the help pages for all the tasks in the IMAGES package. + + cl> phelp images.* + +When viewing multiple help pages as in this last example, note that the +'N' and 'P' keystrokes in the pager may be used to move to the next or +previous help page. "." will return to the first help page (the start +of the spooled help text) and 'G' will skip to the end of file. Type '?' +while in the pager to get a summary of the most often used keystrokes. + +3. Format and page the Lroff (IRAF HELP) format document "MWCS.hlp" in +the system directory "mwcs". + +.nf + cl> cd mwcs + cl> phelp MWCS.hlp fi+ +.fi + +In this case the text being viewed is not part of the on-line help system, +but is a technical document describing one of the IRAF programming interfaces. +Any .hlp file may be viewed in this way. +.ih +TIME REQUIREMENTS +\fIphelp\fR is not quite as fast as \fIhelp\fR since it must fully format +the help text into a temporary file before the file can be viewed. For +small help pages, or to view only the first few screens of a help page, +the \fIhelp\fR task will be faster. +.ih +BUGS +.ih +SEE ALSO +page, help, references +.endhelp diff --git a/pkg/system/doc/protect.hlp b/pkg/system/doc/protect.hlp new file mode 100644 index 00000000..6a0049e4 --- /dev/null +++ b/pkg/system/doc/protect.hlp @@ -0,0 +1,36 @@ +.help protect Nov84 system +.ih +NAME +protect -- protect files from deletion +.ih +USAGE +protect files +.ih +PARAMETERS +.ls files +A template specifying the file or files to be protected. +.le +.ih +DESCRIPTION +\fIProtect\fR asserts protection from deletion for the specified files. +A protected file can be deleted only by first "unprotecting" it. +File protection is preserved when a file is copied or renamed, +even when copied or renamed to a remote network node, +but may be lost when a file is backed up on tape and later restored +(depending upon what utility one uses). Note that imagefiles are +automatically protected to prevent accidental deletion of the header +file, leaving a "zombie" pixel file somewhere on disk. +.ih +EXAMPLES + +1. Protect the file "paper.ms" from deletion, accidental or otherwise. + + cl> protect paper.ms + +2. Protect all the ".ms" files from deletion. + + cl> protect *.ms +.ih +SEE ALSO +unprotect, delete +.endhelp diff --git a/pkg/system/doc/references.hlp b/pkg/system/doc/references.hlp new file mode 100644 index 00000000..a67b4182 --- /dev/null +++ b/pkg/system/doc/references.hlp @@ -0,0 +1,78 @@ +.help references Jun89 system +.ih +NAME +references -- find all help database references to a given topic +.ih +USAGE +references topic +.ih +PARAMETERS +.ls topic +The topic for which help is desired, i.e., a keyword, phrase, or pattern +which the help database or quick-reference file is to be searched for. +.le +.ls quickref = "uparm$quick.ref" +The name of the optional quick-reference file. +.le +.ls updquick = no +Create or update the quick-reference file, e.g., because new packages +have been added to the global help database. Updating the quick-reference +file automatically enables \fIusequick\fR, discussed below. +.le +.ls usequick = no +Use the quick-reference file. By default, a runtime search of all the package +menus in the full help database is performed, which ensures that all packages +are searched, but which is comparatively slow. +.le +.ih +DESCRIPTION +The \fIreferences\fR task is used to search the help database for all tasks +or other help modules pertaining to the given topic, where \fItopic\fR may be +a keyword, phrase, or any general pattern as would be input to the \fImatch\fR +task. By default the full help database will be searched. If desired, +the "one-liner" information used for topic searching may be extracted and +used to prepare a quick-reference file to speed further searches. +This is not done by default because the help database is too dynamic, e.g., +new external packages may be installed at any time, by any user, or new +tasks may be added to existing packages at any time. + +References to tasks (or other objects) are printed in the form + +.nf + keyword1 - one line description + keyword2 - one line description +.fi + +and so on. To determine the \fIpackage pathname\fR of each named task, +get \fIhelp\fR on the named \fIkeyword\fR and the pathname will be seen at +the top of the help screen, followed by additional information about the +referenced object. If there are multiple objects with the same name, +a "help <keyword> \fIall+\fR" may be required to locate a particular one. +.ih +EXAMPLES +1. Find all help on CCDs. + + cl> ref ccd + +2. Create or update your private quick-reference file. + + cl> ref upd+ + +3. Examine the quick-reference file to get a summary of all the tasks +or other help modules in the help database. + + cl> page (ref.quickref) +.ih +TIME REQUIREMENTS +If a quick-reference file is used searching takes seconds, otherwise it +might take a minute or so for the typical large help database containing +all help modules for the core system and several external, layered packages. +.ih +BUGS +Only the one-liner (NAME) field describing each help module is used for +the searches. With a little work searching could be made much more +comprehensive as well as faster. +.ih +SEE ALSO +help, match +.endhelp diff --git a/pkg/system/doc/rename.hlp b/pkg/system/doc/rename.hlp new file mode 100644 index 00000000..226045da --- /dev/null +++ b/pkg/system/doc/rename.hlp @@ -0,0 +1,69 @@ +.help rename Aug97 system +.ih +NAME +rename -- rename a file or set of files +.ih +USAGE +rename file newname +.ih +PARAMETERS +.ls file +A template specifying the file or files to be renamed. +.le +.ls newname +If a single file is being renamed, the new filename, else the new name of +the field being renamed in a set of filenames. If \fInewname\fR is a +directory the input files will be moved to this directory with the same +name. +.le +.ls field = all +If set to "all" the file name remains unchanged and the \fInewname\fR is +assumed to be a destination directory in the case of multiple input files, +or the new filename (which may contain a new directory path) in the case of +a single input file. If set to \fIldir\fR the \fInewname\fR value is taken +to be a destination directory and the file is moved to this directory. +Setting to \fIroot\fR will rename only the root portion of the filename, +a value of \fIextn\fR will change or append the extension. \fInewname\fR +cannot contain a directory path when changing the root or extn field. +.le +.ih +DESCRIPTION +\fIRename\fR renames either a single file to "newname", or a set of files, +changing either the ldir, root or the extension part of each name. +If \fInewname\fR is a directory or \fIfield\fR is "ldir" the input files +are moved to this directory and the filenames remain the same. When +modifying the root or extension part of the filename \fInewname\fR is the +new root or extension name for the input files, an extension will be added +to the file name if it doesn't already exist and the extension field is being +modified. For multiple input files it is assumed +that \fInewname\fR is a directory if the value of \fIfield\fR is "all", +otherwise an error is generated to prevent overwriting files. +.ih +EXAMPLES + +1. Rename file "fred" to "jay". + + cl> rename fred jay + +2. Change the root name of a set of files from "out" to "pkout". + + cl> rename out.x,out.o,out.par pkout field=root + +3. Change the extension of all ".f77" files from ".f77" to ".f". + + cl> rename *.f77 f field=extn + +4. Move all files with a ".dat" extension to a new directory. + + cl> rename *.dat data$ + cl> rename *.dat /data/user + +5. Add a ".fits" extension to all files in a directory. + + cl> rename im00* fits field=extn +.ih +BUGS +.ih +SEE ALSO +movefiles, copy +.endhelp diff --git a/pkg/system/doc/rewind.hlp b/pkg/system/doc/rewind.hlp new file mode 100644 index 00000000..0519f81c --- /dev/null +++ b/pkg/system/doc/rewind.hlp @@ -0,0 +1,36 @@ +.help rewind Apr92 system +.ih +NAME +rewind -- rewind a previously allocated device +.ih +USAGE +rewind device +.ih +PARAMETERS +.ls device +The device to be rewound. +.le +.ls initcache = yes +Initialize the magtape device position cache for the device. This causes +the magtape i/o system to "forget" what it thinks it knows about things +like the number of files on the tape, the amount of tape used, and so on. +.le +.ih +DESCRIPTION +\fIRewind\fR rewinds the specified device, which is most likely +a magnetic tape, and which has been previously allocated to the user. + +By default \fIrewind\fR will initialize the device position cache. When +changing tapes, one should always either rewind or deallocate and reallocate +the device, to force the magtape system to recompute the number of files +on the tape and to ensure that the tape is left in a defined position. +.ih +EXAMPLES + +1. Rewind logical tape drive a. + + cl> rewind mta +.ih +SEE ALSO +allocate, deallocate, devstatus +.endhelp diff --git a/pkg/system/doc/sort.hlp b/pkg/system/doc/sort.hlp new file mode 100644 index 00000000..7d89657b --- /dev/null +++ b/pkg/system/doc/sort.hlp @@ -0,0 +1,62 @@ +.help sort Mar87 system +.ih +NAME +sort -- sort a file or the standard input +.ih +USAGE +sort input_file +.ih +PARAMETERS +.ls input_file +The text file to be sorted. If the standard input is redirected the standard +input is sorted. +.le +.ls column = 0 +If 0, sort entire text lines, else sort based on data/text starting +in the specified column. Columns are delimited by whitespace. Thus, +.nf + 12 abc 34 56 +.fi +has four columns, "abc" being in the second. +.le +.ls ignore_whitespace = no +Ignore leading whitespace. Useful only when column = 0 and the sort is +non-numeric. +.le +.ls numeric_sort = no +If set, make numerical (rather than ASCII text) comparisons. +.le +.ls reverse_sort = no +If set, sort in reverse text/numeric order. +.le +.ih +DESCRIPTION +\fISort\fR sorts the contents of the given text file, or the +standard input, either on a textual (based on the ASCII collating +sequence), or on a numeric basis. If a numeric sort is requested, +and either field in any comparison is non-numeric, a string (ASCII) +comparison will be made instead. +.ih +EXAMPLES + +1. Sort the output of the set command into alphabetic (ASCII collating) +order. + + cl> set | sort + +2. Sort the contents of "file", in reverse ASCII order, ignoring the +contents of columns 1 through 4. + + cl> sort file rev+ col=5 + +3. Print a long form directory listing with the files sorted by size, +largest files first. + + cl> dir | sort num+ rev+ col=3 +.ih +BUGS +Only one file can be sorted per call, and only one column or all columns can +be used for the sort. The current program is inefficient for large numeric +sorting tasks because the same numeric field may be decoded into its +corresponding binary value many times. +.endhelp diff --git a/pkg/system/doc/spy.hlp b/pkg/system/doc/spy.hlp new file mode 100644 index 00000000..33ffa52c --- /dev/null +++ b/pkg/system/doc/spy.hlp @@ -0,0 +1,26 @@ +.help spy Feb85 system +.ih +NAME +spy -- tell who is logged in and what they are doing +.ih +USAGE +spy [v] +.ih +DESCRIPTION +\fISpy\fR prints a summary of who is on the system and what they are doing. +The optional argument \fIv\fR (short for \fIverbose\fR) causes more detailed +information to be given. The operation of this task is machine dependent, +as is the quantity and format of the information returned. +.ih +EXAMPLES +.nf +cl> spy + 4:36pm up 24 days, 5:42, 2 users, load average: 0.29, 0.15, 0.18 +User tty login@ idle JCPU PCPU what +roger ttyh8 4:21pm 15 8 5 -csh +alice ttyh9 4:26pm 44 27 w +.fi +.ih +SEE ALSO +diskspace +.endhelp diff --git a/pkg/system/doc/tail.hlp b/pkg/system/doc/tail.hlp new file mode 100644 index 00000000..bd91e617 --- /dev/null +++ b/pkg/system/doc/tail.hlp @@ -0,0 +1,50 @@ +.help tail Nov84 system +.ih +NAME +tail -- print the last few lines of the specified files +.ih +USAGE +tail files +.ih +PARAMETERS +.ls files +A template specifying the files to be listed. +.le +.ls nlines = 12 +The number of lines to be printed. If negative, the number +of lines to be skipped, counting from the beginning of the file. +.le +.ih +DESCRIPTION +For each file in the input file list, \fItail\fR copies the last \fInlines\fR +of the file to the standard output. If there is more than one file in the +input file list, as one line header is printed before each file. +If "nlines" is negative, then abs(nlines) lines are skipped, and the rest +of the file is printed, i.e., the tail of the file is still printed, but +the offset is measured from the beginning of the file rather than the end. +.ih +EXAMPLES + +1. Prints the last 12 lines of each help file in the current directory. + + cl> tail *.hlp + +2. Print the last line of each help file. + + cl> tail *.hlp nl=1 + +3. Prints the third through fifth lines of "file". The same thing +might be done (at least conceptually) by "head file,nlines=5" +piped into "tail ,nlines=3". However, \fItail\fR does not work on STDIN. + +.nf + cl> tail file nl=-2 | head nl=3 +.fi +.ih +BUGS +\fITail\fR does not presently work on standard input, and therefore cannot +be used in pipes. +.ih +SEE ALSO +head +.endhelp diff --git a/pkg/system/doc/tee.hlp b/pkg/system/doc/tee.hlp new file mode 100644 index 00000000..466b3751 --- /dev/null +++ b/pkg/system/doc/tee.hlp @@ -0,0 +1,36 @@ +.help tee Nov84 system +.ih +NAME +tee -- tee the standard output to a file +.ih +USAGE +tee file +.ih +PARAMETERS +.ls file +The name of the output file. +.le +.ls out_type = "text" +The type of output file to be created, either "text" or "binary". +.le +.ls append = no +If set, append to an existing file, otherwise create a new file. +.le +.ih +DESCRIPTION +\fITee\fR copies its input to both the standard output and the named file. +Its primary use is in pipes where one wants to capture some intermediate output. +.ih +EXAMPLES + +1. The results of the \fIset\fR command are captured in the file "temp", +and are also passed on to the "match" command. The result is +a "temp" file of perhaps 100 lines, with the output to the screen +only around 5 lines. + + cl> set | tee temp | match tty +.ih +BUGS +Since the processes in an IRAF pipe execute serially rather than concurrently, +the teed output will not appear until all tasks to the left have completed. +.endhelp diff --git a/pkg/system/doc/touch.hlp b/pkg/system/doc/touch.hlp new file mode 100644 index 00000000..aedb35a0 --- /dev/null +++ b/pkg/system/doc/touch.hlp @@ -0,0 +1,71 @@ +.help touch Jan04 system +.ih +NAME +touch -- change file access and modification times +.ih +USAGE +touch files +.ih +PARAMETERS +.ls files +List of files to be created or touched. +.le +.ls create = yes +If enabled, the file will be created as a zero-length text file if it doesn't +already exist. +.le +.ls atime = yes +Change the access time of the file. Will not change the modification time +unless \fImtime\fR is also set. +.le +.ls mtime = yes +Change the modification time of the file. Will not change the access time +unless \fIatime\fR is also set. +.le +.ls time = "" +Time and date to set for the file. The format of this string may be any +of DD/MM/YY or CCYY-MM-DD (in which case time is assumed to be midnight of +that day), or CCYY-MM-DDTHH:MM:SS[.SSS...] to specify both date and time. +If not specified, the current system time is used unless the \fIref_file\fR +parameter is set. If specified, \fIref_file\fR will be ignored. +.le +.ls ref_file = "" +Use the corresponding times of the specified file for modifying the +times of the \fIinput_files\fR. If not specified, the current time is +used unless the \fItime\fR parameter is set. +.le +.ls verbose = no +Print verbose output of the files and times being reset. +.le +.ih +DESCRIPTION +The \fItouch\fR task sets the access and modification times of each file +in the \fIfiles\fR list. The file will be created if it does not already +exist when the \fIcreate\fR parameter is set. The time used can be +specified by \fItime\fR parameter or by the corresponding fields of the +file specified by \fIref_file\fR, otherwise the current system time will +be used. The task will update both the modification and access times of +the file unless disabled by the \fIatime\fR or \fImtime\fR parameter. + +.ih +EXAMPLES + +1. Update the times of all SPP source files in the current directory: + + cl> touch *.x + +2. Create an empty file on a remode node: + + cl> touch ursa!/data/trigger_file + +3. Reset the file modification time to 2:33:45 pm on June 5, 2003: + + cl> touch nite1.fits time="2003-06-05T14:23:45" + +4. Reset the file modification time to match dev$hosts: + + cl> touch nite1.fits ref_file=dev$hosts + +.ih +SEE ALSO +.endhelp diff --git a/pkg/system/doc/type.hlp b/pkg/system/doc/type.hlp new file mode 100644 index 00000000..f8af91cd --- /dev/null +++ b/pkg/system/doc/type.hlp @@ -0,0 +1,43 @@ +.help type Nov84 system +.ih +NAME +type -- type a file or files on the standard output +.ih +USAGE +type input_files +.ih +PARAMETERS +.ls input_files +A template specifying the file or files to be typed. +.le +.ls map_cc = yes +If set, output any non-printing control characters in the input text in +a printable form, e.g., ctrl/c (ASCII 3) would be output as ^C. +.le +.ls device = "terminal" +The output device, defaulting to the user's terminal. If the special device +"text" is named, any standout mode control characters embedded in the text +will cause the enclosed text to be output in upper case. +.le +.ih +DESCRIPTION +\fIType\fR copies the named files (or the files selected by +the file template) to the standard output. +If there is more than one file in the input list, a header naming the file +to be printed will precede each output file. +.ih +EXAMPLES + +1. Type all files in the current directory with the extension ".x" on the +standard output. Do not pause between files or pages (unlike \fIpage\fR). + + cl> type *.x + +2. Capture the manual page for task \fIhedit\fR in a text file, in a form +suitable for printing on any device. + + cl> help hedit | type dev=text > hedit.doc +.ih +SEE ALSO +page, head, tail, concatenate, lprint +.endhelp diff --git a/pkg/system/doc/unprotect.hlp b/pkg/system/doc/unprotect.hlp new file mode 100644 index 00000000..99120c07 --- /dev/null +++ b/pkg/system/doc/unprotect.hlp @@ -0,0 +1,27 @@ +.help unprotect Nov84 system +.ih +NAME +unprotect -- remove file protection +.ih +USAGE +unprotect files +.ih +PARAMETERS +.ls files +A template specifying the file or files from which delete protection is +to be removed. +.le +.ih +DESCRIPTION +\fIUnprotect\fR removes delete protection from the named files. +A "protected" file cannot be deleted or clobbered. +.ih +EXAMPLES + +1. Remove file protection from the listed files. + + cl> unprotect alpha,beta,gamma.x,*.db +.ih +SEE ALSO +protect, delete +.endhelp diff --git a/pkg/system/doc/urlget.hlp b/pkg/system/doc/urlget.hlp new file mode 100644 index 00000000..da6ede83 --- /dev/null +++ b/pkg/system/doc/urlget.hlp @@ -0,0 +1,84 @@ +.help urlget Sep2011 system +.ih +NAME +urlget -- Get a (http) URL to the named file +.ih +USAGE +urlget url fname +.ih +PARAMETERS +.ls url +The URL to download. +.le +.ls fname +The name of the file to create containing the URL contents. If not +specified, the trailing part of the URL is used as the filename. +.le +.ls use_cache = yes +Use the system file cache? If 'yes' and the file already exists in the +cache, the cached file will be copied to the output filename. +If 'no' then the URL will be downloaded again. +.le +.ls extn = "" +Optional filename extension to put on the cached filename. This can be +used to force files to be saved as a particular type in the cache. +.le +.ls verbose = no +Print verbose output? +.le +.ls cache = "cache$" +Logical cache directory name. +.le + +.ih +DESCRIPTION +The \fIURLGET\fR task is used to download a URL (HTTP protocol only) to a +local file named by the \fIfname\fR parameter. If no \fIfname\fR is given, +a filename is constructed from the last part of the URL (i.e. +characters trailing any of the '?', '/', or '&' delimiters). Because +the URL may not point to a static file, use of the \fIfname\fR parameter +is recommended. + +If the \fIuse_cache\fR parameter is set, the URL will only be downloaded if +it does not already exist in the file cache pointed to by the \fIcache\fR +parameter, otherwise the cached file will be copied to the output filename. +The \fIextn\fR parameter may be to used to force a specific file extension +to be appended to the filename in the cache, this allows a URL to be passed +to a task and treated as if it were a file of a specific type. + +.ih +EXAMPLES + +1. Download a FITS image from a URL (these are equivalent): + +.nf + cl> urlget http://iraf.noao.edu/foo.fits + cl> urlget http://iraf.noao.edu/foo.fits foo.fits +.fi + +2. Force a URL to be downloaded again: +.nf + cl> urlget http://iraf.noao.edu/foo.fits use_cache=no +.fi + +3. Download a URL with special characters: +.nf + cl> urlget http://iraf.noao.edu/scripts/tget?f=foo.fits +or + cl> s1 = "http://iraf.noao.edu/scripts/tget?f=foo.fits" + cl> urlget(s1) +or + cl> s1 = "http://iraf.noao.edu/scripts/tget?f=foo.fits&d=/iraf/web" + cl> urlget(s1,"foo.fits",verbose+) +.fi + +Escaping special characters isn't required from the commandline since the +URL is assumed to be whitespace or comma delimited. + +.ih +BUGS + +.ih +SEE ALSO + +.endhelp diff --git a/pkg/system/fcache.par b/pkg/system/fcache.par new file mode 100644 index 00000000..0c69ba6f --- /dev/null +++ b/pkg/system/fcache.par @@ -0,0 +1,9 @@ +cmd,s,a,,,,cache command +pattern,s,h,"*",,,filename pattern +src,s,h,"",,,file or url to cache +fname,s,h,"",,,cache filename +extn,s,h,"",,,cache filename extension +age,i,h,-1,,,file age (in days) to purge +verbose,b,h,no,,,print verbose output? +wait,b,h,yes,,,block on operation? +cache,s,h,"cache$",,,cache directory diff --git a/pkg/system/files.par b/pkg/system/files.par new file mode 100644 index 00000000..20e6a230 --- /dev/null +++ b/pkg/system/files.par @@ -0,0 +1,2 @@ +template,s,a,,,,file template +sort,b,h,yes,,,sort file list diff --git a/pkg/system/files.x b/pkg/system/files.x new file mode 100644 index 00000000..9bd94f91 --- /dev/null +++ b/pkg/system/files.x @@ -0,0 +1,32 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# FILES -- Expand a file name template into a list of file names on the +# standard output. + +procedure t_files() + +int list +pointer sp, template, fname + +bool clgetb() +int fntopnb(), fntgfnb(), clgeti(), btoi() + +begin + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (template, SZ_LINE, TY_CHAR) + + if (clgeti ("$nargs") > 0) + call clgstr ("template", Memc[template], SZ_LINE) + else + call strcpy ("*", Memc[template], SZ_LINE) + + list = fntopnb (Memc[template], btoi(clgetb("sort"))) + while (fntgfnb (list, Memc[fname], SZ_FNAME) != EOF) { + call printf ("%s\n") + call pargstr (Memc[fname]) + } + + call fntclsb (list) + call sfree (sp) +end diff --git a/pkg/system/hdbexamine.par b/pkg/system/hdbexamine.par new file mode 100644 index 00000000..9ef63b4a --- /dev/null +++ b/pkg/system/hdbexamine.par @@ -0,0 +1,2 @@ +helpdb,s,h,"helpdb",,,"name of help database to be examined" +verbose,b,h,no,,,"long form output" diff --git a/pkg/system/head.par b/pkg/system/head.par new file mode 100644 index 00000000..2379807e --- /dev/null +++ b/pkg/system/head.par @@ -0,0 +1,2 @@ +input_files,s,a,,,,list of files to be printed +nlines,i,h,12,0,,number of lines to be printed from each file diff --git a/pkg/system/head.x b/pkg/system/head.x new file mode 100644 index 00000000..71b6db2b --- /dev/null +++ b/pkg/system/head.x @@ -0,0 +1,56 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> + +# HEAD -- Print the head (first few lines) of each of the named text files on +# the standard output. If more than one file is to be printed, a brief header +# is printed for each file. +# +# Params: +# input_files file matching template +# nlines [h,8] number of lines to be printed + +procedure t_head() + +char fname[SZ_FNAME] +bool multiple_files +int nlines, list +int clpopni(), clplen(), clgfil(), clgeti() + +begin + list = clpopni ("input_files") + multiple_files = (clplen (list) > 1) + nlines = clgeti ("nlines") + + while (clgfil (list, fname, SZ_FNAME) != EOF) + iferr (call print_head (STDOUT, fname, nlines, multiple_files)) + call erract (EA_WARN) + + call clpcls (list) +end + + +# PRINT_HEAD -- Print the first few lines of a file on the output stream given +# as the first argument, optionally plus a header. + +procedure print_head (out, fname, nlines, print_file_name) + +int out, nlines +bool print_file_name +char fname[SZ_FNAME], lbuf[SZ_LINE] +int in, line, open(), getline() +errchk open, getline, putline + +begin + in = open (fname, READ_ONLY, TEXT_FILE) + + if (print_file_name) { + call fprintf (out, "\n\n===> %s <===\n") + call pargstr (fname) + } + + for (line=1; line <= nlines && getline(in,lbuf) != EOF; line=line+1) + call putline (out, lbuf) + + call close (in) +end diff --git a/pkg/system/help.par b/pkg/system/help.par new file mode 100644 index 00000000..ef6f2060 --- /dev/null +++ b/pkg/system/help.par @@ -0,0 +1,31 @@ +# Parameter file for the HELP task + +template,s,a,"",,,"Module name or package.module style template" + +file_template,b,h,no,,,"Template is a filename matching template" +option,s,h,"help",,,"Type of help (help,source,sysdoc,files,summary,etc)" +device,s,h,"terminal","terminal|gui|text|html|postscript|ps",,"output device" + +# Output parameters. +all,b,h,no,,,"print help for all modules matching template" +parameter,s,h,"all",,,"parameter for which help is desired" +section,s,h,"all",,,"section for which help is desired" + +# Terminal display parameters. +page,b,h,yes,,,"paginate output" +nlpp,i,h,59,1,,"number of lines per page if output redirected" +lmargin,i,h,1,1,,"left margin" +rmargin,i,h,72,2,,"right margin" + +# GUI parameters +search,b,h,no,,,"Search database for help topic?" +home,s,h,"",,,"Homepage to be used" +printer,s,h,"printer",,,"Printer name" +showtype,b,h,no,,,"Indicate packages in list?" +quickref,s,h,"uparm$quick.ref",,,"Quick-reference file" +uifname,s,h,"lib$scr/help.gui",,,"User interface filename" +coords,*gcur,h,"",,,"Cursor" + +# Help Parameters. +helpdb,s,h,"helpdb",,,"Help database to be used" +curpack,s,h,"AskCL",,,"current package" diff --git a/pkg/system/help/README b/pkg/system/help/README new file mode 100644 index 00000000..a448779b --- /dev/null +++ b/pkg/system/help/README @@ -0,0 +1,12 @@ +The HELP package -- online documentation utilties. This directory contains +the source and documtation for the HELP utility. The subdirectory lroff +contains the source for the Lroff text formatter, called by HELP to format +help blocks. + +Jul84 Added the help database facility, i.e., pre-compilation of the help + directories to produce a binary database. Numerous other improvements. + See the revs file for additional details. + +Note: The TASK declaration for HELP is in pkg$system/system.cl. + The TASK declarations for MKHELPDB and HDBEXAMINE are in the softools + package, file pkg$softools/softools.cl. diff --git a/pkg/system/help/design.hlp b/pkg/system/help/design.hlp new file mode 100644 index 00000000..9d236da6 --- /dev/null +++ b/pkg/system/help/design.hlp @@ -0,0 +1,500 @@ +.helpsys help Mar84 "Detailed Design of the Help Utility" +.nh +The Help Database + + Help has to know where to find help files and sources for modules. +This information is stored in two types of files. The package list file, +maintained in lib$ by the system manager, contains an entry for each +installed package. The module list file, maintained in the package +directory by the programmer, contains the same information for each +module in the package. The format of a help list file is as follows: + +.nf + $defdir = pathname|ldir + $ldir1 = pathname|ldir + $ldir2 = pathname|ldir + ... + + name1 hlp=file, src=file, sys=file, pkg=file + name2 hlp=file, src=file, sys=file, pkg=file + ... +.fi + +Logical directories may be defined in the header area of the helpdir file +as shown above. These may be omitted if the package directory is already +defined in the CL environment. The "defdir" prefix will be added to any +file name that does not contain an explicit logical or OS directory +specification. The default directory may be an OS pathname or a logical +directory guaranteed to be defined in the CL environment at the time that +\fBhelp\fR is run. There should be no OS dependent file names in the +module lists. + +Each module entry consists of a number of keyword equals value type +fields. The fields are optional and may be given in any order. If the +last character on the line is a comma, the list is assumed to be continued +on the next line. The \fBhlp\fR field is the name of the file containing the +help block. The \fBsrc\fR file contains the source for the named module. +The \fBsys\fR file contains the system documentation. The \fBpkg\fR field, +present only in the package helpdir file, is the name of the module helpdir +file for the package. Although the help database is organized by +package, the package list is linear, not a tree. + +If multiple entries are given for a module, the entry nearest the tail +of the list is used. + +.nh +Program Structure + + If no args, print help block for the current package, otherwise expand +the template into a list of package.module elements. Process the help +text for each module. In general, the \fBlroff\fR text formatter is called +to process all help text. \fBLroff\fR is called with the names of two external +procedures used to get lines of text from the input and put formatted text +to the output. + +\fBLroff\fR is essentially a numerical procedure which effects a +format conversion on a list of text lines. Additional specialized processing +is carried out in the input and output procedures. Thus, when processing +only the help text for a single section, the input procedure skips input +lines until the desired section is detected, and returns EOF to \fBlroff\fR +when the end of the input section is detected. Similarly, the output +procedure handles all the details of paginating the output on the user +terminal. + +.nf +t_help + clio to get params + salloc ctrl structure + ttyodes + get_option [match option] + process_template + hd_open [open helpdir] + open,getline,close + hd_putldiry + hd_getc + hd_putstr + realloc + hd_putmodule + hd_getc + hd_putstr + realloc + getline + hd_sort_modules + expand_template [encode pat ] + malloc + patmake + read_template [get modname ] + hd_getname + hd_getldir + patmatch + print_help [do a module ] + hd_findmod + hd_getname + hd_getldir + pr_filenames + hd_findmod + hd_getname + hd_getldir + output + nomore + clgetb + ttyputline + putline + pr_sourcefile + hd_findmod + hd_getname + hd_getldir + input + getline + output + ... + pr_summary + hd_findmod + hd_getname + hd_getldir + getline + output + ... + pr_helpblock [default help] + find_help_block + getline + strmatch + pr_header + ttyclear + LROFF [format text ] + input + getline + output + ... + close_template + mfree + hd_close + mfree +.fi + +.nh +Data Structures + + For simplicity, helpdir files are read into an internal buffer in +one operation, and searching for modules, file name extraction, etc. is +thereafter done on the buffered helpdir. The helpdir is represented +in memory by the following structures. + +.nf +struct helpdir { + char *hd_sbuf # string buffer + int hd_nextch # index of next char in sbuf + int hd_szsbuf # size of string buffer + int hd_defdir # index of defdir str + int hd_nldirs # number of ldirs + int hd_nmodules # number of modules + int hd_ldir[MAX_LDIR] # indices of ldirs + struct module hd_module[MAX_MODULES] # module names, files +} + + +struct module { + int m_name # index of module name + int m_hlp # index of help file name + int m_sys # sys help file + int m_src # source file + int m_pkg # package helpdir file +} +.fi + +All character strings are stored in the string buffer, which is initially +allocated with malloc, and which is reallocated with realloc if it fills +up while the helpdir is being read. The maximum number of logical +directory definitions and module entries are fixed when \fBhelp\fR is +compiled. All strings are referred to by an integer index into the +string buffer (if the string buffer is moved by realloc, the integer +offset does not change, whereas a char pointer would). + +.nh +Semicode + +HELP -- The main procedure. Expand the module list, determine the +type of help desired, fetch the names of the doc files and call the +appropriate routine to process the help text. + +.nf +procedure help + +begin + # Get control parameters. + fetch and decode option string + if (option "param") + fetch parameter name + fetch margin params, pagination flag, open tty descriptor, + set up "ctrl" structure + + # Get module template: "mod", "pack.mod", "pack.", etc. If no + # args or template is null, default to "curpack.". + + if (we were called with no positional arguments) + template = null + else + fetch template from cl + + # Format and output the help text. The template list consists + # of a series of templates delimited by commas. + + for (each subtemplate in the template list) + call process_template (template, ctrl) +end +.fi + + +PROCESS_TEMPLATE -- Called with a template defining the packages and +modules for which help is desired, and the control parameters defining +the type of help desired. Expand the template into a list of packages +and modules and process the help for each module. + +.nf +procedure process_template (template, ctrl) + +begin + # Open the system help directory; gives help files and name of + # package help directories for the individual packages. + + hp_sys = hd_open (system helpdir) + + # If null template, print hlp for current package. If template + # not null, but no package named, make package list the current + # CL package search path. Otherwise the template contains all + # necessary information. + + if (entire template is null) { + set package template to the name of the current package + set module template to null + } else { + extract package part of template, delimited by "." + if (null package template) + set package template to CL package search path + } + + # By the time we get here we always have a non-null template. + paklist = expand_template (hp_sys, pak_template) + + # If package help is desired, print help on the package as if + # it were a module. Otherwise, expand module template for + # the package and process help on each module. + + while (read_template (paklist, pakname) != EOF) + if (null module template) + call print_help (hp_sys, pakname, ctrl) + else { + hp_pak = hd_open (package helpdir) + modlist = expand_template (hp_pak, mod_template) + while (read_template (modlist, modname) != EOF) + call print_help (hp_pak, modname, ctrl) + close_template (modlist) + hd_close (hp_pak) + } + + close_template (paklist) + hl_close (hp_sys) +end +.fi + + +EXPAND_TEMPLATE -- Expand a template into a list of module names, +given a help directory defining the pattern matching domain. +The permissible complexity of a help template is somewhat less than +that of a file template. A template consists of a list of patterns; +there is nothing corresponding to the logical directories and list +files used in file templates. Examples of templates include + +.nf + (null) package-help for the current package + cl. package-help clpackage + cl.* all tasks in clpackage + * all tasks in the current package + alpha module alpha +.fi + +The simple alphanumeric string is a special type of pattern. The string +"cl", for example, is equivalent to "cl*" or "cl?*". Thus template +expansion is a simple matter of scanning through the module list of +a help directory and extracting all names which match the pattern. + + +.nf +pointer procedure expand_template (hp, template) + +hp: helpdir descriptor + +begin + allocate template descriptor, containing space for the encoded + pattern, hp, and the module index. + + save hp + encode template into descriptor; turn "*" meta-characters + into "?*" if not following character class + set module index to zero + + return (pointer to template descriptor) +end +.fi + + +READ_TEMPLATE -- Get next module name from help directory matching the +encoded pattern. Return EOF when directory is exhausted. + +.nf +int procedure read_template (template_descriptor, module_name) + +begin + for (index+=1; hp_getname (hp, module_name) != 0; index+=1) { + if (pattern matches module name) + return + } + return (EOF) +end +.fi + + +PRINT_HELP -- Print help documentation for the named module or parameter. +We are called with the name of a single module; all fiddling with packages +and templates has been performed by the time we are called. The help +directory is open and contains the names of the files containing the help +source for the module. Our main task is to determine what kind of help +is desired and call the appropriate routine. + +Recall that the principal options are + +.nf + \fBoption\fR \fBmeaning\fR \fBfile\fR + + help print help block for module hlp + param print help for single param hlp + section print a single section hlp + files print file names ... + source print source file src + sysdoc print system documentation sys + alldoc print all documentation hlp,sys + summary print help block titles hlp,sys +.fi + + +.nf +procedure print_help (hp, modname, ctrl) + +begin + # Handle options which do not access a help file. + if (option == files) { + pr_filenames (hp, modname, ctrl) + return + } else if (option == source) { + get source file name from hp_getname + pr_sourcefile (sourcefile, ctrl) + return + } else if (option == summary) { + # Scan hlp file and print summary of help blocks. + get helpfile name from hp_getname + pr_summary (helpfile, ctrl) + return + } + + # Process help block. Processing is controlled by the + # "ctrl" structure. + + if (option == help or alldoc) { + get helpfile name from hp_getname + pr_helpblock (helpfile, module, ctrl) + if (option == sysdoc or alldoc) { + get sysdocfile name from hp_getname + pr_helpblock (sysdocfile, module, ctrl) + } +end +.fi + + +PR_HELPBLOCK -- Format and print a help block. Open the help file and search +for the named module. Interpret block header and print help title. +Process the remainder of the help block with lroff. + +.nf +procedure pr_helpblock (helpfile, module, ctrl) + +begin + iferr (in = open help file) + print warning message + if (find_help_block (in, module, lbuf) == not found) + cannot find help block for module 'modname' + + clear EOF flag in ctrl + initialize line counter + + if (not printing just single param or section) + pr_header (lbuf, ctrl) + if (lroff (input, ctrl, output, ctrl, ...) == ERR) + print warning message + close help file +end +.fi + + +INPUT -- Lroff line input procedure. Called by Lroff to get lines of +input text. Function varies slightly depending on the Help option. +If printing only single param or single section, our job is to eat all +input which is not part of the indicated section of the help block. +A parameter block begins with ".ls paramname" and ends with a matching +".le" or ".ih", if the text is formatted. Similarly, the single section +begins with a ".ih" followed by the section name on the next line. + +.nf +int procedure input (ctrl, outbuf) + +ctrl: Control structure. Contains fd of input file, and the EOF + flag which may be set by the \fBoutput\fR procedure if we are + called interactively. + +begin + # Eof flag is set after param block has been fully input, + # but normally before the actual end of file. + if (eof flag was set by user interaction) + return (EOF) + else if (processing full help block) + return (getline (infile, outbuf)) + + # We get here only if special processing is required to + # filter out all but a section of the help text. + + if (first call for new file) { + # Determine whether or not the help block is formatted. + get first line of help block + if (line is an Lroff directive) + formatted = true + else + formatted = false + return, passing line to Lroff + } + + if (second call for new file) { + if (single param mode) { + if (formatted) { + eat input lines until a ".ls" directive is + found which contains the param name as + a substring. + } else { + eat input lines until a line beginning with + the parameter name is found. + } + } else if (print a single section) { + if (formatted) { + eat input lines until ".ih\nSECNAME" is found + } else { + eat input lines until a line beginning with the + parameter name or SECNAME is found. + } + put a section indent directive into line buffer + } + return, passing line to Lroff + } + + # By the time we get here we are in the parameter or single + # section. + get input line + if (line is a .ih directive) + set EOF flag + else if (in single param mode and have a matching .le) + set EOF flag + + return, passing line to Lroff +end +.fi + + +OUTPUT -- Output a line of text to the "out" file. If the standard output +is redirected, put lines out as is with \fBputline\fR. Otherwise put lines out +to the interactive terminal with \fBttyputline\fR, which processes standout +mode etc. Count lines and pause between pages, if enabled by control +flag. Pause is implemented as a request for a CL query mode boolean +parameter, just as in the \fBpage\fR utility. + +.nf +procedure output (dev, linebuf) +dev: The "ctrlpar" structure, containing output file descriptor, + pagination flag, TTY descriptor pointer, left and right + margins, flag if output is redirected, and so on. + +begin + if (output is redirected) { + call putline to output line without further processing + return + } + + call ttyputline to output line + bump line counter + + # The NOMORE procedure produces a query on the user terminal, + # giving the user a chance to continue when they have finished + # reading the current screen, or of terminating the help block + # currently being processed. + + if (output page is full) + if (nomore) + set EOF flag for input procedure +end +.fi diff --git a/pkg/system/help/filetemp.x b/pkg/system/help/filetemp.x new file mode 100644 index 00000000..1270abe2 --- /dev/null +++ b/pkg/system/help/filetemp.x @@ -0,0 +1,28 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include "help.h" + +# DO_FILE_TEMPLATE -- Called with a template matching a list of files containing +# help blocks. All help blocks therein are processed and output. + +procedure do_file_template (template, ctrl) + +char template[ARB] # filename matching template +pointer ctrl # Help control structure + +char fname[SZ_FNAME] +int option +pointer list +pointer fntopn() +int fntgfn() + +begin + list = fntopn (template) + option = H_OPTION(ctrl) + + while (fntgfn (list, fname, SZ_FNAME) != EOF) + call pr_helpblock (fname, "", "", NULL, ctrl) + + call fntcls (list) +end diff --git a/pkg/system/help/getoption.x b/pkg/system/help/getoption.x new file mode 100644 index 00000000..a7504531 --- /dev/null +++ b/pkg/system/help/getoption.x @@ -0,0 +1,52 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include "help.h" + +# GET_OPTION -- Map the possibly abbreviated option string into an integer +# option code. It is an error if the abbreviation is not unique. + +define EQUAL 0 + +int procedure get_option (opstr) + +char opstr[ARB] # option string, always lower case +int keycode[MAX_OPTIONS] +int oplen, key, ip, match +int strlen(), strncmp() + +string keywords "help|sources|sysdoc|alldoc|files|summary|directory|references" +data keycode /O_HELP,O_SOURCE,O_SYSDOC,O_ALLDOC,O_FILES,O_SUMMARY,O_DIR, + O_REFERENCES/ + +begin + oplen = strlen (opstr) + ip = 1 + match = 0 + + # Search the keyword table. If the option string matches a keyword, + # it is either an exact match (oplen = keyword length) or a legal + # abbreviation. If an abbreviation matches two keywords it is + # ambiguous and an error. + + for (key=1; keywords[ip] != EOS; key=key+1) { + if (strncmp (keywords[ip], opstr, oplen) == EQUAL) { + if (keywords[ip+oplen] == '|') + return (keycode[key]) # exact match + else { + if (match != 0) + call error (1, "ambiguous help option abbreviation") + else + match = key + } + } + repeat { + ip = ip + 1 + } until (keywords[ip-1] == '|' || keywords[ip] == EOS) + } + + if (match == 0) + call error (2, "unknown help option") + else + return (keycode[match]) +end diff --git a/pkg/system/help/hbgetblk.x b/pkg/system/help/hbgetblk.x new file mode 100644 index 00000000..a39db034 --- /dev/null +++ b/pkg/system/help/hbgetblk.x @@ -0,0 +1,195 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include "help.h" + +.help hb_getnextblk +.nf ___________________________________________________________________________ +HB_GETNEXTBLK -- Scan a file for the next help block, i.e., block of lines +delimited by ".help" and ".endhelp". The syntax of a help block header is +as follows: + + .help[typestr] key1,key2,...,keyN section title + +Whitespace is NOT permitted in the keyword list unless it is quoted. Quotes +are optional for each of the three strings. If the line ends with the +backslash character or a comma we assume that the header is continued on the +next line. The typestr, denoting the type of help block, is optional. +If absent it defaults to "hlp". System help blocks are of type "sys". + +We keep track of the file line number when searching for a help block. The +line number is updated in the HB structure. For this number to be accurate, +the caller must see that it is initialized before we are called. +.endhelp ______________________________________________________________________ + +define SZ_SBUF (MAX_KEYS * SZ_KEY) +define IS_KEYWCHAR (IS_ALNUM($1) || $1 == '_' || $1 == '$') +define exit_ 90 + + +int procedure hb_getnextblk (hb, ctrl) + +pointer hb +pointer ctrl + +bool at_eof +char key[SZ_KEY] +int fd, n, ip, op, junk +pointer sp, lbuf, sbuf, p +int hb_getstr(), strmatch(), getline(), strlen() + +begin + call smark (sp) + call salloc (lbuf, SZ_LINE, TY_CHAR) + call salloc (sbuf, SZ_SBUF, TY_CHAR) + + # Search forward for the next help block. + fd = H_IN(ctrl) + at_eof = true + + while (getline (fd, Memc[lbuf]) != EOF) { + HB_LINENO(hb) = HB_LINENO(hb) + 1 + if (strmatch (Memc[lbuf], "^.{help}") > 0) { + at_eof = false + break + } + } + + if (at_eof) { + call sfree (sp) + return (EOF) + } + + # Initialize everything in case of an early exit. + HB_TYPE(hb) = TY_UNKNOWN + HB_NKEYS(hb) = 0 + HB_TYPESTR(hb) = EOS + HB_SECTION(hb) = EOS + HB_TITLE(hb) = EOS + + # Decode help block into the HB structure. First step is to + # get the type suffix string, if any. + + ip = strlen (".help") + 1 + p = lbuf + ip - 1 + if (IS_ALPHA (Memc[p])) { + for (n=0; IS_ALNUM (Memc[p+n]); n=n+1) + ; + call strcpy (Memc[p], HB_TYPESTR(hb), min(n,SZ_TYPESTR)) + if ( strmatch (HB_TYPESTR(hb), "{sys}") > 0) + HB_TYPE(hb) = TY_SYS + else if (strmatch (HB_TYPESTR(hb), "{hlp}") > 0) + HB_TYPE(hb) = TY_HLP + else + HB_TYPE(hb) = TY_UNKNOWN + } else { + HB_TYPE(hb) = TY_HLP + n = 0 + } + ip = ip + n + + # Now get the keyword string, and break the keywords out into + # the keyword list. + + if (hb_getstr (fd, Memc[lbuf], ip, Memc[sbuf], SZ_SBUF, + HB_LINENO(hb)) == 0) + goto exit_ + + p = sbuf + while (IS_WHITE (Memc[p]) || Memc[p] == ',') + p = p + 1 + for (n=1; n <= MAX_KEYS && Memc[p] != EOS; n=n+1) { + for (op=1; IS_KEYWCHAR (Memc[p]); op=op+1) { + key[op] = Memc[p] + p = p + 1 + } + key[op] = EOS + call strcpy (key, HB_KEY(hb,n), SZ_KEY) + while (IS_WHITE (Memc[p]) || Memc[p] == ',') + p = p + 1 + } + HB_NKEYS(hb) = n - 1 + + # Fetch section label string and title string. + + if (hb_getstr (fd, Memc[lbuf], ip, HB_SECTION(hb), SZ_SECTION, + HB_LINENO(hb)) == 0) + goto exit_ + junk = hb_getstr (fd, Memc[lbuf], ip, HB_TITLE(hb), SZ_TITLE, + HB_LINENO(hb)) + +exit_ call sfree (sp) + return (HB_LINENO(hb)) +end + + +# HB_GETSTR -- Fetch a string (optionally quoted) from the line buffer. +# Handle everything having to do with continuation. + +int procedure hb_getstr (fd, lbuf, ip, outstr, maxch, lineno) + +int fd +char lbuf[ARB] +int ip +char outstr[ARB] +int maxch +int lineno + +char ch +int op, dstart +int stridx(), getline() +string delim " \t'\"" + +begin + while (IS_WHITE (lbuf[ip])) + ip = ip + 1 + op = 1 + + # If quoted string, only a quote can end the string. + dstart = 1 + if (lbuf[ip] == '\'' || lbuf[ip] == '"') { + ip = ip + 1 + dstart = 3 + } + + # Fetch the string. + for (ch=lbuf[ip]; stridx (ch, delim[dstart]) == 0; ch=lbuf[ip]) { + if (op >= maxch) + break + + switch (ch) { + case '\\', ',': + if (lbuf[ip+1] == '\n' || lbuf[ip+1] == EOS) { + # Continue on next line. + if (getline (fd, lbuf) == EOF) + lbuf[1] = EOS + else + lineno = lineno + 1 + ip = 1 + if (ch == '\\') + next + } else + ip = ip + 1 + outstr[op] = ch + op = op + 1 + + case '\n', EOS: + if (delim[dstart] == '\'') { + call eprintf ("Missing right quote in helpfile, line %d\n") + call pargi (lineno) + } + break + + default: + outstr[op] = ch + op = op + 1 + ip = ip + 1 + } + } + + if (ch != EOS) + ip = ip + 1 + outstr[op] = EOS + + return (op - 1) +end diff --git a/pkg/system/help/hdbexamine.hlp b/pkg/system/help/hdbexamine.hlp new file mode 100644 index 00000000..a7498c23 --- /dev/null +++ b/pkg/system/help/hdbexamine.hlp @@ -0,0 +1,55 @@ +.help hdbexamine Feb86 softools +.ih +NAME +hdbexamine -- examine a help database +.ih +USAGE +hdbexamine +.ih +PARAMETERS +.ls helpdb = "helpdb" +The filename of the help database to be examined. The reserved name "helpdb" +causes the actual filename to be taken from the environment variable of +the same name. +.le +.ls verbose = no +If this switch is enabled, \fIhdbexamine\fR will print a detailed description +of the help database listing the modules in each package, the date the entry +for the package was last modified, and other information. A more concise +summary listing only the packages and the number of help modules in each +package is printed by default. +.le +.ih +DESCRIPTION +The \fIhdbexamine\fR task is used to examine the contents of a help +database. By default the standard IRAF help database is examined. +Examining the help database with \fIhdbexamine\fR verifies that it can +be read by \fIhelp\fR, and may be useful as a diagnostic in the event +that an invalid help directory file (".hd") somewhere in the help +directory tree, causes the database to be compiled incorrectly. +.ih +EXAMPLES +1. Print a concise summary of the contents and structure of the standard +help database. + +.nf +cl> hdbexamine +Help database dev$help.db created Feb 14 21:34 by tody +Database contains 794 modules in 43 packages, file size 105460 bytes + +_clpackage Nov 4 1984 tody clpackage$_clpackage.hd +clpackage May 29 17:44 rooke clpackage$clpackage.hd +os Feb 13 11:06 tody host$os/doc/os.hd +root Nov 4 1984 tody lib$root.hd +_math Apr 1 13:38 tody math$_math.hd +curfit Jan 6 16:23 tody math$curfit/doc/curfit.hd +gsurfit Jan 2 14:46 davis math$gsurfit/doc/gsurfit.hd +iminterp Aug 6 16:31 davis math$iminterp/doc/iminterp.hd +bias Dec 17 8:53 valdes pkg$imred/bias/bias.hd +coude Dec 31 14:38 valdes pkg$imred/coude/coude.hd +vtel Jan 22 8:36 lytle pkg$imred/vtel/vtel.hd +plot Jan 28 14:04 hammond pkg$plot/plot.hd +.fi +.ih +SEE ALSO +mkhelpdb, help diff --git a/pkg/system/help/help.h b/pkg/system/help/help.h new file mode 100644 index 00000000..e1ec7070 --- /dev/null +++ b/pkg/system/help/help.h @@ -0,0 +1,115 @@ +# Help Definitions. + +# Control Structure. Contains all control parameters. Pointer to structure +# is passed to Lroff and on by Lroff to the input and output procedures. +# With the exceptions of H_EOF and H_NLINES, the control parameters are +# read only outside the main routine. + +define LEN_CTRLSTRUCT 220 +define SZ_CURPACK 39 # current package +define SZ_SECNAME 39 # section name, single section mode +define SZ_PARNAME 39 # parameter name +define SZ_TEMPLATE 79 # the original modules template +define SZ_HELPDB 1024 # max chars in helpdb file list + +define H_IN Memi[$1] # input file descriptor +define H_OUT Memi[$1+1] # output file descriptor +define H_OPTION Memi[$1+2] # option code (see below) +define H_TTY Memi[$1+3] # TTY device descriptor +define H_LMARGIN Memi[$1+4] # permanent left margin for Lroff +define H_RMARGIN Memi[$1+5] # permanent right margin for Lroff +define H_RAWIN Memi[$1+6] # if YES, do not look at input +define H_RAWOUT Memi[$1+7] # if YES, do not process output +define H_FILTER_INPUT Memi[$1+8] # if YES, filter out part of input +define H_PAGINATE Memi[$1+9] # paginate output? +define H_MANPAGE Memi[$1+10] # manpage style output? +define H_NLPP Memi[$1+11] # number of lines per manual page +define H_NLINES Memi[$1+12] # number of output lines on page +define H_STATE Memi[$1+13] # input state, hinput() +define H_EOF Memi[$1+14] # input should return EOF to Lroff +define H_QUIT Memi[$1+15] # stop program +define H_LENTL Memi[$1+16] # length of the TL template list +define H_ALLMODULES Memi[$1+17] # process all modules matching template +define H_FORMAT Memi[$1+18] # output format type +define H_SOFLAG Memi[$1+19] # standout flags + # (extra space) +define H_CURPACK Memc[P2C($1+20)] # current package +define H_SECNAME Memc[P2C($1+60)] # section name +define H_PARNAME Memc[P2C($1+100)] # parameter name +define H_TEMPLATE Memc[P2C($1+140)] # module name template + +# The nomore flag is set whenever the user responds negatively to the more? +# query. A nomore at the beginning of a help block or two nomores in a row +# stop the program. + +define NOMORE (-1) + +# Option codes. Max_options is used by the get_option keyword recognizer, +# which handles abbreviations. + +define O_HELP 1 # print full help block +define O_SOURCE 2 # print source code +define O_SYSDOC 3 # print technical system documentation +define O_ALLDOC 4 # print all documentation (!source) +define O_FILES 5 # print file names +define O_SUMMARY 6 # summarize contents of help file +define O_DIR 7 # print directory of help blocks +define O_REFERENCES 8 # keyword search output format +define MAX_OPTIONS 8 + +define O_PARAM 7 # output text for single parameter +define O_SECTION 8 # output text for single section +define O_MENU 9 # print package menu + +# Type codes for filenames. Passed to hd_getname to fetch the module name +# or a filename from a help directory. + +define TY_MODNAME 0 +define TY_HLP 1 +define TY_SYS 2 +define TY_SRC 3 +define TY_PKG 4 +define TY_MEN 5 +define TY_UNKNOWN 6 + +# Format codes. This is used to determine whether we output formatted +# text, HTML or Postscript. + +define HF_DEVICES "|terminal|text|gui|html|postscript|ps|" +define HF_TERMINAL 1 +define HF_TEXT 2 +define HF_GUI 3 +define HF_HTML 4 +define HF_POSTSCRIPT 5 +define HF_PS 6 + +# Help block header structure. A ".help" directive is decoded into this +# structure. The line number counter should be zeroed when the structure +# is allocated. + +define LEN_HBSTRUCT 1124 +define MAX_KEYS 50 +define SZ_TYPESTR 9 # help block type string +define SZ_KEY 19 # max size of a key +define SZ_SECTION 39 # section label, i.e., (Mar84) +define SZ_TITLE 63 # block title + +define HB_TYPE Memi[$1] # type of block (default TY_HLP) +define HB_LINENO Memi[$1+1] # line number within file +define HB_NKEYS Memi[$1+2] # number of keys +define HB_TYPESTR Memc[P2C($1+10)] # blk type string +define HB_KEY Memc[P2C($1+20+($2-1)*20)] # keys +define HB_SECTION Memc[P2C($1+1020)] # section label +define HB_TITLE Memc[P2C($1+1060)] # block title + +# Pagination Control Codes. The pagination directives BP, TP, KS, and KE +# are ignored when output is directed to the terminal, but are important +# when output is piped to the printer. When the line input routine HINPUT sees +# one of these directives in the input it places a control code in the +# data stream read by Lroff. Lroff passes control codes on to the output, +# i.e., to HOUTPUT, where pagination takes place. + +define BREAK_PAGE 1 # .bp +define TEST_PAGE 2 # .tp n +define START_KEEP 3 # .ks +define END_KEEP 4 # .ke diff --git a/pkg/system/help/helpdb.x b/pkg/system/help/helpdb.x new file mode 100644 index 00000000..04af40db --- /dev/null +++ b/pkg/system/help/helpdb.x @@ -0,0 +1,1203 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <syserr.h> +include <error.h> +include <finfo.h> +include <fset.h> +include <time.h> +include <mii.h> +include "help.h" +include "helpdir.h" + +.help helpdb +.nf ___________________________________________________________________________ +HELPDB -- Code to manage the help database. The help database is a set of +compiled package help directories. Each help directory file is compiled with +HD_OPEN and the resultant structure is saved in the database, indexed by the +name of the directory file. At run time, instead of opening and interpreting +multiple help directory files to expand templates, we merely read in the +compiled database and search the index for the entry for the named package, +returning a pointer to the compiled help directory structure for the package. +The help database must be recompiled with HDB_COMPILE whenever the system help +directory or a package help directory is modified. + + hdb_compile (root_helpdir_filename, database_filename) + + db = hdb_open (database) + hdb_close (db) + hp = hdb_load (db, help_directory_file) + hdb_free (db, hp) + +There is no provision for updating the database; the whole thing must be +recompiled with HDB_COMPILE. At HELP time the root help directory is opened +with HDB_OPEN, naming either a raw root help directory file or a compiled +help database file. Normally a precompiled help database is used, but if +desired the help directory files will be accessed directly. The directory +for an individual package is accessed with HDB_LOAD, which is functionally +equivalent to HD_OPEN (helpdir.x). HDB_FREE is functionally equivalent to +HD_CLOSE. + +Currently the entire database is read into memory to speed up database +searches. In the future this implementation should be changed to use the +DBIO faciltities if the database becomes large. +.endhelp ______________________________________________________________________ + +define DATA_OFFSET 513 # offset to data area, chars +define MAX_ENTRIES 100 # initial max db entries +define INC_ENTRIES 50 # increment if overflow +define MAX_DEPTH 20 # max nesting of packages +define MAX_MENUSIZE 500 # max modules in a table +define MAX_NAMELEN 20 # max chars in a module name in table +define FIRST_COL 6 # indentation of tables + +# Help database header structure. Stored at the beginning of a help +# database file. + +define LEN_HDBHEADER 14 +define HDB_MAGICVAL 110104B + +define HDB_MAGIC Memi[$1] # helpdb file type code +define HDB_RAW Memi[$1+1] # access compiled or raw database +define HDB_RHD Memi[$1+2] # if raw, HP of root help directory +define HDB_INDEX Memi[$1+3] # index of root help directory +define HDB_CRDATE Meml[$1+4] # creation date +define HDB_NENTRIES Memi[$1+5] # number of help directories in db +define HDB_MAXENTRIES Memi[$1+6] # maximum no. of help directories in db +define HDB_NMODULES Memi[$1+7] # count of the total number of modules +define HDB_INDEXOFFSET Meml[$1+8] # file offset of index, chars +define HDB_INDEXPTR Memi[$1+9] # pointer to loaded index, ty_struct +define HDB_INDEXLEN Memi[$1+10] # length of index structure, su +define HDB_DATAOFFSET Meml[$1+11] # file offset of data area, chars +define HDB_DATAPTR Memi[$1+12] # pointer to loaded data area, ty_struct +define HDB_DATALEN Memi[$1+13] # length of data area, struct units + +# Index structure. Identifies the contents of the database and tells where +# they are stored. There is one index entry for each help directory, i.e., +# for each package. + +define LEN_HDBINDEX 34 +define SZ_DBIKEY 63 +define LEN_DBIDATA 2 + +define DBI_KEY Memc[P2C($1)] # entry name +define DBI_OFFSET Memi[$1+32] # offset of entry into data area, su +define DBI_MTIME Meml[$1+33] # modification date of entry + + +# HDB_COMPILE -- Compile a set of help directories to produce a new help +# database. The root help directory is read first and entered into +# the database, followed by each subdirectory named in the root help +# directory. + +procedure hdb_compile (root_helpdir_file, helpdb_file, verbose) + +char root_helpdir_file[ARB] # name of root help directory file +char helpdb_file[ARB] # name of new database file +bool verbose # print informative messages + +pointer db, index, p1, p2, ix +bool no_entries_interchanged +int fd, temp[LEN_HDBINDEX], i + +int open() +bool strgt(), streq() +long clktime(), note(), fstatl() +errchk open, note, seek, hdb_compile_rhd, mii_writec, mii_writei + +begin + # Open the output database file. + fd = open (helpdb_file, NEW_FILE, BINARY_FILE) + + # Allocate and initialize the database header and index structures. + # The data area begins at a fixed offset and will be written out + # as we go. The index and db header are written out after all + # help directories have been processed. + + call calloc (db, LEN_HDBHEADER, TY_STRUCT) + call calloc (index, MAX_ENTRIES * LEN_HDBINDEX, TY_STRUCT) + + HDB_MAGIC(db) = HDB_MAGICVAL + HDB_MAXENTRIES(db) = MAX_ENTRIES + HDB_CRDATE(db) = clktime (long(0)) + + # Write zeros into the header area of the file, so that the next + # sequential write will place the first data record at the offset + # DATA_OFFSET. We assume that the empty index is larger than the + # header area. + + call write (fd, Memi[index], DATA_OFFSET - 1) + HDB_DATAOFFSET(db) = note (fd) + + # Compile root directory followed by all subdirectories. + # The root directory is expanded into a set of package help + # directories which are compiled and written into the data + # area of the database. The database descriptor and index + # structures are returned. + + call hdb_compile_rhd (fd, root_helpdir_file, db, index, verbose) + + # Sort the index and append it to the database file. A simple + # interchange sort is sufficient here; we have assumed that the + # database is small in this implementation of helpdb. + + if (HDB_NENTRIES(db) > 1) + repeat { + no_entries_interchanged = true + do i = 1, HDB_NENTRIES(db) - 1 { + p1 = index + (i - 1) * LEN_HDBINDEX + p2 = p1 + LEN_HDBINDEX + if (strgt (DBI_KEY(p1), DBI_KEY(p2))) { + call amovi (Memi[p1], temp, LEN_HDBINDEX) + call amovi (Memi[p2], Memi[p1], LEN_HDBINDEX) + call amovi (temp, Memi[p2], LEN_HDBINDEX) + no_entries_interchanged = false + } + } + } until (no_entries_interchanged) + + HDB_INDEXOFFSET(db) = note (fd) + HDB_INDEXLEN(db) = HDB_NENTRIES(db) * LEN_HDBINDEX + HDB_MAXENTRIES(db) = HDB_NENTRIES(db) + + # Get the offset into the index of the "_index" help directory + # (package name list). + + do i = 1, HDB_NENTRIES(db) { + ix = index + (i - 1) * LEN_HDBINDEX + if (streq (DBI_KEY(ix), "_index")) { + HDB_INDEX(db) = i + break + } + } + if (HDB_INDEX(db) == 0) + call eprintf ("Help warning: cannot find _index\n") + + # Write the index structure to the database file. + do i = 1, HDB_NENTRIES(db) { + ix = index + (i - 1) * LEN_HDBINDEX + call mii_writec (fd, DBI_KEY(ix), SZ_DBIKEY + 1) + call mii_writei (fd, DBI_OFFSET(ix), LEN_DBIDATA) + } + + # Update the database file header. + call seek (fd, BOFL) + call mii_writei (fd, Memi[db], LEN_HDBHEADER) + + call printf ("\nTotal of %d help modules in %d packages, ") + call pargi (HDB_NMODULES(db)) + call pargi (HDB_NENTRIES(db) - 1) + call printf ("file size %d bytes\n") + call pargl (fstatl (fd, F_FILESIZE) * SZB_CHAR) + + # All done; close files and deallocate buffers. + call close (fd) + call mfree (index, TY_STRUCT) + call mfree (db, TY_STRUCT) +end + + +# HDB_COMPILE_RHD -- Compile the root help directory and all subdirectories +# into the database. The package structure is hierarchical but the database +# is linear. Subdirectories (subpackages) are recursively expanded starting +# with all packages in the root help directory. Each subdirectory is entered +# into the database as it is found. We end up with an inverted index keyed +# by the filename of the help directory file for each package. Since the +# key is a filename each key is guaranteed to be unique. + +procedure hdb_compile_rhd (fd, root_helpdir_file, db, index, verbose) + +int fd # database file, written sequentially +char root_helpdir_file[ARB] # name of root help directory file +pointer db # database descriptor +pointer index # database index +bool verbose # print notes on structure of database + +bool found_a_subpackage +pointer hp_stk[MAX_DEPTH] # help directory pointer stack +int pk_stk[MAX_DEPTH] # subpackage index stack +char fname[SZ_FNAME] # helpdir filename + +int sp, pk, len_index +pointer ix, hp, modname, data, sv_sbuf +long mtime, fi[LEN_FINFO], savepos + +long note(), clktime() +int hd_getname(), finfo() +pointer hd_open(), hdb_make_rhd() +errchk finfo, seek, note, mii_writei +errchk hd_getname, hdb_make_rhd, hdb_getdata + +begin + # Initialize the stacks and open the next help directory file to be + # processed, i.e., the root directory file. + + sp = 0 + pk = 1 + call strcpy (root_helpdir_file, fname, SZ_FNAME) + + iferr (hp = hd_open (root_helpdir_file)) + call error (2, "cannot open root help directory file") + if (finfo (root_helpdir_file, fi) == ERR) + call error (3, "cannot get finfo on root help directory file") + mtime = FI_MTIME(fi) + + # We enter the compile loop ready to scan the next help directory file, + # which has been pushed onto the top of the stack. The help directory + # file is first entered into the database, then we scan the directory + # until a subdirectory is found. If a subdirectory is found it is + # opened and pushed onto the stack and the process repeats (hd_open + # does not leave the physical file open so running out of file + # descriptors is not a problem). When the end of a directory is + # reached the stack is popped, closing the current directory, and + # we continue to scan the previous directory until another subdirectory + # is found. + + repeat { + # Append the current compiled package help directory to the + # database. Update index; make index larger if it overflows. + + HDB_NMODULES(db) = HDB_NMODULES(db) + HD_NMODULES(hp) + HDB_NENTRIES(db) = HDB_NENTRIES(db) + 1 + + if (HDB_NENTRIES(db) > HDB_MAXENTRIES(db)) { + HDB_MAXENTRIES(db) = HDB_MAXENTRIES(db) + INC_ENTRIES + len_index = HDB_MAXENTRIES(db) * LEN_HDBINDEX + iferr (call realloc (index, len_index, TY_STRUCT)) + call fatal (1, "cannot reallocate index buffer") + } + ix = index + ((HDB_NENTRIES(db) - 1) * LEN_HDBINDEX) + + # Prepare the index entry for the help directory file. + call strcpy (fname, DBI_KEY(ix), SZ_DBIKEY) + DBI_MTIME(ix) = mtime + DBI_OFFSET(ix) = HDB_DATALEN(db) + + # Write the compiled help directory structure to the database + # file. The directory structure consists of the HD structure + # and a string buffer. We write out the HD structure followed + # by the string buffer. Each must be aligned to TY_STRUCT. + # The offset of the string buffer from the start of the helpdir + # struct is saved in the HD_NEXTCH field of the HD structure, + # to be used when loaded and referenced to compute a pointer to + # the buffer. + + HD_NEXTCH(hp) = HD_LENHD(hp) + sv_sbuf = HD_SBUF(hp) + HD_SBUF(hp) = 0 + call mii_writei (fd, Memi[hp], HD_LENHD(hp)) + HD_SBUF(hp) = sv_sbuf + call mii_writec (fd, Memc[HD_SBUF(hp)], HD_SZSBUF(hp)) + + # Keep track of the amount of struct storage that will be + # required later to hold the UNPACKED helpdir data. + + #HDB_DATALEN(db) = HDB_DATALEN(db) + + # HD_LENHD(hp) + ((HD_SZSBUF(hp) + SZ_STRUCT-1) / SZ_STRUCT) + HDB_DATALEN(db) = HDB_DATALEN(db) + + HD_LENHD(hp) + ((HD_SZSBUF(hp) + SZ_STRUCT32-1) / SZ_STRUCT32) + + call printf ("%3d %15s (%s): %d help modules\n") + call pargi (sp + 1) + if (HD_PAKNAME(hp) != NULL) + call pargstr (Memc[HD_SBUF(hp)+HD_PAKNAME(hp)]) + else + call pargstr ("") + call pargstr (fname) + call pargi (HD_NMODULES(hp)) + call flush (STDOUT) + + # Now scan the directory for subdirectories. If one is found, + # open it and push it on the stack, otherwise pop the stack and + # resume scanning the previous directory. + + repeat { + # Search for a module which is a subpackage. + found_a_subpackage = false + for (; pk <= HD_NMODULES(hp); pk=pk+1) { + if (verbose) { + modname = M_NAME(HD_MODULE(hp,pk)) + call printf ("\t\t[%d.%02d] %s\n") + call pargi (sp + 1) + call pargi (pk) + call pargstr (Memc[HD_SBUF(hp) + modname]) + } + if (hd_getname (hp, pk, TY_PKG, fname, SZ_FNAME) > 0) { + found_a_subpackage = true + break + } + } + + if (found_a_subpackage) { + if (finfo (fname, fi) == ERR) { + call eprintf ("\t\t%4w(cannot access `%s')\n") + call pargstr (fname) + # ...and continue searching the current helpdir + pk = pk + 1 + + } else { + # Got one; push it on the stack. Bump PK so that we + # resume scanning the package with the module following + # the subpackage. + sp = sp + 1 + if (sp > MAX_DEPTH) + call fatal (3, "packages nested too deeply") + hp_stk[sp] = hp + pk_stk[sp] = pk + 1 + iferr (hp = hd_open (fname)) { + hp = hp_stk[sp] + sp = sp - 1 + call eprintf ("cannot open helpdir `%s'\n") + call pargstr (fname) + next + } + pk = 1 + mtime = FI_MTIME(fi) + break # go process new helpdir + } + + } else { + # Helpdir has been exhausted. Close it and pop the + # stack, continue scanning on the previous helpdir. + + call hd_close (hp) + if (sp > 0) { + hp = hp_stk[sp] + pk = pk_stk[sp] + sp = sp - 1 + if (verbose) + call printf ("\t\t\t[end of package]\n") + + } else if (sp == 0) { + # Root helpdir file has been fully expanded. Scan + # all compiled helpdirs and produce a master helpdir + # containing an entry for each package in the database. + # This is similar to the root helpdir, but contains + # entries for packages at all levels, not just at the + # root. Note that we must save and restore the file + # position since hdb_make_rhd accesses the file. + + call flush (fd) + savepos = note (fd) + + # Load the database into memory. + + call seek (fd, HDB_DATAOFFSET(db)) + call calloc (data, 4*HDB_DATALEN(db), TY_STRUCT) + call hdb_getdata (fd, data, HDB_DATALEN(db)) + + hp = hdb_make_rhd (db, data, index) + pk = HD_NMODULES(hp) + 1 + call strcpy ("_index", fname, SZ_FNAME) + mtime = clktime (long (0)) + sp = -1 + + call mfree (data, TY_STRUCT) + call seek (fd, savepos) + break + + } else + return # ALL DONE + } + call flush (STDOUT) + } + } +end + + +# HDB_MAKE_RHD -- Make a dummy root help directory for the database. This +# entry looks just like any other compiled help directory, but serves as an +# index to all packages in the database. Each module in root is a package, +# and every package in the system, regardless of its level in the package +# hierarchy, has an entry in root. We could also use the database index +# for this purpose, but it is keyed by filename not package name, and the +# help code considers the root help directory to be conceptually just another +# package help directory (the db index is in the wrong format). The root +# directory is equivalent to the compiled lib$root.hd, except that it +# contains entries for all subpackages as well. +# +# We purposely do NOT sort the package list, because the list is accessed +# sequentially when templates are expanded, hence the order determines the +# search order for the database. Since the order in which packages are +# entered into the database is determined by the order in which they are +# encountered in a depth first search of the package hierarchy, the order of +# the packages in the root help directory determines the search order. +# It is desirable to search those packages most visible to the user (e.g., +# clpackage) before the more technical packages (e.g., sys). +# +# N.B.: This procedure is functionally similar to HD_OPEN and the HD_CLOSE +# procedure may be used to close the HD structure returned by either. + +pointer procedure hdb_make_rhd (db, data, index) + +pointer db #I database descriptor +pointer data #I data buffer (compiled help directories) +pointer index #I database index + +int i, j, len_modlist, pos +pointer hp, o_hp, mp, ix, sbuf, o_mp, c_modlist, hdfile + +bool streq() +pointer coerce() +int hd_putstr(), strncmp() +errchk hdb_putmodule + +begin + # Allocate and initialize descriptor and string buffer. Must init + # nextch to 1 because 0 is the null index. + + call calloc (hp, LEN_HDSTRUCT, TY_STRUCT) + call calloc (sbuf, SZ_SBUF, TY_CHAR) + + HD_SBUF(hp) = sbuf + HD_DEFDIR(hp) = NULL + HD_NEXTCH(hp) = 1 + HD_SZSBUF(hp) = SZ_SBUF + HD_LENHD(hp) = LEN_HDSTRUCT + HD_MAXMODULES(hp) = MAX_MODULES + + # The root help directory is the first module. Since the root is + # not a subpackage of any other package we cannot enter it in the + # loop below. We must handcraft this first entry. + + HD_NMODULES(hp) = 1 + mp = HD_MODULE(hp,1) + call aclri (Memi[mp], LEN_MODSTRUCT) + M_NAME(mp) = hd_putstr (hp, "_root") + M_PKG(mp) = hd_putstr (hp, DBI_KEY(index)) + + # Examine each compiled helpdir for subpackages. Add each subpackage + # found to the current directory. Do not add the index entries + # themselves because they are already referenced in the help + # directories. + + for (i=1; i <= HDB_NENTRIES(db); i=i+1) { + ix = index + (i - 1) * LEN_HDBINDEX + if (strncmp (DBI_KEY(ix), "_index", 6) == 0) + next + + o_hp = data + DBI_OFFSET(ix) + HD_SBUF(o_hp) = coerce (o_hp + HD_NEXTCH(o_hp), TY_STRUCT, TY_CHAR) + + for (j=1; j <= HD_NMODULES(o_hp); j=j+1) { + mp = HD_MODULE(o_hp,j) + if (M_PKG(mp) != NULL) + call hdb_putmodule (hp, o_hp, j) + } + } + + # Our procedure for building the _index module list has changed the + # ordering of the packages from the depth first order of the database + # index. We want the depth first order to be our search order so + # we must reorder the module list to agree with the DBI index. + # Make a copy of the modlist, then write a new one, overwriting the + # old, looking up each package in the index to determine its order + # in the new modlist. + + len_modlist = HD_NMODULES(hp) * LEN_MODSTRUCT + call calloc (c_modlist, len_modlist, TY_STRUCT) + call amovi (Memi[HD_MODULE(hp,1)], Memi[c_modlist], len_modlist) + + pos = 0 + do j = 1, HDB_NENTRIES(db) { + # Find next valid index entry. + ix = index + (j - 1) * LEN_HDBINDEX + if (strncmp (DBI_KEY(ix), "_index", 6) == 0) + next + + # Locate corresponding helpdir entry, if any. + do i = 1, HD_NMODULES(hp) { + o_mp = c_modlist + (i - 1) * LEN_MODSTRUCT + hdfile = HD_SBUF(hp) + M_PKG(o_mp) + if (Memc[hdfile] == EOS) + next + else if (streq (DBI_KEY(ix), Memc[hdfile])) { + # Append entry to output helpdir. + pos = pos + 1 + call amovi (Memi[o_mp], Memi[HD_MODULE(hp,pos)], + LEN_MODSTRUCT) + } + } + } + + call mfree (c_modlist, TY_STRUCT) + HD_NMODULES(hp) = pos + + # Return any unused space in string buffer. + call realloc (HD_SBUF(hp), HD_NEXTCH(hp), TY_CHAR) + HD_SZSBUF(hp) = HD_NEXTCH(hp) + + # Return any unused module descriptors. + HD_LENHD(hp) = HD_LENHD(hp) - + LEN_MODSTRUCT * (HD_MAXMODULES(hp) - HD_NMODULES(hp)) + call realloc (hp, HD_LENHD(hp), TY_STRUCT) + HD_MAXMODULES(hp) = HD_NMODULES(hp) + + return (hp) +end + + +# HDB_OPEN -- Open the help database. We can either read the precompiled +# help database or the distributed, raw help database (.hd textfiles). +# If the precompiled database is to be used access will be faster, but +# packages and modules added since the database was compiled with not be +# accessible. To use the precompiled database we read the database index +# into memory; the actual help files are accessed via this index at runtime. +# If multiple compiled databases are specified they are combined to form one +# large database. + +pointer procedure hdb_open (database) + +char database[ARB] #I name of database to be opened + +bool no_entries_interchanged +pointer sp, fname, files, hp, db, d_op, i_op, ix, p1, p2, db_save +int nfiles, nints, list, fd, d_len, i_len, i, temp[LEN_HDBINDEX] + +long clktime() +bool streq(), strgt() +pointer hd_open(), hdb_make_rhd() +int open(), mii_readi(), mii_readc() +int envgets(), access(), fntopnb(), fntgfnb() +errchk calloc, realloc, open, seek, syserrs +errchk hd_open, fntopnb, fntgfnb, hdb_make_rhd, hdb_getdata +define rejectfile_ 91 +define readerr_ 92 + +begin + call smark (sp) + call salloc (files, SZ_HELPDB, TY_CHAR) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (hp, LEN_HDBHEADER, TY_STRUCT) + call salloc (db_save, LEN_HDBHEADER, TY_STRUCT) + + # Allocate database descriptor. + call calloc (db, LEN_HDBHEADER, TY_STRUCT) + + # If the database name is "helpdir", raw access is desired and the + # name of the root help directory file is given by the environment + # variable "helpdir". If the database name is "helpdb", the + # precompiled database is to be used and the name of the database + # file or files is given by the environment variable "helpdb". + # Otherwise the database name is assumed to be the name of a raw or + # precompiled database file. + + if (streq (database, "helpdir")) { + HDB_RAW(db) = YES + if (envgets ("helpdir", Memc[files], SZ_HELPDB) <= 0) + call syserrs (SYS_ENVNF, "helpdir") + } else if (streq (database, "helpdb")) { + HDB_RAW(db) = NO + if (envgets ("helpdb", Memc[files], SZ_HELPDB) <= 0) + call syserrs (SYS_ENVNF, "helpdb") + } else { + HDB_RAW(db) = access (database, 0, TEXT_FILE) + call strcpy (database, Memc[files], SZ_HELPDB) + } + + # We now have the filename or file list; if it is a raw help directory + # file, open it with HD_OPEN and we are all done for now. Otherwise + # read the helpdb files and construct the help database index. + + if (HDB_RAW(db) == YES) { + iferr (HDB_RHD(db) = hd_open (Memc[files])) + call fatal (1, "cannot open root help directory file") + + call sfree (sp) + return (db) + } + + # Allocate and initialize empty database header and index structures. + HDB_MAGIC(db) = HDB_MAGICVAL + HDB_CRDATE(db) = clktime (long(0)) + + HDB_NENTRIES(db) = 0 + HDB_MAXENTRIES(db) = MAX_ENTRIES + HDB_NMODULES(db) = 0 + HDB_DATAPTR(db) = NULL + HDB_DATALEN(db) = 0 + HDB_INDEXPTR(db) = NULL + HDB_INDEXLEN(db) = 0 + HDB_MAXENTRIES(db) = HDB_NENTRIES(db) + + # Link a binary help database; open each precompiled database and + # link it into the full runtime database. + + list = fntopnb (Memc[files], YES) + nfiles = 0 + + while (fntgfnb (list, Memc[fname], SZ_FNAME) != EOF) { + iferr (fd = open (Memc[fname], READ_ONLY, BINARY_FILE)) { + call eprintf ("Cannot open help database file %s\n") + call pargstr (Memc[fname]) + next + } + + # Save descriptor in case we cannot read this file. + call amovi (Memi[db], Memi[db_save], LEN_HDBHEADER) + + # Read the database file header. + nints = LEN_HDBHEADER + if (mii_readi (fd, Memi[hp], nints) < nints) { + call eprintf ("Cannot read help database file header (%s)\n") + call pargstr (Memc[fname]) + goto rejectfile_ + } + + # Verify the file type. + if (HDB_MAGIC(hp) != HDB_MAGICVAL) { + call eprintf ("Not a help database file (%s)\n") + call pargstr (Memc[fname]) + goto rejectfile_ + } + + # Merge the headers. + HDB_NENTRIES(db) = HDB_NENTRIES(db) + HDB_NENTRIES(hp) + HDB_NMODULES(db) = HDB_NMODULES(db) + HDB_NMODULES(hp) + HDB_MAXENTRIES(db) = HDB_NENTRIES(db) + + d_len = HDB_DATALEN(db) + i_len = HDB_INDEXLEN(db) + + # Make room for the new data and index entries. + iferr { + HDB_DATALEN(db) = HDB_DATALEN(db) + HDB_DATALEN(hp) + call realloc (HDB_DATAPTR(db), HDB_DATALEN(db), TY_STRUCT) + HDB_INDEXLEN(db) = HDB_INDEXLEN(db) + HDB_INDEXLEN(hp) + call realloc (HDB_INDEXPTR(db), HDB_INDEXLEN(db), TY_STRUCT) + } then + call erract (EA_WARN) + + d_op = HDB_DATAPTR(db) + d_len + i_op = HDB_INDEXPTR(db) + i_len + + # Append the data area of the new database file to the end of + # the data buffer. + + call seek (fd, HDB_DATAOFFSET(hp)) + call hdb_getdata (fd, d_op, HDB_DATALEN(hp)) + + # Append the index area of the new database file to the end of + # the index buffer. + + nints = HDB_INDEXLEN(hp) + call seek (fd, HDB_INDEXOFFSET(hp)) + + do i = 1, HDB_NENTRIES(hp) { + ix = i_op + (i - 1) * LEN_HDBINDEX + if (mii_readc (fd, DBI_KEY(ix), SZ_DBIKEY + 1) < SZ_DBIKEY + 1) + goto readerr_ + if (mii_readi (fd, DBI_OFFSET(ix), LEN_DBIDATA) < LEN_DBIDATA) { +readerr_ call eprintf ("Cannot read database index (%s)\n") + call pargstr (Memc[fname]) + goto rejectfile_ + } + + # Patch the index entry to reflect the new offset of the + # directory entry in the data buffer. Rename the _index + # entries in the old (input) databases, since we will be + # building a new _index for the final composite database. + + DBI_OFFSET(ix) = DBI_OFFSET(ix) + d_len + if (streq (DBI_KEY(ix), "_index")) { + call sprintf (DBI_KEY(ix), SZ_DBIKEY, "_index.%s") + call pargstr (Memc[fname]) + } + } + + nfiles = nfiles + 1 + call close (fd) + next +rejectfile_ + # Could not read file; restore the descriptor to the state it + # was in before we tried to read the file, to repair any damage. + + d_op = HDB_DATAPTR(db); i_op = HDB_INDEXPTR(db) + call amovi (Memi[db_save], Memi[db], LEN_HDBHEADER) + HDB_DATAPTR(db) = d_op; HDB_INDEXPTR(db) = i_op + + call close (fd) + } + + # Verify that there was at least one valid file in the list. + if (nfiles <= 0) + call error (5, "invalid help database file list") + + # Build the package name index (root helpdir) for the new database. + hp = hdb_make_rhd (db, HDB_DATAPTR(db), HDB_INDEXPTR(db)) + + # Append the compiled package help directory to the database. + HDB_NMODULES(db) = HDB_NMODULES(db) + HD_NMODULES(hp) + HDB_NENTRIES(db) = HDB_NENTRIES(db) + 1 + + # Append the compiled _index helpdir and associated string buffer + # to the database data buffer, as if these data structures had been + # read from the help database file (all helpdir access codes assume + # this structure). + + d_len = HDB_DATALEN(db) + nints = HD_LENHD(hp) + (HD_SZSBUF(hp) + SZ_STRUCT32-1) / SZ_STRUCT32 + HDB_DATALEN(db) = HDB_DATALEN(db) + nints + call realloc (HDB_DATAPTR(db), HDB_DATALEN(db), TY_STRUCT) + d_op = HDB_DATAPTR(db) + d_len + + HD_NEXTCH(hp) = HD_LENHD(hp) + call amovi (Memi[hp], Memi[d_op], HD_LENHD(hp)) + call amovc (Memc[HD_SBUF(hp)], Memi[d_op+HD_LENHD(hp)], HD_SZSBUF(hp)) + + # Add an index entry for the _index helpdir. + if (HDB_NENTRIES(db) > HDB_MAXENTRIES(db)) { + HDB_MAXENTRIES(db) = HDB_MAXENTRIES(db) + 1 + nints = HDB_MAXENTRIES(db) * LEN_HDBINDEX + iferr (call realloc (HDB_INDEXPTR(db), nints, TY_STRUCT)) + call fatal (1, "cannot reallocate index buffer") + } + + ix = HDB_INDEXPTR(db) + (HDB_NENTRIES(db) - 1) * LEN_HDBINDEX + call strcpy ("_index", DBI_KEY(ix), SZ_DBIKEY) + DBI_MTIME(ix) = clktime (long(0)) + DBI_OFFSET(ix) = d_op - HDB_DATAPTR(db) + + # Free dedicated hp/sbuf, since descriptor is in data buffer now. + call hd_close (hp) + + # Sort the index; a crude sort is adequate here. + if (HDB_NENTRIES(db) > 1) { + repeat { + no_entries_interchanged = true + do i = 1, HDB_NENTRIES(db) - 1 { + p1 = HDB_INDEXPTR(db) + (i - 1) * LEN_HDBINDEX + p2 = p1 + LEN_HDBINDEX + if (strgt (DBI_KEY(p1), DBI_KEY(p2))) { + call amovi (Memi[p1], temp, LEN_HDBINDEX) + call amovi (Memi[p2], Memi[p1], LEN_HDBINDEX) + call amovi (temp, Memi[p2], LEN_HDBINDEX) + no_entries_interchanged = false + } + } + } until (no_entries_interchanged) + } + + # Get the index offset of the NEW "_index" help directory. + HDB_INDEX(db) = 0 + do i = 1, HDB_NENTRIES(db) { + ix = HDB_INDEXPTR(db) + (i - 1) * LEN_HDBINDEX + if (streq (DBI_KEY(ix), "_index")) { + HDB_INDEX(db) = i + break + } + } + if (HDB_INDEX(db) == 0) + call eprintf ("Help warning: cannot find _index") + + call fntclsb (list) + call sfree (sp) + + return (db) +end + + +# HDB_CLOSE -- Close the help database. If raw database is being accessed, +# this means close root help directory and free DB struct. If precompiled, +# deallocate all buffers used by the database. + +procedure hdb_close (db) + +pointer db # database descriptor + +begin + if (HDB_RAW(db) == YES) + call hd_close (HDB_RHD(db)) + else { + call mfree (HDB_DATAPTR(db), TY_STRUCT) + call mfree (HDB_INDEXPTR(db), TY_STRUCT) + } + call mfree (db, TY_STRUCT) +end + + +# HDB_LOAD -- Load the named help directory. Help directories are referred +# to by the name of the directory file, and the database is keyed by the name +# of the file. If the database is being accessed raw, we open and compile +# the named file directly, otherwise we look up the compiled directory in the +# database. In either case we return a HD pointer to the compiled directory. +# The directory "_index" is special, being the package index directory for the +# entire database. + +pointer procedure hdb_load (db, helpdir) + +pointer db # database descriptor +char helpdir[ARB] # help directory to be accessed. + +bool index +pointer hp, ix, sp, errmsg + +bool streq() +int hdb_search() +pointer hd_open(), coerce() +errchk hdb_open + +begin + call smark (sp) + call salloc (errmsg, SZ_LINE, TY_CHAR) + + index = (streq (helpdir, "_index") || streq (helpdir, "_root")) + + if (HDB_RAW(db) == YES) { + if (index) + hp = HDB_RHD(db) + else + hp = hd_open (helpdir) + + } else { + # Compute and return pointer to compiled HD. Fix up pointer to + # the string buffer sbuf, since the pointer value depends on the + # value of the pointer to the newly allocated data area. If not + # found, return NULL pointer. + + if (index) { + ix = HDB_INDEXPTR(db) + (HDB_INDEX(db) - 1) * LEN_HDBINDEX + + } else if (hdb_search (db, helpdir, ix) == ERR) { + # There should be a better way to do this... Format error + # message and pass to the error handling code, then restore + # stack before taking the error action. + + call sprintf (Memc[errmsg], SZ_LINE, + "help directory `%s' not found") + call pargstr (helpdir) + iferr (call error (6, Memc[errmsg])) { + call sfree (sp) + call erract (EA_ERROR) + return (NULL) + } + } + + hp = HDB_DATAPTR(db) + DBI_OFFSET(ix) + HD_SBUF(hp) = coerce (hp + HD_NEXTCH(hp), TY_STRUCT, TY_CHAR) + } + + call sfree (sp) + return (hp) +end + + +# HDB_FREE -- Free space for a help directory loaded with HDB_LOAD. If we are +# using raw access, we let the helpdir package free what ever it wants to since +# it did the allocating. If we are accessing the compiled database then there +# is nothing to free, since everything is maintained in memory. + +procedure hdb_free (db, hp) + +pointer db # database descriptor +pointer hp # help directory + +begin + if (HDB_RAW(db) == YES) + call hd_close (hp) +end + + +# HDB_SEARCH -- Search the database index for the given key. Since the index +# has been sorted we can use a binary search. If the key is found we return +# a pointer to the associated index as an output argument, and OK as the +# function value. + +int procedure hdb_search (db, key, ix) + +pointer db # database descriptor +char key[ARB] # filename key to be located +pointer ix # pointer to index entry (output) + +int low, high, pos +pointer ixoff +bool strle(), streq() + +begin + ixoff = HDB_INDEXPTR(db) + low = 1 + high = HDB_NENTRIES(db) + + # Cut range of search in half until range is narrowed to two values (if + # we go until HIGH-LOW >= 1 an infinite loop can occur). + + while (high - low > 1) { + pos = (high + low) / 2 + if (strle (key, DBI_KEY(ixoff + (pos-1) * LEN_HDBINDEX))) + high = pos + else + low = pos + } + + ix = ixoff + (high - 1) * LEN_HDBINDEX + if (streq (key, DBI_KEY(ix))) + return (high) + ix = ixoff + (low - 1) * LEN_HDBINDEX + if (streq (key, DBI_KEY(ix))) + return (low) + + return (ERR) +end + + +# HDB_EXAMINE -- Examine the structure of the compiled database. A description +# of the contents is printed on the output file. + +procedure hdb_examine (fd, helpdb, verbose) + +int fd # output file +char helpdb[ARB] # filename of database to be examined +bool verbose # print menus as well + +int list, i +long fi[LEN_FINFO] +pointer sp, fname, date, db, ixoff, ix + +bool strne() +pointer hdb_open() +int finfo(), fntopnb(), fntgfnb() +errchk hdb_open, hdb_printpack, fntopnb, fntgfnb + +begin + call smark (sp) + call salloc (date, SZ_DATE, TY_CHAR) + call salloc (fname, SZ_FNAME, TY_CHAR) + + db = hdb_open (helpdb) + ixoff = HDB_INDEXPTR(db) + + call cnvdate (HDB_CRDATE(db), Memc[date], SZ_DATE) + + list = fntopnb (helpdb, YES) + while (fntgfnb (list, Memc[fname], SZ_FNAME) != EOF) { + if (finfo (Memc[fname], fi) == ERR) { + call eprintf ("Cannot get info on file `%s'\n") + call pargstr (Memc[fname]) + next + } + + call fprintf (fd, "Help database %s created %s by %s, size=%d\n") + call pargstr (Memc[fname]) + call pargstr (Memc[date]) + call pargstr (FI_OWNER(fi)) + call pargl (FI_SIZE(fi)) + } + call fntclsb (list) + + call fprintf (fd, "Total of %d modules in %d packages\n") + call pargi (HDB_NMODULES(db)) + call pargi (HDB_NENTRIES(db) - 1) + + do i = 1, HDB_NENTRIES(db) { + ix = ixoff + (i - 1) * LEN_HDBINDEX + if (strne (DBI_KEY(ix), "_index")) + call hdb_printpack (fd, db, ix, verbose) + } + + call hdb_close (db) + call sfree (sp) +end + + +# HDB_PRINTPACK -- Print a description of a single package on the output +# file. + +procedure hdb_printpack (fd, db, ix, verbose) + +int fd # output file +pointer db # database descriptor +pointer ix # database index descriptor of package +bool verbose # print menus + +int m +pointer sp, hp, paknames, date +long fi[LEN_FINFO] +int hd_getname(), envgeti(), finfo() +pointer hdb_load() +errchk hd_getname + +begin + call smark (sp) + call salloc (paknames, MAX_MENUSIZE, TY_POINTER) + call salloc (date, SZ_DATE, TY_CHAR) + + iferr (hp = hdb_load (db, DBI_KEY(ix))) { + call erract (EA_WARN) + call sfree (sp) + return + } + + call cnvdate (DBI_MTIME(ix), Memc[date], SZ_DATE) + if (finfo (DBI_KEY(ix), fi) == ERR) + FI_OWNER(fi) = EOS + + if (verbose) + call fprintf (fd, "\n%s %s %s %s\n") + else + call fprintf (fd, "%-12s %s %-8s %s\n") + + if (HD_PAKNAME(hp) != 0) + call pargstr (Memc[HD_SBUF(hp) + HD_PAKNAME(hp)]) + else + call pargstr ("") + call pargstr (Memc[date]) + call pargstr (FI_OWNER(fi)) + call pargstr (DBI_KEY(ix)) + + if (verbose) { + # Extract the names of the modules in the package. Save the + # pointers in an array for the table print routine. + + for (m=0; m < MAX_MENUSIZE; m=m+1) { + call salloc (Memi[paknames+m], MAX_NAMELEN, TY_CHAR) + if (hd_getname (hp, m+1, TY_MODNAME, Memc[Memi[paknames+m]], + MAX_NAMELEN) <= 0) + break + } + + # Now print the table. It is not necessary to sort the table, + # because the "helpdir" code (which reads the help directory) has + # already done so. + + call strtbl (fd, Memc, Memi[paknames], m, FIRST_COL, + envgeti ("ttyncols"), MAX_NAMELEN, 0) + } + + call hdb_free (db, hp) + call sfree (sp) +end + + +# HDB_PUTMODULE -- Put a module (subpackage) into the root help directory. +# Add new entry, increasing space if necessary. Expand all filenames to +# remove help ldir references and place filenames in our string buffer, +# sbuf offsets into module descriptor. Increase size of sbuf if it fills. + +procedure hdb_putmodule (hp, o_hp, pk) + +pointer hp # new help directory being extended +pointer o_hp # old help directory +int pk # module number in old directory + +int firstch, m +pointer sp, fname, sbuf, o_sbuf, mp, o_mp, pakname +int hd_getname(), hd_putstr() +bool streq() + +begin + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + + sbuf = HD_SBUF(hp) + o_sbuf = HD_SBUF(o_hp) + o_mp = HD_MODULE(o_hp,pk) + pakname = o_sbuf + M_NAME(o_mp) + + # Check if this is a redefinition of a module already defined. + # If so, warn user that new package does not have a unique name, + # and omit package. + + firstch = Memc[pakname] + for (m=1; m <= HD_NMODULES(hp); m=m+1) { + mp = HD_MODULE(hp,m) + if (Memc[sbuf+M_NAME(mp)] == firstch) + if (streq (Memc[sbuf+M_NAME(mp)], Memc[pakname])) { + call eprintf ("package name `%s' (hd=%s) is not unique\n") + call pargstr (Memc[pakname]) + call pargstr (Memc[o_sbuf+M_PKG(o_mp)]) + call sfree (sp) + return + } + } + + # If we are out of space for modules, increase the descriptor + # structure size to allow more module descriptors. + + if (m > HD_NMODULES(hp)) { + if (m > HD_MAXMODULES(hp)) { + HD_LENHD(hp) = HD_LENHD(hp) + (INC_MODULES * LEN_MODSTRUCT) + call realloc (hp, HD_LENHD(hp), TY_STRUCT) + HD_MAXMODULES(hp) = HD_MAXMODULES(hp) + INC_MODULES + } + HD_NMODULES(hp) = m + } + + mp = HD_MODULE(hp,m) + call aclri (Memi[mp], LEN_MODSTRUCT) + + # Put module name in string buffer and save index of string in module + # descriptor. + + M_NAME(mp) = hd_putstr (hp, Memc[pakname]) + + # Extract all filenames and move into string buffer. Call hd_getname to + # extract filenames from old directory, so that help-ldir references + # are expanded. + + if (hd_getname (o_hp, pk, TY_HLP, Memc[fname], SZ_FNAME) > 0) + M_HLP(mp) = hd_putstr (hp, Memc[fname]) + if (hd_getname (o_hp, pk, TY_SYS, Memc[fname], SZ_FNAME) > 0) + M_SYS(mp) = hd_putstr (hp, Memc[fname]) + if (hd_getname (o_hp, pk, TY_SRC, Memc[fname], SZ_FNAME) > 0) + M_SRC(mp) = hd_putstr (hp, Memc[fname]) + if (hd_getname (o_hp, pk, TY_PKG, Memc[fname], SZ_FNAME) > 0) + M_PKG(mp) = hd_putstr (hp, Memc[fname]) + if (hd_getname (o_hp, pk, TY_MEN, Memc[fname], SZ_FNAME) > 0) + M_MEN(mp) = hd_putstr (hp, Memc[fname]) + + call sfree (sp) +end + + +# HDB_GETDATA -- Read a stored series of compiled help directories, stored +# externally in a machine independent format, into the given data buffer. +# Each stored help directory consists of a fixed sized MII-32 header followed +# by a MII byte packed string buffer of arbitrary length. Reading begins +# at the current file position. + +procedure hdb_getdata (fd, obuf, buflen) + +int fd #I input file +pointer obuf #O receives unpacked helpdir data +int buflen #O max su out + +int i, nelem, nr, sz_mii_struct +pointer op, hp +int mii_readi(), mii_readc() +errchk mii_readi, mii_readc +define readerr_ 91 + +begin + nr = 0 + for (op=obuf; nr < buflen; ) { + hp = op + + # Get fixed size helpdir header. + if (mii_readi (fd, Memi[op], LEN_BASEHD) < LEN_BASEHD) + goto readerr_ + nr = nr + LEN_BASEHD + + # Get module entries. + op = op + LEN_BASEHD + nelem = HD_LENHD(hp) - LEN_BASEHD + if (mii_readi (fd, Memi[op], nelem) < nelem) + goto readerr_ + nr = nr + nelem + + # Get string buffer. + op = op + nelem + nelem = HD_SZSBUF(hp) # / (SZ_INT / SZ_INT32) + if (mii_readc (fd, Memi[op], nelem) < nelem) + goto readerr_ + + nr = nr + ((nelem + SZ_STRUCT32-1) / SZ_STRUCT32) + sz_mii_struct = MII_INT / NBITS_BYTE / SZB_CHAR + op = op + ((nelem + sz_mii_struct-1) / sz_mii_struct) + } + + return + +readerr_ + # Common read error code. + call error (1, "Cannot read help database data\n") +end diff --git a/pkg/system/help/helpdir.h b/pkg/system/help/helpdir.h new file mode 100644 index 00000000..89b851a7 --- /dev/null +++ b/pkg/system/help/helpdir.h @@ -0,0 +1,34 @@ +# Size limiting definitions. + +define MAX_LDIRS 50 # maximum ldirs for package +define MAX_MODULES 100 # initial maximum no. modules +define INC_MODULES 50 # increment if overflow +define SZ_SBUF 2048 # initial size string buffer +define INC_SZSBUF 1024 # increment if overflow + +define LEN_HDSTRUCT (10+MAX_LDIRS+MAX_MODULES*LEN_MODSTRUCT) +define LEN_BASEHD 10 +define LEN_MODSTRUCT 6 + +# Helpdir descriptor structure. + +define HD_SBUF Memi[$1] # string buffer +define HD_NEXTCH Memi[$1+1] # index of next char in sbuf +define HD_SZSBUF Memi[$1+2] # size of string buffer +define HD_DEFDIR Memi[$1+3] # offset to defdir +define HD_NLDIRS Memi[$1+4] # number of logical directories +define HD_NMODULES Memi[$1+5] # number of modules in package +define HD_MAXMODULES Memi[$1+6] # max no. of modules in package +define HD_LENHD Memi[$1+7] # length of this structure +define HD_PAKNAME Memi[$1+8] # offset of package name string +define HD_LDIR Memi[$1+10+$2-1] # indices of ldir strings +define HD_MODULE ($1+60+($2-1)*6) # module descriptors + +# Module descriptor structure. + +define M_NAME Memi[$1] # module name index +define M_HLP Memi[$1+1] # help file index +define M_SYS Memi[$1+2] # system docs file index +define M_SRC Memi[$1+3] # source code file index +define M_PKG Memi[$1+4] # pkg helpdir file index +define M_MEN Memi[$1+5] # package menu file index diff --git a/pkg/system/help/helpdir.x b/pkg/system/help/helpdir.x new file mode 100644 index 00000000..38a2e12c --- /dev/null +++ b/pkg/system/help/helpdir.x @@ -0,0 +1,775 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include <error.h> +include "help.h" +include "helpdir.h" + +.help helpdir +.nf ___________________________________________________________________________ +HELPDIR -- Routines for accessing helpdir files. A helpdir lists the +modules in a package, as well as the files containing the help text and +source for each module. There are two kinds of helpdir files: the 'packhelp' +file lists the packages, and each package has its own helpdir file listing +the modules within that package. The following functions are required to +access help module lists: + + hp = hd_open (fname) + hd_close (hp) + + modnum = hd_findmod (hp, modname) + nchars = hd_getname (hp, modnum, field, outstr, maxch) + hd_debug (hp, out) + +The HD_OPEN function opens the helpdir file and decodes the contents, producing +a binary structure pointed to by hp. HD_FINDMOD searches for a module by name, +returning the module number within the helpdir. HD_GETNAME fetches either +the module name (field "mod") or a file name (fields "hlp", "sys", etc.). +File names are returned as OS pathnames, with logical directory expansion taking +place within the helpdir package. + +Helpdir files have the following structure: + + $defdir = pathname|ldir + $ldir1 = pathname|ldir + $ldir2 = pathname|ldir + ... + $ldirN = pathname|ldir + + module1 hlp=file, sys=file, src=file, pkg=file, men=file + module2 hlp=file, etc. + ... + moduleN hlp=file, etc. + +The dollar signs are required to make it easy to distinguish logical directory +declarations from module entries. Logical directories defined local to the +help directory file are not expanded recursively. If the last nonwhite char +on a line is a comma, the file list is assumed to be continued on the next +line. If two or more files in a module list are the same, all but the first +may be set to ".." and the last file name given will be used. Quotes are +optional. All file assignments are optional, and they may occur in any order. +.endhelp _______________________________________________________________________ + + +# HD_OPEN -- Open the helpdir file, allocate descriptor and decode file +# into descriptor. Sort module list when done, unless sorting is disabled +# by inclusion of the directive ".nosort" in the text. Ignore comment lines and +# blank lines. Ldir declarations and module entries may be given in any +# order. + +pointer procedure hd_open (helpdir_file) + +char helpdir_file[ARB] +bool sort_modules +pointer sp, hp, ip, lbuf, defdir, word +int fd, junk + +bool streq() +int open(), getline(), fnroot(), fnldir(), ctowrd() +int hd_putstr() +errchk salloc, open, calloc, getline, hd_putstr +errchk hd_putldiry, hd_putmodule, hd_sort_modules + +begin + call smark (sp) + call salloc (lbuf, SZ_LINE, TY_CHAR) + call salloc (defdir, SZ_PATHNAME, TY_CHAR) + call salloc (word, SZ_FNAME, TY_CHAR) + + # If helpdir file is not yet installed, print warning message + # and return the NULL pointer, indicating that the help directory + # could not be loaded. + + iferr (fd = open (helpdir_file, READ_ONLY, TEXT_FILE)) { + call sfree (sp) + call erract (EA_ERROR) + return (NULL) + } + + # Allocate and initialize descriptor and string buffer. Must init + # nextch to 1 because 0 is the null index. + + call calloc (hp, LEN_HDSTRUCT, TY_STRUCT) + call calloc (HD_SBUF(hp), SZ_SBUF, TY_CHAR) + HD_DEFDIR(hp) = NULL + HD_NEXTCH(hp) = 1 + HD_SZSBUF(hp) = SZ_SBUF + HD_MAXMODULES(hp) = MAX_MODULES + HD_LENHD(hp) = LEN_HDSTRUCT + sort_modules = true + + # Extract package name into string buffer. The package name is assumed + # to be the root of the filename. + + junk = fnroot (helpdir_file, Memc[lbuf], SZ_LINE) + HD_PAKNAME(hp) = hd_putstr (hp, Memc[lbuf]) + + # Extract directory prefix of the package help directory file. Make + # it the default directory prefix for all filenames in the directory. + + if (fnldir (helpdir_file, Memc[defdir], SZ_PATHNAME) == 0) { + call fpathname (helpdir_file, Memc[lbuf], SZ_LINE) + junk = fnldir (Memc[lbuf], Memc[defdir], SZ_PATHNAME) + } + call sprintf (Memc[lbuf], SZ_LINE, "defdir = %s\n") + call pargstr (Memc[defdir]) + call hd_putldiry (hp, Memc[lbuf]) + + # Compile the file, processing all logical directory definitions, + # set option statments, and module declarations. Ignore blank lines + # and comment lines. + + while (getline (fd, Memc[lbuf]) != EOF) { + for (ip=lbuf; IS_WHITE (Memc[ip]); ip=ip+1) + ; + if (Memc[ip] == '#' || Memc[ip] == '\n' || Memc[ip] == EOS) + next + + # A leading dollar sign denotes a logical directory declaration. + # A leading period denotes a compiler directive. + # Anything else is a module entry. + + if (Memc[ip] == '$') { + call hd_putldiry (hp, Memc[ip+1]) + } else if (Memc[ip] == '.') { + ip = ip + 1 + if (ctowrd (Memc, ip, Memc[word], SZ_FNAME) <= 0) + next + # The directive ".nosort" disables sorting of the module list. + # There are no other such directives at present, but they are + # easy to add. + if (streq (Memc[word], "nosort")) + sort_modules = false + else { + call eprintf ("Warning: unknown directive %s in helpdir\n") + call pargstr (Memc[word]) + } + next + } else + call hd_putmodule (hp, fd, Memc[lbuf]) + } + + # We are all done with the helpdir file, so close it. Sort module + # list alphabetically by name. + + call close (fd) + if (sort_modules && HD_NMODULES(hp) > 1) + call hd_sort_modules (hp) + + # Return any unused space in string buffer. + call realloc (HD_SBUF(hp), HD_NEXTCH(hp), TY_CHAR) + HD_SZSBUF(hp) = HD_NEXTCH(hp) + + # Return any unused module descriptors. + HD_LENHD(hp) = HD_LENHD(hp) - + LEN_MODSTRUCT * (HD_MAXMODULES(hp) - HD_NMODULES(hp)) + HD_MAXMODULES(hp) = HD_NMODULES(hp) + call realloc (hp, HD_LENHD(hp), TY_STRUCT) + + call sfree (sp) + return (hp) +end + + +# HD_CLOSE -- Close the helpdir descriptor. The helpdir file has already +# been closed; all we need do is return the string buffer and the helpdir +# descriptor structure. + +procedure hd_close (hp) + +pointer hp + +begin + if (hp != NULL) { + call mfree (HD_SBUF(hp), TY_CHAR) + call mfree (hp, TY_STRUCT) + } +end + + +# HD_PUTLDIRY -- Decode a logical directory declaration and store it away +# in the descriptor. We are passed the declaration minus the leading +# dollar sign. Format: "variable = string". + +procedure hd_putldiry (hp, decl) + +pointer hp +char decl[ARB] + +int ip, nldir, strp +pointer sp, buf, op +char hd_getc() +int strncmp(), hd_putstr() +errchk salloc, hd_getc, hd_putstr + +begin + call smark (sp) + call salloc (buf, SZ_LINE, TY_CHAR) + + # Do nothing if null declaration. + for (ip=1; IS_WHITE(decl[ip]); ip=ip+1) + ; + if (decl[ip] == '\n' || decl[ip] == EOS || decl[ip] == '#') { + call sfree (sp) + return + } + + # Extract "ldir=string", eliminating all whitespace, and deleting + # the newline at the end of the statement. Quotes around the string + # are optional and are deleted in hl_getc. + + for (op=buf; hd_getc (decl, ip, Memc[op]) != EOS; op=op+1) + if (Memc[op] == '\n') + op = op - 1 + + # Deposit the "ldir=string" in the string buffer, and set the + # appropriate pointers for either defdir or a new ldir. + + strp = hd_putstr (hp, Memc[buf]) + if (strncmp (Memc[buf], "defdir", 6) == 0) + HD_DEFDIR(hp) = strp + else { + nldir = HD_NLDIRS(hp) + 1 + if (nldir > MAX_LDIRS) + call error (8, "Too many ldir declarations in helpdir") + HD_NLDIRS(hp) = nldir + HD_LDIR(hp,nldir) = strp + } + + call sfree (sp) +end + + +# HD_PUTMODULE -- Put a module declaration into the helpdir descriptor. +# Start new entry; save module name; process file names. If line ends +# in a comma, get a new line. Print warning if an unknown file type +# keyword is encountered. + +procedure hd_putmodule (hp, fd, lbuf) + +pointer hp +int fd +char lbuf[ARB] + +char ch +int ip, junk, m, ftype, strp +pointer sp, buf, op, sbuf, mp + +bool streq() +char hd_getc(), hd_peekc() +int getline(), ctowrd(), hd_putstr() +errchk salloc, getline, hd_putstr, hd_getc + +begin + call smark (sp) + call salloc (buf, SZ_LINE, TY_CHAR) + sbuf = HD_SBUF(hp) + + # Fetch module name. Cannot be null or line is blank and we would + # not have been called. + ip = 1 + junk = ctowrd (lbuf, ip, Memc[buf], SZ_LINE) + + # Check if this is a redefinition of a module already defined. + # If so, overwrite descriptor of earlier module, else allocate + # a new descriptor. + + for (m=1; m <= HD_NMODULES(hp); m=m+1) { + mp = HD_MODULE(hp,m) + if (streq (Memc[buf], Memc[sbuf+M_NAME(mp)])) + break + } + + if (m > HD_NMODULES(hp)) { + # If we are out of space for modules, increase the descriptor + # structure size to allow more module descriptors. + if (m > HD_MAXMODULES(hp)) { + HD_LENHD(hp) = HD_LENHD(hp) + (INC_MODULES * LEN_MODSTRUCT) + call realloc (hp, HD_LENHD(hp), TY_STRUCT) + HD_MAXMODULES(hp) = HD_MAXMODULES(hp) + INC_MODULES + } + HD_NMODULES(hp) = m + } + + mp = HD_MODULE(hp,m) + call aclri (Memi[mp], LEN_MODSTRUCT) + + # Put module name in string buffer and save index of string in descr. + M_NAME(mp) = hd_putstr (hp, Memc[buf]) + + # Process file name fields, if any. Unrecognized file type keywords + # cause a warning to be issued. Redundant entires overwrite old + # entries. Order makes no diff, absence is ok. + + op = buf + ftype = TY_UNKNOWN + strp = 0 + + repeat { + ch = hd_getc (lbuf, ip, ch) + + switch (ch) { + case '=': + # Buffer contains the code word for the file being set. + Memc[op] = EOS + call strlwr (Memc[buf]) + if ( streq (Memc[buf], "hlp")) + ftype = TY_HLP + else if (streq (Memc[buf], "sys")) + ftype = TY_SYS + else if (streq (Memc[buf], "src")) + ftype = TY_SRC + else if (streq (Memc[buf], "pkg")) + ftype = TY_PKG + else if (streq (Memc[buf], "men")) + ftype = TY_MEN + else { + ftype = TY_UNKNOWN + call eprintf ("Warning: bad file type `%s' in helpdir\n") + call pargstr (Memc[buf]) + } + op = buf + + case ',', '\n', EOS: + # Buffer contains the file name string. Put it in the string + # buffer and save pointer in appropriate field of module + # descriptor. + + Memc[op] = EOS + + # If filename is "..", i.e., "sys=..", the filename is identical + # to that last specified. Use the file name pointer. + + if (streq (Memc[buf], "..")) { + if (strp == 0) + call error (9, "helpdir: `..' reference, no prev file") + } else + strp = hd_putstr (hp, Memc[buf]) + + switch (ftype) { + case TY_HLP: + M_HLP(mp) = strp + case TY_SYS: + M_SYS(mp) = strp + case TY_SRC: + M_SRC(mp) = strp + case TY_PKG: + M_PKG(mp) = strp + case TY_MEN: + M_MEN(mp) = strp + } + op = buf + + if (ch == '\n' || ch == EOS) + break # end of statement + else { + # Check for continuation on next line. Read a new line into + # the buffer if end of line follows comma. + + if (hd_peekc(lbuf,ip) == '\n' || hd_peekc(lbuf,ip) == EOS) { + if (getline (fd, lbuf) == EOF) { + call eprintf ("Unexpected EOF in helpdir file\n") + call sfree (sp) + return + } + ip = 1 + } + } + + default: + # Regular character. Deposit in buffer. + if (op >= buf+SZ_LINE) + call error (10, "helpdir: buffer overflow reading modspec") + Memc[op] = ch + op = op + 1 + } + } + + call sfree (sp) +end + + +# HD_GETC -- Get next nonwhite character from the input line. Leave pointer +# pointing to next character. Ignore quotes, so that file name strings can +# be quoted without penalty. + +char procedure hd_getc (lbuf, ip, ch) + +char lbuf[ARB] +int ip +char ch +char hd_peekc() + +begin + ch = hd_peekc (lbuf, ip) + if (ch != EOS) + ip = ip + 1 + + return (ch) +end + + +# HD_PEEKC -- Peek at the next nonwhite character on a line, but do not +# advance the input pointer past the character. Ignore quote characters +# and comments. + +char procedure hd_peekc (lbuf, ip) + +char lbuf[ARB] +int ip +char ch + +begin + for (ch=lbuf[ip]; ch != EOS; ch=lbuf[ip]) + if (IS_WHITE(ch) || ch == '\'' || ch == '"') { + ip = ip + 1 + } else if (ch == '#') { + while (lbuf[ip] != '\n' && lbuf[ip] != EOS) + ip = ip + 1 + } else + break + + return (ch) +end + + +# HD_PUTSTR -- Put a string (incl EOS) in the string buffer at nextch. +# If there is not enough space in the buffer, reallocate a larger buffer. +# Return the index of the string in the string buffer. + +int procedure hd_putstr (hp, str) + +pointer hp +char str[ARB] +int nextch, nchars, strlen() +errchk realloc + +begin + # Null strings are not stored and cause a null index to be returned. + nchars = strlen (str) + if (nchars == 0) + return (0) + + nextch = HD_NEXTCH(hp) + if (nextch + nchars + 1 > HD_SZSBUF(hp)) { + HD_SZSBUF(hp) = HD_SZSBUF(hp) + INC_SZSBUF + call realloc (HD_SBUF(hp), HD_SZSBUF(hp), TY_CHAR) + } + + call strcpy (str, Memc[HD_SBUF(hp) + nextch], ARB) + HD_NEXTCH(hp) = nextch + nchars + 1 + + return (nextch) +end + + +# HD_SORT_MODULES -- Sort the module list alphabetically by name. +# A simple exchange sort is ok because the sort time is negligible +# compared to all the file accesses, Lroff etc. + +procedure hd_sort_modules (hp) + +pointer hp + +bool sorted +int nmodules, m, mlen, i, temp +pointer sbuf, mp1, mp2 +bool strgt() + +begin + nmodules = HD_NMODULES(hp) + sbuf = HD_SBUF(hp) + mlen = LEN_MODSTRUCT + if (nmodules < 2) + return + + repeat { + sorted = true + do m = 1, nmodules-1 { + mp1 = HD_MODULE(hp,m) + mp2 = mp1 + mlen + if (strgt (Memc[sbuf+M_NAME(mp1)], Memc[sbuf+M_NAME(mp2)])) { + do i = 0, mlen-1 { + temp = Memi[mp1+i] + Memi[mp1+i] = Memi[mp2+i] + Memi[mp2+i] = temp + } + sorted = false + } + } + } until (sorted) +end + + +# HD_FINDMOD -- Search for the named module and return the module number +# if found. Abbreviations are permitted. An ambiguous abbreviation is +# an error. + +int procedure hd_findmod (hp, modname) + +pointer hp +char modname[ARB] +int m, namelen, module +pointer mp, sbuf +int strlen(), strncmp() + +begin + namelen = strlen (modname) + if (namelen == 0) + return (0) + module = 0 + sbuf = HD_SBUF(hp) + + for (m=1; m <= HD_NMODULES(hp); m=m+1) { + mp = HD_MODULE(hp,m) + + if (strncmp (Memc[sbuf+M_NAME(mp)], modname, namelen) == 0) { + if (strlen (Memc[sbuf+M_NAME(mp)]) == namelen) { + return (m) # exact match + } else if (module != 0) { + call eprintf ("\n--> %s <--\n") + call pargstr (modname) + call error (11, "Ambiguous module name abbreviation") + } else + module = m + } + } + + return (module) +end + + +# HD_GETNAME -- Get the module name or a filename. If a filename is requested, +# check if filename contains a logical directory reference. If yes, try to +# satisfy the reference from the local list of ldirs (but no recursive refs +# permitted here). If no, prepend the defdir string. + +define nullstr_ 91 +define nodefdir_ 92 + +int procedure hd_getname (hp, m, field, outstr, maxch) + +pointer hp +int m # module number +int field # field code +char outstr[ARB] +int maxch + +int len_ldir, op +pointer mp, sp, ldir, sbuf, fname_ptr, ip, subdir +int strncmp(), gstrcpy(), hd_getldir(), fnldir() +errchk salloc, hd_getldir + +begin + call smark (sp) + call salloc (ldir, SZ_PATHNAME, TY_CHAR) + call salloc (subdir, SZ_FNAME, TY_CHAR) + + if (hp == NULL) + call error (12, "hd_getname: bad helpdir descriptor") + + if (m < 1 || m > HD_NMODULES(hp)) { +nullstr_ call sfree (sp) + outstr[1] = EOS + return (0) + } + + mp = HD_MODULE(hp,m) + sbuf = HD_SBUF(hp) + + switch (field) { + case TY_MODNAME: + call sfree (sp) + return (gstrcpy (Memc[sbuf+M_NAME(mp)], outstr, maxch)) + case TY_HLP: + fname_ptr = M_HLP(mp) + case TY_SYS: + fname_ptr = M_SYS(mp) + case TY_SRC: + fname_ptr = M_SRC(mp) + case TY_PKG: + fname_ptr = M_PKG(mp) + case TY_MEN: + fname_ptr = M_MEN(mp) + default: + goto nullstr_ + } + + # If index is zero, no filename was given. + if (fname_ptr == 0) + goto nullstr_ + + # Get ldir substring, if any, from filename. If no ldir, prepend + # defdir and quit. Otherwise lookup ldir in local list. If found, + # prepend value. Otherwise the ldir is a CL global one, and return + # filename without modification. If the given ldir string begins + # with "./", substitute the value of defdir for the ".". + + len_ldir = fnldir (Memc[sbuf+fname_ptr], Memc[ldir], SZ_PATHNAME) + + if (len_ldir == 0) { + if (HD_DEFDIR(hp) == 0) + goto nodefdir_ + for (ip = sbuf + HD_DEFDIR(hp); Memc[ip] != '='; ip=ip+1) + ; + op = gstrcpy (Memc[ip+1], outstr, maxch) + 1 + ip = sbuf + fname_ptr + } else if (hd_getldir (hp, Memc[ldir], Memc[subdir], SZ_FNAME) == 0) { + op = 1 + ip = sbuf + fname_ptr + } else { + if (strncmp (Memc[subdir], "./", 2) == 0) { + if (HD_DEFDIR(hp) == 0) +nodefdir_ call error (13, "Default directory omitted in helpdir") + for (ip = sbuf + HD_DEFDIR(hp); Memc[ip] != '='; ip=ip+1) + ; + op = gstrcpy (Memc[ip+1], outstr, maxch) + 1 + ip = subdir + 2 + } else { + op = 1 + ip = subdir + } + op = op + gstrcpy (Memc[ip], outstr[op], maxch - op + 1) + ip = sbuf + fname_ptr + len_ldir + } + + call sfree (sp) + return (gstrcpy (Memc[ip], outstr[op], maxch - op + 1)) +end + + +# HD_GETLDIR -- Search the logical directory list for the package helpdir +# file for the given ldir name. Return value in output string if found. + +int procedure hd_getldir (hp, ldir, outstr, maxch) + +pointer hp +char ldir[ARB] +char outstr[ARB] +int maxch + +int i +pointer sp, ip, op, sbuf, envvar, filvar +bool streq() +int gstrcpy() + +begin + call smark (sp) + call salloc (envvar, SZ_FNAME, TY_CHAR) + call salloc (filvar, SZ_FNAME, TY_CHAR) + + sbuf = HD_SBUF(hp) + + # Ldir string has the form "ldir$". Extract the ldir name into the + # filvar buffer, omitting the $ delimiter. + i = 1 + for (op=filvar; ldir[i] != '$' && ldir[i] != EOS; op=op+1) { + Memc[op] = ldir[i] + i = i + 1 + } + Memc[op] = EOS + + for (i=1; i <= HD_NLDIRS(hp); i=i+1) { + # Extract the helpdir env variable name into the envvar buffer, + # stopping when the '=' is reached. + + ip = sbuf + HD_LDIR(hp,i) + for (op=envvar; Memc[ip] != '='; op=op+1) { + if (Memc[ip] == EOS) + call error (14, "helpdir: missing '=' in ldir declaration") + Memc[op] = Memc[ip] + ip = ip + 1 + } + Memc[op] = EOS + + # Return whatever follows the '=' if we have a match. The input + # pointer is left pointing at the '='. + + if (streq (Memc[filvar], Memc[envvar])) { + call sfree (sp) + return (gstrcpy (Memc[ip+1], outstr, maxch)) + } + } + + outstr[1] = EOS + call sfree (sp) + return (0) +end + + +# HD_DEBUG -- Dump a compiled helpdir structure to the given output file. + +procedure hd_debug (hd, out) + +pointer hd #I compiled helpdir +int out #O output file + +int i +pointer sbuf, mp + +begin + sbuf = HD_SBUF(hd) + + # General header stuff. + call fprintf (out, + "pakname=%d(%s), nmodules=%d, maxmodules=%d, lenhd=%d\n") + call pargi (HD_PAKNAME(hd)) + call pargstr (Memc[sbuf+HD_PAKNAME(hd)]) + call pargi (HD_NMODULES(hd)) + call pargi (HD_MAXMODULES(hd)) + call pargi (HD_LENHD(hd)) + call fprintf (out, "defdir=%d(%s)\n") + call pargi (HD_DEFDIR(hd)) + call pargstr (Memc[sbuf+HD_DEFDIR(hd)]) + call fprintf (out, "sbuf=%x, szsbuf=%d, nextch=%d\n") + call pargi (HD_SBUF(hd)) + call pargi (HD_SZSBUF(hd)) + call pargi (HD_NEXTCH(hd)) + + # List of defined logical directories. + if (HD_NLDIRS(hd) > 0) { + call fprintf (out, "nldirs=%d:\n") + call pargi (HD_NLDIRS(hd)) + do i = 1, HD_NLDIRS(hd) { + call fprintf (out, "%7d %s\n") + call pargi (i) + call pargstr (Memc[sbuf+HD_LDIR(hd,i)]) + } + } + + # List the modules. + if (HD_NMODULES(hd) > 0) { + call fprintf (out, "modules:\n") + do i = 1, HD_NMODULES(hd) { + mp = HD_MODULE(hd,i) + call fprintf (out, "%7d %20s\n") + call pargi (i) + call pargstr (Memc[sbuf+M_NAME(mp)]) + if (M_HLP(mp) > 0) { + call fprintf (out, "\t\t\t\tHLP=%d(%s)\n") + call pargi (M_HLP(mp)) + call pargstr (Memc[sbuf+M_HLP(mp)]) + } + if (M_SYS(mp) > 0) { + call fprintf (out, "\t\t\t\tSYS=%d(%s)\n") + call pargi (M_SYS(mp)) + call pargstr (Memc[sbuf+M_SYS(mp)]) + } + if (M_SRC(mp) > 0) { + call fprintf (out, "\t\t\t\tSRC=%d(%s)\n") + call pargi (M_SRC(mp)) + call pargstr (Memc[sbuf+M_SRC(mp)]) + } + if (M_PKG(mp) > 0) { + call fprintf (out, "\t\t\t\tPKG=%d(%s)\n") + call pargi (M_PKG(mp)) + call pargstr (Memc[sbuf+M_PKG(mp)]) + } + if (M_MEN(mp) > 0) { + call fprintf (out, "\t\t\t\tMEN=%d(%s)\n") + call pargi (M_MEN(mp)) + call pargstr (Memc[sbuf+M_MEN(mp)]) + } + } + } +end diff --git a/pkg/system/help/hinput.x b/pkg/system/help/hinput.x new file mode 100644 index 00000000..c47716e8 --- /dev/null +++ b/pkg/system/help/hinput.x @@ -0,0 +1,274 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include "help.h" + +.help hinput +.nf __________________________________________________________________________ +HINPUT -- Lroff line input procedure. Called by Lroff to get lines of +input text. Function varies slightly depending on the Help option. +If printing only single param or single section, our job is to eat all +input which is not part of the indicated section of the help block. +A parameter block begins with ".ls paramname" and ends with a matching +".le" or ".ih", if the text is formatted. Similarly, the single section +begins with a ".ih" followed by the section name on the next line. +.endhelp ______________________________________________________________________ + +define SEARCHING 1 +define IN_BLOCK 2 +define MAXPAT 10 + + +# HINPUT -- Get next input line from the help block. + +int procedure hinput (ctrl, lbuf) + +pointer ctrl +char lbuf[ARB] + +bool formatted +int fd, level, status, ip +int getline(), strmatch(), gstrcpy(), stridxs() +int h_findparam(), h_findsection() +errchk getline, h_findparam, h_findsection +define findsec_ 91 + +begin + fd = H_IN(ctrl) + + # EOF flag is set after param block has been fully input, + # but normally before the actual end of file. + + if (H_EOF(ctrl) == YES || H_QUIT(ctrl) == YES) + return (EOF) + else if (H_RAWIN(ctrl) == YES || H_FILTER_INPUT(ctrl) == NO) + return (getline (fd, lbuf)) + + # We get here only if special processing is required to + # filter out all but a section of the help text. + + switch (H_STATE(ctrl)) { + case BOF: + # Determine whether or not the help block is formatted. + # Read in first line but save it for later and return a + # dummy line to Lroff, telling it whether or not the help + # block is formatted. + + repeat { + if (getline (fd, lbuf) == EOF) + return (EOF) + for (ip=1; IS_WHITE(lbuf[ip]); ip=ip+1) + ; + } until (lbuf[ip] != '\n') + call ungetline (fd, lbuf) + + if (lbuf[1] == '.') { + formatted = true + status = gstrcpy (".in 4\n", lbuf, SZ_LINE) + } else { + formatted = false + status = gstrcpy (".nf\n", lbuf, SZ_LINE) + } + H_STATE(ctrl) = SEARCHING + + case SEARCHING: + status = getline (fd, lbuf) + if (H_PARNAME(ctrl) != EOS) { + status = h_findparam (fd, lbuf, formatted, H_PARNAME(ctrl)) + level = 1 + } else if (H_SECNAME(ctrl) != EOS) +findsec_ status = h_findsection (fd, lbuf, formatted, H_SECNAME(ctrl)) + H_STATE(ctrl) = IN_BLOCK + + case IN_BLOCK: + # By the time we get here we are in the parameter or single + # section. + status = getline (fd, lbuf) + + if (lbuf[1] == '.') { + if (strmatch (lbuf, "^.{ih}") > 0) { + if (stridxs ("|", H_SECNAME(ctrl)) > 0) + goto findsec_ + status = EOF + } else if (H_PARNAME(ctrl) != EOS) { + if (strmatch (lbuf, "^.{ls}") > 0) + level = level + 1 + else if (strmatch (lbuf, "^.{le}") > 0) { + level = level - 1 + if (level == 0) + status = EOF + } + } + } + + default: + call error (15, "hinput: unknown input state encountered") + } + + return (status) +end + + +# H_FINDPARAM -- If text contains format directives, eat input lines until +# a ".ls" directive is found which contains the param name as a substring. +# If the text is not formatted, search for a line beginning with the pattern. +# We are called with the first line of the file in lbuf. + +int procedure h_findparam (fd, lbuf, formatted, param) + +int fd +char lbuf +bool formatted +char param[ARB] + +bool match_found +pointer sp, pattern +int getline(), strmatch(), strlen() +errchk getline + +begin + call smark (sp) + call salloc (pattern, SZ_FNAME, TY_CHAR) + + match_found = false + + if (formatted) { + call sprintf (Memc[pattern], SZ_FNAME, "{%s}") + call pargstr (param) + repeat { + if (strmatch (lbuf, "^.{ls}") > 0) + if (strmatch (lbuf, Memc[pattern]) > 0) { + match_found = true + break + } + } until (getline (fd, lbuf) == EOF) + + } else { + call sprintf (Memc[pattern], SZ_FNAME, "^#{%s}") + call pargstr (param) + repeat { + if (strmatch (lbuf, Memc[pattern]) > 0) { + match_found = true + break + } + } until (getline (fd, lbuf) == EOF) + } + + call sfree (sp) + if (match_found) + return (strlen (lbuf)) + else + return (EOF) +end + + +# H_FINDSECTION -- If text contains format directives, eat input lines until +# a ".ih" directive is found for the named section. If the text is not +# formatted, search for a line beginning with the section name. +# We are called with the first line of the file in lbuf. + +int procedure h_findsection (fd, lbuf, formatted, sections) + +int fd # input file +char lbuf # line buffer +bool formatted # is help block formatted +char sections[ARB] # list of sections "a|b|c" + +bool match_found +int npat, ip +pointer sp, patbuf, patoff[MAXPAT], op +bool h_match() +int getline(), strmatch(), gstrcpy() +errchk getline + +begin + call smark (sp) + call salloc (patbuf, SZ_LINE, TY_CHAR) + + # Process the list of sections into patbuf and patoff, i.e., into a + # list of EOS delimited strings in the string buffer patbuf. Each + # section name or abbreviation is delimited by '|' (or). + + npat = 1 + op = patbuf + patoff[1] = op + + for (ip=1; sections[ip] != EOS; ip=ip+1) + switch (sections[ip]) { + case '|': + Memc[op] = EOS + op = op + 1 + npat = min (MAXPAT, npat + 1) + patoff[npat] = op + default: + Memc[op] = sections[ip] + op = op + 1 + } + Memc[op] = EOS + + match_found = false + + if (formatted) { + repeat { + if (strmatch (lbuf, "^.{ih}") > 0) + if (getline (fd, lbuf) != EOF) { + match_found = h_match (lbuf, patoff, npat) + if (match_found) + break + } + } until (getline (fd, lbuf) == EOF) + + } else { + repeat { + match_found = h_match (lbuf, patoff, npat) + if (match_found) + break + } until (getline (fd, lbuf) == EOF) + } + + + # If only one section is to be printed, skip the section name, otherwise + # pass the .ih secname on to the text formatter. + + call sfree (sp) + if (match_found) { + if (npat == 1) + return (getline (fd, lbuf)) + else { + call ungetline (fd, lbuf) + return (gstrcpy (".ih\n", lbuf, SZ_LINE)) + } + } else + return (EOF) +end + + +# H_MATCH -- Match a set of patterns against a line of test, matching only +# at the beginning of line in either case. + +bool procedure h_match (lbuf, patoff, npat) + +char lbuf[ARB] # line of text +pointer patoff[npat] # pointers to pattern strings +int npat # number of patterns + +int pat +pointer sp, pattern +int strmatch() + +begin + call smark (sp) + call salloc (pattern, SZ_FNAME, TY_CHAR) + + for (pat=1; pat <= npat; pat=pat+1) { + call sprintf (Memc[pattern], SZ_FNAME, "^{%s}") + call pargstr (Memc[patoff[pat]]) + if (strmatch (lbuf, Memc[pattern]) > 0) { + call sfree (sp) + return (true) + } + } + + call sfree (sp) + return (false) +end diff --git a/pkg/system/help/houtput.x b/pkg/system/help/houtput.x new file mode 100644 index 00000000..499e4292 --- /dev/null +++ b/pkg/system/help/houtput.x @@ -0,0 +1,147 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ttyset.h> +include <chars.h> +include <fset.h> +include "help.h" + +define HELP "[q=quit,d=downhalf,f|sp=downfull,j|cr=downline,N=next]" +define QUIT 'q' +define FWD_SCREEN 'f' +define SCROLL_DOWN 'd' +define NEXT_LINE 'j' +define NEXT_FILE 'N' +define NEXT_FILE_ALT 'n' +define REDRAW '\014' + + +# HOUTPUT -- The help line output procedure. Count output lines and paginate +# output if enabled. If manpage format is desired pass output lines to manpage +# filter. + +procedure houtput (ctrl, lbuf) + +pointer ctrl +char lbuf[ARB] +bool formfeed, query_enabled +int map_cc, maxlines, nlines, ip, cmd +int envgeti(), ho_getcmd() +data map_cc /YES/ + +begin + if (H_RAWOUT(ctrl) == YES) { + call putline (H_OUT(ctrl), lbuf) + return + } else if (H_MANPAGE(ctrl) == YES) { + call man_output (H_OUT(ctrl), lbuf, H_NLPP(ctrl), + H_LMARGIN(ctrl), H_RMARGIN(ctrl)) + return + } else if (H_EOF(ctrl) == YES) + return + + # Check for end of page (either full or formfeed in line) + # before processing the output line, because we want to + # pause to let the user read the screen before paging. + + ip = 1 + formfeed = (lbuf[1] == '\f') + if (formfeed) + ip = 2 + + iferr (maxlines = envgeti ("ttynlines") - 1) + maxlines = 24 + + # Help blocks and files are preceded by a form feed and a header. + # The "more" query is issued between blocks and files to give the + # user a chance to read the previous page before the screen is cleared. + # The query is disabled for the first block or file by initialization + # of nlines to -1 in the main help routine. + + query_enabled = (H_NLINES(ctrl) > 0) + nlines = max (0, H_NLINES(ctrl)) + + if (H_PAGINATE(ctrl) == YES) { + if (formfeed || nlines >= maxlines) { + if (query_enabled) { + # Pause to give the user a chance to read the output, and + # to indicate whether they wish to continue. + + repeat { + cmd = ho_getcmd (H_TTY(ctrl)) + + switch (cmd) { + case FWD_SCREEN, BLANK, REDRAW: + nlines = 0 + case SCROLL_DOWN: + nlines = (maxlines + 1) / 2 + case NEXT_LINE, CR, LF: + nlines = maxlines - 1 + case NEXT_FILE, NEXT_FILE_ALT: + H_EOF(ctrl) = YES + nlines = 0 + case QUIT: + H_QUIT(ctrl) = YES + H_EOF(ctrl) = YES + default: + call eprintf ("\07") + call flush (STDERR) + cmd = ERR + } + } until (cmd > 0) + } + + if (formfeed && H_QUIT(ctrl) == NO) { + call ttyclear (H_OUT(ctrl), H_TTY(ctrl)) + nlines = 0 + } + } + } + + # Do not output the line if the user just said to quit. + if (H_EOF(ctrl) == NO) + if (lbuf[ip] != EOS) { + call ttyputline (H_OUT(ctrl), H_TTY(ctrl), lbuf[ip], map_cc) + nlines = nlines + 1 + } + + H_NLINES(ctrl) = nlines +end + + +# HO_GETCMD -- Query the user for a single character command keystroke. + +int procedure ho_getcmd (tty) + +pointer tty # tty descriptor + +int key +char strval[1] +int clgkey() + +begin + # Ensure synchronization with the standard output. + call flush (STDOUT) + + # Print query in standout mode. + call ttyso (STDERR, tty, YES) + call eprintf (HELP) + call ttyso (STDERR, tty, NO) + call flush (STDERR) + + call fseti (STDIN, F_SETREDRAW, REDRAW) + + # Read the command keystroke in raw mode. + if (clgkey ("cl.ukey", key, strval, 1) == EOF) + key = QUIT + else if (key == INTCHAR) + key = QUIT + + call fseti (STDIN, F_SETREDRAW, 0) + + # Erase the prompt and return. + call eprintf ("\r") + call ttyclearln (STDERR, tty) + call flush (STDERR) + + return (key) +end diff --git a/pkg/system/help/lroff/breakline.o b/pkg/system/help/lroff/breakline.o Binary files differnew file mode 100644 index 00000000..d0dceee2 --- /dev/null +++ b/pkg/system/help/lroff/breakline.o diff --git a/pkg/system/help/lroff/breakline.x b/pkg/system/help/lroff/breakline.x new file mode 100644 index 00000000..2be9f5a1 --- /dev/null +++ b/pkg/system/help/lroff/breakline.x @@ -0,0 +1,99 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <chars.h> +include "lroff.h" + +define LEFT 1 +define RIGHT 2 + +# BREAKLINE -- Break the current output line and output with or without +# justification. The "current output line" is the set of NWORDS words +# pointed to by the WORDS array of word pointers. Copy the NWORDS words +# into the output buffer; do nothing if the word buffer is empty. If the +# OUTPUT buffer is not empty, append a newline, causing the buffer to be +# flushed. Breakline is called by textout() when enough words have been +# collected to fill an output line, or whenever it is desired to flush +# the output buffer. If both the word buffer and the output buffer are +# empty, breakline is essentially a nop. + +procedure breakline (out, justify_flag) + +extern out() +int justify_flag + +int w, i, end_to_fill_from, next_output_column +int nholes, nfill, n_per_hole, nextra, hole1, hole2 +errchk outstr, outc +include "lroff.com" +include "words.com" + +begin + if (wbuf == NULL || words == NULL) + call error (1, "No Lroff word buffer allocated") + + # First we flush the word buffer. + if (nwords > 0) { + # Strip any trailing whitespace from the line. + for (wp=wp-2; Memc[wp] == BLANK && wp > wbuf; wp=wp-1) + wcols = wcols - 1 + wp = wp + 1 + Memc[wp] = EOS + wp = wp + 1 + + # If justification is disabled or if there is only one word on + # the line, do not add spaces to right justify. + + if (justify_flag == NJ || justify == NO || nwords <= 1) { + for (w=1; w <= nwords; w=w+1) + call outstr (out, Memc[Memi[words+w-1]]) + + } else { + # To justify the line, determine the number of extra spaces + # needed to right justify the last character on the line. + # Determine the number of holes between words, and how many + # spaces to add to each. + + nholes = nwords - 1 + nfill = max (0, right_margin - left_margin + 1 - wcols) + n_per_hole = nfill / nholes + nextra = nfill - (n_per_hole * nholes) + + # Determine where the extra spaces need to be added. Add + # extra spaces from the left and then the right on succesive + # lines. + if (end_to_fill_from == LEFT) { + hole1 = 1 + hole2 = nextra + end_to_fill_from = RIGHT + } else { + hole1 = nwords - nextra + hole2 = nholes + end_to_fill_from = LEFT + } + + # Fill the output line. Move the word and then add the + # requisite number of blanks per hole, plus an extra if in + # the range hole1 to hole2 (at left or right). + + do w = 1, nwords { + call outstr (out, Memc[Memi[words+w-1]]) + do i = 1, n_per_hole + call outc (out, BLANK) + if (w >= hole1 && w <= hole2) + call outc (out, BLANK) + } + } + } + + + # If there is anything in the output buffer, append a newline, flushing + # the buffer. + + call getoutcol (next_output_column) + if (next_output_column > left_margin) + call outc (out, '\n') + + wp = wbuf # clear the word buffer + nwords = 0 + wcols = 0 +end diff --git a/pkg/system/help/lroff/center.o b/pkg/system/help/lroff/center.o Binary files differnew file mode 100644 index 00000000..6e3442d3 --- /dev/null +++ b/pkg/system/help/lroff/center.o diff --git a/pkg/system/help/lroff/center.x b/pkg/system/help/lroff/center.x new file mode 100644 index 00000000..b3581f3a --- /dev/null +++ b/pkg/system/help/lroff/center.x @@ -0,0 +1,32 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <chars.h> +include "lroff.h" + +# CENTER_TEXT -- Center and output the next input line within the current +# left and right margins. The optional argument specifies the column +# (measured from the left margin) at which the text is to be centered. + +procedure center_text (in, out, linebuf, ip) + +extern in(), out() +char linebuf[ARB] +int ip + +int len_inputline, center_column, nblanks, i +int in(), input(), lgetarg() +errchk breakline, input, outc, outline +include "lroff.com" + +begin + call breakline (out, NJ) + center_column = lgetarg (linebuf, ip, (left_margin + right_margin) / 2) + len_inputline = input (in, linebuf) - 1 + + if (len_inputline != EOF) { + nblanks = center_column - (len_inputline / 2) - left_margin + for (i=1; i <= nblanks; i=i+1) + call outc (out, BLANK) + call outline (out, linebuf) + } +end diff --git a/pkg/system/help/lroff/dols.o b/pkg/system/help/lroff/dols.o Binary files differnew file mode 100644 index 00000000..55b5fbcd --- /dev/null +++ b/pkg/system/help/lroff/dols.o diff --git a/pkg/system/help/lroff/dols.x b/pkg/system/help/lroff/dols.x new file mode 100644 index 00000000..26ba165b --- /dev/null +++ b/pkg/system/help/lroff/dols.x @@ -0,0 +1,108 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <chars.h> +include <error.h> +include "lroff.h" + +# DO_LS -- Depending on the action, push an LS block (print label and indent +# one level), or pop an LS block (restore the previous indent level). INIT_LS +# clears the LS stack. Called with the LS command line in "lbuf", minus +# the ".ls". The command line may consist of an argument specifying the number +# of spaces to indent, the label string, both, or neither. +# If the label string is shorter than the amount by which the block is indented, +# the text block will begin on the same line as the label, otherwise the line +# is broken and the text block begins on the following line. + +procedure do_LS (out, lbuf, action, last_command) + +extern out() +char lbuf[ARB] # ".ls [arg] [text]" +int action # LS or LE +int last_command + +int indent[MAX_NLS] +int n, ip, next_output_column +int lgetarg(), strlen() +errchk skiplines, outstr, outc, breakline +include "lroff.com" + +begin + switch (action) { + case LS: + # We normally skip a line when beginning an LS block. If two or + # more LS directives are given in a row, however, only skip a + # single line. + + call breakline (out, NJ) + if (last_command != LS) + call skiplines (out, 1) + call testpage (out, 3) + + # Push new LS block on stack. + nls = nls + 1 + if (nls > MAX_NLS) { + iferr (call error (1, "LS blocks nested too deep")) + call erract (EA_WARN) + nls = MAX_NLS + } + + # Get number of spaces to indent, if given. If arg is negative, + # do not remember the argument, otherwise make it the new default. + ip = 1 + n = lgetarg (lbuf, ip, ls_indent) + if (n < 0) + indent[nls] = -n + else { + ls_indent = n + indent[nls] = ls_indent + } + + # Copy the label, if any, into the output buffer. We must do this + # before we change the left margin since the label is not indented. + + call outstr (out, lbuf[ip]) + + # Try to adjust the left margin by the indicated amount. Save the + # actual indentation level for restoration by LE. + + indent[nls] = max (perm_left_margin, min (right_margin, + left_margin + indent[nls])) - left_margin + left_margin = left_margin + indent[nls] + + # If the length of the label string plus one blank does not leave + # space to start the first line of the text block on the same line, + # we must break the line and start the block on the next line. + # Otherwise, output spaces until the new left margin is reached. + + if (strlen (lbuf[ip]) >= indent[nls]) + call outc (out, '\n') + else { + call getoutcol (next_output_column) + while (next_output_column < left_margin) { + call outc (out, BLANK) + call getoutcol (next_output_column) + } + } + + case LE: # end LS block + call breakline (out, NJ) + if (nls >= 1) { + left_margin = left_margin - indent[nls] + nls = nls - 1 + } + + default: + call error (1, "do_LS") + } +end + + +# INIT_LS -- Set or clear any LS indentation. + +procedure init_ls() + +include "lroff.com" + +begin + nls = 0 +end diff --git a/pkg/system/help/lroff/getarg.o b/pkg/system/help/lroff/getarg.o Binary files differnew file mode 100644 index 00000000..fcfc8fd9 --- /dev/null +++ b/pkg/system/help/lroff/getarg.o diff --git a/pkg/system/help/lroff/getarg.x b/pkg/system/help/lroff/getarg.x new file mode 100644 index 00000000..b85c5462 --- /dev/null +++ b/pkg/system/help/lroff/getarg.x @@ -0,0 +1,35 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <chars.h> +include "lroff.h" + +.help lgetarg +.nf _________________________________________________________________________ +LGETARG -- Get an integer argument to a directive. If no argument is found, +return the default value. We are called with IP pointing to the start of +the argument field to be searched. Leave IP pointing to the next argument +field. +.endhelp ____________________________________________________________________ + +int procedure lgetarg (input_line, ip, default_value) + +char input_line[ARB] +int ip, default_value +int argument +int ctoi() + +begin + if (ctoi (input_line, ip, argument) == 0) + argument = default_value + + # Eat comma argument delimiter, if multiple arguments. Also eat + # trailing whitespace, in case a string argument follows. + while (input_line[ip] == BLANK) + ip = ip + 1 + if (input_line[ip] == ',') + ip = ip + 1 + while (input_line[ip] == BLANK) + ip = ip + 1 + + return (argument) +end diff --git a/pkg/system/help/lroff/indent.o b/pkg/system/help/lroff/indent.o Binary files differnew file mode 100644 index 00000000..b2f75a10 --- /dev/null +++ b/pkg/system/help/lroff/indent.o diff --git a/pkg/system/help/lroff/indent.x b/pkg/system/help/lroff/indent.x new file mode 100644 index 00000000..6857e315 --- /dev/null +++ b/pkg/system/help/lroff/indent.x @@ -0,0 +1,17 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "lroff.h" + +# INDENT_LEFT_MARGIN -- Execute a relative indent of the left margin. + +procedure indent_left_margin (in, out, number_of_spaces) + +extern in(), out() +int in(), number_of_spaces +include "lroff.com" + +begin + call breakline (out, NJ) + left_margin = max (perm_left_margin, min (right_margin, + left_margin + number_of_spaces)) +end diff --git a/pkg/system/help/lroff/input.o b/pkg/system/help/lroff/input.o Binary files differnew file mode 100644 index 00000000..80ef4865 --- /dev/null +++ b/pkg/system/help/lroff/input.o diff --git a/pkg/system/help/lroff/input.x b/pkg/system/help/lroff/input.x new file mode 100644 index 00000000..908bd81d --- /dev/null +++ b/pkg/system/help/lroff/input.x @@ -0,0 +1,123 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include <chars.h> +include "lroff.h" + +.help input +.nf ___________________________________________________________________________ +INPUT -- Read a line of text into the user supplied input buffer. Convert +any tabs therein to spaces to simplify further processing. If generation +of standout mode control chars is enabled, map "\f[BIR]" sequences into the +appropriate control chars (defined in <chars.h>), otherwise delete any such +sequences found (these control chars are later mapped by HELP, PAGE, LPRINT +etc. into whatever sequence the actual output device requires). Return the +number of PRINTABLE chars in the input line. Control characters are not +counted, but are copied to the output line. The trailing newline is stripped; +Lroff deals mainly with words, not lines. Only printable characters are made +to "stand out", i.e., standout mode is always turned off between words and at +the end of a line. +.endhelp ______________________________________________________________________ + +int procedure input (in, userbuf) + +extern in() +char userbuf[ARB] + +bool standout_mode_in_effect +char ch +int len_inputline, ocol +pointer sp, lbuf, ip, op +int stridx(), in() +errchk salloc, in +include "lroff.com" + +begin + call smark (sp) + call salloc (lbuf, SZ_IBUF, TY_CHAR) + + # Get input line and deal with any tab characters therein. + if (in (in_magic_arg, Memc[lbuf]) == EOF) { + call sfree (sp) + return (EOF) + } + + standout_mode_in_effect = false + len_inputline = 0 + ip = lbuf + op = 1 + ocol = 0 + + # Process the input buffer, converting any "\f?" font escape sequences + # found. Terminate when newline is reached. Delete the newline. + # Expand all tabs. + + for (ch=Memc[ip]; ch != '\n' && ch != EOS; ch=Memc[ip]) { + if (ch == '\\') + if (Memc[ip+1] == 'f' && stridx (Memc[ip+2], "BIR") > 0) { + # Turn standout mode on or off. Can only be turned on + # if "soflag" is YES. + switch (Memc[ip+2]) { + case 'B', 'I': # bold, italic + if (soflag == YES) + standout_mode_enabled = true + case 'R': # roman + if (standout_mode_in_effect) { + userbuf[op] = SO_OFF + op = op + 1 + standout_mode_in_effect = false + } + standout_mode_enabled = false + } + ip = ip + 3 # \f? = 3 + next + } + + # Only make alphanumeric chars "stand out". + + if (IS_ALNUM(ch)) { + len_inputline = len_inputline + 1 + ocol = ocol + 1 + if (standout_mode_enabled && !standout_mode_in_effect) { + userbuf[op] = SO_ON + op = op + 1 + standout_mode_in_effect = true + } + + } else if (ch == '\t') { + repeat { + userbuf[op] = ' ' + op = op + 1 + ocol = ocol + 1 + len_inputline = len_inputline + 1 + } until (ocol > 1 && mod (ocol, TABSIZE) == 0) + ip = ip + 1 + next + + } else { + if (IS_PRINT(ch)) { + len_inputline = len_inputline + 1 + ocol = ocol + 1 + } + if (standout_mode_in_effect) { + userbuf[op] = SO_OFF + op = op + 1 + standout_mode_in_effect = false + } + } + + userbuf[op] = ch + op = op + 1 + ip = ip + 1 + } + + if (standout_mode_in_effect) { + userbuf[op] = SO_OFF + op = op + 1 + standout_mode_in_effect = false + } + userbuf[op] = EOS + + call sfree (sp) + return (len_inputline) +end diff --git a/pkg/system/help/lroff/justify.o b/pkg/system/help/lroff/justify.o Binary files differnew file mode 100644 index 00000000..db814dfb --- /dev/null +++ b/pkg/system/help/lroff/justify.o diff --git a/pkg/system/help/lroff/justify.x b/pkg/system/help/lroff/justify.x new file mode 100644 index 00000000..8085ca6b --- /dev/null +++ b/pkg/system/help/lroff/justify.x @@ -0,0 +1,63 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <chars.h> +include "lroff.h" + +# RIGHT_JUSTIFY -- Right justify the text string argument in LINEBUF on the +# next input line, and write to the output. + +procedure right_justify (in, out, linebuf, ip) + +extern in(), out() +char linebuf[ARB] +int ip +pointer sp, rjbuf +int in(), input() +errchk salloc, breakline, input, rjline +include "lroff.com" + +begin + call smark (sp) + call salloc (rjbuf, SZ_IBUF, TY_CHAR) + + call breakline (out, NJ) + if (input (in, Memc[rjbuf]) != EOF) + call rjline (out, Memc[rjbuf], linebuf[ip]) + + call sfree (sp) +end + + + +# RJLINE -- Right justify a text string on an unfilled input line and +# send it out. + +procedure rjline (out, input_line, rjtext) + +extern out() +char input_line[ARB] # unfilled input line +char rjtext[ARB] # string to be right justified on same line + +int i, nblanks, len_rjtext, next_output_column +int textlen() +errchk outstr, outc, outline +include "lroff.com" + +begin + # Breakline should already have been called by the time we get here. + # Output the input line at the left margin without filling. + + call outstr (out, input_line) + + # Determine the (printable) length of the rjtext string, and space + # over so that it comes out right justified. Always output at least + # one space. Exceed the right margin if necessary. + + call getoutcol (next_output_column) + len_rjtext = textlen (rjtext) + nblanks = max (1, right_margin - (next_output_column + len_rjtext) + 1) + do i = 1, nblanks + call outc (out, BLANK) + + call outline (out, rjtext) +end diff --git a/pkg/system/help/lroff/lroff.com b/pkg/system/help/lroff/lroff.com new file mode 100644 index 00000000..1e64173c --- /dev/null +++ b/pkg/system/help/lroff/lroff.com @@ -0,0 +1,24 @@ +# Common for the Lroff text formatter. + +int right_margin # working margins +int left_margin +int perm_right_margin # permanent margins +int perm_left_margin +int in_magic_arg # magic args for in/out procedures +int out_magic_arg +int soflag # if YES, output standout mode chars +int foflag # if YES, output forms mode chars +int justify # right justify text +int nls # .LS nesting level +int ls_indent # .LS, def number of spaces to indent +int sh_nskip # .SH, def nlines to skip +int ih_nskip # .IH, def nlines to skip +int ih_indent # .IH, def nspaces to indent +int nh_nskip # .NH, def nlines to skip +int nh_level[MAX_NHLEVEL] # .NH, section level numbers +bool standout_mode_enabled # see input() + +common /lrfcom/ right_margin, left_margin, perm_right_margin, + perm_left_margin, in_magic_arg, out_magic_arg, soflag, + foflag, justify, nls, ls_indent, sh_nskip, ih_nskip, ih_indent, + nh_nskip, nh_level, standout_mode_enabled diff --git a/pkg/system/help/lroff/lroff.h b/pkg/system/help/lroff/lroff.h new file mode 100644 index 00000000..5111fcd0 --- /dev/null +++ b/pkg/system/help/lroff/lroff.h @@ -0,0 +1,41 @@ +# Input buffer must allow space for tab expansion and standout mode control +# characters. Word and output buffer dimensions depend on margins. + +define SZ_IBUF (2*SZ_LINE) +define MAX_NLS 20 # nesting level for LS +define MAX_NHLEVEL 10 # max level for numbered sections + +# Default formatter parameters. +define DEF_IHINDENT 4 # .ih indent level +define DEF_LSINDENT 4 # .ls indent level +define DEF_IHNSKIP 2 # .ih number of lines to skip +define DEF_NHNSKIP 2 # .nh number of lines to skip +define DEF_SHNSKIP 2 # .sh number of lines to skip +define DEF_TPNLINES 2 # .tp nlines left on page + +define TABSIZE 8 +define INVISIBLE ($1 < BLANK) + +# Lroff Directive Opcodes. +define FI 1 # enter fill mode +define NF 2 # leave fill mode (nofill) +define JU 3 # enter line justification mode +define NJ 4 # leave line justification mode +define RJ 5 # right justify text on nf,nj line +define SH 6 # section heading +define IH 7 # indented section heading +define NH 8 # numbered section heading +define BR 9 # break line +define CE 10 # center next line +define SP 11 # break, space N spaces on output +define IN 12 # indent +/- N spaces +define LS 13 # begin labelled section +define LE 14 # end labelled section +define BP 15 # break page +define TP 16 # test space left on page +define KS 17 # start floating keep +define KE 18 # end floating keep +define HR 19 # HTML href tag +define HN 20 # HTML name tag +define ENDHELP 21 # end of help block +define HELP 22 # start of help block diff --git a/pkg/system/help/lroff/lroff.hlp b/pkg/system/help/lroff/lroff.hlp new file mode 100644 index 00000000..6607977b --- /dev/null +++ b/pkg/system/help/lroff/lroff.hlp @@ -0,0 +1,258 @@ +.help lroff Nov83 "Online Help Utilities" +.ih +NAME +\fBlroff\fR -- line oriented text formatter +.ih +PURPOSE +\fBLroff\fR is a simple text formatter used by the IRAF on-line Help command, +and other utilities (MANPAGE, LIST), to format text. +\fBLroff\fR style documentation text may be embedded in program source files. +\fBlroff\fR is line oriented, rather than page oriented, +and is implemented as a library procedure rather than as a task. +.ih +USAGE +status = lroff (input, output, left_margin, right_margin) +.ih +PARAMETERS +.ls input +An integer procedure, called by \fBlroff\fR to get lines of input, +which takes the \fBlroff\fR input buffer as an argument, +and which returns EOF upon End of File (like GETLINE). +Each line of input must be terminated by a newline and an EOS +(End Of String marker). +.le +.ls output +A procedure, called by \fBlroff\fR to output formatted lines of text, +which takes the \fBlroff\fR output buffer as an argument ("output (buffer)"). +.le +.ls left_margin +The first column to be filled (>= 1). +.le +.ls right_margin +The last column to be filled. +.le +.ls status +ERR is returned if meaningless margins are specified, or if an unrecoverable +error occurs during processing. +.le +.ih +DESCRIPTION +\fBLroff\fR input may be bracketed by ".help" and ".endhelp" directives in +the actual source file of the program being documented (if intended as input +to the \fBhelp\fR utility), or may be in a separate file. +The input text consists +of a mixture of lines of text and \fBlroff\fR directives. +\fBLroff\fR recognizes only a few directives, +summarized in the "Request Summary" below. Whenever a directive +performs the same function as a UNIX TROFF directive, the name is the same. +Unrecognized directives are ignored, and are not passed on to the output. +Directives must be left justified and preceeded by a period. + +Help text need not be formatted unless desired. Filling and justification +are NOT ENABLED unless a legal directive (other than ".nf") is given on the +line immediately following the ".help" directive. + +While filling, embedded whitespace in text IS significant to \fBlroff\fR, +except at the end of a line. +\fBlroff\fR recognizes no special characters. +Blank lines cause a break, and are passed on to the output (a blank line +is equivalent to ".sp"). +Case is not significant in command directives. +Control characters embedded in text will be passed on to the output. + +Since both whitespace and blank lines are significant, \fBlroff\fR will properly +format ordinary paragraphs of text, and single line section headers, +without need for embedded directives. + +Since the i/o routines used by \fBlroff\fR are parameterized, pagination can be +achieved by having the user supplied OUTPUT procedure count output lines. +Similarly, pagination control directives can be added to the list of +\fBlroff\fR directives, to be intercepted by the user supplied INPUT procedure. +See the Manpage command for an example. + + +DIRECTIVES + +Most of the \fBlroff\fR directives function the same as in the UNIX text +formatters. For the benefit of readers without experience with UNIX, +"filling" means collecting words of text until an output line has been +filled, and "justification" refers to adding extra spaces between words +to cause the output line to be both left and right justified (as in this +paragraph). Filling is disabled with NF, and resumes following a FI. +While filling is disabled, only the control directives FI and RJ will be +recognized. Justification is enabled with JU, and disabled with NJ. +The filling of an output line may be stopped, and the line output, with BR. +SP (or a blank line) does the same thing, outputting one or more blank +lines as well. CE causes the current line to be broken, and outputs the +next line of input, centered. + +The directive ".rj text" breaks the current line, and outputs the next +line of input, unfilled, with "text" right justified on the same line. +RJ is especially useful for numbering equations. The RJ directive is +recognized whether or not filling is in effect. + +SH and IH may be used for section headers. Both cause a break, followed +by a couple blank lines, followed by the next line of input, +left justified on the output line. The left margin is reset to its +initial value. If IH is used, the text following the section header will +be indented one level in from the left margin. +The number of lines of blank lines before the heading, +and the amount of indentation, are optional arguments. +The default values are shown in the request summary below. If values +other than the defaults are desired, they need only be supplied as arguments +once. Succeeding calls will continue to use the new values. + +The IH and LS directives are especially useful in help text (manual pages). +LS with a label string is useful for parameter lists, +as shown in the example below. +LS without a label string is used for relative indenting. +A following LE restores the previous level of indentation. + +The LS directive has the form ".ls [n] [stuff]", where "n" (optional) +is the amount by which the following text is to be indented, +and "stuff" is the (optional) label for the indented text block. +LS causes a break, followed by one blank line, then the label string (if given), +left justified. +If the length of "stuff" is less than N-1 characters, the text +block will start filling on the same line, otherwise on the next line. +The indented text block may contain anything, including additional LS +directives if nesting is desired. A matching LE eventually terminates the +block, restoring the previous level of indentation. + +The LS directive takes the most recent argument as the new default +indentation, allowing the argument to be omitted in subsequent calls. +To keep the current default value from being changed, use a negative +argument. + +.ih +EXAMPLE +.sp +Many examples of the use of the \fBlroff\fR command directives in help text +can be found by browsing about in source listings. +A brief example is included here for convenient reference. +.sp +The ".help" directive, used to mark the beginning +of a block of help text, is used by HELP and MANPAGE rather than \fBlroff\fR. +The (optional) arguments to ".help" are the keyword name of the help +text block, and two strings. +The keyword argument may be a list of the form ".help keyw1, +keyw2, ..., keywn", if more than one keyword is appropriate. +The first keyword in the list is placed in the header of a manual page, +followed by the first string, in parenthesis. The second string, +if given, is centered in the header line. The strings need not be +delimited unless they contain whitespace. +.sp +The \fBlroff\fR-format help text fragment +.sp +.ls +.nf +.help stcopy 2 "string utilities" +.ih +NAME +stcopy -- copy a string. +.ih +PURPOSE +Stcopy is used to copy an EOS delimited character +string. The EOS delimiter MUST be present. +.ih +USAGE +stcopy (from, to, maxchar) +.ih +PARAMETERS +.ls from +The input string. +.le +.ls to +The output string, of length no less than "maxchar" +characters (excluding the EOS). +.le +.ls maxchar +The maximum number of characters to be copied. +Note that "maxchar" does not include the EOS. +Thus, the destination string must contain storage +for at least (maxchar + 1) characters. +.le +.ih +DESCRIPTION +.fi +.sp 2 +.le +would be converted by \fBlroff\fR (as called from Help) into something like +the following. Remember that the margins are runtime arguments to \fBlroff\fR. +Help does not print a header line, or break pages. +.sp 2 +.in 8 +NAME +.in 5 +stcopy -- copy a string. +.in -5 +.sp 2 +PURPOSE +.in 5 +Stcopy is used to copy an EOS delimited character +string. The EOS delimiter MUST be present. +.in -5 +.sp 2 +USAGE +.in 5 +stcopy (from, to, maxchar) +.in -5 +.sp 2 +PARAMETERS +.in 5 +.ls from +The input string. +.le +.ls to +The output string, of length no less than "maxchar" +characters (excluding the EOS). +.le +.ls maxchar +The maximum number of characters to be copied. +Note that "maxchar" does not include the EOS. +Thus, the destination string must contain storage +for at least (maxchar + 1) characters. +.le +.in -5 +.sp 2 +DESCRIPTION +.sp +.ih +SEE ALSO +help + +The reader should note that MANPAGE, which is page oriented, +recognizes the following directives in addition to those recognized +by \fBlroff\fR: BP (break page), and KS, KE (start and end keep). MANPAGE also +omits blank lines at the top of a page. These directives may safely +be included in \fBlroff\fR text, as they will be ignored by \fBlroff\fR if not +intercepted by the procedure calling \fBlroff\fR. + +.ih +REQUEST SUMMARY +.sp +.nf +Request Initial Default Break Meaning + + .fi yes yes Begin filling output lines. + .nf no yes Stop filling output lines. + .ju yes no Right justify output lines. + .nj no no Don't right justify. + .rj text yes Rt justify text on next line. + .sh n n=2 yes Skip n lines, start section. + .ih m n m=2,n=5 yes Like SH, but indent n spaces. + .br yes Stop filling current line. + .ce yes Center following line. + .sp n n=1 yes Space "n" lines. + .in n n=0 n=0 yes Set left margin to "current+n". + .ls n label n=8 yes Begin labeled text block. + .le yes End labeled text block. + +additional directives provided by MANPAGE: + + .bp yes Start a new page of output. + .tp n n=4 yes Break page if < n lines left. + .ks yes Begin saving output. + .ke yes Output saved text all on one page. +.fi +.endhelp diff --git a/pkg/system/help/lroff/lroff.o b/pkg/system/help/lroff/lroff.o Binary files differnew file mode 100644 index 00000000..4151c327 --- /dev/null +++ b/pkg/system/help/lroff/lroff.o diff --git a/pkg/system/help/lroff/lroff.x b/pkg/system/help/lroff/lroff.x new file mode 100644 index 00000000..e9624827 --- /dev/null +++ b/pkg/system/help/lroff/lroff.x @@ -0,0 +1,220 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <chars.h> +include <ctype.h> +include "lroff.h" + +.help lroff +.nf ___________________________________________________________________________ +Source for the LROFF line-oriented text formatter. LROFF is a simple text +formatter patterned after the NROFF formatter of UNIX. LROFF is unusual in +that it is a "numerical" library procedure which does not directly do any +i/o (except for buffer allocation and use of ERROR). + +LROFF -- The main entry point. Lroff reads lines with the input procedure, +performs the format conversion, and writes lines with the output procedure, +both of which are passed as arguments. Conversion proceeds until the .endhelp +directive or EOF is reached. The calling sequences for the input and output +procedures are as follows: + + stat = inproc (inarg, linebuf) + outproc (outarg, linebuf) + +where "inarg" and "outarg" are magic integer arguments which Lroff merely +passes on to the input and output procedures when they are called. + +Other arguments to Lroff include PLM and PRM, the permanent left and right +margins for the output text, and SOFLAG, set to YES if "standout mode" control +chars are permitted in the output text. + +The forms control directives BP, TP, KS, and KE are ignored unless forms mode +is enabled (foflag=YES). If forms control is enabled these directives cause +a breakline followed by output of a special control character forms directive, +used to control the layout of text on a page. When forms mode is in effect +the section header directives also cause output of a TP (test page) directive +before the section. Processing of forms control characters is left to the +program that reads lroff output. +.endhelp ______________________________________________________________________ + +procedure lroff (in, in_arg, out, out_arg, plm, prm, soflag_val, foflag_val) + +extern in() # called to get lines of input text +int in_arg # magic argument for in() +extern out() # called to output formatted lines of text +int out_arg # magic argument for out() +int plm, prm # permanent left and right margins +int soflag_val # output standout mode control chars? +int foflag_val # output form control chars? + +char ctrlstr[2] +pointer sp, ibuf +int ip, command, last_command +int in(), nextcmd(), lgetarg(), input(), nofill() + +errchk input, textout, nofill, rawcopy, skiplines, breakline, right_justify +errchk salloc, new_section, new_indented_section, center_text, init_ls +errchk init_nh, indent_left_margin, do_LS, textout, set_wordbuf, set_outbuf +include "lroff.com" + +define text_ 98 + +begin + call smark (sp) + call salloc (ibuf, SZ_IBUF, TY_CHAR) + + if (plm > prm || plm < 1) + call error (1, "Lroff called with invalid margins") + + # General initialization. Set up the Lroff common. Call the various + # initialization procedures to initialize the directives and to + # set up the word buffer and output buffer, the size of which depends + # on the margins. + + justify = YES + perm_left_margin = plm + perm_right_margin = prm + left_margin = plm + right_margin = prm + last_command = NULL + in_magic_arg = in_arg + out_magic_arg = out_arg + soflag = soflag_val + foflag = foflag_val + standout_mode_enabled = false + + ls_indent = DEF_LSINDENT + ih_indent = DEF_IHINDENT + sh_nskip = DEF_SHNSKIP + nh_nskip = DEF_NHNSKIP + ih_nskip = DEF_IHNSKIP + + call init_ls() + call init_nh() + call set_wordbuf (prm - plm + 2) + call set_outbuf (max (SZ_LINE, 2 * (prm - plm + 1))) + + # If the first line of text is not an Lroff directive, we copy the + # input to the output without modification, except for moving the text + # to the desired left margin, stopping only at EOF or .endhelp. + # If any directive is given, the default mode is justify+fill. + + if (input (in, Memc[ibuf]) == EOF) { + call sfree (sp) + return + } else if (nextcmd (Memc[ibuf], ip) < 0) { + call rawcopy (in, out, Memc[ibuf]) + call sfree (sp) + return + } + + + # The main Lroff interpreter loop. Get input line: if directive, + # execute directive; else call textout() to process a line of text. + # The basic idea is to break the input stream up into words, saving + # these until we have one more than needed to fill the output line. + # The words are then copied into the output line, starting at the left + # margin, adding spaces as needed to right justify the line. Many + # commands cause the "current output line" to be broken, forcing + # whatever has been accumulated out without right justification. + + repeat { + command = nextcmd (Memc[ibuf], ip) + switch (command) { + case FI: + call breakline (out, NJ) + case NF: + call breakline (out, NJ) + if (nofill (in, out, Memc[ibuf]) == ENDHELP) + break + case JU: + justify = YES + case NJ: + justify = NO + case RJ: + call right_justify (in, out, Memc[ibuf], ip) + case SH: + call new_section (in, out, Memc[ibuf], ip) + case IH: + call new_indented_section (in, out, Memc[ibuf], ip) + case NH: + call new_numbered_section (in, out, Memc[ibuf], ip) + case BR: + call breakline (out, NJ) + case CE: + call center_text (in, out, Memc[ibuf], ip) + case SP: + call skiplines (out, lgetarg(Memc[ibuf],ip,1)) + case IN: + call indent_left_margin (in, out, lgetarg(Memc[ibuf],ip,0)) + case LS, LE: + call do_LS (out, Memc[ibuf+ip-1], command, last_command) + + case HR: + # HTML href target of the form ".hr <href> <text>", we skip + # ahead to the <text> and process as a normal line. + while (IS_WHITE(Memc[ibuf+ip])) # skip space + ip = ip + 1 + while (!IS_WHITE(Memc[ibuf+ip])) # skip <href> + ip = ip + 1 + call amovc (Memc[ibuf+ip+1], Memc[ibuf], SZ_IBUF) + ip = 0 + goto text_ + + case HN: + # HTML name target of the form ".hn <name>", ignore. + next + + # The following cases are for forms control. + case BP: + call breakline (out, NJ) + if (foflag == YES) + call outcc (out, FC_BREAKPAGE) + case TP: + call breakline (out, NJ) + if (foflag == YES) { + ctrlstr[1] = FC_TESTPAGE + ctrlstr[2] = lgetarg (Memc[ibuf], ip, DEF_TPNLINES) + ctrlstr[3] = EOS + call out (out_magic_arg, ctrlstr) + } + case KS: + call breakline (out, NJ) + if (foflag == YES) + call outcc (out, FC_STARTKEEP) + case KE: + call breakline (out, NJ) + if (foflag == YES) + call outcc (out, FC_ENDKEEP) + + case ENDHELP: # normal exit point + break + + default: # ordinary line of text +text_ if (Memc[ibuf] == '.') { + # Ignore unrecognized directives. + next + } else { + # Determine if line is blank; skip a line if so, otherwise + # process a normal line of text. + for (ip=0; Memc[ibuf+ip] == BLANK; ip=ip+1) + ; + if (Memc[ibuf+ip] == EOS) + call skiplines (out, 1) + else if (Memc[ibuf] == '\\') + call textout (out, Memc[ibuf+1]) + else + call textout (out, Memc[ibuf]) + } + } + + last_command = command + + } until (input (in, Memc[ibuf]) == EOF) + + +99 call breakline (out, NJ) + call set_wordbuf (0) + call set_outbuf (0) + + call sfree (sp) +end diff --git a/pkg/system/help/lroff/lroff2html.c b/pkg/system/help/lroff/lroff2html.c new file mode 100644 index 00000000..26cf8227 --- /dev/null +++ b/pkg/system/help/lroff/lroff2html.c @@ -0,0 +1,1381 @@ +/* lroff2html.x -- translated by f2c (version 20100827). + You must link the resulting object file with libf2c: + on Microsoft Windows system, link with libf2c.lib; + on Linux or Unix systems, link with .../path/to/libf2c.a -lm + or, if you install libf2c.a in a standard place, with -lf2c -lm + -- in that order, at the end of the command line, as in + cc *.o -lf2c -lm + Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., + + http://www.netlib.org/f2c/libf2c.zip +*/ + +#include "f2c.h" + +/* Common Block Declarations */ + +struct { + doublereal memd[1]; +} mem_; + +#define mem_1 mem_ + +struct { + integer rightn, leftmn, permrn, permln, inmagg, outmag, soflag, foflag, + justiy, nls, lsindt, shnskp, ihnskp, ihindt, nhnskp, nhlevl[10]; + logical standd; +} lrfcom_; + +#define lrfcom_1 lrfcom_ + +struct { + logical xerflg, xerpad[84]; +} xercom_; + +#define xercom_1 xercom_ + +/* Table of constant values */ + +static integer c__2046 = 2046; +static integer c__2 = 2; +static integer c__1023 = 1023; +static integer c__255 = 255; +static integer c__256 = 256; +static integer c__9 = 9; +static integer c__0 = 0; +static integer c__10 = 10; +static integer c__1 = 1; +static logical c_true = TRUE_; +static integer c__3 = 3; + +/* Subroutine */ int lroffl_(in, out, module, parstr, center, lsblok, sectin) +integer *in, *out; +shortint *module, *parstr, *center, *lsblok, *sectin; +{ + /* Initialized data */ + + static shortint st0003[5] = { 60,80,62,10,0 }; + static shortint st0004[7] = { 94,46,104,101,108,112,0 }; + static shortint st0005[8] = { 60,47,80,82,69,62,10,0 }; + static shortint st0006[7] = { 60,80,82,69,62,10,0 }; + static shortint st0007[13] = { 60,47,68,68,62,10,60,47,68,76,62,10,0 }; + static shortint st0008[13] = { 60,47,68,68,62,10,60,47,68,76,62,10,0 }; + static shortint st0009[2] = { 124,0 }; + static shortint st0010[13] = { 60,47,68,68,62,10,60,47,68,76,62,10,0 }; + static shortint st0011[25] = { 60,67,69,78,84,69,82,62,37,115,60,47,67,69, + 78,84,69,82,62,60,66,82,62,10,0 }; + static shortint st0012[6] = { 60,66,82,62,10,0 }; + static shortint st0013[6] = { 60,66,82,62,10,0 }; + static shortint st0014[6] = { 60,66,82,62,10,0 }; + static shortint st0015[13] = { 60,68,76,62,10,60,68,84,62,60,66,62,0 }; + static shortint st0016[22] = { 60,65,32,78,65,77,69,61,34,108,95,37,115, + 34,62,37,115,60,47,65,62,0 }; + static shortint st0017[11] = { 60,47,66,62,60,47,68,84,62,10,0 }; + static shortint st0018[46] = { 60,33,32,83,101,99,61,37,115,32,76,101,118, + 101,108,61,37,100,32,76,97,98,101,108,61,39,37,115,39,32,76,105, + 110,101,61,39,37,115,39,62,10,60,68,68,62,0 }; + static shortint st0019[5] = { 78,111,110,101,0 }; + static shortint st0020[2] = { 32,0 }; + static shortint st0021[13] = { 60,47,68,68,62,10,60,47,68,76,62,10,0 }; + static shortint st0022[21] = { 60,65,32,72,82,69,70,61,34,37,115,34,62,37, + 115,60,47,65,62,10,0 }; + static shortint st0023[19] = { 60,65,32,78,65,77,69,61,34,37,115,34,62,60, + 47,65,62,10,0 }; + static shortint st0024[7] = { 60,80,82,69,62,10,0 }; + static shortint st0025[8] = { 60,47,80,82,69,62,10,0 }; + static shortint st0026[5] = { 39,37,115,39,0 }; + static shortint st0027[7] = { 60,47,85,76,62,10,0 }; + static shortint st0028[22] = { 60,33,32,69,110,100,83,101,99,116,105,111, + 110,58,32,32,32,37,115,62,10,0 }; + static shortint st0029[32] = { 60,72,50,62,60,65,32,78,65,77,69,61,34,115, + 95,37,115,34,62,37,115,60,47,65,62,60,47,72,50,62,10,0 }; + static shortint st0030[35] = { 60,72,50,62,60,65,32,78,65,77,69,61,34,115, + 95,37,115,34,62,37,115,32,37,115,60,47,65,62,60,47,72,50,62,10,0 } + ; + static shortint st0031[24] = { 60,33,32,66,101,103,105,110,83,101,99,116, + 105,111,110,58,32,39,37,115,39,62,10,0 }; + static shortint st0032[6] = { 60,85,76,62,10,0 }; + static shortint st0033[3] = { 37,115,0 }; + static shortint st0034[30] = { 60,47,85,76,62,10,60,33,32,69,110,100,83, + 101,99,116,105,111,110,58,32,32,32,32,37,115,62,10,10,0 }; + static shortint st0035[14] = { 60,33,32,67,111,110,116,101,110,116,115,58, + 32,0 }; + static shortint st0036[4] = { 37,115,32,0 }; + static shortint st0037[5] = { 32,62,10,10,0 }; + static shortint st0038[17] = { 60,47,66,79,68,89,62,10,60,47,72,84,77,76, + 62,10,0 }; + static shortint st0001[24] = { 60,84,73,84,76,69,62,37,115,60,47,84,73,84, + 76,69,62,10,60,85,76,62,10,0 }; + static shortint st0002[2] = { 32,0 }; + + /* System generated locals */ + integer i__1; + + /* Local variables */ + static integer i__, ip, sp, cmd, arg; +#define memb ((logical *)&mem_1) +#define memc ((shortint *)&mem_1) + static integer name__, ibuf; +#define memi ((integer *)&mem_1) + static integer nsec; +#define meml ((integer *)&mem_1) + static integer sw0001, sw0002; +#define memr ((real *)&mem_1) +#define mems ((shortint *)&mem_1) +#define memx ((complex *)&mem_1) + static integer font, sptr; + extern /* Subroutine */ int aclrc_(), pargi_(), sfree_(); + static integer level, unesc; + extern /* Subroutine */ int smark_(); + static integer indend; + extern integer lgetag_(); + extern /* Subroutine */ int lhesce_(); + static logical formad; + extern integer getlie_(), lhfink_(), lhfinn_(); + extern /* Subroutine */ int salloc_(), lhmkne_(); + static integer lastle; + static logical format, quitae, quitah; + extern integer nextcd_(), strmah_(); + static integer lslevl; + extern integer strids_(); + extern /* Subroutine */ int amovki_(), ungete_(), lhprog_(), fprinf_(), + pargsr_(), lhsetl_(), sprinf_(), xffluh_(), zzepro_(); + extern integer xstrln_(); + extern /* Subroutine */ int xstrcy_(); + + /* Parameter adjustments */ + --sectin; + --lsblok; + --center; + --parstr; + --module; + + /* Function Body */ + smark_(&sp); + salloc_(&ibuf, &c__2046, &c__2); + salloc_(&unesc, &c__2046, &c__2); + salloc_(&name__, &c__1023, &c__2); + salloc_(&level, &c__255, &c__2); + salloc_(&sptr, &c__256, &c__9); + aclrc_(&memc[ibuf - 1], &c__2046); + aclrc_(&memc[name__ - 1], &c__1023); + aclrc_(&memc[unesc - 1], &c__2046); + aclrc_(&memc[level - 1], &c__255); + lastle = 3; + font = 1; + indend = 1; + nsec = 0; + lslevl = 0; + format = TRUE_; + quitae = FALSE_; + quitah = FALSE_; + formad = FALSE_; + amovki_(&c__0, lrfcom_1.nhlevl, &c__10); +L110: + if (! (getlie_(in, &memc[ibuf - 1]) == -2)) { + goto L120; + } + goto L98; +L120: + ip = 1; +L130: + if (! (memc[ibuf + ip - 2] == 32 || memc[ibuf + ip - 2] == 9)) { + goto L132; + } +/* L131: */ + ++ip; + goto L130; +L132: +/* L111: */ + if (! (memc[ibuf + ip - 2] != 10)) { + goto L110; + } +/* L112: */ + ungete_(in, &memc[ibuf - 1]); + if (! (memc[ibuf - 1] == 46)) { + goto L140; + } + formad = TRUE_; +L140: + if (! (sectin[1] != 0)) { + goto L150; + } + if (! (lhfinn_(in, &formad, §in[1]) == -2)) { + goto L160; + } + goto L98; +L160: + goto L151; +L150: + if (! (lsblok[1] != 0)) { + goto L170; + } + if (! (lhfink_(in, &formad, &lsblok[1]) == -2)) { + goto L180; + } + goto L98; +L180: + quitae = TRUE_; +L170: +L151: + lhprog_(out, &module[1], &parstr[1], ¢er[1]); + fprinf_(out, st0001); + if (! (lsblok[1] != 0)) { + goto L190; + } + pargsr_(&lsblok[1]); + goto L191; +L190: + if (! (sectin[1] != 0)) { + goto L200; + } + pargsr_(§in[1]); + goto L201; +L200: + if (! (module[1] != 0)) { + goto L210; + } + pargsr_(&module[1]); + goto L211; +L210: + pargsr_(st0002); +L211: +L201: +L191: +L220: + if (! (getlie_(in, &memc[ibuf - 1]) != -2)) { + goto L221; + } + memc[ibuf + xstrln_(&memc[ibuf - 1]) - 2] = 0; + xstrcy_(&memc[ibuf - 1], &memc[unesc - 1], &c__1023); + lhesce_(&memc[ibuf - 1], &font, &format, &c__0, &c__1023); + sw0001 = memc[ibuf - 1]; + goto L230; +L240: + fprinf_(out, st0003); + goto L231; +L250: + if (! (strmah_(&memc[ibuf - 1], st0004) > 0)) { + goto L260; + } + goto L220; +L260: + ip = 1; + lastle = 3; + cmd = nextcd_(&memc[ibuf - 1], &ip); +L270: + if (! (memc[ibuf + ip - 1] == 32 || memc[ibuf + ip - 1] == 9)) { + goto L271; + } + ++ip; + goto L270; +L271: + sw0002 = cmd; + goto L280; +L290: + fprinf_(out, st0005); + format = TRUE_; + goto L281; +L300: + fprinf_(out, st0006); + format = FALSE_; + goto L281; +L310: + goto L220; +L320: + goto L220; +L330: + goto L220; +L340: + if (! (lslevl > 0)) { + goto L350; + } + fprinf_(out, st0007); + lslevl = 0; +L350: + lastle = 1; + memc[level - 1] = 0; + goto L220; +L360: + if (! (lslevl > 0)) { + goto L370; + } + fprinf_(out, st0008); + lslevl = 0; +L370: + lastle = 1; + memc[level - 1] = 0; + if (! quitah) { + goto L380; + } + if (! (strids_(st0009, §in[1]) > 0)) { + goto L390; + } + quitah = FALSE_; + ungete_(in, &memc[ibuf - 1]); + if (! (lhfinn_(in, &formad, §in[1]) == -2)) { + goto L400; + } + goto L221; +L400: + goto L391; +L390: + goto L221; +L391: +L380: + goto L220; +L410: + if (! (lslevl > 0)) { + goto L420; + } + fprinf_(out, st0010); + lslevl = 0; +L420: + i__1 = lgetag_(&memc[ibuf - 1], &ip, &c__1); + lhsetl_(&i__1, &memc[level - 1]); + lastle = 1; + goto L220; +L430: + if (! (getlie_(in, &memc[ibuf - 1]) == -2)) { + goto L440; + } + goto L221; +L440: + lhesce_(&memc[ibuf - 1], &font, &c_true, &c__0, &c__1023); + fprinf_(out, st0011); + pargsr_(&memc[ibuf - 1]); +/* L441: */ + goto L281; +L450: + fprinf_(out, st0012); + goto L281; +L460: + arg = lgetag_(&memc[ibuf - 1], &ip, &c__1); + fprinf_(out, st0013); + i__ = 1; +L470: + if (! (i__ < arg)) { + goto L472; + } + fprinf_(out, st0014); +/* L471: */ + ++i__; + goto L470; +L472: + goto L281; +L480: + goto L220; +L490: + arg = lgetag_(&memc[ibuf - 1], &ip, &c__0); + if (! (arg == 0)) { + goto L500; + } + ip = 5; +L500: + xstrcy_(&memc[ibuf + ip - 2], &memc[name__ - 1], &c__1023); + i__ = 0; +L510: + if (! (memc[name__ + i__ - 1] >= 65 && memc[name__ + i__ - 1] <= 90 || + memc[name__ + i__ - 1] >= 97 && memc[name__ + i__ - 1] <= 122 || + memc[name__ + i__ - 1] >= 48 && memc[name__ + i__ - 1] <= 57 || + memc[name__ + i__ - 1] == 95)) { + goto L512; + } +/* L511: */ + ++i__; + goto L510; +L512: + memc[name__ + i__ - 1] = 0; + memc[ibuf + ip + xstrln_(&memc[ibuf + ip - 1]) - 2] = 0; + fprinf_(out, st0015); + fprinf_(out, st0016); + pargsr_(&memc[name__ - 1]); + pargsr_(&memc[ibuf + ip - 2]); + fprinf_(out, st0017); + lhesce_(&memc[unesc + ip - 2], &font, &c_true, &c__1, &c__1023); + memc[unesc + xstrln_(&memc[unesc - 1]) - 2] = 0; + fprinf_(out, st0018); + if (! (nsec > 0)) { + goto L520; + } + pargsr_(&memc[memi[sptr + nsec - 2] - 1]); + goto L521; +L520: + pargsr_(st0019); +L521: + pargi_(&lslevl); + pargsr_(&memc[name__ - 1]); + if (! (memc[unesc + ip - 2] == 10)) { + goto L530; + } + pargsr_(st0020); + goto L531; +L530: + pargsr_(&memc[unesc + ip - 2]); +L531: + ++lslevl; + goto L281; +L540: + fprinf_(out, st0021); + --lslevl; + if (! quitae) { + goto L550; + } + goto L221; +L550: + goto L281; +L560: + memc[ibuf + ip + xstrln_(&memc[ibuf + ip - 1]) - 2] = 0; + i__ = 0; +L570: + if (memc[ibuf + ip - 1] == 32 || memc[ibuf + ip - 1] == 9) { + goto L572; + } + memc[name__ + i__ - 1] = memc[ibuf + ip - 1]; + ++i__; +/* L571: */ + ++ip; + goto L570; +L572: + memc[name__ + i__ - 1] = 0; + fprinf_(out, st0022); + pargsr_(&memc[name__ - 1]); + pargsr_(&memc[ibuf + ip]); + goto L281; +L580: + memc[ibuf + ip + xstrln_(&memc[ibuf + ip - 1]) - 2] = 0; + fprinf_(out, st0023); + pargsr_(&memc[ibuf + ip - 1]); + goto L281; +L590: + goto L220; +L600: + goto L220; +L610: + fprinf_(out, st0024); + format = FALSE_; + goto L281; +L620: + fprinf_(out, st0025); + format = TRUE_; + goto L281; +L630: + goto L221; +L280: + if (sw0002 < 1 || sw0002 > 21) { + goto L281; + } + switch ((int)sw0002) { + case 1: goto L290; + case 2: goto L300; + case 3: goto L310; + case 4: goto L320; + case 5: goto L330; + case 6: goto L340; + case 7: goto L360; + case 8: goto L410; + case 9: goto L450; + case 10: goto L430; + case 11: goto L460; + case 12: goto L480; + case 13: goto L490; + case 14: goto L540; + case 15: goto L590; + case 16: goto L600; + case 17: goto L610; + case 18: goto L620; + case 19: goto L560; + case 20: goto L580; + case 21: goto L630; + } +L281: + goto L231; +L640: + if (! (lastle == 1)) { + goto L650; + } + salloc_(&memi[sptr + nsec - 1], &c__1023, &c__2); + aclrc_(&memc[memi[sptr + nsec - 1] - 1], &c__1023); + memc[ibuf + xstrln_(&memc[ibuf - 1]) - 2] = 0; + sprinf_(&memc[memi[sptr + nsec - 1] - 1], &c__1023, st0026); + pargsr_(&memc[ibuf - 1]); + if (! (indend == 1)) { + goto L660; + } + fprinf_(out, st0027); +L660: + if (! (nsec > 0)) { + goto L670; + } + fprinf_(out, st0028); + pargsr_(&memc[memi[sptr + nsec - 2] - 1]); +L670: + lhmkne_(&memc[ibuf - 1], &memc[name__ - 1]); + if (! (memc[level - 1] == 0)) { + goto L680; + } + fprinf_(out, st0029); + pargsr_(&memc[name__ - 1]); + pargsr_(&memc[ibuf - 1]); + goto L681; +L680: + fprinf_(out, st0030); + pargsr_(&memc[name__ - 1]); + pargsr_(&memc[level - 1]); + pargsr_(&memc[ibuf - 1]); + memc[level - 1] = 0; +L681: + fprinf_(out, st0031); + pargsr_(&memc[ibuf - 1]); + if (! (indend == 1)) { + goto L690; + } + fprinf_(out, st0032); +L690: + lastle = 2; + ++nsec; + if (! (sectin[1] != 0)) { + goto L700; + } + quitah = TRUE_; +L700: + goto L651; +L650: +/* L99: */ + fprinf_(out, st0033); + pargsr_(&memc[ibuf - 1]); + lastle = 3; +L651: + goto L231; +L230: + if (sw0001 == 10) { + goto L240; + } + if (sw0001 == 46) { + goto L250; + } + goto L640; +L231: + aclrc_(&memc[ibuf - 1], &c__2046); + aclrc_(&memc[unesc - 1], &c__2046); + aclrc_(&memc[name__ - 1], &c__1023); + goto L220; +L221: + if (! (nsec > 0)) { + goto L710; + } + fprinf_(out, st0034); + pargsr_(&memc[memi[sptr + nsec - 2] - 1]); +L710: + fprinf_(out, st0035); + i__ = 0; +L720: + if (! (i__ < nsec)) { + goto L722; + } + fprinf_(out, st0036); + pargsr_(&memc[memi[sptr + i__ - 1] - 1]); +/* L721: */ + ++i__; + goto L720; +L722: + fprinf_(out, st0037); + fprinf_(out, st0038); + xffluh_(out); +L98: + sfree_(&sp); +/* L100: */ + zzepro_(); + return 0; +} /* lroffl_ */ + +#undef memx +#undef mems +#undef memr +#undef meml +#undef memi +#undef memc +#undef memb + + +/* Subroutine */ int lhprog_(fd, mod, date, title) +integer *fd; +shortint *mod, *date, *title; +{ + /* Initialized data */ + + static shortint st0001[15] = { 60,72,84,77,76,62,10,60,66,79,68,89,62,10, + 0 }; + static shortint st0002[36] = { 60,84,65,66,76,69,32,87,73,68,84,72,61,34, + 49,48,48,37,37,34,32,66,79,82,68,69,82,61,48,62,60,84,82,62,10,0 } + ; + static shortint st0003[30] = { 60,84,68,32,65,76,73,71,78,61,76,69,70,84, + 62,60,70,79,78,84,32,83,73,90,69,61,52,62,10,0 }; + static shortint st0004[10] = { 60,66,62,37,115,60,47,66,62,0 }; + static shortint st0005[15] = { 60,66,62,37,115,32,40,37,115,41,60,47,66, + 62,0 }; + static shortint st0006[14] = { 60,47,70,79,78,84,62,60,47,84,68,62,10,0 }; + static shortint st0007[32] = { 60,84,68,32,65,76,73,71,78,61,67,69,78,84, + 69,82,62,60,70,79,78,84,32,83,73,90,69,61,52,62,10,0 }; + static shortint st0008[11] = { 60,66,62,37,115,60,47,66,62,10,0 }; + static shortint st0009[14] = { 60,47,70,79,78,84,62,60,47,84,68,62,10,0 }; + static shortint st0010[31] = { 60,84,68,32,65,76,73,71,78,61,82,73,71,72, + 84,62,60,70,79,78,84,32,83,73,90,69,61,52,62,10,0 }; + static shortint st0011[10] = { 60,66,62,37,115,60,47,66,62,0 }; + static shortint st0012[15] = { 60,66,62,37,115,32,40,37,115,41,60,47,66, + 62,0 }; + static shortint st0013[14] = { 60,47,70,79,78,84,62,60,47,84,68,62,10,0 }; + static shortint st0014[18] = { 60,47,84,82,62,60,47,84,65,66,76,69,62,60, + 80,62,10,0 }; + + extern /* Subroutine */ int fprinf_(), pargsr_(), zzepro_(); + + /* Parameter adjustments */ + --title; + --date; + --mod; + + /* Function Body */ + fprinf_(fd, st0001); + if (! (date[1] == 0 && title[1] == 0)) { + goto L110; + } + goto L100; +L110: + fprinf_(fd, st0002); + fprinf_(fd, st0003); + if (! (date[1] == 0)) { + goto L120; + } + fprinf_(fd, st0004); + pargsr_(&mod[1]); + goto L121; +L120: + fprinf_(fd, st0005); + pargsr_(&mod[1]); + pargsr_(&date[1]); +L121: + fprinf_(fd, st0006); + if (! (title[1] != 0)) { + goto L130; + } + fprinf_(fd, st0007); + fprinf_(fd, st0008); + pargsr_(&title[1]); + fprinf_(fd, st0009); +L130: + fprinf_(fd, st0010); + if (! (date[1] == 0)) { + goto L140; + } + fprinf_(fd, st0011); + pargsr_(&mod[1]); + goto L141; +L140: + fprinf_(fd, st0012); + pargsr_(&mod[1]); + pargsr_(&date[1]); +L141: + fprinf_(fd, st0013); + fprinf_(fd, st0014); +L100: + zzepro_(); + return 0; +} /* lhprog_ */ + +/* Subroutine */ int lhesce_(str, font, format, speciy, maxch) +shortint *str; +integer *font; +logical *format; +integer *speciy, *maxch; +{ + /* Initialized data */ + + static shortint st0013[5] = { 60,47,66,62,0 }; + static shortint st0014[4] = { 60,73,62,0 }; + static shortint st0015[5] = { 60,47,66,62,0 }; + static shortint st0016[5] = { 60,47,73,62,0 }; + static shortint st0017[5] = { 60,47,66,62,0 }; + static shortint st0018[5] = { 60,47,73,62,0 }; + static shortint st0019[5] = { 60,66,82,62,0 }; + static shortint st0020[3] = { 10,0,0 }; + static shortint st0001[4] = { 60,62,38,0 }; + static shortint st0002[5] = { 38,108,116,59,0 }; + static shortint st0003[5] = { 38,103,116,59,0 }; + static shortint st0004[6] = { 38,97,109,112,59,0 }; + static shortint st0005[5] = { 60,84,84,62,0 }; + static shortint st0006[6] = { 60,47,84,84,62,0 }; + static shortint st0007[5] = { 60,84,84,62,0 }; + static shortint st0008[6] = { 60,47,84,84,62,0 }; + static shortint st0009[7] = { 60,47,84,84,62,34,0 }; + static shortint st0010[6] = { 34,60,84,84,62,0 }; + static shortint st0011[5] = { 60,47,73,62,0 }; + static shortint st0012[4] = { 60,66,62,0 }; + + /* Local variables */ + static integer i__, ip, sp, buf; +#define memb ((logical *)&mem_1) +#define memc ((shortint *)&mem_1) +#define memi ((integer *)&mem_1) +#define meml ((integer *)&mem_1) + static integer sw0001; +#define memr ((real *)&mem_1) +#define mems ((shortint *)&mem_1) +#define memx ((complex *)&mem_1) + extern /* Subroutine */ int aclrc_(), sfree_(), amovc_(), smark_(), + salloc_(); + static integer keywod; + extern integer gstrcy_(), stridx_(); + extern /* Subroutine */ int zzepro_(); + + /* Parameter adjustments */ + --str; + + /* Function Body */ + smark_(&sp); + salloc_(&buf, maxch, &c__2); + salloc_(&keywod, maxch, &c__2); + aclrc_(&memc[buf - 1], maxch); + aclrc_(&memc[keywod - 1], maxch); + ip = buf; + i__ = 1; +L110: + if (! (str[i__] != 0 && i__ <= *maxch)) { + goto L112; + } + if (! (*speciy == 1 && stridx_(&str[i__], st0001) == 0)) { + goto L120; + } + goto L90; +L120: + sw0001 = str[i__]; + goto L130; +L140: + ip += gstrcy_(st0002, &memc[ip - 1], &c__1023); + goto L131; +L150: + ip += gstrcy_(st0003, &memc[ip - 1], &c__1023); + goto L131; +L160: + ip += gstrcy_(st0004, &memc[ip - 1], &c__1023); + goto L131; +L170: + if (! (str[i__ + 2] == 39)) { + goto L180; + } + ip += gstrcy_(st0005, &memc[ip - 1], &c__1023); + ip += gstrcy_(&str[i__], &memc[ip - 1], &c__3); + ip += gstrcy_(st0006, &memc[ip - 1], &c__1023); + i__ += 2; + goto L181; +L180: + goto L90; +L181: + goto L131; +L190: + if (! (str[i__ + 2] == 96 || str[i__ + 2] == 39)) { + goto L200; + } + ip += gstrcy_(st0007, &memc[ip - 1], &c__1023); + ip += gstrcy_(&str[i__], &memc[ip - 1], &c__3); + ip += gstrcy_(st0008, &memc[ip - 1], &c__1023); + i__ += 2; + goto L201; +L200: + goto L90; +L201: + goto L131; +L210: + if (! (*format && str[i__ + 1] != 47 && str[i__ + 2] != 47)) { + goto L220; + } + if (! (*font == 5)) { + goto L230; + } + ip += gstrcy_(st0009, &memc[ip - 1], &c__1023); + *font = 1; + goto L231; +L230: + if (! (*font == 1)) { + goto L240; + } + ip += gstrcy_(st0010, &memc[ip - 1], &c__1023); + *font = 5; + goto L241; +L240: + goto L90; +L241: +L231: + goto L221; +L220: + goto L90; +L221: + goto L131; +L250: + if (! (str[i__ + 1] == 102)) { + goto L260; + } + if (! (str[i__ + 2] == 66)) { + goto L270; + } + if (! (*font == 3)) { + goto L280; + } + goto L111; +L280: + if (! (*font == 2)) { + goto L290; + } + ip += gstrcy_(st0011, &memc[ip - 1], &c__1023); +L290: + ip += gstrcy_(st0012, &memc[ip - 1], &c__1023); + *font = 3; + goto L271; +L270: + if (! (str[i__ + 2] == 73)) { + goto L300; + } + if (! (*font == 2)) { + goto L310; + } + goto L111; +L310: + if (! (*font == 3)) { + goto L320; + } + ip += gstrcy_(st0013, &memc[ip - 1], &c__1023); +L320: + ip += gstrcy_(st0014, &memc[ip - 1], &c__1023); + *font = 2; + goto L301; +L300: + if (! (str[i__ + 2] == 82)) { + goto L330; + } + if (! (*font == 3)) { + goto L340; + } + ip += gstrcy_(st0015, &memc[ip - 1], &c__1023); + goto L341; +L340: + if (! (*font == 2)) { + goto L350; + } + ip += gstrcy_(st0016, &memc[ip - 1], &c__1023); +L350: +L341: + *font = 1; + goto L331; +L330: + if (! (str[i__ + 2] == 80)) { + goto L360; + } + if (! (*font == 3)) { + goto L370; + } + ip += gstrcy_(st0017, &memc[ip - 1], &c__1023); + goto L371; +L370: + if (! (*font == 2)) { + goto L380; + } + ip += gstrcy_(st0018, &memc[ip - 1], &c__1023); +L380: +L371: + *font = 1; +L360: +L331: +L301: +L271: + i__ += 2; + goto L261; +L260: + if (! (str[i__ + 1] == 10 || str[i__ + 1] == 0)) { + goto L390; + } + memc[ip - 1] = str[i__]; + ++ip; + ++i__; + ip += gstrcy_(st0019, &memc[ip - 1], &c__1023); + goto L391; +L390: + goto L90; +L391: +L261: + goto L131; +L400: +L90: + memc[ip - 1] = str[i__]; + ++ip; + goto L131; +L130: + if (sw0001 == 34) { + goto L210; + } + if (sw0001 == 38) { + goto L160; + } + if (sw0001 == 39) { + goto L170; + } + if (sw0001 == 60) { + goto L140; + } + if (sw0001 == 62) { + goto L150; + } + if (sw0001 == 92) { + goto L250; + } + if (sw0001 == 96) { + goto L190; + } + goto L400; +L131: +L111: + ++i__; + goto L110; +L112: + ip += gstrcy_(st0020, &memc[ip - 1], &c__1023); + amovc_(&memc[buf - 1], &str[1], maxch); + sfree_(&sp); +/* L100: */ + zzepro_(); + return 0; +} /* lhesce_ */ + +#undef memx +#undef mems +#undef memr +#undef meml +#undef memi +#undef memc +#undef memb + + +/* Subroutine */ int lhsetl_(n, level) +integer *n; +shortint *level; +{ + /* Initialized data */ + + static shortint st0001[4] = { 37,100,46,0 }; + + /* System generated locals */ + integer i__1; + + /* Local variables */ + static integer i__; + extern /* Subroutine */ int pargi_(), amovki_(), sprinf_(), zzepro_(); + extern integer xstrln_(); + + /* Parameter adjustments */ + --level; + + /* Function Body */ + ++lrfcom_1.nhlevl[(60 + (0 + (*n - 1 << 2)) - 60) / 4]; + i__1 = 10 - *n; + amovki_(&c__0, &lrfcom_1.nhlevl[*n], &i__1); + level[1] = 0; + i__1 = *n; + for (i__ = 1; i__ <= i__1; ++i__) { + sprinf_(&level[xstrln_(&level[1]) + 1], &c__2046, st0001); + pargi_(&lrfcom_1.nhlevl[i__ - 1]); +/* L110: */ + } +/* L111: */ + if (! (*n > 1 && level[xstrln_(&level[1])] == 46)) { + goto L120; + } + level[xstrln_(&level[1])] = 0; +L120: +/* L100: */ + zzepro_(); + return 0; +} /* lhsetl_ */ + +integer lhfink_(fd, formad, param) +integer *fd; +logical *formad; +shortint *param; +{ + /* Initialized data */ + + static shortint st0001[5] = { 123,37,115,125,0 }; + static shortint st0002[7] = { 94,46,123,108,115,125,0 }; + static shortint st0003[7] = { 94,35,123,37,115,125,0 }; + + /* System generated locals */ + integer ret_val; + + /* Local variables */ + static integer sp, len; +#define memb ((logical *)&mem_1) +#define memc ((shortint *)&mem_1) +#define memi ((integer *)&mem_1) + static integer lbuf; +#define meml ((integer *)&mem_1) +#define memr ((real *)&mem_1) +#define mems ((shortint *)&mem_1) +#define memx ((complex *)&mem_1) + extern /* Subroutine */ int sfree_(), smark_(); + static logical matchd; + extern integer getlie_(); + extern /* Subroutine */ int salloc_(), ungete_(); + static integer patten; + extern integer strmah_(); + extern /* Subroutine */ int pargsr_(), sprinf_(), zzepro_(); + extern integer xstrln_(); + + /* Parameter adjustments */ + --param; + + /* Function Body */ + smark_(&sp); + salloc_(&patten, &c__255, &c__2); + salloc_(&lbuf, &c__1023, &c__2); + matchd = FALSE_; + if (! (getlie_(fd, &memc[lbuf - 1]) == -2) && ! xercom_1.xerflg) { + goto L110; + } + if (xercom_1.xerflg) { + goto L100; + } + goto L90; +L110: + if (! (*formad)) { + goto L120; + } + sprinf_(&memc[patten - 1], &c__255, st0001); + pargsr_(¶m[1]); +L130: + if (! (strmah_(&memc[lbuf - 1], st0002) > 0)) { + goto L140; + } + if (! (strmah_(&memc[lbuf - 1], &memc[patten - 1]) > 0)) { + goto L150; + } + matchd = TRUE_; + goto L132; +L150: +L140: +/* L131: */ + if (! (getlie_(fd, &memc[lbuf - 1]) == -2) && ! xercom_1.xerflg) { + goto L130; + } + if (xercom_1.xerflg) { + goto L100; + } +L132: + goto L121; +L120: + sprinf_(&memc[patten - 1], &c__255, st0003); + pargsr_(¶m[1]); +L160: + if (! (strmah_(&memc[lbuf - 1], &memc[patten - 1]) > 0)) { + goto L170; + } + matchd = TRUE_; + goto L162; +L170: +/* L161: */ + if (! (getlie_(fd, &memc[lbuf - 1]) == -2) && ! xercom_1.xerflg) { + goto L160; + } + if (xercom_1.xerflg) { + goto L100; + } +L162: +L121: + ungete_(fd, &memc[lbuf - 1]); +L90: + len = xstrln_(&memc[lbuf - 1]); + sfree_(&sp); + if (! matchd) { + goto L180; + } + ret_val = len; + goto L100; +L180: + ret_val = -2; + goto L100; +/* L181: */ +L100: + zzepro_(); + return ret_val; +} /* lhfink_ */ + +#undef memx +#undef mems +#undef memr +#undef meml +#undef memi +#undef memc +#undef memb + + +integer lhfinn_(fd, formad, sectis) +integer *fd; +logical *formad; +shortint *sectis; +{ + /* Initialized data */ + + static shortint st0001[7] = { 94,46,123,105,104,125,0 }; + static shortint st0002[5] = { 46,105,104,10,0 }; + + /* System generated locals */ + integer ret_val, i__1, i__2; + + /* Local variables */ + static integer ip, op, sp; +#define memb ((logical *)&mem_1) +#define memc ((shortint *)&mem_1) +#define memi ((integer *)&mem_1) + static shortint lbuf[1024]; +#define meml ((integer *)&mem_1) + static integer sw0001; +#define memr ((real *)&mem_1) +#define mems ((shortint *)&mem_1) + static integer npat; +#define memx ((complex *)&mem_1) + extern /* Subroutine */ int sfree_(), smark_(); + static logical matchd; + extern integer getlie_(); + extern logical lhmath_(); + static integer patoff[10]; + extern /* Subroutine */ int salloc_(); + static integer patbuf; + extern /* Subroutine */ int ungete_(); + extern integer strmah_(); + extern /* Subroutine */ int zzepro_(); + + /* Parameter adjustments */ + --sectis; + + /* Function Body */ + smark_(&sp); + salloc_(&patbuf, &c__1023, &c__2); + npat = 1; + op = patbuf; + patoff[0] = op; + if (! (getlie_(fd, lbuf) == -2) && ! xercom_1.xerflg) { + goto L110; + } + if (xercom_1.xerflg) { + goto L100; + } + goto L91; +L110: + ip = 1; +L120: + if (! (sectis[ip] != 0)) { + goto L122; + } + sw0001 = sectis[ip]; + goto L130; +L140: + memc[op - 1] = 0; + ++op; +/* Computing MIN */ + i__1 = 10, i__2 = npat + 1; + npat = min(i__1,i__2); + patoff[npat - 1] = op; + goto L131; +L150: + memc[op - 1] = sectis[ip]; + ++op; + goto L131; +L130: + if (sw0001 == 124) { + goto L140; + } + goto L150; +L131: +/* L121: */ + ++ip; + goto L120; +L122: + memc[op - 1] = 0; + matchd = FALSE_; + if (! (*formad)) { + goto L160; + } +L170: + if (! (strmah_(lbuf, st0001) > 0)) { + goto L180; + } + if (! (getlie_(fd, lbuf) != -2) && ! xercom_1.xerflg) { + goto L190; + } + if (xercom_1.xerflg) { + goto L100; + } + matchd = lhmath_(lbuf, patoff, &npat); + if (! matchd) { + goto L200; + } + goto L172; +L200: +L190: +L180: +/* L171: */ + if (! (getlie_(fd, lbuf) == -2) && ! xercom_1.xerflg) { + goto L170; + } + if (xercom_1.xerflg) { + goto L100; + } +L172: + ungete_(fd, lbuf); + ungete_(fd, st0002); + goto L161; +L160: +L210: + matchd = lhmath_(lbuf, patoff, &npat); + if (! matchd) { + goto L220; + } + goto L212; +L220: +/* L211: */ + if (! (getlie_(fd, lbuf) == -2) && ! xercom_1.xerflg) { + goto L210; + } + if (xercom_1.xerflg) { + goto L100; + } +L212: + ungete_(fd, lbuf); +L161: +L91: + sfree_(&sp); + if (! matchd) { + goto L230; + } + ret_val = 0; + goto L100; +L230: + ret_val = -2; + goto L100; +/* L231: */ +L100: + zzepro_(); + return ret_val; +} /* lhfinn_ */ + +#undef memx +#undef mems +#undef memr +#undef meml +#undef memi +#undef memc +#undef memb + + +logical lhmath_(lbuf, patoff, npat) +shortint *lbuf; +integer *patoff, *npat; +{ + /* Initialized data */ + + static shortint st0001[6] = { 94,123,37,115,125,0 }; + + /* System generated locals */ + logical ret_val; + + /* Local variables */ + static integer sp, pat; +#define memb ((logical *)&mem_1) +#define memc ((shortint *)&mem_1) +#define memi ((integer *)&mem_1) +#define meml ((integer *)&mem_1) +#define memr ((real *)&mem_1) +#define mems ((shortint *)&mem_1) +#define memx ((complex *)&mem_1) + extern /* Subroutine */ int sfree_(), smark_(), salloc_(); + static integer patten; + extern integer strmah_(); + extern /* Subroutine */ int pargsr_(), sprinf_(), zzepro_(); + + /* Parameter adjustments */ + --lbuf; + --patoff; + + /* Function Body */ + smark_(&sp); + salloc_(&patten, &c__255, &c__2); + pat = 1; +L110: + if (! (pat <= *npat)) { + goto L112; + } + sprinf_(&memc[patten - 1], &c__255, st0001); + pargsr_(&memc[patoff[pat] - 1]); + if (! (strmah_(&lbuf[1], &memc[patten - 1]) > 0)) { + goto L120; + } + sfree_(&sp); + ret_val = TRUE_; + goto L100; +L120: +/* L111: */ + ++pat; + goto L110; +L112: + sfree_(&sp); + ret_val = FALSE_; + goto L100; +L100: + zzepro_(); + return ret_val; +} /* lhmath_ */ + +#undef memx +#undef mems +#undef memr +#undef meml +#undef memi +#undef memc +#undef memb + + +/* Subroutine */ int lhmkne_(instr, outstr) +shortint *instr, *outstr; +{ + static integer i__; + extern /* Subroutine */ int zzepro_(), xstrcy_(), strlwr_(); + + /* Parameter adjustments */ + --outstr; + --instr; + + /* Function Body */ + xstrcy_(&instr[1], &outstr[1], &c__1023); + strlwr_(&outstr[1]); + i__ = 1; +L110: + if (! (i__ < 1023)) { + goto L112; + } + if (! (outstr[i__] == 0 || outstr[i__] == 10)) { + goto L120; + } + goto L112; +L120: + if (outstr[i__] >= 65 && outstr[i__] <= 90 || outstr[i__] >= 97 && outstr[ + i__] <= 122 || outstr[i__] >= 48 && outstr[i__] <= 57) { + goto L130; + } + outstr[i__] = 95; +L130: +/* L121: */ +/* L111: */ + ++i__; + goto L110; +L112: +/* L100: */ + zzepro_(); + return 0; +} /* lhmkne_ */ + diff --git a/pkg/system/help/lroff/lroff2html.x b/pkg/system/help/lroff/lroff2html.x new file mode 100644 index 00000000..1e3815ae --- /dev/null +++ b/pkg/system/help/lroff/lroff2html.x @@ -0,0 +1,781 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include "lroff.h" + +define DIRECTIVE 1 # processing codes +define NAME 2 +define TEXT 3 + +define F_ROMAN 1 # font changes +define F_ITALIC 2 +define F_BOLD 3 +define F_PREVIOUS 4 +define F_TELETYPE 5 # HTML-specific font + +define SPTR Memi[$1+$2] +define SECTION Memc[SPTR($1,$2)] +define MAX_SECTIONS 256 + + +# LROFF2HTML -- Convert LROFF text to HTML. By default we process the +# entire file however we allow for the printing of only a particular section +# or labelled text block to be compatible with the HELP task options. +# If a section name is given that section will be printed and and .ls +# block request will be ignored. + +procedure lroff2html (in, out, module, parstr, center, ls_block, section) + +int in #I input file descriptor +int out #I output file descriptor +char module[ARB] #I .help module name +char parstr[ARB] #I .help optional keyword 2 +char center[ARB] #I .help optional keyword 3 +char ls_block[ARB] #I .ls block to search for +char section[ARB] #I section to print + +pointer sp, ip, sptr +pointer ibuf, unesc, name, level +int lastline, font, indented, ls_level +int i, arg, nsec, cmd +bool format, quit_at_le, quit_at_ih, formatted + +int lh_findsection(), lh_findblock(), nextcmd() +int stridxs(), getline(), strlen(), strmatch(), lgetarg() + +define text_ 99 +define err_ 98 + +include "lroff.com" + +begin + call smark (sp) + call salloc (ibuf, SZ_IBUF, TY_CHAR) + call salloc (unesc, SZ_IBUF, TY_CHAR) + call salloc (name, SZ_LINE, TY_CHAR) + call salloc (level, SZ_FNAME, TY_CHAR) + call salloc (sptr, MAX_SECTIONS, TY_POINTER) + + call aclrc (Memc[ibuf], SZ_IBUF) + call aclrc (Memc[name], SZ_LINE) + call aclrc (Memc[unesc], SZ_IBUF) + call aclrc (Memc[level], SZ_FNAME) + + # Initialize. + lastline = TEXT + font = F_ROMAN + indented = YES + nsec = 0 + ls_level = 0 + format = true + quit_at_le = false + quit_at_ih = false + formatted = false + + # Initialize the section numbering. + call amovki (0, nh_level, MAX_NHLEVEL) + + # Determine whether or not the text is formatted. + repeat { + if (getline (in, Memc[ibuf]) == EOF) + goto err_ + for (ip=1; IS_WHITE(Memc[ibuf+ip-1]); ip=ip+1) + ; + } until (Memc[ibuf+ip-1] != '\n') + call ungetline (in, Memc[ibuf]) + if (Memc[ibuf] == '.') + formatted = true + + # Scan forward if searching for and item. + if (section[1] != EOS) { + if (lh_findsection (in, formatted, section) == EOF) + goto err_ + } else if (ls_block[1] != EOS) { + if (lh_findblock (in, formatted, ls_block) == EOF) + goto err_ + quit_at_le = true + } + + # Begin the output. + call lh_prolog (out, module, parstr, center) + call fprintf (out, "<TITLE>%s</TITLE>\n<UL>\n") + if (ls_block[1] != EOS) + call pargstr (ls_block) + else if (section[1] != EOS) + call pargstr (section) + else if (module[1] != EOS) + call pargstr (module) + else + call pargstr (" ") + + + # Process the file. + while (getline (in, Memc[ibuf]) != EOF) { + + # Make a copy of the raw line minus the newline char, we may need + # this to extract comments later. + Memc[ibuf+strlen(Memc[ibuf])-1] = EOS + call strcpy (Memc[ibuf], Memc[unesc], SZ_LINE) + + + # Escape problem chars for HTML and handle font changes. Changes + # are done in-place. + call lh_escape (Memc[ibuf], font, format, NO, SZ_LINE) + + switch (Memc[ibuf]) { + case '\n': + call fprintf (out, "<P>\n") + + case '.': + # Swallow any help strings if present. + if (strmatch (Memc[ibuf], "^.help") > 0) + next + + ip = 1 + lastline = TEXT + + # Process the directive, position the ip at the beginning + # of any argument. + cmd = nextcmd (Memc[ibuf], ip) + while (IS_WHITE(Memc[ibuf+ip])) # skip spaces + ip = ip + 1 + + switch (cmd) { + case FI: # enter fill mode + call fprintf (out, "</PRE>\n") + format = true + case NF: # leave fill mode (nofill) + call fprintf (out, "<PRE>\n") + format = false + case JU: # enter line justification mode + # no-op + next + case NJ: # leave line justification mode + # no-op + next + case RJ: # right justify text on nf,nj line + # no-op + next + + case SH: # section heading + if (ls_level > 0) { # for missing .le statements + call fprintf (out, "</DD>\n</DL>\n") + ls_level = 0 + } + lastline = DIRECTIVE + Memc[level] = EOS + next + case IH: # indented section heading + if (ls_level > 0) { # for missing .le statements + call fprintf (out, "</DD>\n</DL>\n") + ls_level = 0 + } + lastline = DIRECTIVE + Memc[level] = EOS + if (quit_at_ih) + if (stridxs ("|", section) > 0) { + quit_at_ih = false + call ungetline (in, Memc[ibuf]) + if (lh_findsection (in, formatted, section) == EOF) + break + } else + break + next + case NH: # numbered section heading + if (ls_level > 0) { # for missing .le statements + call fprintf (out, "</DD>\n</DL>\n") + ls_level = 0 + } + call lh_set_level (lgetarg(Memc[ibuf],ip,1), Memc[level]) + lastline = DIRECTIVE + next + + case CE: # center next line + if (getline (in, Memc[ibuf]) == EOF) + break + else { + call lh_escape (Memc[ibuf], font, true, NO, SZ_LINE) + call fprintf (out, "<CENTER>%s</CENTER><BR>\n") + call pargstr (Memc[ibuf]) + } + + case BR: # break line + call fprintf (out, "<BR>\n") + case SP: # break, space N spaces on output + arg = lgetarg (Memc[ibuf], ip, 1) + call fprintf (out, "<BR>\n") + for (i=1; i < arg; i = i + 1) + call fprintf (out, "<BR>\n") + case IN: # indent +/- N spaces + # no-op + next + + case LS: # begin labelled section + arg = lgetarg (Memc[ibuf], ip, 0) + if (arg == 0) + ip = 5 + + # Generate a HREF of the label, we use only the first word. + call strcpy (Memc[ibuf+ip-1], Memc[name], SZ_LINE) + for (i=0; IS_ALNUM(Memc[name+i]) || + Memc[name+i] == '_'; i=i+1) + ; + Memc[name+i] = EOS + Memc[ibuf+ip+strlen(Memc[ibuf+ip])-1] = EOS + + call fprintf (out, "<DL>\n<DT><B>") + call fprintf (out,"<A NAME=\"l_%s\">%s</A>") + call pargstr (Memc[name]) + call pargstr (Memc[ibuf+ip-1]) + call fprintf (out, "</B></DT>\n") + + # Write out a comment line for the GUI to use. + call lh_escape(Memc[unesc+ip-1], font, true, YES, SZ_LINE) + Memc[unesc+strlen(Memc[unesc])-1] = EOS + call fprintf (out, + "<! Sec=%s Level=%d Label=\'%s\' Line=\'%s\'>\n<DD>") + if (nsec > 0) + call pargstr (SECTION(sptr, nsec-1)) + else + call pargstr ("None") + call pargi (ls_level) + call pargstr (Memc[name]) + if (Memc[unesc+ip-1] == '\n') + call pargstr (" ") + else + call pargstr (Memc[unesc+ip-1]) + ls_level = ls_level + 1 + + case LE: # end labelled section + call fprintf (out, "</DD>\n</DL>\n") + ls_level = ls_level - 1 + if (quit_at_le) + break + + case HR: # HREF anchor + # HTML href anchor of the form ".hr <href> <anch_text>", + # we skip ahead to the <text> and process as a normal line. + Memc[ibuf+ip+strlen(Memc[ibuf+ip])-1] = EOS + for (i=0; !IS_WHITE(Memc[ibuf+ip]); ip=ip+1) { + Memc[name+i] = Memc[ibuf+ip] + i = i + 1 + } + Memc[name+i] = EOS + + call fprintf (out, "<A HREF=\"%s\">%s</A>\n") + call pargstr (Memc[name]) + call pargstr (Memc[ibuf+ip+1]) + + case HN: # NAME target + # HTML name target of the form ".hn <name>", strip the + # newline added in the escape routine. + Memc[ibuf+ip+strlen(Memc[ibuf+ip])-1] = EOS + call fprintf (out, "<A NAME=\"%s\"></A>\n") + call pargstr (Memc[ibuf+ip]) + + case BP: # break page + # no-op + next + case TP: # test space left on page + # no-op + next + case KS: # start floating keep + call fprintf (out, "<PRE>\n") + format = false + case KE: # end floating keep + call fprintf (out, "</PRE>\n") + format = true + case ENDHELP: # end of help block + break + } + + default: + if (lastline == DIRECTIVE) { + + # Section directive name. For certain standard sections + # we'll force an indention to make the output look better, + # everything else gets written normally. + + # Save the section name. + call salloc (SPTR(sptr,nsec), SZ_LINE, TY_CHAR) + call aclrc (SECTION(sptr,nsec), SZ_LINE) + Memc[ibuf+strlen(Memc[ibuf])-1] = EOS + call sprintf (SECTION(sptr,nsec), SZ_LINE, "\'%s\'") + call pargstr (Memc[ibuf]) + + if (indented == YES) + call fprintf (out, "</UL>\n") + if (nsec > 0) { + call fprintf (out, "<! EndSection: %s>\n") + call pargstr (SECTION(sptr,nsec-1)) + } + + # Make the section name a URL target. + call lh_mkname (Memc[ibuf], Memc[name]) + if (Memc[level] == EOS) { + call fprintf (out, "<H2><A NAME=\"s_%s\">%s</A></H2>\n") + call pargstr (Memc[name]) + call pargstr (Memc[ibuf]) + } else { + call fprintf (out, + "<H2><A NAME=\"s_%s\">%s %s</A></H2>\n") + call pargstr (Memc[name]) + call pargstr (Memc[level]) + call pargstr (Memc[ibuf]) + Memc[level] = EOS + } + + call fprintf (out, "<! BeginSection: \'%s\'>\n") + call pargstr (Memc[ibuf]) + if (indented == YES) + call fprintf (out, "<UL>\n") + + lastline = NAME + nsec = nsec + 1 + if (section[1] != EOS) + quit_at_ih = true + + } else { + # Ordinary text line. +text_ call fprintf (out, "%s") + call pargstr (Memc[ibuf]) + lastline = TEXT + } + } + + call aclrc (Memc[ibuf], SZ_IBUF) + call aclrc (Memc[unesc], SZ_IBUF) + call aclrc (Memc[name], SZ_LINE) + } + + # Close the last section. + if (nsec > 0) { + call fprintf (out, "</UL>\n<! EndSection: %s>\n\n") + call pargstr (SECTION(sptr,nsec-1)) + } + + # Write out an HTML comment giving the document section names. + call fprintf (out, "<! Contents: ") + for (i=0; i < nsec; i=i+1) { + call fprintf (out, "%s ") + call pargstr (SECTION(sptr,i)) + } + call fprintf (out, " >\n\n") + call fprintf (out, "</BODY>\n</HTML>\n") + + call flush (out) +err_ call sfree (sp) +end + + +# LH_PROLOG -- Begin the HTML output, print the header table for a help +# page if we have the information. + +procedure lh_prolog (fd, mod, date, title) + +int fd #I output file descriptor +char mod[ARB] #I .help module name +char date[ARB] #I .help keyword 2 +char title[ARB] #I .help keyword 3 + +begin + call fprintf (fd, "<HTML>\n<BODY>\n") + + # If we only have the module name don't bother with header. + if (date[1] == EOS && title[1] == EOS) + return + + # Begin the HTML output prolog. + call fprintf (fd, "<TABLE WIDTH=\"100%%\" BORDER=0><TR>\n") + + # Left side page header. + call fprintf (fd, "<TD ALIGN=LEFT><FONT SIZE=4>\n") + if (date[1] == EOS) { + call fprintf (fd, "<B>%s</B>") + call pargstr (mod) + } else { + call fprintf (fd, "<B>%s (%s)</B>") + call pargstr (mod) + call pargstr (date) + } + call fprintf (fd, "</FONT></TD>\n") + + # Center page header. + if (title[1] != EOS) { + call fprintf (fd, "<TD ALIGN=CENTER><FONT SIZE=4>\n") + call fprintf (fd, "<B>%s</B>\n") + call pargstr (title) + call fprintf (fd, "</FONT></TD>\n") + } + + # Right side page header. + call fprintf (fd, "<TD ALIGN=RIGHT><FONT SIZE=4>\n") + if (date[1] == EOS) { + call fprintf (fd, "<B>%s</B>") + call pargstr (mod) + } else { + call fprintf (fd, "<B>%s (%s)</B>") + call pargstr (mod) + call pargstr (date) + } + call fprintf (fd, "</FONT></TD>\n") + + call fprintf (fd, "</TR></TABLE><P>\n") +end + + +# LH_ESCAPE -- Escape any HTML problem characters in the line ('<','>','&') +# as well as the font changes. + +procedure lh_escape (str, font, format, special_only, maxch) + +char str[ARB] #I string to edit +int font #U current font +bool format #I formatting flag +int special_only #I escape only special chars? +int maxch #I max length of string + +pointer sp, ip, buf, keyword +int i, gstrcpy(), stridx() + +define copy_ 90 + +begin + call smark (sp) + call salloc (buf, maxch, TY_CHAR) + call salloc (keyword, maxch, TY_CHAR) + call aclrc (Memc[buf], maxch) + call aclrc (Memc[keyword], maxch) + + ip = buf + for (i=1; str[i] != EOS && i <= maxch; i = i + 1) { + + if (special_only == YES && stridx (str[i], "<>&") == 0) + goto copy_ + + switch (str[i]) { + + # Handle special chars. + case '<': + ip = ip + gstrcpy ("<", Memc[ip], SZ_LINE) + case '>': + ip = ip + gstrcpy (">", Memc[ip], SZ_LINE) + case '&': + ip = ip + gstrcpy ("&", Memc[ip], SZ_LINE) + + # Quoted single chars and strings get a special font. + case '\'': + if (str[i+2] == '\'') { + ip = ip + gstrcpy ("<TT>", Memc[ip], SZ_LINE) + ip = ip + gstrcpy (str[i], Memc[ip], 3) + ip = ip + gstrcpy ("</TT>", Memc[ip], SZ_LINE) + i = i + 2 + } else + goto copy_ + case '`': + if (str[i+2] == '`' || str[i+2] == '\'') { + ip = ip + gstrcpy ("<TT>", Memc[ip], SZ_LINE) + ip = ip + gstrcpy (str[i], Memc[ip], 3) + ip = ip + gstrcpy ("</TT>", Memc[ip], SZ_LINE) + i = i + 2 + } else + goto copy_ + case '"': + if (format && str[i+1] != '/' && str[i+2] != '/') { + if (font == F_TELETYPE) { + # Do a closing quote. + ip = ip + gstrcpy ("</TT>\"", Memc[ip], SZ_LINE) + font = F_ROMAN + } else if (font == F_ROMAN) { + # Do an opening quote. + ip = ip + gstrcpy ("\"<TT>", Memc[ip], SZ_LINE) + font = F_TELETYPE + } else + goto copy_ + } else + goto copy_ + + # Process font changes. + case '\\': + if (str[i+1] == 'f') { + if (str[i+2] == 'B') { + if (font == F_BOLD) + next + if (font == F_ITALIC) + ip = ip + gstrcpy ("</I>", Memc[ip], SZ_LINE) + ip = ip + gstrcpy ("<B>", Memc[ip], SZ_LINE) + font = F_BOLD + + } else if (str[i+2] == 'I') { + if (font == F_ITALIC) + next + if (font == F_BOLD) + ip = ip + gstrcpy ("</B>", Memc[ip], SZ_LINE) + ip = ip + gstrcpy ("<I>", Memc[ip], SZ_LINE) + font = F_ITALIC + + } else if (str[i+2] == 'R') { + if (font == F_BOLD) + ip = ip + gstrcpy ("</B>", Memc[ip], SZ_LINE) + else if (font == F_ITALIC) + ip = ip + gstrcpy ("</I>", Memc[ip], SZ_LINE) + font = F_ROMAN + + } else if (str[i+2] == 'P') { + if (font == F_BOLD) { + ip = ip + gstrcpy ("</B>", Memc[ip], SZ_LINE) + } else if (font == F_ITALIC) { + ip = ip + gstrcpy ("</I>", Memc[ip], SZ_LINE) + } + font = F_ROMAN + } + i = i + 2 + } else if (str[i+1] == '\n' || str[i+1] == EOS) { + Memc[ip] = str[i] + ip = ip + 1 + i = i + 1 + ip = ip + gstrcpy ("<BR>", Memc[ip], SZ_LINE) + } else + goto copy_ + + default: +copy_ Memc[ip] = str[i] + ip = ip + 1 + } + } + + # Add the trailing newline we stripped above. + ip = ip + gstrcpy ("\n\0", Memc[ip], SZ_LINE) + + # Move the string back. + call amovc (Memc[buf], str, maxch) + + call sfree (sp) +end + + +# LH_SET_LEVEL -- Increment the level number of a numbered header. + +procedure lh_set_level (n, level) + +int n #I level number +char level[ARB] #U level string + +int i, strlen() +include "lroff.com" + +begin + # Increment the desired section number; zero all higher + # numbered section counters. + nh_level[n] = nh_level[n] + 1 + call amovki (0, nh_level[n+1], MAX_NHLEVEL - n) + + # Output the section number followed by a blank and then + # the section label. + level[1] = EOS + do i = 1, n { + call sprintf (level[strlen(level)+1], SZ_IBUF, "%d.") + call pargi (nh_level[i]) + } + + # Cancel the final "." if subsection heading. Add a blank. + if (n > 1 && level[strlen(level)] == '.') + level[strlen(level)] = EOS +end + + +# LH_FINDBLOCK -- If text contains format directives, eat input lines until +# a ".ls" directive is found which contains the block name as a substring. +# If the text is not formatted, search for a line beginning with the pattern. + +int procedure lh_findblock (fd, formatted, param) + +int fd +bool formatted +char param[ARB] + +bool match_found +pointer sp, lbuf, pattern +int len +int getline(), strmatch(), strlen() +errchk getline + +define err_ 90 + +begin + call smark (sp) + call salloc (pattern, SZ_FNAME, TY_CHAR) + call salloc (lbuf, SZ_LINE, TY_CHAR) + + match_found = false + + # Get the first line. + if (getline (fd, Memc[lbuf]) == EOF) + goto err_ + + if (formatted) { + call sprintf (Memc[pattern], SZ_FNAME, "{%s}") + call pargstr (param) + repeat { + if (strmatch (Memc[lbuf], "^.{ls}") > 0) + if (strmatch (Memc[lbuf], Memc[pattern]) > 0) { + match_found = true + break + } + } until (getline (fd, Memc[lbuf]) == EOF) + + } else { + call sprintf (Memc[pattern], SZ_FNAME, "^#{%s}") + call pargstr (param) + repeat { + if (strmatch (Memc[lbuf], Memc[pattern]) > 0) { + match_found = true + break + } + } until (getline (fd, Memc[lbuf]) == EOF) + } + call ungetline (fd, Memc[lbuf]) + +err_ len = strlen (Memc[lbuf]) + call sfree (sp) + if (match_found) + return (len) + else + return (EOF) +end + + +# LH_FINDSECTION -- If text contains format directives, eat input lines until +# a ".ih" directive is found for the named section. If the text is not +# formatted, search for a line beginning with the section name. + +define MAXPAT 10 + +int procedure lh_findsection (fd, formatted, sections) + +int fd # input file +bool formatted # is help block formatted +char sections[ARB] # list of sections "a|b|c" + +bool match_found +int npat, ip +pointer sp, patbuf, patoff[MAXPAT], op +char lbuf[SZ_LINE] + +bool lh_match() +int getline(), strmatch() +errchk getline + +define err_ 91 + +begin + call smark (sp) + call salloc (patbuf, SZ_LINE, TY_CHAR) + + # Process the list of sections into patbuf and patoff, i.e., into a + # list of EOS delimited strings in the string buffer patbuf. Each + # section name or abbreviation is delimited by '|' (or). + + npat = 1 + op = patbuf + patoff[1] = op + + # Get the first line. + if (getline (fd, lbuf) == EOF) + goto err_ + + for (ip=1; sections[ip] != EOS; ip=ip+1) + switch (sections[ip]) { + case '|': + Memc[op] = EOS + op = op + 1 + npat = min (MAXPAT, npat + 1) + patoff[npat] = op + default: + Memc[op] = sections[ip] + op = op + 1 + } + Memc[op] = EOS + + match_found = false + + if (formatted) { + repeat { + if (strmatch (lbuf, "^.{ih}") > 0) + if (getline (fd, lbuf) != EOF) { + match_found = lh_match (lbuf, patoff, npat) + if (match_found) + break + } + } until (getline (fd, lbuf) == EOF) + call ungetline (fd, lbuf) + call ungetline (fd, ".ih\n") + + } else { + repeat { + match_found = lh_match (lbuf, patoff, npat) + if (match_found) + break + } until (getline (fd, lbuf) == EOF) + call ungetline (fd, lbuf) + } + +err_ call sfree (sp) + if (match_found) + return (OK) + else + return (EOF) +end + + +# LH_MATCH -- Match a set of patterns against a line of test, matching only +# at the beginning of line in either case. + +bool procedure lh_match (lbuf, patoff, npat) + +char lbuf[ARB] # line of text +pointer patoff[npat] # pointers to pattern strings +int npat # number of patterns + +int pat +pointer sp, pattern +int strmatch() + +begin + call smark (sp) + call salloc (pattern, SZ_FNAME, TY_CHAR) + + for (pat=1; pat <= npat; pat=pat+1) { + call sprintf (Memc[pattern], SZ_FNAME, "^{%s}") + call pargstr (Memc[patoff[pat]]) + if (strmatch (lbuf, Memc[pattern]) > 0) { + call sfree (sp) + return (true) + } + } + + call sfree (sp) + return (false) +end + + +# LH_MKNAME -- Given a string make it suitable for use as an HREF name. + +procedure lh_mkname (instr, outstr) + +char instr[ARB] +char outstr[ARB] + +int i + +begin + # Make it a URL. First convert the section name to a + # lower-case string and replace the blanks. + call strcpy (instr, outstr, SZ_LINE) + call strlwr (outstr) + for (i=1; i < SZ_LINE; i=i+1) + if (outstr[i] == EOS || outstr[i] == '\n') + break + else if (!IS_ALNUM(outstr[i])) + outstr[i] = '_' +end diff --git a/pkg/system/help/lroff/lroff2ps.x b/pkg/system/help/lroff/lroff2ps.x new file mode 100644 index 00000000..a782ca21 --- /dev/null +++ b/pkg/system/help/lroff/lroff2ps.x @@ -0,0 +1,460 @@ +include <syserr.h> +include <ctype.h> +include <psset.h> +include "lroff.h" + + +define DIRECTIVE 1 # processing codes +define NAME 2 +define TEXT 3 +define NEWLINE 4 + +define INDENT 5 # size of indentitudedness + + +# LROFF2PS -- Convert LROFF text to Postscript. By default we process the +# entire file however we allow for the printing of only a particular section +# or labelled text block to be compatible with the HELP task options. +# If a section name is given that section will be printed and and .ls +# block request will be ignored. + +procedure lroff2ps (in, out, psptr, ls_block, section) + +int in #i input file descriptor +int out #i output file descriptor +pointer psptr #i PSIO pointer +char ls_block[ARB] #i .ls block to search for +char section[ARB] #i section to print + +pointer sp, ip, ps +pointer ibuf, line, level +int lastline, font, indent, ls_level +int i, arg, nsec, cmd, last_cmd +bool format, quit_at_le, quit_at_ih, formatted + +pointer ps_open() +int lh_findsection(), lh_findblock(), nextcmd() +int stridxs(), getline(), strlen(), strmatch(), lgetarg() + +define text_ 99 +define err_ 98 + +include "lroff.com" + +begin + call smark (sp) + call salloc (ibuf, SZ_IBUF, TY_CHAR) + call salloc (line, SZ_LINE, TY_CHAR) + call salloc (level, SZ_FNAME, TY_CHAR) + + call aclrc (Memc[ibuf], SZ_LINE) + call aclrc (Memc[line], SZ_LINE) + call aclrc (Memc[level], SZ_LINE) + + # Initialize. + lastline = TEXT + font = F_ROMAN + indent = 0 + nsec = 0 + ls_level = 0 + format = true + quit_at_le = false + quit_at_ih = false + formatted = false + + # Initialize the section numbering. + call amovki (0, nh_level, MAX_NHLEVEL) + + # Determine whether or not the text is formatted. + repeat { + if (getline (in, Memc[ibuf]) == EOF) + goto err_ + for (ip=1; IS_WHITE(Memc[ibuf+ip-1]); ip=ip+1) + ; + } until (Memc[ibuf+ip-1] != '\n') + call ungetline (in, Memc[ibuf]) + if (Memc[ibuf] == '.') + formatted = true + + # Scan forward if searching for and item. + if (section[1] != EOS) { + if (lh_findsection (in, formatted, section) == EOF) + goto err_ + } else if (ls_block[1] != EOS) { + if (lh_findblock (in, formatted, ls_block) == EOF) + goto err_ + quit_at_le = true + } + + # Begin the output is we aren't passed a pointer that may have + # already set up headers, page parameters, etc. + if (psptr == NULL) + ps = ps_open (out, YES) + else + ps = psptr + call ps_write_prolog (ps) + + # Process the file. + while (getline (in, Memc[ibuf]) != EOF) { + + # Escape the line, inserting special font changes for quotes + # chars and strings. + call lp_escape (Memc[ibuf], font, format, SZ_LINE) + + switch (Memc[ibuf]) { + case '\n': + if (lastline != NEWLINE) + call ps_linebreak (ps, NO) + call ps_newline (ps) + lastline = NEWLINE + + case '.': + # Swallow any help strings if present. + if (strmatch (Memc[ibuf], "^.{help}") > 0) + next + + # Stomp the newline. + Memc[ibuf+strlen(Memc[ibuf])-1] = EOS + + # Process the directive, position the ip at the beginning + # of any argument. + ip = 1 + cmd = nextcmd (Memc[ibuf], ip) + while (IS_WHITE(Memc[ibuf+ip])) # skip spaces + ip = ip + 1 + + switch (cmd) { + case FI, KE: # enter fill mode + call ps_setfont (ps, F_ROMAN) + call ps_set_justify (ps, YES) + lastline = NEWLINE + format = true + case NF, KS: # leave fill mode (nofill) + if (lastline != NEWLINE && last_cmd != KS && last_cmd != NF) + call ps_linebreak (ps, NO) + call ps_setfont (ps, F_TELETYPE) + call ps_set_justify (ps, NO) + lastline = NEWLINE + format = false + case JU: # enter line justification mode + call ps_set_justify (ps, YES) + next + case NJ: # leave line justification mode + call ps_set_justify (ps, NO) + next + case RJ: # right justify text on next line + call ps_linebreak (ps, NO) + call strcpy (Memc[ibuf+4], Memc[line], SZ_FNAME) + Memc[line+strlen(Memc[line])-1] = EOS + if (getline (in, Memc[ibuf]) != EOF) { + call ps_output (ps, Memc[ibuf], NO) + call ps_rightjustify (ps, Memc[line]) + } + next + + case SH: # section heading + if (ls_level > 0) { # for missing .le statements + ls_level = 0 + indent = 0 + } + if (nsec > 0) { + call ps_linebreak (ps, NO) + call ps_linebreak (ps, NO) + } + lastline = DIRECTIVE + Memc[level] = EOS + next + case IH: # indented section heading + if (ls_level > 0) { # for missing .le statements + ls_level = 0 + indent = 0 + } + + if (nsec > 0) + call ps_linebreak (ps, NO) + if (lastline == TEXT) + call ps_linebreak (ps, NO) + lastline = DIRECTIVE + Memc[level] = EOS + if (quit_at_ih) + if (stridxs ("|", section) > 0) { + quit_at_ih = false + call ungetline (in, Memc[ibuf]) + if (lh_findsection (in, formatted, section) == EOF) + break + } else + break + next + case NH: # numbered section heading + if (ls_level > 0) { # for missing .le statements + ls_level = 0 + indent = 0 + } + call lh_set_level (lgetarg(Memc[ibuf],ip,1), Memc[level]) + if (nsec > 0) { + call ps_linebreak (ps, NO) + call ps_linebreak (ps, NO) + } + lastline = DIRECTIVE + next + + case CE: # center next line + if (getline (in, Memc[ibuf]) != EOF) { + call lp_escape (Memc[ibuf], font, true, SZ_LINE) + call ps_linebreak (ps, NO) + call ps_center (ps, Memc[ibuf]) + } + + case BR: # break line + call ps_linebreak (ps, NO) + case SP: # break, space N spaces on output + arg = lgetarg (Memc[ibuf], ip, 1) + call ps_linebreak (ps, NO) + for (i=1; i < arg; i = i + 1) + call ps_linebreak (ps, NO) + case IN: # indent +/- N spaces + arg = lgetarg (Memc[ibuf], ip, 0) + call ps_indent (ps, arg) + next + + case LS: # begin labelled section + arg = lgetarg (Memc[ibuf], ip, INDENT) + if (arg == 0) + ip = 5 + + if (lastline == TEXT) + call ps_linebreak (ps, NO) + call ps_testpage (ps, 2) + if (ls_level < 1 || (last_cmd == LS && lastline == TEXT)) + call ps_linebreak (ps, NO) + call ps_spfont (ps, F_BOLD) + call ps_output (ps, Memc[ibuf+ip-1], NO) + if (strlen (Memc[ibuf+ip-1]) > (INDENT-1)) + call ps_linebreak (ps, NO) + call ps_spfont (ps, NULL) + call ps_setfont (ps, F_ROMAN) + + indent = max (0, indent + INDENT) + call ps_indent (ps, indent) + ls_level = ls_level + 1 + + case LE: # end labelled section + if (last_cmd != LE || (last_cmd == LE && lastline == TEXT)) + call ps_linebreak (ps, NO) + indent = max (0, indent - INDENT) + call ps_indent (ps, indent) + ls_level = ls_level - 1 + lastline = NEWLINE + if (quit_at_le) + break + + case HR: # HREF anchor + # HTML href anchor of the form ".hr <href> <anch_text>", + # we skip ahead to the <text> and process as a normal line. + for (i=0; !IS_WHITE(Memc[ibuf+ip]); ip=ip+1) + i = i + 1 + call ps_deposit (ps, Memc[ibuf+ip+1]) + + case HN: # NAME target + # HTML name target of the form ".hn <name>". + # no-op + + case BP: # break page + call ps_linebreak (ps, NO) + call ps_pagebreak (ps) + next + case TP: # test space left on page + # no-op + next + case ENDHELP: # end of help block + break + } + last_cmd = cmd + + default: + # Stomp the newline. + Memc[ibuf+strlen(Memc[ibuf])-1] = EOS + + if (lastline == DIRECTIVE) { + + # Section directive name. For certain standard sections + # we'll force an indention to make the output look better, + # everything else gets written normally. + + indent = max (0, indent - INDENT) + call ps_indent (ps, indent) + + call ps_setfont (ps, F_BOLD) + call ps_testpage (ps, 3) + if (Memc[level] == EOS) { + call ps_output (ps, Memc[ibuf], NO) + } else { + call sprintf (Memc[line], SZ_LINE, "%s %s") + call pargstr (Memc[level]) + call pargstr (Memc[ibuf]) + + call ps_output (ps, Memc[line], NO) + Memc[level] = EOS + } + call ps_setfont (ps, F_ROMAN) + call ps_linebreak (ps, NO) + + indent = max (0, indent + INDENT) + call ps_indent (ps, indent) + + lastline = NAME + nsec = nsec + 1 + if (section[1] != EOS) + quit_at_ih = true + + } else { + # Ordinary text line. +text_ if (format) { + call ps_deposit (ps, Memc[ibuf]) + } else { + call lp_strdetab (Memc[ibuf], Memc[line], SZ_LINE) + call ps_output (ps, Memc[line], NO) + call ps_linebreak (ps, NO) + } + lastline = TEXT + } + } + + call aclrc (Memc[ibuf], SZ_LINE) + call aclrc (Memc[line], SZ_LINE) + } + + # Close the last section. + call ps_linebreak (ps, NO) + call ps_close (ps) + + call flush (out) +err_ call sfree (sp) +end + + +# LP_ESCAPE -- Escape any HTML problem characters in the line ('<','>','&') +# as well as the font changes. + +procedure lp_escape (str, font, format, maxch) + +char str[ARB] #i string to edit +int font #u current font +bool format #i formatting flag +int maxch #i max length of string + +pointer sp, ip, buf, keyword +int i, strmatch(), gstrcpy() +bool is_ls + +define copy_ 90 + +begin + call smark (sp) + call salloc (buf, maxch, TY_CHAR) + call salloc (keyword, maxch, TY_CHAR) + call aclrc (Memc[buf], maxch) + call aclrc (Memc[keyword], maxch) + + ip = buf + is_ls = FALSE + if (strmatch (str, "^.{ls}") > 0) + is_ls = TRUE + + for (i=1; str[i] != EOS && i <= maxch; i = i + 1) { + + switch (str[i]) { + + # Quoted single chars and strings get a special font. + case '\'', '`': + if (str[i+2] == '`' || str[i+2] == '\'') { + if (format) + ip = ip + gstrcpy ("\\fT", Memc[ip], SZ_LINE) + ip = ip + gstrcpy (str[i], Memc[ip], 3) + if (format) { + if (is_ls) + ip = ip + gstrcpy ("\\fB", Memc[ip], SZ_LINE) + else { + switch (font) { + case F_ROMAN: + ip = ip + gstrcpy ("\\fR", Memc[ip], SZ_LINE) + case F_BOLD: + ip = ip + gstrcpy ("\\fB", Memc[ip], SZ_LINE) + case F_ITALIC: + ip = ip + gstrcpy ("\\fI", Memc[ip], SZ_LINE) + case F_TELETYPE: + ip = ip + gstrcpy ("\\fT", Memc[ip], SZ_LINE) + default: + ip = ip + gstrcpy ("\\fR", Memc[ip], SZ_LINE) + } + } + } + i = i + 2 + } else + goto copy_ + case '"': + if (format && str[i+1] != '/' && str[i+2] != '/') { + if (font == F_TELETYPE) { + # Do a closing quote. + if (format) { + if (is_ls) + ip = ip + gstrcpy ("\"\\fB", Memc[ip], SZ_LINE) + else + ip = ip + gstrcpy ("\"\\fR", Memc[ip], SZ_LINE) + } + font = F_ROMAN + } else if (font == F_ROMAN) { + # Do an opening quote. + if (format) + ip = ip + gstrcpy ("\\fT\"", Memc[ip], SZ_LINE) + font = F_TELETYPE + } else + goto copy_ + } else + goto copy_ + + default: +copy_ Memc[ip] = str[i] + ip = ip + 1 + } + } + + # Add the trailing newline we stripped above. + ip = ip + gstrcpy ("\n\0", Memc[ip], SZ_LINE) + + # Move the string back. + call amovc (Memc[buf], str, maxch) + + call sfree (sp) +end + + +# LP_STRDETAB -- Procedure to remove tabs from a line of text. + +procedure lp_strdetab (line, outline, maxch) + +char line[ARB], outline[ARB] +int maxch + +int ip, op + +begin + ip = 1 + op = 1 + + while (line[ip] != EOS && op <= maxch) { + if (line[ip] == '\t') { + repeat { + outline[op] = ' ' + op = op + 1 + } until (mod(op,8) == 0 || op > maxch) + ip = ip + 1 + } else { + outline[op] = line [ip] + ip = ip + 1 + op = op + 1 + } + } + + outline[op] = EOS +end diff --git a/pkg/system/help/lroff/mkpkg b/pkg/system/help/lroff/mkpkg new file mode 100644 index 00000000..73a157d4 --- /dev/null +++ b/pkg/system/help/lroff/mkpkg @@ -0,0 +1,27 @@ +# Make the LROFF line-oriented text formatter. + +$checkout libpkg.a ../../ +$update libpkg.a +$checkin libpkg.a ../../ +$exit + +libpkg.a: + breakline.x lroff.com lroff.h words.com <chars.h> + center.x lroff.com lroff.h <chars.h> + dols.x lroff.com lroff.h <chars.h> <error.h> + getarg.x lroff.h <chars.h> + indent.x lroff.com lroff.h + input.x lroff.com lroff.h <chars.h> <ctype.h> + justify.x lroff.com lroff.h <chars.h> + lroff.x lroff.com lroff.h <chars.h> <ctype.h> + lroff2html.x lroff.com lroff.h <ctype.h> + lroff2ps.x lroff.com lroff.h <psset.h> <ctype.h> + nextcmd.x lroff.h <ctype.h> + nofill.x lroff.com lroff.h + output.x lroff.com lroff.h <chars.h> <mach.h> + rawcopy.x lroff.com lroff.h + section.x lroff.com lroff.h <chars.h> <ctype.h> + skiplines.x lroff.h + textlen.x lroff.h <chars.h> + textout.x lroff.com lroff.h words.com <chars.h> + ; diff --git a/pkg/system/help/lroff/nextcmd.x b/pkg/system/help/lroff/nextcmd.x new file mode 100644 index 00000000..d4b09f44 --- /dev/null +++ b/pkg/system/help/lroff/nextcmd.x @@ -0,0 +1,56 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include "lroff.h" + +.help nextcmd +.nf ________________________________________________________________________ +NEXTCMD -- Examine the input line; if it is an Lroff directive, return +the integer code of the directive, otherwise NULL. Leave IP pointing +to the argument field if a command, otherwise leave it pointing at the +first char of the text line. Note that the "directives" string must +match the opcode definitions given in lroff.h +.endhelp ___________________________________________________________________ + +define SZ_OPCODE 2 + +int procedure nextcmd (linebuf, ip) + +char linebuf[ARB] +int ip, op +char opcode[SZ_OPCODE] +int command, kwp, strmatch(), strncmp() +string directives "finfjunjrjshihnhbrcespinlslebptpkskehrhn" + +begin + if (linebuf[1] != '.') # not a command line? + return (NULL) + if (strmatch (linebuf, "^.endhelp") > 0) + return (ENDHELP) + ip = 2 # skip the '.' + + # Directives may be either upper or lower case. + for (op=1; op <= SZ_OPCODE; op=op+1) { + opcode[op] = linebuf[ip] + if (IS_UPPER (opcode[op])) + opcode[op] = TO_LOWER (opcode[op]) + ip = ip + 1 + } + + # Just in case a directive happens to be longer than 2 chars, make + # sure IP points past the directive name. + while (IS_ALPHA (linebuf[ip])) + ip = ip + 1 + + # Lookup directive, return opcode number if found. + command = NULL + for (kwp=1; directives[kwp] != EOS; kwp=kwp+SZ_OPCODE) + if (strncmp (opcode, directives[kwp], SZ_OPCODE) == 0) { + command = (kwp+1) / SZ_OPCODE + break + } + + if (command == NULL) # unrecognized directive + ip = 1 + return (command) +end diff --git a/pkg/system/help/lroff/nofill.x b/pkg/system/help/lroff/nofill.x new file mode 100644 index 00000000..f81b0d88 --- /dev/null +++ b/pkg/system/help/lroff/nofill.x @@ -0,0 +1,45 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "lroff.h" + +.help nofill +.nf __________________________________________________________________________ +NOFILL -- Copy a block of text in ".nf" (nofill) mode, leaving the text +alone except for left justification. The only directives recognized in +a nofill block are FI (resume filling) and RJ (right justify). +.endhelp _____________________________________________________________________ + +int procedure nofill (in, out, linebuf) + +extern in(), out() +char linebuf[ARB] +int ip, command +pointer sp, rjbuf +int in(), input(), nextcmd() +errchk salloc, breakline, input, rjline, outline +include "lroff.com" + +begin + call smark (sp) + call salloc (rjbuf, SZ_IBUF, TY_CHAR) + + call breakline (out, NJ) + + while (input (in, linebuf) != EOF) { + command = nextcmd (linebuf, ip) + switch (command) { + case FI, ENDHELP: + call sfree (sp) + return (command) + case RJ: # right justify text + if (input (in, Memc[rjbuf]) == EOF) + break + call rjline (out, Memc[rjbuf], linebuf[ip]) + default: + call outline (out, linebuf) + } + } + + call sfree (sp) + return (ENDHELP) +end diff --git a/pkg/system/help/lroff/output.x b/pkg/system/help/lroff/output.x new file mode 100644 index 00000000..84ebea0d --- /dev/null +++ b/pkg/system/help/lroff/output.x @@ -0,0 +1,190 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <chars.h> +include "lroff.h" + +.help outstr, outc, getoutcol, set_outbuf +.nf __________________________________________________________________________ +OUTSTR, OUTC, OUTCOL -- Routines for buffering the output line. An output +line is built up with calls to OUTPUT to pass strings, and to OUTC to pass +characters. OUTCOL may be called to determine the index of the PRINTABLE +column at which the next character will be deposited (this is unaffected by +control chars in the output stream). + +The output buffer is flushed when OUTC is called to deposit a newline +character, by calling the user supplied output procedure. The output column +pointer is reset to the CURRENT left margin when the first character of the +new line is deposited. Any changes to the left margin made after the first +character is deposited do not take effect until the next line. OUTCOL returns +the value of the current left margin if called when the buffer is empty. + +NOTE: set_outbuf() must be called during Lroff startup and shutdown to +allocate the output buffer, the size of which depends on the maximum output +line length. +.endhelp _____________________________________________________________________ + + +# SET_OUTBUF -- Allocate and initialize the output buffer. + +procedure set_outbuf (outbuf_size) + +int outbuf_size # new buffer size in chars + +include "lroff.com" +errchk malloc, out +bool first_time +data first_time /true/ + +pointer obuf, op, otop +int col, old_left_margin, buffer_empty +common /lroout/ obuf, op, otop, col, old_left_margin, buffer_empty + +begin + if (first_time) { + obuf = NULL + buffer_empty = YES + first_time = false + } + + if (outbuf_size <= 0 && obuf != NULL) + call mfree (obuf, TY_CHAR) + else { + call malloc (obuf, outbuf_size, TY_CHAR) + otop = obuf + outbuf_size - 1 + op = obuf + buffer_empty = YES + old_left_margin = 1 + } +end + + +# OUTC -- Output a single character. Note that the character value is +# passed as an integer. + +procedure outc (out, ch) + +extern out() # user line output procedure +int ch # character to be output + +char text[1] +data text[1] /EOS/ + +begin + text[1] = ch + call outstr (out, text) +end + + +# OUTSTR -- Output a text string. + +procedure outstr (out, text) + +extern out() # user line output procedure +char text[ARB] # text string to be output + +int ch, ip, i +pointer obuf, op, otop +int col, old_left_margin, buffer_empty +common /lroout/ obuf, op, otop, col, old_left_margin, buffer_empty +include "lroff.com" + +begin + for (ip=1; text[ip] != EOS; ) { + if (buffer_empty == YES) { + if (obuf == NULL) + call error (1, "No Lroff output buffer allocated") + + # If left margin has been moved inward, blank out the unused + # columns. + + if (left_margin != old_left_margin) { + for (i=old_left_margin; i < left_margin; i=i+1) + Memc[obuf+i-1] = BLANK + old_left_margin = left_margin + } + + op = obuf + left_margin - 1 + col = left_margin + buffer_empty = NO + } + + # Move the text string into the buffer. The string may contain + # more than one line of text. + + for (; text[ip] != EOS; ip=ip+1) { + ch = text[ip] + Memc[op] = ch + op = op + 1 + + if (INVISIBLE(ch) || op > otop) { + if (ch == '\r' || ch == '\n') { + # Flush the buffer. + Memc[op] = EOS + call out (out_magic_arg, Memc[obuf]) + buffer_empty = YES + + # If all text data has not been copied (buffer overflow + # or newline embedded in the text), we must reinit the + # buffer and copy the remaining data. Otherwise we must + # return without calling the buffer_empty code to give + # the caller a chance to change the left margin. + + if (text[ip+1] == EOS) + return + } + } else + col = col + 1 + } + } +end + + +# GETOUTCOL -- Return the index of the next column of output. + +procedure getoutcol (next_column) + +int next_column # next col to be written (output) +pointer obuf, op, otop +int col, old_left_margin, buffer_empty +common /lroout/ obuf, op, otop, col, old_left_margin, buffer_empty +include "lroff.com" + +begin + if (buffer_empty == YES) + next_column = left_margin + else + next_column = col +end + + +# OUTCC -- Output a control sequence, i.e., a forms control sequence. +# Called only after a line has already been output. Does not interfere +# with output buffer. Sequence is not newline terminated. + +procedure outcc (out, ctrlchar) + +extern out() # user supplied line output procedure +int ctrlchar # character to be output (INT) +char ctrlstr[1] +include "lroff.com" + +begin + ctrlstr[1] = ctrlchar + ctrlstr[2] = EOS + call out (out_magic_arg, ctrlstr) +end + + +# OUTLINE -- Output a string and append a newline to flush the output buffer. + +procedure outline (out, text) + +extern out() +char text[ARB] +errchk outstr + +begin + call outstr (out, text) + call outc (out, '\n') +end diff --git a/pkg/system/help/lroff/rawcopy.x b/pkg/system/help/lroff/rawcopy.x new file mode 100644 index 00000000..d303b96e --- /dev/null +++ b/pkg/system/help/lroff/rawcopy.x @@ -0,0 +1,26 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "lroff.h" + +.help rawcopy +.nf ________________________________________________________________________ +RAWCOPY -- Copy an unformatted help block without modification, except +for moving to the desired left margin. Stop only when the .endhelp +directive is seen, or at EOF. Ignore all other directives. +.endhelp ___________________________________________________________________ + +procedure rawcopy (in, out, linebuf) + +extern in(), out() +char linebuf[ARB] +int ip, in(), input(), nextcmd() +errchk input, outline +include "lroff.com" + +begin + while (input (in, linebuf) != EOF) + if (nextcmd (linebuf, ip) == ENDHELP) + break + else + call outline (out, linebuf) +end diff --git a/pkg/system/help/lroff/section.x b/pkg/system/help/lroff/section.x new file mode 100644 index 00000000..3df732c8 --- /dev/null +++ b/pkg/system/help/lroff/section.x @@ -0,0 +1,224 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <chars.h> +include <ctype.h> +include "lroff.h" + +# NEW_SECTION -- Begin a section heading. Argument is the number of lines +# to skip. Output section heading string given on next input line. Reset left +# margin and cancel out any LS indents. + +procedure new_section (in, out, linebuf, ip) + +extern in(), out() +char linebuf[ARB] +int ip + +int inbold(), in(), lgetarg() +errchk skiplines, inbold, outline +include "lroff.com" + +begin + sh_nskip = lgetarg (linebuf, ip, sh_nskip) + call skiplines (out, sh_nskip) + left_margin = perm_left_margin + call testpage (out, DEF_TPNLINES) + + if (inbold (in, linebuf) != EOF) + call outline (out, linebuf) + + call init_ls() +end + + +# NEW_NUMBERED_SECTION -- Begin a numbered section heading. Arguments are +# the number of lines to skip and the section level to be incremented (default +# is 1). If only one arg is given, we assume it is the section level. +# Output section number followed by section heading string given on next input +# line. Reset left margin and cancel out any LS indents. + +procedure new_numbered_section (in, out, linebuf, ip) + +extern in(), out() +char linebuf[ARB] +int ip + +int i, n +int inbold(), in(), lgetarg(), strlen() +errchk skiplines, sprintf, pargi, outstr, outc, inbold, outline +include "lroff.com" + +begin + # Get level, nskip arguments. + n = max (1, min (MAX_NHLEVEL, lgetarg (linebuf, ip, 1))) + nh_nskip = lgetarg (linebuf, ip, nh_nskip) + + call skiplines (out, nh_nskip) + left_margin = perm_left_margin + call testpage (out, DEF_TPNLINES) + + # Increment the desired section number; zero all higher numbered + # section counters. + + nh_level[n] = nh_level[n] + 1 + call amovki (0, nh_level[n+1], MAX_NHLEVEL - n) + + # Output the section number followed by a blank and then the section + # label. + + linebuf[1] = EOS + do i = 1, n { + call sprintf (linebuf[strlen(linebuf)+1], SZ_IBUF, "%d.") + call pargi (nh_level[i]) + } + + # Cancel the final "." if subsection heading. Add a blank. + if (n > 1 && linebuf[strlen(linebuf)] == '.') + linebuf[strlen(linebuf)] = EOS + call outstr (out, linebuf) + call outc (out, BLANK) + + # Get section label from next input line, write that out on the same + # line in standout mode, then terminate the line. + + if (inbold (in, linebuf) != EOF) + call outline (out, linebuf) + + call init_ls() +end + + +# INIT_NH -- Initialize section numbering. + +procedure init_nh() + +include "lroff.com" + +begin + call amovki (0, nh_level, MAX_NHLEVEL) +end + + +# NEW_INDENTED_SECTION -- Begin an indented section heading. Optional +# arguments are the number of spaces to indent subsequent text and the number +# of lines to skip. Output section heading string given on next input line. +# Reset left margin and cancel out any LS indents. + +procedure new_indented_section (in, out, linebuf, ip) + +extern in(), out() +char linebuf[ARB] +int ip + +int inbold(), in(), lgetarg() +errchk skiplines, inbold, outline +include "lroff.com" + +begin + ih_indent = lgetarg (linebuf, ip, ih_indent) + ih_nskip = lgetarg (linebuf, ip, ih_nskip) + + call skiplines (out, ih_nskip) + left_margin = perm_left_margin + call testpage (out, DEF_TPNLINES) + + # Read in and output the section heading in boldface. + if (inbold (in, linebuf) != EOF) + call outline (out, linebuf) + + # Reset the left margin and cancel out any LS indents. + left_margin = max (perm_left_margin, min (right_margin, + perm_left_margin + ih_indent)) + + call init_ls() +end + + +# INBOLD -- Input a line in standout mode. If the line is already all in +# upper case, do not use standout mode. The input procedure processes +# all font escape sequences. We must get the raw input line by calling the +# user input procedure, then pass it on to input() enclosed in \fB...\fR +# font escape sequences, to enable standout mode. + +int procedure inbold (in, user_linebuf) + +extern in() +int in() +char user_linebuf[ARB] + +pointer sp, ip, lbuf, first +int save_in_magic_arg, status +int stropen(), input() +extern getline() +errchk salloc, stropen, input +include "lroff.com" + +begin + call smark (sp) + call salloc (lbuf, SZ_LINE + 3 + 3, TY_CHAR) + + # Deposit escape sequence to turn bold on. + call strcpy ("\\fB", Memc[lbuf], ARB) + + # Read in the input line after the three char escape sequence. + if (in (in_magic_arg, Memc[lbuf+3]) == EOF) { + call sfree (sp) + return (EOF) + } + + # Scan the line to see if there are any lower case characters. + # If all upper case, omit the mode control sequences (this procedure + # becomes equivalent to input()). + + first = lbuf + 3 + for (ip=lbuf+3; Memc[ip] != EOS; ip=ip+1) + if (IS_LOWER (Memc[ip])) { + first = lbuf + break + } + + # Step on the newline if there is one, then add the \fR + # sequence to turn bold off. + if (first == lbuf) { + for (ip=lbuf; Memc[ip] != EOS; ip=ip+1) + ; + if (Memc[ip-1] == '\n') + Memc[ip-1] = EOS + call strcat ("\\fR\n", Memc[lbuf], ARB) + } + + # Now open the string as a file and call input to process it + # into our caller's buffer. We must save and restore the input + # magic argument, set to the fd of the string file when input is + # called. This is a good example of the disadvantages of commons... + + save_in_magic_arg = in_magic_arg + in_magic_arg = stropen (Memc[first], ARB, READ_ONLY) + status = input (getline, user_linebuf) + call close (in_magic_arg) + in_magic_arg = save_in_magic_arg + + call sfree (sp) + return (status) +end + + +# TESTPAGE -- If forms mode is enabled, output the control code for a test +# page followed by the number of lines to test for. Test page tests if the +# specified number of lines are left on a page, and breaks the page if not. + +procedure testpage (out, nlines) + +extern out() +int nlines +char ctrlstr[2] +include "lroff.com" + +begin + if (foflag == YES) { + ctrlstr[1] = FC_TESTPAGE + ctrlstr[2] = nlines + ctrlstr[3] = EOS + call out (out_magic_arg, ctrlstr) + } +end diff --git a/pkg/system/help/lroff/skiplines.x b/pkg/system/help/lroff/skiplines.x new file mode 100644 index 00000000..0449dc50 --- /dev/null +++ b/pkg/system/help/lroff/skiplines.x @@ -0,0 +1,19 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "lroff.h" + +# SKIPLINES -- Skip one or more lines on the output, i.e., break the current +# output line and add a few empty lines. + +procedure skiplines (out, nlines) + +extern out() +int nlines, i +errchk breakline, outc + +begin + call breakline (out, NJ) + + do i = 1, nlines + call outc (out, '\n') +end diff --git a/pkg/system/help/lroff/textlen.x b/pkg/system/help/lroff/textlen.x new file mode 100644 index 00000000..e192314f --- /dev/null +++ b/pkg/system/help/lroff/textlen.x @@ -0,0 +1,20 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <chars.h> +include "lroff.h" + +# TEXTLEN -- Return the number of printable characters in a text string. + +int procedure textlen (text_string) + +char text_string[ARB] +int ip, nchars + +begin + nchars = 0 + for (ip=1; text_string[ip] != EOS; ip=ip+1) + if (!INVISIBLE (text_string[ip])) + nchars = nchars + 1 + + return (nchars) +end diff --git a/pkg/system/help/lroff/textout.x b/pkg/system/help/lroff/textout.x new file mode 100644 index 00000000..663bccc8 --- /dev/null +++ b/pkg/system/help/lroff/textout.x @@ -0,0 +1,140 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <chars.h> +include "lroff.h" + +# TEXTOUT -- Process a line of text. Move words from the text buffer into +# the word buffer WBUF, maintaining an array of pointers to the words, until +# an output line has been filled. Leading whitespace is part of the word, +# if it is the first word on a line (thus we get paragraph indents). +# Thereafter only trailing whitespace is included in the word. The last word +# on a line gets one trailing space, unless the last char is a period, in which +# case it gets two. Otherwise whitespace at the end of the input text line is +# stripped. BREAKLINE is subsequently called to reassemble the words to form +# an output line. +# +# WBUF is the word buffer (a set of strings separated by EOS markers). WP is +# a pointer to the next available char in WBUF. NWORDS is the number of words +# in the buffer. WORDS is a pointer to the array of word pointers. We do not +# check for word buffer overflow because the word buffer is allocated large +# enough to accommodate the worst case (the buffer is flushed when an output +# line is filled, which always happens before the buffer overflows). WCOLS is +# the number of printable characters in the word buffer. The word buffer +# variables are all stored in the "words" common for use by TEXTOUT and +# BREAKLINE. Set_wordbuf() must be called upon startup and shutdown to +# allocate/deallocate the word buffer. + +procedure set_wordbuf (max_words) + +int max_words #I output word buffer size + +int word_buffer_size +errchk malloc + +include "lroff.com" +include "words.com" + +begin + word_buffer_size = (max_words * 2) + SZ_LINE # worst case + if (max_words <= 0 && words != NULL) { + call mfree (wbuf, TY_CHAR) + call mfree (words, TY_POINTER) + } else { + call malloc (wbuf, word_buffer_size, TY_CHAR) + call malloc (words, max_words, TY_POINTER) + wp = wbuf + nwords = 0 + wcols = 0 + } +end + + +# TEXTOUT -- Output a newline delimited line of text. + +procedure textout (out, text) + +extern out() +char text[1] + +char ch +int ip_save, wcols_save, ip +errchk breakline +include "lroff.com" +include "words.com" + +begin + if (wbuf == NULL || words == NULL) + call error (1, "No Lroff word buffer allocated") + + for (ip=1; text[ip] != EOS; ) { + # Set up descriptors of new word. Save the input pointer in case + # the output line fills and we have to "put the word back". + + Memi[words+nwords] = wp # word pointer + ip_save = ip + wcols_save = wcols + + # The following is a nop except at the beginning of a line. + for (; text[ip] == BLANK; ip=ip+1) { + Memc[wp] = BLANK + wp = wp + 1 + wcols = wcols + 1 + } + + # Copy the word itself. + for (ch=text[ip]; ch != BLANK && ch != EOS; ch=text[ip]) { + Memc[wp] = ch + wp = wp + 1 + if (!INVISIBLE (ch)) + wcols = wcols + 1 + ip = ip + 1 + } + + # And then any trailing whitespace. + for (; text[ip] == BLANK; ip=ip+1) { + Memc[wp] = BLANK + wp = wp + 1 + wcols = wcols + 1 + } + + # End of word string. + Memc[wp] = EOS + wp = wp + 1 + + # If line has been filled, call breakline to format output line + # and send it out. Put word which caused break back for next line. + # Do not put word back if it is the first word, or we will have + # an infinite loop. + if (wcols > (right_margin - left_margin + 1) && nwords > 0) { + ip = ip_save + wcols = wcols_save + wp = Memi[words+nwords] + call breakline (out, JU) + } else + nwords = nwords + 1 + } + + # Strip trailing whitespace at the end of an input line. If input + # line ends with a period, assume it is a sentence and add a blank. + # Otherwise add a blank to separate words when output line is filled. + # If a sentence ends within a line, the user is responsible for placing + # two spaces after the period. + + if (nwords > 0) { + for (wp=wp-2; Memc[wp] == BLANK && wp > wbuf; wp=wp-1) + wcols = wcols - 1 + if (Memc[wp] == '.') { + wp = wp + 1 + Memc[wp] = BLANK + wcols = wcols + 1 + } + wp = wp + 1 # point to next avail + + Memc[wp] = BLANK # need at least one + wp = wp + 1 + wcols = wcols + 1 + + Memc[wp] = EOS + wp = wp + 1 + } +end diff --git a/pkg/system/help/lroff/words.com b/pkg/system/help/lroff/words.com new file mode 100644 index 00000000..d0c220da --- /dev/null +++ b/pkg/system/help/lroff/words.com @@ -0,0 +1,9 @@ +# Common for Textout()/Breakline(). + +pointer wbuf # the word buffer, a string buffer +pointer wp # pointer to next available char in word buffer +pointer words # array of word pointers +int nwords # number of words in word buffer +int wcols # number of printable columns in word buffer + +common /wrdcom/ wbuf, wp, words, nwords, wcols diff --git a/pkg/system/help/manout.x b/pkg/system/help/manout.x new file mode 100644 index 00000000..b81abc8b --- /dev/null +++ b/pkg/system/help/manout.x @@ -0,0 +1,330 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <chars.h> +include <ctype.h> +include "help.h" + +.help man_output, man_close +.nf ___________________________________________________________________________ +Process a stream of output lines containing forms control codes. This mode is +used when manual page format is desired. Input is a sequence of manual pages. +A manual page consists of a formfeed, a two line page header, and then an +arbitrary number of lines of text. Pages are broken every H_NLPP lines, +the page header is printed at the top of each page, and the page number is +printed at the bottom of each page. The following special directives may +be inserted in the text as control character forms codes; the forms code must +be the first character in a line but may be followed by text. + + FC_BREAKPAGE Start a new page, unless already at the + top of a page. + + FC_TESTPAGE n Test if there are at least N (binary code) + lines left on the page. If no, break the + page before more text is output. + + FC_STARTKEEP Start spooling lines into an internal buffer. + Try to output the keep block all on one page. + + FC_ENDKEEP Stop spooling and output the keep block. + +MAN_CLOSE should be called at program termination to return buffer space and +reinit variables. +.endhelp ______________________________________________________________________ + +define LEN_HEADER 2 +define LEN_FOOTER 3 +define LEN_KEEP 1024 +define SZ_PAGELABEL 6 +define SZ_HEADER_GAP 2 + +define IN_HEADER 1 +define IN_TEXT 2 +define IN_KEEP 3 +define FLUSH_KEEP 4 + + +# MAN_OUTPUT -- Output a line, optionally preceded by one or more forms control +# characters. Start a new manual page, save lines in header, save lines in keep +# buffer, or write line to output. + +procedure man_output (fd, lbuf, nlines_per_page, lmargin, rmargin) + +int fd # output file +char lbuf[ARB] # next output line +int nlines_per_page +int lmargin, rmargin + +char end_keep_chars[3] +int ip, mode, max_lineno, i + +int nlines_in_keep, nlines_in_header, init +int lineno, pageno, center_col, nlpp +pointer header_lines[LEN_HEADER], keep_lines[LEN_KEEP] +common /hlpman/ lineno, pageno, nlpp, center_col, init, + nlines_in_header, nlines_in_keep, header_lines, keep_lines + +int stridx() +pointer man_putstr() +data end_keep_chars /FC_STARTKEEP, FC_BREAKPAGE, '\f', EOS/ + +begin + if (init == YES) { + # Initialize internal variables. + lineno = 0 + pageno = 0 + mode = IN_TEXT + nlines_in_header = 0 + nlines_in_keep = 0 + nlpp = nlines_per_page + max_lineno = max(1, min(LEN_KEEP, nlpp - LEN_FOOTER)) + center_col = (lmargin + rmargin) / 2 + init = NO + } + + for (ip=1; lbuf[ip] != EOS; ) { + switch (mode) { + + case IN_HEADER: + # Just started a new manual page; still accumulating header + # lines. Forms control chars not recognized in header area. + # Output header to start new page as soon as we have all the + # lines. + + nlines_in_header = nlines_in_header + 1 + header_lines[nlines_in_header] = man_putstr (lbuf[ip]) + if (nlines_in_header == LEN_HEADER) { + mode = IN_TEXT + call man_breakpage (fd, header_lines, nlines_in_header, + lineno, pageno, nlpp, center_col) + pageno = 1 + } + break + + case IN_KEEP: + # Any forms control character in a keep ends the keep, in case + # the KE is missing. Don't bump input pointer unless sentinel + # is ENDKEEP, else forms control character will be skipped. + + if (lbuf[ip] == FC_ENDKEEP) { + mode = FLUSH_KEEP + ip = ip + 1 + } else if (stridx (lbuf[ip], end_keep_chars) > 0) { + mode = FLUSH_KEEP + } else if (lineno + nlines_in_keep > max_lineno) { + mode = FLUSH_KEEP + } else { + # Put line in keep buffer. + nlines_in_keep = nlines_in_keep + 1 + keep_lines[nlines_in_keep] = man_putstr (lbuf[ip]) + break + } + + case FLUSH_KEEP: + # Break page and output header if insufficient room left on + # page. + if (lineno + nlines_in_keep > max_lineno) + call man_breakpage (fd, header_lines, nlines_in_header, + lineno, pageno, nlpp, center_col) + + # Output contents of keep buffer and return buffer space. + for (i=1; i <= nlines_in_keep; i=i+1) { + call putline (fd, Memc[keep_lines[i]]) + call mfree (keep_lines[i], TY_CHAR) + lineno = lineno + 1 + } + nlines_in_keep = 0 + mode = IN_TEXT + + case IN_TEXT: + # Not in any special mode. Check for forms chars and loop if + # one is found. Otherwise output line and bump line pointer. + # Break page when it fills. + + switch (lbuf[ip]) { + case FC_BREAKPAGE: + call man_breakpage (fd, header_lines, nlines_in_header, + lineno, pageno, nlpp, center_col) + ip = ip + 1 + + case FC_TESTPAGE: + # The first char following the testpage forms control char + # is the number of lines to test for, in binary. + + if (lineno + lbuf[ip+1] > max_lineno) + call man_breakpage (fd, header_lines, nlines_in_header, + lineno, pageno, nlpp, center_col) + ip = ip + 2 + + case FC_STARTKEEP: + mode = IN_KEEP + ip = ip + 1 + case FC_ENDKEEP: + ip = ip + 1 + + case '\f': + # Start accumulating new header. Page cannot be broken + # until we have the header. + + for (i=1; i <= nlines_in_header; i=i+1) + call mfree (header_lines[i], TY_CHAR) + nlines_in_header = 0 + mode = IN_HEADER + ip = ip + 1 + + default: + # This is the case that gets called most often; output an + # ordinary line, not in any special mode. Eat blank lines + # at top of page. + + if (lineno <= nlines_in_header + SZ_HEADER_GAP + 1) { + for (i=ip; IS_WHITE (lbuf[i]); i=i+1) + ; + if (lbuf[i] == '\n' || lbuf[i] == EOS) + break + } + call putline (fd, lbuf[ip]) + lineno = lineno + 1 + if (lineno > max_lineno) + call man_breakpage (fd, header_lines, nlines_in_header, + lineno, pageno, nlpp, center_col) + break + } + } + } +end + + +# MAN_INIT -- Called to initialize the manpage internal data structures. + +procedure man_init() + +int i +bool first_time +data first_time /true/ + +int nlines_in_keep, nlines_in_header, init +int lineno, pageno, center_col, nlpp +pointer header_lines[LEN_HEADER], keep_lines[LEN_KEEP] +common /hlpman/ lineno, pageno, nlpp, center_col, init, + nlines_in_header, nlines_in_keep, header_lines, keep_lines + +begin + # Clean up in the event of an interrupt. + if (!first_time) { + for (i=1; i <= nlines_in_header; i=i+1) + call mfree (header_lines[i], TY_CHAR) + for (i=1; i <= nlines_in_keep; i=i+1) + call mfree (keep_lines[i], TY_CHAR) + } + + init = YES + first_time = false +end + + +# MAN_CLOSE -- Called at program termination to write the page number at the +# bottom of the last manual page. + +procedure man_close (fd) + +int fd +int nlines_in_keep, nlines_in_header, i +int lineno, pageno, center_col, nlpp, init +pointer header_lines[LEN_HEADER], keep_lines[LEN_KEEP] +common /hlpman/ lineno, pageno, nlpp, center_col, init, + nlines_in_header, nlines_in_keep, header_lines, keep_lines + +begin + if (init == YES) + return + + # Trash any data in keep buffer if missing the KE by the time we are + # called (at program termination). + + call man_breakpage (fd, header_lines, 0, lineno, pageno, nlpp, + center_col) + + for (i=1; i <= nlines_in_header; i=i+1) + call mfree (header_lines[i], TY_CHAR) + for (i=1; i <= nlines_in_keep; i=i+1) + call mfree (keep_lines[i], TY_CHAR) + + nlines_in_header = 0 + nlines_in_keep = 0 + init = YES +end + + +# MAN_BREAKPAGE -- Advance to bottom of page, print page number, bump page +# number, init line counter, formfeed, output page header of new page. + +procedure man_breakpage (fd, header_lines, nlines_in_header, lineno, pageno, + nlines_per_page, center_col) +int fd +pointer header_lines[ARB] +int nlines_in_header +int lineno, pageno +int nlines_per_page +int center_col + +char pagelabel[SZ_PAGELABEL] +int i, destcol +int strlen() + +begin + # Output page footer if there is anything on the page and if there + # was a page header. + + if (lineno > 0 && nlines_in_header > 0) { + while (lineno <= nlines_per_page - 1) { + call putline (fd, "\n") + lineno = lineno + 1 + } + + call sprintf (pagelabel, SZ_PAGELABEL, "-%d-") + call pargi (pageno) + + destcol = max (1, center_col - strlen (pagelabel) / 2) + for (i=1; i < destcol; i=i+1) + call putci (fd, ' ') + call putline (fd, pagelabel) + call putci (fd, '\n') + } + + # Break page and output page header if there are any header lines. + # Leave two blank lines between header and first line of text. + + if (nlines_in_header > 0) { + if (pageno > 0) + call putci (fd, '\f') + lineno = 1 + pageno = pageno + 1 + + for (i=1; i <= nlines_in_header; i=i+1) { + call putline (fd, Memc[header_lines[i]]) + lineno = lineno + 1 + } + for (i=1; i <= SZ_HEADER_GAP; i=i+1) { + call putline (fd, "\n") + lineno = lineno + 1 + } + } +end + + +# MAN_PUTSTR -- Save a string on the heap and return a pointer to the string. + +pointer procedure man_putstr (str) + +char str[ARB] +int nchars +pointer bp +int strlen() + +begin + nchars = strlen (str) + call malloc (bp, nchars, TY_CHAR) + call strcpy (str, Memc[bp], nchars) + + return (bp) +end diff --git a/pkg/system/help/mkhelpdb.hlp b/pkg/system/help/mkhelpdb.hlp new file mode 100644 index 00000000..d3534cf6 --- /dev/null +++ b/pkg/system/help/mkhelpdb.hlp @@ -0,0 +1,75 @@ +.help mkhelpdb Feb89 softools +.ih +NAME +mkhelpdb -- update the help database +.ih +USAGE +mkhelpdb helpdir helpdb +.ih +PARAMETERS +.ls helpdir = "lib$root.hd" +The filename of the root help directory file (".hd" file) defining the +help tree to be updated. By convention this is \fIroot.hd\fR in some +directory. +.le +.ls helpdb = "lib$helpdb.mip" +The filename of the help database file to be written. By convention this +is \fIhelpdb.mip\fR in some directory (the ".mip" signifies that the file +format is machine independent). +.le +.ls verbose = no +If this switch is enabled, \fImkhelpdb\fR will print a detailed description +of the help database as it is being compiled. A more concise summary listing +only the packages and the number of help modules in each package is printed +by default. +.le +.ih +DESCRIPTION +The \fImkhelpdb\fR task descends a tree of help directory (".hd") files and +compiles a binary help database from the information therein. The help +database is used to speed global searches when help is requested for a +module, the ".hlp" file for which might be anywhere in the system. +The help database defines the packages and modules in the help database, +and stores the filenames of the associated help files. No actual help text +is stored in the help database, only sufficient index information to find +the help files when the \fIhelp\fR task is run. The help directory files +are text files which define the packages and modules in the help database. +The format of these files is self explanatory hence is documented by example +only. + +By default, \fImkhelpdb\fR recompiles the standard IRAF help database, +although any other similar database may be recompiled by changing the values +of the parameters \fIhelpdir\fR and \fIhelpdb\fR. The standard +IRAF help database is rooted in the file \fBlib$root.hd\fR. + +The help database must be updated whenever a new help module (e.g., manual +page) is added, deleted, or renamed. It is also necessary for sites receiving +a source only version of IRAF to run \fImkhelpdb\fR to rebuild the help +database once the system is up, since the database is a binary file and +is not included in a source only distribution. It is not necessary to rerun +\fImkhelpdb\fR when an existing manual page is edited, since only index +information is stored in the database. + +The \fIhelp\fR utilities make use of the following types of files. Examples +of these files will be found throughout the IRAF directories. + +.nf + .hd help directory file (tree structured) + .hlp manual page + .men package menu (module listing) +.fi +.ih +EXAMPLES +1. Update the standard IRAF help database. + +.nf + cl> softools + so> mkhelpdb helpdir=lib$root.hd helpdb=lib$helpdb.mip +.fi + +2. Update the NOAO package help database. + + so> mkhelpdb helpdir=noao$lib/root.hd helpdb=noao$lib/helpdb.mip +.ih +SEE ALSO +hdbexamine, help diff --git a/pkg/system/help/mkpkg b/pkg/system/help/mkpkg new file mode 100644 index 00000000..3cb437ec --- /dev/null +++ b/pkg/system/help/mkpkg @@ -0,0 +1,36 @@ +# Make the HELP and LROFF library modules. + +$checkout libpkg.a ../ +$update libpkg.a +$checkin libpkg.a ../ +$exit + +libpkg.a: + @lroff + @xhelp + + filetemp.x help.h <ctype.h> + getoption.x help.h <ctype.h> + hbgetblk.x help.h <ctype.h> + helpdb.x help.h helpdir.h <error.h> <finfo.h> <fset.h> <mach.h>\ + <time.h> + helpdir.x help.h helpdir.h <ctype.h> <error.h> + hinput.x help.h <ctype.h> + houtput.x help.h <ttyset.h> <chars.h> <fset.h> + manout.x help.h <chars.h> <ctype.h> + modlist.x help.h helpdir.h <ctype.h> <error.h> + modtemp.x help.h <ctype.h> + prblkhdr.x help.h + prdir.x help.h <error.h> <ttyset.h> + prfile.x help.h <finfo.h> <time.h> <ctype.h> + prfnames.x help.h helpdir.h + prhelp.x help.h helpdir.h <error.h> + prhlpblk.x help.h <error.h> + prmodname.x help.h + prsummary.x help.h + t_hdbexamine.x help.h <error.h> + t_help.x help.h <error.h> <fset.h> <finfo.h> + t_lroff.x + t_mkhelpdb.x <error.h> + tlist.x help.h <ctype.h> + ; diff --git a/pkg/system/help/modlist.x b/pkg/system/help/modlist.x new file mode 100644 index 00000000..dce63f59 --- /dev/null +++ b/pkg/system/help/modlist.x @@ -0,0 +1,200 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include <error.h> +include "help.h" +include "helpdir.h" + +.help modlist +.nf ___________________________________________________________________________ +MODLIST -- Routines for expanding a template into a list of module names, +and accessing successive elements of the list, given a template and a help +directory defining the pattern matching domain as input. + +The permissible complexity of a help template is somewhat less than that of +a file template; we do not have to deal with logical directories, virtual +file names, and list files. The class of characters permitted in a CL +module name is fairly limited. By the time we are called, the template +list will already have been expanded into a list of templates, wherein +each list element has a full package name (the package field has already +been expanded). Our job is to process a single template. + + * all modules + im* all modules whose names start with 'im' + [a-z]?* all modules beg. with lowercase letter + alpha all modules alpha* + +Note that a simple alphanumeric name like 'alpha' is treated as an +abbreviation, i.e., as 'alpha?*'. All occurrences of the closure metacharacter +* are converted to ?*, except after a character class. + +Entry points in this package include: + + ml_open set up to match and extract module names + ml_read get next module name which matches pattern + ml_close called when done to return buffers +.endhelp ______________________________________________________________________ + +define LEN_MLSTRUCT 165 # module list structure +define SZ_PATBUF 159 + +define ML_HP Memi[$1] # help directory +define ML_INDEX Memi[$1+1] # index of next module in helpdir +define ML_SIMPAT Memi[$1+2] # pattern is simple (no metacharacters) +define ML_PATBUF Memc[P2C($1+5)] # encoded pattern buffer + + +# ML_OPEN -- Set up to read module names from a directory which match +# a certain pattern. Allocate descriptor, save pointer to directory, +# encode pattern, rewind module index. + +pointer procedure ml_open (hp, template) + +pointer hp # help directory +char template[ARB] # "alpha", "*", etc. + +bool metachars +int ip +pointer ml, sp, pat, op +int patmake() + +begin + call smark (sp) + call salloc (pat, SZ_LINE, TY_CHAR) + + iferr (call calloc (ml, LEN_MLSTRUCT, TY_STRUCT)) + call erract (EA_FATAL) + ML_INDEX(ml) = 1 + ML_HP(ml) = hp + + # Match only at beginning of module name. Remember to scrap this + # metacharacter if matching a SIMPAT simple pattern. + + Memc[pat] = '^' + op = pat + 1 + + # If no metacharacters present in pattern set SIMPAT flag so that we + # can use a more efficient pattern matching algorithm. If closure + # metacharacter is present and it does not follow ], replace it with ?*. + + metachars = false + for (ip=1; template[ip] != EOS && op-pat < SZ_LINE; ip=ip+1) { + switch (template[ip]) { + case '?', '[', ']': + metachars = true + case '*': + metachars = true + if (ip == 1 || (ip > 1 && template[ip-1] != ']')) { + Memc[op] = '?' + op = op + 1 + } + } + Memc[op] = template[ip] + op = op + 1 + } + Memc[op] = EOS + + if (!metachars) { + ML_SIMPAT(ml) = YES + # Copy pattern string, stripping off the leading '^'. + call strcpy (Memc[pat+1], ML_PATBUF(ml), SZ_PATBUF) + } else { + ML_SIMPAT(ml) = NO + if (patmake (Memc[pat], ML_PATBUF(ml), SZ_PATBUF) == ERR) + call error (16, "Cannot encode help pattern") + } + + call sfree (sp) + return (ml) +end + + +# ML_READ -- Get next module name from help directory matching the +# encoded pattern. Return EOF when directory is exhausted. We directly +# access the HD structure for efficiency. + +int procedure ml_read (ml, modnum, module, maxch) + +pointer ml # pointer to module list descriptor +int modnum # module number (output) +char module[ARB] # module name (output) +int maxch + +bool match_found +char first_char +int m +pointer hp, sbuf, mp, modname +int patmatch(), ml_patmatch(), gstrcpy() +errchk patmatch + +begin + if (ml == NULL) + call error (17, "help.ml_read called with null descriptor") + hp = ML_HP(ml) + sbuf = HD_SBUF(hp) + first_char = ML_PATBUF(ml) + m = ML_INDEX(ml) + match_found = false + + # Scan down the list of modules in the package, returning the name + # of each matching the pattern in successive calls. Return EOF when + # the list is exhausted. + + while (m <= HD_NMODULES(hp)) { + mp = HD_MODULE(hp, m) + modname = sbuf + M_NAME(mp) + m = m + 1 + if (ML_SIMPAT(ml) == YES) { + if (Memc[modname] == first_char) + if (ml_patmatch (Memc[modname], ML_PATBUF(ml)) > 0) { + match_found = true + break + } + } else if (patmatch (Memc[modname], ML_PATBUF(ml)) > 0) { + match_found = true + break + } + } + + ML_INDEX(ml) = m + modnum = m - 1 + + # If no modules were found matching the template then we can only be + # at the end of the list. + + if (match_found) + return (gstrcpy (Memc[modname], module, maxch)) + else { + module[1] = EOS + return (EOF) + } +end + + +# ML_PATMATCH -- Determine if a SIMPAT simple pattern is an abbreviation of +# a module name. The pattern is simple, i.e., contains no metacharacters. + +int procedure ml_patmatch (module, pattern) + +char module[ARB] # module name to be compared to pattern +char pattern[ARB] # pattern of the form "^abbrev" +int ip + +begin + for (ip=1; pattern[ip] != EOS; ip=ip+1) + if (pattern[ip] != module[ip]) + return (0) + + return (1) +end + + +# ML_CLOSE -- Return buffers allocated by open_template. + +procedure ml_close (ml) + +pointer ml + +begin + call mfree (ml, TY_STRUCT) +end diff --git a/pkg/system/help/modtemp.x b/pkg/system/help/modtemp.x new file mode 100644 index 00000000..d539a2f2 --- /dev/null +++ b/pkg/system/help/modtemp.x @@ -0,0 +1,190 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include <syserr.h> +include "help.h" + +# DO_MODULE_TEMPLATE -- Called with a template defining the packages and +# modules for which help is desired, and the control parameters defining +# the type of help desired. Expand the template into a list of packages +# and modules and process the help for each module. +# +# Most of the work here is done by HD_LOAD, which opens and interprets a +# help directory, and TL_OPEN/TL_READ, which expand the template list. +# Each element of the template list is a module matching pattern for a +# single package. When this is expanded we get the names of the individual +# modules and call PRINT_HELP to print the help text for a single module +# of a particular package. In the worst case (template "*.*"), we might +# process all modules in the help database. + +procedure do_module_template (db, tlist, ctrl) + +pointer db # help database to be used +char tlist[ARB] # template list ("a.*,b.*,...") +pointer ctrl # Help control structure + +int m, pk +bool no_matches, matchall +pointer sp, fname, template, module, pakname, modtemp, curmod +pointer hp_sys, hp_pak, tl, ip, op, modlist + +bool strne() +int tl_read(), ml_read(), print_help() +int stridxs(), ml_patmatch(), hd_findmod(), hd_getname() +pointer hdb_load(), tl_open(), ml_open() +errchk tl_read, hd_findmod, hd_getname, ml_read, hdb_load +errchk tl_open, ml_open, print_help + +begin + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (template, SZ_LINE, TY_CHAR) + call salloc (module, SZ_FNAME, TY_CHAR) + call salloc (pakname, SZ_FNAME, TY_CHAR) + call salloc (modtemp, SZ_FNAME, TY_CHAR) + call salloc (curmod, SZ_FNAME, TY_CHAR) + + # The help database contains the package names and references to + # all help modules in the package. Load the help database index + # ("_index") which contains a list of all packages in the database. + + hp_sys = hdb_load (db, "_index") + + # Expand the template list into a list of simple "pak.mod" + # templates, where the package name is spelled out and only + # the module template remains to be expanded. The null + # template list gets turned into "curpack.". + + tl = tl_open (db, hp_sys, tlist, ctrl) + Memc[curmod] = EOS + no_matches = true + matchall = (H_ALLMODULES(ctrl) == YES) + + # Process each "package_name.module_template" element of the TL + # list. The package_name field is always valid. If the module + # field is null, package help is desired, so print help on the + # package as if it were a module. Otherwise, expand the module + # template for the package and process help on each module. + + while (tl_read (tl, Memc[template], SZ_FNAME) != EOF) { + # Extract package name. + op = pakname + for (ip=template; IS_WHITE(Memc[ip]); ip=ip+1) + ; + for (; Memc[ip] != '.' && Memc[ip] != EOS; ip=ip+1) { + Memc[op] = Memc[ip] + op = op + 1 + } + Memc[op] = EOS + + # Extract module template. + op = modtemp + if (Memc[ip] == '.') + ip = ip + 1 + for (; Memc[ip] != EOS; ip=ip+1) { + Memc[op] = Memc[ip] + op = op + 1 + } + Memc[op] = EOS + + # The following is used to count the number of matches for a module + # (used to generate the "No help available" message). The + # template list will typically contain sequences like "curpak.mod", + # "paki.", "pakj.", "pak1.mod", "pak2.mod", and so on (where the + # pak[ij] are the full names of packages matched by an ambiguous + # template). Reset no_matches whenever the module name changes. + # If the module name disappears, i.e., if the template is a package + # name, then we have a match if the old module name is an + # abbreviation for the package. + + if (Memc[curmod] == EOS || strne(Memc[modtemp],Memc[curmod])) { + if (Memc[modtemp] == EOS) { + if (ml_patmatch (Memc[pakname], Memc[modtemp]) > 0) + no_matches = false + } else { + if (no_matches && Memc[curmod] != EOS) { + call eprintf ("No help available for `%s'\n") + call pargstr (Memc[curmod]) + } + no_matches = true + call strcpy (Memc[modtemp], Memc[curmod], SZ_FNAME) + } + } + + # Search system help directory for the named package. If it + # cannot be found it is not an error if the original template + # was ambiguous (did not have a "."). A package reference is + # always generated for an ambiguous template because we do not + # know what the user wants help for. + + pk = hd_findmod (hp_sys, Memc[pakname]) + if (pk == 0) { + if (Memc[modtemp] == EOS) + if (stridxs (".", tlist) != 0) { + call eprintf ("Package `%s' not in Help database\n") + call pargstr (Memc[pakname]) + } + next + } + + # If module template is null, user wants help on the package + # itself; print help on the package as a module of hp_sys. + # Otherwise expand the module template and print help on each + # module. + + if (Memc[modtemp] == EOS) { + if (print_help (db, hp_sys, Memc[pakname], pk, ctrl) == ERR) { + call eprintf ("No help available for package `%s'\n") + call pargstr (Memc[pakname]) + } + } else { + # Get name of package helpdir for package `pk'. + if (hd_getname (hp_sys,pk,TY_PKG,Memc[fname],SZ_FNAME) == 0) { + call eprintf ("No help available for package `%s'\n") + call pargstr (Memc[pakname]) + next + } + + # Open the help directory for the package, then open the + # template. + + iferr (hp_pak = hdb_load (db, Memc[fname])) + next + modlist = ml_open (hp_pak, Memc[modtemp]) + + # Process each module matching the module template. The QUIT + # flag is set if the user responds no to the "more" query + # between help blocks or files. + + while (ml_read (modlist, m, Memc[module], SZ_FNAME) != EOF) { + if (print_help (db, hp_pak, Memc[module], m, ctrl) == OK) { + no_matches = false + if (!matchall) + break + } + if (H_QUIT(ctrl) == YES) + break + } + + call ml_close (modlist) + call hdb_free (db, hp_pak) + } + + if (H_QUIT(ctrl) == YES) + break + else if (!matchall && !no_matches) + break + } + + # A final check for no matches is necessary for the last module in + # the template list. + + if (no_matches && Memc[curmod] != EOS) { + call eprintf ("No help available for `%s'\n") + call pargstr (Memc[curmod]) + } + + call tl_close (tl) + call hdb_free (db, hp_sys) + call sfree (sp) +end diff --git a/pkg/system/help/prblkhdr.x b/pkg/system/help/prblkhdr.x new file mode 100644 index 00000000..168965ab --- /dev/null +++ b/pkg/system/help/prblkhdr.x @@ -0,0 +1,80 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "help.h" + +# PR_BLOCK_HEADER -- Print the help block header. Clear screen first if +# enabled. Print header in the form +# +# MODNAME (section) title MODNAME (section) +# +# followed by a blank line. + +procedure pr_block_header (hb, modname, ctrl) + +pointer hb # encode help block header +char modname[ARB] # module name +pointer ctrl # help control block + +char blank +int n, center, offset, lmargin, rmargin +pointer sp, lbuf, edge, op, hbuf +int strlen(), gstrcpy() + +begin + call smark (sp) + call salloc (lbuf, SZ_LINE, TY_CHAR) + call salloc (edge, SZ_LINE, TY_CHAR) + call salloc (hbuf, SZ_LINE, TY_CHAR) + + # Clear screen. + if (H_FORMAT(ctrl) == HF_TEXT) { + if (H_SOFLAG(ctrl) == YES) + call houtput (ctrl, "\f") + } else { + call sfree (sp) + return + } + + lmargin = H_LMARGIN(ctrl) + rmargin = min (H_RMARGIN(ctrl), SZ_LINE-1) + + # Initialize the output line to blanks. + blank = ' ' + call amovkc (blank, Memc[lbuf], SZ_LINE) + + n = strlen (HB_TITLE(hb)) + center = (lmargin + rmargin) / 2 + offset = max (lmargin, center - n/2) + + # Center help block title in output line. + call amovc (HB_TITLE(hb), Memc[lbuf+offset], min(n,rmargin-offset)) + + # Format the MODNAME (section) into the "edge" buffer. MODNAME is the + # module name (one of the keys), transformed to upper case. + + if (HB_NKEYS(hb) >= 1) { + op = edge + gstrcpy (modname, Memc[edge], SZ_LINE) + call strupr (Memc[edge]) + } else { + Memc[edge] = EOS + op = edge + } + + if (HB_SECTION(hb) != EOS) { + call sprintf (Memc[op], SZ_LINE-SZ_KEY, " (%s)") + call pargstr (HB_SECTION(hb)) + } + + n = strlen (Memc[edge]) + call amovc (Memc[edge], Memc[lbuf+lmargin-1], n) + call amovc (Memc[edge], Memc[lbuf + rmargin - n], n) + + Memc[lbuf+rmargin] = '\n' + Memc[lbuf+rmargin+1] = EOS + + # Write out the header line, followed by a blank line. + call houtput (ctrl, Memc[lbuf]) + call houtput (ctrl, "\n") + + call sfree (sp) +end diff --git a/pkg/system/help/prdir.x b/pkg/system/help/prdir.x new file mode 100644 index 00000000..08322522 --- /dev/null +++ b/pkg/system/help/prdir.x @@ -0,0 +1,108 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ttyset.h> +include <error.h> +include "help.h" + +# PR_DIRECTORY -- Print a directory of the help blocks for a package. +# Extract the names of all the modules therein into a string buffer +# and print it as a table. + +define SZ_OBUF 2048 # buffer for directory +define MAX_MODULES 500 # max modules that can be sorted +define MAX_NAMELEN 20 # max chars in a module name +define FIRST_COL 6 +define exit_ 90 + + +procedure pr_directory (db, hp, pakname, paknum, ctrl) + +pointer db # help database descriptor +pointer hp # root help directory +char pakname[ARB] # name of package +int paknum # package number in root directory +pointer ctrl # help control params + +bool multiple_directories +int m, fd +pointer sp, indices, hdr, fname, hp_pak, lbuf, obuf + +int hd_getname(), ttystati(), stropen(), getline() +pointer hdb_load() +errchk hd_getname, ttystati + +begin + call smark (sp) + call salloc (indices, MAX_MODULES, TY_POINTER) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (hdr, SZ_FNAME, TY_CHAR) + call salloc (obuf, SZ_OBUF, TY_CHAR) + call salloc (lbuf, SZ_LINE, TY_CHAR) + + # Get the filename of the help directory for the package. + if (hd_getname (hp,paknum,TY_PKG,Memc[fname],SZ_FNAME) == 0) { + call eprintf ("No help available for package `%s'\n") + call pargstr (pakname) + goto exit_ + } + + # Open the help directory for the package. + iferr (hp_pak = hdb_load (db, Memc[fname])) { + call sfree (sp) + call erract (EA_WARN) + goto exit_ + } + + # Extract the names of the modules in the package. Save the pointers + # in an array for the table print routine. + + for (m=0; m < MAX_MODULES; m=m+1) { + call salloc (Memi[indices+m], MAX_NAMELEN, TY_CHAR) + if (hd_getname (hp_pak, m+1, TY_MODNAME, Memc[Memi[indices+m]], + MAX_NAMELEN) == 0) + break + } + + # If the template supplied by the user specified more than a single + # package, print the name of the package. + + multiple_directories = (H_LENTL(ctrl) > 1) + + # We may have been called with any legal abbreviation of the package + # name; fetch the full name from the system package directory. + + if (multiple_directories) { + call houtput (ctrl, "\n") + if (hd_getname (hp, paknum, TY_MODNAME, Memc[hdr], SZ_FNAME) != 0) { + call strcat (":\n", Memc[hdr], SZ_FNAME) + call houtput (ctrl, Memc[hdr]) + } + } + + # Now print the table. It is not necessary to sort the table, + # because the "helpdir" code (which reads the help directory) has + # already done so. The directory is written into a string buffer + # and then output line by line with houtput, since there is no + # easy way to make STRTBL call houtput. + + # Format the table into the buffer. A blank line marks the end of + # the table. + + fd = stropen (Memc[obuf], SZ_OBUF, NEW_FILE) + call strtbl (fd, Memc, Memi[indices], m, FIRST_COL, + ttystati (H_TTY(ctrl), TTY_NCOLS), MAX_NAMELEN, 0) + call putline (fd, "\n") + call close (fd) + + # Copy lines from the buffer to the HELP output. Do not read off + # end of buffer or FIO will file fault and abort. + + fd = stropen (Memc[obuf], SZ_OBUF, READ_ONLY) + while (getline (fd, Memc[lbuf]) > 1) + call houtput (ctrl, Memc[lbuf]) + call close (fd) + + call hdb_free (db, hp_pak) +exit_ + call sfree (sp) +end diff --git a/pkg/system/help/prfile.x b/pkg/system/help/prfile.x new file mode 100644 index 00000000..8ecf1af1 --- /dev/null +++ b/pkg/system/help/prfile.x @@ -0,0 +1,84 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <finfo.h> +include <time.h> +include <ctype.h> +include "help.h" + +# PR_FILE -- Print a file. Called to print menu files and source files. +# Do not print block header, but do page output if enabled by user. + +procedure pr_file (fname, ctrl, pakname) + +char fname[ARB] +pointer ctrl +char pakname[ARB] + +int center_col, ip +long fi[LEN_FINFO] +pointer sp, lbuf, time +int open(), hinput(), strlen(), finfo() +errchk houtput, open, hinput + +begin + call smark (sp) + call salloc (lbuf, SZ_LINE, TY_CHAR) + call salloc (time, SZ_TIME, TY_CHAR) + + H_EOF(ctrl) = NO + H_RAWIN(ctrl) = YES + center_col = (H_LMARGIN(ctrl) + H_RMARGIN(ctrl)) / 2 + + # Clear screen and print filename if printing source file. + # Filename is printed centered between left and right margins. + # Note header must be two lines for man_output(). + + if (H_OPTION(ctrl) == O_SOURCE) { + if (finfo (fname, fi) == ERR) { + call sprintf (Memc[lbuf], SZ_LINE, "%s `%s'") + call pargstr ("Cannot get file info for file") + call pargstr (fname) + call error (20, Memc[lbuf]) + } + call cnvtime (FI_MTIME(fi), Memc[time], SZ_TIME) + + # Header format: "FILE date FILE". + call sprintf (Memc[lbuf], SZ_LINE, "%*t%s %*t%s %*t%s\n") + call pargi (H_LMARGIN(ctrl)) + call pargstr (fname) + call pargi (center_col - strlen(Memc[time]) / 2) + call pargstr (Memc[time]) + call pargi (H_RMARGIN(ctrl) - strlen (fname) + 1) + call pargstr (fname) + + call houtput (ctrl, "\f") + call houtput (ctrl, Memc[lbuf]) + call houtput (ctrl, "\n") + } + + # Use hinput/houtput to read and print file so that output is + # paginated. + H_IN(ctrl) = open (fname, READ_ONLY, TEXT_FILE) + + while (hinput (ctrl, Memc[lbuf]) != EOF) { + if (H_OPTION(ctrl) == O_REFERENCES) { + # Replace the newline character. + ip = strlen (Memc[lbuf]) - 1 + Memc[lbuf+ip] = ' ' + + # Append the package name. + call strcat (" [", Memc[lbuf], SZ_LINE) + call strcat (pakname, Memc[lbuf], SZ_LINE) + call strcat ("]\n", Memc[lbuf], SZ_LINE) + + # Strip leading whitespace. + for (ip=0; IS_WHITE(Memc[lbuf+ip]); ip=ip+1) + ; + call houtput (ctrl, Memc[lbuf+ip]) + } else + call houtput (ctrl, Memc[lbuf]) + } + + call close (H_IN(ctrl)) + call sfree (sp) +end diff --git a/pkg/system/help/prfnames.x b/pkg/system/help/prfnames.x new file mode 100644 index 00000000..f4e42205 --- /dev/null +++ b/pkg/system/help/prfnames.x @@ -0,0 +1,69 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "help.h" +include "helpdir.h" + +# PR_FILENAMES -- Print file names associated with module. + +define NFILES 5 + +procedure pr_filenames (hp, module, modnum, ctrl) + +pointer hp +char module[ARB] +int modnum +pointer ctrl + +int i, nfiles, ftype[NFILES] +pointer sp, lbuf, pakname, modname, fname[NFILES] +int hd_getname() +errchk hd_getname, houtput +data ftype /TY_HLP, TY_SYS, TY_SRC, TY_PKG, TY_MEN/ +string fcode "hlpsyssrcpkgmen" + + +begin + call smark (sp) + call salloc (lbuf, SZ_LINE, TY_CHAR) + call salloc (pakname, SZ_FNAME, TY_CHAR) + call salloc (modname, SZ_FNAME, TY_CHAR) + + do i = 1, NFILES + call salloc (fname[i], SZ_PATHNAME, TY_CHAR) + + nfiles = 0 + do i = 1, NFILES + if (hd_getname (hp, modnum, ftype[i], Memc[fname[i]], + SZ_PATHNAME) > 0) + nfiles = nfiles + 1 + + if (nfiles > 0) { + # Get the package and module names. If there is no package name + # in the help directory, it is root help directory, and the module + # name is actually the name of a package. + + if (HD_PAKNAME(hp) == 0) { + call strcpy (module, Memc[pakname], SZ_FNAME) + Memc[modname] = EOS + } else { + call strcpy (Memc[HD_SBUF(hp) + HD_PAKNAME(hp)], + Memc[pakname], SZ_FNAME) + call strcpy (module, Memc[modname], SZ_FNAME) + } + + # Print "pakname.modname". + if (H_LENTL(ctrl) > 1) + call pr_modname (ctrl, Memc[pakname], Memc[modname]) + + # List the names of the help files. + do i = 1, NFILES + if (Memc[fname[i]] != EOS) { + call sprintf (Memc[lbuf], SZ_LINE, "\t%0.3s = %s\n") + call pargstr (fcode[(i-1)*3+1]) + call pargstr (Memc[fname[i]]) + call houtput (ctrl, Memc[lbuf]) + } + } + + call sfree (sp) +end diff --git a/pkg/system/help/prhelp.x b/pkg/system/help/prhelp.x new file mode 100644 index 00000000..7fba611d --- /dev/null +++ b/pkg/system/help/prhelp.x @@ -0,0 +1,144 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> +include "help.h" +include "helpdir.h" + +.help print_help +.nf __________________________________________________________________________ +PRINT_HELP -- Print help documentation for the named module or parameter. +We are called with the name of a single module; all fiddling with packages +and templates has been performed by the time we are called. The help +directory is open and contains the names of the files containing the help +source for the module. Our main task is to determine what kind of help +is desired and call the appropriate routine. + +Recall that the principal options are + + option meaning file + + help print help block for module hlp + param print help for single param hlp + section print a single section hlp + files print file names ... + source print source file src + sysdoc print system documentation sys + alldoc print all documentation hlp,sys + summary print help block titles hlp,sys +.endhelp ______________________________________________________________________ + +define exit_ 90 + + +# PRINT_HELP -- Print the indicated type of help text for the named module. +# If we are called the module exists in the package, but the type of help +# information indicated may not exist. Return OK if help is printed, ERR +# otherwise. + +int procedure print_help (db, hp, module, modnum, ctrl) + +pointer db # help database descriptor +pointer hp # help directory for package +char module[ARB] # name of module for which help is desired +int modnum # module number within package directory +pointer ctrl # help control parameters + +bool not_found +int option +pointer sp, fname, pakname, modname +int hd_getname() + +begin + call smark (sp) + call salloc (fname, SZ_PATHNAME, TY_CHAR) + call salloc (pakname, SZ_FNAME, TY_CHAR) + call salloc (modname, SZ_FNAME, TY_CHAR) + + # Handle options which do not access a help file. + option = H_OPTION(ctrl) + H_STATE(ctrl) = BOF + not_found = true + + if (option == O_MENU) { + if (hd_getname (hp, modnum, TY_MEN, Memc[fname], SZ_PATHNAME) == 0) + goto exit_ + iferr (call pr_file (Memc[fname], ctrl, "test")) + call erract (EA_WARN) + else + not_found = false + + } else if (option == O_FILES) { + # Print names of all files associated with module. + ifnoerr (call pr_filenames (hp, module, modnum, ctrl)) + not_found = false + + } else if (option == O_DIR) { + # Print a directory of all help blocks for the named package. + ifnoerr (call pr_directory (db, hp, module, modnum, ctrl)) + not_found = false + + } else if (option == O_SOURCE) { + # Print source file, if given. + if (hd_getname (hp, modnum, TY_SRC, Memc[fname], SZ_PATHNAME) == 0) + goto exit_ + iferr (call pr_file (Memc[fname], ctrl, "test")) + call erract (EA_WARN) + else + not_found = false + + } else if (option == O_SUMMARY) { + # Scan hlp file and print summary of help blocks. + if (hd_getname (hp, modnum, TY_HLP, Memc[fname], SZ_PATHNAME) == 0) + goto exit_ + iferr (call pr_summary (Memc[fname], ctrl)) + call erract (EA_WARN) + else + not_found = false + + } else { + # Get the package and module names. If there is no package name + # in the help directory, it is root help directory, and the module + # name is actually the name of a package. + + if (HD_PAKNAME(hp) == 0) { + call strcpy (module, Memc[pakname], SZ_FNAME) + Memc[modname] = EOS + } else { + call strcpy (Memc[HD_SBUF(hp) + HD_PAKNAME(hp)], + Memc[pakname], SZ_FNAME) + call strcpy (module, Memc[modname], SZ_FNAME) + } + + # Print full helpblock (default action). + if (option == O_HELP || option == O_ALLDOC || + option == O_REFERENCES) { + + if (hd_getname (hp,modnum,TY_HLP,Memc[fname],SZ_PATHNAME) > 0) { + ifnoerr { + call pr_helpblock (Memc[fname], + Memc[pakname], Memc[modname], TY_HLP, ctrl) + } then + not_found = false + } + } + + # Print system documentation. + if (option == O_SYSDOC || option == O_ALLDOC) { + if (hd_getname (hp,modnum,TY_SYS,Memc[fname],SZ_PATHNAME) > 0) { + ifnoerr { + call pr_helpblock (Memc[fname], + Memc[pakname], Memc[modname], TY_HLP, ctrl) + } then + not_found = false + } + } + } + +exit_ + call flush (H_OUT(ctrl)) + call sfree (sp) + if (not_found) + return (ERR) + else + return (OK) +end diff --git a/pkg/system/help/prhlpblk.x b/pkg/system/help/prhlpblk.x new file mode 100644 index 00000000..833cc09b --- /dev/null +++ b/pkg/system/help/prhlpblk.x @@ -0,0 +1,154 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> +include "help.h" + +# PR_HELPBLOCK -- Print a normal helpblock. Open the help file and search +# for the named help block. If found and not printing single section or +# parameter, print manpage title. Process helpblock through Lroff. + +procedure pr_helpblock (fname, pakname, modname, blktype, ctrl) + +char fname[ARB] +char pakname[ARB] +char modname[ARB] +int blktype +pointer ctrl + +bool block_found, help_file, at_eof +int fd, lmarg, rmarg, soflag, foflag, i, nblocks +pointer sp, hb, block_name, ps + +bool streq() +int open(), hb_getnextblk() +pointer ps_open() +extern hinput(), houtput() +errchk hb_getnextblk, pr_block_header + +begin + call smark (sp) + call salloc (hb, LEN_HBSTRUCT, TY_STRUCT) + call salloc (block_name, SZ_FNAME, TY_CHAR) + + iferr (fd = open (fname, READ_ONLY, TEXT_FILE)) { + call sfree (sp) + call erract (EA_ERROR) + return + } + + # Search through the help file for the named help block, of type + # help or system. Decode the help block header into the HB struct. + + H_IN(ctrl) = fd + HB_LINENO(hb) = 0 + H_EOF(ctrl) = NO + lmarg = H_LMARGIN(ctrl) + rmarg = H_RMARGIN(ctrl) + at_eof = false + help_file = false + nblocks = 0 + call strcpy (modname, Memc[block_name], SZ_FNAME) + + # Output standout mode control chars (soflag) only if told to do so. + # Only output forms mode control chars if using Manpage format output + # filter. + + soflag = H_SOFLAG(ctrl) + foflag = H_MANPAGE(ctrl) + + # Process all help blocks in the file which list the current key + # (modname) in their title block, and which are of the desired + # type, i.e., hlp or sys. + + while (!at_eof && H_QUIT(ctrl) != YES) { + block_found = false + repeat { + at_eof = (hb_getnextblk (hb, ctrl) == EOF) + if (!at_eof) { + help_file = true + + if (HB_TYPE(hb) == blktype || blktype == NULL) { + # Search keyword list for the module name. If no + # module name was given, match anything. + + if (modname[1] == EOS) { + block_found = true + nblocks = nblocks + 1 + } else { + for (i=1; i <= HB_NKEYS(hb); i=i+1) + if (streq (HB_KEY(hb,i), modname)) { + block_found = true + nblocks = nblocks + 1 + break + } + } + + # If no module name, use first key as help block name. + if (modname[1] == EOS) + call strcpy (HB_KEY(hb,1), Memc[block_name], + SZ_FNAME) + } + } + } until (block_found || at_eof) + + if (at_eof) { + # If cannot find block, something is wrong, because the + # help directory said there was a block of the desired + # type in this file. If no help blocks at all were found + # in the file, the best thing we can do is to simply print + # the file; hopefully it contains unformatted text. If the + # file contains help blocks, but none with the correct key + # and type, then we print a warning message. + + if (!help_file) { + call close (fd) + # Print header only if there is more than a single list + # element. + if (H_LENTL(ctrl) > 1 && H_OPTION(ctrl) != O_REFERENCES) + call pr_modname (ctrl, pakname, modname) + call pr_file (fname, ctrl, pakname) + call sfree (sp) + return + } else if (nblocks == 0) { + call eprintf ("Cannot find help block for `%s' in `%s'\n") + call pargstr (modname) + call pargstr (fname) + break + } else + break + } + + # Clear the screen and print the block header, if not printing a + # single section or parameter. + + H_EOF(ctrl) = NO + if (H_SECNAME(ctrl) == EOS && H_PARNAME(ctrl) == EOS) + call pr_block_header (hb, Memc[block_name], ctrl) + + + # Finally!! Call Lroff to format the help text. + iferr { + if (H_FORMAT(ctrl) == HF_TEXT) { + call lroff (hinput, ctrl, houtput, ctrl, lmarg, rmarg, + soflag, foflag) + } else if (H_FORMAT(ctrl) == HF_HTML) { + call lroff2html (H_IN(ctrl), H_OUT(ctrl), Memc[block_name], + HB_SECTION(hb), HB_TITLE(hb), H_PARNAME(ctrl), + H_SECNAME(ctrl)) + } else if (H_FORMAT(ctrl) == HF_PS) { + ps = ps_open (H_OUT(ctrl), YES) + call sprintf (Memc[block_name], SZ_LINE, "%s (%s)") + call pargstr (Memc[block_name]) + call pargstr (HB_SECTION(hb)) + call ps_header (ps, Memc[block_name], HB_TITLE(hb), + Memc[block_name]) + call lroff2ps (H_IN(ctrl), H_OUT(ctrl), ps, + H_PARNAME(ctrl), H_SECNAME(ctrl)) + } + } then + call erract (EA_WARN) + } + + call close (fd) + call sfree (sp) +end diff --git a/pkg/system/help/prmodname.x b/pkg/system/help/prmodname.x new file mode 100644 index 00000000..dbf2b939 --- /dev/null +++ b/pkg/system/help/prmodname.x @@ -0,0 +1,35 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "help.h" + +# PR_MODNAME -- Print the module name header "pakname.modname". Omit the +# package name if it begins with an underscore, unless there is no module +# name. + +procedure pr_modname (ctrl, pakname, modname) + +pointer ctrl # help control parameters +char pakname[ARB] # package name +char modname[ARB] # module name + +pointer sp, lbuf + +begin + call smark (sp) + call salloc (lbuf, SZ_LINE, TY_CHAR) + + if (pakname[1] != EOS || modname[1] != EOS) { + call houtput (ctrl, "\n") + if (pakname[1] == '_' && modname[1] != EOS) { + call sprintf (Memc[lbuf], SZ_LINE, "%s:\n") + call pargstr (modname) + } else { + call sprintf (Memc[lbuf], SZ_LINE, "%s.%s:\n") + call pargstr (pakname) + call pargstr (modname) + } + call houtput (ctrl, Memc[lbuf]) + } + + call sfree (sp) +end diff --git a/pkg/system/help/prsummary.x b/pkg/system/help/prsummary.x new file mode 100644 index 00000000..d030842d --- /dev/null +++ b/pkg/system/help/prsummary.x @@ -0,0 +1,95 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "help.h" + +# PR_SUMMARY -- Print a summary of the headers of all help blocks in a +# helpfile. Open the help file and search for the successive blocks. +# Print nice diagnostics describing the contents of the file. + +define TABSTOP 50 + +procedure pr_summary (fname, ctrl) + +char fname[ARB] +pointer ctrl + +int fd, i, n, nlines +pointer sp, hb, lbuf +int open(), gstrcat(), hb_getnextblk(), strlen(), getline(), strmatch() + +begin + call smark (sp) + call salloc (hb, LEN_HBSTRUCT, TY_STRUCT) + call salloc (lbuf, SZ_LINE, TY_CHAR) + + iferr (fd = open (fname, READ_ONLY, TEXT_FILE)) { + call eprintf ("Cannot open helpfile `%s'\n") + call pargstr (fname) + call sfree (sp) + return + } + HB_LINENO(hb) = 0 + H_IN(ctrl) = fd + + # Search through the help file for the named help block, of type + # help or system. Decode the help block header into the HB struct. + + call houtput (ctrl, "\n") + call sprintf (Memc[lbuf], SZ_LINE, "==> %s <==\n") + call pargstr (fname) + call houtput (ctrl, Memc[lbuf]) + + while (H_EOF(ctrl) != EOF && hb_getnextblk (hb, ctrl) != EOF) { + # Describe help block. + call sprintf (Memc[lbuf], SZ_LINE, "%6d ") + call pargi (HB_LINENO(hb)) + + # Print keyword names. + if (HB_NKEYS(hb) > 0) + n = gstrcat (HB_KEY(hb,1), Memc[lbuf], SZ_LINE) + else + n = strlen (Memc[lbuf]) + + for (i=2; i <= HB_NKEYS(hb); i=i+1) { + n = gstrcat (", ", Memc[lbuf], SZ_LINE) + n = gstrcat (HB_KEY(hb,i), Memc[lbuf], SZ_LINE) + } + + # Advance to tabstop and print section label. + repeat { + Memc[lbuf+n] = ' ' + n = n + 1 + } until (n >= TABSTOP) + Memc[lbuf+n] = EOS + + n = gstrcat (HB_SECTION(hb), Memc[lbuf], SZ_LINE) + if (HB_TYPE(hb) != TY_HLP) { + call sprintf (Memc[lbuf+n], SZ_LINE-n, " (%s)") + call pargstr (HB_TYPESTR(hb)) + } + + call strcat ("\n", Memc[lbuf], SZ_LINE) + call houtput (ctrl, Memc[lbuf]) + + # Print block title, if any, on next line. + if (strlen (HB_TITLE(hb)) > 0) { + call sprintf (Memc[lbuf], SZ_LINE, " %s\n") + call pargstr (HB_TITLE(hb)) + call houtput (ctrl, Memc[lbuf]) + } + + # Count and print number of lines in help block. + for (nlines=0; getline (fd, Memc[lbuf]) != EOF; nlines=nlines+1) + if (strmatch (Memc[lbuf], "^.{endhelp}") > 0) + break + call sprintf (Memc[lbuf], SZ_LINE, " block size %d lines\n") + call pargi (nlines) + + call houtput (ctrl, Memc[lbuf]) + call houtput (ctrl, "\n") + HB_LINENO(hb) = HB_LINENO(hb) + nlines + 1 + } + + call close (fd) + call sfree (sp) +end diff --git a/pkg/system/help/t_hdbexamine.x b/pkg/system/help/t_hdbexamine.x new file mode 100644 index 00000000..8046848e --- /dev/null +++ b/pkg/system/help/t_hdbexamine.x @@ -0,0 +1,35 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <syserr.h> +include <error.h> +include "help.h" + + +# HDBEXAMINE -- Examine the help database. + +procedure t_hdbexamine() + +pointer sp, helpdb +bool streq(), clgetb() +int envgets() +string s_helpdb "helpdb" + +begin + call smark (sp) + call salloc (helpdb, SZ_HELPDB, TY_CHAR) + + # Fetch the name of the help database file to be examined. If the + # name is "helpdb", the filename is taken from the environment. + + call clgstr (s_helpdb, Memc[helpdb], SZ_HELPDB) + if (streq (Memc[helpdb], s_helpdb)) + if (envgets (s_helpdb, Memc[helpdb], SZ_HELPDB) <= 0) + call syserrs (SYS_ENVNF, s_helpdb) + + # Examine the structure and contents of the database, printing the + # results on the standard output. + + call hdb_examine (STDOUT, Memc[helpdb], clgetb ("verbose")) + + call sfree (sp) +end diff --git a/pkg/system/help/t_help.x b/pkg/system/help/t_help.x new file mode 100644 index 00000000..2f840fb0 --- /dev/null +++ b/pkg/system/help/t_help.x @@ -0,0 +1,290 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <syserr.h> +include <finfo.h> +include <fset.h> +include <error.h> +include "help.h" + +.help help +.nf __________________________________________________________________________ +HELP -- Print help documentation for the named modules (tasks, packages, +or library procedures). Given the package name and module name, the help +database is used to locate the file(s) containing the desired help text. +Documentation is organized by package, and is maintained in the package +directory. The Lroff text formatter is used to process help text containing +formatting directives. Text is output via the TTY interface, which processes +standout mode control sequences, and clears the screen between pages. +If the standard output is redirected, output is via putline, and pagination +is disabled. See Help.hlp for detailed documentation. +.endhelp _____________________________________________________________________ + +define SZ_TEMPBUF SZ_HELPDB + + +# HELP -- The main procedure. Fetch all parameters, decode the option +# string, set up the control structure, and finally call process_template +# to expand the module template and process the help text for each module. + +procedure t_help() + +int ncols, nlines, list, out_device +long fi[LEN_FINFO], db_ctime +char helpdb[SZ_HELPDB], device[SZ_FNAME] +bool output_is_not_redirected, file_template +pointer sp, ctrl, option, tempbuf, db, tty, fname, tempdev + +long clktime() +pointer ttyodes(), hdb_open() +bool strne(), streq(), clgetb() +int btoi(), stridxs(), finfo(), fntopnb(), fntgfnb(), strdic() +int clgeti(), get_option(), fstati(), envgets(), envgeti() + +data tty /NULL/, db_ctime /0/ +string s_helpdb "helpdb" +define forms_ 91 + +begin + call smark (sp) + call salloc (ctrl, LEN_CTRLSTRUCT, TY_STRUCT) + call salloc (option, SZ_FNAME, TY_CHAR) + call salloc (tempbuf, SZ_TEMPBUF, TY_CHAR) + call salloc (tempdev, SZ_FNAME, TY_CHAR) + call salloc (fname, SZ_PATHNAME, TY_CHAR) + + # If we were called without any arguments, do not query for the + # template, just set it to null and help will be given for the + # current package. + + call aclri (Memi[ctrl], LEN_CTRLSTRUCT) + if (clgeti ("$nargs") == 0) { + H_OPTION(ctrl) = O_MENU + H_TEMPLATE(ctrl) = EOS + H_PARNAME(ctrl) = EOS + H_SECNAME(ctrl) = EOS + } else + call clgstr ("template", H_TEMPLATE(ctrl), SZ_LINE) + + # get the output device type. If the device is 'gui' pass off to + # the XHELP code to execute the GUI, otherwise process the device + # type once we set up the normal HELP task structure. + + call aclrc (Memc[tempdev], SZ_TEMPBUF) + call clgstr ("device", Memc[tempdev], SZ_FNAME) + out_device = strdic (Memc[tempdev], device, SZ_FNAME, HF_DEVICES) + if (out_device == HF_GUI) { + call xhelp (H_TEMPLATE(ctrl)) + call sfree (sp) + return + } + + # Determine whether the template is a module name template or a + # file matching template. + + file_template = clgetb ("file_template") + if (file_template) { + H_OPTION(ctrl) = O_HELP + goto forms_ + } + + # Fetch the name of the help database, i.e., "helpdb", "helpdir", + # or the name of a file. The first time the process runs we open + # and read in the database. The database remains in memory between + # calls to HELP, provided the process does not shutdown, provided + # the name of the database to be used does not change, and provided + # a new help database is not created. + + call aclrc (Memc[tempbuf], SZ_TEMPBUF) + call clgstr (s_helpdb, Memc[tempbuf], SZ_TEMPBUF) + if (streq (Memc[tempbuf], s_helpdb)) + if (envgets (s_helpdb, Memc[tempbuf], SZ_TEMPBUF) <= 0) + call syserrs (SYS_ENVNF, s_helpdb) + + # Check to see if any of the files in the list are newer than the + # time of the last hdb_open. + + if (db_ctime > 0) { + list = fntopnb (Memc[tempbuf], YES) + while (fntgfnb (list, Memc[fname], SZ_PATHNAME) != EOF) { + if (finfo (Memc[fname], fi) == ERR) { + call eprintf ("Cannot access help database file `%s'\n") + call pargstr (Memc[fname]) + } else if (db != NULL && FI_CTIME(fi) > db_ctime) { + call hdb_close (db) + db = NULL + break + } + } + call fntclsb (list) + } else + db = NULL + + # Reopen the help database if in-core copy is out of date. + if (db == NULL || strne (Memc[tempbuf], helpdb)) { + call strcpy (Memc[tempbuf], helpdb, SZ_HELPDB) + if (db != NULL) + call hdb_close (db) + db = hdb_open (helpdb) + db_ctime = clktime (long(0)) + } + + # Fetch the value of the ALL switch. This determines whether help + # will stop after processing the first module matching the template, + # or process all modules in the database which match the template. + # Explicit use of a pattern matching character anywhere in the template + # enable allmodoules. + + if (stridxs ("*?[],", H_TEMPLATE(ctrl)) > 0) + H_ALLMODULES(ctrl) = YES + else + H_ALLMODULES(ctrl) = btoi (clgetb ("all")) + + # If the FILTER_INPUT flag is set, only part of the input text will be + # processed. Filtering is only done if printing a single section or + # parameter. + + H_FILTER_INPUT(ctrl) = NO + + # Determine whether or not text for a single section or parameter + # is to be output. If the value of one of these strings is "all", + # all sections or all parameters are to be output. If the "all" + # default is in effect, null the string as a flag to lower level + # code that all help text is to be processed. + + if (H_OPTION(ctrl) == NULL) { + call clgstr ("section", H_SECNAME(ctrl), SZ_SECNAME) + if (streq (H_SECNAME(ctrl), "all")) { + H_SECNAME(ctrl) = EOS + call clgstr ("parameter", H_PARNAME(ctrl), SZ_PARNAME) + if (streq (H_PARNAME(ctrl), "all")) + H_PARNAME(ctrl) = EOS + } + if (H_SECNAME(ctrl) != EOS || H_PARNAME(ctrl) != EOS) + H_FILTER_INPUT(ctrl) = YES + } + + # Fetch and decode option string; abbreviations are permitted. + if (H_OPTION(ctrl) != O_MENU) { + call clgstr ("option", Memc[option], SZ_FNAME) + call strlwr (Memc[option]) + iferr (H_OPTION(ctrl) = get_option (Memc[option])) { + call erract (EA_WARN) + H_OPTION(ctrl) = O_HELP + } + } +forms_ + # Pause between screens of output text only if the standard output + # is not redirected, and if enabled by the user. + + H_IN(ctrl) = ERR + H_OUT(ctrl) = STDOUT + H_NLINES(ctrl) = -1 + H_STATE(ctrl) = BOF + H_EOF(ctrl) = NO + H_QUIT(ctrl) = NO + + # If the standard output is not redirected, i.e., if writing to the + # terminal, determine whether or not output is to be paginated (pause + # between pages). If output is redirected, the pagination flag + # and help option controls whether or not manpage style output is + # enabled. Manpage output formatting is desirable only when formatting + # help text or printing named files. + + H_RAWOUT(ctrl) = NO + H_MANPAGE(ctrl) = NO + H_PAGINATE(ctrl) = NO + output_is_not_redirected = (fstati (STDOUT, F_REDIR) == NO) + + if (out_device < HF_GUI) { + if (output_is_not_redirected && out_device == HF_TERMINAL) { + if (clgetb ("page")) { + H_PAGINATE(ctrl) = YES + call xttysize (ncols, nlines) + } + } else { + if (clgetb ("page")) { + switch (H_OPTION(ctrl)) { + case O_HELP, O_SOURCE, O_SYSDOC, O_ALLDOC: + H_MANPAGE(ctrl) = YES + H_NLPP(ctrl) = clgeti ("nlpp") + call man_init() + default: + H_RAWOUT(ctrl) = YES + } + } else + H_RAWOUT(ctrl) = YES + } + } + + # Get the current package. Normally this is specified as the null + # string or "AskCL", which causes a runtime query of the CL for the + # current package when a help template is expanded. The reason for + # providing this parameter is to allow this query to be disabled + # (by setting the value to the name of an actual package such as + # system or clpackage) so that, e.g., the help task can be called + # as a host level task. + + iferr (call clgstr ("curpack", H_CURPACK(ctrl), SZ_CURPACK)) + call strcpy ("AskCL", H_CURPACK(ctrl), SZ_CURPACK) + + # Get output device (normally "terminal"), open TTY descriptor for + # the device. The TTY descriptor is left open between calls to HELP + # provided the process does not shutdown and the device name or page + # size does not change. + + if (out_device == HF_TERMINAL) { + if (tty == NULL || strne (Memc[tempdev], device)) { + call strcpy (Memc[tempdev], device, SZ_FNAME) + if (tty != NULL) + call ttycdes (tty) + tty = ttyodes (device) + } + } + + if (out_device == HF_HTML) { + H_FORMAT(ctrl) = HF_HTML + H_RAWOUT(ctrl) = YES + H_SOFLAG(ctrl) = NO + H_MANPAGE(ctrl) = NO + tty = NULL + } else if (out_device == HF_PS || out_device == HF_POSTSCRIPT) { + H_FORMAT(ctrl) = HF_PS + H_RAWOUT(ctrl) = YES + H_SOFLAG(ctrl) = NO + H_MANPAGE(ctrl) = NO + tty = NULL + } else if (out_device == HF_TEXT) { + H_FORMAT(ctrl) = HF_TEXT + H_SOFLAG(ctrl) = NO + } else { + H_FORMAT(ctrl) = HF_TEXT + H_SOFLAG(ctrl) = YES + } + H_TTY(ctrl) = tty + + # Get left and right margins for output text. Make sure right margin + # does not exceed screen width of output device. + + if (H_FORMAT(ctrl) == HF_TEXT) { + H_LMARGIN(ctrl) = max (1, clgeti ("lmargin")) + H_RMARGIN(ctrl) = max (H_LMARGIN(ctrl) + 1, clgeti ("rmargin")) + if (streq (device, "terminal")) + H_RMARGIN(ctrl) = min (H_RMARGIN(ctrl), envgeti ("ttyncols")) + } + + # Initialization is completed, control structure is completed. + # Format and output the help text. If we have a module name template + # process the template against the help database, otherwise work + # directly out of the named files. + + if (file_template) + call do_file_template (H_TEMPLATE(ctrl), ctrl) + else + call do_module_template (db, H_TEMPLATE(ctrl), ctrl) + + # Finish last page and return buffer space if writing manpages. + if (H_MANPAGE(ctrl) == YES) + call man_close (H_OUT(ctrl)) + + call sfree (sp) +end diff --git a/pkg/system/help/t_lroff.x b/pkg/system/help/t_lroff.x new file mode 100644 index 00000000..9df65d43 --- /dev/null +++ b/pkg/system/help/t_lroff.x @@ -0,0 +1,35 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# LROFF -- Text process a file. + +procedure t_lroff() + +char fname[SZ_FNAME] +char line[SZ_LINE] +char format[SZ_FNAME] +int fd, lmargin, rmargin +int open(), getline(), strmatch(), clgeti() +extern getline(), putline() + +begin + call clgstr ("input_file", fname, SZ_FNAME) + fd = open (fname, READ_ONLY, TEXT_FILE) + + lmargin = clgeti ("lmargin") + rmargin = clgeti ("rmargin") + call clgstr ("format", format, SZ_FNAME) + + while (getline (fd, line) != EOF) { + if (strmatch (line, "^.help") > 0) { + if (format[1] == 't') + call lroff (getline, fd, putline, STDOUT, lmargin, rmargin, + YES, NO) + else if (format[1] == 'h') + call lroff2html (fd, STDOUT, fname, "", "", "", "") + else if (format[1] == 'p') + call lroff2ps (fd, STDOUT, NULL, "", "") + } + } + + call close (fd) +end diff --git a/pkg/system/help/t_mkhelpdb.x b/pkg/system/help/t_mkhelpdb.x new file mode 100644 index 00000000..b4cff7a7 --- /dev/null +++ b/pkg/system/help/t_mkhelpdb.x @@ -0,0 +1,76 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <syserr.h> +include <error.h> + +# MKHELPDB -- Make (compile) the help database. The root help directory +# is compiled, along with all sub help directories in the package hierarchy. +# Each package in the system, including both CL packages and library packages, +# has an associated help directory file. Despite the fact that the package +# structure is hierarchical, package names must be distinct because packages +# are indexed in the database in a linear structure. + +procedure t_mkhelpdb() + +bool verbose +pointer sp, helpdir, helpdb, tempname +int envgets(), access() +bool streq(), clgetb() +string s_helpdir "helpdir" +string s_helpdb "helpdb" + +begin + call smark (sp) + call salloc (helpdir, SZ_FNAME, TY_CHAR) + call salloc (helpdb, SZ_FNAME, TY_CHAR) + call salloc (tempname, SZ_FNAME, TY_CHAR) + + # Fetch the names of the root help directory file and the new database + # file. If the names are "helpdir" or "helpdb", the filenames are + # taken from the environment. + + call clgstr (s_helpdir, Memc[helpdir], SZ_FNAME) + if (streq (Memc[helpdir], s_helpdir)) + if (envgets (s_helpdir, Memc[helpdir], SZ_FNAME) <= 0) + call syserrs (SYS_ENVNF, s_helpdir) + + call clgstr (s_helpdb, Memc[helpdb], SZ_FNAME) + if (streq (Memc[helpdb], s_helpdb)) + if (envgets (s_helpdb, Memc[helpdb], SZ_FNAME) <= 0) + call syserrs (SYS_ENVNF, s_helpdb) + + verbose = clgetb ("verbose") + if (verbose) { + call printf ("helpdir = %s\n") + call pargstr (Memc[helpdir]) + call printf ("helpdb = %s\n") + call pargstr (Memc[helpdb]) + } + + # The database is compiled into a temporary file to protect the current + # database in the event the compile is aborted. When the compile has + # successfully completed we will delete the original and replace it + # with the new database. This also has the advantage that the switch + # takes very little time, making it less likely that anyone will notice + # when the database is updated. + + call mktemp ("tmp$hdb", Memc[tempname], SZ_FNAME) + + # Perform the compilation. + call hdb_compile (Memc[helpdir], Memc[tempname], verbose) + + # Now attempt to delete the old database and replace it with the new. + # By default, the help database flle is maintained in dev$, a directory + # with global write permission, so that anyone can delete the file. + # If the old file cannot be deleted we delete the new database and + # abort. + + if (access (Memc[helpdb],0,0) == YES) + iferr (call delete (Memc[helpdb])) { + call delete (Memc[tempname]) + call erract (EA_ERROR) + } + + call rename (Memc[tempname], Memc[helpdb]) + call sfree (sp) +end diff --git a/pkg/system/help/tlist.x b/pkg/system/help/tlist.x new file mode 100644 index 00000000..5bd61ab1 --- /dev/null +++ b/pkg/system/help/tlist.x @@ -0,0 +1,406 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include "help.h" + +.help tlist +.nf __________________________________________________________________________ +TLIST -- Routines for processing the template list. +Functions: + tl_open Expand the template list into a list + of unambiguous templates. + tl_read Fetch next template from the list. + tl_close Close the list. + +Do not confuse these routines with those used to expand and read from the +template for a single package. Our main function is to pass through the +template list, adding package names where they were left out by the user. +If no package name is given all packages in the database are searched. +.endhelp ______________________________________________________________________ + +define SZ_TLSBUF 1024 # local string buffer +define INC_SZTLSBUF 512 # increment if overflow +define SZ_CURPACK 31 # allocation for curpack name string + +define LEN_TLSTRUCT 7 +define TL_CTRL Memi[$1] # string buffer +define TL_SBUF Memi[$1+1] # string buffer +define TL_SZSBUF Memi[$1+2] # size of string buffer +define TL_NEXTCH Memi[$1+3] # index of next char in sbuf +define TL_LISTPTR Memi[$1+4] # for fetching list elements +define TL_CURPACK Memi[$1+5] # offset of name of current package +define TL_LISTLEN Memi[$1+6] # number of elements in list + + +# TL_OPEN -- Take the template list supplied by the user and produce as +# output a list wherein each element has an explicit package name. If an +# element is a module name or a module matching template, it gets replaced +# by a set of such templates, one for each package in the database. +# If a package matching template is given, it is expanded into a list of +# packages. + +pointer procedure tl_open (db, hp, tlist, ctrl) + +pointer db # database descriptor +pointer hp # system package directory +char tlist[ARB] # template list string +pointer ctrl + +int ip, junk +pointer sp, op, tl, sbuf, template, pakstr, modstr +int tl_fetchelem(), tl_matchpak(), tl_putstr(), tl_getcurpack() +errchk tl_getcurpack, tl_ambiguous, tl_matchpak +define paknotfound_ 91 + +begin + call smark (sp) + call salloc (template, SZ_LINE, TY_CHAR) + call salloc (pakstr, SZ_FNAME, TY_CHAR) + call salloc (modstr, SZ_FNAME, TY_CHAR) + + call calloc (tl, LEN_TLSTRUCT, TY_STRUCT) + call malloc (sbuf, SZ_TLSBUF, TY_CHAR) + + TL_CTRL(tl) = ctrl + TL_SBUF(tl) = sbuf + TL_SZSBUF(tl) = SZ_TLSBUF + TL_NEXTCH(tl) = SZ_CURPACK + 2 + TL_LISTPTR(tl) = SZ_CURPACK + 2 + TL_LISTLEN(tl) = 0 + + # If null template list, set to "curpack.". This will cause the + # help for the current package to be printed. Otherwise expand + # the template. Template expansion can produce a very big list. + + for (ip=1; IS_WHITE (tlist[ip]); ip=ip+1) + ; + + if (tlist[ip] == EOS) { + # Put current package name into list. + op = template + tl_getcurpack (tl, Memc[template], SZ_LINE) + Memc[op] = '.' + Memc[op+1] = EOS + junk = tl_putstr (tl, Memc[template]) + + } else { + # Expand nonnull template list. Each time through the loop + # processes the next comma delimited template. + + while (tl_fetchelem (tlist,ip,Memc[pakstr],Memc[modstr]) > 0) { + if (Memc[pakstr] == EOS) { + if (H_OPTION(ctrl) == O_DIR) { + # User wants to print a help directory, but left out + # the "." in the package name. Assume the package + # name is an abbreviation and all all packages which + # match to the list. + + if (tl_matchpak (tl, hp, Memc[modstr], "") == 0) + goto paknotfound_ + } else + call tl_ambiguous (tl, db, hp, Memc[modstr]) + + } else if (tl_matchpak (tl,hp,Memc[pakstr],Memc[modstr]) == 0) { + # Explicit package template was given by user, but no + # matches were made to packages installed in the system + # help directory. Inform user. +paknotfound_ + call eprintf ("Cannot find help for package `%s'\n") + call pargstr (Memc[pakstr]) + } + } + } + + # Return unused space in string buffer. Copy length of list to + # the main help structure. + + call realloc (TL_SBUF(tl), TL_NEXTCH(tl), TY_CHAR) + TL_SZSBUF(tl) = TL_NEXTCH(tl) + H_LENTL(ctrl) = TL_LISTLEN(tl) + + call sfree (sp) + return (tl) +end + + +# TL_CLOSE -- Close a template list opened with TL_OPEN. + +procedure tl_close (tl) + +pointer tl + +begin + call mfree (TL_SBUF(tl), TY_CHAR) + call mfree (tl, TY_STRUCT) +end + + +# TL_READ -- Get the next template from the template list. +# Returns EOF when end of list is reached, else nchars in template. + +int procedure tl_read (tl, outstr, maxch) + +pointer tl +char outstr[ARB] +int maxch +int offset, nchars +int gstrcpy() + +begin + if (TL_LISTPTR(tl) >= TL_NEXTCH(tl)) + return (EOF) + + offset = TL_LISTPTR(tl) + nchars = gstrcpy (Memc[TL_SBUF(tl)+offset], outstr, maxch) + TL_LISTPTR(tl) = offset + nchars + 1 + + return (nchars) +end + + +# TL_MATCHPACK -- Match package name against the system package list, +# add each package matched to the list. + +int procedure tl_matchpak (tl, hp, package, module) + +pointer tl +pointer hp +char package[ARB] +char module[ARB] + +int paklen, junk, ngen, modnum +pointer sp, template, op, ml +int tl_putstr(), ml_read() +pointer ml_open() +errchk ml_open, ml_read, tl_putstr + +begin + call smark (sp) + call salloc (template, SZ_LINE, TY_CHAR) + + ngen = 0 + ml = ml_open (hp, package) + + repeat { + paklen = ml_read (ml, modnum, Memc[template], SZ_LINE) + if (paklen == EOF) + break + op = template + paklen + Memc[op] = '.' + call strcpy (module, Memc[op+1], SZ_LINE-paklen-1) + junk = tl_putstr (tl, Memc[template]) + ngen = ngen + 1 + } + + call ml_close (ml) + call sfree (sp) + return (ngen) +end + + +# TL_AMBIGUOUS -- Called to expand an ambiguous template, i.e., one which did +# not include the "." delimiter to denote the package and module fields. +# We handle this by generating a series of module matching templates, one for +# each package in the database, starting with the current package. If the +# ambiguous pattern contains any pattern matching metacharacters we match only +# against the modules in the current package. Otherwise (completely ambiguous +# template) we match against: +# +# [1] all modules in the current package +# [2] all modules in all packages, except the current package +# +# For example, "alpha" might be expanded into the list +# curpack.alpha, pak1.alpha, pak2.alpha, ... +# +# The search [2] is a depth-first search of all packages in the root. Since +# each non-root package is a module of some other package, this search will +# find all non-root packages as well as modules. For the root packages to be +# found they must reference themselves as modules, but NOT as subpackages, +# otherwise recursion will occur. + +procedure tl_ambiguous (tl, db, hp, module) + +pointer tl # template list descriptor +pointer db # database descriptor +pointer hp # package directory +char module[ARB] # module template + +int paklen, junk, ip, pk +pointer sp, curpack, template, op +bool streq() +int tl_putstr(), stridx(), tl_getcurpack(), hd_getname() +errchk tl_putstr, tl_getcurpack, hd_getname + +begin + call smark (sp) + call salloc (template, SZ_LINE, TY_CHAR) + call salloc (curpack, SZ_FNAME, TY_CHAR) + + # Output the template for the current package. Save the name of + # the current package for later use. + + op = template + tl_getcurpack (tl, Memc[template], SZ_LINE) + call strcpy (Memc[template], Memc[curpack], SZ_FNAME) + Memc[op] = '.' + call strcpy (module, Memc[op+1], SZ_LINE-(op-template)-1) + junk = tl_putstr (tl, Memc[template]) + + # Check for pattern matching metacharacters. If present we match + # only against the current package, hence we are all done. + + for (ip=1; module[ip] != EOS; ip=ip+1) + if (stridx (module[ip], "*?[]") > 0) { + call sfree (sp) + return + } + + # Output a template for each remaining package in the database, + # excluding the current package which gets searched first and has + # already been put in the list. Template is "pakname.module". + + pk = 1 + repeat { + paklen = hd_getname (hp, pk, TY_MODNAME, Memc[template], SZ_LINE) + pk = pk + 1 + if (paklen <= 0) + break + if (streq (Memc[template], Memc[curpack])) + next + op = template + paklen + Memc[op] = '.' + call strcpy (module, Memc[op+1], SZ_LINE-paklen-1) + junk = tl_putstr (tl, Memc[template]) + } + + call sfree (sp) +end + + +# TL_FETCHELEM -- Extract next element from template list. An element +# consists of the package pattern, module pattern, both, or either. +# Set output strings to the null string if field not present. Return +# the number of chars in the full element, zero when EOS is reached on +# the template list. + +int procedure tl_fetchelem (tlist, ip, pakstr, modstr) + +char tlist[ARB] +int ip +char pakstr[SZ_FNAME] +char modstr[SZ_FNAME] + +bool package_seen +char ch +int op, ip_save + +begin + package_seen = false + pakstr[1] = EOS + + # Skip whitespace, the comma delimiters between list elements, + # and any null list elements (i.e. ",,"). + + while (IS_WHITE (tlist[ip]) || tlist[ip] == ',') + ip = ip + 1 + ip_save = ip + + # Extract the first field. If period is seen, this is the package + # field, copy it to pakstr. Remainder is the module name. + op = 1 + ch = tlist[ip] + while (ch != ',' && ch != '\n' && ch != EOS) { + modstr[op] = ch + if (ch == '.') { + if (package_seen) + call error (18, "Too many '.' delims in help template") + package_seen = true + modstr[op] = EOS + call strcpy (modstr, pakstr, SZ_FNAME) + op = 1 + } else + op = op + 1 + ip = ip + 1 + ch = tlist[ip] + } + modstr[op] = EOS + + return (ip - ip_save) +end + + +# TL_GETCURPACK -- Get the name of the current package. The hidden CL command +# "_curpack" prints the name of the current package. + +int procedure tl_getcurpack (tl, pakname, maxch) + +pointer tl # template list +char pakname[maxch] # package name (output) +int maxch + +pointer ctrl +int nchars, junk +int gstrcpy(), fscan() +bool strne() +errchk clcmd + +begin + # The current package is read only once for each tlist expansion. + # The following uses the CL global parameter "list" to read the + # package list. The CL interface is violated by sending an explicit + # command to the CL. Poor practice, but the query can be disabled + # by setting the help.curpack parameter, if this causes a problem. + + if (TL_CURPACK(tl) == NULL) { + # Was the current package set via a help task parameter? + ctrl = TL_CTRL(tl) + if (H_CURPACK(ctrl) != EOS) + if (strne (H_CURPACK(ctrl), "AskCL")) { + call strcpy (H_CURPACK(ctrl), + Memc[TL_SBUF(tl)+1], SZ_CURPACK) + TL_CURPACK(tl) = 1 + } + + if (TL_CURPACK(tl) == NULL) { + # Send "_curpack" command to the CL, read the response (a single + # line) from CLIN. + + call clcmd ("_curpack") + junk = fscan (CLIN) + call gargwrd (Memc[TL_SBUF(tl)+1], SZ_CURPACK) + TL_CURPACK(tl) = 1 + } + } + + nchars = gstrcpy (Memc[TL_SBUF(tl) + TL_CURPACK(tl)], pakname, maxch) + return (nchars) +end + + +# TL_PUTSTR -- Put a string (incl EOS) in the string buffer at nextch. +# If there is not enough space in the buffer, reallocate a larger buffer. +# Return the index of the string in the string buffer. + +int procedure tl_putstr (tl, str) + +pointer tl +char str[ARB] +int nextch, nchars, strlen() +errchk realloc + +begin + # Null strings are not stored and cause a null index to be returned. + nchars = strlen (str) + if (nchars == 0) + return (0) + + nextch = TL_NEXTCH(tl) + if (nextch + nchars + 1 > TL_SZSBUF(tl)) { + TL_SZSBUF(tl) = TL_SZSBUF(tl) + INC_SZTLSBUF + call realloc (TL_SBUF(tl), TL_SZSBUF(tl), TY_CHAR) + } + + call strcpy (str, Memc[TL_SBUF(tl) + nextch], ARB) + TL_NEXTCH(tl) = nextch + nchars + 1 + TL_LISTLEN(tl) = TL_LISTLEN(tl) + 1 + + return (nextch) +end diff --git a/pkg/system/help/xhelp/help.gui b/pkg/system/help/xhelp/help.gui new file mode 100644 index 00000000..b3f21c07 --- /dev/null +++ b/pkg/system/help/xhelp/help.gui @@ -0,0 +1,3027 @@ +# XHELP.GUI -- Graphics user interface for the IRAF help browser. + +reset-server +appInitialize xhelp XHelp { + +XHelp*objects:\ + toplevel Layout helpLayout\ + helpLayout Group menubarGroup\ + helpLayout Paned helpPanes\ + menubarGroup Layout menubarLayout\ + menubarLayout MenuButton fileButton\ + menubarLayout MenuButton optionsButton\ + menubarLayout Command printButton\ + menubarLayout Command findButton\ + menubarLayout Command searchButton\ + menubarLayout MenuButton historyButton\ + menubarLayout Command helpButton\ + menubarLayout Command quitButton\ +\ + helpPanes Group topicGroup\ + topicGroup Layout topicLayout\ + topicLayout Label topicLabel\ + topicLayout Command reloadButton\ + topicLayout Frame topicFrame\ + topicFrame AsciiText topicEntry\ + topicLayout Command topicClear\ + topicLayout Frame listFrame\ + listFrame Viewport listView\ + listView List topicList\ +\ + helpPanes Group outputGroup\ + outputGroup Layout outputLayout\ + outputLayout Command htbButton\ + outputLayout Command htfButton\ + outputLayout Command htuButton\ + outputLayout Command hthButton\ + outputLayout MenuButton secButton\ + outputLayout MenuButton parButton\ + outputLayout TextToggle hlpOpt\ + outputLayout TextToggle srcOpt\ + outputLayout TextToggle sysOpt\ + outputLayout TextToggle filOpt\ + outputLayout Frame helpFrame\ + helpFrame HTML helpText\ +\ +\ + toplevel TopLevelShell printShell\ + printShell Layout prntLayout\ + prntLayout Group printGroup\ + prntLayout Group printCmdGroup\ +\ + printGroup Layout printLayout\ + printLayout Label toLabel\ + printLayout TextToggle toPrinter\ + printLayout TextToggle toFile\ + printLayout Label printLabel\ + printLayout Frame printFrame\ + printFrame AsciiText printEntry\ + printLayout Label pageLabel\ + printLayout TextToggle pageLetter\ + printLayout TextToggle pageLegal\ + printLayout TextToggle pageA4\ + printLayout TextToggle pageB5\ +\ + printCmdGroup Layout printCmdLayout\ + printCmdLayout Command printOkay\ + printCmdLayout Command printDismiss\ +\ +\ + toplevel TopLevelShell searchShell\ + searchShell Group searchGroup\ + searchGroup Layout searchLayout\ + searchLayout Label resLabel\ + searchLayout Frame resFrame\ + resFrame HTML resList\ + searchLayout Label searchLabel\ + searchLayout Frame searchFrame\ + searchFrame AsciiText searchEntry\ + searchLayout Command searchClear\ + searchLayout Command searchOkay\ + searchLayout Label searchStatus\ + searchLayout TextToggle exactMatch\ + searchLayout Command searchHelp\ + searchLayout Command searchDismiss\ +\ +\ + toplevel TransientShell findShell\ + findShell Layout fsLayout\ + fsLayout Group findGroup\ + fsLayout Group findCmdGroup\ +\ + findGroup Layout findLayout\ + findLayout Label findLabel\ + findLayout Frame findFrame\ + findFrame AsciiText findEntry\ + findLayout TextToggle findDir\ + findLayout TextToggle findCase\ +\ + findCmdGroup Layout findCmdLayout\ + findCmdLayout Command findOkay\ + findCmdLayout Command findClear\ + findCmdLayout Command findDismiss\ +\ +\ + toplevel TopLevelShell fileShell\ + fileShell Layout flist\ + flist Group flGroup\ + flGroup Layout flFrame\ + flFrame Label flistLabel\ + flFrame Frame flistFrame\ + flistFrame AsciiText flistText\ + flFrame Label flpkgLabel\ + flFrame Label flpkgVal\ + flFrame Command flDismiss\ +\ +\ + toplevel TopLevelShell fileBrowser\ + fileBrowser Layout fbLayout\ + fbLayout Group fnavGroup\ + fbLayout Group fbCmdGroup\ + fbLayout Parameter directory\ +\ + fnavGroup Layout fnavLayout\ + fnavLayout Command fnavHome\ + fnavLayout Command fnavUp\ + fnavLayout Command fnavRoot\ + fnavLayout Command fnavRescan\ + fnavLayout Label filterLabel\ + fnavLayout Frame filterFrame\ + filterFrame AsciiText filterEntry\ + fnavLayout Command filterClear\ + fnavLayout Group dirGroup\ + dirGroup Frame dirFrame\ + dirFrame Viewport dirView\ + dirView List dirList\ + fnavLayout Group fileGroup\ + fileGroup Frame fgFrame\ + fgFrame Viewport fileView\ + fileView List fileList\ + fnavLayout Label curdirLabel\ + fnavLayout Label curdirVal\ + fnavLayout Label fnameLabel\ + fnavLayout Frame fnameFrame\ + fnameFrame AsciiText fnameEntry\ + fnavLayout Command fnameClear\ +\ + fnavLayout Group fmtGroup\ + fmtGroup Layout fmtLayout\ + fmtLayout Label fmtLabel\ + fmtLayout TextToggle fmtSrc\ + fmtLayout TextToggle fmtText\ + fmtLayout TextToggle fmtHTML\ + fmtLayout TextToggle fmtPS\ + fmtLayout Label owLabel\ + fmtLayout TextToggle overwrite\ +\ + fbCmdGroup Layout fbCmdLayout\ + fbCmdLayout Command fbcOkay\ + fbCmdLayout Command fbcHelp\ + fbCmdLayout Command fbcDismiss\ +\ +\ + toplevel TopLevelShell doc_source\ + doc_source Layout srcLayout\ + srcLayout Frame srcMenuFrame\ + srcMenuFrame Layout srcMenuBar\ + srcMenuBar Command srcDismiss\ + srcLayout Frame srcFrame\ + srcFrame AsciiText srcText\ +\ +\ + toplevel TopLevelShell hlpShell\ + hlpShell Layout hlpLayout\ + hlpLayout Group hlpMenuGroup\ + hlpMenuGroup Layout hlpMenu\ + hlpMenu Command hlpBack\ + hlpMenu Command hlpForward\ + hlpMenu Command hlpHome\ + hlpMenu Command hlpTutorial\ + hlpMenu Command hlpDismiss\ + hlpLayout Frame hlpTextFrame\ + hlpTextFrame HTML hlpText\ + hlpLayout Label hfLabel\ + hlpLayout Frame hfFrame\ + hfFrame AsciiText hfEntry\ + hlpLayout Command hfFind\ + hlpLayout Command hfClear\ + hlpLayout TextToggle hfDir\ + hlpLayout TextToggle hfCase\ + hlpShell Parameter help\ +\ +\ + toplevel TransientShell warning\ + warning Layout warn\ + warn Frame warnFrame\ + warnFrame Layout WFlayout\ + WFlayout Icon warnIcon\ + WFlayout TextBox warnText\ + warn Frame warnBtnFrame\ + warnBtnFrame Command warnDismiss\ +\ +\ + toplevel TopLevelShell tclShell\ + tclShell Layout tclLayout\ + tclLayout Group tclCmdGroup\ + tclCmdGroup Layout tclCmd\ + tclCmd Command tclClear\ + tclCmd Command tclExecute\ + tclCmd Toggle tclLogging\ + tclCmd Command tclDismiss\ + tclLayout Frame tclFrame\ + tclFrame AsciiText tclEntry\ +\ +\ + toplevel Parameter xhelp\ + xhelp Parameter textout\ + xhelp Parameter alert\ + xhelp Parameter apropos\ + xhelp Parameter pkglist\ + xhelp Parameter helpres\ + xhelp Parameter helpfiles\ + xhelp Parameter printer\ + xhelp Parameter curpack\ + xhelp Parameter curtask\ + xhelp Parameter history\ + xhelp Parameter showtype\ + xhelp Parameter type + + + + !------------------------------------------------------- + ! Define some global resources for the main menu panels. + !------------------------------------------------------- + *shadowWidth: 1 + *background: gray75 + *Arrow.width: 16 + *Arrow.height: 25 + *Text*height: 21 + *Command.height: 21 + *Command.highlightThickness: 1 + *Command.internalHeight: 4 + *MenuButton.height: 21 + *MenuButton.highlightThickness: 1 + *Label.borderWidth: 0 + *Label.shadowWidth: 0 + *TextButton.shadowWidth: 0 + *TextButton.highlightThickness: 1 + *TextToggle*borderWidth: 0 + *TextToggle.highlightThickness: 0 + *Toggle.highlightThickness: 1 + *Group.shrinkToFit: True + + *Arrow.foreground: gray72 + *Arrow.background: gray72 + *Text*background: gray72 + *AsciiText*background: gray72 + *TextBox.background: gray72 + *MultiList*background: gray72 + *List*background: gray72 + *Slider2d*thumbColor: gray75 + + + !------------------------------------------------------------- + ! Define resources to take advantage of the 3D scrollbar look. + !------------------------------------------------------------- + *Scrollbar*background: gray75 + *Scrollbar*width: 15 + *Scrollbar*height: 15 + *Scrollbar*shadowWidth: 1 + *Scrollbar*cursorName: top_left_arrow + *Scrollbar*pushThumb: true + + + !---------------------------------------- + ! Menu resources giving a shadow effect. + !---------------------------------------- + *SmeBSB.leftMargin: 10 + *SmeBSB.rightMargin: 5 + *SmeBSB.shadowWidth: 2 + *SmeBSB*background: SteelBlue + *SimpleMenu*background: gray77 + *SimpleMenu.borderWidth: 2 + *SimpleMenu.borderColor: Black + *SimpleMenu.shadowWidth: 2 + *SimpleMenu.line1.foreground: gray51 + *SimpleMenu.line2.foreground: gray91 + *SimpleMenu.line3.foreground: gray51 + *SimpleMenu.line4.foreground: gray91 + *SimpleMenu.line5.foreground: gray51 + *SimpleMenu.line6.foreground: gray91 + *SimpleMenu.line7.foreground: gray51 + *SimpleMenu.line8.foreground: gray91 + *SimpleMenu.line9.foreground: gray51 + *SimpleMenu.line10.foreground: gray91 + *SimpleMenu.line11.foreground: gray51 + *SimpleMenu.line12.foreground: gray91 + *SimpleMenu.line13.foreground: gray51 + *SimpleMenu.line14.foreground: gray91 + *SimpleMenu.line15.foreground: gray51 + *SimpleMenu.line16.foreground: gray91 + *SimpleMenu.line17.foreground: gray51 + *SimpleMenu.line18.foreground: gray91 + *SimpleMenu.line19.foreground: gray51 + *SimpleMenu.line20.foreground: gray91 + *SimpleMenu.line21.foreground: gray51 + *SimpleMenu.line22.foreground: gray91 + *SimpleMenu.line23.foreground: gray51 + *SimpleMenu.line24.foreground: gray91 + *SimpleMenu.line25.foreground: gray51 + *SimpleMenu.line26.foreground: gray91 + *SimpleMenu.line27.foreground: gray51 + *SimpleMenu.line28.foreground: gray91 + *SimpleMenu.line29.foreground: gray51 + *SimpleMenu.line30.foreground: gray91 + + + !---------------------------------------- + ! Define the default fonts to be used. + !---------------------------------------- + *font: -adobe-times-medium-r-normal-*-14-*-*-* + *Command.font: -adobe-times-bold-i-normal-*-12-*-*-* + *MenuButton.font: -adobe-times-bold-i-normal-*-12-*-*-* + *Toggle.font: -adobe-times-bold-i-normal-*-12-*-*-* + *Label.font: -adobe-times-bold-i-normal-*-12-*-*-* + *TextToggle.font: -adobe-times-bold-i-normal-*-12-*-*-* + *Group*SimpleMenu*font: 7x13 + *HTML*SimpleMenu*font: 7x13 + + *HTML.plainFont: -*-fixed-medium-r-*-*-13-*-*-* + *HTML.listingFont: -*-fixed-medium-r-*-*-13-*-*-* + *HTML.font: -adobe-times-medium-r-normal-*-14-*-*-* + *HTML.boldFont: -adobe-times-bold-r-normal-*-14-*-*-* + *HTML.plainboldFont: -adobe-times-bold-r-normal-*-14-*-*-* + *HTML.fixedboldFont: -adobe-times-bold-r-normal-*-14-*-*-* + *HTML.header1Font: -adobe-times-bold-r-normal-*-18-*-*-* + *HTML.header2Font: -adobe-times-bold-r-normal-*-14-*-*-* + *HTML.header3Font: -adobe-times-bold-r-normal-*-14-*-*-* + *HTML.header4Font: -adobe-times-bold-r-normal-*-14-*-*-* + *HTML.header5Font: -adobe-times-medium-i-normal-*-12-*-*-* + *HTML.header6Font: -adobe-times-bold-r-normal-*-10-*-*-* + *HTML.anchorUnderlines: 0 + *HTML.visitedAnchorUnderlines: 0 + *HTML.anchorColor: blue + *HTML.visitedAnchorColor: red3 + *HTML*background: gray72 + *HTML*Scrollbar.background: gray75 + *HTML*Scrollbar*width: 15 + *HTML*Scrollbar*height: 15 + + + !--------------------------- + ! Set the default resources. + !--------------------------- + *xhelp.title: IRAF Help Browser V1.0 - DEV + *xhelp.geometry: +0+0 + *xhelp.width: 625 + *xhelp.minWidth: 580 + *xhelp.minheight: 450 + *xhelp.height: 850 + + *helpLayout.geometry: 600x700+0+0 + *helpLayout*borderWidth: 0 + *helpLayout*Group.shrinkToFit: True + *helpLayout*Frame.frameType: sunken + *helpLayout*Frame.frameWidth: 1 + *helpLayout*Command.internalHeight: 2 + *helpLayout*MenuButton.internalHeight: 2 + *helpLayout*Label*highlightThickness: 0 + *helpLayout*List*shadeSurplus: False + *helpLayout*List.internalWidth: 10 + *helpLayout*Viewport.allowVert: True + *helpLayout*Viewport.forceBars: True + *helpLayout.width: 600 + *helpLayout.layout: vertical { \ + menubarGroup < +inf -inf * > \ + -1 \ + horizontal { \ + -1 \ + helpPanes < +inf -inf * +inf -inf > \ + -1 \ + } \ + -1 \ + } + *helpLayout*SimpleMenu.shadowWidth: 2 + *helpLayout*SimpleMenu.borderColor: Black + *helpLayout*SimpleMenu.borderWidth: 2 + + *menubarGroup.label: + *menubarGroup.outerOffset: 0 + *menubarGroup.innerOffset: 5 + *menubarGroup.frameType: raised + *menubarGroup.frameWidth: 2 + *menubarGroup*Command.shadowWidth: 0 + *menubarGroup*MenuButton.shadowWidth: 0 + *menubarLayout.layout: horizontal { \ + fileButton 5 \ + optionsButton 5 \ + printButton 5 \ + findButton 5 \ + searchButton 5 \ + historyButton 5 \ + 10 < +inf -inf > \ + helpButton 5 \ + quitButton \ + } + *fileButton.label: File + *fileButton.menuName: fileMenu + *optionsButton.label: Options + *optionsButton.menuName: optsMenu + *printButton.label: Print + *findButton.label: Find + *searchButton.label: Search + *historyButton.label: History + *historyButton.menuName: historyMenu + *helpButton.label: Help + *quitButton.label: Quit + + *topicGroup.label: + *topicGroup.outerOffset: 2 + *topicGroup.innerOffset: 2 + *topicGroup*frameType: chiseled + *topicGroup.frameWidth: 2 + *topicGroup*Label.shadowWidth: 0 + *topicGroup*Label.borderWidth: 1 + *topicGroup*Label.highlightThickness: 1 + *topicGroup*Viewport.useRight: True + *topicGroup*Viewport.useBottom: True + *topicLayout.layout: vertical { \ + 2 < +2 -2 > \ + horizontal { \ + 3 < +3 -3 > \ + topicLabel 2 topicFrame < +inf * > \ + 2 \ + topicClear 5 reloadButton \ + 1 \ + } \ + 4 \ + horizontal { \ + vertical { \ + -1 \ + listFrame < +inf -inf * +inf -inf > \ + -1 \ + } \ + } \ + 2 < +2 -2 > \ + } + *reloadButton.label: Reload + *topicLabel.label: Topic: + *topicLabel.justify: right + *topicEntry*width: 100 + *topicEntry*editType: edit + *topicEntry*font: 7x13 + *topicEntry*displayCaret: True + *topicClear.label: Clear + + *topicList.font: 7x13 + *topicList.width: 500 + *topicList.height: 100 + *topicList.columnSpacing: 20 + *topicList.verticalList: True + !*topicList.defaultColumns: 6 + !*topicList.forceColumns: True + + *outputGroup.label: + *outputGroup.outerOffset: 2 + *outputGroup.innerOffset: 2 + *outputGroup*frameType: chiseled + *outputGroup.frameWidth: 2 + *outputGrout*TextToggle*on: 0 + *outputGroup*TextToggle.frameWidth: 2 + *outputGroup*TextToggle.frameType: chiseled + *outputGroup*TextToggle.location: 0 0 65 25 + *outputGroup*TextToggle.leftMargin: 4 + *outputLayout.layout: vertical { \ + 2 \ + horizontal { \ + 5 \ + htbButton 2 htfButton 2 htuButton 2 hthButton 2 \ + 10 < +inf -10 > \ + secButton 2 parButton \ + 10 < +inf -10 > \ + hlpOpt -2 srcOpt -2 sysOpt 4 filOpt \ + 5 \ + } \ + 2 \ + horizontal { \ + 2 \ + helpFrame < +inf -inf * +inf -inf > \ + 2 \ + } \ + } + *htbButton.label: Back + *htbButton.sensitive: False + *htfButton.label: Forward + *htfButton.sensitive: False + *htuButton.label: Up + *htuButton.sensitive: False + *hthButton.label: Home + *printButton.label: Print + *secButton.label: Sections + *secButton.menuName: secMenu + *parButton.label: Parameters + *parButton.menuName: parMenu + *hlpOpt*label: Help + *hlpOpt*on: 1 + *hlpOpt*onIcon: diamond1s + *hlpOpt*offIcon: diamond0s + *hlpOpt*highlightColor: green + *srcOpt*label: Source + *srcOpt*on: 0 + *srcOpt*onIcon: diamond1s + *srcOpt*offIcon: diamond0s + *srcOpt*highlightColor: green + *sysOpt*label: Sysdoc + *sysOpt*on: 0 + *sysOpt*onIcon: diamond1s + *sysOpt*offIcon: diamond0s + *sysOpt*highlightColor: green + *filOpt*label: Files + *filOpt*on: 0 + *filOpt*onIcon: square1s + *filOpt*offIcon: square0s + *filOpt*highlightColor: yellow + + *helpText.width: 650 + *helpText.height: 620 + *helpText.anchorUnderlines: 1 + *helpText.visitedAnchorUnderlines: 1 + *helpText.verticalScrollOnRight: true + *helpText.translations: \ + <Btn2Down>: popup(secMenu) \n\ + <Btn2Up>: popdown(secMenu) \n\ + <Btn3Down>: popup(navMenu) \n\ + <Btn3Up>: popdown(navMenu) \n + + *helpText*navMenu.foreground: Black + *helpText*navMenu.background: gray75 + *helpText*secMenu.foreground: Black + *helpText*secMenu.background: gray75 + + + !--------------------------+ + ! Printer Shell resources. | + !--------------------------+ + *printShell.title: Printer Selection + *printShell.width: 300 + *printShell.height: 177 + *printShell.minHeight: 177 + *printShell.maxHeight: 177 + *printShell*borderWidth: 0 + *printShell*Group.frameType: chiseled + *printShell*Group.frameWidth: 2 + *printShell*Group.innerOffset: 5 + *printShell*Group.outerOffset: 2 + *printShell*Command.internalheight: 4 + *printShell*Text*editType: edit + *printShell*Text*height: 25 + *printShell*TextToggle.frameWidth: 0 + *printShell*Group.label: + *prntLayout.layout: vertical { \ + printGroup < +inf -inf * > \ + printCmdGroup < +inf -inf * > \ + } + + *printLayout*location: 0 0 70 25 + *printLayout*offIcon: diamond0s + *printLayout*onIcon: diamond1s + *printLayout*highlightColor: yellow + *printLayout*Label.height: 35 + *printLayout*Label.justify: right + *printLayout*TextToggle.frameWidth: 0 + *printLayout*TextToggle.leftMargin: 8 + *printLayout*TextToggle*highlightColor: yellow + *printLayout*TextToggle*onIcon: square1s + *printLayout*TextToggle*offIcon: square0s + *printLayout*TextToggle*alignment: left + *printLayout.layout: vertical { \ + 0 < +0 >\ + horizontal { toLabel 10 toPrinter 10 toFile 10 } \ + 5 < +inf -5 > \ + horizontal { \ + printLabel 5 printFrame < +inf -inf * > -1 \ + } \ + 5 < +inf -5 > \ + horizontal { \ + vertical { pageLabel 10 } \ + 12 \ + horizontal { \ + vertical { pageLetter -3 pageLegal } \ + 10 \ + vertical { pageA4 -3 pageB5 } \ + } \ + } \ + 0 < +0 >\ + } + *toLabel.label: Print to: + *toPrinter.label: Printer + *toPrinter.on: True + *toFile.label: File + *printLabel.label: Printer: + *printFrame.frameType: sunken + *printFrame.frameWidth: 1 + *printEntry*string: printer + *pageLabel.label: Page Size: + *pageLetter.label: Letter + *pageLetter.on: 1 + *pageLegal.label: Legal + *pageA4.label: A4 + *pageB5.label: B5 + + *printCmdLayout.layout: horizontal { \ + 3 \ + printOkay 20 < +inf -20 > printDismiss \ + 3 \ + } + *printOkay.label: Print + *printDismiss.label: Dismiss + + + !-------------------------+ + ! File Browser resources. | + !-------------------------+ + *fileBrowser.width: 450 + *fileBrowser.height: 375 + *fileBrowser.title: Open a New File... + *fileBrowser*borderWidth: 0 + *fileBrowser*Group.frameType: chiseled + *fileBrowser*Group.frameWidth: 2 + *fileBrowser*Group.innerOffset: 3 + *fileBrowser*Group.outerOffset: 3 + *fileBrowser*Group.label: + + *fbLayout.layout: vertical { \ + 2 \ + fnavGroup < +inf -inf * +inf -inf > \ + -2 \ + horizontal { \ + -5 \ + fbCmdGroup < +inf -inf * > \ + -5 } \ + -3 \ + } + + *fnavGroup*Frame.frameType: sunken + *fnavGroup*Frame.frameWidth: 1 + *fnavGroup*Text*editType: edit + *fnavGroup*Text*height: 25 + *fnavGroup*Text*font: 7x13 + *fnavGroup*List.verticalList: True + *fnavGroup*List.defaultColumns: 1 + *fnavGroup*List.forceColumns: True + *fnavGroup*List.font: 7x13 + *fnavGroup*Label.justify: left + *fnavGroup*Viewport.allowVert: True + *fnavGroup*Viewport.allowHoriz: False + *fnavGroup*Viewport.forceBars: True + *fnavGroup*Viewport.useRight: True + *fnavGroup*Group.outerOffset: 7 + *fnavGroup*Group.innerOffset: 3 + *fnavLayout.layout: vertical { \ + 5 \ + vertical { \ + -1 \ + horizontal { \ + 5 \ + fnavHome < +inf -inf * > 2 \ + fnavUp < +inf -inf * > 2 \ + fnavRoot < +inf -inf * > 2 \ + fnavRescan < +inf -inf * > \ + 10 \ + filterLabel 2 filterFrame < +inf -inf * > \ + 2 \ + filterClear \ + 5 \ + } \ + 3 \ + } \ + 5 \ + horizontal { \ + -5 \ + dirGroup < +inf -inf * +inf - inf > \ + -8 \ + fileGroup < +inf -inf * +inf - inf > \ + -5 \ + } \ + -3 \ + horizontal { \ + curdirLabel 5 curdirVal < +inf -inf * > 5 } \ + 5 \ + horizontal { \ + fnameLabel 2 fnameFrame < +inf -inf * > 2 fnameClear 5\ + } \ + 7 \ + fmtGroup < +inf -inf * > \ + -3 \ + } + *fileBrowser*fnavGroup*dirGroup.label: Directories + *fileBrowser*fnavGroup*fileGroup.label: Files + *fileBrowser*fnavGroup*dirGroup.innerOffset: 3 + *fileBrowser*fnavGroup*fileGroup.innerOffset: 3 + *fileBrowser*fnavGroup*dirGroup.outerOffset: 7 + *fileBrowser*fnavGroup*fileGroup.outerOffset: 7 + *fileBrowser*fnavGroup*dirGroup.font: 7x13bold + *fileBrowser*fnavGroup*fileGroup.font: 7x13bold + + *filterLabel.label: Filter + *filterClear.label: Clear + *curdirLabel.label: Directory: + *curdirVal.label: + *curdirVal.font: 7x13 + *fnameLabel.label: Selection\ \ + *fnameClear.label: Clear + *fnavHome.label: Home + *fnavUp.label: Up + *fnavRoot.label: Root + *fnavRescan.label: Rescan + + *fmtGroup*Group.outerOffset: 3 + *fmtGroup*Group.innerOffset: 3 + *fmtLayout*TextToggle.frameWidth: 0 + *fmtLayout*TextToggle.leftMargin: 4 + *fmtLayout*TextToggle.alignment: left + *fmtLayout*TextToggle*highlightColor: yellow + *fmtLayout*TextToggle*onIcon: square1s + *fmtLayout*TextToggle*offIcon: square0s + *fmtLayout.layout: vertical { \ + horizontal { 5 fmtLabel 10 fmtSrc 3 fmtText 3 fmtHTML 3 fmtPS 5 } \ + horizontal { 50 owLabel 10 overwrite 5 < +inf > } \ + } + *fmtLabel.label: Save As Format: + *fmtSrc.label: Source + *fmtSrc.on: 1 + *fmtSrc.location: 0 0 65 22 + *fmtText.label: Text + *fmtText.location: 0 0 65 22 + *fmtHTML.label: HTML + *fmtHTML.location: 0 0 65 22 + *fmtPS.label: PostScript + *fmtPS.location: 0 0 100 22 + *owLabel.label: Options: + *overwrite.label: Allow overwrite of existing files? + *overwrite.location: 0 0 200 22 + + *fbCmdLayout.outerOffset: 0 + *fbCmdLayout.layout: horizontal { \ + 5 \ + vertical { 2 fbcOkay 2 } \ + 20 < +inf -20 > \ + vertical { 2 fbcHelp 2 } \ + 2 \ + vertical { 2 fbcDismiss 2 } \ + 5 \ + } + *fbcOkay.label: Okay + *fbcHelp.label: Help + *fbcDismiss.label: Dismiss + + + !-----------------------+ + ! Find Shell resources. | + !-----------------------+ + *findShell.title: Find within a document... + *findShell.width: 365 + *findShell.height: 130 + *findShell*borderWidth: 0 + *findShell*Group.frameType: chiseled + *findShell*Group.frameWidth: 2 + *findShell*Group.innerOffset: 5 + *findShell*Group.outerOffset: 2 + *findShell*Command.internalheight: 4 + *findShell*Text*editType: edit + *findShell*Text*height: 25 + *findShell*TextToggle.frameWidth: 0 + *findShell*Group.label: + *fsLayout.layout: vertical { \ + findGroup < +inf -inf * > \ + findCmdGroup < +inf -inf * > \ + } + + *findLayout*location: 0 0 120 25 + *findLayout*offIcon: diamond0s + *findLayout*onIcon: diamond1s + *findLayout*highlightColor: yellow + *findLayout*Label.height: 35 + *findLayout*Label.justify: right + *findLayout*TextToggle.frameWidth: 0 + *findLayout*TextToggle.leftMargin: 4 + *findLayout*TextToggle*highlightColor: yellow + *findLayout*TextToggle*onIcon: square1s + *findLayout*TextToggle*offIcon: square0s + *findLayout.layout: vertical { \ + 5 \ + horizontal { \ + findLabel 7 findFrame < +inf -inf * > -1 \ + } \ + 5 \ + horizontal { \ + 20 < +inf -20 > \ + findDir 10 findCase \ + 20 < +inf -20 > \ + } \ + } + *findLabel.label: Find: + *findFrame.frameType: sunken + *findFrame.frameWidth: 1 + *findEntry*string: + *findDir.label: Find Backwards + *findCase.label: Case Sensitive + + *findCmdLayout.layout: horizontal { \ + 3 \ + findOkay \ + 20 < +inf -20 > \ + findClear \ + 20 < +inf -20 > \ + findDismiss \ + 3 \ + } + *findOkay.label: Find + *findClear.label: Clear + *findDismiss.label: Dismiss + + + !-------------------------------------------+ + ! Set the document source viewer resources. | + !-------------------------------------------+ + *doc_source.title: Page source + *doc_source.width: 575 + *doc_source.height: 450 + *srcLayout*borderWidth: 0 + *srcLayout.layout: vertical { \ + srcMenuFrame < +inf -inf * > \ + -2 \ + srcFrame < +inf -inf * +inf -inf > \ + -2 \ + } + + *srcMenuBar.layout: horizontal { 50 < +inf -inf > srcDismiss 5 } + *srcMenuFrame.height: 40 + *srcMenuFrame.outerOffset: 0 + *srcMenuFrame.innerOffset: 5 + *srcMenuFrame.frameType: chiseled + *srcMenuFrame.frameWidth: 2 + *srcFrame.frameType: sunken + *srcFrame.frameWidth: 1 + *srcFrame.outerOffset: 5 + *srcText*scrollVertical: always + *srcText*scrollHorizontal: always + *srcText*Scrollbar.width: 15 + *srcText*Scrollbar.height: 15 + *srcText*background: gray75 + *srcText*font: 7x13 + *srcText*editType: read + *srcText*displayCaret: False + *srcDismiss.label: Dismiss + *srcDismiss.width: 150 + + + !-------------------------+ + ! Search Shell resources. | + !-------------------------+ + *searchShell.title: Search for a topic... + *searchShell.width: 600 + *searchShell.height: 250 + *searchShell*borderWidth: 0 + *searchShell*Viewport.allowVert: True + *searchShell*Viewport.allowHoriz: True + *searchShell*Viewport.useBottom: True + *searchShell*Viewport.useRight: False + *searchShell*Viewport.forceBars: True + *searchGroup.frameType: chiseled + *searchGroup.frameWidth: 2 + *searchGroup.innerOffset: 7 + *searchGroup.outerOffset: 7 + *searchGroup.highlightThickness: 0 + *searchGroup.label: + *searchLayout.layout: vertical { \ + horizontal { \ + 45 < +45 -45 > \ + resLabel < +inf -inf * > \ + 5 < +inf -inf > \ + exactMatch \ + } \ + 2 < +2 - 2 > \ + resFrame < +inf -inf * +inf -inf > \ + 5 < +5 - 5 > \ + horizontal { \ + searchLabel 5 searchFrame \ + 5 \ + searchClear 2 searchOkay \ + 5 < +inf -inf > \ + searchStatus \ + 5 < +inf -inf > \ + searchHelp 2 searchDismiss \ + } \ + } + *resLabel.label: Task Package Description + *resLabel.justify: left + *resFrame.frameType: sunken + *resFrame.frameWidth: 1 + *resList.font: 7x13 + *resList.width: 100 + *resList.height: 100 + *resList.marginWidth: 5 + *resList.marginHeight: 5 + + *searchLabel.label: Topic: + *searchFrame.frameType: sunken + *searchFrame.frameWidth: 1 + *searchEntry*font: 7x13 + *searchEntry*displayCaret: True + *searchEntry*editType: edit + *searchEntry*height: 25 + *searchEntry*width: 150 + *searchClear.label: Clear + *searchOkay.label: Search + *searchStatus.label: + *exactMatch.label: Require Exact Match + *exactMatch*on: 1 + *exactMatch*onIcon: diamond1s + *exactMatch*offIcon: diamond0s + *exactMatch*highlightColor: green + *exactMatch.frameWidth: 2 + *exactMatch.frameType: chiseled + *exactMatch.location: 0 0 150 25 + *exactMatch.leftMargin: 4 + *searchHelp.label: Help + *searchDismiss.label: Dismiss + + + !---------------- + ! Help Window. + !---------------- + *hlpShell.title: Help + *hlpShell.width: 500 + *hlpShell.height: 620 + *hlpLayout*borderWidth: 0 + *hlpLayout*Frame*frameType: sunken + *hlpLayout*Frame*frameWidth: 1 + + *hlpMenuGroup.label: + *hlpMenuGroup.outerOffset: 0 + *hlpMenuGroup.innerOffset: 0 + *hlpLayout.layout: vertical { \ + hlpMenuGroup < +inf -inf * > \ + -3 \ + hlpTextFrame < +inf -inf * +inf -inf > \ + horizontal { \ + 5 \ + hfLabel 5 hfFrame < +inf -inf *> \ + 2 \ + hfFind 2 hfClear 5 hfDir 5 hfCase \ + 5 \ + } \ + 2 \ + } + *hlpLayout*TextToggle*location: 0 0 90 25 + *hlpLayout*TextToggle*offIcon: diamond0s + *hlpLayout*TextToggle*onIcon: diamond1s + *hlpLayout*TextToggle*highlightColor: yellow + *hlpLayout*TextToggle*frameType: chiseled + *hlpLayout*TextToggle*frameWidth: 2 + *hfEntry*editType: edit + *hfEntry*font: 7x13 + *hfEntry*displayCaret: True + *hfLabel.label: Find: + *hfFind.label: Find + *hfClear.label: Clear + *hfDir.label: Backwards + *hfCase.label: Caseless + *hfCase.on: true + + *hlpMenu*Command.internalHeight: 4 + *hlpMenu*Command.highlightThickness: 1 + *hlpMenu*Command.height: 20 + *hlpMenu.layout: vertical { \ + 5 \ + horizontal { \ + 5 \ + hlpBack 2 hlpForward 2 hlpHome 2 hlpTutorial \ + 20 < +inf -20 > \ + hlpDismiss \ + 5 \ + } \ + 5 \ + } + *hlpBack.label: Back + *hlpBack.sensitive: False + *hlpForward.label: Forward + *hlpHome.label: Home + *hlpTutorial.label: Tutorial + *hlpTutorial.sensitive: false + *hlpDismiss.label: Dismiss + + *hlpTextFrame.outerOffset: 2 + *hlpText.width: 500 + *hlpText.height: 500 + *hlpText.anchorUnderlines: 1 + *hlpText.visitedAnchorUnderlines: 1 + *hlpText.verticalScrollOnRight: true + + + !------------------+ + ! File List dialog. + !------------------+ + *fileShell.title: Help Files + *fileShell.geometry: 500x165 + *fileShell*borderWidth: 0 + *fileShell*Command.width: 90 + *fileShell*Command.height: 30 + *fileShell*Frame.frameType: sunken + *fileShell*Frame.frameWidth: 1 + *fileShell*Frame.innerOffset: 1 + *fileShell*Text*font: 7x13 + *flist.layout: vertical { \ + 1 \ + horizontal { 1 flGroup < +inf -inf * +inf -inf> 1 } \ + 1 \ + } + + *flGroup.frameType: chiseled + *flGroup.frameWidth: 2 + *flGroup.innerOffset: 5 + *flGroup.outerOffset: 5 + *flGroup.label: + *flFrame.layout: vertical { \ + 5 \ + horizontal { \ + 13 \ + flistLabel < +inf -inf * > \ + 5 < +inf -5 > \ + } \ + 2 \ + horizontal { 1 flistFrame < +inf -inf * +inf -inf > 1 } \ + 7 \ + horizontal { \ + 5 \ + flpkgLabel 2 flpkgVal < +inf -inf * > \ + 5 < +inf -5 > \ + flDismiss \ + 5 \ + } \ + } + *flDismiss.label: Dismiss + *flistLabel.label: Option Status Filename + *flistLabel.justify: left + *flpkgLabel.label: Task: + *flpkgLabel.justify: left + *flpkgVal.label: (Undefined) + *flpkgVal.justify: left + *flpkgVal*font: 7x13 + *flistText.label: + *flistText.scrollVertical: Never + *flistText.scrollHorizontal: whenNeeded + *flistText*displayCaret: False + *flistText*editType: edit + + + !----------------+ + ! WARNING dialog. + !----------------+ + *warning.geometry: +400+300 + *warning*borderWidth: 0 + *warning*TextBox.frameWidth: 0 + *warning*Command.width: 90 + *warning*Command.height: 30 + *warning*Frame.frameType: sunken + *warning*Frame.frameWidth: 1 + *warning*Frame.innerOffset: 3 + *warn.layout: vertical { \ + 5 \ + horizontal { \ + 5 \ + warnFrame < +inf * +inf > \ + 5 \ + } \ + 5 \ + horizontal { \ + 5 < +inf -5 > \ + warnBtnFrame \ + 5 < +inf -5 > \ + } \ + 5 \ + } + + *WFlayout.layout: horizontal { \ + 5 \ + vertical { \ + 5 < +inf -5 > \ + warnIcon \ + 5 < +inf -5 > \ + } \ + 5 \ + warnText < +inf -inf * +inf -inf > \ + 5 \ + } + *warnIcon.location: 0 0 40 40 + *warnIcon.image: WARNING + *warnText.label: generic warning text + *warnText.width: 270 + *warnText.height: 60 + *warnText*background: gray75 + *warnDismiss.label: Dismiss + + !-------------------------- + ! Define a Debug Tcl shell. + !-------------------------- + *tclShell.width: 550 + *tclShell.height: 180 + *tclShell.title: TCL Command Entry Shell + *tclLayout*borderWidth: 0 + *tclLayout*Frame.frameType: sunken + *tclLayout*Frame.frameWidth: 1 + *tclLayout.layout: vertical { \ + tclCmdGroup < +inf -inf * > \ + tclFrame < +inf -inf * +inf -inf> \ + } + *tclEntry*editType: edit + *tclEntry*type: string + *tclEntry*scrollVertical: Always + *tclEntry*scrollHorizontal: whenNeeded + + *tclCmdGroup.label: + *tclCmdGroup.outerOffset: 0 + *tclCmdGroup.innerOffset: 0 + *tclCmd.layout: vertical { \ + 5 \ + horizontal { \ + 5 \ + tclClear 3 tclExecute \ + 10 < +inf -10> \ + tclLogging 3 tclDismiss \ + 5 \ + } \ + 5 \ + } + *tclClear.label: Clear + *tclExecute.label: Execute + *tclLogging.label: Enable Logging + *tclDismiss.label: Dismiss +} + + + +################################################################################ + +createObjects + +# Define Bitmaps and Pixmaps to be used. +createBitmap null 16 16 { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + +createBitmap check 16 16 { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, + 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x08, 0x06, 0x18, 0x03, 0xb0, 0x01, + 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00} + +createBitmap arrow 16 16 { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x14, 0xf8, 0x27, + 0x08, 0x40, 0xf8, 0x27, 0x00, 0x14, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + +activate + +################################################################################ + + +################################################################################ +# Global variables. | +################################################################################ +set version "IRAF Help GUI V1.0" ;# version string +set curpack "" ;# current values +set curtask "" +set helpType "package" ;# type of help to get +set helpOption "help" ;# help option param +set fileManaged 0 ;# is fileShell mapped? +set pkgList { } +set visited(0) empty + +set listOrient 1 ;# options +set showType 0 +set showFiles 1 +set exactMatch 1 + +set MAX_MENU_SIZE 40 ;# what it says it is + +# History array initialization. +set HPkg(0) {Home} ;# package +set HOpt(0) {help} ;# option +set HTask(0) {Home} ;# task +set HUrl(0) {} ;# url +set HType(0) {task} ;# type (task|package|file) +set HFile(0) {} ;# filename +set htop 0 ;# top of array +set hcurrent 0 ;# current page + +# Panel mapping flags. +set search_mapped 0 ;# searchShell mapped? + + +################################################################################ +# Utility Callbacks +################################################################################ + +# Procedures for sending client cursor commands. +proc GKey { key args } { send client gkey $key } +proc GCmd { args } { send client gcmd $args } + +# Procedures to test True/False strings in resources. +proc true { v } \ + { expr { $v=="true" || $v=="True" || $v=="TRUE" || $v==1 || $v=="yes" } } +proc false { v } \ + { expr { $v=="false" || $v=="False" || $v=="FALSE" || $v==0 || $v=="no" } } + +# No-op procedure for text widgets with no callbacks to swallow newline. +proc noop { args } { } + +# Common functions. +proc min { a b } { expr {($a < $b) ? $a : $b} } +proc max { a b } { expr {($a > $b) ? $a : $b} } + + +#--------------------+ +# Debugging options. | +#--------------------+ +set debug 0 ;# debug flag +send tclLogging set state [min 1 $debug] + + +################################################################################ +# Initialize. | +################################################################################ +proc Init args { + global history curpack curtask debug + global secMenuDescription parMenuDescription + global HPkg HTask HUrl HOpt HFile HType + + if {$debug == 1} { send tclShell map } + + # Reinitialize global vars in case of a restart. + set curpack "" + set curtask "" + set helpType "package" + set helpOption "help" + + # Initialize the entry strings. + send printEntry set string "" + send topicEntry set string "" + + # Initialize the various lists. + send topicList setList "{ }" resize + + send secButton set sensitive False + send parButton set sensitive False + editMenu secMenu secButton $secMenuDescription + editMenu parMenu parButton $parMenuDescription + +} ; #send server postActivateCallback Init + + + +# Create the Navigation Menu. +set navMenuDescription { + { "Back " f.exec { Back } + sensitive {([send htbButton isSensitive]==1) ? "true" : "false" } + } + { "Forward " f.exec { Forward } + sensitive {([send htfButton isSensitive]==1) ? "true" : "false" } + } + { "Up " f.exec { Up } + sensitive {([send htuButton isSensitive]==1) ? "true" : "false" } + } + { "Home " f.exec { Home } } + { f.dblline } + { "Reload " f.exec { Reload } } + { "Open File... " f.exec { Open } } + { "Save As... " f.exec { SaveAs } } + { "View Page Source " f.exec { srcOpen } } + { f.dblline } + { "Find... " f.exec { Find } } + { "Search... " f.exec { Search } } + { "Print... " f.exec { Print } } +} ; createMenu navMenu helpText $navMenuDescription + +# Create the default Section Menu. +set secMenuDescription { + { " Top of Page " f.exec { send helpText gotoId 0 } } + { f.dblline } + { " " f.exec { noop } } + { " No Sections Found " f.exec { noop } } + { " " f.exec { noop } } +} ; createMenu secMenu secButton $secMenuDescription + +# Create the default Parameter Menu. +set parMenuDescription { + { " No Parameters Found" f.exec { noop } } +} ; createMenu parMenu parButton $parMenuDescription + + +# Initialize. +Init + + +################################################################################ +# Menubar command callbacks. +################################################################################ + +# File Menu +set fileMenuDescription { + { " Open File... " f.exec { Open } } + { " Save As... " f.exec { SaveAs } } + { " Print... " f.exec { Print } } + { f.dblline } + { " Reload... " f.exec { Reload } } + { " View Page Source " f.exec { srcOpen } } + { " Search... " f.exec { Search } } + { " Find... " f.exec { Find } } + { f.dblline } + { " Help " f.exec { Help } } + { " Quit " f.exec { Quit } } +} ; createMenu fileMenu fileButton $fileMenuDescription + + +# History Menu +set historyMenuDescription { + { " Back " f.exec { Back } + sensitive {([send htbButton isSensitive]==1) ? "true" : "false" } + } + { " Forward " f.exec { Forward } + sensitive {([send htfButton isSensitive]==1) ? "true" : "false" } + } + { " Up " f.exec { Up } + sensitive {([send htuButton isSensitive]==1) ? "true" : "false" } + } + { " Home " f.exec { Home } } + { f.dblline } + { " Clear History" f.exec { histClear } } + { f.dblline } +} ; createMenu historyMenu historyButton $historyMenuDescription + + +# Options Menu +set optsMenuDescription { + { " Show task type " f.exec { setOpts showType } + bitmap {($showType==1)? "check" : "null"} } + { " Show missing files " f.exec { setOpts showFiles } + bitmap {($showFiles==1)? "check" : "null"} } + { f.dblline } + { " Vertical task listing " f.exec { setOpts verticalList True } + bitmap {($listOrient==1)? "check" : "null"} + } + { " Horizontal task listing " f.exec { setOpts verticalList False } + bitmap {($listOrient==0)? "check" : "null"} + } + { f.dblline } + { " Tcl Command Shell " f.exec { tclOpen } } +} ; createMenu optsMenu optionsButton $optsMenuDescription + + +proc setOpts { opt args } { + global optsMenuDescription + global listOrient showType showFiles + global HTask HPkg HOpt hcurrent + + switch $opt { + showType { set showType [expr { ($showType == 1) ? 0 : 1 } ] + GCmd type $showType + set h $hcurrent + GCmd help $HTask($h) $HPkg($h) $HOpt($h) + } + showFiles { set showFiles [expr { ($showFiles == 1) ? 0 : 1 } ] + } + verticalList { set listOrient [expr { ($args == "False") ? 0 : 1 } ] + send topicList set verticalList $args + } + } + editMenu optsMenu optionsButton $optsMenuDescription +} + +proc Print args { + send printShell map +} ; send printButton addCallback Print + +proc Find { args } { + send findShell popup +} ; send findButton addCallback Find + +proc Search { args } { + global search_mapped + + send searchShell map + set search_mapped 1 +} ; send searchButton addCallback Search + +proc Reload args { + global HPkg HType HUrl HOpt HTask HFile hcurrent + + if { $HType($hcurrent) == "file"} { + if {[info exists HFile($hcurrent)] == 1} { + GCmd directory open $HFile($hcurrent) + } else { + setAlert param old [format "HFile param at %d not found" $hcurrent] + } + } else { + loadHistItem $hcurrent $HPkg($hcurrent) $HTask($hcurrent) \ + $HOpt($hcurrent) $HType($hcurrent) $HUrl($hcurrent) + } +} ; send reloadButton addCallback Reload + +proc Help args { + send hlpShell map +} ; send helpButton addCallback Help + +proc Open args { + send fmtGroup unmap + send fmtGroup set height 0 + send fbcOkay set label Load + send fileBrowser map +} + +proc SaveAs args { + global format + + # Reset the default format every time we open. + send $format set on 0 + set format fmtSrc + send $format set on 1 + + # If there's no filename specified set one as a default. + setDefaultFname + + send fmtGroup map + send fmtGroup set height 65 + send fbcOkay set label Save + send fileBrowser map +} + +proc Quit args { + GCmd quit + deactivate unmap +}; send quitButton addCallback Quit + + + +################################################################################ +# Callbacks for client state variables (UI parameter objects). When the +# client's state changes it updates a UI parameter to reflect the change. +# This produces a callback to one or more of the callbacks defined below, +# used to update the GUI to reflect the changing state of the client. +################################################################################ + +proc setShowType { param old new } { + global showType listOrient showFiles optsMenuDescription + set showType $new + editMenu optsMenu optionsButton $optsMenuDescription +}; send showtype addCallback setShowType + +proc setTopics { param old new } { + global pkgList + set pkgList $new + send topicList setList $new resize +}; send pkglist addCallback setTopics + +proc appendHist { param old new } { + global helpType helpOption curtask curpack + + if {$new == "package"} { + #addHistRecord $curpack $curpack "" $helpOption "" $helpType + addHistRecord $curpack $curpack "" $helpOption "" "package" + } elseif {$new == "append"} { + # We've got a result of some kind and all of the values have been + # set, so create a history record. + if {$curpack != "" && $curtask != ""} { + addHistRecord $curpack $curtask "" $helpOption "" $helpType + } + } +}; send history addCallback appendHist + +proc setCurpack { param old new } { + global curpack + + if { $new != [getPkgName $curpack] } { + if { $curpack != "" && \ + $curpack != "clpackage" && \ + [string match "root*" $new] != 1} { + set curpack [ format "%s.%s" $curpack $new] + send htuButton set sensitive true + } else { + set curpack $new + } + } +}; send curpack addCallback setCurpack + + +proc setCurtask { param old new } { + global curtask curpack helpType + + if {$helpType == "package"} { + send topicEntry set string $curpack + } else { + send topicEntry set string [ format "%s.%s" $curpack $new ] + } + + # Update the printer dialog so the filename defaults to the curtask. + if { [send toFile get on] } { + if {$HType($hcurrent) == "file" || [send srcOpt get on] == 1} { + send printEntry set string [format "%s" [fileSource] ] + } else { + send printEntry set string [format "%s.ps" $new] + } + } else { + send printEntry set string "printer" + } + set curtask $new +}; send curtask addCallback setCurtask + + +proc getPkgName { pkg } { + set last [ string last "." $pkg ] + if { $last > -1 } { + return [ string range $pkg [incr last] end ] + } else { + return $pkg + } +} + +proc getParentName { pkg } { + set last [ string last "." $pkg ] + if { $last > -1 } { + set root [ string range $pkg 0 [incr last -1] ] + } else { + set root $pkg + } + return [getPkgName $root] +} + + +# Topic list selection callback. +proc topicSelect { widget event args } { + global htop hcurrent curpack curtask helpOption helpType + global visited + + # If we're currently positioned somewhere in the middle of the + # history menu, push the current page to the history list before + # getting the next result. + if {$htop != $hcurrent} { + addHistRecord $curpack $curtask "" $helpOption "" $helpType + send htbButton set sensitive True + send htuButton set sensitive True + } + + set item [string trimright [send topicList getItem itemno] "."] + send topicList getItem itemno + if { $itemno != "none" } { + GCmd help $item $curpack $helpOption + set visited($item) 1 + } +} ; send topicList addEventHandler topicSelect buttonReleaseMask + +proc listViewResize { args } { + global pkglist + send topicList setList $pkglist resize +} ; send listView addEventHandler listViewResize ResizeRedirectMask + + +# Get help for a specific topic from the topic entry widget. +proc getTopicHelp { widget mode topic args } { + global curpack helpOption + + if { [string match "*\.*" $topic] == 1} { + set pkglist [ split $topic "." ] + set pack [lindex $pkglist [expr {[llength $pkglist] - 2}] ] + set task [lindex $pkglist [expr {[llength $pkglist] - 1}] ] + set curpack $pack + GCmd help $task $curpack $helpOption + } else { + set curtask "" + set curpack "" + GCmd help $topic $curpack $helpOption + } +} ; send topicEntry addCallback getTopicHelp + +proc topicClear { args } { + send topicEntry set string "" +} ; send topicClear addCallback topicClear + + + +################################################################################ +# Help text and HTML processing procedures. +################################################################################ + +proc setHelpResult { param old new } { + global helpType helpOption curtask curpack + global secMenuDescription parMenuDescription + global pkgList debug + + # Debug status + if {$debug == 1} { + send tclEntry append \ + [format "helpres: type=%1.1s opt=%4.4s curtask=%s curpack=%s\n" \ + $helpType $helpOption $curtask $curpack ] + print [format "helpres: type=%1.1s opt=%4.4s curtask=%s curpack=%s\n" \ + $helpType $helpOption $curtask $curpack ] + } + + if { [string match "*<HTML>*" $new] == 1} { + # Strip the header table. + if {[ string match "*TABLE*" $new] == 1 } { + set new_start [expr [string first "</TABLE>" $new] + 12] + set text [ filterBraces [string range $new $new_start end] ] + } else { + set text [ filterBraces $new ] + } + + # Got HTML directly from the client. + send helpText setText [format "<HTML><BODY>\n%s" $text ] + + # Save the source for the viewer + set docSrc \ + [ format "<HTML><BODY>\n%s\n</BODY></HTML>\n" $text] + + # Parse the file for menu items. + setSectionMenu $new + setParameterMenu $new + + } else { + # Disable help page content buttons for plain text. + send parButton set sensitive False + send secButton set sensitive False + editMenu secMenu secButton $secMenuDescription + editMenu parMenu parButton $parMenuDescription + + # Filter plaintext .men files into something with links, otherwise + # unescape the curly braces used to pass the text through Tcl. + if {$helpType == "package"} { + set str [ filterLinks [ filterTcl $new ] ] + } else { + set str [ filterTcl $new ] + } + + # Load the results + send helpText setText "<HTML><BODY><PRE>\n$str\n</PRE></BODY></HTML>" + + # Save the source for the viewer + set docSrc \ + [ format "<HTML><BODY><PRE>\n%s\n</PRE></BODY></HTML>\n" $str] + } + send helpText retestAnchors + send srcText set string $docSrc + + # See which files associated with this topic are available. We turn off + # the option toggles first so they can be reset as needed by the client. + if {$helpOption != "sysdoc"} {send sysOpt "set sensitive False ; set on 0" } + if {$helpOption != "source"} {send srcOpt "set sensitive False ; set on 0" } + + if {$helpType == "package"} { + set parent [getParentName $curpack] + if {$parent == "clpackage" || [string match "root*" $parent] == 1} { + GCmd files $curtask "clpackage" + } else { + GCmd files $curtask $parent + } + } else { + GCmd files $curtask [string range $curpack \ + [expr {[string last "." $curpack ] + 1}] end] + } + + # Highlight the package list item. + for {set i 0} {$i < [llength $pkgList]} {incr i} { + if {[lindex $pkgList $i] == $curtask } { + send topicList highlight $i + break + } + } + printHistStack "helpres " + +}; send helpres addCallback setHelpResult + + +# Set an arbitrary TextToggle widget highlight color. +proc setOptColor { widget color args } { + send $widget "set on 1 ; \ + set offIcon diamond0s ; \ + set highlightColor $color ; \ + set background gray75 ; \ + set onIcon diamond1s ; \ + set highlightColor $color ; \ + set background gray75" +} + + +# Set the file options for the files that were found to be valid (i.e. +# they're listed in the files output and actually exist). +proc setHelpFileOpts { param old new } { + global helpType helpOption curtask curpack + global showFiles + + set opt [lindex $new 0] + set val [lindex $new 1] + if {$opt != "file"} { set stat [lindex $new 2] } + + # Set the option toggles according to valid files. + if {$opt == "sys" && $stat == 0} { + send sysOpt set sensitive True + } elseif {$opt == "sys" && $stat == 1 && $showFiles == 1} { + setOptColor sysOpt yellow + } + if {$opt == "src" && $stat == 0} { + send srcOpt set sensitive True + } elseif {$opt == "src" && $stat == 1 && $showFiles == 1} { + setOptColor srcOpt yellow + } + + # Update the help files panel text. + if {$opt == "file"} { + set pkg [ string trimright $val ":"] + send flpkgVal set label [ format "%s" $pkg ] + send toplevel set title [format "XHelp: %s" $pkg ] + send flistText set string "" + } else { + send flistText append [ format " %5.5s %-7.7s %s\n" \ + $opt \ + [ expr { ($stat == 0) ? "Okay" : "Error" }] \ + $val] + } + +} ; send helpfiles addCallback setHelpFileOpts + + +# Process an HREF link selection. URLs are assumed to be of the form +# +# <pkgname>.<task> +# <task> +# '#'<hname> +# +# If an internal link is found as in the last case we ignore any defined +# package/task given, otherwise load the selected page. + +proc textAnchorSelected {widget cbtype event text href args} { + global HPkg HType HUrl HOpt HTask HFile hcurrent htop + global curpack helpOption visited + + set visited($href) 1 + send helpText retestAnchors + + if {[string match "*#*" $href] == 1} { + set link [string range $href [expr [string first "#" $href] + 1] end ] + set HUrl($hcurrent) $link + send helpText gotoId [ send helpText anchorToId $link ] + } else { + if { [string match "*\.*" $href] == 1} { + set pack [lindex [split $href "."] 0] + set task [lindex [split $href "."] 1] + set curpack $pack + GCmd help $task $curpack $helpOption + + } else { + GCmd help $href $curpack $helpOption + } + } + + if {$hcurrent <= $htop} { + set h $hcurrent + addHistRecord $HPkg($h) $HTask($h) $HUrl($h) $HOpt($h) \ + HFile($h) $HType($h) + } + +}; send helpText addCallback textAnchorSelected anchor + + +# Remove only the escaped curly braces. Used to filter HTML text passed to +# the GUI with escapes in it. + +proc filterBraces { istr args } { + if {$istr != ""} { + regsub -all {(\\\{)} $istr "\{" v1 + regsub -all {(\\\})} $v1 "\}" results + return $results + } +} + +# Remove the backslash escapes from source files, escape special chars for +# presentation on an HTML widget. + +proc filterTcl { istr args } { + if {$istr != ""} { + regsub -all {(\\\{)} $istr "\{" v1 + regsub -all {(\\\})} $v1 "\}" v2 + regsub -all {(\<)} $v2 "\\<" v3 + regsub -all {(\>)} $v3 "\\>" results + return $results + } +} + + +# Scan a plaintext doc to see if maybe this is a package help menu. We use +# some assumption that most of the lines will be of the form "task '-' desc" +# then parse the file resetting all of the 'task' names as HREFs for other +# tasks. + +proc filterLinks { istr args } { + + set lines [split $istr "\n"] + set blank " " + set results { } + lappend results "" + foreach i $lines { + set line [string trimleft [detab $i] ] + if {[regexp {(^[a-zA-Z0-9\ \_\(\)]+[\+|\-]*)} $line arg] == 1 && + ([string match "*\-*" $arg] == 1 || + [string first "\*" $line] > 0 || + [string match "*\+*" $arg] == 1) } { + + set task [string trim [string trimright $arg "-+"] ] + set l [string first "-" $line] + if {$l == -1} { + set l [string first "+" $line] + if {$l == -1} { + set l [string first "\*" $line] + } + } + set desc [ string range $line $l end ] + + # We now have the task name and the description string, format + # on output with the HREF defined. + set nblanks [expr 13 - [string length $task] ] + set fmtstr [format "%%%ds<A HREF=\"%%s\">%%s</A> %%s\n" $nblanks ] + set ostr [format $fmtstr $blank $task $task $desc] + + lappend results $ostr + + } elseif {[regexp {(^[a-zA-Z0-9\_]+\.[a-zA-Z0-9\_]+\:$)} $i val] == 1} { + + # Break out the task and package names. + regsub -all {[\.:]} $i " " val + scan $val "%s %s" parent child + + # Format a URL and append the results. + if { [ string match "*root*" $parent] == 0} { + set ref [format "<A HREF=\"%s\">%s</A>.<A HREF=\"%s\">%s</A>:\n"\ + $parent $parent $child $child ] + } else { + set ref [format "%s.<A HREF=\"%s\">%s</A>:\n"\ + $parent $child $child ] + } + lappend results $ref + + } else { + set nblanks [expr [string length $i] - [string length $line] ] + set fmtstr [format "%%%ds%%s\n" $nblanks ] + lappend results [format $fmtstr $blank $line ] + } + } + return [ join $results ] +} + + +# Generated a list of the lines and create the section menu. + +proc setSectionMenu { text args } { + global secMenuDescription + + # Break out the table of contents from the string. Note we're hard- + # wired here into the form of the comment string used to contain the + # section name. + set l [expr [string first "<! Contents: " $text] + 12] + if {$l == 0} { return } + set s [string range $text $l end] + set r [expr [string first ">" $s] - 4] + set t [string range $s 0 $r] + set lst [split $t '\''] + + # Now take the list generated and create the menu. + set items { } + lappend items " \"Top of Page\" f.exec \{ send helpText gotoId 0 \}" + lappend items " f.dblline " + foreach i $lst { + if {$i != " "} { + set i [ string trimright $i ] + regsub -all {[ ,.():;]} [string tolower $i] _ url + lappend items " \" $i \" f.exec \{ jumpToName #s_$url \}" + } + } + + if { [llength $items] == 3 } { + send secButton set sensitive False + editMenu secMenu secButton $secMenuDescription + } else { + editMenu secMenu secButton $items + send secButton set sensitive True + } +} + + +# Generated a list of the lines and create the parameter menu. +proc setParameterMenu { text args } { + global parMenuDescription + set items { } + foreach i [split $text "\n"] { + if {[string match "\<\! Sec*PARAMETERS*Level=0*" $i] == 1} { + set l [expr [string first "Line='" $i] + 6] + set s [string range $i $l end] + set r [expr [string first "\'" $s] - 1] + set t [string range $s 0 $r] + regsub -all {[\ ]} $t " " d ;# remove tabs + regsub -all {[\"]} $d "\\\"" entry + + set l [expr [string first "Label='" $i] + 7] + set s [string range $i $l end] + set r [expr [string first "\'" $s] - 1] + set t [string range $s 0 $r] + + lappend items " \"$entry\" f.exec \{ jumpToName #l_$t \}" + } + } + + if { [llength $items] == 0 } { + send parButton set sensitive False + editMenu parMenu parButton $parMenuDescription + } else { + editMenu parMenu parButton $items + send parButton set sensitive True + } +} + + +# Position the page to the requested href name. +proc jumpToName { name } { + global curtask curpack helpType helpOption + + send helpText gotoId [send helpText anchorToId $name] + send helpText retestAnchors + + # Now add a history record for the jump + addHistRecord $curpack $curtask $name $helpOption "" $helpType +} + + +# Utility routine to 'detab' a line and preserve format. +proc detab {str {tablen 8}} { + set a 0 + set i [string first "\t" $str] + while {$i != -1} { + set m { } + set j $i + while {[incr j] % $tablen} { append m { } } + set str [string range $str $a \ + [expr {$i-1}]]$m[string range $str [incr i] end] + set i [string first "\t" $str] + } + return $str +} + + +################################################################################ +# Navigation and History Callbacks +################################################################################ + +# Go back one page. +proc Back args { + global curtask curpack helpType helpOption + global HPkg HType HUrl HOpt HTask HFile htop hcurrent + + incr hcurrent -1 + if {$hcurrent >= 0} { + set item $HTask($hcurrent) + set pkg $HPkg($hcurrent) + set type $HType($hcurrent) + set h $hcurrent + + if { $item == "Home" } { + loadHomePage + } else { + if { $HType($h) == "file"} { + if {[info exists HFile($h)] == 1} { + loadHistItem $h pkg $HFile($h) help file + } else { + setAlert param old \ + [format "HFile param at %d not found" $hcurrent] + } + } else { + loadHistItem $h $HPkg($h) $HTask($h) $HOpt($h) \ + $HType($h) $HUrl($h) + } + } + + if {$hcurrent == 0} { + send htbButton set sensitive False + send htuButton set sensitive False + } + if {$hcurrent >= 0} { + send htfButton set sensitive True + send htuButton set sensitive True + } + } else { + set hcurrent 0 + } + editHistoryMenu + printHistStack "Back " +} ; send htbButton addCallback Back + + +# Go forward one page. +proc Forward args { + global curtask curpack helpType helpOption + global HPkg HType HUrl HOpt HTask HFile htop hcurrent + + incr hcurrent + if {$hcurrent <= $htop} { + set item $HTask($hcurrent) + set pkg $HPkg($hcurrent) + set type $HType($hcurrent) + set h $hcurrent + + if { $item == "Home" } { + loadHomePage + } else { + if { $HType($h) == "file"} { + if {[info exists HFile($h)] == 1} { + loadHistItem $h pkg $HFile($h) help file + } else { + setAlert param old \ + [format "HFile param at %d not found" $hcurrent] + } + } else { + loadHistItem $h $HPkg($h) $HTask($h) $HOpt($h) \ + $HType($h) $HUrl($h) + } + } + + if {$hcurrent == $htop } { + send htfButton set sensitive False + send htbButton set sensitive True + } else { + send htbButton set sensitive True + } + } else { + incr hcurrent -1 + } + editHistoryMenu + printHistStack "Forward " +} ; send htfButton addCallback Forward + + +# Go up to previous package, skipping over pages inbetween. +proc Up args { + global curtask curpack helpType helpOption + global HPkg HType HUrl HOpt HTask htop hcurrent + + # From the current page go back until we find a package + if {$HType($hcurrent) == "package"} { + set i [expr {$hcurrent-1} ] + } else { + set i $hcurrent + } + while {$HType($i) != "package" && $i >= 0} { + incr i -1 + } + + # Found package, go get it. + set hcurrent $i + if {$i == 0} { + loadHomePage ;# push a history record?? + } else { + GCmd load $HTask($i) [getPkgName $HPkg($i)] $HOpt($i) + } + + set curtask $HTask($hcurrent) ;# update the state of things + set curpack $HPkg($hcurrent) + set helpOption $HOpt($hcurrent) + set helpType $HType($hcurrent) + + send topicEntry set string $curpack ;# update topic entry string + + if {$hcurrent == 0} { ;# adjust navigation buttons + send htbButton set sensitive False + send htuButton set sensitive False + } + if {$hcurrent >= 0} { + send htfButton set sensitive True + send htuButton set sensitive True + } + editHistoryMenu + printHistStack "Forward " +} ; send htuButton addCallback Up + + +# Go straight to the homepage. +proc Home args { + global curtask curpack helpType helpOption + global HPkg HType HUrl HOpt HTask HFile htop hcurrent + + # Load the homepage. + loadHomePage + + # A Home command jumps over everything in the history list but we + # need to push a history record for it anyway. + addHistRecord $HPkg(0) $HTask(0) $HUrl(0) $HOpt(0) $HFile(0) $HType(0) + + send topicEntry set string "" + set curtask "" + set curpack "" + set helpType "package" + set helpType "help" +} ; send hthButton addCallback Home + + +# Load the homepage. +proc loadHomePage { args } { + global curtask curpack version showType + + GCmd help Home + + # Clean up. + set curtask "" + set curpack "" + send topicEntry set string "" + send toplevel set title $version +} + +# Clear all the history information. +proc histClear args { + global HPkg HType HUrl HOpt HTask HFile htop hcurrent + global visited + + # Clear the visited anchors list. + foreach i [array names visited] { + unset visited($i) + } + + # Clear the history stack. + for { set i [expr {$htop -1}] } { $i >= 0 } { incr i -1 } { + catch { + unset HType($i) + unset HOpt($i) + unset HTask($i) + unset HPkg($i) + unset HUrl($i) + unset HFile($i) + } + } + + # Reinitialize, but save the current page as the new history stack. + catch { + set HPkg(0) $HPkg($htop) ;# package + set HOpt(0) $HOpt($htop) ;# option + set HTask(0) $HTask($htop) ;# task + set HUrl(0) $HUrl($htop) ;# url + set HType(0) $HType($htop) ;# type + set HFile(0) $HFile($htop) ;# filename + } + set htop 0 + set hcurrent 0 + + # Update navigation options and history menu. + send htbButton set sensitive False + send htfButton set sensitive False + send htuButton set sensitive False + editHistoryMenu +} + + +# Push an item on the history stack. +proc addHistRecord { pkg task url opt file type } { + global HPkg HType HUrl HOpt HTask HFile htop hcurrent + global helpType helpOption + global historyMenuDescription + + # Push a new history record to the top of the stack and make that the + # current record. + incr htop + set HPkg($htop) $pkg + set HTask($htop) $task + set HUrl($htop) $url + set HOpt($htop) $opt + set HFile($htop) [ expr {($file == "") ? "none" : $file } ] + set HType($htop) $type + set hcurrent $htop + + # Activate the Back button. + if {$hcurrent == 1} { + send htbButton set sensitive True + if {$type == "package"} { + send htuButton set sensitive True + } + } + + # Edit the history menu. + editHistoryMenu + printHistStack "addHistRecord" +} + + +# Edit the history menu to reflect the current state. +proc editHistoryMenu { args } { + global HPkg HType HUrl HOpt HTask htop hcurrent + global helpType helpOption + global historyMenuDescription + global navMenuDescription + global MAX_MENU_SIZE + + set items $historyMenuDescription + set nitems 0 + if {$htop > $MAX_MENU_SIZE} { + set nstart [ min $htop [expr {$hcurrent + 3}] ] + } else { + set nstart $htop + } + for { set i $nstart } { $i >= 0 } { incr i -1 } { + set pkg $HPkg($i) + set task $HTask($i) + set type $HType($i) + set opt $HOpt($i) + set url $HUrl($i) + if {$pkg != "" || $type == "file"} { + if {$type == "task"} { + if {$url == ""} { + set entry [format "%-22.22s %4s" $task \ + [menuItemType $type $url $opt ] ] + } else { + set entry [format "%-22.22s %4s" \ + [ format "%s (%s)" $task [string trimleft $url "#"] ] \ + [menuItemType $type $url $opt ] ] + } + } elseif {$type == "package"} { + set entry [format "%-22.22s %4s" [getPkgName $pkg] \ + [menuItemType $type $url $opt ] ] + } elseif {$type == "file"} { + upvar #0 HFile file + set entry [format "%s" $file($i) ] + } else { + setAlert param old [format "Unknown help type: %s" $type] + } + + if {$type == "file"} { + lappend items " \" $entry \" f.exec \{ \ + loadHistItem $i pkg $entry help file \} \ + bitmap \{\($i==$hcurrent\) ? \"arrow\" : \"null\" \} " + } else { + lappend items " \" $entry \" f.exec \{ \ + loadHistItem $i [getPkgName $pkg] $task $opt $type $url \} \ + bitmap \{\($i==$hcurrent\) ? \"arrow\" : \"null\" \} " + } + } + + incr nitems 1 + if {$nitems > $MAX_MENU_SIZE} { + lappend items "f.dblline" + lappend items " \" History truncated... \" f.exec \{ \} " + break + } + } + editMenu historyMenu historyButton $items + + # Edit the navigation menu to get the sensitivities right for + # the current state. + editMenu navMenu helpText $navMenuDescription +} + + +# Utility routine to set the history item entry type. +proc menuItemType { type url opt } { + if {$url != ""} { + return [format "Link"] + } + + switch $opt { + "help" { return [format "%s" [expr {($type=="task")?"Task":"Pkg"} ]] } + "source" { return [format "(src)"] } + "sysdoc" { return [format "(sys)"] } + } +} + + +# Load a particular page/link from the history list. +proc loadHistItem { itemno pkg task opt type args } { + global HPkg HType HUrl HOpt HTask htop hcurrent + global curtask curpack helpType helpOption hcurrent + global version + + # Load the requested page. Check whether we just need to jump to + # the current page. + if {$task == "Home"} { + loadHomePage + + } elseif {$type == "file"} { + GCmd directory open $task + + } elseif {$itemno == $hcurrent || \ + ($pkg != $curpack || \ + $task != $curtask || \ + $type != $helpType || \ + $opt != $helpOption) } { + GCmd load $task $pkg $opt + } + + # If the history item included an internal link, jump to it. The + # 'args' value will either be the URL or an empty string. + if {$args != ""} { + send helpText gotoId [send helpText anchorToId $args] + send helpText retestAnchors + } + + # Update the topic entry string. + if { $type == "task" } { + send topicEntry set string [ format "%s.%s" $pkg $task ] + } elseif { $type == "file" } { + send topicEntry set string $task + } else { + send topicEntry set string $pkg + } + + # Change the options button if needed. + if {$HOpt($itemno) != $helpOption} { + send [ getOptWidget $helpOption ] set on 0 + setOptColor [ getOptWidget $HOpt($itemno) ] green + } + + # Update the current entry. + set hcurrent $itemno + + if { $type != "file" } { + set curtask $HTask($hcurrent) + set curpack $HPkg($hcurrent) + set helpOption $HOpt($hcurrent) + set helpType $HType($hcurrent) + } else { + set helpOption "help" + set helpType "file" + } + + # Tweak the navigation buttons. + if {$hcurrent == 0} { + send htbButton set sensitive False + send htuButton set sensitive False + } + if {$hcurrent >= 0} { + send htfButton set sensitive True + send htuButton set sensitive True + } + if {$hcurrent == $htop } { + send htfButton set sensitive False + send htbButton set sensitive True + } + + # Edit the history menu. + editHistoryMenu +} + +# Initialize the history menu. +editHistoryMenu + +# Given the option type return the widget name. +proc getOptWidget { opt } { + switch $opt { + "help" { return "hlpOpt" } + "source" { return "srcOpt" } + "sysdoc" { return "sysOpt" } + } +} + +# Debug utility to print the history stack. +proc printHistStack { where args } { + global HPkg HType HUrl HOpt HTask HFile htop hcurrent + global debug + + # Print the stack... + if {$debug > 0} { + print "_______________________________________________________________" + print $where + for { set i $htop } { $i >= 0 } { incr i -1 } { + if {$HType($i) == "file"} { + upvar #0 HFile file + print [format "%3s%d: type=%1.1s file=%s\n"\ + [ expr {($i==$hcurrent) ? ">>>" : "---"} ] \ + $i $HType($i) $file($i) ] + } else { + print [format "%3s%d: type=%1.1s opt=%4.4s task=%s pack=%s\n"\ + [ expr {($i==$hcurrent) ? ">>>" : "---"} ] \ + $i $HType($i) $HOpt($i) $HTask($i) $HPkg($i) $HUrl($i) ] + } + } + } +} + +# Test whether an anchor has been visited. +proc testAnchor {widget cbtype href} { + global visited + return [info exists visited($href)] +} +send hlpText addCallback testAnchor testAnchor +send helpText addCallback testAnchor testAnchor +send resList addCallback testAnchor testAnchor + + +################################################################################ +# Options Menu +################################################################################ + +proc setType { param old new } { + global helpType + set helpType [string tolower $new ] +} ; send type addCallback setType + +proc selectOption { widget type value args } { + global curtask curpack helpOption + + if { $curtask != "" } { + foreach i { hlpOpt srcOpt sysOpt } { send $i set on 0 } + setOptColor $widget green + send $widget set on 1 + switch $widget { + hlpOpt { set helpOption help + send fmtText setSensitive true + send fmtPS setSensitive true + } + srcOpt { set helpOption source + send fmtText setSensitive false + send fmtPS setSensitive false + } + sysOpt { set helpOption sysdoc + send fmtText setSensitive true + send fmtPS setSensitive true + } + } + GCmd help $curtask [getParentName $curpack] $helpOption + } +}; foreach i {hlpOpt srcOpt sysOpt } { send $i addCallback selectOption } + +proc toggleFileOption { args } { + if { [ send filOpt get on] == 1 } { + send fileShell map + } else { + send fileShell unmap + } +} ; send filOpt addCallback toggleFileOption + +send flDismiss addCallback "send fileShell unmap ; send filOpt set on 0" + + +################################################################################ +# Procedure used by the printer prompt box. +################################################################################ + +proc setPrinterName { param old new } { + send printEntry set string $new +}; send printer addCallback setPrinterName + +set page_size pageLetter + +proc pageRadio { widget type state args } { + global page_size + + if {$state == 0} { + # Don't allow a button to be turned off. + send $widget set on 1 + } else { + send $page_size set on 0 + set page_size $widget + } +} +foreach w {pageLetter pageLegal pageA4 pageB5} { send $w addCallback pageRadio } + +proc toPrinterToggle args { + global curtask HType hcurrent + if { [send toPrinter get on] } { + send toFile set on False + send printLabel set label "Printer: " + send printEntry set string "printer" + } else { + send toFile set on True + send printLabel set label "File Name: " + if {$HType($hcurrent) == "file" || [send srcOpt get on] == 1} { + send printEntry set string [format "%s" [fileSource] ] + } else { + send printEntry set string [format "%s.ps" $curtask] + } + } +} ; send toPrinter addCallback toPrinterToggle + +proc toFileToggle args { + global curtask HType hcurrent + if { [send toFile get on] } { + send toPrinter set on False + send printLabel set label "File Name: " + if {$HType($hcurrent) == "file" || [send srcOpt get on] == 1} { + send printEntry set string [format "%s" [fileSource] ] + } else { + send printEntry set string [format "%s.ps" $curtask] + } + } else { + send toPrinter set on True + send printLabel set label "Printer: " + send printEntry set string "printer" + } +} ; send toFile addCallback toFileToggle + +proc doPrintOkay { args } { + global curtask curpack HType hcurrent + + set device [ send printEntry get string ] + if { [send toPrinter get on] } { + GCmd print $curtask $curpack $device + } else { + if {$HType($hcurrent) == "file" || [send srcOpt get on] == 1} { + GCmd directory save [fileSource] $fname 1 source + } else { + GCmd directory save [fileSource] $fname 1 postscript + } + } + send printShell unmap +} +send printOkay addCallback doPrintOkay +send printEntry addCallback doPrintOkay + +send printDismiss addCallback "send printShell unmap " + + +################################################################################ +# Procedures used by the fileBrowser. +################################################################################ + +# File browsing globals +set curdir "" ;# current directory +set pattern "*" ;# filename template +set format "fmtSrc" ;# SaveAs format + + +# Browser selection callback. +proc browserSelect { widget event args } { + global curdir helpOption + + set opt [expr {$widget == "dirList" ? "dirlist" : "loadfile"}] + set item [send $widget getItem itemno] + send $widget getItem itemno + set mode [send fbcOkay get label] + + if { $itemno != "none" } { + if { $mode == "Load"} { + if {$opt != "dirlist"} { + addHistRecord "" "" "" help [format "%s%s" $curdir $item] "file" + } + GCmd directory $opt $item + send flistText set string [format " file Okay %s%s\n" \ + $curdir $item] + } else { + if {$opt == "dirlist"} { + GCmd directory $opt $item + } else { + send fnameEntry set string [format "%s%s" $curdir $item] + } + } + } +} +send dirList addEventHandler browserSelect buttonReleaseMask +send fileList addEventHandler browserSelect buttonReleaseMask + + +# Client callback. +proc browserListing { param old new } { + global curdir pattern + + set option [ lindex $new 0 ] + switch $option { + dirlist { set list [lindex $new 1] + send dirList setList $list resize + } + filelist { set list [lindex $new 1] + send fileList setList $list resize + } + template { set pattern [lindex $new 1] + send filterEntry set string $pattern + } + curdir { set curdir [lindex $new 1] + send curdirVal set label $curdir + } + selection { send fnameEntry set string [lindex $new 1] } + } +} ; send directory addCallback browserListing + + +# Set the filename matching template. +proc setTemplate { widget mode pattern args } { + GCmd directory template $pattern +} ; send filterEntry addCallback setTemplate + + +# get the filename of the currently displayed page. +proc fileSource { args } { + global helpOption + + set str [ send flistText get string ] + + set fname "" + for {set i 0} {$i < [llength $str]} {incr i 3} { + set j [expr {$i + 2} ] + if {($helpOption == "source" && [lindex $str $i] == "src") || + ($helpOption == "sysdoc" && [lindex $str $i] == "sys") || + ($helpOption == "help" && [lindex $str $i] == "hlp") || + ($helpOption == "file" && [lindex $str $i] == "file")} { + set fname [lindex $str $j] + break + } + } + return $fname +} + +# Open a specific file, either to load a new page or save the current page. +proc openFile { widget args } { + global curdir helpOption + + set fname [send fnameEntry get string] + + if {$fname == ""} { + setAlert param old "No filename specified" + } else { + if { [send fbcOkay get label] == "Load"} { + addHistRecord "" "" "" "" [format "%s%s" $curdir $fname] "file" + GCmd directory open $fname + send flistText set string [format " file Okay %s\n" $fname] + } else { + set page [fileSource] + set ow [send overwrite get on] + if {[send fmtSrc get on] == 1} { + GCmd directory save $page $fname $ow source + } elseif {[send fmtText get on] == 1} { + GCmd directory save $page $fname $ow text + } elseif {[send fmtHTML get on] == 1} { + GCmd directory save $page $fname $ow html + } elseif {[send fmtPS get on] == 1} { + GCmd directory save $page $fname $ow postscript + } + } + } +} ; send fbcOkay addCallback openFile + + +# Make the SaveAs formats a radio box. +proc fmtRadio { widget type state args } { + global format + + if {$state == 0} { + # Don't allow a button to be turned off. + send $widget set on 1 + } else { + send $format set on 0 + set format $widget + } + + # If there's no filename specified set one as a default. + setDefaultFname + +} ; foreach w {fmtSrc fmtText fmtHTML fmtPS} { send $w addCallback fmtRadio } + + +# Set a default filename based on the selected format and task name +proc setDefaultFname args { + global format curtask curdir + + set fname [send fnameEntry get string] + if {$curtask != ""} { + switch $format { + fmtSrc { send fnameEntry \ + set string [format "%s%s" $curdir $curtask] } + fmtText { send fnameEntry \ + set string [format "%s%s.txt" $curdir $curtask] } + fmtHTML { send fnameEntry \ + set string [format "%s%s.html" $curdir $curtask] } + fmtPS { send fnameEntry \ + set string [format "%s%s.ps" $curdir $curtask] } + } + } +} + +proc browserHelp args { + if { [send fbcOkay get label] == "Load"} { + showHelp lfiles + } else { + showHelp sfiles + } +} ; send fbcHelp addCallback browserHelp + +send fnavHome addCallback "GCmd directory home" +send fnavUp addCallback "GCmd directory up" +send fnavRoot addCallback "GCmd directory root" +send fnavRescan addCallback "GCmd directory rescan" +send fnameClear addCallback "send fnameEntry set string \"\"" +send filterClear addCallback "send filterEntry set string \"\"" +send fbcDismiss addCallback "send fileBrowser unmap" + + + +################################################################################ +# Procedures used by the find box. +################################################################################ + +proc doFindOkay args { + set dir forward + set case caseless + set phrase [send findEntry get string] + + if { $phrase != "" } { + if { [send findDir get on] } { set dir backward } + if { [send findCase get on] } { set case caseSensitive } + + if { [send helpText searchText $phrase start end $dir $case] > 0 } { + set elid [lindex [lindex $start 0] 0] + set id [max 1 [expr $elid - 10] ] + + send helpText gotoId $id + send helpText setSelection $start $end + } else { + send warnText set label "Search string not found." + send warning map + } + } else { + send warnText set label "Warning: No search phrase entered." + send warning map + } +} ; foreach w { findOkay findEntry } { send $w addCallback doFindOkay } + +send findClear addCallback { send findEntry set string "" } +send findDismiss addCallback { send findShell popdown } + + +################################################################################ +# Procedures used by the apropos prompt box. +################################################################################ + +proc doSearchOkay args { + set phrase [send searchEntry get string] + if { $phrase != "" } { + send searchStatus set label "Searching..." + GCmd search [send exactMatch get on] $phrase + } else { + send warnText set label "Warning: No search phrase entered." + send warning map + } +} ; foreach w { searchOkay searchEntry } { send $w addCallback doSearchOkay } + +proc searchResults { param old new } { + global search_mapped + + if {$search_mapped == 0} { + Search + } + send resList setText $new + send resList retestAnchors + send searchStatus set label "" +} ; send apropos addCallback searchResults + +# Selection callback. +proc searchAnchorSelected {widget cbtype event text href args} { + global helpOption helpType curpack curtask + global visited + + # Break out the task and package names. + set pack [lindex [split $href "."] 0] + set task [lindex [split $href "."] 1] + + # Set the state and load the page. + if {$helpOption != "help"} { + send [getOptWidget $helpOption] set on 0 + setOptColor hlpOpt green + } + set curtask $task + set curpack $pack + set helpOption "help" + set helpType [expr {($pack == $task) ? "package" : "task"}] + GCmd load $curtask $curpack $helpOption + + # Add the history record, one for the package and one for the task. + addHistRecord $curpack $curpack "" $helpOption "" "package" + if {$pack != $task} { + addHistRecord $curpack $curtask "" $helpOption "" "task" + } + send htbButton set sensitive True + send htuButton set sensitive True + editHistoryMenu + printHistStack "searchAnchorSelected" + + # Update the topic entry string. + if { $task == $pack } { + send topicEntry set string $pack + } else { + send topicEntry set string [ format "%s.%s" $pack $task ] + } + + set visited($href) 1 + send resList retestAnchors + +} ; send resList addCallback searchAnchorSelected anchor + +proc doSearchClear args { + send searchEntry set string "" +} ; send searchClear addCallback doSearchClear + +proc doSearchDismiss args { + global search_mapped + + set search_mapped 0 + send searchShell unmap +} ; send searchDismiss addCallback doSearchDismiss + +send searchHelp addCallback { showHelp search } + + +################################################################################ +# Define procedures for the help panel +################################################################################ + +# Stuff for keeping track of visited anchors. +set h_links { 0 } +set h_linkIndex 0 + +proc getHelpText { param old new } { + send hlpText setText $new +}; send help addCallback getHelpText + +proc anchorSelected {widget cbtype event text href args} { + global visited h_links h_linkIndex + set anchID [send hlpText anchorToId $href] + set visited($href) 1 + if {$h_linkIndex == 0} { + send hlpBack set sensitive True + if {[lindex $h_links 1] != $anchID} { + set h_links { 0 } + send hlpForward set sensitive False + } + } + if {$h_linkIndex > 0 && \ + [lindex $h_links [expr $h_linkIndex + 1]] != $anchID} { + #set h_links [lrange $h_links 0 $h_linkIndex] + set pos [send hlpText positionToId 0 0] + set h_links [lreplace $h_links $h_linkIndex end $pos] + } + if {[lindex $h_links [expr $h_linkIndex + 1]] != $anchID} { + lappend h_links $anchID + incr h_linkIndex + } else { + send hlpForward set sensitive False + incr h_linkIndex + } + if {$h_linkIndex == [expr [llength $h_links] - 1]} { + send hlpForward set sensitive False + } + send hlpText gotoId $anchID + send hlpText retestAnchors +}; send hlpText addCallback anchorSelected anchor + + +# Callbacks to position forwards and backwards in link list. +proc hlpForward args { + global h_links h_linkIndex + incr h_linkIndex + if {$h_linkIndex <= [llength $h_links]} { + set anchID [lindex $h_links $h_linkIndex] + send hlpText gotoId $anchID + send hlpText retestAnchors + if {$h_linkIndex == [expr [llength $h_links] - 1]} { + send hlpForward set sensitive False + send hlpBack set sensitive True + } else { + send hlpBack set sensitive True + } + } else { + incr h_linkIndex -1 + } +}; send hlpForward addCallback hlpForward + +proc hlpBack args { + global h_links h_linkIndex + incr h_linkIndex -1 + if {$h_linkIndex >= 0} { + set anchID [lindex $h_links $h_linkIndex] + send hlpText gotoId $anchID + send hlpText retestAnchors + if {$h_linkIndex == 0} { send hlpBack set sensitive False } + if {$h_linkIndex >= 0} { send hlpForward set sensitive True } + } else { + incr h_linkIndex 1 + } +}; send hlpBack addCallback hlpBack + +proc hlpHome args { + global h_links h_linkIndex + set h_links { 0 } + set h_linkIndex 0 + send hlpText gotoId 0 + send hlpForward set sensitive False + send hlpBack set sensitive False +}; send hlpHome addCallback hlpHome + +proc hlpTutorial args { + showHelp tutorial +}; send hlpTutorial addCallback hlpTutorial +send hlpTutorial unmap ;# NO TUTORIAL AT THE MOMENT + +proc showHelp {name args} { + anchorSelected widget cbtype event text #$name + send hlpShell map +} + +proc hlpFind args { + set phrase [send hfEntry get string] + set dir forward + set case caseless + + if { $phrase != "" } { + if { [send hfDir get on] } { set dir backward } + if { [send hfCase get on] } { set case caseSensitive } + if {[send hlpText searchText $phrase start end $dir $case ] > 0} { + set elid [lindex [lindex $start 0] 0] + set id [max 1 [expr $elid - 10] ] + send hlpText gotoId $id + send hlpText setSelection $start $end + } else { + send warnText set label "Search string not found." + send warning map + } + } else { + send warnText set label "Warning: No search phrase entered." + send warning map + } +} ; foreach w { hfEntry hfFind } { send $w addCallback hlpFind } + +send hfClear addCallback { send hfEntry set string "" } + +send hlpDismiss addCallback "send hlpShell unmap" + + +################################################################################ +# Document source viewer procedures. +################################################################################ + +proc srcOpen { args } { send doc_source map } +send srcDismiss addCallback "send doc_source unmap" + + +################################################################################ +# Define some TCL debug procedures +################################################################################ + +proc tclOpen {} { send tclShell map } + +proc tclCommandClear { widget args } { + send tclEntry set string "" +} ; send tclClear addCallback tclCommandClear + +proc tclCommandExecute { widget args } { \ + send server [send tclEntry {get string}] +} ; send tclExecute addCallback tclCommandExecute + +proc tclCommand { widget mode command args } { + send server $command +} ; send tclEntry addCallback tclCommand + +proc tclToggleLogging args { + global debug + if { [ send tclLogging get state] } { + set debug 1 + send tclLogging set label "Disable Logging" + } else { + set debug 0 + send tclLogging set label "Enable Logging" + } +} ; tclToggleLogging +send tclLogging addCallback tclToggleLogging + +send tclDismiss addCallback "send tclShell unmap" + +# Connect the 'textout' parameter so it appends messages from +# the client to the Tcl text window. +proc tclLogMessages { param old new } { + global debug + if {$debug == 1} { send tclEntry append [format "%s\n" $new ] } +} ; send textout addCallback tclLogMessages + + +################################################################################ +# Warning dialog. This pops up a dialog box with the given warning message. +################################################################################ + +proc warnOkay {widget args} { + global curpack curtask + + set label [send warnText get label] + if {[string match "No*" $label ] == 1} { + set topic [send topicEntry get string] + set last [string last "." $topic ] + send topicEntry set string [ string range $topic 0 [ incr last -1 ] ] + } + send warning unmap +}; send warnDismiss addCallback warnOkay + + +# The parameter "alert" is used to forward alerts from the client. The +# special 'dismiss' value can be used to shut down the alert from the +# client, the special "pop" value pops the last history elements from the +# stack (used in case of an error loading a file). + +proc setAlert {param old new} { + global HPkg HType HUrl HOpt HTask HFile htop hcurrent + + if {$new == "dismiss"} { + send warning unmap + } elseif {$new == "pop"} { + catch { + unset HType($hcurrent) + unset HOpt($hcurrent) + unset HTask($hcurrent) + unset HPkg($hcurrent) + unset HUrl($hcurrent) + unset HFile($hcurrent) + } + incr hcurrent -1 + } else { + send searchStatus set label "" + send warnText set label $new + send warning map + } +}; send alert addCallback setAlert + + diff --git a/pkg/system/help/xhelp/mkpkg b/pkg/system/help/xhelp/mkpkg new file mode 100644 index 00000000..a12b2788 --- /dev/null +++ b/pkg/system/help/xhelp/mkpkg @@ -0,0 +1,28 @@ +# Make the GUI part of the HELP task. + +$checkout libpkg.a ../ +$update libpkg.a +$checkin libpkg.a ../ +$exit + +zzdebug: + $omake zzdebug.x + $link zzdebug.o -l xtools + ; + +libpkg.a: + xhelp.x ../help.h xhelp.h + xhcmds.x ../help.h xhelp.h + xhdir.x xhelp.h <ctype.h> <diropen.h> <finfo.h> + xhfiles.x ../help.h xhelp.h <ctype.h> <fset.h> + xhhelp.x ../help.h xhelp.h <error.h> <finfo.h> <fset.h> + xhinit.x xhelp.h + xhofile.x xhelp.h <fset.h> + xhpkg.x <error.h> <fset.h> ../helpdir.h ../help.h xhelp.h + xhprint.x xhelp.h ../help.h <ctype.h> <error.h> <ttyset.h> + xhqref.x ../help.h xhelp.h <ctype.h> <finfo.h> + xhroot.x xhelp.h + xhsave.x ../help.h xhelp.h <ctype.h> + xhsearch.x xhelp.h <ctype.h> <fset.h> + xhsort.x xhelp.h <ctype.h> + ; diff --git a/pkg/system/help/xhelp/xhcmds.x b/pkg/system/help/xhelp/xhcmds.x new file mode 100644 index 00000000..2c98af79 --- /dev/null +++ b/pkg/system/help/xhelp/xhcmds.x @@ -0,0 +1,185 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <syserr.h> +include "../help.h" +include "xhelp.h" + + +# XHELP callback commands. +define XC_COMMANDS "|help|load|print|quit|search|files|directory|type|package|" +define CMD_HELP 1 +define CMD_LOAD 2 +define CMD_PRINT 3 +define CMD_QUIT 4 +define CMD_SEARCH 5 +define CMD_FILES 6 +define CMD_DIRECTORY 7 +define CMD_TYPE 8 +define CMD_PACKAGE 9 + + +# XH_COMMAND_LOOP -- Process the GUI command loop. + +procedure xh_command_loop (xh) + +pointer xh #I task descriptor + +pointer sp, cmd, name, pkg, pat, opt, dev +real x, y +int wcs, key, exact_match +char str[SZ_FNAME] + +bool streq() +int strdic(), clgcur() +int xh_pkglist() + +begin + call smark (sp) + call salloc (name, SZ_FNAME, TY_CHAR) + call salloc (pkg, SZ_FNAME, TY_CHAR) + call salloc (opt, SZ_FNAME, TY_CHAR) + call salloc (dev, SZ_FNAME, TY_CHAR) + call salloc (cmd, SZ_FNAME, TY_CHAR) + call salloc (pat, SZ_FNAME, TY_CHAR) + + + # Enter the command loop. + while (clgcur ("coords", x, y, wcs, key, str, SZ_FNAME) != EOF) { + + # Skip any non-colon commands. + if (key != ':') + next + + # Get the colon command string. + call sscan (str) + call gargwrd (Memc[cmd], SZ_FNAME) + + switch (strdic (Memc[cmd], Memc[cmd], SZ_FNAME, XC_COMMANDS)) { + case CMD_HELP: + call gargwrd (Memc[name], SZ_FNAME) + + # Get help on the requested topic, updates package list + # if necesary. + if (streq(Memc[name],"Home")) { + call xh_init (xh, NO, YES) + } else { + call gargwrd (Memc[pkg], SZ_FNAME) # curpack + call gargwrd (Memc[opt], SZ_FNAME) # option + call xh_cmd_help (xh, Memc[name], Memc[pkg], Memc[opt]) + } + + case CMD_FILES: + call gargwrd (Memc[name], SZ_FNAME) # task name + call gargwrd (Memc[pkg], SZ_FNAME) # parent package + call xh_files (xh, Memc[name], Memc[pkg]) + + case CMD_LOAD: + # Load a requested page from the history. + call gargwrd (Memc[name], SZ_FNAME) # task name + call gargwrd (Memc[pkg], SZ_FNAME) # curpack + call gargwrd (Memc[opt], SZ_FNAME) # help option + if (xh_pkglist (xh, Memc[name], HELPDB(xh), LIST(xh)) != 0) + call gmsg (XH_GP(xh), "pkglist", LIST(xh)) + call xh_help (xh, Memc[name], Memc[pkg], Memc[opt]) + + case CMD_PRINT: + # Print the current results. + call gargwrd (Memc[name], SZ_FNAME) # task name + call gargwrd (Memc[pkg], SZ_FNAME) # curpack + call gargwrd (Memc[dev], SZ_FNAME) # printer name + call xh_print_help (xh, Memc[name], Memc[pkg], Memc[dev]) + + case CMD_QUIT: + # Quit the task. + break + + case CMD_SEARCH: + # Get the results of the keyword search. + call gargi (exact_match) + call gargstr (Memc[pat], SZ_FNAME) + call xh_search (xh, exact_match, Memc[pat]) + + case CMD_DIRECTORY: + # Process the directory browsing command. + call gargwrd (Memc[opt], SZ_FNAME) + call xh_directory (xh, Memc[opt]) + + case CMD_TYPE: + # Get the showtype value from the GUI + call gargi (XH_SHOWTYPE(xh)) + + case CMD_PACKAGE: + # For the given item return the package in which it + # was found. [DEBUG ROUTINE.] + call gargwrd (Memc[name], SZ_FNAME) + call xh_pkgpath (xh, Memc[name], CURPACK(xh), Memc[pkg]) + call printf ("%s => %s\n") + call pargstr (Memc[name]) + call pargstr (Memc[pkg]) + call flush(STDOUT) + } + } + + call sfree (sp) +end + + +# XH_CMD_HELP -- Process a help command. + +procedure xh_cmd_help (xh, topic, curpack, option) + +pointer xh # task descriptor +char topic[ARB] # requested topic +char curpack[ARB] # current package +char option[ARB] # option (help|source|sysdoc) + +int len + +bool streq() +int strncmp() +int xh_pkgname(), xh_pkglist() + +begin + if (streq (option, "help")) { + # No package name given, find one and load it. + if (streq (curpack, "{}")) { + curpack[1] = EOS + len = 0 + if (xh_pkgname (xh, topic, curpack) == OK) + len = xh_pkglist (xh, curpack, HELPDB(xh), LIST(xh)) + + if (len != 0 && + strncmp(curpack, "root", 4) != 0 && + strncmp(curpack, "clpack", 6) != 0) { + call gmsg (XH_GP(xh), "pkglist", LIST(xh)) + call strcpy (curpack, CURPACK(xh), SZ_FNAME) + call gmsg (XH_GP(xh), "curpack", curpack) + call gmsg (XH_GP(xh), "history", "package") + } + } + + if (xh_pkglist (xh, topic, HELPDB(xh), LIST(xh)) != 0) { + # Got a package listing.... + call gmsg (XH_GP(xh), "pkglist", LIST(xh)) + call strcpy (topic, CURPACK(xh), SZ_FNAME) + call gmsg (XH_GP(xh), "curpack", topic) + } + } + + if (streq (topic, CURPACK(xh))) { + call gmsg (XH_GP(xh), "type", "package") + call gmsg (XH_GP(xh), "curtask", topic) + if (streq (option, "help")) + call xh_help (xh, "", CURPACK(xh), option) + else + call xh_help (xh, topic, curpack, option) + call strcpy (CURPACK(xh), CURTASK(xh), SZ_FNAME) + + } else { + call gmsg (XH_GP(xh), "type", "task") + call gmsg (XH_GP(xh), "curtask", topic) + call xh_help (xh, topic, CURPACK(xh), option) + call strcpy (topic, CURTASK(xh), SZ_FNAME) + } + call gmsg (XH_GP(xh), "history", "append") +end diff --git a/pkg/system/help/xhelp/xhdir.x b/pkg/system/help/xhelp/xhdir.x new file mode 100644 index 00000000..3c951afa --- /dev/null +++ b/pkg/system/help/xhelp/xhdir.x @@ -0,0 +1,567 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <diropen.h> +include <ctype.h> +include <finfo.h> + +include "xhelp.h" + + +# Pattern matching definitions. +define PATCHARS "*?[" + +# Browsing command dictionary. +define DIR_CMDS "|dirlist|loadfile|open|template|home|up|root|rescan|save|" +define DIRLIST 1 # get the directory listing +define LOADFILE 2 # load the requested file +define OPEN 3 # load the requested file +define TEMPLATE 4 # filename matching template +define HOME 5 # goto the user's home$ +define UP 6 # go up one directory +define ROOT 7 # go to the root directory +define RESCAN 8 # rescan current directory +define SAVE 9 # save to the requested file + + +# XH_DIRECTORY -- Process the directory browsing command. + +procedure xh_directory (xh, command) + +pointer xh #i task descriptor +char command[ARB] #i command option + +pointer sp, dir, file, pattern, path, fmt +pointer task, pkg, opt, type +int ncmd, overwrite +int strdic(), strcmp(), envgets() + +begin + # Allocate working space and clear it. + call smark (sp) + call salloc (dir, SZ_PATHNAME, TY_CHAR) + call salloc (path, SZ_PATHNAME, TY_CHAR) + call salloc (file, SZ_FNAME, TY_CHAR) + call salloc (pattern, SZ_FNAME, TY_CHAR) + call salloc (fmt, SZ_FNAME, TY_CHAR) + call salloc (task, SZ_FNAME, TY_CHAR) + call salloc (pkg, SZ_FNAME, TY_CHAR) + call salloc (opt, SZ_FNAME, TY_CHAR) + call salloc (type, SZ_FNAME, TY_CHAR) + + call aclrc (Memc[dir], SZ_FNAME) + call aclrc (Memc[path], SZ_FNAME) + call aclrc (Memc[file], SZ_FNAME) + call aclrc (Memc[fmt], SZ_FNAME) + call aclrc (Memc[pattern], SZ_FNAME) + call aclrc (Memc[task], SZ_FNAME) + call aclrc (Memc[pkg], SZ_FNAME) + call aclrc (Memc[opt], SZ_FNAME) + call aclrc (Memc[type], SZ_FNAME) + + ncmd = strdic (command, command, SZ_LINE, DIR_CMDS) + switch (ncmd) { + case DIRLIST: + call gargwrd (Memc[dir], SZ_PATHNAME) # get the dirname + if (strcmp ("../", Memc[dir]) == 0) { + call xh_updir (xh) + } else { + call sprintf (Memc[path], SZ_PATHNAME, "%s%s") + call pargstr (CURDIR(xh)) + call pargstr (Memc[dir]) + call xh_set_curdir (xh, Memc[path]) + call xh_dirlist (xh, CURDIR(xh), PATTERN(xh)) + call xh_selection (xh, CURDIR(xh)) + } + + case LOADFILE: + call gargwrd (Memc[file], SZ_FNAME) # get the filename + call sprintf (Memc[path], SZ_PATHNAME, "%s%s") + call pargstr (CURDIR(xh)) + call pargstr (Memc[file]) + call xh_open_file (xh, "helpres", Memc[path], YES, YES) + call xh_selection (xh, Memc[path]) + + case OPEN: + call gargwrd (Memc[file], SZ_FNAME) # get the filename + call xh_ldfile (xh, Memc[file]) + + case TEMPLATE: + call gargwrd (Memc[pattern], SZ_FNAME) # set the template + call xh_set_pattern (xh, Memc[pattern]) + call xh_dirlist (xh, CURDIR(xh), PATTERN(xh)) + + case HOME: + if (envgets ("home", Memc[dir], SZ_PATHNAME) != EOF) { + call xh_set_curdir (xh, Memc[dir]) + call xh_dirlist (xh, CURDIR(xh), PATTERN(xh)) + } + + case UP: + call xh_updir (xh) + + case ROOT: + call xh_set_curdir (xh, "/") + call xh_dirlist (xh, CURDIR(xh), PATTERN(xh)) + + case RESCAN: + call xh_dirlist (xh, CURDIR(xh), PATTERN(xh)) + + case SAVE: + call gargwrd (Memc[path], SZ_FNAME) # get the filename + call gargwrd (Memc[file], SZ_FNAME) # get the output fname + call gargi (overwrite) # get the overwrite flag + call gargwrd (Memc[fmt], SZ_FNAME) # get the save format + call xh_save_file (xh, Memc[path], Memc[file], Memc[fmt], + overwrite) + } + + call sfree (sp) +end + + +# XH_DIRLIST -- Given the directory name and a file template return the +# directory contents. + +procedure xh_dirlist (xh, directory, pattern) + +pointer xh #i task descriptor +char directory[ARB] #i directory to read +char pattern[ARB] #i matching template + +pointer sp, path, fname, patbuf +pointer dp, fp, ip, op, ep, sym +bool match_extension +int dd, n, patlen +int nfiles, ndirs, lastch + +pointer stopen(), stenter() +int diropen(), xh_isdir(), strncmp(), stridxs() +int patmake(), patmatch(), strlen(), getline() + +begin + call smark (sp) + call salloc (path, SZ_PATHNAME, TY_CHAR) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (patbuf, SZ_LINE, TY_CHAR) + + call aclrc (Memc[patbuf], SZ_LINE) + + # If this isn't a directory just return silently. + if (xh_isdir (directory, Memc[path], SZ_PATHNAME) == 0) { + call sfree (sp) + return + } + + # Open the requested directory + dd = diropen (directory, PASS_HIDDEN_FILES) + + # Set up the pattern matching code. We recognize selecting all files + # with a particular extension as a special case, since this case is + # very common and can be done much more efficiently if we don't use + # the general pattern matching code. If we have no pattern set the + # length to zero to indicate that everything will match. + + if (pattern[1] == EOS) { + patlen = 0 + } else { + match_extension = (strncmp (pattern, "*.", 2) == 0 && + stridxs (PATCHARS, pattern[3]) <= 0) + if (match_extension) + patlen = strlen (pattern) + else { + # Convert file matching pattern into general pattern string. + Memc[fname] = '^' + op = fname + 1 + lastch = 0 + for (ip=1; pattern[ip] != EOS; ip=ip+1) { + if (pattern[ip] == '*' && lastch != '?' && lastch != ']') { + Memc[op] = '?' + op = op + 1 + } + lastch = pattern[ip] + Memc[op] = lastch + op = op + 1 + } + Memc[op] = '$' + op = op + 1 + Memc[op] = EOS + + # Compile the pattern. + patlen = patmake (pattern, Memc[patbuf], SZ_LINE) + } + } + + # Initialize counters. + ndirs = 0 + nfiles = 0 + dp = NULL + fp = NULL + + # Accumulate the contents into the directory and files lists. We + # match files against the given template, all directories are + # matched regardless. + for (n=0; n != EOF; ) { + n = getline (dd, Memc[fname]) + if (n < 1) + break + n = n - 1 + Memc[fname+n] = EOS # stomp the newline + + # See if this is a directory. + call sprintf (Memc[path], SZ_PATHNAME, "%s%s") + call pargstr (CURDIR(xh)) + call pargstr (Memc[fname]) + if (xh_isdir (Memc[path], Memc[path], SZ_PATHNAME) > 0) { + ndirs = ndirs + 1 + + # If this is the first directory initialize the symbol table. + if (ndirs == 1) + dp = stopen ("dirlist", LEN_INDEX, LEN_STAB, SZ_SBUF) + + # Enter the directory name into the symbol table. + call strcat ("/", Memc[fname], SZ_FNAME) + sym = stenter (dp, Memc[fname], strlen(Memc[fname])+1) + + } else { + # Check if the file matches the given pattern. + if (patlen > 0) { + if (match_extension) { + if (n < patlen) + next + ep = fname + n - 1 + for (ip=patlen; ip > 2; ip=ip-1) { + if (Memc[ep] != pattern[ip]) + break + ep = ep - 1 + } + if (pattern[ip] != '.' || Memc[ep] != '.') + next + } else if (patmatch (Memc[fname], Memc[patbuf]) <= 0) + next + } + + # We have a match. + nfiles = nfiles + 1 + + # If this is the first file initialize the symbol table. + if (nfiles == 1) + fp = stopen ("filelist", LEN_INDEX, LEN_STAB, SZ_SBUF) + + # Enter the directory name into the symbol table. + sym = stenter (fp, Memc[fname], strlen(Memc[fname])+1) + } + } + + # Send the results to the GUI. + call xh_putlist (xh, dp, "directory", "dirlist") + call xh_putlist (xh, fp, "directory", "filelist") + + # Clean up. + if (dp != NULL) + call stclose (dp) + if (fp != NULL) + call stclose (fp) + call close (dd) + call sfree (sp) +end + + +# XH_PUTLIST -- Given the symtab for the directory contents construct a +# list suitable for a message to the GUI. The 'arg' parameter is passed +# to indicate which type of list this is. + +procedure xh_putlist (xh, stp, param, arg) + +pointer xh #i task descriptor +pointer stp #i symtab ptr for list +char param[ARB] #i GUI param to notify +char arg[ARB] #i GUI param arg + +pointer sp, list, msg, sym, name, ip +int nchars + +pointer sthead(), stnext(), stname() +int stsize(), gstrcpy(), strcmp(), strlen() + +begin + # Return if there is no symtab information. + if (stp == NULL) { + call smark (sp) + call salloc (msg, SZ_FNAME , TY_CHAR) + call sprintf (Memc[msg], SZ_FNAME, "%s { }") + call pargstr (arg) + + call gmsg (XH_GP(xh), param, Memc[msg]) # send it to the GUI + call gflush (XH_GP(xh)) + call sfree (sp) + return + } + + # Allocate space for the list. + nchars = stsize (stp) + 1 + + call smark (sp) + call salloc (list, nchars , TY_CHAR) + call aclrc (Memc[list], nchars) + ip = list + + # Build the list from the symtab. + for (sym = sthead (stp); sym != NULL; sym = stnext (stp,sym)) { + name = stname(stp,sym) + if (strcmp (Memc[name], "./") != 0) { + ip = ip + gstrcpy (Memc[name], Memc[ip], SZ_FNAME) + ip = ip + gstrcpy (" ", Memc[ip], SZ_FNAME) + } + } + + # Sort the list. + call xh_sort_list (Memc[list]) + + # Allocate space for the message buffer. The "+ 6" is space for + # the brackets around the list in the message created below. + nchars = nchars + strlen (arg) + 6 + call salloc (msg, nchars, TY_CHAR) + call aclrc (Memc[msg], nchars) + ip = msg + + # Begin the message by adding the arg and make a Tcl list of the + # contents. + call sprintf (Memc[msg], nchars, "%s { ") + call pargstr (arg) + call strcat (Memc[list], Memc[msg], nchars) + call strcat (" }", Memc[msg], nchars) + + # Finally, send it to the GUI. + call gmsg (XH_GP(xh), param, Memc[msg]) + call gflush (XH_GP(xh)) + + call sfree (sp) +end + + +# XH_LDFILE -- Load the requested file. If this is a file display it's +# contents and update the browser with it's directory, otherwise if it's +# a directory jump the browser to that directory. + +procedure xh_ldfile (xh, file) + +pointer xh #i task descriptor +char file[ARB] #i requested file/dir + +pointer sp, ip, dir, parent, path +int nchars +int access(), strlen(), xh_isdir() + +begin + call smark (sp) + call salloc (dir, SZ_PATHNAME, TY_CHAR) + call salloc (path, SZ_PATHNAME, TY_CHAR) + call salloc (parent, SZ_PATHNAME, TY_CHAR) + + # Expand the current directory to a host path. + call fdirname (file, Memc[dir], SZ_PATHNAME) + + if (xh_isdir (Memc[dir], Memc[path], SZ_PATHNAME) > 0) { + # Set the curdir and load it's contents. + call xh_set_curdir (xh, Memc[path]) + call xh_dirlist (xh, CURDIR(xh), PATTERN(xh)) + call xh_selection (xh, Memc[path]) + } + + if (access(file,0,0) == YES && + xh_isdir (file, Memc[path], SZ_PATHNAME) == 0) { + # Work backwards to the parent '/', be sure to skip the trailing + # backslash already in the dirname. + ip = dir + strlen (Memc[dir]) - 2 + while (Memc[ip] != '/' && ip > dir) + ip = ip - 1 + + nchars = ip - dir + if (nchars > 0) + call strcpy (Memc[dir], Memc[parent], nchars) + else + call strcpy ("/", Memc[parent], nchars) + + # Set the parent dir and load it's contents. + call xh_set_curdir (xh, Memc[parent]) + call xh_dirlist (xh, CURDIR(xh), PATTERN(xh)) + + # Now load the file itself. + call xh_open_file (xh, "helpres", file, YES, YES) + call xh_selection (xh, file) + } + + call sfree (sp) +end + + +# XH_UPDIR -- Go up to the parent directory and return contents. + +procedure xh_updir (xh) + +pointer xh #i task descriptor + +pointer sp, ip, dir, parent +int nchars, strlen() + +begin + call smark (sp) + call salloc (dir, SZ_PATHNAME, TY_CHAR) + call salloc (parent, SZ_PATHNAME, TY_CHAR) + + # Expand the current directory to a host path. + call fdirname (CURDIR(xh), Memc[dir], SZ_PATHNAME) + + # Work backwards to the parent '/', be sure to skip the trailing + # backslash already in the dirname. + ip = dir + strlen (Memc[dir]) - 2 + while (Memc[ip] != '/' && ip > dir) + ip = ip - 1 + + nchars = ip - dir + if (nchars > 0) + call strcpy (Memc[dir], Memc[parent], nchars) + else + call strcpy ("/", Memc[parent], nchars) + + # Set the parent dir and load it's contents. + call xh_set_curdir (xh, Memc[parent]) + call xh_dirlist (xh, CURDIR(xh), PATTERN(xh)) + call xh_selection (xh, CURDIR(xh)) + + call sfree (sp) +end + + +# XH_SET_CURDIR -- Set the filename matching template pattern. + +procedure xh_set_curdir (xh, dir) + +pointer xh #i task descriptor +char dir[ARB] #i current directory + +pointer sp, dirbuf +int strlen() + +begin + call smark (sp) + call salloc (dirbuf, SZ_PATHNAME, TY_CHAR) + + call strcpy (dir, CURDIR(xh), SZ_PATHNAME) + if (dir[strlen(dir)] != '/') + call strcat ("/", CURDIR(xh), SZ_PATHNAME) + + call sprintf (Memc[dirbuf], SZ_PATHNAME, "curdir %s") + call pargstr (CURDIR(xh)) + + call gmsg (XH_GP(xh), "directory", Memc[dirbuf]) + call gflush (XH_GP(xh)) + + call sfree (sp) +end + + +# XH_SET_PATTERN -- Set the filename matching template pattern. + +procedure xh_set_pattern (xh, pattern) + +pointer xh #i task descriptor +char pattern[ARB] #i template pattern + +pointer sp, patbuf + +begin + call smark (sp) + call salloc (patbuf, SZ_FNAME, TY_CHAR) + + call sprintf (Memc[patbuf], SZ_FNAME, "template %s") + call pargstr (pattern) + + call strcpy (pattern, PATTERN(xh), SZ_FNAME) + call gmsg (XH_GP(xh), "directory", Memc[patbuf]) + call gflush (XH_GP(xh)) + + call sfree (sp) +end + + +# XH_SELECTION -- Set the selected filename. + +procedure xh_selection (xh, selection) + +pointer xh #i task descriptor +char selection[ARB] #i selection + +pointer sp, buf + +begin + call smark (sp) + call salloc (buf, SZ_FNAME, TY_CHAR) + + call sprintf (Memc[buf], SZ_FNAME, "selection %s") + call pargstr (selection) + + call gmsg (XH_GP(xh), "directory", Memc[buf]) + call gflush (XH_GP(xh)) + call sfree (sp) +end + + +# XH_ISDIR -- Test whether the named file is a directory. Check first to +# see if it is a subdirectory of the current directory. If VFN is a directory, +# return the OS pathname of the directory in pathname, and the number of +# chars in the pathname as the function value. Otherwise return 0. + +int procedure xh_isdir (vfn, pathname, maxch) + +char vfn[ARB] # name to be tested +char pathname[ARB] # receives path of directory +int maxch # max chars out + +bool isdir +pointer sp, fname, op +int ip, fd, nchars, ch +long file_info[LEN_FINFO] +int finfo(), diropen(), gstrcpy(), strlen() + +begin + call smark (sp) + call salloc (fname, SZ_PATHNAME, TY_CHAR) + + # Copy the VFN string, minus any whitespace on either end. + op = fname + for (ip=1; vfn[ip] != EOS; ip=ip+1) { + ch = vfn[ip] + if (!IS_WHITE (ch)) { + Memc[op] = ch + op = op + 1 + } + } + Memc[op] = EOS + + isdir = false + if (finfo (Memc[fname], file_info) != ERR) { + isdir = (FI_TYPE(file_info) == FI_DIRECTORY) + + if (isdir) { + call fdirname (Memc[fname], pathname, maxch) + nchars = strlen (pathname) + } + + } else { + # If we get here, the VFN is the name of a new file. + ifnoerr (fd = diropen (Memc[fname], 0)) { + call close (fd) + isdir = true + } + nchars = gstrcpy (Memc[fname], pathname, maxch) + } + + call sfree (sp) + if (isdir) + return (nchars) + else { + pathname[1] = EOS + return (0) + } +end diff --git a/pkg/system/help/xhelp/xhelp.h b/pkg/system/help/xhelp/xhelp.h new file mode 100644 index 00000000..24bffc71 --- /dev/null +++ b/pkg/system/help/xhelp/xhelp.h @@ -0,0 +1,89 @@ +# XHELP.H -- Include file for the XHELP GUI task. + +# Help database header structure. Stored at the beginning of a help +# database file. This information is taken from the help$helpdb.x source. + +define LEN_HDBHEADER 14 +define HDB_MAGICVAL 110104B + +define HDB_MAGIC Memi[$1] # helpdb file type code +define HDB_RAW Memi[$1+1] # access compiled or raw database +define HDB_RHD Memi[$1+2] # if raw, HP of root help directory +define HDB_INDEX Memi[$1+3] # index of root help directory +define HDB_CRDATE Meml[$1+4] # creation date +define HDB_NENTRIES Memi[$1+5] # number of help directories in db +define HDB_MAXENTRIES Memi[$1+6] # maximum no. of help directories in db +define HDB_NMODULES Memi[$1+7] # count of the total number of modules +define HDB_INDEXOFFSET Meml[$1+8] # file offset of index, chars +define HDB_INDEXPTR Memi[$1+9] # pointer to loaded index, ty_struct +define HDB_INDEXLEN Memi[$1+10] # length of index structure, su +define HDB_DATAOFFSET Meml[$1+11] # file offset of data area, chars +define HDB_DATAPTR Memi[$1+12] # pointer to loaded data area, ty_struct +define HDB_DATALEN Memi[$1+13] # length of data area, struct units + +# Index structure. Identifies the contents of the database and tells where +# they are stored. There is one index entry for each help directory, i.e., +# for each package. + +define LEN_HDBINDEX 34 +define SZ_DBIKEY 63 +define LEN_DBIDATA 2 + +define DBI_KEY Memc[P2C($1)] # entry name +define DBI_OFFSET Memi[$1+32] # offset of entry into data area, su +define DBI_MTIME Meml[$1+33] # modification date of entry + +define MAX_ENTRIES 100 # initial max db entries +define INC_ENTRIES 50 # increment if overflow +define MAX_DEPTH 20 # max nesting of packages +define MAX_MENUSIZE 500 # max modules in a table +define MAX_NAMELEN 20 # max chars in a module name in table + + +# XHELP Macro definitions. +define SZ_HELPLIST 20480 +define SZ_XHELPSTRUCT 45 + +define XH_GP Memi[$1] # graphics descriptor +define XH_LPTR Memi[$1+1] # ptr for pkg list +define XH_TEMPLATE Memi[$1+2] # initial help topic +define XH_OPTION Memi[$1+3] # help option +define XH_PRINTER Memi[$1+4] # printer name +define XH_CURTASK Memi[$1+5] # current task name +define XH_CURPACK Memi[$1+6] # current package name +define XH_QUICKREF Memi[$1+7] # quick-reference filen +define XH_HOMEPAGE Memi[$1+8] # startup page +define XH_CURDIR Memi[$1+9] # current directory +define XH_PATTERN Memi[$1+10] # current filename template +define XH_HELPDB Memi[$1+11] # help database string +define XH_SHOWTYPE Memi[$1+12] # indicate packages in list +define XH_STP Memi[$1+13] # package list symtab ptr + +# Helpful macros +define LIST Memc[XH_LPTR($1)] +define TEMPLATE Memc[XH_TEMPLATE($1)] +define OPTION Memc[XH_OPTION($1)] +define PRINTER Memc[XH_PRINTER($1)] +define CURTASK Memc[XH_CURTASK($1)] +define CURPACK Memc[XH_CURPACK($1)] +define QUICKREF Memc[XH_QUICKREF($1)] +define HOMEPAGE Memc[XH_HOMEPAGE($1)] +define CURDIR Memc[XH_CURDIR($1)] +define PATTERN Memc[XH_PATTERN($1)] +define HELPDB Memc[XH_HELPDB($1)] + +define WIDE_PAGE 100 # needed by the print routines +define SZ_DDSTR 256 + + +# Filenames. +define HELP "lib$scr/help.html" # default help file +define PKGFILE "uparm$help.pkgs" # default package list symtab +define QREFFILE "uparm$quick.ref" # default references file + + +# Symbol table definitions. +define LEN_INDEX 10 # length of symtab index +define LEN_STAB 32 # initial length of symtab +define SZ_SBUF 32 # initial size of symtab string buffer + diff --git a/pkg/system/help/xhelp/xhelp.x b/pkg/system/help/xhelp/xhelp.x new file mode 100644 index 00000000..95a2f250 --- /dev/null +++ b/pkg/system/help/xhelp/xhelp.x @@ -0,0 +1,167 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <syserr.h> +include "../help.h" +include "xhelp.h" + + +# XHELP -- The main task procedure. XHELP is a GUI client program for +# browsing the IRAF help system. As much as possible it uses the existing +# help database code but provides a friendlier interface, allowing users to +# browse packages for help pages in the same way they would browse packages +# in the CL. It provides an HTML converter for LROFF sources for better +# presentation in the GUI, as well as Postscript generation for better +# looking hardcopy. XHelp acts as a server for the help system, merely +# returning any output that the GUI has requested. Navigation is done in +# the GUI code, this program maintains just the state of the last page +# returned and knows nothing about how it got there. See the xhelp.hlp for +# detailed documentation. + +procedure xhelp (topic) + +char topic[ARB] #I help template + +pointer xh +char uifname[SZ_FNAME] +int search, template + +pointer xh_open(), gopenui() +bool clgetb() +int btoi() + +begin + # Open structure and allocate pointers. + xh = xh_open () + call strcpy (topic, TEMPLATE(xh), SZ_FNAME) + + # Load the task parameters. + call clgstr ("option", OPTION(xh), SZ_FNAME) + call clgstr ("printer", PRINTER(xh), SZ_FNAME) + call clgstr ("quickref", QUICKREF(xh), SZ_FNAME) + XH_SHOWTYPE(xh) = btoi (clgetb("showtype")) + search = btoi (clgetb("search")) + template = btoi (clgetb("file_template")) + + # Fetch the name of the help database. + call xh_ghelpdb (xh) + + # Open the GUI. + call clgstr ("uifname", uifname, SZ_FNAME) + XH_GP(xh) = gopenui ("stdgraph", NEW_FILE, uifname, STDGRAPH) + call gflush (XH_GP(xh)) + + # Initialize the task and send topic list to the GUI. + call xh_init (xh, template, search) + + # Initialize the task and send topic list to the GUI. + call xh_command_loop (xh) + + # Clean up. + call gclose (XH_GP(xh)) + call xh_close (xh) +end + + +# XH_OPEN -- Open and allocate the XHELP task structure. + +pointer procedure xh_open () + +pointer xh # task descriptor +errchk calloc + +begin + iferr (call calloc (xh, SZ_XHELPSTRUCT, TY_STRUCT)) + call error (0, "Error opening task structure.") + + iferr { + call calloc (XH_LPTR(xh), SZ_HELPLIST, TY_CHAR) + call calloc (XH_TEMPLATE(xh), SZ_FNAME, TY_CHAR) + call calloc (XH_OPTION(xh), SZ_FNAME, TY_CHAR) + call calloc (XH_PRINTER(xh), SZ_FNAME, TY_CHAR) + call calloc (XH_CURTASK(xh), SZ_FNAME, TY_CHAR) + call calloc (XH_CURPACK(xh), SZ_FNAME, TY_CHAR) + call calloc (XH_QUICKREF(xh), SZ_FNAME, TY_CHAR) + call calloc (XH_HOMEPAGE(xh), SZ_FNAME, TY_CHAR) + call calloc (XH_CURDIR(xh), SZ_PATHNAME, TY_CHAR) + call calloc (XH_PATTERN(xh), SZ_FNAME, TY_CHAR) + call calloc (XH_HELPDB(xh), SZ_HELPDB, TY_CHAR) + } then + call error (0, "Error allocating structure pointers.") + + return (xh) +end + + +# XH_CLOSE -- Close the XHELP task structure. + +procedure xh_close (xh) + +pointer xh # task descriptor + +begin + call mfree (XH_TEMPLATE(xh), TY_CHAR) + call mfree (XH_OPTION(xh), TY_CHAR) + call mfree (XH_PRINTER(xh), TY_CHAR) + call mfree (XH_CURTASK(xh), TY_CHAR) + call mfree (XH_CURPACK(xh), TY_CHAR) + call mfree (XH_QUICKREF(xh), TY_CHAR) + call mfree (XH_HOMEPAGE(xh), TY_CHAR) + call mfree (XH_CURDIR(xh), TY_CHAR) + call mfree (XH_PATTERN(xh), TY_CHAR) + call mfree (XH_HELPDB(xh), TY_CHAR) + call mfree (XH_LPTR(xh), TY_CHAR) + + call mfree (xh, TY_STRUCT) +end + + +# XH_GHELPDB -- Fetch the name of the help database, i.e., "helpdb", +# "helpdir", or the name of a file. If the helpdb string is a list check +# for the existance of each file in the list to ensure the final list +# contains only valid help databases. + +procedure xh_ghelpdb (xh) + +pointer xh # task descriptor + +pointer sp, hdb, hdbstr, name +int list +int fntopnb(), fntgfnb() +int access(), envgets() +bool streq() + +begin + call smark (sp) + call salloc (name, SZ_FNAME, TY_CHAR) + call salloc (hdb, SZ_HELPDB, TY_CHAR) + call salloc (hdbstr, SZ_HELPDB, TY_CHAR) + + # Clear the working memory. + call aclrc (Memc[name], SZ_FNAME) + call aclrc (Memc[hdb], SZ_HELPDB) + call aclrc (Memc[hdbstr], SZ_HELPDB) + + # Get the parameter value. + call clgstr ("helpdb", Memc[hdbstr], SZ_HELPDB) + if (streq (Memc[hdbstr], "helpdb")) + if (envgets ("helpdb", Memc[hdbstr], SZ_HELPDB) <= 0) + call syserrs (SYS_ENVNF, "helpdb") + + # Open the list. + list = fntopnb (Memc[hdbstr], YES) + + # Copy each of the existing files in the list to the output database + # string to be used by the task. + while (fntgfnb(list, Memc[name], SZ_FNAME) != EOF) { + if (access (Memc[name], 0, 0) == YES) { + if (Memc[hdb] != EOS) + call strcat (",", Memc[hdb], SZ_HELPDB) + call strcat (Memc[name], Memc[hdb], SZ_HELPDB) + } + } + call strcpy (Memc[hdb], HELPDB(xh), SZ_HELPDB) + + # Clean up. + call fntclsb (list) + call sfree (sp) +end diff --git a/pkg/system/help/xhelp/xhfiles.x b/pkg/system/help/xhelp/xhfiles.x new file mode 100644 index 00000000..53597eda --- /dev/null +++ b/pkg/system/help/xhelp/xhfiles.x @@ -0,0 +1,89 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <fset.h> +include <ctype.h> +include "../help.h" +include "xhelp.h" + + +# XH_FILES -- Get the files associated with the requested help topic, +# i.e. do a "help <topic> opt=files" request. + +procedure xh_files (xh, topic, curpack) + +pointer xh #i task struct pointer +char topic[ARB] #i help topic +char curpack[ARB] #i current package + +pointer sp, bp, buf +pointer opt, val, line +int fd +long fsize +char fname[SZ_FNAME] + +long fstatl() +int getline(), access(), open(), stridxs(), strlen() + +begin + if (topic[1] == EOS && curpack[1] == EOS) + return + + call smark (sp) + call salloc (line, SZ_LINE, TY_CHAR) + call salloc (buf, SZ_FNAME, TY_CHAR) + call salloc (opt, SZ_FNAME, TY_CHAR) + call salloc (val, SZ_FNAME, TY_CHAR) + + # Get a temp file name. + call mktemp ("tmp$xhelpi", fname, SZ_FNAME) + + # Open a temp file with the help information found. + fd = open (fname, NEW_FILE, TEXT_FILE) + call xh_get_help (fd, topic, curpack, "", HF_HTML, HELPDB(xh), + "all", "files") + call close (fd) + + # Open the results file for reading. + fd = open (fname, READ_ONLY, TEXT_FILE) + fsize = fstatl (fd, F_FILESIZE) + + # If we got a result parse the lines for "opt=file" information. + if (fsize != 0) { + + while (getline (fd, Memc[line]) != EOF) { + + # Stomp the newline. + Memc[line+strlen(Memc[line])-1] = EOS + + # Extract the option type and filename. + if (stridxs ("=", Memc[line]) > 0) { + for (bp=line; IS_WHITE(Memc[bp]); bp=bp+1) + ; + call strcpy (Memc[bp], Memc[opt], 3) + for (; Memc[bp] != '='; bp=bp+1) + ; + call strcpy (Memc[bp+1], Memc[val], SZ_FNAME) + + # See if the file exists. + call sprintf (Memc[buf], SZ_FNAME, "%s %s \0") + call pargstr (Memc[opt]) + call pargstr (Memc[val]) + if (access (Memc[val],0,0) == YES) + call strcat (" 0", Memc[buf], SZ_FNAME) + else + call strcat (" 1", Memc[buf], SZ_FNAME) + call gmsg (XH_GP(xh), "helpfiles", Memc[buf]) + + } else if (stridxs (":", Memc[line]) > 0) { + call xh_pkgpath (xh, topic, curpack, Memc[line]) + call sprintf (Memc[buf], SZ_FNAME, "file %s") + call pargstr (Memc[line]) + call gmsg (XH_GP(xh), "helpfiles", Memc[buf]) + } + } + } + + call close (fd) # clean up + call delete (fname) + call sfree (sp) +end diff --git a/pkg/system/help/xhelp/xhhelp.x b/pkg/system/help/xhelp/xhhelp.x new file mode 100644 index 00000000..708a00ce --- /dev/null +++ b/pkg/system/help/xhelp/xhhelp.x @@ -0,0 +1,276 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <fset.h> +include <finfo.h> +include <error.h> +include "../help.h" +include "xhelp.h" + + +# XH_HELP -- Get the requested help topic and send the result to the GUI. + +procedure xh_help (xh, topic, curpack, opt) + +pointer xh #i task struct pointer +char topic[ARB] #i help topic +char curpack[ARB] #i current package +char opt[ARB] #i help option + +pointer helpstr +int ip, fdi +long fsize +char ch, fname[SZ_FNAME], err[SZ_LINE] + +long fstatl() +char getc() +int open() +bool strne() + +begin + # Get a temp file name. + call mktemp ("tmp$xhelpi", fname, SZ_FNAME) + + # Open a temp file with the help information found. + fdi = open (fname, NEW_FILE, TEXT_FILE) + call xh_get_help (fdi, topic, curpack, "", HF_HTML, HELPDB(xh), + "all", opt) + call close (fdi) + + # Open the results file for reading. + fdi = open (fname, READ_ONLY, TEXT_FILE) + fsize = fstatl (fdi, F_FILESIZE) + + # If no results try using the topic name as a curpack param. + if (fsize == 0) { + call close (fdi) # clean up from before + call delete (fname) + + # Open a temp file with the help information found. + fdi = open (fname, NEW_FILE, TEXT_FILE) + call xh_get_help (fdi, topic, topic, "", HF_HTML, HELPDB(xh), + "all", opt) + call close (fdi) + + # Open the results file for reading. + fdi = open (fname, READ_ONLY, TEXT_FILE) + fsize = fstatl (fdi, F_FILESIZE) + + # If we still have nothing then punt... + if (fsize == 0 && topic[1] != EOS) { + if (strne (opt, "help")) { + call sprintf (err, SZ_LINE, + "No '%s' option help available\n for `%s'.") + call pargstr (opt) + call pargstr (topic) + } else { + call sprintf (err, SZ_LINE, "No help available for\n`%s'.") + call pargstr (topic) + } + call gmsg (XH_GP(xh), "alert", err) + call close (fdi) + call delete (fname) + return + } + } + + # Now filter the file to escape the curly braces so they pass thru + # to the Tcl cleanly. Put the result in the string sent to the GUI. + call calloc (helpstr, fsize + SZ_LINE, TY_CHAR) + ip = helpstr + repeat { + ch = getc (fdi, ch) + if (ch == '{' || ch == '}') { + Memc[ip] = '\\' + ip = ip + 1 + } + Memc[ip] = ch + ip = ip + 1 + } until (ch == EOF) + Memc[ip-1] = EOS + + # Clean up. + call close (fdi) + call delete (fname) + + # Send the help text to the GUI who will display it. + call gmsg (XH_GP(xh), "helpres", Memc[helpstr]) + call mfree (helpstr, TY_CHAR) +end + + +# XH_GET_HELP -- The main work procedure, i.e. a rip-off of the t_help() +# procedure. Decode the option string, set up the control structure, and +# finally call process_template to expand the module template and process +# the help text for each module. The output is written to a temp file +# opened by the calling procedure which may optionally sort it or display +# it as is. + +procedure xh_get_help (fd, topic, curpack, file, format, helpdb, section, opt) + +int fd #i file descriptor of result +char topic[ARB] #i topic +char curpack[ARB] #i current package +char file[ARB] #i file template +int format #i output format (text|html|ps) +char helpdb[ARB] #i help database +char section[ARB] #i section on which to get help +char opt[ARB] #i type of help + +int list +long fi[LEN_FINFO], db_ctime +pointer sp, ctrl, optn, db, fname + +long clktime() +pointer hdb_open() +bool strne(), streq() +int stridxs(), finfo(), fntopnb(), fntgfnb(), get_option() + +errchk hdb_open + +data db_ctime /0/ +define forms_ 91 + +begin + call smark (sp) + call salloc (ctrl, LEN_CTRLSTRUCT, TY_STRUCT) + call salloc (optn, SZ_FNAME, TY_CHAR) + call salloc (fname, SZ_PATHNAME, TY_CHAR) + + # If we were called without any arguments, do not query for the + # template, just set it to null and help will be given for the + # current package. + + call aclri (Memi[ctrl], LEN_CTRLSTRUCT) + if (topic[1] == EOS) { + if (file[1] == EOS) { + H_OPTION(ctrl) = O_MENU + H_TEMPLATE(ctrl) = EOS + H_PARNAME(ctrl) = EOS + H_SECNAME(ctrl) = EOS + } else + call strcpy (file, H_TEMPLATE(ctrl), SZ_LINE) + } else { + call strcpy (topic, H_TEMPLATE(ctrl), SZ_LINE) + } + + + # Check to see if any of the files in the list are newer than the + # time of the last hdb_open. The first time the process runs we open + # and read in the database. The database remains in memory between + # calls to HELP, provided the process does not shutdown, provided + # the name of the database to be used does not change, and provided + # a new help database is not created. + + if (db_ctime > 0) { + list = fntopnb (helpdb, YES) + while (fntgfnb (list, Memc[fname], SZ_PATHNAME) != EOF) { + if (finfo (Memc[fname], fi) != ERR) { + if (db != NULL && FI_CTIME(fi) > db_ctime) { + call hdb_close (db) + db = NULL + break + } + } + } + call fntclsb (list) + } else + db = NULL + + # Reopen the help database if in-core copy is out of date. + if (db == NULL) { + db = hdb_open (helpdb) + db_ctime = clktime (long(0)) + } + + # Fetch the value of the ALL switch. This determines whether help + # will stop after processing the first module matching the template, + # or process all modules in the database which match the template. + # Explicit use of a pattern matching character anywhere in the template + # enable allmodoules. + + if (stridxs ("*?[],", H_TEMPLATE(ctrl)) > 0) + H_ALLMODULES(ctrl) = YES + else + H_ALLMODULES(ctrl) = NO + + # If the FILTER_INPUT flag is set, only part of the input text will be + # processed. Filtering is only done if printing a single section or + # parameter. + + H_FILTER_INPUT(ctrl) = NO + + # Determine whether or not text for a single section or parameter + # is to be output. If the value of one of these strings is "all", + # all sections or all parameters are to be output. If the "all" + # default is in effect, null the string as a flag to lower level + # code that all help text is to be processed. + + if (H_OPTION(ctrl) == NULL) { + call strcpy (section, H_SECNAME(ctrl), SZ_SECNAME) + if (streq (H_SECNAME(ctrl), "all")) { + H_SECNAME(ctrl) = EOS + H_PARNAME(ctrl) = EOS + } + if (H_SECNAME(ctrl) != EOS || H_PARNAME(ctrl) != EOS) + H_FILTER_INPUT(ctrl) = YES + } + + # Fetch and decode option string; abbreviations are permitted. + if (H_OPTION(ctrl) != O_MENU) { + call strcpy (opt, Memc[optn], SZ_FNAME) + call strlwr (Memc[optn]) + iferr (H_OPTION(ctrl) = get_option (Memc[optn])) { + H_OPTION(ctrl) = O_HELP + call erract (EA_WARN) + } + } + +forms_ + # Pause between screens of output text only if the standard output + # is not redirected, and if enabled by the user. + + H_IN(ctrl) = ERR + H_OUT(ctrl) = fd + H_NLINES(ctrl) = -1 + H_STATE(ctrl) = BOF + H_EOF(ctrl) = NO + H_QUIT(ctrl) = NO + + # If the standard output is not redirected, i.e., if writing to the + # terminal, determine whether or not output is to be paginated (pause + # between pages). If output is redirected, the pagination flag + # and help option controls whether or not manpage style output is + # enabled. Manpage output formatting is desirable only when formatting + # help text or printing named files. + + H_RAWOUT(ctrl) = YES + H_MANPAGE(ctrl) = NO + H_PAGINATE(ctrl) = NO + H_SOFLAG(ctrl) = NO + H_FORMAT(ctrl) = format + + # We don't produce output to a screen so shut off the tty. + + H_TTY(ctrl) = NULL + + # Set left and right margins for output text format. + + H_LMARGIN(ctrl) = 1 + H_RMARGIN(ctrl) = 72 + + # Copy the current package to the control struct. + if (strne(curpack,"Home") && strne(curpack,"")) + call strcpy (curpack, H_CURPACK(ctrl), SZ_CURPACK) + + # Initialization is completed, control structure is completed. + # Format and output the help text. If we have a module name template + # process the template against the help database, otherwise work + # directly out of the named files. + + if (file[1] == EOS) + call do_module_template (db, H_TEMPLATE(ctrl), ctrl) + else + call do_file_template (H_TEMPLATE(ctrl), ctrl) + + call sfree (sp) +end diff --git a/pkg/system/help/xhelp/xhinit.x b/pkg/system/help/xhelp/xhinit.x new file mode 100644 index 00000000..41ff5b65 --- /dev/null +++ b/pkg/system/help/xhelp/xhinit.x @@ -0,0 +1,77 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "xhelp.h" + + +# XH_INIT -- Initialize the task and the GUI. + +procedure xh_init (xh, file_template, search) + +pointer xh #i task struct pointer +int file_template #i is topic a file template? +int search #i doing a search? + +char curdir[SZ_FNAME] +int fd + +pointer strestore() +int envgets(), open() +bool streq() +errchk open + +begin + # Update the quickref file. + call xh_updt_quickref (xh) + + # If starting up with a search, get that information first. + if (search == YES && TEMPLATE(xh) != EOS) { + call xh_search (xh, NO, TEMPLATE(xh)) + call strcpy ("", TEMPLATE(xh), SZ_FNAME) + call strcpy ("", LIST(xh), SZ_LINE) + } + + # Create the root package and send the results to the GUI. + call xh_root_pkg (xh) + call gmsg (XH_GP(xh), "pkglist", LIST(xh)) + + # Initialize the package list symtab. + iferr (fd = open (PKGFILE, READ_ONLY, BINARY_FILE)) + call error (0, "Cannot open package list symtab") + XH_STP(xh) = strestore (fd) + call close (fd) + call gmsgi (XH_GP(xh), "showtype", XH_SHOWTYPE(xh)) + + + if (TEMPLATE(xh) != EOS && file_template == NO) { + # If we're given an initial help topic, get the page and load it. + #call xh_help (xh, TEMPLATE(xh), TEMPLATE(xh), OPTION(xh)) + call xh_cmd_help (xh, TEMPLATE(xh), "{}", OPTION(xh)) + call strcpy ("", TEMPLATE(xh), SZ_FNAME) + + } else if (TEMPLATE(xh) != EOS && file_template == YES) { + # Load a user defined page. + call xh_open_file (xh, "helpres", TEMPLATE(xh), YES, YES) + call strcpy ("", TEMPLATE(xh), SZ_FNAME) + + } else { + # Load either a user defined homepage or the task help. + call clgstr ("home", HOMEPAGE(xh), SZ_FNAME) + if (streq ("", HOMEPAGE(xh))) + call strcpy (HELP, HOMEPAGE(xh), SZ_FNAME) + call xh_open_file (xh, "helpres", HOMEPAGE(xh), NO, YES) + } + + # Set the printer to be used. + call gmsg (XH_GP(xh), "printer", PRINTER(xh)) + + # Initialize the online help doc. + call xh_open_file (xh, "help", HELP, NO, YES) + + # Initialize the file browsing parameters. Since we can't + # get the current directory for the session use home$. + if (envgets ("home", curdir, SZ_FNAME) != EOF) { + call xh_set_pattern (xh, "*") + call xh_set_curdir (xh, curdir) + call xh_dirlist (xh, CURDIR(xh), PATTERN(xh)) + } +end diff --git a/pkg/system/help/xhelp/xhofile.x b/pkg/system/help/xhelp/xhofile.x new file mode 100644 index 00000000..c12ea7d3 --- /dev/null +++ b/pkg/system/help/xhelp/xhofile.x @@ -0,0 +1,188 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <fset.h> +include "xhelp.h" + + +# XH_OPEN_FILE -- Open the named file and send it to the GUI. If this is +# a help document (i.e. it contains a ".help" block) we first convert it +# to HTML, otherwise send it as is. + +procedure xh_open_file (xh, parameter, filename, check_for_help, warn) + +pointer xh # task descriptor +char parameter[ARB] # GUI parameter to notify +char filename[ARB] # file to open +int check_for_help # check file for help block? +int warn # warn if not present? + +pointer sp, ip, buf, out, text +int fdi, fdo +long fsize +bool has_help + +int access(), open(), getline() +int strmatch(), gstrcpy() +long fstatl() +errchk open + +define err_ 99 + +begin + call smark (sp) + call salloc (buf, SZ_LINE, TY_CHAR) + call salloc (out, SZ_FNAME, TY_CHAR) + + # Make sure the file exists. + if (access (filename, 0, 0) == NO) { + if (warn == YES) { + call sprintf (Memc[buf], SZ_LINE, "File does not exist:\n`%s'.") + call pargstr (filename) + call gmsg (XH_GP(xh), "alert", Memc[buf]) + } + goto err_ + } else if (access (filename, 0, BINARY_FILE) == YES) { + if (warn == YES) { + call sprintf (Memc[buf], SZ_LINE, + "Attempt to load binary file:\n`%s'.") + call pargstr (filename) + call gmsg (XH_GP(xh), "alert", "pop") + call gmsg (XH_GP(xh), "alert", Memc[buf]) + } + goto err_ + } + + # If we're told not to look for help simply open the file and send + # it to the GUI (e.g. used for homepage and online help). + if (check_for_help == NO) { + call xh_load_file (xh, parameter, filename) + call sfree (sp) + return + } + + # Open the file. + iferr (fdi = open (filename, READ_ONLY, TEXT_FILE)) { + if (warn == YES) { + call sprintf (Memc[buf], SZ_LINE, "Cannot open file\n`%s'.") + call pargstr (filename) + call gmsg (XH_GP(xh), "alert", Memc[buf]) + } + goto err_ + } + + # Allocate an array the length of the file, if this isn't a help file + # we use this as the message buffer and send it to the GUI. + fsize = fstatl (fdi, F_FILESIZE) + call salloc (text, fsize+1, TY_CHAR) + call aclrc (Memc[text], fsize+1) + + # See whether this is a help file + has_help = FALSE + ip = text + while (getline (fdi, Memc[buf]) != EOF) { + if (strmatch (Memc[buf], "^.help") > 0) { + has_help = TRUE + break + } + ip = ip + gstrcpy (Memc[buf], Memc[ip], SZ_LINE) + } + Memc[ip] = EOS + + + # If the file was found to have a .help block we're positioned at + # the beginning of the block. Convert the remainder to an HTML + # temp file and send that to the GUI, otherwise we already have the + # contents of the file in the text buffer so send that. + if (has_help) { + # Create an output filename and open it for writing. + call mktemp ("tmp$xhelpi", Memc[out], SZ_FNAME) + fdo = open (Memc[out], NEW_FILE, TEXT_FILE) + + # Convert the remainder to HTML and send it to the GUI. + if (fdo != ERR) { + call lroff2html (fdi, fdo, filename, "", "", "", "") + call close (fdo) + + call xh_load_file (xh, "helpres", Memc[out]) + call delete (Memc[out]) + } + + } else { + # No help was found, send the contents straight to the display. + call xh_text_msg (XH_GP(xh), "helpres", Memc[text]) + } + + +err_ if (fdi != ERR) + call close (fdi) + call sfree (sp) +end + + +# XH_LOAD_FILE -- Load the named file in the GUI. + +procedure xh_load_file (xh, parameter, filename) + +pointer xh # task descriptor +char parameter[ARB] # GUI parameter to notify +char filename[ARB] # file to display + +pointer sp, ip, line, text +int fd, open(), getline(), gstrcpy() +long fsize, fstatl() +errchk open + +begin + call smark (sp) + call salloc (line, SZ_LINE, TY_CHAR) + + # Open the file and send it to the display. + fd = open (filename, READ_ONLY, TEXT_FILE) + if (fd != ERR) { + fsize = fstatl (fd, F_FILESIZE) + call salloc (text, fsize+1, TY_CHAR) + call aclrc (Memc[text], fsize+1) + + for (ip=text; getline (fd, Memc[line]) != EOF; ) + ip = ip + gstrcpy (Memc[line], Memc[ip], SZ_LINE) + + Memc[ip] = EOS + call close (fd) + + call xh_text_msg (XH_GP(xh), parameter, Memc[text]) + } + + call sfree (sp) +end + + +# XH_TEXT_MSG -- Send a text message to a named UI parameter but first +# escape all curly braces so it passes through the Tcl correctly. + +procedure xh_text_msg (gp, param, msg) + +pointer gp +char param[ARB], msg[ARB] + +pointer buf, ip +int i, nchars +int strlen() + +begin + nchars = strlen (msg) + call calloc (buf, nchars + SZ_LINE, TY_CHAR) + + ip = buf + for (i=1; i < nchars; i=i+1) { + if (msg[i] == '{' || msg[i] == '}') { + Memc[ip] = '\\' + ip = ip + 1 + } + Memc[ip] = msg[i] + ip = ip + 1 + } + + call gmsg (gp, "type", "file") + call gmsg (gp, param, Memc[buf]) + call mfree (buf, TY_CHAR) +end diff --git a/pkg/system/help/xhelp/xhpkg.x b/pkg/system/help/xhelp/xhpkg.x new file mode 100644 index 00000000..44580f15 --- /dev/null +++ b/pkg/system/help/xhelp/xhpkg.x @@ -0,0 +1,192 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <fset.h> +include <error.h> +include "../help.h" +include "../helpdir.h" +include "xhelp.h" + + +# XH_GPKGLIST -- Get the requested package list as a sorted array of pointers. +# This is essentially a "help <pkg>" request, the caller passes the sorted +# list returned in 'pkglist" required. + +int procedure xh_pkglist (xh, topic, helpdb, pkglist) + +pointer xh #i task descriptor pointer +char topic[ARB] #i search key +char helpdb[ARB] #i filename of database to be examined +char pkglist[ARB] #o package list + +int i, m +pointer sp, pknm, hp, pp, sym +pointer db, ixoff, ix + +bool strne() +int gstrcpy(), strsearch(), hd_getname() +pointer hdb_open(), hdb_load(), stfind() +errchk hdb_open, hdb_printpack, hdb_load + +begin + call smark (sp) + call salloc (pknm, MAX_MENUSIZE, TY_POINTER) + + db = hdb_open (helpdb) + ixoff = HDB_INDEXPTR(db) + pp = NULL + + # Search for the right topic. + do i = 1, HDB_NENTRIES(db) { + ix = ixoff + (i - 1) * LEN_HDBINDEX + if (strne (DBI_KEY(ix), "_index") && + strsearch (DBI_KEY(ix),topic) != 0) { + + iferr (hp = hdb_load (db, DBI_KEY(ix))) { + call sfree (sp) + call erract (EA_WARN) + return (0) + } + + # If this isn't the package we're after then move on. + if (HD_PAKNAME(hp) == 0 || + strne (topic, Memc[HD_SBUF(hp)+HD_PAKNAME(hp)])) + next + + # Extract the names of the modules in the package. Save the + # pointers in an array for the table print routine. + + pp = 1 + for (m=0; m < MAX_MENUSIZE; m=m+1) { + call salloc (Memi[pknm+m], MAX_NAMELEN, TY_CHAR) + if (hd_getname (hp, m+1, TY_MODNAME, Memc[Memi[pknm+m]], + MAX_NAMELEN) <= 0) + break + + # Copy the names to the output array. + pp = pp + gstrcpy (Memc[Memi[pknm+m]], pkglist[pp], ARB) + if (XH_SHOWTYPE(xh) == YES && XH_STP(xh) != NULL) { + sym = stfind (XH_STP(xh), Memc[Memi[pknm+m]]) + if (sym != NULL) + pp = pp + gstrcpy (".", pkglist[pp], ARB) + } + pp = pp + gstrcpy (" ", pkglist[pp], ARB) + } + break + } + } + if (pp != NULL) + pkglist[pp] = EOS + + call hdb_free (db, hp) + call hdb_close (db) + call sfree (sp) + return (pp) +end + + +# XH_PKGPATH -- Get the package path associated with a particular task. +# If we're given a parent package follow it back so we get the correct +# path for a task that may be defined multiple places (e.g. SPLOT). + +procedure xh_pkgpath (xh, topic, curpack, path) + +pointer xh #i task struct pointer +char topic[ARB] #i help topic +char curpack[ARB] #i help topic +char path[ARB] #o package path + +pointer sp, pkg, task, buf +int strncmp(), xh_pkgname() +bool streq() + +begin + call smark (sp) + call salloc (pkg, SZ_FNAME, TY_CHAR) + call salloc (task, SZ_FNAME, TY_CHAR) + call salloc (buf, SZ_FNAME, TY_CHAR) + + if (curpack[1] == EOS || + streq (topic, curpack) || + strncmp ("root", curpack, 4) == 0 || + streq ("clpackage", curpack)) { + call strcpy (topic, Memc[task], SZ_FNAME) + call strcpy (topic, path, SZ_FNAME) + } else { + call strcpy (curpack, Memc[task], SZ_FNAME) + call sprintf (path, SZ_PATHNAME, "%s.%s") + call pargstr (curpack) + call pargstr (topic) + } + + Memc[pkg] = EOS + while (xh_pkgname (xh, Memc[task], Memc[pkg]) == OK) { + if (strncmp ("root", Memc[pkg], 4) == 0 || + streq (Memc[task], Memc[pkg]) || + streq ("clpackage", Memc[pkg])) + break + else { + call sprintf (Memc[buf], SZ_PATHNAME, "%s.%s") + call pargstr (Memc[pkg]) + call pargstr (path) + call strcpy (Memc[buf], path, SZ_PATHNAME) + } + call strcpy (Memc[pkg], Memc[task], SZ_FNAME) + Memc[pkg] = EOS + } + + call sfree (sp) +end + + +# XH_PKGNAME -- Get the package name associated with a particular task. + +int procedure xh_pkgname (xh, topic, pack) + +pointer xh #i task struct pointer +char topic[ARB] #i help topic +char pack[ARB] #o package + +pointer sp, line, fname +long fsize, fstatl() +int fd, status, getline(), open(), stridxs() + +begin + call smark (sp) + call salloc (line, SZ_LINE, TY_CHAR) + call salloc (fname, SZ_LINE, TY_CHAR) + + status = ERR + + # Get a temp file name. + call mktemp ("tmp$xhelpi", Memc[fname], SZ_FNAME) + + # Open a temp file with the help information found. + fd = open (Memc[fname], NEW_FILE, TEXT_FILE) + call xh_get_help (fd, topic, "", "", HF_HTML, HELPDB(xh), + "all", "files") + call close (fd) + + # Open the results file for reading. + fd = open (Memc[fname], READ_ONLY, TEXT_FILE) + fsize = fstatl (fd, F_FILESIZE) + + # Search the results for the package line. + if (fsize != 0) { + status = OK + while (getline (fd, Memc[line]) != EOF) { + + # Extract the package name. + if (stridxs (":", Memc[line]) > 0) { + Memc[line+stridxs(".",Memc[line])-1] = EOS + call strcpy (Memc[line], pack, SZ_FNAME) + break + } + } + } + + call close (fd) # clean up + call delete (Memc[fname]) + call sfree (sp) + + return (status) +end diff --git a/pkg/system/help/xhelp/xhprint.x b/pkg/system/help/xhelp/xhprint.x new file mode 100644 index 00000000..4e273848 --- /dev/null +++ b/pkg/system/help/xhelp/xhprint.x @@ -0,0 +1,151 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <syserr.h> +include <error.h> +include <ctype.h> +include <ttyset.h> +include "../help.h" +include "xhelp.h" + + +# XH_PRINT_HELP -- Print the requested help topic. + +procedure xh_print_help (xh, topic, curpack, name) + +pointer xh #i task struct pointer +char topic[ARB] #i help topic +char curpack[ARB] #i current package +char name[ARB] #i printer name + +int fd +char fname[SZ_FNAME] + +int open() +errchk open + +begin + # Open a temp file with the help information. + call mktemp ("tmp$xhelpi", fname, SZ_FNAME) + fd = open (fname, NEW_FILE, TEXT_FILE) + call xh_get_help (fd, topic, curpack, "", HF_PS, HELPDB(xh), + "all", OPTION(xh)) + call close (fd) + + call strcpy (name, PRINTER(xh), SZ_FNAME) + call xh_lprint (fname, PRINTER(xh)) + + # Clean up. + call delete (fname) +end + + +# XH_LPRINT -- Print a file or files on the lineprinter. TTYPUTLINE is used +# to output lines to the printer file, so that formfeeds, standout mode, etc., +# may be properly translated for the indicated device. + +procedure xh_lprint (fname, device) + +char fname[ARB] +char device[ARB] + +int out +pointer sp, lp, ddstr + +pointer ttyodes() +bool streq() +int envgets(), lpopen(), ttygets() +string printer "printer" +errchk clgfil, xh_print_file + +begin + call smark (sp) + call salloc (ddstr, SZ_DDSTR, TY_CHAR) + + # Get device name. Default is "printer", which means that the actual + # device name is given by the environment variable "printer". + + if (streq (device, printer)) + if (envgets (printer, device, SZ_FNAME) <= 0) + call syserrs (SYS_ENVNF, printer) + + # Open TTY descriptor and printer file. We deal only with character + # data, so open printer as a text file. Output the files to the line + # printer device. + + lp = ttyodes (device) + if (ttygets (lp, "DD", Memc[ddstr], SZ_DDSTR) <= 0) + call error (1, "missing 'DD' parameter in termcap entry") + + out = lpopen (Memc[ddstr], APPEND, TEXT_FILE) + + # Output file, followed by a form feed. + iferr { + call xh_print_file (out, lp, fname) + call flush (out) + } then + call erract (EA_WARN) + + call close (out) + call ttycdes (lp) + call sfree (sp) +end + + +# XH_PRINT_FILE -- Open and print the named text file on the output file, +# under control of the tty device descriptor LP. Print a header on each +# page if enabled, and formfeed at the end of the file. The number of lines +# per page is given by the tty descriptor. + +procedure xh_print_file (out, lp, fname) + +int out +pointer lp +char fname[ARB] + +bool one_tab_in +int lineno, maxlines, status, in +pointer sp, ip, lbuf +int open(), getline(), ttystati() +errchk salloc, open, ttystati, getline, ttyputline + +begin + call smark (sp) + call salloc (lbuf, SZ_LINE+1, TY_CHAR) + + in = open (fname, READ_ONLY, TEXT_FILE) + maxlines = ttystati (lp, TTY_NLINES) + + # If printer page is very wide, set page in one tabstop from left + # margin. + + one_tab_in = (ttystati (lp, TTY_NCOLS) > WIDE_PAGE) + if (one_tab_in) { + Memc[lbuf] = '\t' + ip = lbuf + 1 + } else + ip = lbuf + + + # Format and write each page of output. If headers are enabled, + # output formfeed and header between pages. + + status = OK + while (status != EOF) { + # Output one page of text. Each output line is processed by + # ttyputline to expand tabs, underline, etc. + + for (lineno=1; lineno <= maxlines; lineno=lineno+1) { + status = getline (in, Memc[ip]) + if (status == EOF) + break + if (Memc[ip] == '\f') { + call ttyputline (out, lp, "\f", YES) + call strcpy (Memc[ip+1], Memc[ip], SZ_LINE) + } + call ttyputline (out, lp, Memc[lbuf], YES) + } + } + + call close (in) + call sfree (sp) +end diff --git a/pkg/system/help/xhelp/xhqref.x b/pkg/system/help/xhelp/xhqref.x new file mode 100644 index 00000000..51912169 --- /dev/null +++ b/pkg/system/help/xhelp/xhqref.x @@ -0,0 +1,250 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <syserr.h> +include <finfo.h> +include <ctype.h> +include "../help.h" +include "xhelp.h" + +define MAX_PKGS 200 +define SZ_PKG 32 +define EXTPKG "hlib$extern.pkg" + + +# XH_UPDT_QUICKREF -- Update a quick reference file for the help database +# if needed. + +procedure xh_updt_quickref (xh) + +pointer xh + +long fiq[LEN_FINFO], fie[LEN_FINFO] + +int access() +long finfo() +errchk access, finfo + +begin + # If the quickref file exists, and it is older than the + # hlib$extern.pkg file which defines the helpdb rebuild + # the quickref file so we're current, otherwise rebuild + # the quickref file anyway. + if ((access (QUICKREF(xh), 0, 0) == NO) || + (access (PKGFILE, 0, 0) == NO)) { + call xh_make_quickref (xh, QUICKREF(xh)) + } else { + if (finfo (QUICKREF(xh), fiq) == ERR) + call filerr (QUICKREF(xh), SYS_FOPNNEXFIL) + if (finfo (EXTPKG, fie) == ERR) + call filerr (EXTPKG, SYS_FOPNNEXFIL) + + if (FI_MTIME[fie] > FI_MTIME[fiq]) { + call delete (QUICKREF(xh)) + call xh_make_quickref (xh, QUICKREF(xh)) + } + } +end + + +# XH_MAKE_QUICKREF -- Make a quick reference file for the help database. + +procedure xh_make_quickref (xh, quickref) + +pointer xh #i task struct pointer +char quickref[ARB] #i quickref filename + +pointer pkglist, pp +int fdi, fdo, fd_err +int sz_pbuf, npkgs +char fname[SZ_FNAME], efname[SZ_FNAME] +char pkg[SZ_PKG], lastpkg[SZ_PKG], line[SZ_LINE] + +int open(), access(), getline(), gstrcpy(), strsearch(), strcmp() +errchk open + +begin + # Tell the GUI we're actually busy doing something.... + call gmsg (XH_GP(xh), "alert", + "Please wait,\ngenerating QuickRef file...") + call gflush (XH_GP(xh)) + + # Open the STDERR stream onto a dummy file to catch any + # "no help available" messages that may interfere with the + # textout GUI parameter. + call mktemp ("tmp$xerr", efname, SZ_FNAME) + fd_err = open (efname, NEW_FILE, TEXT_FILE) + call frediro (STDERR, fd_err) + + # Open a temp file with the raw search information. + call mktemp ("tmp$xhelpq", fname, SZ_FNAME) + fdi = open (fname, NEW_FILE, TEXT_FILE) + + call xh_get_help (fdi, "[a-z]*.", "", "", HF_HTML, HELPDB(xh), "help", + "references") + call close (fdi) + + # Close the error file, swap back the descriptors first and delete it. + call fswapfd (STDERR, fd_err) + call close (fd_err) + call delete (efname) + + # Delete existing files. + if (access (quickref, 0, 0) == YES) + call delete (quickref) + + # Open the references file. + iferr (fdo = open (quickref, NEW_FILE, TEXT_FILE)) { + call sprintf (line, SZ_LINE, "Cannot create quickref file `%s'.") + call pargstr (quickref) + call error (0, line) + } + fdi = open (fname, READ_ONLY, TEXT_FILE) + + # Initialize for the package list. + pkg[1] = EOS + lastpkg[1] = EOS + npkgs = 0 + sz_pbuf = MAX_PKGS * SZ_PKG + call malloc (pkglist, sz_pbuf, TY_CHAR) + pp = pkglist + + # Loop over the lines in the file, save the ones that are the + # descriptions. Descriptions are assumed to contain a '-' since + # this is standard for .men files, to be safe we also required + # the bracketed package name generated with a 'references' query. + # The package name is used to create the package list symtab we + # use to show the item as a task or package. + + while (getline(fdi,line) != EOF) { + if (strsearch (line, " - ") != 0 && strsearch (line, "[") != 0) { + call putline (fdo, line) + + # Extract the package name. The results aren't sorted at + # this point so we see whether this package is the same as + # the last before adding it to the package list. This + # gives us a unique list of unsorted package names. + + call xh_gname (line, pkg) + if (lastpkg[1] == EOS) + call strcpy (pkg, lastpkg, SZ_PKG) + if (strcmp (pkg, lastpkg) != 0) { + npkgs = npkgs + 1 + + # Protect against overflowing the buffer. + if ((pp - pkglist) > sz_pbuf) + call error (1, "Package buffer overflow.") + + pp = pp + gstrcpy (pkg, Memc[pp], SZ_PKG) + pp = pp + gstrcpy (" ", Memc[pp], SZ_PKG) + call strcpy (pkg, lastpkg, SZ_PKG) + } + } + } + Memc[pp] = EOS + + # Close the new references file. + call close (fdo) + + # Close and delete the references temp files. + call close (fdi) + call delete (fname) + + # Sort the lines of the references file. + call xh_file_sort (quickref) + + # Now send the package list off to be stored for the next time. + call xh_make_pkglist (Memc[pkglist]) + + call mfree (pkglist, TY_CHAR) + + # Tell the GUI we're done. + call gmsg (XH_GP(xh), "alert", "dismiss") + call gflush (XH_GP(xh)) +end + + +# XH_MAKE_PKGLIST -- Update the package symtab file. We are only called +# when updating the quickref database so delete any existing file before +# writing the new one. + +procedure xh_make_pkglist (list) + +char list[ARB] #i package list + +pointer sp, err, pkg +pointer stp, sym +int i, ip, fd + +pointer stopen(), stenter() +int open(), access(), strlen() +errchk open + +begin + call smark (sp) + call salloc (err, SZ_LINE, TY_CHAR) + call salloc (pkg, SZ_FNAME, TY_CHAR) + + # Delete existing files. + if (access(PKGFILE,0,0) == YES) + call delete (PKGFILE) + + # Open the package symtab file. + iferr (fd = open (PKGFILE, NEW_FILE, BINARY_FILE)) { + call sprintf (Memc[err], SZ_LINE, "Can't create pkg symtab `%s'.") + call pargstr (PKGFILE) + call error (0, Memc[err]) + } + + # Sort the list before making the symtab. + call xh_sort_list (list) + + # Open the symtab. + stp = stopen ("package list", LEN_INDEX, LEN_STAB, SZ_SBUF) + + # Enter strings in the symtab. + i = 0 + for (ip=1; list[ip] != EOS; ip=ip+1) { + if (list[ip] == ' ') { + Memc[pkg+i] = EOS + sym = stenter (stp, Memc[pkg], strlen (Memc[pkg]) + 1) + i = 0 + ip = ip + 1 + } + Memc[pkg+i] = list[ip] + i = i + 1 + } + + # Save the symtab file. + call stsqueeze (stp) + call stsave (stp, fd) + + # Clean up. + call stclose (stp) + call close (fd) + call sfree (sp) +end + + +# XH_GNAME -- Extract the package name from a 'references' line. + +procedure xh_gname (line, pkg) + +char line[ARB] #i references line +char pkg[ARB] #o package name in line + +int ip, strlen() + +begin + # Clear trailing whitespace back to the ']' at end of the + # package name. + for (ip=strlen(line); line[ip] != ']' || IS_WHITE(line[ip]); ) + ip = ip - 1 + line[ip] = EOS + + # Move back to starting '[' of package name. + while (line[ip] != '[' && ip > 0) + ip = ip - 1 + + # What's left is the package name, copy it to the output. + call strcpy (line[ip+1], pkg, SZ_PKG) +end diff --git a/pkg/system/help/xhelp/xhroot.x b/pkg/system/help/xhelp/xhroot.x new file mode 100644 index 00000000..9559662a --- /dev/null +++ b/pkg/system/help/xhelp/xhroot.x @@ -0,0 +1,73 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include "xhelp.h" + + +# XH_ROOT_PKG -- Make the root package. Search the help database and +# create a package list for all modules found. We add special entries for +# system modules (imfort/math/os) which are not normally in the help tree +# but provide documents. + +procedure xh_root_pkg (xh) + +pointer xh #i struct pointer. + +pointer sp, fname, buf, ip, op, lp +int list + +int xh_pkglist() +int gstrcpy(), fntopnb(), fntgfnb() +bool strne() + +begin + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (buf, SZ_FNAME, TY_CHAR) + + # Set initial packages and help databases. This consists of the + # system documentation (in sys$sys.hd), the contents of the + # clpackage module and each of the external packages. + + lp = XH_LPTR(xh) + + # Create an entry for seldom-read system docs. + if (XH_SHOWTYPE(xh) == YES) { + lp = lp + gstrcpy ("imfort. ", Memc[lp], ARB) + lp = lp + gstrcpy ("math. ", Memc[lp], ARB) + lp = lp + gstrcpy ("os. ", Memc[lp], ARB) + } else { + lp = lp + gstrcpy ("imfort ", Memc[lp], ARB) + lp = lp + gstrcpy ("math ", Memc[lp], ARB) + lp = lp + gstrcpy ("os ", Memc[lp], ARB) + } + + # Add the external packages to the list. + list = fntopnb (HELPDB(xh), YES) + while (fntgfnb (list, Memc[fname], SZ_FNAME) != EOF) { + op = buf + ip = fname + while (Memc[ip] != '$' && Memc[ip] != EOS && Memc[ip] != ',') { + Memc[op] = Memc[ip] + ip = ip + 1 + op = op + 1 + } + Memc[op] = EOS + if (strne(Memc[buf],"lib")) { + lp = lp + gstrcpy (Memc[buf], Memc[lp], ARB) + if (XH_SHOWTYPE(xh) == YES) + lp = lp + gstrcpy (".", Memc[lp], ARB) + lp = lp + gstrcpy (" ", Memc[lp], ARB) + } + } + + # Add the clpackage contents to the list. + lp = lp + xh_pkglist (xh, "clpackage", HELPDB(xh), Memc[lp]) + + if (lp > (XH_LPTR(xh) + SZ_HELPLIST)) + call error (1, "Memory error: LIST pointer overflow.") + + # Sort the list so it's presentable. + call xh_sort_list (LIST(xh)) + + call sfree (sp) +end diff --git a/pkg/system/help/xhelp/xhsave.x b/pkg/system/help/xhelp/xhsave.x new file mode 100644 index 00000000..f280146d --- /dev/null +++ b/pkg/system/help/xhelp/xhsave.x @@ -0,0 +1,184 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include "../help.h" +include "xhelp.h" + +define SZ_EXTN 10 + + +# XH_SAVE_FILE -- Save the currently displayed page to the named file in +# the specified format. + +procedure xh_save_file (xh, iname, oname, format, overwrite) + +pointer xh #i package descriptor +char iname[ARB] #i input file +char oname[ARB] #i output filename +char format[ARB] #i format +int overwrite #i overwrite flag + +pointer sp, buf +char extn[SZ_EXTN] + +int access(), fnextn(), strlen(), strcmp() + +begin + if (access (oname, 0, 0) == YES && overwrite == NO) { + call smark (sp) + call salloc (buf, SZ_LINE, TY_CHAR) + call sprintf (Memc[buf], SZ_LINE, + "Operation would overwrite\nexisting file '%s'") + call pargstr (oname) + call gmsg (XH_GP(xh), "alert", Memc[buf]) + call sfree (sp) + return + + } else if (access (oname, 0, 0) == YES) + call delete (oname) + + call aclrc (extn, SZ_EXTN) + + # Strip off any braces around the arguments that were put + # in by the Tcl script. + if (iname[1] == '{') { + call amovc (iname[2], iname, strlen(iname)-2) + iname[strlen(iname)-1] = EOS + } + if (oname[1] == '{') { + call amovc (oname[2], oname, strlen(oname)-2) + oname[strlen(oname)-1] = EOS + } + + switch (format[1]) { + case 's': # source + call fcopy (iname, oname) + case 't': # text + if (fnextn(iname, extn, 3) > 0 && strcmp("hlp", extn) == 0) + call xh_save_text (xh, iname, oname) + else + call fcopy (iname, oname) + case 'h': # html + if (fnextn(iname, extn, 3) > 0 && strcmp("hlp", extn) == 0) + call xh_save_html (xh, iname, oname, YES) + else + call xh_save_html (xh, iname, oname, NO) + case 'p': # postscript + if (fnextn(iname, extn, 3) > 0 && strcmp("hlp", extn) == 0) + call xh_save_ps (xh, iname, oname, YES) + else + call xh_save_ps (xh, iname, oname, NO) + default: + call gmsg (XH_GP(xh), "alert", "Invalid format specifier") + } +end + + +# XH_SAVE_TEXT -- Save the page as a formatted text file. + +procedure xh_save_text (xh, in, out) + +pointer xh #i package descriptor +char in[ARB], out[ARB] #i file names + +char err[SZ_LINE] +int fdout, open() +errchk open + +begin + # Open the output file. + iferr (fdout = open (out, NEW_FILE, TEXT_FILE)) { + call sprintf (err, SZ_LINE, "Cannot open output file `%s'.") + call pargstr (out) + call gmsg (XH_GP(xh), "alert", err) + return + } + + # Format the help as text. + call xh_get_help (fdout, "", "", in, HF_TEXT, HELPDB(xh), "all", "help") + + # Close the file. + call close (fdout) +end + + +# XH_SAVE_HTML -- Save the page as an HTML file. + +procedure xh_save_html (xh, in, out, ishelp) + +pointer xh #i package descriptor +char in[ARB], out[ARB] #i file names +int ishelp #i is this a help file? + +char err[SZ_LINE] +int fdout, fdin, open() +errchk open + +begin + # Open the output file. + iferr (fdout = open (out, NEW_FILE, TEXT_FILE)) { + call sprintf (err, SZ_LINE, "Cannot open output file `%s'.") + call pargstr (out) + call gmsg (XH_GP(xh), "alert", err) + return + } + + # Format the help as text. + if (ishelp == YES) { + call xh_get_help (fdout, "", "", in, HF_HTML, HELPDB(xh), + "all", "help") + } else { + # Open the input file. + iferr (fdout = open (out, NEW_FILE, TEXT_FILE)) { + call sprintf (err, SZ_LINE, "Cannot open output file `%s'.") + call pargstr (out) + call gmsg (XH_GP(xh), "alert", err) + return + } + + call fprintf (out, "<HTML><BODY>\n") + call fprintf (out, "<TITLE>%s</TITLE>\n") + call pargstr (in) + call fprintf (out, "<PRE>\n") + call fcopyo (in, out) + call fprintf (out, "</PRE>\n") + call fprintf (out, "</BODY></HTML>\n") + + call close (fdin) + } + + # Close the file. + call close (fdout) +end + + +# XH_SAVE_PS -- Save the page as a postscript file. + +procedure xh_save_ps (xh, in, out, ishelp) + +pointer xh #i package descriptor +char in[ARB], out[ARB] #i file names +int ishelp #i is this a help file? + +char err[SZ_LINE] +int fdout, open() +errchk open + +begin + if (ishelp == NO) + return + + # Open the output file. + iferr (fdout = open (out, NEW_FILE, TEXT_FILE)) { + call sprintf (err, SZ_LINE, "Cannot open output file `%s'.") + call pargstr (out) + call gmsg (XH_GP(xh), "alert", err) + return + } + + # Format the help as text. + call xh_get_help (fdout, "", "", in, HF_PS, HELPDB(xh), "all", "help") + + # Close the file. + call close (fdout) +end diff --git a/pkg/system/help/xhelp/xhsearch.x b/pkg/system/help/xhelp/xhsearch.x new file mode 100644 index 00000000..18f1aa28 --- /dev/null +++ b/pkg/system/help/xhelp/xhsearch.x @@ -0,0 +1,185 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <fset.h> +include <ctype.h> +include "xhelp.h" + + +# XH_SEARCH -- Given a search pattern generate a list of tasks matching the +# pattern. + +procedure xh_search (xh, exact_match, pattern) + +pointer xh #i task struct pointer +int exact_match #i require an exact match? +char pattern[ARB] #i search pattern + +pointer sp, lfile, line, helpstr, item +pointer tp, lp, pat +char task[SZ_FNAME], pkg[SZ_FNAME], desc[SZ_FNAME] +int i, ip, fd, fdl +long fsize + +long fstatl() +int open(), xh_match(), getline(), gstrcpy() +errchk open, xh_updt_quickref + +begin + call smark (sp) + call salloc (lfile, SZ_FNAME, TY_CHAR) + call salloc (line, SZ_LINE, TY_CHAR) + call salloc (item, SZ_LINE, TY_CHAR) + call salloc (pat, SZ_FNAME, TY_CHAR) + + # Open the quick reference file. + iferr (fd = open (QUICKREF(xh), READ_ONLY, TEXT_FILE)) + call error (0, "Cannot open quick-reference file.") + + # Open the temp file for the matched lines. + call mktemp ("tmp$xhelpq", Memc[lfile], SZ_FNAME) + fdl = open (Memc[lfile], NEW_FILE, TEXT_FILE) + + # Allocate space for the results string. + fsize = fstatl (fd, F_FILESIZE) + + # Check pattern for multi-word searches. + call aclrc (Memc[pat], SZ_FNAME) + for (ip=1; IS_WHITE(pattern[ip]); ip=ip+1) + ; + if (pattern[ip] == '{') { + ip = ip + 1 + for (i=0; pattern[ip] != '}'; ip=ip+1) { + Memc[pat+i] = pattern[ip] + i = i + 1 + } + } else + call strcpy (pattern[ip], Memc[pat], SZ_FNAME) + + # Loop over the lines in the file and match the pattern. + while (getline(fd,Memc[line]) != EOF) { + if (xh_match (Memc[line], Memc[pat], exact_match) != 0) + call putline (fdl, Memc[line]) # save it to the file + } + call close (fdl) + call close (fd) + + # Now read back the file to see if we matched anything, and so we + # can parse the file for task/package names. + fdl = open (Memc[lfile], READ_ONLY, TEXT_FILE) + fsize = fstatl (fdl, F_FILESIZE) + + # See whether we got anything, if not return. + if (fsize == 0) { + call sprintf (Memc[line], SZ_LINE, + "No help available for\npattern `%s'.") + call pargstr (Memc[pat]) + call gmsg (XH_GP(xh), "alert", Memc[line]) + + call close (fdl) + call delete (Memc[lfile]) + call sfree (sp) + return + } + call calloc (helpstr, 5*fsize, TY_CHAR) + + # Read back the sorted list, separate the task name, package, and + # descriptions and format it for the GUI. + tp = helpstr + tp = tp + gstrcpy ("<HTML><BODY><PRE>", Memc[tp], ARB) + while (getline(fdl, Memc[line]) != EOF) { + Memc[item] = EOS + lp = line + + # Get the task name. + for (i=1; !IS_WHITE(Memc[lp]); i=i+1) { + task[i] = Memc[lp] + lp = lp + 1 + if (Memc[lp] == EOS || i >= SZ_FNAME) + break + } + task[i] = EOS + + # Skip delimiter. + while (IS_WHITE(Memc[lp]) || Memc[lp] == '-') + lp = lp + 1 + + # Get the description up to the '[' package name. + for (i=1; Memc[lp] != '['; i=i+1) { + desc[i] = Memc[lp] + lp = lp + 1 + if (Memc[lp] == EOS || i >= SZ_FNAME) + break + } + desc[i] = EOS + + # Get the package name up to the ']' delimiter. + if (Memc[lp] != EOS) { + lp = lp + 1 + for (i=1; Memc[lp] != ']'; i=i+1) { + pkg[i] = Memc[lp] + lp = lp + 1 + if (Memc[lp] == '\n' || Memc[lp] == EOS || i >= SZ_FNAME) + break + } + } + pkg[i] = EOS + + call sprintf(Memc[item], SZ_LINE, "<A HREF=%s.%s>%10.10s</A> ") + call pargstr (pkg) + call pargstr (task) + call pargstr (task) + tp = tp + gstrcpy (Memc[item], Memc[tp], ARB) + call sprintf(Memc[item], SZ_LINE, "<A HREF=%s.%s>%10.10s</A> ") + call pargstr (pkg) + call pargstr (pkg) + call pargstr (pkg) + tp = tp + gstrcpy (Memc[item], Memc[tp], ARB) + call sprintf(Memc[item], SZ_LINE, " %s\n") + call pargstr (desc) + tp = tp + gstrcpy (Memc[item], Memc[tp], ARB) + } + call strcat ("</PRE></BODY></HTML>\n", Memc[tp], SZ_LINE) + Memc[tp] = EOS + call close (fdl) + + # Send it to the GUI. + call gmsg (XH_GP(xh), "apropos", Memc[helpstr]) + + # Clean up. + call delete (Memc[lfile]) + call mfree (helpstr, TY_CHAR) + call sfree (sp) +end + + +# XH_MATCH -- Match any or all words in a pattern against the given line. +# We can either look for an exact match or just the occurence of one word +# in the pattern. + +int procedure xh_match (line, pattern, exact_match) + +char line[ARB] #i line to be matched +char pattern[ARB] #i pattern words +int exact_match + +char word[SZ_FNAME] +int i, j +int strsearch() + +begin + if (exact_match == YES) { + return (strsearch(line, pattern)) + } else { + # See if any word in the pattern matches in the line. + for (i=1; pattern[i] != EOS; i=i+1) { + for (j=1; pattern[i] != EOS && pattern[i] != ' '; j=j+1) { + word[j] = pattern[i] + i = i + 1 + } + word[j] = EOS + if (strsearch(line, word) != 0) + return (YES) + } + return (NO) + } +end diff --git a/pkg/system/help/xhelp/xhsort.x b/pkg/system/help/xhelp/xhsort.x new file mode 100644 index 00000000..b5ccc081 --- /dev/null +++ b/pkg/system/help/xhelp/xhsort.x @@ -0,0 +1,223 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> +include "xhelp.h" + +define MAXPTR 20000 +define SZ_LINBUF 300000 + + +# XH_SORT_LIST -- Take a list of words (as with a package list) and sort them. + +procedure xh_sort_list (list) + +char list[ARB] #u list to be sorted + +pointer sp, index, buf, ip +int i, j, count, len + +int strlen() + +begin + len = strlen (list) + + call smark (sp) + call salloc (index, SZ_HELPLIST, TY_INT) + call salloc (buf, len+2, TY_CHAR) + + # Build up the index array. + count = 1 + Memi[index] = 1 + for (i=2; i<len; i=i+1) { + if (list[i] == ' ') { + list[i] = EOS + Memi[index+count] = i + 1 + count = count + 1 + } + } + + # Sort the list. + call strsrt (Memi[index], list, count) + + # Restore the list. + ip = buf + do i = 1, count { + for (j=0; list[Memi[index+i-1]+j] != EOS; j=j+1) { + Memc[ip] = list[Memi[index+i-1]+j] + ip = ip + 1 + } + Memc[ip] = ' ' + ip = ip + 1 + } + Memc[ip-1] = EOS + call strcpy (Memc[buf], list, strlen(Memc[buf])) + call sfree (sp) +end + + +# XH_FILE_SORT -- Sort the lines in the named file. + +procedure xh_file_sort (fname) + +char fname[SZ_FNAME] #i file to be sorted + +pointer linbuf, linptr +int nlines, fd +int open() + +begin + call calloc (linptr, MAXPTR, TY_INT) + call calloc (linbuf, SZ_LINBUF, TY_CHAR) + + # Sort the file then write it back out. + fd = open (fname, READ_ONLY, TEXT_FILE) + call xh_gtext (fd, Memi[linptr], nlines, Memc[linbuf]) + call close (fd) + call delete (fname) + + call xh_quick (Memi[linptr], Memc[linbuf], nlines) + + fd = open (fname, NEW_FILE, TEXT_FILE) + call xh_ptext (fd, Memi[linptr], nlines, Memc[linbuf]) + + call mfree (linbuf, TY_CHAR) + call mfree (linptr, TY_INT) + call close (fd) +end + + +# XH_GTEXT -- Get text lines into linbuf. + +procedure xh_gtext (infile, linptr, nlines, linbuf) + +int infile, linptr[ARB], nlines +char linbuf[ARB] + +int lbp, len, getline() +errchk getline + +begin + nlines = 0 + lbp = 1 + + repeat { + len = getline (infile, linbuf[lbp]) + if (len == EOF) + break + else if (len == 1) + # ignore blank lines + else { + nlines = nlines + 1 + linptr[nlines] = lbp + lbp = lbp + len + 1 # '1' = room for EOS + } + } until (lbp >= SZ_LINBUF - SZ_LINE || nlines >= MAXPTR) +end + + +# XH_PTEXT -- Output text lines from linbuf to outfile. + +procedure xh_ptext (outfil, linptr, nlines, linbuf) + +int outfil, linptr[ARB], nlines +char linbuf[ARB] +int i, j +errchk putline + +begin + for (i=1; i <= nlines; i=i+1) { + j = linptr[i] + call putline (outfil, linbuf[j]) + } +end + + +# XH_QUICK -- Quicksort for text data. NOTE -- This algorithm is quadratic in +# the worst case, i.e., when the data is already sorted. A random method of +# selecting the pivot should be used to improve the behaviour on sorted arrays. + +procedure xh_quick (linptr, linbuf, nlines) + +int linptr[ARB] # indices of strings in buffer +char linbuf[ARB] # string buffer +int nlines # number of strings + +define LOGPTR 32 +define swap {temp=$1;$1=$2;$2=temp} + +int i, j, k, temp, lv[LOGPTR], p, pivlin, uv[LOGPTR] +int xh_compare() + +begin + lv[1] = 1 + uv[1] = nlines + p = 1 + + while (p > 0) { + if (lv[p] >= uv[p]) # only one elem in this subset + p = p - 1 # pop stack + else { + # Dummy loop to trigger optimizer. + do p = p, ARB { + i = lv[p] - 1 + j = uv[p] + + # Select pivot element at midpoint of interval to avoid + # quadratic behavior on a sorted list. + + k = (lv[p] + uv[p]) / 2 + swap (linptr[j], linptr[k]) + pivlin = linptr[j] + + while (i < j) { + for (i=i+1; xh_compare (linptr[i], pivlin, linbuf) < 0; + i=i+1) + ; + for (j=j-1; j > i; j=j-1) + if (xh_compare (linptr[j], pivlin, linbuf) <= 0) + break + if (i < j) # out of order pair + swap (linptr[i], linptr[j]) + } + + j = uv[p] # move pivot to position i + swap (linptr[i], linptr[j]) + + if (i-lv[p] < uv[p] - i) { # stack so shorter done first + lv[p+1] = lv[p] + uv[p+1] = i - 1 + lv[p] = i + 1 + } else { + lv[p+1] = i + 1 + uv[p+1] = uv[p] + uv[p] = i - 1 + } + + break + } + + p = p + 1 # push onto stack + } + } +end + + +# XH_COMPARE -- Compare two strings. Return -1 if str1<str2, 1 if str1>str2, +# or 0 if the two strings are equal. + +int procedure xh_compare (lp1, lp2, linbuf) + +int lp1, lp2 # pointers to substrings in linbuf +char linbuf[ARB] # text buffer + +int ip1, ip2, answer +int strcmp() + +begin + for (ip1=lp1; IS_WHITE(linbuf[ip1]); ip1=ip1+1) + ; + for (ip2=lp2; IS_WHITE(linbuf[ip2]); ip2=ip2+1) + ; + answer = strcmp (linbuf[ip1], linbuf[ip2]) + return (answer) +end diff --git a/pkg/system/help/xhelp/zzdebug.x b/pkg/system/help/xhelp/zzdebug.x new file mode 100644 index 00000000..70a95d9b --- /dev/null +++ b/pkg/system/help/xhelp/zzdebug.x @@ -0,0 +1,59 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + + +# ZZDEBUG.X -- Debug routines for the help formatting system. + +task lroff2html = t_lroff2html, + lroff2ps = t_lroff2ps + + +# LROFF2HTML -- Test program to convert an Lroff source file to HTML. + +procedure t_lroff2html () + +int fdi, fdo +char iname[SZ_FNAME], oname[SZ_FNAME] + +int open() +errchk open + +begin + call clgstr ("input", iname, SZ_FNAME) # get parameters + call clgstr ("output", oname, SZ_FNAME) + + fdi = open (iname, READ_ONLY, TEXT_FILE) # open the file + fdo = open (oname, NEW_FILE, TEXT_FILE) + + # Process it. + call lroff2html (fdi, fdo, iname, "", "", "", "") + + call close (fdi) + call close (fdo) +end + + +# LROFF2PS -- Test program to convert an Lroff source file to Postscript. + +procedure t_lroff2ps () + +int fdi, fdo +char iname[SZ_FNAME], oname[SZ_FNAME] + +pointer ps +int open() +errchk open + +begin + call clgstr ("input", iname, SZ_FNAME) # get parameters + call clgstr ("output", oname, SZ_FNAME) + + fdi = open (iname, READ_ONLY, TEXT_FILE) # open the files + fdo = open (oname, READ_ONLY, TEXT_FILE) + + # Process it. + ps = NULL + call lroff2ps (fdi, fdo, ps, "", "") + + call close (fdi) + call close (fdo) +end diff --git a/pkg/system/lprint.par b/pkg/system/lprint.par new file mode 100644 index 00000000..268ccac1 --- /dev/null +++ b/pkg/system/lprint.par @@ -0,0 +1,5 @@ +files,s,a,,,,"list of files to be printed" +device,s,h,"printer",,,"name of output device" +map_cc,b,h,yes,,,"make unknown control chars printable" +paginate,s,h,"auto",,,"break pages (auto, yes, no)" +label,s,h,"STDIN",,,"file name label if input redirected" diff --git a/pkg/system/lprint.x b/pkg/system/lprint.x new file mode 100644 index 00000000..3b61328c --- /dev/null +++ b/pkg/system/lprint.x @@ -0,0 +1,213 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <syserr.h> +include <error.h> +include <finfo.h> +include <time.h> +include <ttyset.h> + +define WIDE_PAGE 100 +define SZ_DDSTR 256 + + +# LPRINT -- Print a file or files on the lineprinter. A one line header is +# printed at the top of each page, unless we are reading from the standard +# input. If printing multiple files, each file begins on a new page. +# TTYPUTLINE is used to output lines to the printer file, so that formfeeds, +# standout mode, etc., may be properly translated for the indicated device. + +procedure t_lprint() + +int out, list, map_cc +bool input_redirected, one_file +bool print_heading, auto_header +pointer sp, fname, device, label, lp, ddstr + +pointer ttyodes() +bool streq(), clgetb() +int clpopni(), clplen(), envgets(), lpopen(), clgfil(), ttygets(), btoi() +string printer "printer" +errchk clgfil, lp_print_file + +begin + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (label, SZ_FNAME, TY_CHAR) + call salloc (device, SZ_FNAME, TY_CHAR) + call salloc (ddstr, SZ_DDSTR, TY_CHAR) + + # Open list of files to be printed. + list = clpopni ("files") + one_file = (clplen (list) == 1) + + # Get device name. Default is "printer", which means that the actual + # device name is given by the environment variable "printer". + + call clgstr ("device", Memc[device], SZ_FNAME) + if (streq (Memc[device], printer)) + if (envgets (printer, Memc[device], SZ_FNAME) <= 0) { + call clpcls (list) + call syserrs (SYS_ENVNF, printer) + } + + # Map unknown control chars into printable sequences? + map_cc = btoi (clgetb ("map_cc")) + + # If automatic pagination is selected, lprint will break pages and + # print headers only if the standard input is not redirected. + # Otherwise, pagination is disabled unless paginate=yes. The file + # name buffer is used as a temporary to hold the value string. + + call clgstr ("paginate", Memc[fname], SZ_FNAME) + auto_header = streq (Memc[fname], "auto") + if (!auto_header) + print_heading = streq (Memc[fname], "yes") + + # Open TTY descriptor and printer file. We deal only with character + # data, so open printer as a text file. Output the files to the line + # printer device. + + lp = ttyodes (Memc[device]) + if (ttygets (lp, "DD", Memc[ddstr], SZ_DDSTR) <= 0) + call error (1, "missing 'DD' parameter in termcap entry") + + out = lpopen (Memc[ddstr], APPEND, TEXT_FILE) + + while (clgfil (list, Memc[fname], SZ_FNAME) != EOF) { + # If only one file and it is the standard input (i.e., reading + # from a pipe), and if header printing is not explicitly enabled + # or disabled, do not break pages and print headers. + + input_redirected = (one_file && streq (Memc[fname], "STDIN")) + if (auto_header) + print_heading = !input_redirected + + # Get page header label string. File name is used unless reading + # from the standard input. + + if (input_redirected) + call clgstr ("label", Memc[label], SZ_FNAME) + else + call strcpy (Memc[fname], Memc[label], SZ_FNAME) + + # Output file, followed by a form feed. + iferr { + call lp_print_file (out, lp, Memc[fname], Memc[label], map_cc, + print_heading) + call flush (out) + } then + call erract (EA_WARN) + } + + call close (out) + call clpcls (list) + call ttycdes (lp) + call sfree (sp) +end + + +# LP_PRINT_FILE -- Open and print the named text file on the output file, +# under control of the tty device descriptor LP. Print a header on each +# page if enabled, and formfeed at the end of the file. The number of lines +# per page is given by the tty descriptor. + +procedure lp_print_file (out, lp, fname, label, map_cc, print_heading) + +int out +pointer lp +char fname[ARB] +char label[ARB] +int map_cc +bool print_heading + +bool one_tab_in, streq() +int pageno, lineno, maxlines, totlines, status, in +long fi[LEN_FINFO], time, clktime() +pointer sp, ip, lbuf, timebuf +int open(), getline(), finfo(), ttystati() +errchk salloc, finfo, cnvtime, open, ttystati, getline, ttyputline + +begin + call smark (sp) + call salloc (lbuf, SZ_LINE+1, TY_CHAR) + call salloc (timebuf, SZ_TIME, TY_CHAR) + + # Get time and date file was last modified. + if (print_heading) { + if (streq (fname, "STDIN")) + time = clktime (long(0)) + else { + if (finfo (fname, fi) == ERR) { + call sprintf (Memc[lbuf], SZ_LINE, "%s '%s'\n") + call pargstr ("Cannot get info on file") + call pargstr (fname) + call error (1, Memc[lbuf]) + } else + time = FI_MTIME(fi) + } + call cnvtime (time, Memc[timebuf], SZ_TIME) + } + + in = open (fname, READ_ONLY, TEXT_FILE) + maxlines = ttystati (lp, TTY_NLINES) + + # If printer page is very wide, set page in one tabstop from left + # margin. + + one_tab_in = (ttystati (lp, TTY_NCOLS) > WIDE_PAGE) + if (one_tab_in) { + Memc[lbuf] = '\t' + ip = lbuf + 1 + } else + ip = lbuf + + # If printing header and breaking pages, allow for the 3 line header + # and a three line border at the bottom of the page. + + if (print_heading) + maxlines = maxlines - 6 + + totlines = 0 + status = OK + + # Format and write each page of output. If headers are enabled, + # output formfeed and header between pages. + + for (pageno=1; status != EOF; pageno=pageno+1) { + # Print header, if enabled. We assume that we are already + # positioned to the top of a page. + + if (print_heading) { + call sprintf (Memc[ip], SZ_LINE, "%s %s Page %d\n\n\n") + call pargstr (Memc[timebuf]) + call pargstr (label) + call pargi (pageno) + call ttyputline (out, lp, Memc[lbuf], map_cc) + totlines = totlines + 3 + } + + # Output one page of text. Each output line is processed by + # ttyputline to expand tabs, underline, etc. + + for (lineno=1; lineno <= maxlines; lineno=lineno+1) { + status = getline (in, Memc[ip]) + if (status == EOF) + break + if (Memc[ip] == '\f') { + call ttyputline (out, lp, "\f", map_cc) + call strcpy (Memc[ip+1], Memc[ip], SZ_LINE) + } + call ttyputline (out, lp, Memc[lbuf], map_cc) + totlines = totlines + 1 + } + + # Output formfeed, leaving printer positioned to top of page. + # Do not break pages if headers are disabled. + + if (print_heading && totlines > 0) + call ttyputline (out, lp, "\f", map_cc) + } + + call close (in) + call sfree (sp) +end diff --git a/pkg/system/lroff.par b/pkg/system/lroff.par new file mode 100644 index 00000000..512769eb --- /dev/null +++ b/pkg/system/lroff.par @@ -0,0 +1,4 @@ +input_file,f,a,,,,file containing help text +lmargin,i,h,1,1,160,left margin +rmargin,i,h,72,1,160,right margin +format,s,h,"text","|text|html|ps|postscript|",,format for output diff --git a/pkg/system/match.par b/pkg/system/match.par new file mode 100644 index 00000000..fa2670b3 --- /dev/null +++ b/pkg/system/match.par @@ -0,0 +1,5 @@ +pattern,s,a,,,,text pattern to be matched +files,s,a,,,,files to be searched for the pattern +stop,b,h,no,,,"stop, rather than pass, matched lines?" +print_file_names,b,h,yes,,,print file names if multiple files? +metacharacters,b,h,yes,,,recognize pattern matching metacharacters? diff --git a/pkg/system/match.x b/pkg/system/match.x new file mode 100644 index 00000000..b9f8feb2 --- /dev/null +++ b/pkg/system/match.x @@ -0,0 +1,96 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <pattern.h> +include <ctype.h> + +# MATCH -- Search for the indicated pattern in each line of a file or files, +# passing or stopping only those lines which contain the pattern. + +procedure t_match() + +bool stop_matched_lines # pass or stop matched lines? +char chset[2] +int fd, list +pointer sp, ip, line, fname, patbuf, pattern +bool line_matches, encode_pattern, print_file_names, match_pattern +bool clgetb() +int strmatch(), strsearch(), patmatch(), patmake(), stridxs() +int open(), getline(), clpopni(), clplen(), clgfil() + +begin + call smark (sp) + call salloc (line, SZ_LINE, TY_CHAR) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (patbuf, SZ_LINE, TY_CHAR) + call salloc (pattern, SZ_FNAME, TY_CHAR) + + # Get pattern. If it contains either * or [, general pattern + # matching with an encoded pattern must be used. If no metacharacters + # at all are used, or if metacharacters are disabled, use STRSEARCH + # for maximum efficiency. + + call clgstr ("pattern", Memc[pattern], SZ_FNAME) + if (clgetb ("metacharacters")) { + + # Check for the tough pattern matching metachars. + chset[1] = CH_CLOSURE + chset[2] = CH_CCL + chset[3] = EOS + encode_pattern = (stridxs (chset, Memc[pattern]) > 0) + + # If don't have to use patmatch, see if we have a simple alphanum + # string so that we can use strsearch. + + if (!encode_pattern) { + for (ip=pattern; IS_ALNUM(Memc[ip]); ip=ip+1) + ; + match_pattern = (Memc[ip] != EOS) + } + + } else { + encode_pattern = false + match_pattern = false + } + + stop_matched_lines = clgetb ("stop") + list = clpopni ("files") + print_file_names = (clplen(list) > 1) && (clgetb("print_file_names")) + + if (encode_pattern) + if (patmake (Memc[pattern], Memc[patbuf], SZ_LINE) == ERR) + call error (1, "Pattern is too complex") + + # Search each file in the list, passing a line on to the output + # only if the line matches and stop is false, or if the line does + # not match and stop is true. + + while (clgfil (list, Memc[fname], SZ_FNAME) != EOF) { + fd = open (Memc[fname], READ_ONLY, TEXT_FILE) + + while (getline (fd, Memc[line]) != EOF) { + if (encode_pattern) + line_matches = (patmatch (Memc[line], Memc[patbuf]) > 0) + else if (match_pattern) + line_matches = (strmatch (Memc[line], Memc[pattern]) > 0) + else + line_matches = (strsearch (Memc[line], Memc[pattern]) > 0) + + if ((line_matches && !stop_matched_lines) || + (!line_matches && stop_matched_lines)) { + + if (print_file_names) { + call printf ("%s:") + call pargstr (Memc[fname]) + } + + call putline (STDOUT, Memc[line]) + call flush (STDOUT) + } + } + + call close (fd) + } + + call sfree (sp) + call clpcls (list) +end diff --git a/pkg/system/mkdir.par b/pkg/system/mkdir.par new file mode 100644 index 00000000..b2cbe135 --- /dev/null +++ b/pkg/system/mkdir.par @@ -0,0 +1 @@ +newdir,s,a,,,,name of the new directory diff --git a/pkg/system/mkdir.x b/pkg/system/mkdir.x new file mode 100644 index 00000000..a1711d51 --- /dev/null +++ b/pkg/system/mkdir.x @@ -0,0 +1,12 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# MKDIR -- Make a directory. (May be an IRAF VFN or an OS directory spec) + +procedure t_mkdir () + +char newdir[SZ_FNAME] + +begin + call clgstr ("newdir", newdir, SZ_FNAME) + call fmkdir (newdir) +end diff --git a/pkg/system/mkhelpdb.par b/pkg/system/mkhelpdb.par new file mode 100644 index 00000000..0c1139f5 --- /dev/null +++ b/pkg/system/mkhelpdb.par @@ -0,0 +1,3 @@ +helpdir,s,a,"lib$root.hd",,,"root help directory to be compiled" +helpdb,s,a,"lib$helpdb.mip",,,"name of help database to be created" +verbose,b,h,no,,,"detail the structure of the package hierarchy" diff --git a/pkg/system/mkpkg b/pkg/system/mkpkg new file mode 100644 index 00000000..1392b3c6 --- /dev/null +++ b/pkg/system/mkpkg @@ -0,0 +1,53 @@ +# Make the SYSTEM system utilities package (including HELP) + +$call relink +$exit + +update: + $call relink + $call install + ; + +relink: + $update libpkg.a + $omake x_system.x + $link x_system.o libpkg.a -o xx_system.e + ; + +install: + $move xx_system.e bin$x_system.e + ; + +libpkg.a: + @help + + cmdstr.x <ctype.h> + chkupdate.x <fio.h> <fset.h> <finfo.h> <syserr.h> + concatenate.x + copy.x <error.h> + count.x <chars.h> <ctype.h> <error.h> + delete.x <error.h> + directory.x <chars.h> <ctype.h> <diropen.h> <finfo.h>\ + <fset.h> <protect.h> <time.h> + files.x + head.x <error.h> + lprint.x <error.h> <finfo.h> <time.h> <ttyset.h> + match.x <ctype.h> <pattern.h> + mkdir.x + movefiles.x <error.h> + mtclean.x + netstatus.x + page.x <fset.h> + pathnames.x + protect.x <error.h> <protect.h> + rename.x <error.h> + rewind.x + sort.x sort.com <ctype.h> + tail.x <error.h> + tee.x <fset.h> + touch.x <error.h> <finfo.h> <time.h> + type.x <error.h> + unprotect.x <error.h> <protect.h> + t_fcache.x <error.h> + t_urlget.x <error.h> <imhdr.h> <imset.h> <mach.h> + ; diff --git a/pkg/system/mkscript.cl b/pkg/system/mkscript.cl new file mode 100644 index 00000000..984cdf27 --- /dev/null +++ b/pkg/system/mkscript.cl @@ -0,0 +1,79 @@ +#{ MKBATCH -- Make a batch script. + +{ + # Make a copy of the script file query parameter and delete the + # file if it exists and not appending. + + scrpt = script + if (access (scrpt) && !append) + delete (scrpt, verify=verify) + + # Outer loop provides return when the user wants to start over. + + while (YES) { + + # Add commands until the user is done. + + while (YES) { + + # Determine the task name and check that it is loaded. + + ltask = task + if (!deftask (ltask)) { + print ("Task ", ltask, " not loaded.") + next + } + + # Edit the task parameters. + + eparam (ltask) + print ("") + + # If the user is verifying then display the command. + + if (verify) { + lparam (ltask) | cmdstr (ltask, hidden=hidden) + cok = YES + if (cok) { + lparam (ltask) | cmdstr (ltask, hidden=hidden, >> scrpt) + print ("", >> scrpt) + } + } else { + lparam (ltask) | cmdstr (ltask, hidden=hidden, >> scrpt) + print ("", >> scrpt) + } + + # Ask if more commands are to be added to the script. + + more = YES + if (!more) + break + } + + # If verifying page the script and let the user decide to start + # over. + + if (verify) { + page (scrpt) + sok = YES + if (sok) + break + else + delete (scrpt, verify=verify) + } else + break + } + + # If the user does not want to submit the script then quit. + + if (!submit) + bye +} + +# Submit the script as a background process. + +print ("Script ", scrpt, " submitted at:") +time +print ("\nScript ", scrpt, " submitted at:", >> logfile) +time (>> logfile) +cl (< scrpt, >>& logfile) & diff --git a/pkg/system/mkscript.par b/pkg/system/mkscript.par new file mode 100644 index 00000000..46afb1b6 --- /dev/null +++ b/pkg/system/mkscript.par @@ -0,0 +1,17 @@ +script,s,a,script.cl,,,Script file name +task,s,a,,,,Task name of command to be added to script +submit,b,a,yes,,,Submit the script as a background job? + +append,b,h,no,,,Append new to existing script? +hidden,b,h,yes,,,Include hidden parameters in command? +verify,b,h,yes,,,Verify each command? +logfile,f,h,script.log,,,Script log file name + +# Script query parameters and variables. + +cok,b,a,yes,,,Is the command ok? +sok,b,a,yes,,,Is the script ok? +more,b,a,yes,,,Add another command? + +scrpt,s,h +ltask,s,h diff --git a/pkg/system/movefiles.par b/pkg/system/movefiles.par new file mode 100644 index 00000000..1aa0cc27 --- /dev/null +++ b/pkg/system/movefiles.par @@ -0,0 +1,3 @@ +files,s,a,,,,list of files to be moved +newdir,f,a,,,,name of destination directory +verbose,b,h,no,,,print names of files as they are moved diff --git a/pkg/system/movefiles.x b/pkg/system/movefiles.x new file mode 100644 index 00000000..32842f61 --- /dev/null +++ b/pkg/system/movefiles.x @@ -0,0 +1,52 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> + +# MOVEFILES -- Move a set of files to another directory. If the destination +# is not a directory it is a fatal error. Ambiguous directory specifications +# are resolved in favor of subdirectories, rather than logical directories. + +procedure t_movefiles() + +bool verbose +int list, root_len +pointer sp, fname, newdir, pathname, newname, junkstr +bool clgetb() +int clpopni(), clgfil(), fnldir(), isdirectory() + +begin + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (newdir, SZ_FNAME, TY_CHAR) + call salloc (pathname, SZ_PATHNAME, TY_CHAR) + call salloc (newname, SZ_PATHNAME, TY_CHAR) + call salloc (junkstr, SZ_FNAME, TY_CHAR) + + list = clpopni ("files") + call clgstr ("newdir", Memc[newdir], SZ_FNAME) + verbose = clgetb ("verbose") + + if (isdirectory (Memc[newdir], Memc[pathname], SZ_PATHNAME) == 0) { + call strcat ("$", Memc[newdir], SZ_FNAME) + if (isdirectory (Memc[newdir], Memc[pathname], SZ_PATHNAME) == 0) + call error (1, "destination is not a directory") + } + + while (clgfil (list, Memc[fname], SZ_FNAME) != EOF) { + call strcpy (Memc[pathname], Memc[newname], SZ_PATHNAME) + root_len = fnldir (Memc[fname], Memc[junkstr], SZ_FNAME) + call strcat (Memc[fname+root_len], Memc[newname], SZ_PATHNAME) + + if (verbose) { + call eprintf ("%s -> %s\n") + call pargstr (Memc[fname]) + call pargstr (Memc[newname]) + } + + iferr (call rename (Memc[fname], Memc[newname])) + call erract (EA_WARN) + } + + call clpcls (list) + call sfree (sp) +end diff --git a/pkg/system/mtclean.par b/pkg/system/mtclean.par new file mode 100644 index 00000000..d30e2b82 --- /dev/null +++ b/pkg/system/mtclean.par @@ -0,0 +1,3 @@ +all,b,h,no,,,delete all lok files unconditionally +stale,i,h,3600,,,threshold (seconds) after which old lok files are deleted +verbose,b,h,no,,,print names of lok files as they are deleted diff --git a/pkg/system/mtclean.x b/pkg/system/mtclean.x new file mode 100644 index 00000000..d79359c5 --- /dev/null +++ b/pkg/system/mtclean.x @@ -0,0 +1,25 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# MTCLEAN -- Clean the magtape .lok file area, i.e., delete any old .lok files. +# These files no longer serve any device locking purpose, rather, they are +# used by the magtape system to store knowledge of the tape position when +# the drive is not being accessed. The mtclean task is called during CL +# startup to delete any old .lok files to keep these from being erroneously +# used to indicate the tape position. In normal use the .lok files are +# created when a tape is allocated and deleted when the tape is deallocated, +# but the files can be left behind if the CL is killed without doing a +# deallocate. + +procedure t_mtclean() + +int out +bool clgetb() +int clgeti(), btoi() + +begin + out = NULL + if (clgetb ("verbose")) + out = STDOUT + + call mtclean (btoi(clgetb("all")), clgeti("stale"), out) +end diff --git a/pkg/system/netstatus.x b/pkg/system/netstatus.x new file mode 100644 index 00000000..b7ecb225 --- /dev/null +++ b/pkg/system/netstatus.x @@ -0,0 +1,9 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# NETSTATUS -- Print the network status. + +procedure t_netstatus() + +begin + call ki_shownet (STDOUT) +end diff --git a/pkg/system/news.cl b/pkg/system/news.cl new file mode 100644 index 00000000..ee3e88ec --- /dev/null +++ b/pkg/system/news.cl @@ -0,0 +1,5 @@ +#{ NEWS -- Page the system news file. + +{ + page "doc$newsfile" +} diff --git a/pkg/system/page.par b/pkg/system/page.par new file mode 100644 index 00000000..2419bf06 --- /dev/null +++ b/pkg/system/page.par @@ -0,0 +1,6 @@ +files,s,a,,,,Files to be paged +map_cc,b,h,yes,,,Map control characters into printable sequences? +clear_screen,b,h,yes,,,Clear screen between pages? +first_page,i,h,1,1,,First page of file to be displayed +prompt,s,h,"",,,Prompt string if not filename +device,s,h,"terminal",,,Output device diff --git a/pkg/system/page.x b/pkg/system/page.x new file mode 100644 index 00000000..208bb56b --- /dev/null +++ b/pkg/system/page.x @@ -0,0 +1,41 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <fset.h> + +# PAGE -- Display a text file or files on the standard output (the user +# terminal) one screen at a time, pausing after each screen has been filled. +# The program is keystroke driven in raw mode, and currently recognizes the +# keystrokes defined above. + +procedure t_page() + +bool redirin +pointer sp, device, prompt, files +int map_cc, clear_screen, first_page + +bool clgetb() +int fstati(), clgeti(), btoi() + +begin + call smark (sp) + call salloc (device, SZ_FNAME, TY_CHAR) + call salloc (prompt, SZ_FNAME, TY_CHAR) + call salloc (files, SZ_LINE, TY_CHAR) + + redirin = (fstati (STDIN, F_REDIR) == YES) + if (redirin) + call strcpy ("STDIN", Memc[files], SZ_LINE) + else + call clgstr ("files", Memc[files], SZ_LINE) + + map_cc = btoi (clgetb ("map_cc")) + clear_screen = btoi (clgetb ("clear_screen")) + first_page = clgeti ("first_page") + call clgstr ("prompt", Memc[prompt], SZ_FNAME) + call clgstr ("device", Memc[device], SZ_FNAME) + + call xpagefiles (Memc[files], Memc[device], Memc[prompt], + first_page, clear_screen, map_cc) + + call sfree (sp) +end diff --git a/pkg/system/pathnames.par b/pkg/system/pathnames.par new file mode 100644 index 00000000..20e6a230 --- /dev/null +++ b/pkg/system/pathnames.par @@ -0,0 +1,2 @@ +template,s,a,,,,file template +sort,b,h,yes,,,sort file list diff --git a/pkg/system/pathnames.x b/pkg/system/pathnames.x new file mode 100644 index 00000000..86ee74f4 --- /dev/null +++ b/pkg/system/pathnames.x @@ -0,0 +1,55 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# PATHNAMES -- Convert one or more filenames into OS pathnames. If the input +# is redirected, filenames are read from the standard input. Otherwise, +# a file name template is expanded and used as the list of filenames to be +# transformed. If called without any arguments, return the pathname of the +# current working directory. + +procedure t_pathnames() + +int list +pointer sp, fname, osfname +bool streq(), clgetb() +int clgeti(), clpopni(), clpopnu(), clgfil(), fscan() + +begin + call smark (sp) + call salloc (fname, SZ_LINE, TY_CHAR) + call salloc (osfname, SZ_LINE, TY_CHAR) + + # If no arguments, return the pathame of the current + # directory: do not prompt for the template. + + if (clgeti ("$nargs") == 0) { + call fpathname ("", Memc[osfname], SZ_LINE) + call printf ("%s\n") + call pargstr (Memc[osfname]) + call sfree (sp) + return + } + + # Expand template, output pathname of each file therein. + if (clgetb ("sort")) + list = clpopni ("template") + else + list = clpopnu ("template") + + while (clgfil (list, Memc[fname], SZ_FNAME) != EOF) { + if (streq (Memc[fname], "STDIN")) { + while (fscan (STDIN) != EOF) { + call gargstr (Memc[fname], SZ_LINE) + call fpathname (Memc[fname], Memc[osfname], SZ_LINE) + call printf ("%s\n") + call pargstr (Memc[osfname]) + } + } else { + call fpathname (Memc[fname], Memc[osfname], SZ_LINE) + call printf ("%s\n") + call pargstr (Memc[osfname]) + } + } + + call clpcls (list) + call sfree (sp) +end diff --git a/pkg/system/phelp.cl b/pkg/system/phelp.cl new file mode 100644 index 00000000..4de3eab2 --- /dev/null +++ b/pkg/system/phelp.cl @@ -0,0 +1,41 @@ +# PHELP -- Paged help. + +procedure phelp (template) + +string template {prompt="module name template"} + +bool file_template=no {prompt="print help file"} +bool all=yes {prompt="find all modules matching template"} +string parameter="all" {prompt="parameter for which help is desired"} +string section="all" {prompt="section for which help is desired"} +string option="help" {prompt="type of help desired"} +int lmargin=1 {min=1, prompt="left margin"} +int rmargin=72 {min=2, prompt="right margin"} +string helpdb="helpdb" {prompt="help database to be used"} + +begin + file helptext + string s_template + + # Get a temp file to hold help text. + helptext = mktemp ("tmp$htx") + s_template = template + + # Run HELP, redirecting the output to the temp file. + help (s_template, > helptext, page=no, + all = all, + file_template = file_template, + parameter = parameter, + section = section, + option = option, + lmargin = lmargin, + rmargin = rmargin, + device = "terminal", + helpdb = helpdb) + + # Page saved text output. + page (helptext, prompt = s_template) + + # Delete temp file. + delete (helptext, verify-) +end diff --git a/pkg/system/protect.par b/pkg/system/protect.par new file mode 100644 index 00000000..cb9721ac --- /dev/null +++ b/pkg/system/protect.par @@ -0,0 +1 @@ +files,s,a,,,,list of files to be protected diff --git a/pkg/system/protect.x b/pkg/system/protect.x new file mode 100644 index 00000000..4ed12db9 --- /dev/null +++ b/pkg/system/protect.x @@ -0,0 +1,23 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <protect.h> +include <error.h> + +# PROTECT -- Protect a list of files. + +procedure t_protect() + +char fname[SZ_FNAME] +int list, status + +int clpopns(), clgfil(), protect() + +begin + list = clpopns ("files") + + while (clgfil (list, fname, SZ_FNAME) != EOF) + iferr (status = protect (fname, SET_PROTECTION)) + call erract (EA_WARN) + + call clpcls (list) +end diff --git a/pkg/system/references.cl b/pkg/system/references.cl new file mode 100644 index 00000000..ca93e6a6 --- /dev/null +++ b/pkg/system/references.cl @@ -0,0 +1,50 @@ +# REFERENCES -- Search the help database for help on a given subject. +# By default a runtime search is performed of all the package menus in the +# help database, but the user may prepare a "quick-reference" file to speed +# further searches if desired. This cannot easily be done automatically +# since any set of packages may form the help database. +# +# NOTE -- Uses LISTS. + +procedure references (topic) + +string topic { prompt = "topic to find help for" } +file quickref = "uparm$quick.ref" { prompt = "quick-reference file" } +bool updquick = no { prompt = "update quick-reference file" } +bool usequick = no { prompt = "use quick-reference file" } + +begin + string pattern + file fname + + # Make a quick-search file if so requested. + if (updquick) { + fname = quickref + print ("generating new quick-reference file " // fname // "...") + if (access (fname)) + delete (fname, verify-) + help ("[a-z]*.", option="ref", curpack="AsckCL", device="terminal", + helpdb="helpdb") |& match ("-", metacharacters=yes) | + sort(ignore+) | unique ( > fname) + references.quickref = fname + references.usequick = yes + + } else { + # Ignore case. + pattern = ("{" // topic // "}") + + # If the user has prepared a quick-search file (e.g., by running + # this task with topic=* and saving the output to make the quick + # file), search that if it exists, otherwise perform a runtime + # search of the package menu files for the entire help database. + + if (usequick && access (quickref)) + match (pattern, quickref, metacharacters=yes) + else { + print ("searching the help database...") + help ("[a-z]*.", section="all", option="ref", curpack="AsckCL", + device="terminal", helpdb="helpdb") |& sort(ignore+) | + unique | match (pattern, metacharacters=yes) + } + } +end diff --git a/pkg/system/rename.par b/pkg/system/rename.par new file mode 100644 index 00000000..b7e19293 --- /dev/null +++ b/pkg/system/rename.par @@ -0,0 +1,3 @@ +files,s,a,,,,list of files to be renamed +newname,s,a,,,,new file name or field name +field,s,h,all,"|all|ldir|root|extn|",,field to be modified (all|ldir|root|extn) diff --git a/pkg/system/rename.x b/pkg/system/rename.x new file mode 100644 index 00000000..95cf395c --- /dev/null +++ b/pkg/system/rename.x @@ -0,0 +1,176 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> + +define F_ALL 0 +define F_LDIR 1 +define F_ROOT 2 +define F_EXTN 3 + + +# RENAME -- Rename a file, or rename a list of files. In the latter case +# the ldir, root, or extn field in each of the input files is changed to +# the value of the "output file", which in this case is the value of the +# specified field of an output file name. Thus, +# +# cl> rename task.* newtask +# +# would rename task.x as newtask.x, task.cl as newtask.cl, and so on. +# If 'newtask' is a logical or host directory the input files are moved to +# this directory with the same name. + +procedure t_rename() + +bool isdir +pointer sp, oldfile, newname, field +pointer o_ldir, o_root, o_extn, n_ldir, n_root, n_extn +pointer pathname, newfile, junkstr +int list, len, modfield + +bool streq() +int clpopni(), clgfil(), clplen(), stridxs() +int access(), fnldir(), fnroot(), fnextn(), isdirectory() +string s_clobber "Warning: %s would overwrite existing file %s - skipping\n" + +begin + call smark (sp) + call salloc (oldfile, SZ_FNAME, TY_CHAR) + call salloc (newname, SZ_PATHNAME, TY_CHAR) + call salloc (pathname, SZ_PATHNAME, TY_CHAR) + call salloc (newfile, SZ_PATHNAME, TY_CHAR) + call salloc (junkstr, SZ_FNAME, TY_CHAR) + call salloc (field, SZ_FNAME, TY_CHAR) + call salloc (o_ldir, SZ_FNAME, TY_CHAR) + call salloc (n_ldir, SZ_FNAME, TY_CHAR) + call salloc (o_root, SZ_FNAME, TY_CHAR) + call salloc (n_root, SZ_FNAME, TY_CHAR) + call salloc (o_extn, SZ_FNAME, TY_CHAR) + call salloc (n_extn, SZ_FNAME, TY_CHAR) + + # Open the list of files to be renamed. This is done first so that + # the old file name is queried for before the new file name. + + list = clpopni ("files") + + # Get the output file name, or the new name for the field to be + # changed. + + call clgstr ("newname", Memc[newname], SZ_PATHNAME) + call clgstr ("field", Memc[field], SZ_FNAME) + + if (streq (Memc[field], "ldir")) + modfield = F_LDIR + else if (streq (Memc[field], "root")) + modfield = F_ROOT + else if (streq (Memc[field], "extn")) + modfield = F_EXTN + else if (streq (Memc[field], "all")) + modfield = F_ALL + else { + call clpcls (list) + call error (1, "rename: unrecognized filename field code") + } + + # See if we're modifying the logical directory, If so, move the input + # files to this directory, otherwise do the renaming as we've always + # done. + + Memc[pathname] = EOS + isdir = (isdirectory (Memc[newname], Memc[pathname], SZ_PATHNAME) > 0) + + if (isdir || modfield == F_LDIR) { + # Move each of the files in the list to the destination dir. + call fdirname (Memc[newname], Memc[n_ldir], SZ_FNAME) + + while (clgfil (list, Memc[oldfile], SZ_FNAME) != EOF) { + if (Memc[pathname] != EOS) + call strcpy (Memc[pathname], Memc[newfile], SZ_PATHNAME) + else + call strcpy (Memc[n_ldir], Memc[newfile], SZ_PATHNAME) + len = fnldir (Memc[oldfile], Memc[junkstr], SZ_FNAME) + call strcat (Memc[oldfile+len], Memc[newfile], SZ_PATHNAME) + + iferr (call rename (Memc[oldfile], Memc[newfile])) + call erract (EA_WARN) + } + + } else if (modfield == F_ALL) { + # "newname" is the new filename. This makes sense only if there + # is a single input filename. Note that the new name may contain + # a new logical directory, renaming both the file and moving it # to a new directory. + + if (clplen (list) > 1) + call error (2, "rename: `newname' must be a directory") + + # Rename the file. + if (clgfil (list, Memc[oldfile], SZ_FNAME) != EOF) + iferr (call rename (Memc[oldfile], Memc[newname])) + call erract (EA_WARN) + + } else { + # We're either modifying the root or the extension. Break out + # the ldir, root and extn for the input and output file names + # then construct the new name from these components. + + Memc[n_root] = EOS + Memc[n_extn] = EOS + + if (modfield == F_ROOT) { + call strcpy (Memc[newname], Memc[n_root], SZ_FNAME) + if (stridxs ("$/", Memc[n_root]) > 0) { + call clpcls (list) + call error (3, "rename: bad replacement root field") + } + } + if (modfield == F_EXTN) { + call strcpy (Memc[newname], Memc[n_extn], SZ_FNAME) + if (stridxs ("$/", Memc[n_extn]) > 0) { + call clpcls (list) + call error (4, "rename: bad replacement extn field") + } + } + + # Process the files. + while (clgfil (list, Memc[oldfile], SZ_FNAME) != EOF) { + + # Get the ldir, root and extension names of the old filename. + len = fnroot (Memc[oldfile], Memc[o_root], SZ_FNAME) + len = fnextn (Memc[oldfile], Memc[o_extn], SZ_FNAME) + len = fnldir (Memc[oldfile], Memc[o_ldir], SZ_PATHNAME) + + # Start by copying the ldir to the new name. + call aclrc (Memc[newname], SZ_PATHNAME) + call strcpy (Memc[o_ldir], Memc[newname], SZ_PATHNAME) + + # Build up the new file name. + if (modfield == F_ROOT) { + call strcat (Memc[n_root], Memc[newname], SZ_FNAME) + if (Memc[o_extn] != EOS) { + call strcat (".", Memc[newname], SZ_PATHNAME) + call strcat (Memc[o_extn], Memc[newname], SZ_FNAME) + } + } else if (modfield == F_EXTN) { + call strcat (Memc[o_root], Memc[newname], SZ_FNAME) + call strcat (".", Memc[newname], SZ_PATHNAME) + call strcat (Memc[n_extn], Memc[newname], SZ_FNAME) + } + + # Check to see if we're going to clobber a file. + if (clplen (list) > 1) { + if (access (Memc[newname], 0, 0) == YES) { + call eprintf (s_clobber) + call pargstr (Memc[oldfile]) + call pargstr (Memc[newname]) + next + } + } + + # Rename the file. + iferr (call rename (Memc[oldfile], Memc[newname])) + call erract (EA_WARN) + } + } + + call clpcls (list) + call sfree (sp) +end diff --git a/pkg/system/rewind.par b/pkg/system/rewind.par new file mode 100644 index 00000000..714a56bf --- /dev/null +++ b/pkg/system/rewind.par @@ -0,0 +1,2 @@ +device,f,a,mta,,,device to be rewound +initcache,b,h,yes,,,discard cached information on tape contents diff --git a/pkg/system/rewind.x b/pkg/system/rewind.x new file mode 100644 index 00000000..9316b212 --- /dev/null +++ b/pkg/system/rewind.x @@ -0,0 +1,14 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# REWIND -- Rewind a (previously allocated) magtape device. + +procedure t_rewind() + +char device[SZ_FNAME] +bool clgetb() +int btoi() + +begin + call clgstr ("device", device, SZ_FNAME) + call mtrewind (device, btoi(clgetb("initcache"))) +end diff --git a/pkg/system/sort.com b/pkg/system/sort.com new file mode 100644 index 00000000..4b66ac5f --- /dev/null +++ b/pkg/system/sort.com @@ -0,0 +1,10 @@ +# Common for the SORT program. + +int column # column to be sorted (if nonzero) +int ignore_whitespace # ignore leading whitespace +int numeric_sort # sort numerically rather than alphabetically +int reverse_sort # reverse the sense of the sort +int use_strsrt # ok to use standard STRSRT routine? + +common /srtcom/ column, ignore_whitespace, numeric_sort, reverse_sort, + use_strsrt diff --git a/pkg/system/sort.par b/pkg/system/sort.par new file mode 100644 index 00000000..84d721a3 --- /dev/null +++ b/pkg/system/sort.par @@ -0,0 +1,5 @@ +input_file,s,a,,,,file to be sorted +column,i,h,0,,,column to be sorted (if nonzero) +ignore_whitespace,b,h,no,,,ignore leading whitespace +numeric_sort,b,h,no,,,sort numerically rather than alphabetically +reverse_sort,b,h,no,,,reverse the sense of the sort diff --git a/pkg/system/sort.x b/pkg/system/sort.x new file mode 100644 index 00000000..e53b5fd8 --- /dev/null +++ b/pkg/system/sort.x @@ -0,0 +1,434 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <ctype.h> + +# SORT -- Sort a text file, alphabetically or numerically, in forward or +# reverse order, by line or by the contents of any column. Derived from +# Chap. 4 of Software Tools. This is old code, not very pretty. + +define MERGEORDER 8 +define MAXPTR 20000 +define SZ_LINBUF 200000 +define LOGPTR 32 +define swap {temp=$1;$1=$2;$2=temp} + + +# SORT -- The main CL callable routine. + +procedure t_sort() + +pointer linbuf, linptr +int infil[MERGEORDER], nlines +char name[SZ_FNAME], source_file[SZ_FNAME] +int high, lim, low, fd, outfil, t, list, junk + +bool clgetb() +int ss_gtext(), ss_mkfile() +int open(), clpopni(), clplen(), clgfil(), clgeti(), btoi() +include "sort.com" + +begin + list = clpopni ("input_file") + if (clplen (list) > 1) { + call clpcls (list) + call error (1, "Cannot yet sort more than one file at a time") + } + + # Determine type of sort to be applied. + column = clgeti ("column") + numeric_sort = btoi (clgetb ("numeric_sort")) + reverse_sort = btoi (clgetb ("reverse_sort")) + + ignore_whitespace = NO + if (column == 0 && numeric_sort == NO) + if (clgetb ("ignore_whitespace")) + ignore_whitespace = YES + + # The standard STRSRT is fastest if we can use it. + use_strsrt = NO + if (ignore_whitespace == NO && numeric_sort == NO && + reverse_sort == NO && column == 0) + use_strsrt = YES + + # Allocate buffer space. + call malloc (linbuf, SZ_LINBUF, TY_CHAR) + call malloc (linptr, MAXPTR, TY_INT) + + # Perform the sort. + junk = clgfil (list, source_file, SZ_FNAME) + fd = open (source_file, READ_ONLY, TEXT_FILE) + + # Initial formation of runs. + high = 0 + repeat { + t = ss_gtext (fd, Memi[linptr], nlines, Memc[linbuf]) + if (use_strsrt == YES) + call strsrt (Memi[linptr], Memc[linbuf], nlines) + else + call ss_quick (Memi[linptr], Memc[linbuf], nlines) + + high = high + 1 + outfil = ss_mkfile (high) + call ss_ptext (outfil, Memi[linptr], nlines, Memc[linbuf]) + call close (outfil) + + } until (t == EOF) + + # Merge sorted chunks. + for (low = 1; low < high; low = low + MERGEORDER) { + lim = min (low + MERGEORDER - 1, high) + call ss_gopen (infil, low, lim) + high = high + 1 + outfil = ss_mkfile (high) + call ss_merge (infil, outfil, lim - low + 1) + call close (outfil) + call ss_gremov (infil, low, lim) + } + + call mfree (linbuf, TY_CHAR) + call mfree (linptr, TY_INT) + + call ss_gname (high, name) # final cleanup + outfil = open (name, READ_ONLY, TEXT_FILE) + call fcopyo (outfil, STDOUT) + call close (outfil) + + call delete (name) + call close (fd) +end + + +# SS_MKFILE -- Open a temporary file. + +int procedure ss_mkfile (n) + +int n +char name[SZ_FNAME] +int open() +errchk open, ss_gname + +begin + call ss_gname (n, name) + return (open (name, NEW_FILE, TEXT_FILE)) +end + + +# SS_GNAME -- Quickie routine to generate a temporary file name in tmp$ (the +# original tools version would put the temp files in the cwd). Make a name +# of the form "tmp$srtPID_XX", where XX is the file number argument N, +# and PID is the process pid. The tools sort code requires that the file +# name be easily reproduced given only N, so we cannot use mktemp. + +procedure ss_gname (n, name) + +int n +char name[ARB] +int pid + +begin + call zgtpid (pid) + call sprintf (name, SZ_FNAME, "tmp$srt%d_%d") + call pargi (pid) + call pargi (n) +end + + +# SS_GOPEN -- Open a range of files. + +procedure ss_gopen (infil, low, lim) + +int infil[ARB], lim, low +char name[SZ_FNAME] +int i, open() +errchk open, ss_gname + +begin + for (i=1; i <= lim-low+1; i=i+1) { + call ss_gname (low+i-1, name) + infil[i] = open (name, READ_ONLY, TEXT_FILE) + } +end + + +# SS_GREMOV -- Remove a range of files. + +procedure ss_gremov (infil, low, lim) + +int infil[ARB], low, lim + +int i +char name[SZ_FNAME] +errchk ss_gname, delete, close + +begin + for (i=1; i <= lim-low+1; i=i+1) { + call close (infil[i]) + call ss_gname (low+i-1, name) + call delete (name) + } +end + + +# SS_MERGE -- Merge file onto outfil. + +procedure ss_merge (infil, outfil, nfiles) + +int infil[ARB] # input file numbers +int outfil # output file number +int nfiles # number of files to be merged + +pointer sp, linbuf +int linptr[MERGEORDER] +int i, inf, lbp, lp1, nf +int getline() +errchk getline, putline, ss_quick +include "sort.com" + +begin + call smark (sp) + call salloc (linbuf, MERGEORDER * SZ_LINE, TY_CHAR) + + lbp = 1 + nf = 0 + + # Get one line from each file. + for (i=1; i <= nfiles; i=i+1) { + if (getline (infil[i], Memc[linbuf+lbp-1]) != EOF) { + nf = nf + 1 + linptr[nf] = lbp + lbp = lbp + SZ_LINE + } + } + + # Make initial heap. + if (use_strsrt == YES) + call strsrt (linptr, Memc[linbuf], nf) + else + call ss_quick (linptr, Memc[linbuf], nf) + + while (nf > 0) { + lp1 = linptr[1] + call putline (outfil, Memc[linbuf+lp1-1]) + inf = lp1 / SZ_LINE + 1 # compute file index + if (getline (infil[inf], Memc[linbuf+lp1-1]) == EOF) { + linptr[1] = linptr[nf] + nf = nf - 1 + } + call ss_reheap (linptr, Memc[linbuf], nf) + } + + call sfree (sp) +end + + +# SS_REHEAP -- propagate linbuf[linptr[1]] to proper place in heap. + +procedure ss_reheap (linptr, linbuf, nf) + +int linptr[ARB] +char linbuf[ARB] +int nf + +int i, j, temp +int ss_compare() + +begin + for (i=1; 2 * i <= nf; i=j) { + j = 2 * i + if (j < nf) # find smaller child + if (ss_compare (linptr[j], linptr[j+1], linbuf) > 0) + j = j + 1 + if (ss_compare (linptr[i], linptr[j], linbuf) <= 0) + break # proper position found + + swap (linptr[i], linptr[j]) + } +end + + +# SS_QUICK -- Quicksort for text data. NOTE -- This algorithm is quadratic in +# the worst case, i.e., when the data is already sorted. A random method of +# selecting the pivot should be used to improve the behaviour on sorted arrays. + +procedure ss_quick (linptr, linbuf, nlines) + +int linptr[ARB] # indices of strings in buffer +char linbuf[ARB] # string buffer +int nlines # number of strings + +int i, j, k, temp, lv[LOGPTR], p, pivlin, uv[LOGPTR] +int ss_compare() + +begin + lv[1] = 1 + uv[1] = nlines + p = 1 + + while (p > 0) { + if (lv[p] >= uv[p]) # only one elem in this subset + p = p - 1 # pop stack + else { + # Dummy loop to trigger optimizer. + do p = p, ARB { + i = lv[p] - 1 + j = uv[p] + + # Select pivot element at midpoint of interval to avoid + # quadratic behavior on a sorted list. + + k = (lv[p] + uv[p]) / 2 + swap (linptr[j], linptr[k]) + pivlin = linptr[j] + + while (i < j) { + for (i=i+1; ss_compare (linptr[i], pivlin, linbuf) < 0; + i=i+1) + ; + for (j=j-1; j > i; j=j-1) + if (ss_compare (linptr[j], pivlin, linbuf) <= 0) + break + if (i < j) # out of order pair + swap (linptr[i], linptr[j]) + } + + j = uv[p] # move pivot to position i + swap (linptr[i], linptr[j]) + + if (i-lv[p] < uv[p] - i) { # stack so shorter done first + lv[p+1] = lv[p] + uv[p+1] = i - 1 + lv[p] = i + 1 + } else { + lv[p+1] = i + 1 + uv[p+1] = uv[p] + uv[p] = i - 1 + } + + break + } + + p = p + 1 # push onto stack + } + } +end + + +# SS_COMPARE -- Compare two strings. Return -1 if str1<str2, 1 if str1>str2, +# or 0 if the two strings are equal. + +int procedure ss_compare (lp1, lp2, linbuf) + +int lp1, lp2 # pointers to substrings in linbuf +char linbuf[ARB] # text buffer + +double num1, num2 +int ip1, ip2, answer, len1, len2 +int strcmp(), ss_findcolumn(), gctod() +include "sort.com" + +begin + if (column != 0) { + ip1 = ss_findcolumn (linbuf, lp1, column) + ip2 = ss_findcolumn (linbuf, lp2, column) + } else if (ignore_whitespace == YES) { + for (ip1=lp1; IS_WHITE(linbuf[ip1]); ip1=ip1+1) + ; + for (ip2=lp2; IS_WHITE(linbuf[ip2]); ip2=ip2+1) + ; + } else { + ip1 = lp1 + ip2 = lp2 + } + + if (numeric_sort == YES) { + len1 = gctod (linbuf, ip1, num1) + len2 = gctod (linbuf, ip2, num2) + + # If fields are nonnumeric, compare as strings. + if (len1 == 0 || len2 == 0) + answer = strcmp (linbuf[ip1-len1], linbuf[ip2-len2]) + else if (num1 < num2) + answer = -1 + else if (num1 > num2) + answer = 1 + else + answer = 0 + } else + answer = strcmp (linbuf[ip1], linbuf[ip2]) + + if (reverse_sort == YES) + return (-answer) + else + return (answer) +end + + +# SS_FINDCOLUMN -- Determine the offset of the first character in the +# desired column. + +int procedure ss_findcolumn (buf, start, column) + +char buf[ARB] +int start, column +int ip, col + +begin + for (ip=start; IS_WHITE(buf[ip]); ip=ip+1) + ; + for (col=1; col < column; col=col+1) { + for (; !IS_WHITE(buf[ip]) && buf[ip] != EOS; ip=ip+1) + ; + for (; IS_WHITE(buf[ip]); ip=ip+1) + ; + } + + return (ip) +end + + +# SS_GTEXT -- Get text lines into linbuf. + +int procedure ss_gtext (infile, linptr, nlines, linbuf) + +int infile, linptr[ARB], nlines +char linbuf[ARB] + +int lbp, len, getline() +errchk getline + +begin + nlines = 0 + lbp = 1 + + repeat { + len = getline (infile, linbuf[lbp]) + if (len == EOF) + break + else if (len == 1) + # ignore blank lines + else { + nlines = nlines + 1 + linptr[nlines] = lbp + lbp = lbp + len + 1 # '1' = room for EOS + } + } until (lbp >= SZ_LINBUF - SZ_LINE || nlines >= MAXPTR) + + return (len) +end + + +# SS_PTEXT -- Output text lines from linbuf to outfile. + +procedure ss_ptext (outfil, linptr, nlines, linbuf) + +int outfil, linptr[ARB], nlines +char linbuf[ARB] +int i, j +errchk putline + +begin + for (i=1; i <= nlines; i=i+1) { + j = linptr[i] + call putline (outfil, linbuf[j]) + } +end diff --git a/pkg/system/system.cl b/pkg/system/system.cl new file mode 100644 index 00000000..1e114d72 --- /dev/null +++ b/pkg/system/system.cl @@ -0,0 +1,55 @@ +lists + +#{ SYSTEM.CL -- Package script task for the SYSTEM package. This package is +# loaded by the CL upon startup, and is always in the search path. + +package system + +task cmdstr, + chkupdate, + concatenate, + copy, + count, + delete, + directory, + files, + head, + lprint, + match, + mkdir, + movefiles, + mtclean, + $netstatus, + page, + pathnames, + protect, + rename, + sort, + tail, + tee, + touch, + type, + rewind, + unprotect, + fcache, + urlget, + help = "system$x_system.e" + +task mkscript = "system$mkscript.cl"; hidetask cmdstr +task $news = "system$news.cl" +task $bench = "system$bench.cl" + +task allocate = "hlib$allocate.cl" +task gripes = "hlib$gripes.cl" +task deallocate = "hlib$deallocate.cl" +task devstatus = "hlib$devstatus.cl" +task $diskspace = "hlib$diskspace.cl" +task $spy = "hlib$spy.cl" + +task $devices = "system$devices.cl" +task references = "system$references.cl" +task phelp = "system$phelp.cl" + +hidetask mtclean + +keep diff --git a/pkg/system/system.hd b/pkg/system/system.hd new file mode 100644 index 00000000..be4b1bbe --- /dev/null +++ b/pkg/system/system.hd @@ -0,0 +1,47 @@ +# Help directory for the SYSTEM package. + +$defdir = "system$" +$doc = "system$doc/" +$help = "system$help/" + +allocate hlp=doc$allocate.hlp, src=hlib$allocate.cl +concatenate hlp=doc$concatenate.hlp, src=concatenate.x +chkupdate hlp=doc$chkupdate.hlp, src=chkupdate.x +copy hlp=doc$copy.hlp, src=copy.x +count hlp=doc$count.hlp, src=count.x +deallocate hlp=doc$deallocate.hlp, src=hlib$deallocate.cl +delete hlp=doc$delete.hlp, src=delete.x +devices hlp=dev$devices.hlp, src=devices.cl +devstatus hlp=doc$devstatus.hlp, src=hlib$devstatus.cl +directory hlp=doc$directory.hlp, src=directory.x +diskspace hlp=doc$diskspace.hlp, src=hlib$diskspace.cl +fcache hlp=doc$fcache.hlp, src=t_fcache.x +files hlp=doc$files.hlp, src=files.x +gripes hlp=doc$gripes.hlp, src=hlib$gripes.cl +head hlp=doc$head.hlp, src=head.x +help hlp=doc$help.hlp, src=help$t_help.x +lprint hlp=doc$lprint.hlp, src=lprint.x +match hlp=doc$match.hlp, src=match.x +mkdir hlp=doc$mkdir.hlp, src=mkdir.x +mkscript hlp=doc$mkscript.hlp, src=mkscript.cl +movefiles hlp=doc$movefiles.hlp, src=movefiles.x +news hlp=doc$news.hlp, src=news.cl +netstatus hlp=doc$netstatus.hlp, src=netstatus.x +page hlp=doc$page.hlp, src=page.x +pathnames hlp=doc$pathnames.hlp, src=pathnames.x +phelp hlp=doc$phelp.hlp, src=phelp.cl +protect hlp=doc$protect.hlp, src=protect.x +references hlp=doc$references.hlp, src=references.cl +rename hlp=doc$rename.hlp, src=rename.x +revisions hlp=doc$revisions.hlp, src=revisions.cl +rewind hlp=doc$rewind.hlp, src=rewind.x +sleep hlp=doc$sleep.hlp, src=sleep.x +sort hlp=doc$sort.hlp, src=sort.x +spy hlp=doc$spy.hlp, src=hlib$spy.cl +system hlp=doc$system.hlp, src=system.cl +tail hlp=doc$tail.hlp, src=tail.x +tee hlp=doc$tee.hlp, src=tee.x +touch hlp=doc$touch.hlp, src=touch.x +type hlp=doc$type.hlp, src=type.x +urlget hlp=doc$urlget.hlp, src=urlget.x +unprotect hlp=doc$unprotect.hlp, src=unprotect.x diff --git a/pkg/system/system.men b/pkg/system/system.men new file mode 100644 index 00000000..b79ae550 --- /dev/null +++ b/pkg/system/system.men @@ -0,0 +1,39 @@ + allocate - Allocate a device, i.e., magtape drive mta, mtb, ... + concatenate - Concatenate a list of files + chkupdate - Check for an available IRAF update + copy - Copy a file or files (use IMCOPY for imagefiles) + count - Count the number of lines, words, characters in a text file + deallocate - Deallocate a previously allocated device + delete - Delete a file or files (use IMDELETE to delete imagefiles) + devices - Print information on the locally available devices + devstatus - Print the status of a device (mta, mtb, ...) + directory - List the files in a directory + diskspace - Show how much diskspace is available + fcache - List, clean or manipulate the file cache + files - Expand a file template into a list of files + gripes - Send suggestions, complaints, etc. to the system + head - Print the first few lines of a text file + help - Print online documentation + lprint - Print a file on the line printer device + match - Print all lines in a file that match a pattern + mkdir - Create a new directory + mkscript - Make a command script + movefiles - Move files to a directory + netstatus - Print the status of the local network + news - Page through the system news file + page - Page through a file + pathnames - Expand a file template into a list of OS pathnames + phelp - Paged HELP: collects and pages the output of HELP + protect - Protect a file from deletion + references - Find all help database references for a given topic + rename - Rename a file + rewind - Rewind a device (magtape) + sort - Sort a text file + spy - Show processor status + system - Simple benchmarking tool + tail - Print the last few lines of a file + tee - Tee the standard output into a file + touch - Change file access and modification times + type - Type a text file on the standard output + urlget - Get a (http) URL to a named file + unprotect - Remove delete protection from a file diff --git a/pkg/system/system.par b/pkg/system/system.par new file mode 100644 index 00000000..238ccfcd --- /dev/null +++ b/pkg/system/system.par @@ -0,0 +1,5 @@ +# Package parameter file for SYSTEM. + +version,s,h,"12-Nov-83" +release,s,h,)cl.release,,,IRAF release version +mode,s,h,ql diff --git a/pkg/system/t_fcache.x b/pkg/system/t_fcache.x new file mode 100644 index 00000000..236c33c4 --- /dev/null +++ b/pkg/system/t_fcache.x @@ -0,0 +1,118 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> + +define FC_CMDS "|init|purge|destroy|list|lookup|access|add|delete|wait|help|" + +define FC_INIT 1 +define FC_PURGE 2 +define FC_DESTROY 3 +define FC_LIST 4 +define FC_LOOKUP 5 +define FC_ACCESS 6 +define FC_ADD 7 +define FC_DELETE 8 +define FC_WAIT 9 +define FC_HELP 10 + + +# FCACHE -- Task interface to the file cache. + +procedure t_fcache () + +char cmd[SZ_FNAME], cache[SZ_FNAME], fname[SZ_FNAME] +char pattern[SZ_FNAME], src[SZ_FNAME], cname[SZ_FNAME], extn[SZ_FNAME] +bool verbose, in_src, exists +int age + +int strdic(), clgeti(), envgeti() +bool clgetb(), fcaccess() + +begin + # Get the common parameters. + call clgstr ("cmd", cmd, SZ_FNAME) + call clgstr ("cache", cache, SZ_FNAME) + verbose = clgetb ("verbose") + + # Process the requested command. + switch (strdic (cmd, cmd, SZ_FNAME, FC_CMDS)) { + case FC_INIT: + call clgstr ("pattern", pattern, SZ_FNAME) + call fcinit (cache, pattern) + + case FC_PURGE: + age = clgeti ("age") + if (age < 0) + age = envgeti ("cache_age") + call fcpurge (cache, verbose, age) + + case FC_DESTROY: + call fcdestroy (cache, verbose) + + case FC_LIST: + call fclist (cache, verbose, STDOUT) + + case FC_LOOKUP: + call clgstr ("src", src, SZ_FNAME) + if (src[1] != EOS) { + call fclookup (cache, src, fname, extn, SZ_FNAME) + if (verbose) { + call printf ("%s\n") + call pargstr (fname) + } + call clpstr ("fname", fname) + call clpstr ("extn", extn) + } else { + call clgstr ("fname", fname, SZ_FNAME) + call clgstr ("extn", extn, SZ_FNAME) + call fclookup (cache, src, fname, extn, SZ_FNAME) + if (verbose) { + call printf ("%s\n") + call pargstr (src) + } + call clpstr ("src", src) + } + + case FC_ACCESS: + call clgstr ("src", src, SZ_FNAME) + call clgstr ("extn", extn, SZ_FNAME) + + exists = fcaccess (cache, src, extn) + call printf ("%b\n") + call pargb (exists) + + case FC_ADD: + call clgstr ("src", src, SZ_FNAME) + call clgstr ("extn", extn, SZ_FNAME) + call fcadd (cache, src, extn, cname, SZ_FNAME) + if (verbose) { + call eprintf ("%s\n") + call pargstr (cname) + } + call clpstr ("fname", cname) + if (clgetb ("wait")) + call fcwait (cache, cname) + + case FC_DELETE: + call clgstr ("src", src, SZ_FNAME) + if (src[1] != EOS) { + # Delete by src string. + call fclookup (cache, src, fname, extn, SZ_FNAME) + call fcdelete (cache, fname) + } else { + # Delete by cached filename. + call clgstr ("fname", fname, SZ_FNAME) + call fcdelete (cache, fname) + } + + case FC_WAIT: + call clgstr ("src", src, SZ_FNAME) + call fcwait (cache, src) + + case FC_HELP: + + default: + call eprintf ("Unknown command '%s'\n") + call pargstr (cmd) + } +end diff --git a/pkg/system/t_urlget.x b/pkg/system/t_urlget.x new file mode 100644 index 00000000..d1c234df --- /dev/null +++ b/pkg/system/t_urlget.x @@ -0,0 +1,96 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> +include <syserr.h> +include <imhdr.h> +include <imset.h> +include <mach.h> + + + +# URLGET -- Do an HTTP GET of a URL to the named file. + +procedure t_urlget () + +pointer reply +char url[SZ_PATHNAME], fname[SZ_PATHNAME], extn[SZ_PATHNAME] +char cache[SZ_PATHNAME], lfname[SZ_PATHNAME] +int nread +bool use_cache, verbose + +int nargs, clgeti(), url_get() +bool clgetb(), fcaccess() + +begin + # Get the parameters + call clgstr ("url", url, SZ_PATHNAME) + nargs = clgeti ("$nargs") + if (nargs < 2) { + # No output name specified, so create one from URL + call url_to_name (url, fname, SZ_PATHNAME) + } else + call clgstr ("fname", fname, SZ_PATHNAME) + call clgstr ("extn", extn, SZ_PATHNAME) + call clgstr ("cache", cache, SZ_PATHNAME) + verbose = clgetb ("verbose") + use_cache = clgetb ("use_cache") + + + # Tell them what we're doing. + if (verbose) { + call printf ("%s -> %s\n") + call pargstr (url) + call pargstr (fname) + call flush (STDOUT) + } + + # Retrieve the URL. + if (use_cache) { + call aclrc (lfname, SZ_FNAME); + + if (fcaccess (cache, url, "fits")) { + call fcname (cache, url, "f", lfname, SZ_PATHNAME) + if (extn[1] != EOS) { + # Add an extension to the cached file. + call strcat (".", lfname, SZ_PATHNAME) + call strcat (extn, lfname, SZ_PATHNAME) + } + } else { + # Add it to the cache, also handles the download. + call fcadd (cache, url, extn, lfname, SZ_PATHNAME) + } + call fcopy (lfname, fname) + + } else { + # Not in cache, or not using the cache, so force the download. + call calloc (reply, SZ_LINE, TY_CHAR) + nread = url_get (url, fname, reply) + call mfree (reply, TY_CHAR) + } +end + + +# URL_TO_NAME -- Generate a filename from a URL. + +procedure url_to_name (url, name, maxch) + +char url[ARB] #i URL being accessed +char name[ARB] #o output name +int maxch #i max size of output name + +int ip, strlen() +char ch + +begin + ip = strlen (url) + while (ip > 1) { + ch = url[ip] + if (ch == '/' || ch == '?' || ch == '&' || ch == ';' || ch == '=') { + call strcpy (url[ip+1], name, maxch) + return + } + ip = ip - 1 + } + + call strcpy (url[ip], name, maxch) +end diff --git a/pkg/system/tail.par b/pkg/system/tail.par new file mode 100644 index 00000000..649e66ad --- /dev/null +++ b/pkg/system/tail.par @@ -0,0 +1,2 @@ +input_files,s,a,,,,list of files to be printed +nlines,i,h,12,,,number of lines to print from each file diff --git a/pkg/system/tail.x b/pkg/system/tail.x new file mode 100644 index 00000000..ad4ebae0 --- /dev/null +++ b/pkg/system/tail.x @@ -0,0 +1,107 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> + +# TAIL -- Print the tail (last few lines) of each of the named text files on the +# standard output. If more than one file is to be printed, a brief header is +# printed for each file. +# +# Params: +# input_files File matching template +# nlines [h,12] Number of lines at tail of file to be printed +# +# If NLINES is negative, its absolute value is the number of lines to skip at +# head of file. + +procedure t_tail() + +char fname[SZ_FNAME] +bool multiple_files +int nlines, list +int clpopni(), clplen(), clgfil(), clgeti() + +begin + list = clpopni ("input_files") + nlines = clgeti ("nlines") + + multiple_files = (clplen (list) > 1) + + while (clgfil (list, fname, SZ_FNAME) != EOF) + iferr (call print_tail (STDOUT, fname, nlines, multiple_files)) + call erract (EA_WARN) + + call clpcls (list) +end + + +# PRINT_TAIL -- Print the last few lines of a file on the output stream +# given as the first argument, optionally plus a header. + +procedure print_tail (out, fname, nlines, print_file_name) + +char fname[ARB] +int out, nlines +bool print_file_name + +pointer sp, offsets, line +int in, linenum, index, noffsets, nlines_in_file +int open(), getline() +long note() +errchk open, getline, putline, note + +begin + if (nlines == 0) + return + else + noffsets = abs (nlines) + 1 + + call smark (sp) + call salloc (line, SZ_LINE, TY_CHAR) + call salloc (offsets, noffsets, TY_LONG) + + # Open the file. + in = open (fname, READ_ONLY, TEXT_FILE) + + if (print_file_name) { + call fprintf (out, "\n\n===> %s <===\n") + call pargstr (fname) + } + + # If nlines is negative, skip nlines lines at head of file and + # print rest of file. If nlines is positive, print nlines lines + # at tail of file. + + linenum = 0 + repeat { + linenum = linenum + 1 + if (nlines < 0 && linenum > -nlines) + break + else if (nlines > 0) { + index = mod (linenum - 1, noffsets) + Meml[offsets+index] = note (in) + } + } until (getline (in, Memc[line]) == EOF) + + nlines_in_file = linenum - 1 + + # Seek back to offset of desired line, if not skipping head of file. + if (nlines > 0) + if (nlines_in_file <= nlines) + call seek (in, BOFL) + else { + index = mod (nlines_in_file - nlines, noffsets) + call seek (in, Meml[offsets+index]) + } + + # If nlines is positive, print nlines lines, otherwise print rest + # of file. + linenum = 1 + while ((linenum <= nlines || nlines < 0) && + (getline (in, Memc[line]) != EOF)) { + call putline (out, Memc[line]) + linenum = linenum + 1 + } + + call sfree (sp) + call close (in) +end diff --git a/pkg/system/tee.par b/pkg/system/tee.par new file mode 100644 index 00000000..9e833007 --- /dev/null +++ b/pkg/system/tee.par @@ -0,0 +1,3 @@ +tee_file,s,a,,,,name of file into which STDOUT is to be copied +out_type,s,h,"text",,,type of output file (text|binary) +append,b,h,no,,,append to output file? diff --git a/pkg/system/tee.x b/pkg/system/tee.x new file mode 100644 index 00000000..b22abd32 --- /dev/null +++ b/pkg/system/tee.x @@ -0,0 +1,58 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <fset.h> + +define SZ_OTSTR 10 + +# TEE -- Tee the standard output. The type of the output file defaults to +# text file unless the caller specifies otherwise. Note that this tee +# writes the entire output all at once. + +procedure t_tee() + +char tee_file[SZ_FNAME], out_type_string[SZ_OTSTR] +bool clgetb() +pointer sp, buf +int out, sz_buf, out_type, nchars +int open(), read(), strmatch(), getline(), fstati() + +begin + # Get params and open the output file. + call clgstr ("tee_file", tee_file, SZ_FNAME) + call clgstr ("out_type", out_type_string, SZ_OTSTR) + + if (strmatch (out_type_string, "^#{b}") > 0) + out_type = BINARY_FILE + else + out_type = TEXT_FILE + + if (clgetb ("append")) + out = open (tee_file, APPEND, out_type) + else + out = open (tee_file, NEW_FILE, out_type) + + + # Make a buffer and perform the copy operation. + call smark (sp) + + if (out_type == TEXT_FILE) { + call salloc (buf, SZ_LINE, TY_CHAR) + while (getline (STDIN, Memc[buf]) != EOF) { + call putline (STDOUT, Memc[buf]) + call putline (out, Memc[buf]) + } + + } else { + sz_buf = fstati (STDIN, F_BUFSIZE) + call salloc (buf, sz_buf, TY_CHAR) + + while (read (STDIN, Memc[buf], sz_buf) != EOF) { + nchars = fstati (STDIN, F_NCHARS) + call write (STDOUT, Memc[buf], nchars) + call write (out, Memc[buf], nchars) + } + } + + call sfree (sp) + call close (out) +end diff --git a/pkg/system/touch.par b/pkg/system/touch.par new file mode 100644 index 00000000..4adb14b3 --- /dev/null +++ b/pkg/system/touch.par @@ -0,0 +1,7 @@ +files,s,a,,,,list of files to be created or touched +create,b,h,yes,,,create file if it doesn't exist? +atime,b,h,yes,,,update file access time? +mtime,b,h,yes,,,update file modification time? +time,s,h,"",,,time to set (empty for current time) +ref_file,s,h,"",,,reference file for times +verbose,b,h,no,,,verbose output flag diff --git a/pkg/system/touch.x b/pkg/system/touch.x new file mode 100644 index 00000000..5635dbec --- /dev/null +++ b/pkg/system/touch.x @@ -0,0 +1,193 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <finfo.h> +include <error.h> +include <time.h> + + +# TOUCH -- Change file access and modification times, creating an empty +# file if necessary. File times may come from the current system time, +# a user-specified string, or a reference file. + +procedure t_touch() + +pointer list +char fname[SZ_FNAME], time[SZ_FNAME] +char ref_file[SZ_PATHNAME] +char at_str[SZ_TIME], mt_str[SZ_TIME] +bool create, atime, mtime, verbose + +long ref[LEN_FINFO] +long t_atime, t_mtime, ltime + +long clktime() +int clpopni(), clgfil() +int finfo(), dtm_ltime() +bool clgetb() + +errchk touch + +begin + # Initialize. + call aclrc (time, SZ_FNAME) + call aclrc (ref_file, SZ_PATHNAME) + + # Process the parameters. + list = clpopni ("files") + + create = clgetb ("create") + atime = clgetb ("atime") + mtime = clgetb ("mtime") + verbose = clgetb ("verbose") + call clgstr ("time", time, SZ_FNAME) + + # Check for error conditions. + if (!atime && !mtime) { + call eprintf ( + "ERROR: Must specify at least one of 'atime' or 'mtime'.\n") + call clpcls (list) + return + } + + # Get the time to be set. + if (time[1] == EOS) { + # No 'time' param, look for a reference file to use. + call clgstr ("ref_file", ref_file, SZ_PATHNAME) + if (ref_file[1] == EOS) { + # No 'ref_file' param, use the current system time. + t_atime = clktime (long(0)) + t_mtime = t_atime + + if (verbose) { + call cnvtime (t_atime, at_str, SZ_TIME) + call printf ("Modifying to system time: %s\n\n") + call pargstr (at_str) + } + + } else { + # Open the reference file and use those times. + if (finfo (ref_file, ref) == ERR) { + call eprintf ("Error opening reference file: '%s'\n") + call pargstr (ref_file) + return + } + t_atime = FI_ATIME(ref) + t_mtime = FI_MTIME(ref) + + if (verbose) { + call cnvtime (t_atime, at_str, SZ_TIME) + call cnvtime (t_mtime, mt_str, SZ_TIME) + call printf ("Modifying to reference time: ") + call printf ("%s (atime)\n%30t%s (mtime)\n\n") + call pargstr (at_str) + call pargstr (mt_str) + } + } + + } else { + # Parse the time parameter to get the modification time. + if (dtm_ltime (time, ltime) == ERR) { + if (ltime < 0) + call eprintf ("Invalid time string: '%s'\n") + else + call eprintf ("Error parsing time string: '%s'\n") + call pargstr (time) + return + } + t_atime = ltime + t_mtime = ltime + + if (verbose) { + call cnvtime (t_atime, at_str, SZ_TIME) + call printf ("Modifying to user-specified time: %s\n\n") + call pargstr (at_str) + } + } + + # Now apply the atime/mtime params to update only what's needed. + if (!atime) t_atime = NULL + if (!mtime) t_mtime = NULL + + + # Process the list of input files. + while (clgfil (list, fname, SZ_FNAME) != EOF) { + iferr (call touch (fname, create, t_atime, t_mtime, verbose)) + ; + } + + # Clean up and close the list. + call clpcls (list) +end + + +# TOUCH -- Touch a file to modify the times. + +procedure touch (fname, create, atime, mtime, verbose) + +char fname[ARB] #i file name to touch +bool create #i create file if necessary? +long atime, mtime #i access and modify time +bool verbose #i verbose output? + +char dir[SZ_PATHNAME], ip +char vfn[SZ_PATHNAME] +int fd +int access(), open(), futime() + +begin + if (verbose) { + call printf ("%s: ") + call pargstr (fname) + } + + # Check first it the file exists. + if (access (fname, 0, 0) == NO) { + if (create) { + + call fnldir (fname, vfn, SZ_PATHNAME) + call fpathname (vfn, dir, SZ_PATHNAME) + if (access (dir, READ_WRITE, 0) == NO) { + for (ip=1; dir[ip] != '!'; ip=ip+1) + ; + call eprintf ("Error: Cannot open directory '%s'\n") + call pargstr (dir[ip+1]) + call erract (EA_ERROR) + return; + } + + # Create a new empty file. + iferr (fd = open (fname, NEW_FILE, TEXT_FILE)) { + call eprintf ("Error: Cannot touch file '%s'\n") + call pargstr (fname) + call erract (EA_ERROR) + return; + } + call close (fd) + if (verbose) call printf ("(created) ") + + } else { + if (verbose) call printf ("(not created)\n") + return + } + } + + # Update the times. + if (futime (fname, atime, mtime) == ERR) + call eprintf ("Error processing file\n") + + else if (verbose) { + call printf ("(updated %s%s%s)\n") + if (atime > 0) + call pargstr ("atime") + else + call pargstr ("") + if (atime > 0 && mtime > 0) + call pargstr ("/") + else + call pargstr ("") + if (mtime > 0) + call pargstr ("mtime") + else + call pargstr ("") + } +end diff --git a/pkg/system/type.par b/pkg/system/type.par new file mode 100644 index 00000000..62ce1380 --- /dev/null +++ b/pkg/system/type.par @@ -0,0 +1,3 @@ +input_files,s,a,,,,list of files to be typed +map_cc,b,h,yes,,,make unknown control chars printable +device,s,h,"terminal",,,output device diff --git a/pkg/system/type.x b/pkg/system/type.x new file mode 100644 index 00000000..156cb5c5 --- /dev/null +++ b/pkg/system/type.x @@ -0,0 +1,68 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <error.h> + +# TYPE -- Type the named files on the standard output. If more than one +# file, print a brief header identifying each file. + +procedure t_type() + +char fname[SZ_FNAME], device[SZ_FNAME] +bool multiple_files +int map_cc, list +pointer tty, ttyodes() +bool clgetb() +int clpopni(), clplen(), clgfil(), btoi() + +begin + list = clpopni ("input_files") + multiple_files = (clplen (list) > 1) + map_cc = btoi (clgetb ("map_cc")) + call clgstr ("device", device, SZ_FNAME) + tty = ttyodes (device) + + while (clgfil (list, fname, SZ_FNAME) != EOF) + iferr (call type_file (STDOUT, tty, fname, multiple_files, map_cc)) + call erract (EA_WARN) + + call ttycdes (tty) + call clpcls (list) +end + + +# TYPE_FILE -- Print the named file on the output stream given as the first +# argument, optionally with a leading header. + +procedure type_file (out, tty, fname, print_file_name, map_cc) + +int out +pointer tty +char fname[ARB] +bool print_file_name +int map_cc + +int in +pointer sp, buf +int open(), getline() +errchk salloc, open, getline, ttyputline + +begin + call smark (sp) + call salloc (buf, SZ_LINE, TY_CHAR) + + in = open (fname, READ_ONLY, TEXT_FILE) + + if (print_file_name) { + call fprintf (out, "===> %s <===\n") + call pargstr (fname) + } + + while (getline (in, Memc[buf]) != EOF) + call ttyputline (out, tty, Memc[buf], map_cc) + + if (print_file_name) + call fprintf (out, "\n\n") + + call close (in) + call sfree (sp) +end diff --git a/pkg/system/unprotect.par b/pkg/system/unprotect.par new file mode 100644 index 00000000..f57772b3 --- /dev/null +++ b/pkg/system/unprotect.par @@ -0,0 +1 @@ +files,s,a,,,,list of files from which protection is to be removed diff --git a/pkg/system/unprotect.x b/pkg/system/unprotect.x new file mode 100644 index 00000000..c265bbf8 --- /dev/null +++ b/pkg/system/unprotect.x @@ -0,0 +1,23 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <protect.h> +include <error.h> + +# UNPROTECT -- Remove protection from a list of files. + +procedure t_unprotect() + +char fname[SZ_FNAME] +int list, status + +int clpopns(), clgfil(), protect() + +begin + list = clpopns ("files") + + while (clgfil (list, fname, SZ_FNAME) != EOF) + iferr (status = protect (fname, REMOVE_PROTECTION)) + call erract (EA_WARN) + + call clpcls (list) +end diff --git a/pkg/system/urlget.par b/pkg/system/urlget.par new file mode 100644 index 00000000..64126be8 --- /dev/null +++ b/pkg/system/urlget.par @@ -0,0 +1,6 @@ +url,s,q,"",,,"URL (http) to retrieve" +fname,s,q,"",,,"Output file name" +use_cache,b,h,yes,,,"Use previously cached file?" +extn,s,h,"",,,"Filename extn for cached file" +verbose,b,h,no,,,"Use verbose output?" +cache,s,h,"cache$",,,"Cache directory" diff --git a/pkg/system/x_system.x b/pkg/system/x_system.x new file mode 100644 index 00000000..0695b0d3 --- /dev/null +++ b/pkg/system/x_system.x @@ -0,0 +1,36 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# Process x_system (the executable part of the SYSTEM package). + +task chkupdate = t_chkupdate, + concatenate = t_concatenate, + copy = t_copy, + count = t_count, + delete = t_delete, + directory = t_directory, + fcache = t_fcache, + files = t_files, + head = t_head, + match = t_match, + mkdir = t_mkdir, + movefiles = t_movefiles, + mtclean = t_mtclean, + netstatus = t_netstatus, + page = t_page, + pathnames = t_pathnames, + protect = t_protect, + rename = t_rename, + sort = t_sort, + tail = t_tail, + tee = t_tee, + type = t_type, + unprotect = t_unprotect, + rewind = t_rewind, + lprint = t_lprint, + help = t_help, + lroff = t_lroff, + mkhelpdb = t_mkhelpdb, + hdbexamine = t_hdbexamine, + cmdstr = t_cmdstr, + touch = t_touch, + urlget = t_urlget |