From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 20-APR-1989 14:39
To:	MRGATE::"ARISIA::EVERHART"
Subj:	crude 'man -k' program for VMS

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Thu, 20 APR 89 08:57:58 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Thu, 20 Apr 89 08:41:08 PDT
Received: by ucbvax.Berkeley.EDU (5.61/1.36)
	id AA00511; Thu, 20 Apr 89 08:38:30 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 19 Apr 89 13:04:14 GMT
From: mcvax!ukc!stc!stl!scott@uunet.uu.net  (Mike Scott)
Organization: STC Technology Limited, London Road, Harlow, Essex, UK
Subject: crude 'man -k' program for VMS
Message-Id: <1376@stl.stc.co.uk>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

I've had enough requests for this to warrant posting it. It's code to
provide a crude 'man -k'-like facility for VMS. I hope it will
stimulate further though about good ways to tackle this type of
problem. If you find bugs please let me know (not that I'm promising
to fix them). If you have something better, tell the world!

It's the usual VMS_SHARE format. Just extract the text below, and '@' it.


$! ..................... Cut between dotted lines and save. ....................
$!.............................................................................
$! VAX/VMS archive file created by VMS_SHARE V06.06A 19-DEC-1988.
$!
$! VMS_SHARE was written by James Gray (Gray:OSBUSouth@Xerox.COM) from
$! VMS_SHAR by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au).
$!
$! To unpack, simply save, concatinate all parts into one file and
$! execute (@) that file.
$!
$! This archive was created by user SCOTT
$! on 19-APR-1989 13:50:37.68.
$!
$! It contains the following 13 files:
$!        AAAREADME.1ST
$!        BUILD.COM
$!        EATLINE.C
$!        FILE_DEFAULTS.C
$!        FJIG.C
$!        FSCNDEF.H
$!        ISPREFIX.C
$!        MAN-K-GEN.COM
$!        MAN-K-INDEX.C
$!        MAN-K.COM
$!        MISC.H
$!        OPENDEF.C
$!        USER_ERRORS.MSG
$!
$!==============================================================================
$ SET SYMBOL/SCOPE=( NOLOCAL, NOGLOBAL )
$ VERSION = F$GETSYI( "VERSION" )
$ IF VERSION .GES "V4.4" THEN GOTO VERSION_OK
$ WRITE SYS$OUTPUT "You are running VMS ''VERSION'; ", -
    "VMS_SHARE V06.06A 19-DEC-1988 requires VMS V4.4 or higher."
$ EXIT 44 ! SS$_ABORT
$VERSION_OK:
$ GOTO START
$!
$UNPACK_FILE:
$ WRITE SYS$OUTPUT "Creating ''FILE_IS'"
$ DEFINE/USER_MODE SYS$OUTPUT NL:
$ EDIT/TPU/COMMAND=SYS$INPUT/NODISPLAY/OUTPUT='FILE_IS'/NOSECTION -
    VMS_SHARE_DUMMY.DUMMY
b_part := CREATE_BUFFER( "{Part}", GET_INFO( COMMAND_LINE, "file_name" ) )
; s_file_spec := GET_INFO( COMMAND_LINE, "output_file" ); SET( OUTPUT_FILE
, b_part, s_file_spec ); b_errors := CREATE_BUFFER( "{Errors}" ); i_errors 
:= 0; pat_beg_1 := ANCHOR & "-+-+-+ Beginning"; pat_beg_2 := LINE_BEGIN 
& "+-+-+-+ Beginning"; pat_end := ANCHOR & "+-+-+-+-+ End"; POSITION
( BEGINNING_OF( b_part ) ); LOOP EXITIF SEARCH( SPAN( ' ' )@r_trail 
& LINE_END, FORWARD) = 0; POSITION( r_trail ); ERASE( r_trail ); ENDLOOP
; POSITION( BEGINNING_OF( b_part ) ); i_append_line := 0; LOOP EXITIF MARK
( NONE ) = END_OF( b_part ); s_x := ERASE_CHARACTER( 1 )
; IF s_x = '+' THEN r_skip := SEARCH( pat_beg_1, FORWARD, EXACT ); IF r_skip 
<> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ERASE_LINE; ENDIF
; ENDIF; IF s_x = '-' THEN r_skip := SEARCH( pat_end, FORWARD, EXACT )
; IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); m_skip 
:= MARK( NONE ); r_skip := SEARCH( pat_beg_2, FORWARD, EXACT ); IF r_skip 
<> 0 THEN POSITION( END_OF( r_skip ) ); MOVE_HORIZONTAL( -CURRENT_OFFSET )
; MOVE_VERTICAL( 1 ); MOVE_HORIZONTAL( -1 ); ELSE POSITION( END_OF( b_part ) 
); ENDIF; ERASE( CREATE_RANGE( m_skip, MARK( NONE ), NONE ) ); ENDIF; ENDIF
; IF s_x = 'V' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE
; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line := 1
; MOVE_VERTICAL( 1 ); ENDIF; IF s_x = 'X' THEN s_x := ''; IF i_append_line 
<> 0 THEN APPEND_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF
; i_append_line := 0; MOVE_VERTICAL( 1 ); ENDIF; IF s_x <> '' THEN i_errors 
:= i_errors + 1; s_text := CURRENT_LINE; POSITION( b_errors ); COPY_TEXT
( "The following line could not be unpacked properly:" ); SPLIT_LINE
; COPY_TEXT( s_x ); COPY_TEXT( s_text ); POSITION( b_part ); MOVE_VERTICAL
( 1 ); ENDIF; ENDLOOP; POSITION( BEGINNING_OF( b_part ) ); LOOP r_x := SEARCH
( "`", FORWARD, EXACT ); EXITIF r_x = 0; POSITION( r_x ); ERASE_CHARACTER( 1 
); COPY_TEXT( ASCII( INT( ERASE_CHARACTER( 3 ) ) ) ); ENDLOOP
; IF i_errors = 0 THEN SET( NO_WRITE, b_errors, ON ); ELSE POSITION
( BEGINNING_OF( b_errors ) ); COPY_TEXT( FAO
( "The following !UL errors were detected while unpacking !AS", i_errors
, s_file_spec ) ); SPLIT_LINE; SET( OUTPUT_FILE, b_errors, "SYS$COMMAND" )
; ENDIF; EXIT; 
$ DELETE VMS_SHARE_DUMMY.DUMMY;*
$ CHECKSUM 'FILE_IS
$ WRITE SYS$OUTPUT " CHECKSUM ", -
  F$ELEMENT( CHECKSUM_IS .EQ. CHECKSUM$CHECKSUM, ",", "failed!!,passed." )
$ RETURN
$!
$START:
$ FILE_IS = "AAAREADME.1ST"
$ CHECKSUM_IS = 1263432749
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
XThis is a crude attempt at a 'man -k' facility for VMS. It works by scanning
Xall help files in a specified list for help keywords at all levels. These
Xkeywords are munged by removing non-alphanumeric characters. A new set of
Xkeywords is also generated by splitting at '_' characters. Prefixes like sys$
Xare also removed. All keys are truncated to 16 characters max. A huge indexed
Vfile is built up, indexed by these keys, and containing the needed info to ge
Xt
Vhelp on that topic. Making this file is quite slow! However, the user procedu
Xre
Xto read the file is fast, which is what matters.`032
X
XYou just need to do
X
X$ @build
X
Xto build the man-k-index program. This is invoked from the man-k-gen.com
Xbuild file, which is used thus:
X
X$ @man-k-gen sys$help:*.hlb
X
XThis produces a file index.dat, which can be moved manually to the required
Xlocation (probably sys$help). A possible set of locations is built into
Xa search list in man-k.com.
X
XYou can then do, e.g.
X
X$ @man-k getjpi
X
Xto just print various paths, or
X
X$ @man-k getjpi x
X
Xto query whether help is wanted for each path as it is printed.
X
X
XSorry about the crudity of all this... it's rather experimental still! Usual
Vdisclaimers apply: I don't warrant the code to do anything much other than us
Xe
Vup disk space; nor can any responsibility accepted for loss/damage/etc caused
X by
Xits use. If you find bugs or better ways of doing this, please let me know.
$ GOSUB UNPACK_FILE
$ FILE_IS = "BUILD.COM"
$ CHECKSUM_IS = 1061374588
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X$ define vaxc$include sys$disk:[],sys$library:
X$ cc man-k-index
X$ cc fjig
X$ cc opendef
X$ cc eatline
X$ cc file_defaults
X$ cc isprefix
X$ message user_errors
X$ link man-k-index,fjig,opendef,eatline,file_defaults,isprefix,user_errors, -
X sys$input/opt
Xsys$library:vaxcrtl/share
$ GOSUB UNPACK_FILE
$ FILE_IS = "EATLINE.C"
$ CHECKSUM_IS = 857175127
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/*$$++ eatline.c`009x0.0`009mas 22-oct-85
X
Xread up to and includeing end of current line (i.e. to
Xnext '\n' character), taking accpunt of EOF.
X
Xcalling sequence:-
X
XFILE *f;
Xeatline(f);
X
Xreturns 0, or EOF if eof found
X
X$$--*/
X
X#include stdio
X
Xeatline(f)
XFILE *f;
X`123
X   char c;
X
X   do
X      c = getc(f);
X   while( c!='\n' && c!=EOF );
X
X   return c==EOF ? EOF : 0;
X   `125
$ GOSUB UNPACK_FILE
$ FILE_IS = "FILE_DEFAULTS.C"
$ CHECKSUM_IS = 1543530464
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/*$$++ file_defaults.c`009x0.0`009mas`00915-may-85
X
XFill in defaults in a file name from a model file spec.
X
Xcalling sequence:-
X
Xchar *fn;`009`009`009input filename
Xchar *fn_d;`009`009`009defaults file string
Xchar fn_result[256];`009`009resulting string
Xint fnb;`009`009`009to receive nam$l_fnb flags
Xerr = file_defaults(fn,fn_d,fn_result,&fnb);
X
XAll file strings are null-terminated.
XReturns rms error codes.
X
X$$--*/
X
X#include rms
X
Xint file_defaults(fn,fn_d,fn_r,fnb)
Xchar *fn,*fn_d,*fn_r;
Xint *fnb;
X`123
X   struct FAB fab = cc$rms_fab;
X   struct NAM nam = cc$rms_nam;
X   int err;
X
X   fab.fab$l_dna = fn_d;`009`009/* default file spec */
X   fab.fab$b_dns = strlen(fn_d);
X
X   fab.fab$l_fna = fn;`009`009`009/* input file spec */
X   fab.fab$b_fns = strlen(fn);
X
X   fab.fab$l_nam = &nam;
X
X   nam.nam$l_esa = fn_r;`009`009/* output string */
X   nam.nam$b_ess = NAM$C_MAXRSS;`009/* output string length (255) */
X
X   nam.nam$b_nop = NAM$M_SYNCHK;`009/* parse with no i/o */
X
X   err = sys$parse(&fab);
X
X   if( fnb!=0 )
X      *fnb = nam.nam$l_fnb;`009`009/* return flag word */
X
X   fn_r[nam.nam$b_esl] = 0;`009`009/* terminate o/p string */
X   `125
$ GOSUB UNPACK_FILE
$ FILE_IS = "FJIG.C"
$ CHECKSUM_IS = 809456495
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/*$$++ fjig.c  x0.0  mas  9-aug-85
X
Xanalyse input file string, transferring only desired components
Xto output string.
X
Xcalling sequence:-
X#include <fscndef.h>`009`009( bit definitions from sys$filescan)
Xchar *in;`009`009input file spec string, must be valid syntax
Xchar out[255+1];`009output "   "     "
Xlong keepflgs;`009`009word defing components to transfer from in to out:
X`009`009`009FSCN$M_NODE, FSCN$M_DEVICE, FSCN$M_ROOT,
X`009`009`009FSCN$M_DIRECTORY, FSCN$M_NAME, FSCN$M_TYPE,
X`009`009`009FSCN$M_VERSION. (same bits as sys$filescan service)
Xlong gotflgs;`009`009receives above bits depending on what was specified
X`009`009`009in "in".
Xerr = fscan(in,out,keepflgs,&gotflgs);
X
Xerrors are any returned by sys$filescan service
X
X$$--*/
X
X#include ssdef
X#include descrip
X#include <fscndef.h>"
X#include <misc.h>
X
X
X/* order of this list must agree with "fields" array */
Xlong cmpts[] = `123
X      FSCN$M_NODE,
X      FSCN$M_DEVICE,
X      FSCN$M_ROOT,
X      FSCN$M_DIRECTORY,
X      FSCN$M_NAME,
X      FSCN$M_TYPE,
X      FSCN$M_VERSION,
X      `125;
X#define NCMPTS (sizeof(cmpts)/sizeof(cmpts[0]))
X
X/* input array to sys$filescan service. must agree with that layout.
XOrdering must agree with "cmpts" array */
Xstruct `123
X   short fld_len;
X   short fld_code;
X   char *fld_addr;
X   `125 fields[NCMPTS+1]= `123`009`009/* allow for terminator */
X   0,FSCN$_NODE,0,
X   0,FSCN$_DEVICE,0,
X   0,FSCN$_ROOT,0,
X   0,FSCN$_DIRECTORY,0,
X   0,FSCN$_NAME,0,
X   0,FSCN$_TYPE,0,
X   0,FSCN$_VERSION,0,
X   0,0,0 `125;
X
X
Xint fjig(in,out,keepflgs,gotflgs)
Xchar *in,*out;
Xint keepflgs;
Xint *gotflgs;
X`123
X   int i;
X   $DESCRIPTOR(src,"");
X
X   src.dsc$a_pointer = in;`009`009`009/* make string descriptor */
X   src.dsc$w_length = strlen(in);
X
X   CHK_R( sys$filescan(&src,fields,gotflgs) );`009/* return on error */
X
X   for( i=0; i<NCMPTS; i++ )
X      if( cmpts[i]&keepflgs )`009`009`009/* he wants this one */
X         for( ; fields[i].fld_len>0; --fields[i].fld_len )
X            *out++ = *fields[i].fld_addr++;`009/* copy it, if there */
X   *out = 0;`009`009`009`009`009/* terminate o/p string */
X   return SS$_NORMAL;
X   `125
$ GOSUB UNPACK_FILE
$ FILE_IS = "FSCNDEF.H"
$ CHECKSUM_IS = 85005298
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X#define FSCN$L_ADDR      0x04
X#define FSCN$M_DEVICE    0x02
X#define FSCN$M_DIRECTORY 0x08
X#define FSCN$M_NAME      0x10
X#define FSCN$M_NODE      0x01
X#define FSCN$M_ROOT      0x04
X#define FSCN$M_TYPE      0x20
X#define FSCN$M_VERSION   0x40
X#define FSCN$S_FLDFLAGS  0x01
X#define FSCN$S_FSCNDEF   0x08
X#define FSCN$S_ITEM_LEN  0x08
X#define FSCN$V_DEVICE    0x01
X#define FSCN$V_DIRECTORY 0x03
X#define FSCN$V_NAME      0x04
X#define FSCN$V_NODE      0x00
X#define FSCN$V_ROOT      0x02
X#define FSCN$V_TYPE      0x05
X#define FSCN$V_VERSION   0x06
X#define FSCN$W_ITEM_CODE 0x02
X#define FSCN$W_LENGTH    0x00
X#define FSCN$_DEVICE     0x03
X#define FSCN$_DIRECTORY  0x05
X#define FSCN$_FILESPEC   0x01
X#define FSCN$_NAME       0x06
X#define FSCN$_NODE       0x02
X#define FSCN$_ROOT       0x04
X#define FSCN$_TYPE       0x07
X#define FSCN$_VERSION    0x08
$ GOSUB UNPACK_FILE
$ FILE_IS = "ISPREFIX.C"
$ CHECKSUM_IS = 825169537
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/*$$++ isprefix.c`009x0.0`009mas`00925-feb-85
X
X1. return 0 if first string is not a leading substring of 2nd string, 1 if
X   it is. (Returns 1 if first string is null).
Xchar *sp, *s;
Xisprefix(sp,s);
X
X2. Return 0 if 1st string is null or not a leading substring of 2nd string,
X   1 if non-null and a leading substring.
Xchar *sp,*s;
Xisnnprefix(sp,s);
X
X$$## prefix,substring,leading
X
X$$--*/
X
X
Xint isprefix(sp,s)
Xchar *sp,*s;
X`123
X   for( ;*sp!=0; sp++,s++ )
X      if( *sp!=*s )
X         return(0);
X   return(1);
X   `125
X
X
Xint isnnprefix(sp,s)
Xchar *sp,*s;
X`123
X   if( *sp==0 )
X      return 0;
X   else
X      return isprefix(sp,s);
X   `125
$ GOSUB UNPACK_FILE
$ FILE_IS = "MAN-K-GEN.COM"
$ CHECKSUM_IS = 242884499
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X$ov='f$verify(0)
X$ on warning then goto exit
X$ if p2 .nes. "" then delete = "!"
X$ if p2 .nes. "" then goto phase_'p2'
X$! generate indexed file for man-k
X$! p1 help libraries to process
X$! each help (sub)topic is [truncated] key of record, the 1st 16 characters
X$! rest of record is filename, then complete help path list.
X$! spaces between items (incl col 17)
X$!
X$phase_HELP_EXTRACT:
X$ hfl = ""
X$ open/write txt help.txt
X$hf_loop:
X$ hf = f$search(p1)
X$ if hf .eqs. "" then goto hf_done
X$ if hf .eqs. hfl then goto hf_done
X$ hfl = hf
X$ write sys$output hf
X$ write txt "*** ''hf'"
X$ libr/help 'hf'/extr=*/out=txt
X$ goto hf_loop
X$hf_done:
X$!
X$ close txt
X$!
X$phase_INDEX:
X$ where = f$element(0,"]",f$environment("procedure")) + "]"
X$ mc 'where'man-k-index help.txt index.tmp
X$ delete/noconfirm help.txt;*
X$!
X$phase_FDL:
X$ convert index.tmp index.dat/fdl=sys$input:
XFILE
X`009ALLOCATION              20
X`009BEST_TRY_CONTIGUOUS     yes
X`009BUCKET_SIZE             3
X`009CLUSTER_SIZE            3
X`009CONTIGUOUS              no
X`009EXTENSION               3
X`009GLOBAL_BUFFER_COUNT     0
X`009ORGANIZATION            indexed
X`009PROTECTION              (system:RWED, owner:RWED, group:RE, world:RE)
X
XRECORD
X`009BLOCK_SPAN              yes
X`009CARRIAGE_CONTROL        carriage_return
X`009FORMAT                  variable
X`009SIZE                    0
X
XAREA 0
X`009ALLOCATION              9
X`009BUCKET_SIZE             3
X`009EXTENSION               3
X
XAREA 1
X`009ALLOCATION              6
X`009BUCKET_SIZE             3
X`009EXTENSION               3
X
XKEY 0
X`009CHANGES                 no
X`009DATA_KEY_COMPRESSION    yes
X`009DATA_RECORD_COMPRESSION yes
X`009DATA_AREA               0
X`009DATA_FILL               100
X`009DUPLICATES              yes
X`009INDEX_AREA              1
X`009INDEX_COMPRESSION       yes
X`009INDEX_FILL              100
X`009LEVEL1_INDEX_AREA       1
X`009NAME                    ""
X`009NULL_KEY                no
X`009PROLOG                  3
X`009SEG0_LENGTH             16
X`009SEG0_POSITION           0
X`009TYPE                    string
X$!
X$exit:
X$ ov = f$verify(ov)
$ GOSUB UNPACK_FILE
$ FILE_IS = "MAN-K-INDEX.C"
$ CHECKSUM_IS = 1007180457
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/* read help file text with intersprsed '*** filename' lines.
Xgenerate output index file */
X
X
X#define KEYLEN 16
X#define MAXLEN 255
X#define MAXLEVELS 15
X#define MINKEY 2
X
X
X#include <stdio.h>
X#include <misc.h>
X#include <ctype.h>
X#include <fscndef.h>
X
X
Xstatic char *pfx_list[] = `123
X   "sys$", "rtl$", "lib$", "dtk$", "mth$",
X   "ots$", "str$", "smg$", "$", "vt", "f$",
X   0,
X   `125;
X
X
X/* generalised alphanumeric test */
X#define alpha(x) ( isalnum(x) `124`124 (strchr("$_",(x))!=0) )
X
X
X/* convrt to l/c, remove non-alphanumerics and pad to 16 chars */
Xstatic char *fudge_key(k)
Xchar *k;
X`123
X   static  char newk[KEYLEN+1];
X   int i;
X
X   for( i = 0; (i<KEYLEN) && (*k!='\0'); ++k ) `123
X      if( alpha(*k) )
X         newk[i++] = tolower(*k);
X      `125
X   for( ; i<KEYLEN; ++i )
X      newk[i] = ' ';
X   newk[i] = '\0';
X
X   return newk;
X   `125
X
X
X/* take filename and see if it's in sys$help. If so return just the
Xname, else the full spec. */
Xstatic char *fudge_fn(fn)
Xchar *fn;
X`123
X   static char fn_last[FNLEN+1];
X   static char fn_fudged[FNLEN+1];
X
X   char fn1[FNLEN+1],fn2[FNLEN+1],name[FNLEN+1];
X   int junk;
X
X   FILE *f1,*f2;
X
X   if( strcmp(fn,fn_last)==0 )
X      return fn_fudged;
X
X   CHK_E( fjig(fn,name,FSCN$M_NAME,&junk) );
X   CHK_IF( opendef(&f1,name,"sys$help:.hlb",fn1,"r") ) `123  /* searchlist */
V      CHK_E( opendef(&f1,name,"sys$lclroot:[syshlp].hlb",fn1,"r") ); /* hack!
X */
X      `125;`009/* exit if not found */
X   fclose(f1);
X   CHK_E( fjig(fn1,fn1,
X    FSCN$M_DEVICE`124FSCN$M_DIRECTORY`124FSCN$M_NAME`124FSCN$M_TYPE,&junk) );
X
X   CHK_E( opendef(&f2,fn,"",fn2,"r") );`009`009/* exit if not found */
X   fclose(f2);
X   CHK_E( fjig(fn2,fn2,
X    FSCN$M_DEVICE`124FSCN$M_DIRECTORY`124FSCN$M_NAME`124FSCN$M_TYPE,&junk) );
X
X   if( strcmp(fn1,fn2)!=0 )
X      strcpy(fn_fudged,fn2);`009`009`009/* not in sys$help */
X   else
X      strcpy(fn_fudged,name);`009`009`009/* in sys$help */
X
X   strcpy(fn_last,fn);
X
X   return fn_fudged;
X   `125
X
X
X/* write out index entry */
Xstatic void write_index(f,k,fn,options,level)
XFILE *f;
Xchar *k;
Xchar *fn;
Xchar (*options)[MAXLEVELS+1][MAXLEN+1];
Xint level;
X`123
X   int i,j;
X
X   if( strlen(k)<MINKEY )
X      return;
X
X   k = fudge_key(k);
X   fn = fudge_fn(fn);
X
X   if( *k!=' ' ) `123`009`009`009/* may be all odd chars */
X      fprintf(f,"%-16s %s ",k,fn);
X
X      for( i = 1; i<=level; ++i )        /* output path */
X         fprintf(f,"%s ",(*options)[i]);
X      fprintf(f,"\n");
X      `125
X
X/* now check for prefixes, and do it all again... */
X   for( j = 0; pfx_list[j]!=0; ++j ) `123
X      if( isprefix(pfx_list[j],k) ) `123
X         k = fudge_key(k+strlen(pfx_list[j]));
X         if( *k!=' ' ) `123`009`009`009/* may be all odd chars */
X            fprintf(f,"%-16s %s ",k,fn);
X
X            for( i = 1; i<=level; ++i )        /* output path */
X               fprintf(f,"%s ",(*options)[i]);
X            fprintf(f,"\n");
X            `125
X         break;
X         `125
X      `125
X   `125
X
X
X/* read a line and skip to terminator */
Xstatic char *clib_read_line(f,a,len)
XFILE *f;
Xchar *a;
Xint len;
X`123
X   char c;
X   int n;
X
X   for( n = 0; n<len; ++n )  `123
X      c = getc(f);
X      if( c==EOF `124`124 c=='\n' )
X         break;
X      *a++ = c;
X      `125
X   *a++ = 0;
X
X   if( c!=EOF && c!='\n' )
X      eatline(f);
X
X   return c==EOF ? (char*)EOF : a;
X   `125
X
X
X/* lowercase a string */
Xstatic char *downcase(a)
Xchar *a;
X`123
X   char *a1;
X
X   for( a1 = a; *a1!='\0'; ++a1 )
X      *a1 = tolower(*a1);
X   return a;
X   `125
X
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X`123
X   FILE *in,*out;
X
X   if( argc!=3 )
X      exit(USER_FATAL`124USER_INHIBIT);
X
X   in = fopen(argv[1],"r");
X   if( in==0 ) `123
X      perror(argv[1]);
X      exit(USER_FATAL`124USER_INHIBIT);
X      `125
X
X   out= fopen(argv[2],"w");
X   if( out==0 ) `123
X      perror(argv[2]);
X      exit(USER_FATAL`124USER_INHIBIT);
X      `125
X
X   for( ;; ) `123
X      char *ptr[3];`009/* number, text, null */
X      int nargs;
X      char line[MAXLEN+1];
X      char fn[FNLEN+1];
X      int level;
X      char options[MAXLEVELS+1][MAXLEN+1];
X      char *k;
X
X      int err = clib_read_line(in,line,MAXLEN);
X      if( err==EOF )
X         break;
X
X      if( (line[0]==' ') `124`124 (line[0]=='\t') )
X         continue;
X      if( parse(line,&nargs,ptr,3) == -1 )
X         continue;`009/* too much */
X      if( nargs!=2 )
X         continue;`009/* too little? */
X
X      if( strcmp(ptr[0],"***")==0 ) `123`009/* a filename */
X         strncpy(fn,ptr[1],FNLEN);
X         continue;
X         `125
X
X      level = number(ptr[0]);
X      if( level>MAXLEVELS ) `123
X         printf("problem -- level %d too great\n",level);
X         printf("<%s> <%s>\n",ptr[0],ptr[1]);
X         exit(USER_FATAL`124USER_INHIBIT);
X         `125
X
X      if( level >= 0 ) `123`009`009/* a level number */
X         int i;
X         int bits = 0;
X
X         strcpy(options[level],ptr[1]);`009`009/* must fit */
X         downcase(options[level]);
X
X/* index under 'complete' key first, as this gets destroyed */
X         write_index(out,ptr[1],fn,&options[0][0],level);
X
X/* then under key separated by '_' characters (used as spaces in help index)
XThis destroys the key string.... */
X         for(;;) `123
X            char *c = strrchr(ptr[1],'_');
X            if( c==0 ) `123
X/* first component only if not whole */
X               if( bits )
X                  write_index(out,ptr[1],fn,&options[0][0],level);
X               break;
X               `125
X
X            *c = '\0';
X            if( alpha(*(c+1)) )
X               write_index(out,c+1,fn,&options[0][0],level);
X            bits = 1;
X            `125
X         `125
X      `125
X   `125
X
X
X
X/* this replaces spaces with EOS's, thereby destroying the input string */
Xstatic int parse(buf, argc, argv, len)
Xchar *buf, *argv[];
Xint *argc, len;
X`123
X   char *cp;
X
X   *argc = 0;
X   for (cp = buf; *cp;) `123
X      while (isspace(*cp)) cp++;
X      if (*cp == EOS) break;
X      *argv++ = cp; (*argc)++;
X      if (*argc >= len) return(-1);
X
X      while (*cp != EOS && !isspace(*cp)) cp++;
X      if (*cp == EOS) break;
X      *cp++ = EOS;
X      `125
X    *argv++ = 0;
X
X    return 0;
X   `125
X
X
X/* return -1 if not a decimal number */
Xstatic int number(a)
Xchar *a;
X`123
X   int n;
X
X   if( *a=='\0' )
X      return -1;
X
X   for( n = 0; *a!='\0'; ++a ) `123
X      if( (*a < '0') `124`124 (*a > '9') )
X         return -1;
X      n += (*a)-'0';
X      `125
X   return n;
X   `125
X
X
$ GOSUB UNPACK_FILE
$ FILE_IS = "MAN-K.COM"
$ CHECKSUM_IS = 1124295761
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X$ov='f$verify(0)
X$! suggest where to find help
X$! if p2 not empty, then queries whether to run help for that item.
X$!
X$! assumes key is 16 long
X$!
X$ p1 = f$edit(p1,"lowercase")
X$ orig_key = p1
X$! remove all non-alpha chars
X$ i = 0
X$ len = f$length(p1)
X$ key = ""
X$l1:
X$ if i .gt. len then goto done_l1
X$ c = f$extract(i,1,p1)
X$ if -
X   ("a" .les. c .and. c .les. "z") .or. -
X   ("0" .les. c .and. c .les. "9") .or. -
X   (c .eqs. "$") .or. (c .eqs. "_") -
X then key = key + c
X$ i = i+1
X$ goto l1
X$done_l1:
X$!
X$ where = f$element(0,"]",f$environment("procedure")) + "]"
X$ define/nolog man_k$_where 'where',sys$help:,ut:,util:,[]
X$ open/read input man_k$_where:index.dat
X$ deas man_k$_where
X$!
X$ total = 0
X$ last_file = "`126"
X$!
X$ lookup_key = f$fao("!16AS",key)
X$!
X$! this takes a given key, and prints all references to it
X$! and optionally runs help to print that text.
X$ read input/key="''lookup_key'"/err=done line
X$loop:
X$ k1 = f$extract(0,16,line)
X$ if k1 .nes. lookup_key then goto done
X$ line = line - k1 - " "
X$ file = f$element(0," ",line)
X$ line = line - file
X$!
X$ if p2 .nes. "" then goto print_help
X$ if file .nes. last_file then -
X  write sys$output "$ help/libr=''file'"
X$ last_file = file
X$ write sys$output line
X$ goto do_total
X$!
X$print_help:
X$prompt:
X$ read sys$command/prompt="$ help/libr=''file' -`013`010 ''line'? [y/n] " -
X /end=done yesno
X$ yesno = f$edit(yesno,"lowercase")
X$ if yesno .eqs. "" then yesno = "y"
X$ if yesno .nes. "y" .and. yesno .nes. "n" then goto prompt
X$ if yesno .eqs. "n" then goto do_total
X$ help /libr='file' 'line'
X$!
X$do_total:
X$ total = total + 1
X$ read input /end=done line
X$ goto loop
X$ done:
X$!
X$exit:
X$! close input
X$ key = f$edit(orig_key,"trim")
X$ if total .eq. 0 then -
X write sys$output "sorry, no help on ""''key'"""
X$ov=f$verify(ov)
$ GOSUB UNPACK_FILE
$ FILE_IS = "MISC.H"
$ CHECKSUM_IS = 826025349
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/*$$++ misc.h`009miscellaneous macros for C programs
X
Xmaths macros:-
X`009ABS(x)
X`009SIGN(x)
X`009MAX(x,y)
X`009MIN(x,y)
X`009CLIP(x,xmin,xmax)`009boundary operator
X`009ROUND(x)
X`009PI
X`009TWOPI
X`009PI2
X`009SQ(x)`009`009`009square operator
X`009FLOAT(i)
X`009INT(i)
X`009DOUBLE(i)
X
X
Xcheck system error status for succes bit and take action (x will normally
Xbe a system service or library call):-
X`009CHK_R(x)`009`009return error to caller
X`009CHK_E(x)`009`009exit on error, returning error code to dcl
X`009CHK_S(x)`009`009signal error with lib$signal
V`009CHK_IF(x) `123...`125`009`009execute following compound statement on erro
Xr
X`009CHK_IFOK(x) `123...`125`009" " " if no error
X`009IS_ERROR(x)`009`009set if x denotes VMS error condition
X
Xlogical bits
X`009TRUE
X`009FALSE
X`009BOOLEAN
X
Xerror code twiddling
X`009FATAL(x)`009`009make fatal code
X`009SIG_TO_RET;`009`009convert any succeeding signal to returned value
X`009USER_FATAL`009`009error codes for user progs
X`009USER_ERROR
X`009USER_WARNING
X`009USER_SUCCESS
X`009USER_INHIBIT`009`009(error msg inhibit bit)
X
Xuseful string lengths (excl trailing NULL)
X`009FNLEN`009`009`009filename
X`009SIMSEQLEN`009`009simseq ident length
X`009DAYTIMELEN`009`009daytime() buffer length
X
Xloop control
X`009EXITIF(cond)`009`009if(cond)break;
X
Xmodule identification
X`009IDENT(module,version)`009module must be unique global name, version
X`009`009`009`009is a quoted char string
X
Xothers
X`009EOS`009`009`009end-of-string character
X`009NULL`009`009`009null pointer
X
X$$--*/
X
X
X/* maths macros */
X#define ABS(x) ((x)<0?-(x):(x))
X#define SIGN(x) ((x)>=0?1:-1)
X#define MAX(x,y) ((x)<(y)?(y):(x))
X#define MIN(x,y) ((x)<(y)?(x):(y))
X#define CLIP(x,xmin,xmax) MIN(MAX((x),(xmin)),(xmax))
X#define ROUND(x) ((int)((x)+0.5))
X#define PI 3.141592653589793
X#define TWOPI (2.0*PI)
X#define PI2 (PI*0.5)
X#define SQ(x) ((x)*(x))
X#define FLOAT(i) ((float)(i))
X#define INT(i) ((int)(i))
X#define DOUBLE(i) ((double)(i))
X
X/* system status return error check */
X#define CHK_R(x) `123int e=(x);if((e&1)==0)return(e);`125
X#define CHK_E(x) `123int e=(x);if((e&1)==0)exit(e);`125
X#define CHK_S(x) `123int e=(x);if((e&1)==0)`123lib$signal(e);`125`125
X#define CHK_IF(x) if(((x)&1)==0)
X#define CHK_IFOK(x) if(((x)&1)!=0)
X#define IS_ERROR(x) (((x)&1)==0)
X
X/* logical bits */
X#define TRUE 1
X#define FALSE 0
X#define BOOLEAN short int
X
X/* error code twiddling */
X#define FATAL(x) ((x)&`12607`12404)
V#define SIG_TO_RET `123extern lib$sig_to_ret();lib$establish(&lib$sig_to_ret)
X;`125
Xglobalref user$_severe;
X#define USER_FATAL ((int)(&user$_severe))`009`009/* these are temp only */
Xglobalref user$_error;
X#define USER_ERROR ((int)(&user$_error))
Xglobalref user$_warning;
X#define USER_WARNING ((int)(&user$_warning))
Xglobalref user$_normal;
X#define USER_SUCCESS ((int)(&user$_normal))
X#define USER_INHIBIT 0x10000000
X
X
X/* useful string lengths (excl trailing null) */
X#define FNLEN 255
X#define DEVLEN 64
X#define NODELEN 64`009`009/* CHECK THIS!!*/
X#define SIMSEQLEN 9
X#define DAYTIMELEN 24
X
X
X/* loop control */
X#define EXITIF(x) if(x)break;
X
X
X/* module identification -- use with ident() procedure */
V#define IDENT(prog,id) readonly globaldef `123"$$$$$$$$$$$$$$identifications_
Xb"`125 char* prog = id;
X
X/* module initialisation -- use with init_all() procedure */
V#define INIT_ALL(prog,rtne) extern void rtne(); readonly globaldef `123"$$$$$
X$$$$$$$$$initialisations_b"`125 void (*prog)()=rtne;
X
X
X/* others */
X#define EOS '\0'
X#define NULL 0
X
X/* terminal characteristics buffer */
X
Xtypedef struct tt_characteristics `123
X/* this bit is like the qio requires (ie don't change it!)... */
X   char tt_class;`009`009      /* always DC$_TERM */
X   char tt_type;
X   short tt_buflen;`009`009      /* buffer length */`009
X   long tt_basic;`009`009      /* TT$M_xxx bits (top byte is tt_page) */
X   long tt_ext;`009`009`009      /* TT2$M_xxx bits */
X/* ... while this bit is private */
X   char tt_rxs,tt_txs;`009`009      /* line speeds (tt_rxs always there) */
X   char tt_crf,tt_lff;`009`009      /* cr, lf fill counts */
X   char tt_parity;`009`009      /* parity flags (not used) */
X   char tt_page;`009`009      /* page length */
X   `125 TT_CHARACTERISTICS;
X
X
X
X/* ast_routine definition */
Xtypedef void (*AST_RTNE)();
X
X
X/* standard vms item list */
Xstruct vms_item_list `123
X   short buflen;
X   short code;
X   char *buffer;
X   short *retlen;
X   `125;
X
$ GOSUB UNPACK_FILE
$ FILE_IS = "OPENDEF.C"
$ CHECKSUM_IS = 503806484
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/*$$++ opendef.c`009x0.0`009mas 29-oct-85
X
Xapply defaults to filename and open it, returning the C file pointer,
Xand the expanded filename.
X
Xcalling sequence:-
Xint err;
XFILE *f;`009C file pointer returned if successful
Xchar fn[];`009supplied filename
Xchar fnd[];`009filename defaults
Xchar fno[FNLEN+1];`009returned expanded filename string (if successful)
Xchar mode[];`009access mode (for fopen()) - "r", "w", etc
Xerr = opendef(&f,fn,fnd,mode);
X
Xerror returns are any system/rms errors.
X
X$$--*/
X
X#include stdio
X#include <misc.h>
X#include ssdef
X#include errno
X
X
Xopendef(f,fn,fnd,fno,mode)
XFILE **f;
Xchar *fn,*fnd;
Xchar *fno;
Xchar *mode;
X`123
X   FILE *ff;
X
X   CHK_R( file_defaults(fn,fnd,fno,0) ); /* returns any syntax errors */
X
X   if( (ff = fopen(fno,mode))==NULL )
X      return vaxc$errno;`009`009/* prob rms error code */
X   else `123
X      *f = ff;`009`009`009`009/* all ok */
X      return SS$_NORMAL;
X      `125
X   `125
$ GOSUB UNPACK_FILE
$ FILE_IS = "USER_ERRORS.MSG"
$ CHECKSUM_IS = 2118339779
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X.title usercode_msg
X.facility user,2043/prefix=user$_
X.ident 'x0.0'
X
X.severity success
Xnormal`009`009<normal successful completion>
X
X.severity warning
Xwarning`009`009<warning of possible errors>
X
X.severity error
Xerror`009`009<error state>
X
X.severity severe
Xsevere`009`009<severe error>
X
X.end
$ GOSUB UNPACK_FILE
$ EXIT
--
Regards.    Mike Scott       STL, London Road, Harlow, Essex  CM17 9NA, UK
scott@stl.stc.co.uk <or> ...uunet!mcvax!ukc!stl!scott <or>
PSI%234237100122::SCOTT        phone +44-279-29531 xtn 3133.

