Google
 

Trailing-Edge - PDP-10 Archives - LCG_Integration_Tools_Clearinghouse_T20_v7_30Apr86 - tools/recog3/helpfs.mem
There are 3 other files named helpfs.mem in the archive. Click here to see a list.


                            VMS RECOGNITION PACKAGE
                       (INCREMENTAL HELP AND RECOGNITION)
                            FUNCTIONAL SPECIFICATION
                                   revision 3











1.0  PRODUCT OVERVIEW

The purpose of this product is to provide a tool  for  VMS  users
that  will  allow  them  to  write  code  that  gets input from a
terminal in "help mode".  By "help mode" we mean that the  person
typing  in  the  input  can  get incremental help and can perform
command recognition as he types.

     1.  Incremental help refers to the ability to type a  <HELP>
         key  in  the  middle  of  a  command line and get a help
         message immediately that explains what kind of input  is
         expected.   The  system  then retypes the command up the
         point of interruption and allows the  user  to  continue
         typing the rest of the command.

     2.  Command recognition (also known as  command  completion)
         refers  to  the ability to type a <RECOGNIZE> key in the
         middle of a command line and have the system complete  a
         partially entered field for you automatically.

EXAMPLE 1:

The user types

$ SET <HELP>

and the result he sees on the terminal is:

$ SET ?        Keyword, one of the following
CARD__READER    [NO]CONTROL__Y    DEFAULT         HOST
MAGTAPE        MESSAGE          [NO]ON          PASSWORD
PROCESS        PROTECTION       QUEUE           RMS__DEFAULT
TERMINAL       [NO]VERIFY       WORKING__SET
$ SET

The system tells the user what his legal options are to  the  SET
command and then brings him back to the space after the word SET.
                                                                          Page 2


EXAMPLE 2:

The user types:

$ SET PR<HELP>

and the result he sees on the terminal is:

$ SET PR?     Keyword, one of the following:
PROCESS       PROTECTION
$ SET PR

and he is left positioned immediately after the "PR".  He is told
that  there  are  only  two  keywords that begin with the letters
"PR".

EXAMPLE 3:

The user types

$ INIT<RECOGNIZE>

and the result he sees is:

$ INITIALIZE (DEVICE)

The system has completed the word "INIT"  to  "INITIALIZE"  since
there is only one valid command beginning with the letters "INIT"
and then displays the guideword  "(DEVICE)"  reminding  the  user
what  field  is  to  be  typed  next.  He is then left positioned
immediately after the space after the guideword ready to continue
typing.

EXAMPLE 4:

The user types

$ FORTRAN INV<RECOGNIZE>

and the result he sees is

$ FORTRAN INVERT.FOR;23

since there was only one FORTRAN file in  the  user's  area  that
began  with  the  letters "INV".  He is left positioned after the
space after the filespec, ready to type <RETURN> or  to  continue
entering more data (such as qualifiers).

Note that the routines provided by this product do not constitute
a  general  "parser",  such  as  TPARSE,  but  rather  are  to be
considered a low level tool (down near the QIO level) that can be
used  by  general  parsers  to  parse  primitive elements such as
keywords, numbers, or filespecifications.  The  user  or  general
                                                                          Page 3


parser  would  then write code to combine these primitive parsing
tasks into more complex parsing tasks.

This project does not include interfacing these routines into DCL
or other VMS utilities.



2.0  PRODUCT GOALS

2.1  Background

Most of the code to handle incremental help and  recognition  had
already been written.  It was embedded in SCP, the command parser
for the DECset Integrated Publishing System which  is  a  layered
product  that  runs  under VMS.  This code shipped with DECset V1
and is deeply embedded in the bowels of SCP.  It was the  purpose
of  this  project to remove that code from SCP and turn it into a
nicely packaged set of RTL routines that would  be  user-callable
and easy to use.




2.1.1  Demos -

There are now several demo programs running under VMS  that  have
already  interfaced  to the recognition package.  The easiest one
to get hold of is WHAT.EXE.  The program WHAT.EXE is  a  midnight
hack  that lets you monitor various pieces of system information,
such as processes, devices, open files, mounted volumes,  network
logical  links,  etc.   WHAT  has  a  command mode (just type any
character to get into command mode).   While  entering  commands,
you  may type TAB and "?" to see recognition and incremental help
in action.  Keep in mind that WHAT  is  a  display  program  that
manages  the  screen,  so  that  the  user  interface is slightly
different from what you would get  with  a  normal  program  that
doesn't  do  screen  management.   This is because WHAT traps the
output from the recognition package and places it on  the  screen
where it would like to see it go.




2.2  Specific Goals


High Priority Goals:

     1.  The interface shall be general enough  that  it  can  be
         re-integrated with DECset.
                                                                          Page 4


     2.  The code shall be general enough that it can support the
         DCL  command  language,  should  the VMS group decide to
         integrate this code into DCL.

     3.  Should DCL decide to use these routines,  then  the  DCL
         user  interface  shall  looks  exactly  as it looks now,
         provided  that  the  user  never  types  the  <HELP>  or
         <RECOGNIZE> keys.

     4.  The code should run as quickly as possible, putting  the
         least  amount  of  strain  on  VMS  as possible.  (It is
         expected that sometime in the future, this code will  be
         frequently invoked.)

     5.  The code must react gracefully to CTRL/C and CTRL/Y.  It
         must  not assume that the image will exit on CTRL/Y.  It
         must establish condition handlers,  when  necessary,  to
         react  to an UNWIND signal and to cleanly deallocate any
         virtual memory that has been allocated, close  any  open
         files, release channels, etc.

     6.  The code shall be general enough to handle  the  parsing
         needs  of  most  VMS-supplied  utilities  (such as MAIL,
         DEBUG, SYSGEN, SDA, AUTHORIZE, etc.).

     7.  The code shall be easily invoked from  either  MACRO  or
         BLISS.

     8.  The code shall follow the practices set forth in the VMS
         Guide to Writing Modular Library Routines.

Medium Priority Goals:

     1.  The code shall be general enough to handle  the  parsing
         needs of most user programs.

     2.  To a user at a terminal using this  facility,  the  user
         interface  should look similar to the corresponding user
         interface   on   TOPS-20   (except   with   regard    to
         functionality    explicity    excluded    in   the   VMS
         implementation).

     3.  It shall be as easy as possible  to  interface  to  this
         code  (subject  to the constraint that the high-priority
         goals must be met).

     4.  Any time the code wants a user-specified descriptor, the
         code   shall  accept  any  kind  of  string  descriptor,
         including dynamic string descriptors and varying  string
         descriptors.    The   code   shall  not  assume  that  a
         descriptor fits in a quadword.
                                                                          Page 5


     5.  The code shall be reentrant.

Low Priority Goals (but goals nonetheless):

     1.  To  a  programmer  using  this  facility,  the   program
         interface  should  look  similar  to  the  corresponding
         program interface on TOPS-20 (the COMND JSYS),  wherever
         this  is practical.  <For those people familiar with the
         TOPS-20 implementation, I include notes enclosed  within
         angle  brackets  throughout this document describing the
         correspondence  between  this  implementation  and   the
         TOPS-20 implementation.>

     2.  It should be easy to invoke this  code  from  high-level
         languages.  (This goal may not be easy to attain.)

     3.  The code should work with block mode terminals  that  do
         their   own   handling   of  rubouts  and  other  action
         characters.   (This  is  under  our  control  for  VT173
         terminals  used with DECset, but may not be a realizable
         goal for all block mode terminals supported by  VMS,  if
         any.)

     4.  The programmer should not have to  know  anything  about
         writing condition handlers to do normal things.

     5.  The system should provide as few limits as  possible  on
         the  programmer.   For  example, LIB$GET_INPUT currently
         will not let you read a record from  SYS$INPUT  that  is
         greater  than 256 bytes long if you use a dynamic string
         descriptor.  My code, when  possible,  shall  impose  no
         limits  on the programmer.  He should be able to write a
         program  that  will  take  an  arbitrarily  long   input
         command,  provided  that  he  supplies  a dynamic string
         descriptor to hold the command and that  the  user  does
         not  run  out  of any process quota or exceed any sysgen
         parameter.

     6.  The user shall not get  errors  during  the  recognition
         process.  For example, if while trying to do recognition
         on a field, some system service  returns  with  a  quota
         exceeded  error, the response to the recognition request
         will be a  beep,  meaning  that  the  system  could  not
         perform  recognition  on  that  field  and  the user may
         continue typing.  The response  shall  not  be  a  quota
         exceeded error message.

Specific features that are goals:

     1.  <HELP> key
                                                                          Page 6


     2.  <RECOGNIZE> key

     3.  Guidewords

     4.  Prompting




2.3  Non Goals

The following features are available under TOPS-20  but  are  not
committed  for this product at this time, however hooks are being
left in the code so that these features can be added at  a  later
date:

     1.  Retype of previous line up to  point  of  error.   Under
         TOPS-20, typing CTRL/H at the beginning of a line (after
         an error has occured) causes the system to redisplay the
         previous  command  line,  up  to the point in error, and
         allow the user to continue typing from that point.

     2.  Partial Field recognition.  Under TOPS-20, typing CTRL/F
         in the middle of a file specification causes the current
         subfield of the file specification to be completed,  but
         not  the  entire  specification.   For  example,  typing
         CTRL/F in the middle of a file name would  complete  the
         file  name  but  would  not complete the file type, even
         though a unique (or default) file  type  and/or  version
         number can be determined.

     3.  Automatic   indirect   command   files.    The   TOPS-20
         implementation  handles  "@filespecification" constructs
         automatically.  This is not planned  for  this  release.
         Indirect  command  files  may  still be implemented by a
         user program by specifically allowing  for  this  syntax
         and  then  doing  the  appropriate  thing (as opposed to
         having it happen automatically).

The current code uses a "fake terminal  service"  to  get  around
certain  deficiencies  in  the VMS V  terminal driver.  This code
does it's own input line editing by waking up any time  the  user
types  rubout, CTRL/R or CTRL/U.  This is very inefficient.  This
will be fixed  for  V4  when  better  terminal  support  will  be
available.   This  will entail one change:  the current code uses
CTRL/W to mean rub-word.  Under V4, LINE FEED is used to mean rub
word,   so  this  code  will  be  changed  to  conform  with  VMS
conventions.

Hooks are being left for the following features, but they are not
committed for the initial release:
                                                                          Page 7


     1.  Asynchronous operation and the ability to parse commands
         from multiple terminals simultaneously.

     2.  The ability to read a help library from the middle of  a
         command to aid in the incremental help process.

     3.  The ability to conveniently use these  routines  from  a
         high  level  language.   The reason for this is the same
         reason that RMS, Cross Reference Utilities,  and  TPARSE
         can  not be conveniently used from high level languages.
         Many high level languages,  like  FORTRAN,  just  cannot
         conveniently  create and manipulate the table structures
         needed to use these routines.

The following features are not being  implemented  at  this  time
because  VMS  provides no clean user-interface for getting at the
appropriate data.

     1.  The ability to recognize node names.

     2.  The ability to recognize device names.

     3.  The ability to recognize logical names.

     4.  The ability to  recognize  topics  from  HELP  libraries
         (except perhaps for the top level topic).

     5.  The ability to recognize account names.

     6.  The ability to recognize usernames.

Specific non-goals:

     1.  It is not a goal of this product to provide users with a
         general-purpose high-level parser.

     2.  It is not a goal of this project to  actually  interface
         these  facilities  into various VMS utilities, but it is
         hoped that the VMS  group  will  decide  to  phase  this
         product  into  their  utilities.   We  have had informal
         talks  with  the  VMS  group,  but  they  have  made  no
         commitment at this time.

     3.  It is not a goal of this product to write  the  code  in
         transportable BLISS.
                                                                          Page 8


2.3.1  STATUS -

The code is reasonably complete (for VMS V3) and has already been
used  in  several  demo  programs  and  some  in-house  products.
however, I have had no luck in submitting




3.0  FUNCTIONAL DEFINITION

There are two main interfaces that need to be described, the user
interface and the programmer interface.

Part A describes the user interface which is what a terminal user
sees when he is typing input to a program that makes use of these
facilities.

Part B describes the  programmer  interface  which  includes  the
usage,  calling  sequences,  macros, and table formats associated
with the RTL routines that one must call  in  order  to  write  a
program that makes use of these facilities.

Note that there are really two types of users  of  this  package.
There  is  the  person  that  writes  code that interfaces to the
recognition package.  We shall  refer  to  this  person  as  "the
programmer"  throughout this spec.  There is also the person that
sits at a keyboard and enters commands  to  a  program  that  was
coded  to  use  the  recognition package.  We shall refer to this
person as "the user" throughout this spec.

Throughout this spec, we give examples of command lines that come
from  DCL  and  other  VMS utilities.  This in no way is meant to
imply that the recognition package is being interfaced  into  DCL
at  this time;  we use DCL commands as examples because they will
be familiar to the readers of this spec.
                                                                          Page 9


                          PART A - THE USER INTERFACE




3.1  Keys Used For Help And Recognition

The keys chosen to do  help  and  recognition  are  "?"  and  TAB
respectively.

"?" has long  been  reserved  by  the  Digital  Command  Language
Standard for this purpose.

The reason that ESCAPE was not  chosen  to  do  recognition,  was
because  the  VMS  group  and  the terminals group felt that they
wanted to reserve  ESCAPE  for  the  purpose  of  sending  escape
sequences  to  the  host.  In V4 of VMS, the terminal driver will
normally use  escape  sequences  to  handle  input  command  line
editing.  Also, new terminals are being built that have no ESCAPE
key.

The key used to do recognition must be  easy  to  type  since  it
turns out that this key will be typed a lot, once people get used
to doing recognition.  In fact, it will probably  be  typed  even
more  than  "space".   The reason for this is that by ending each
field typed by <RECOGNIZE> rather than by <SPACE>, the user  gets
an  immediate feedback about whether what he has typed is correct
or not.  In this way, he doesn't have  to  wait  until  he  types
carriage  return at the end of the command to see if he gets some
sort of error message.  This is not  just  a  feature  that  only
novices will use - even experts find it very convenient.

The <TAB> key turns out to be  very  easy  to  touch-type;   even
easier than the ESCAPE key.



3.2  Other Keys Used

In the current implementation (using my  fake  terminal  service)
the  CTRL/W  key is used to mean "rub word".  This will change to
LINE FEED once the recognition package is upgraded for  use  with
V4  of  VMS.   LINE  FEED  is  the  character V4 is using to mean
rub-word.



3.3  Incremental Help

At any time while entering a command, the user can  type  "?"  to
find  out  what  type  of field the computer is expecting at that
point.  He will  get  back  either  a  canned  message  from  the
recognition  package  (such  as  "filespec"  or  "number")  or  a
                                                                         Page 10


tailored message if the programmer  has  supplied  one  (such  as
"FORTRAN source file" or "number of copies to print").

If the current field is an explicit quoted string, then  the  "?"
character  is  a valid data character and can be entered directly
into the command line.  No incremental help occurs.  This  allows
a user to type a command such as

MAIL (FILE) ABC.TXT (TO) JOE /SUBJECT="How are you?"

and have the "?" be used as valid text in the subject string.

If the current field is a keyword field  (including  a  qualifier
field),  then the incremental help message will give the user the
valid list of keywords (or qualifiers) that can be typed at  that
time.  All valid keywords will be listed, although the programmer
has the option of suppressing selected  keywords  from  the  help
display  (such  as  obsolete  keywords) if desired.  If a partial
keyword has already been entered,  then  the  system  only  lists
those keywords that begin with the letters typed.  If the keyword
or qualifier takes a value, the system will display an "=" at the
end  of  the  keyword in the help frame to remind the user that a
value can be supplied.  If the keyword is negatable, and "?"  was
typed  at the beginning of the field, the keyword will be printed
with  the  negation  prefix  enclosed  in  square  brackets,  e.g
/[NO]LIST reminding the user that the keyword can be negated.




3.4  Recognition

If TAB is typed at the beginning of a  field,  then  the  default
value for that field will be recognized, if there was one.  If no
default value was specified by the programmer, or if TAB is typed
in  the  middle of a field, normal recognition as described below
is attempted.

When TAB is typed, the system looks at the partial field  already
entered  by  the  user  and tries to complete it.  If the current
field is a keyword field (including a qualifier  field),  and  if
there  is  a unique qualifier beginning with the letters typed so
far, then the remainder of the keyword is recognized.   If  there
are  multiple  keywords  beginning with the letters typed so far,
the system recognizes as many as it can and  then  beeps  at  the
user telling him that further recognition was not possible.

If the current field is a filespec field, the system will try  to
complete this field too.  No attempt will be made to check to see
if a name is a node name, logical name, or device name;  the name
will  be  assumed  to  be  a filename unless the syntax precludes
this.  Recognition can occur within the  file  name,  file  type,
file  version, or directory portion of the filespecification.  If
                                                                         Page 11


multiple  choices  are  possible,  the  system  will  attempt  to
complete  as much of the partial filespecification as it can, and
then  it  will  beep  at  the  user  telling  him  that   further
recognition was not possible.  After completing a directory name,
the closing "]" (or ">") will be  recognized,  unless  there  are
subdirectories  present  for  that  directory,  in which case the
system will beep indicating that the user may either type "]"  or
"." to specify a subdirectory.

Note that the  programmer  is  permitted  to  include  a  default
filespec  and  a  related  filespec when coding a filespec parse.
These  will  be  taken   into   consideration   when   performing
recognition.   For  example, suppose a default filespec of ".FOR"
is associated with the filespec parse of the first  parameter  in
the DCL FORTRAN command.  Then if a user types FORTRAN A and then
types <RECOGNIZE> and he has only one FORTRAN file beginning with
the  letter  "A", that filename will be recognized, including the
filetype and the latest version number.  This is true even though
he  might have some .OBJ or .EXE files in his area also beginning
with the letter "A".  If the default filetype of ".FOR"  had  not
been  specified  to  the  recognition package, then when the user
typed <RECOGNIZE>, the system  would  complete  the  filename  to
"ABCDEF.",  say,  and  then  beep him since the filespec could be
completed with .OBJ or .FOR.



3.5  Guidewords

The  programmer  can  specify  guidewords  for  any  field.    If
recognition  is  successful  on the previous field, the guideword
for the next field will be displayed in parentheses, as a helpful
reminder  to  the  user of what is expected next.  The guidewords
for a command can be designed to make the command read more  like
English,  rather than computerese.  The guideword can be typed in
directly by the user, but never needs to be typed in.   If  typed
in,  it  must  be  correct.   Help  and recognition work within a
guideword field.



3.6  Choices For Fields

The programmer can specify that there is a list of choices for  a
given  field, for example, the field can be either a keyword or a
number.  In such cases, when the user types "?", he will be  told
about each possible choice.  The choices will be separated by the
word "or" and will be listed in the order that  the  system  will
attempt  matching.   Note  that  if there is a set of choices and
recongition is  requested  by  the  user,  the  recognition  will
proceed choice by choice.  If partial recognition occurs with any
choice, that will determine which characters get recognized.
                                                                         Page 12


3.7  Miscellaneous

If help or recognition is requested by the user  and  the  system
cannot  figure  out  what  type of field is being entered because
some earlier part of the command line is  totally  erroneous,  an
immediate  error  message  will result.  For example, if the user
types SHOW PRICESS /Q?  wanting to know about all the  qualifiers
beginning  with  the  letter  Q  in the SHOW PROCESS command, the
system will not know that  he  wants  the  SHOW  PROCESS  command
because  the  word  "PROCESS" was misspelled.  An immediate error
message results.  In all other cases, if any sort of error occurs
during  the  recognition process itself, no error message will be
given.  The system will mereley beep at the user telling him that
recognition  could  not  be  accomplished.   For example, if when
trying to recognize a filename, the  recognition  package  should
get  a  protection  violation  reading a directory, or run out of
quota, or some other system type error, this error  will  not  be
printed,  but  the package will beep at the user telling him that
it was unable to recognize the filename.
                                                                         Page 13


                       PART B - THE PROGRAMMER INTERFACE




3.7.1  OVERVIEW -

The parsing routines are very closely tied in with  the  terminal
service.   For  example,  the  interface  could  not  be that the
programmer calls LIB$GET_INPUT to read a command  line  and  then
calls  the  recognition  package to parse that line;  for by that
time it is too late.  The <HELP> and <RECOGNIZE> characters  must
be  processed  by  the routine that is reading the input from the
terminal.  In that sense, these routines can be considered to  be
a  replacement  for  the  standard LIB$GET_INPUT routine, or more
generally, a replacement for the $INPUT macro call.




3.7.2  Background Information -

We have seen that the parsing routines must be very closely  tied
in with the terminal input service.  If in the middle of typing a
filespecification, in the middle of  a  command  line,  the  user
types  <RECOGNIZE>, the code must know that a filespec is desired
by the program, so that filespec-recognition  can  occur.   Thus,
the programmer's parsing routine must be invoked at this point.

Consider the following scenario:

A user begins typing a command line, say

$ DELETE ABCD

and then types <RECOGNIZE>.  The  program's  parsing  routine  is
called.   It specifies that the first parameter in the command is
to be a keyword.  The  recognition  package  then  hands  it  the
keyword  "DELETE"  and  the  user's program notes the fact that a
DELETE command has been entered, say by setting  a  bit  in  some
table.   Then  the program's parsing routine says that it wants a
filespecification.   All  well  and  good.   We  see  a   partial
filespecification ("ABCD") and go to try to complete it.  Suppose
partial completion occurs;   we  type  out  "E."  and  leave  the
terminal looking like

$ DELETE ABCDE.

and we await more input, allowing the user to type in a filetype.
At  this  point,  instead  of  typing  further,  the user deletes
characters in his command line back to the "D" at  the  beginning
and  then  types  "IR",  having  changed  his  mind about doing a
DELETE.  He now wishes to issue the  DIRECTORY  command  instead.
                                                                         Page 14


His terminal looks like:

$ DIR

and he types <RECOGNIZE> expecting  "DIR"  to  get  completed  to
"DIRECTORY".   At  this point, we must again invoke the program's
parsing routine to find out  what  kind  of  field  is  expected.
However,  when we last left the program's parsing routine, it was
waiting for a return from a request to read  a  filespecification
from the terminal, preparatory to performing the DELETE command.

The way we handle this is by the recognition package establishing
a condition handler (behind the programmer's back) and signalling
HLP$_REPARSE when a reparse is necessary.  Our condition  handler
catches  this  signal  and  performs  an  unwind;  then calls the
program's parsing routine over again from the start.   With  this
scheme,  it  is not necessary for the programmer to actually have
to establish any condition handlers of his own.  The programmer's
parsing  routine  must be written so that it can be entered again
should a  reparse  of  the  line  be  necessary.   Normally  this
involves  no extra work on the part of the programmer.  He should
initialize all variables used (not assume they are initially  0).
In  some cases, the programmer may have to test a first-time flag
or some other flag.  For example, if the parsing routine needs to
allocate  virtual  memory,  it  should  first  test to see if the
virtual memory has already been allocated, and only if it has not
yet been allocated, should it allocate it.

In extreme cases, the programmer's parsing routine  may  have  to
establish  a  condition  handler  to  clean up on an unwind;  for
example, if the parsing routine must open a file for some obscure
reason  in the middle of parsing the command line, then it should
establish a condition handler to close the file should an  unwind
occur.



3.7.3  The Programmer Interface -

Two interfaces have been proposed, the general interface and  the
simple  interface.   The  general  programmer  interface  is  the
interface that has been coded and is general enough to handle all
envisioned  parsing  needs.   The simple programmer interface was
envisioned to be simpler to use than the general interface and is
still in the design stage.
                                                                         Page 15


3.7.4  The General Programmer Interface. -

The  general  programmer  interface  consists  of  two  routines,
LIB$PARSE_LINE and LIB$PARSE_FIELD.  LIB$PARSE_LINE initiates the
command line parse.  There are  many  options,  so  it  would  be
inconvenient  to  specify  them  all as actual parameters in this
call.  They are specified in a data block and the address of  the
data  block  is  passed  to LIB$PARSE_LINE.  (Although there is a
large number of options, only a small number  of  them  are  ever
needed, except for incredibly complex programs, such as DCL which
might need about half these options).

The control structure passed  to  LIB$PARSE_LINE  is  called  the
Command  Access  Block  (CAB).   <This corresponds to the command
state table in the TOPS-20 implementation.>  The  format  of  the
call to LIB$PARSE_LINE is:

ret-status.wlc.v =
LIB$PARSE_LINE(cab-adr.ma.v,parse-rtn.flc.rp,parse-arg.rlu.v)

where

cab-adr        is the address of the CAB

parse-rtn      is the address of the  programmer's  routine  that
               will  perform  the  parsing of the line being read
               in.

parse-arg      is an arbitrary longword value  that  gets  passed
               along  to  the programmer's parsing routine.  This
               is an optional argument.  If not  specified,  a  0
               will   be   passed  to  the  programmer's  parsing
               routine.

The programmer specifies the buffer that is to receive  the  line
read in, the prompt string, and other things related to the parse
request, by placing this information in the CAB prior to  issuing
this  call.   To  make  it  easy  to  do  this,  there is a macro
interface to the CAB.  A typical initialization of  a  CAB  might
look like:

$CAB(BUF=IN_BUF,PMT=%ASCID 'FLX> ',OPT=<CVT,COM>)

which specifies the input buffer to receive the command  line,  a
prompt  string  to  be  used ("FLX>"), and two options (CVT means
convert lower case to upper case and COM means allow "!" to  mean
end-of-line comment).

The programmer's parsing routine is called with one argument.

This  argument  is  the   value   of   the   programmer-specified
parse-argument.   This allows the programmer to pass arguments to
his routine.  If more than 32 bits worth of information needs  to
                                                                         Page 16


be  passed,  the  programmer  can  pass the address of a block of
information.  In case the programmer has more than  one  CAB,  he
could specify the address of the CAB as this argument.

It was originally  proposed  that  another  argument  be  passed;
telling  the  parsing  routine  whether this is a reparse or not.
However, it was decided that this is not necessary,  because  the
programmer can set up and test a first-time flag here if he needs
to know whether or not this is a reparse.  (A reparse occurs when
the  recognition  package  calls the programmer's parsing routine
again, after an unwind,  indicating  that  the  user  rubbed  out
fields  that  had  previously  been  parsed,  and  that it is now
necessary for the programmer to parse the line again.)

LIB$PARSE_FIELD is then called once for each field to  be  parsed
by the programmer's parsing routine.  This routine must be passed
the address of a Parameter Block (PAB) containing all the details
about the field to be parsed.

The format of this call is

ret-status.wlc.v = LIB$PARSE_FIELD(pab-adr.ma.v)

where pab-adr is the address of the PAB.

The structure names CAB and PAT have been "signed out"  from  the
VMS  group.   (Originally,  the names CAB and PAB were requested,
however, the name PAB turned out to be in use, so PAT was  chosen
instead.   However,  the  code  currently  uses the prefix "PAB".
Should the VMS group ever accept this code, it will  most  likely
change to PAT.) The prefix "HLP" that you will see below is known
to already be in use and  will  have  to  change  so  as  not  to
conflict  with  other  symbols  appearing  in STARLET;  however I
haven't yet signed out an appropriate replacement prefix.



3.7.5  EXAMPLE -

Before  we  go  into  the  nitty-gritty  of  all  the  bits   and
structures, a simple example would be useful.

Suppose a user  program  wants  to  parse  a  command  line  that
consists  of  a keyword followed by a number.  The valid keywords
are "STOP", "GO", "CONTINUE", and "HALT".  The program  wants  to
prompt for this command using the string "CTRL> " as a prompt.

The programmer starts by writing a standard LIB$LOOKUP_KEY  table
for his four keywords.  Let us say that the address of this table
is USERTAB.  Let us say that when the user is done, he wants  the
keyword  number  1,  2,  3,  or 4 (corresponding to "STOP", "GO",
"CONTINUE", "HALT") stored at address KEYNUM, and  the  value  of
the decimal number stored at address NUMBER.  Let us suppose that
                                                                         Page 17


symbols USERTAB, KEYNUM, and NUMBER are  all  defined  at  module
level, and we omit showing the LIB$LOOKUP_KEY table.

First the programmer  builds  a  CAB  that  contains  his  prompt
string.   Then the programmer calls LIB$PARSE_LINE specifying the
address of this CAB and the address of his parsing routine.   For
example (in BLISS),

LOCAL STATUS,
      PROG__CAB     : $CAB(PMT=%ASCID 'CTRL> ');

STATUS=
   LIB$PARSE__LINE(PROG__CAB,CTRL__PARSER);

The parsing routine, CTRL_PARSER,  specified  by  the  programmer
would look something like this:

ROUTINE CTRL__PARSER =
BEGIN
LOCAL STATUS;

OWN

    KPAB  : $PAB(CAB=PROG__CAB,
                 TYP=KEYWORD,        ! Keyword field
                 ARG=USERTAB,        ! Address of keyword table
                 HLP=%ASCID 'control command'),
                                     ! In-line help message

    NPAB  : $PAB(CAB=PROG__CAB,
                 TYP=NUMBER,         ! Number field
                 HLP=%ASCID 'count', ! in-line help message
                 DEF=%ASCID '1',     ! Default is 1
                 GDW=%ASCID 'WITH'); ! Guideword is "(WITH)"

!+
! Parse keyword.
!-

STATUS = LIB$PARSE__FIELD(KPAB);
IF NOT .STATUS
THEN
    BEGIN
    do whatever you want to tell the user about the error
    and then return.  You could SIGNAL(.STATUS) if desired.
    END;

!+
! Pull the returned value corresponding to
! the keyword that matched
! out of the PAB and store it at KEYNUM.
!-
                                                                         Page 18


KEYNUM = .KPAB[PAB$L__VAL];

!+
! Parse the number.
!-

STATUS = LIB$PARSE__FIELD(NPAB);
IF NOT .STATUS THEN SIGNAL(.STATUS);

!+
! Store away the returned value.
!-

NUMBER = .NPAB[PAB$L__VAL];

RETURN SS$__NORMAL
END;




3.7.6  Types Of Fields -

The type of field to be parsed is specified by the programmer  by
putting  it  in  field  PAB$B_TYPE in the PAB.  The various legal
field types are defined symbolically and will be  made  available
to  the programmer in the same way that the structure offsets for
the CABs and PABs are made available to  the  programmer.   These
names can be distributed through inclusion in STARLET, if the VMS
group wants to do it that way, or through  an  independent  macro
library (MACRO) or require file (BLISS).

HLP$K_KEYWORD

          A keyword is to be parsed.  Field  PAB$L_ARG  specifies
          the  address  of a keyword table containing the list of
          valid keywords.  A standard LIB$LOOKUP_KEY table may be
          specified   or   a   new-style  keyword  table  may  be
          specified.  (See below.)

HLP$K_NUMBER

          A number is to be parsed.  For example,  the  value  of
          the  /COPIES=  qualifier to the DCL PRINT command would
          use  this  type  of  field.   No  range   checking   is
          performed.   That  is  up  to  the  user  program.  Any
          syntactically valid non-null number  is  recognized  as
          being valid.  That is, typing <RECOGNIZE> after a digit
          will cause the system  to  go  on  to  the  next  field
          (normally  a space would print) informing the user that
          a valid number was entered.  Field PAB$L_ARG  specifies
          the radix of the number (2-16).
                                                                         Page 19


HLP$K_QUALIFIER

          A qualifier is to be parsed.  Field PAB$L_ARG specifies
          the  address  of a keyword table containing the list of
          valid aulaifiers.  A standard LIB$LOOKUP_KEY table  may
          be  specified  or  a  new-style  keyword  table  may be
          specified.  The  initial  "/"  is  not  stored  in  the
          keyword table.  If the new style keyword table is used,
          then the programmer can specify which  qualifiers  take
          values,  so  that  the incremental help will inform the
          user of this  fact  by  displaying  an  "="  after  the
          qualifier   name   in   the   help  display.   Obsolete
          qualifiers can  be  marked  by  setting  the  KIT$V_INV
          (invisible)  bit  in  the  KIT.   This  will  allow the
          qualifier to be parsed, but it will not appear  in  the
          incremental   help   text.    For  example,  the  /VT05
          qualifier on the SET TERMINAL command to DCL  has  been
          obsoleted  by  the  qualifier  /DEVICE_TYPE=VT05, so it
          could  be  marked  as  being  invisible,  if   desired.
          Negatable  qualifiers can also be so indicated, so that
          the incremental help text can list them  in  the  form,
          /[NO]FOO, if desired.

HLP$K_INPUT_FILE

          An input filespec is to  be  parsed.   Field  PAB$L_ARG
          specifies  the  address  of  a vector of two longwords.
          The first longword is the address a descriptor for  the
          default  name and the second longword is the address of
          a descriptor for the  related  name.   Either  or  both
          longwords  may be 0.  (((Originally, I had spec'ed that
          this field contained the address of an RMS FAB with  an
          associated NAM block containing the default and related
          strings, however in actual practice, it turned  out  to
          be inconvenient to have to build FABs just to specify a
          default name.)))

HLP$K_OUTPUT_FILE

          An output filespec is to be  parsed.   Field  PAB$L_ARG
          specifies  the address of a vector of two longwords (as
          above) specifying the default and related  names.   The
          difference  between this type of parameter and an input
          file is the way in which recognition works.  For output
          file recognition, the FAB$V_OFP (output file parse) bit
          in the FOP parameter of the FAB structure is  set  whch
          causes   defaults   from   the   related  name  to  act
          differently.  (See the RMS manual  for  more  details).
          Also,  for  input  file  recognition,  the exact vesion
          number (normally the  latest  version)  is  recognized.
          For   output   file   reognition,   ";0"   is  normally
          recognized, indicating that a new version of  the  file
          is to be created.
                                                                         Page 20


HLP$K_GENERAL_FILE

          A general filespec is to be parsed.  (((I  don't  fully
          understand  the  need  for  this  yet,  but the TOPS-20
          people seem to think it is important.)))

HLP$K_PARAM

          An arbitrary parameter terminated by space,  slash,  or
          comma  is to be parsed.  This is useful for fields that
          are not understood  by  the  recognition  package.   No
          recognition is performed on such fields.

HLP$K_END

          The end of the line is expected at  this  point.   This
          field  must eventually be parsed for all command lines.
          The default help text for this field is  "confirm  with
          carriage  return",  but of course this can be overriden
          by specifying explicit  help  text  via  the  PAB$A_HLP
          field  in  the  PAB.  The guidword field (PAB$A_GDW) is
          normally  not  used  with  this  field,  but  could  be
          specified if the programmer wants a guideword to appear
          after the normal termination of  the  command,  say  to
          make  the command read more like English.  For example,
          the WHAT command, SHOW DEVICES (IN  THE  DISPLAY)  uses
          this feature.

HLP$K_DIRECTORY

          A device-directory specification is to  be  parsed.   A
          node  name  is  also optional.  For example, the DECset
          command BUILD DATABASE (ON) DBA3:[FOO] would  use  this
          type   of   field.   Recognition  is  peformed  on  the
          directory portion of this field,  but  not  within  the
          node  name  or  device  name portion.  If the PAB$V_SPO
          (syntax parse only) bit in the PAB is  specified,  then
          the  directory need not exist, i.e., a new directory is
          being created.  In that case,  the  directory  name  is
          only  checked for syntax.  For example, the DCL command
          CREATE/DIRECTORY [FOOBAR] would need to set this bit.

HLP$K_USERNAME

          A username is to be parsed.  For example, the  argument
          to  the  TO>  prompt in the MAIL program would use this
          type of field.  The name  must  be  a  valid  username,
          however, this is not checked for in this release of the
          recognition package because there is no easy way to get
          at  the  list of legal usernames.  Of course, a program
          like AUTHORIZE that has the list of legal names,  could
          put  them  in a keyword table and then parse this field
          as a keyword field, if  desired.   Recognition  is  not
                                                                         Page 21


          performed on this field in this release.  The PAB$V_SPO
          (syntax parse  only)  bit  is  set  to  mean  that  the
          username  need not exist.  For example, the command ADD
          NEUMANN to the AUTHORIZE program would need to set this
          bit.  In that case, the field is only checked for legal
          syntax.

HLP$K_FLOAT

          A  floating  point  constant  is  to  be  parsed.    No
          recognition is performed on this field.

HLP$K_DEVICE

          A device name is to be parsed.  For  example,  the  DCL
          command ALLOCATE DBA2:  would use this type of field to
          parse its parameter.  Partial field recognition is  not
          currently  supported  but  could  be  easily added once
          wildcard  support  is  added  to  the  $GETDVI   system
          service.   Until  then, there is no easy way for a user
          program to get access  to  the  list  of  legal  device
          names.

HLP$K_TEXT

          Arbitrary text is to be  parsed.   All  characters  are
          legal  from  this  point  to the end of the line.  This
          field would be specified when the text to  be  obtained
          is  of  unknown syntax.  It will be accepted and passed
          to  the  user  program   for   further   parsing.    No
          recognition  occurs in such a field.  For example, if a
          user defines the DCL symbol FOO as $SYS$SYSTEM:PROG.EXE
          and  then  types FOO ABC DEF to DCL, he is invoking the
          program PROG through the foreign command  interface  to
          DCL  and  DCL would parse everything after the word FOO
          as a TEXT field.  This text would then be passed to the
          user  program.   (If  a  user wants to invent a new DCL
          command  and  wants  recognition  facilities,  then  he
          should  invoke  his  command  using  the  CLE interface
          rather than the  foreign  command  interface,  assuming
          that recognition services eventually finds its way into
          the CLE.)

HLP$K_TIME

          A  date-time  specification  is  to  be  parsed.    For
          example,  the value of the /AFTER= qualifier on the DCL
          SUBMIT command would use this type of field.  Any legal
          date/time  specification  is  permitted, as well as the
          keywords TODAY, TOMORROW, and YESTERDAY.

HLP$K_QUOTED_STRING
                                                                         Page 22


          A quoted string is to be  parsed.   The  quoted  string
          must  be  enclosed  in  the  quote  character  which is
          specified  in  field  PAB$L_ARG  in  the   PAB.    This
          character   defaults   to   double  quote  (")  if  not
          specified.  The quote character may appear  within  the
          quoted  text by doubling it up.  If the quote character
          is double quote, then the characters "?" and TAB may be
          entered  directly  into  this  field while entering the
          command  line.   They  will  echo  as   "?"   and   tab
          respectively.   In such a case, these characters do not
          signal the start of incremental  help  or  recognition.
          For  example,  the  DCL command A="TEST" would use this
          type of field.  Note that if the surrounding quotes are
          optional,  then  the  next  field  type  should be used
          instead.

HLP$K_STRING

          A string is to be parsed.  The string may  have  double
          quotes around it.  The double quotes are necessary only
          if the string contains special characters such as space
          or  comma.   For  example,  the  value on the /SUBJECT=
          qualifier to the MAIL command to  DCL  would  use  this
          type  of  field.   If  the  first character is a double
          quote, then the field behaves exactly as  the  previous
          type  of  field  (HLP$K_QUOTED_STRING).   If  the first
          character is not a double quote, then the field extends
          to  the  first  valid  separator  (space,  comma, plus,
          slash) or end-of-line.

HLP$K_TOKEN

          An explicit string is to be parsed.  Each character  in
          this  string  must match exactly.  Typically, this is a
          one-character string used to match  syntactic  elements
          like  comma, at-sign, equal sign, etc.  Field PAB$L_ARG
          contains the address of a descriptor  for  the  string.
          For   example,  one  of  the  choices  allowed  at  the
          beginning of a command line to WHAT.EXE is a  construct
          of  the  form  @filespec, telling it to accept commands
          from an indirect command file.  The first character  of
          this   construct  is  parsed  using  a  field  type  of
          HLP$K_TOKEN.

HLP$K_ACCOUNT

          An account name is to  be  parsed.   For  example,  the
          value  of the /ACCOUNT= qualifier to the DCL ACCOUNTING
          command would use this type of field.  The account must
          exist,  however  there is currently no way to check for
          this.  If the bit PAB$V_SPO (syntax parse only) is  set
          in  the PAB, then the account name need not exist, i.e.
          a new account name is being  created.   This  would  be
                                                                         Page 23


          needed  for  the /ACCOUNT= qualifier to the ADD command
          in AUTHORIZE.  Recognition is  not  performed  on  this
          field  in this release of the recognition package;  the
          field is just checked to see  if  it  is  syntactically
          correct.

HLP$K_NODENAME

          A nodename is to be parsed.   For  example,  the  third
          field  in  the  DCL  command SET HOST VAX4::  would use
          this type of field.  The name  must  be  a  valid  node
          name,  however  there is currently no easy way to check
          for this.  If the bit PAB$V_SPO (syntax parse only)  is
          set in the PAB, then the node name need not exist, i.e.
          a new node name is being created.   For  example,  this
          would  be  used to parse field 5 in the NCP command SET
          NODE 23 NAME FOOBAR.  Recognition is not  performed  on
          this  field  in this release of the recognition package
          because  VMS  does  not  provide  an  easy  way  for  a
          user-level   program  to  get  at  the  list  of  valid
          nodenames.  Thus, the field is just checked to  see  if
          it is syntactically correct.

HLP$K_LOGICAL_NAME

          A logical name is to be parsed.  For example, the third
          field in the DCL command SHOW TRANSLATION FOO$BAR would
          use this type of field.   The  name  must  be  a  valid
          logical name.  If the bit PAB$V_SPO (syntax parse only)
          is set in the PAB,  then  the  logical  name  need  not
          already  exist,  i.e.   a  new  logical  name  is being
          created.  For example, this  would  be  used  to  parse
          field  2  in  the  DCL command DEFINE FOO$SYSTEM "XYZ".
          Normally, bit PAB$V_NOWLD (no wildcards) should be  set
          to  prohibit  wildcards in the name.  This bit would be
          clear if wildcards are legal, as  in  the  DCL  command
          SHOW   LOGICAL   ABC*.    Full   field  recognition  is
          performed, however partial  field  recognition  is  not
          implemented  in  this  release because there is no easy
          way to get at the complete list of valid logical names.

HLP$K_UIC

          A UIC of the form [m,n] or <m,n> is to be parsed.   For
          example,  the  third  field  of the DCL command SET UIC
          [23,45] would use this type of field.   No  recognition
          is performed in this field.

HLP$K_TOPIC

          Reserved for future use to allow recognition  of  topic
          names  from  help libraries.  The problem is that there
          is no easy way to get the list of legal subtopic  names
                                                                         Page 24


          (other than the top level topics) from a help library.

HLP$K_NAME

          A name consisting of letters, digits,  and  underscores
          is wanted.  No semantics are involved.  This field type
          is used for names that are unknown to  the  recognition
          package.   If recognition is requested, the system will
          print a space indicating that a  valid  name  has  been
          typed if it is syntactically valid.

HLP$K_CHARACTER

          Any single character is valid.  This field type is used
          as  a  last-ditch  emergency  escape  if the programmer
          wishes  to  perform  parsing  of  some  kind  that   is
          completely out of the scope of the recognition package.
          No  recognition  is  performed  on  this  field.    The
          programmer  can then get as many characters as he wants
          from the command line  and  parse  them  himself.   For
          example, the debugger has a command of the form

          SET BREAK expr DO cmd

          where  "expr"  denotes  any  valid  expression  in  the
          currently  selected language.  The debugger already has
          a large piece of code that parses such expressions, and
          if  they  decide  to  use the recognition package, they
          might not want to  recode  all  this  language-specific
          expression  parsing  code  on  a first pass.  Thus they
          could parse the keyword fields,  SET,  BREAK,  DO,  and
          those  in  "cmd"  via the recognition package and parse
          the "expr" field with their original parser by  getting
          characters    from    the   command   line   with   the
          HLP$K_CHARACTER field type.
                                                                         Page 25


3.7.7  Fields Within The Command Access Block (CAB) -

Fields that are not programmer-initializable:

CAB$W_BLN      Size of CAB in bytes.  This field  is  initialized
               to CAB$K_BLN by the $CAB macro.

CAB$B_BID      Block ID of CAB.  This  field  is  initialized  to
               CAB$K_BID  by  the  $CAB macro.  The value of this
               constant should be assigned by the VMS group.

Common fields set by programmer:

CAB$A_CMD      Address of descriptor for buffer  to  store  final
               command   line  that  was  read.   This  field  is
               actually optional.  If  the  programmer  cares  to
               have  us  parse his line and never really wants to
               see what the line was, he can do that.  Note  that
               if  this  descriptor is a dynamic descriptor, then
               the  recognition  package  will  never  return   a
               "command   line  buffer  overflow"  error  to  the
               programmer.  If the current internal command  line
               buffer  should  fill up, additional virtual memory
               will be obtained, and  the  current  $QIO  request
               will be started again specifying the data typed so
               far as the initial string.   Thus  the  user  will
               never know that the command line buffer filled up.
               He will only get an error if he exceeds some quota
               or runs out of virtual memory.

CAB$A_PMT      Address of  descriptor  for  main  prompt  string.
               <This field corresponds to the .CMRTY field in the
               TOPS-20 implementation.>

CAB$A_ATM      Address of  descriptor  for  atom  buffer.   <This
               field  corresponds to the .CMABP and .CMABC fields
               in the TOPS-20 implementation.> The atom buffer is
               a  buffer to contain the string of characters that
               actually matched the current field specification.

Obscure fields that can be specified by the programmer:

CAB$W_CHN      Channel of input device.  If this word is 0,  then
               it  means  the programmer wants input to come from
               SYS$INPUT.   A  channel   is   assigned   by   the
               recognition  package in this case.  LIB$PARSE_LINE
               will then ASSIGN a channel to SYS$INPUT and  place
               the  channel  number  back  in  this field.  <This
               field corresponds to the left half of  the  .CMIOJ
               field  in the TOPS-20 implementation.  There is no
               field corresponding to the right half of that word
               (the  output  JFN) because no one has been able to
               explain to me the purpose of the  output  JFN.   I
                                                                         Page 26


               can  see  no  reason  why  you  would want to type
               <RECOGNIZE>  on  one   terminal   and   have   the
               recognized characters sent to another device.> For
               example, a program that runs from one terminal but
               wishes  to  take  commands  from one or more other
               terminals would need this ability to  specify  the
               channel  of  the  device from which input is to be
               taken.  If the input device  is  not  a  terminal,
               then  RMS  is  used  to read the command line from
               this device.  In this case, incremental  help  and
               recognition  facilities are not available.  Should
               the   <HELP>   or   <RECOGNIZE>   characters    be
               encountered  in  a  record  read from this device,
               they will be treated as text characters.

CAB$V_CVT      Convert lower  case  to  upper  case.   <This  bit
               corresponds  to  the  CM%RAI  bit  in  the TOPS-20
               implementation.> For example, this  bit  would  be
               set  by  LOGINOUT  when  prompting for a username.
               Note that this  bit  is  actually  passed  to  the
               terminal QIO (via the IO$M_CVTLOW bit) so that the
               characters actually echo  in  uppercase.   If  the
               program  wants the characters to echo in upper and
               lower case but be converted to upper  case  before
               being  passed  back  to  the  program,  that  is a
               different  option  (see  the  description  of  the
               CAB$V_UCA bit).

CAB$V_UCA      Uppercase the atom buffer.   Specifying  this  bit
               causes  the string stored in the atom buffer to be
               up-cased   for   all   field   types   that    are
               case-insignificant,  for example HLP$K_KEYWORD and
               HLP$K_INPUT_FILE.  This bit has no affect  on  the
               atom buffer for fields such as HLP$K_QUOTED_STRING
               where lower case letters are significant.  In that
               case,  the  atom  buffer  gets the exact string as
               typed by the user.  This bit will be useful to DCL
               to  help  implement  the  feature  that  allows  a
               program to call back to DCL to get a copy  of  the
               command  line  in  "normal  form"  with non-quoted
               fields up-cased and  multiple  spaces  reduced  to
               single  spaces.   DCL will simply specify this bit
               and then append together all the atom  buffers  as
               it  parses the line (separating the atomic strings
               by a single space).

CAB$V_COM      Treat "!" as  an  end-of-line  comment  character.
               Only  "!"s  in the proper syntactical context will
               have this meaning.  A "!" found in a quoted string
               or  in  an  access  control string or in a foreign
               filespecification will be considered data and will
               not terminate the command parse.
                                                                         Page 27


CAB$V_CON      Allow continuation lines with hyphen ("-").   Only
               hyphens  found  between  fields will be considered
               continuation  line  indicators.   For  example,  a
               hyphen  found in proper context while scanning for
               a date specification (such as 28-JAN-1982) will be
               considered data and will not terminate the command
               scan.  Similarly, hyphens  within  quoted  strings
               are   considered  to  be  data.   (((This  is  not
               implemented yet.  Should I forgo implementing this
               and  leave  it up to the user program to handle it
               or should I make continuation lines  available  to
               all  user  programs?  It is also unclear to me how
               to handle a request for a continuation line  after
               a (sub) prompt has been issued.)))

CAB$V_IND      Allow indirect command file with "@" (reserved for
               future  use).   <This bit corresponds inversely to
               the CM%XIF bit in the TOPS-20 implementation.>  If
               this feature is allowed at all, it is necessary to
               enable and  disable  it,  because  many  utilities
               allow  "@"  as  part of its normal command syntax.
               For example, the command

               EXAMINE @FOO

               is a  perfectly  valid  command  to  SDA  (meaning
               examine  location  referenced  indirectly  by  the
               symbol FOO) and does not mean invoke  an  indirect
               command  file  at  this point in the command line.
               On the other hand, a  large  number  of  utilities
               already  support  indirect  command files (or want
               to) and it would be wasteful to have each of these
               utilities do it themselves.

CAB$A_LEX      Address of a programmer-suplied lexical processing
               routine.  This routine is called after any wake-up
               character is typed (such as  <HELP>,  <RECOGNIZE>,
               or  <RETURN>)  and  is given the line typed by the
               user.  This routine may perform lexical processing
               on  this  line (such as symbol substitution or any
               other sort of pre-processing, and then return  the
               line  to the recognition package.  The recognition
               package  then  proceeds  to  perform  its   normal
               parsing,  incremental  help,  or  recognition.  If
               this longword is 0,  then  no  pre-processing  has
               been requested by the programmer.  This field will
               be useful to DCL to allow  it  to  perform  symbol
               substitution  with  the  ' (apostrophe character).
               The lexical  processing  routine  is  called  with
               three arguments.  Argument 1 is the address of the
               CAB.  Argument 2 is the address of a descriptor to
               received  the  line  back after lexical processing
               has occurred.  Argument 3  is  the  address  of  a
                                                                         Page 28


               descriptor  for  the line as typed in by the user.
               The lexical processing routine must check the  CAB
               to  determine  if  a  lexical  construct  has been
               interrupted with a request for help or recognition
               and handle such a request.  If the lexical parsing
               routine returns with a FALSE status,  this  aborts
               command  parsing  and  LIB$PARSE_LINE returns with
               the status supplied  by  the  lexical  proceessor.
               (Not yet implemented.)

CAB$V_TMO      Timeout operation.  The timeout time (in  seconds)
               is  specified in the CAB$B_TMO field.  This bit is
               actually passed  to  the  terminal  QIO  (via  the
               IO$M_TIMED bit).  This is useful for programs that
               want to time-out the terminal read operation.  For
               example,   LOGINOUT   would   set  this  bit  when
               prompting for a username.

CAB$B_TMO      Timeout time (in seconds).  This byte is  actually
               passed  to the terminal QIO (via the P3 argument).
               This byte is ignored if the CAB$V_TMO bit  is  not
               set.   Consult  the  VAX/VMS  I/O User's Guide for
               more details.  (((RMS uses a byte  field  for  the
               timeout  time, however the terminal driver appears
               to allow a longword time.  Should  I  change  this
               field to be a word or even a longword?)))

CAB$V_PTA      Purge type-ahead buffer.   This  bit  is  actually
               passed  to  the  terminal  QIO (via the IO$M_PURGE
               bit).  The type-ahead buffer is purged before  the
               initial read.  No type-ahead buffer purging occurs
               later in the  process.   For  example,  type-ahead
               typed   while   the   system   is   displaying  an
               incremental help message will not be  purged.   If
               the  programmer  really  wishes  to  disallow  all
               type-ahead,  he  should  change   the   terminal's
               characteristics to prohibit type-ahead.

CAB$V_RNE      Read with no echo.  This bit is actually passed to
               the  terminal  QIO (via the IO$M_NOECHO bit).  For
               example, this bit would be set  by  LOGINOUT  when
               prompting for a password.

CAB$A_QIOGET   Address  of  a  programmer-supplied   routine   to
               replace   the   normal   read   QIO  used  by  the
               recognition package to  read  the  user's  command
               line.  If this longword is 0, then the recognition
               package uses the standard VMS  terminal  QIO's  to
               get  input  from the terminal.  This address would
               only be needed by  systems  that  have  their  own
               (non-standard)   terminal   driver.    The  DECset
               product needs this field in order to allow  us  to
               support  the  VT173 terminal.  This field could be
                                                                         Page 29


               reserved to DEC if we decided not  to  clutter  up
               user-documentation by explaining how it works.

CAB$A_QIOPUT   Address  of  a  programmer-supplied   routine   to
               replace   the   normal   write  QIO  used  by  the
               recognition package to write text  to  the  user's
               terminal.    If  this  longword  is  0,  then  the
               recognition package uses the standard VMS terminal
               QIO's  to  write  to  the  terminal.  This address
               would only be needed by systems  that  have  their
               own  (non-standard)  terminal  driver.  The DECset
               product needs this field in order to allow  us  to
               support  the  VT173 terminal.  This field could be
               reserved to DEC if we decided not  to  clutter  up
               user-documentation by explaining how it works.

CAB$V_WAK      Wake up and begin parsing after each field.   This
               is   useful   if   you  want  to  change  terminal
               characteristics for some fields, such as turn echo
               off  for a password field.  This feature should be
               used very sparingly since it is quite inefficient.
               <This  bit  corresponds  to  the CM%WKF bit in the
               TOPS-20 implementation.> The recommended method of
               changing terminal characteristics within a command
               is  to  input  the  field  requiring  the  special
               characteristics  on  the  next  line  with its own
               prompt.  For example, if a program is accepting  a
               password  (other than as part of an access control
               string) it  should  perform  a  separate  call  to
               LIB$PARSE_LINE   specifying  a  prompt  string  of
               "PASSWORD:  " and including the CAB$V_RNO  bit  to
               read  that  entire  line  with  no  echo.   A more
               efficient method of  suppressing  the  echoing  of
               passwords within an access control string within a
               filespecification is given later.  This  field  is
               reserved for future use.

CAB$A_GET      The address of a routine that should be called  to
               get  the  command  line  into  the command buffer.
               This is specified when the  programmer  wishes  to
               obtain   the   line   himself  without  using  our
               services.  Our services are merely being  used  to
               parse   the  command  line.   This  feature  would
               typically be used if the programmer implements his
               own indirect command mechanism.  Upon encountering
               an @filespec (or similar command)  the  programmer
               then  gets  subsequent commands from the specified
               file and then merely calls us to use  our  parsing
               facilities.    This   field   is  ignored  if  the
               CAB$V_GOT bit is set.

CAB$V_GOT      The command line has already been gotten and is in
               the  programmer's buffer (specified by CAB$A_CMD).
                                                                         Page 30


               The programmer has already  obtained  the  command
               line  and  only  wants  to make use of our parsing
               services.  This feature would normally be used  to
               execute  a  command  that  is  hard coded into the
               user's program.  In that case, he would just point
               at   the   fixed   command  line.   This  is  more
               convenient than pointing at the fixed command line
               and   then  specifying  a  dummy  routine  in  the
               CAB$A_UCI field that does nothing but return.  For
               example, PHONE could use this feature if CTRL/Z is
               typed;  it would call LIB$PARSE_LINE  pointing  at
               an  "EXIT"  command and the program would continue
               as if the user had typed "EXIT".

CAB$V_ASY      This is an asynchronous operation.  LIB$PARSE_LINE
               returns   immediately   to  the  programmer.   The
               programmer must  explicitly  test  the  associated
               event  flag (specified in field CAB$W_EFN) to find
               out when the line has been  read  in  and  parsed.
               (reserved for future use)

CAB$W_EFN      Event flag to be set when the operation completes.
               This  field is ignored if the CAB$V_ASY bit is not
               set.  (reserved for future use)

CAB$A_ASTADR   Address of AST  routine  to  be  called  when  the
               operation completes.  This field is ignored if the
               CAB$V_ASY bit is not set.  If specified,  the  AST
               routine executes at the access mode from which the
               call to LIB$PARSE_LINE was  made.   (reserved  for
               future use)

CAB$L_ASTPRM   AST parameter to be  passed  to  the  AST  service
               routine.   This  field is ignored if the CAB$V_ASY
               bit is not set.  (reserved for future use)

CAB$A_IOSB     Address of quadword I/O status block  that  is  to
               receive  final  completion  status.  This field is
               valid even if CAB$V_ASY is not  set,  however  the
               data  in the I/O status block is valid only if the
               input device is a  terminal.   Useful  information
               returned  in  the  I/O  status  block is the final
               terminator   character   (the    character    that
               terminated  the  command line read operation), the
               terminator size (if it was  an  escape  sequence),
               and  the offset to the terminator.  This offset is
               relative to the buffer address contained in  field
               CAB$A_CBF.   The terminator is not included in the
               programmer's buffer (specified by  the  descriptor
               at CAB$A_BUF).

CAB$A_ERR      Address of routine to be  called  if  there  is  a
               syntax  error  encountered  in  the  command  line
                                                                         Page 31


               parsed  by  LIB$PARSE_LINE.   This   argument   is
               normally  only useful with asynchronous operation.
               The routine  is  called  with  one  argument,  the
               address of the CAB.  (reserved for future use)

CAB$A_SUC      Address of routine to be  called  if  the  command
               line  parse completes successfully (with no syntax
               error).  This argument  is  normally  only  useful
               with   asynchronous  operation.   The  routine  is
               called with one argument, the address of the  CAB.
               (reserved for future use)

CAB$A_PUT      Address of routine to be  called  to  control  the
               display of the incremental help output.  Normally,
               when the  <HELP>  key  is  depressed,  the  system
               automatically  displays  the incremental help text
               on the terminal in the format it wants.  This  may
               not  be  convenient,  for  example, if the user is
               running on a  scope  terminal  and  is  performing
               screen  management (as is the case with WHAT.EXE).
               In that case, he may want to be under full control
               of  where  the help text prints.  In this case, he
               supplies the address of a routine  in  this  field
               and  that  routine  gets called successively, once
               for each line of help  output  that  is  produced.
               This   action   routine   option  is  provided  in
               conformity to  recommendation  51  of  the  VAX-11
               Modular   Programming  Standard  with  regards  to
               human-readable text output.  (See the VAX-11 Guide
               to  Writing  Modular  Library  Routines  for  more
               details.)   The   action   routine   gets   called
               repeatedly for each line of help text.  The action
               routine is called with three arguments.  The first
               argument  is the type of help line being supplied.
               The second argument is the  address  of  the  PAB.
               The  third  argument  is  programmer-supplied  and
               resides  at  CAB$L_PUT.   If  the  action  routine
               returns   a  status  of  FALSE  (low  bit  clear),
               additional lines of help text are not produced and
               the  system  goes  back  to get more command input
               from the user in the usual manner.

CAB$L_PUT      A context longword whose contents  are  passed  to
               the  action  routine whose address is specified in
               CAB$A_PUT.

CAB$W_WIDTH    Width of the input device.   This  information  is
               necessary  when  deciding  how  to format the help
               output for keywords when there are  more  keywords
               than   will  fit  on  a  single  line.   Normally,
               LIB$PARSE_LINE will determine  the  width  of  the
               input  device  (if  it  is  a terminal) by calling
               $GETDVI and use the actual width of the  terminal.
                                                                         Page 32


               However,  the  program  can override this width by
               setting this field to be  non-0.   This  would  be
               useful   for  programs  that  are  displaying  the
               incremental  help  themselves  (by  specifying   a
               routine  to do so in the CAB$A_HLP field) and wish
               to display the help information in only a  portion
               of   the   screen.    If   not  specified  by  the
               programmer, this field is defaulted  in  from  the
               CAB$W_DEVBUFSIZ field.

Fields containing data returned to programmer:

CAB$W_CLN      Number of characters returned  in  command  buffer
               (specified   by   field  CAB$A_BUF)  not  counting
               padding in the  case  of  a  fixed  length  string
               descriptor.

CAB$W_ALN      Number of characters returned in atom buffer,  not
               counting  padding  in  the  case of a fixed length
               string descriptor.

CAB$V_REC      <RECOGNIZE>  terminated  this  field.   <This  bit
               corresponds  to  the  CM%ESC  bit  in  the TOPS-20
               implementation.>

CAB$V_EOL      Field was terminated by end-of-record  (or  CRLF).
               <This  bit  corresponds  to  the CM%EOC bit in the
               TOPS-20 implementation.>

CAB$V_RPT      A reparse is needed.  Internal use only.

CAB$V_PFR      <RECOGNIZE> terminated previous  field  <This  bit
               corresponds  to  the  CM%PFE  bit  in  the TOPS-20
               implementation.>

CAB$B_TRM      Field terminator character.  This is the character
               that  terminated  the  current  field  (it  is not
               necessarily a wake-up character.) Do  not  confuse
               this   with  the  character  that  terminated  the
               current  QIO  read.   That  character   shall   be
               referred  to as the QIO terminator and is returned
               in the I/O status block.

CAB$V_DEF      This bit gets set if the default string  for  this
               field   was   supplied   because  the  user  typed
               <RECOGNIZE> at the beginning of the  field  or  if
               the field was omitted and the programmer specified
               that he did not want to prompt for this field.

Obscure fields that can be read by the programmer:

CAB$A_CBF      Address of actual command line buffer.   This  may
               or  may  not  be  the  address  specified  by  the
                                                                         Page 33


               programmer  in  the  descriptor  given  at   field
               CAB$A_BUF.   If  the  programmer's  descriptor  is
               static, then we read directly into his buffer.  If
               the  programmer's  descriptor  is dynamic, then we
               use a buffer of our own and then use LIB$SCOPY  to
               copy  the  command line to the programmer's buffer
               when we are done.  <This field corresponds to  the
               .CMBFP field in the TOPS-20 implementation.>

CAB$W_CSZ      Size of command line buffer.

CAB$A_PAB      Address of first Parameter block for  the  current
               field.

CAB$A_CURPAB   Address of the current Parameter  Block  (in  case
               several   were   specified   that   were   chained
               together).  The programmer will sometimes need  to
               check this field to see which PAB actually matched
               what the user typed in.

CAB$A_IND_FAB  Address of  FAB  being  used  to  process  current
               indirect command file.  Reserved for future use.

CAB$A_IND_RAB  Address of  RAB  being  used  to  process  current
               indirect command file.  Reserved for future use.

CAB$W_PTR      Offset to next character to be parsed.

CAB$W_FLD_PTR  Pointer to beginning of current field.   <I  think
               this  field corresponds to the .CMPTR field in the
               TOPS-20  implementation.   There   is   no   field
               corresponding to the .CMCNT or .CMINC fields since
               the  contents  of  these  fields  can  be   easily
               calculated  using  CAB$W_FLD_PTR,  CAB$W_PTR,  and
               CAB$W_CSZ.>

CAB$W_PMT_PTR  Pointer to first field  in  current  (sub)  prompt
               line.

CAB$W_SUB_PTR  Pointer to beginning of current subfield

CAB$W_CNT_PTR  Pointer  to  beginning  of  current  line   of   a
               multi-line  command  (if  continuation  lines  are
               being used).

CAB$L_DEVCHAR  Device characteristics for  the  input  device  as
               returned by $GETDVI.

CAB$B_DEVCLASS Device class for the input device as  returned  by
               $GETDVI.

CAB$B_DEVTYPE  Device type for the input device  as  returned  by
               $GETDVI.
                                                                         Page 34


CAB$W_DEVBUFSIZ Input device buffer size as returned by $GETDVI.

CAB$L_DEVDEPEND Device dependent information for the input device
               as returned by $GETDVI.

CAB$L_DEVDEPND2 Additional device dependent information about the
               input  device  as returned by $GETDVI.  We need to
               know if the  device  is  a  block  mode  terminal,
               because  in that case, editing of the command line
               can  be  performed  even  when  we  didn't   think
               possible, so we must signal HLP$_REPARSE after any
               terminal I/O operation.

CAB$V_HLP      Line ended with "?".

NOTES:

     1.  The following bits are available in $QIO  calls  to  the
         terminal  driver  but  are  not  accessible  through the
         LIB$PARSE_LINE call:

         1.  IO$M_DSABLMBX.  Does not seem applicable.

         2.  IO$M_NOFILTR.  Incremental help and recognition does
             not seem appropriate in NOFILTR mode.

         3.  IO$M_REFRESH.  Under our control.  Always specified.
             Things  would  get  very  confusing without this bit
             set.

         4.  IO$M_TRMNOECHO.    Under   our   control.     Always
             specified.


     2.  The following fields exist in the TOPS-20 implementation
         and have no counterpart here:

         1.  The CM%NOP bit (parse  failed).   This  bit  is  not
             necessary  because  the  programmer can test the low
             order bit of the returned status value.

         2.  The CM%RPT bit (reparse is needed bit).  We  do  not
             use  this  bit because it was felt that there was no
             reason to  ever  let  the  programmer  do  a  manual
             reparse.   Under  our  implementation,  reparses are
             handled automatically as necessary and are invisible
             to  the  programmer.  To explain to a programmer how
             to do the reparse would be very complicated since he
             might  have  to set up a condition handler and do an
             unwind.
                                                                         Page 35


         3.  The CM%SWT bit (switch value  occurred).   This  bit
             appears  to  be  unnecessary.   The  programmer  can
             examine  field  CAB$B_TRM  to  get  the   terminator
             character for the qualifier field.  He can then test
             this character to see if it  is  a  ":"  or  "="  to
             determine  whether  or  not the user has specified a
             value associated with the qualifier.





3.7.8  Fields In The Parameter Block (PAB) -

Fields that are not programmer-initializable:

PAB$W_BLN      Size of PAB in bytes.  This word is initialized to
               PAB$K_BLN by the $PAB macro.

PAB$B_BID      Block ID for the PAB.  This field  is  initialized
               to PAB$K_BID by the $PAB macro.  The value of this
               constant should be assigned by the VMS group.

Common fields supplied by programmer:

PAB$A_CAB      Pointer back to associated CAB

PAB$B_TYP      Field  type.   <This  field  corresponds  to   the
               .CMFNP(CM%FNC)     field     in     the    TOPS-20
               implementation.> For example, this field would  be
               set to HLP$K_KEYWORD if a keyword is to be parsed.
               This field would  be  set  to  HLP$K_NUMBER  if  a
               number  is  to be parsed.  A complete set of valid
               field types is given elsewhere in this document.

PAB$L_ARG      Function-specific    argument.     <This     field
               corresponds  to  the  .CMFNP(CM%DAT)  field in the
               TOPS-20 implementation.> Many field types take  an
               additional  argument.   For  example, if the field
               type were HLP$K_KEYWORD, then this argument  would
               be   the   address  of  the  LIB$LOOKUP_KEY  table
               specifying the list of  valid  keywords.   If  the
               field  type  were HLP$K_NUMBER, then this argument
               would be the radix of the  numeric  string  to  be
               parsed.   If the field type were HLP$K_INPUT_FILE,
               then this argument would be the address of  a  FAB
               specifying  details  about  the file-specification
               wanted (such as what is the default name  and  the
               related name, if any).  A complete list of all the
               different kinds of  field  types  and  what  their
               associated   function-specific  arguments  are  is
               given elsewhere in this document.
                                                                         Page 36


PAB$A_DEF      Address of descriptor for  default  string.   A  0
               longword    indicates    that    there    is    no
               program-supplied default for  this  field.   <This
               field  corresponds  to  the  .CMDEF  field  in the
               TOPS-20 implementation.  There is no necessity for
               a  bit  corresponding to the CM%DPP bit, since the
               presence  of  a  non-0  longword  in  this   field
               specifies that a default string is provided.> This
               string is the string that  is  recognized  if  the
               user  types  <RECOGNIZE>  at  the  beginning  of a
               field.

               Note that <RECOGNIZE>  works  differently  at  the
               beginning  of  a  field  than  in  the middle of a
               field.  For example, if a program  specifies  that
               the default string for a certain filespecification
               field  is  PROG.GLK,  then  if  the   user   types
               <RECOGNIZE>   at  the  beginning  of  that  field,
               "PROG.GLK" will be  recognized.   However,  if  he
               then  types  P followed by <RECOGNIZE>, the system
               would beep at him if he had more than one file  in
               his  area  beginning with the letter "P".  Another
               example:  suppose the default width value  to  the
               /WIDTH=  qualifier in some command were the string
               "80".  If the user typed  <RECOGNIZE>  immediately
               after  the "=", then "80" would be recognized, but
               if he typed "8" and then <RECOGNIZE>, "8" would be
               recognized  as a valid number and the system would
               type a space and go on to the next field.

               The default  string,  if  selected  by  the  above
               mechanism,  is  still  subject  to a syntax check.
               Thus, it is considered a  programming  bug,  if  a
               programmer   specifies   a  syntactically  invalid
               string as the default string for some field.  When
               a  user then types <RECOGNIZE> at the beginning of
               such a field, the faulty default will be displayed
               immediately   followed   by   an   error  message.
               Normally this is not a problem, but  could  happen
               in cases where a program is trying to be fancy and
               peform dynamic  field  defaulting.   For  example,
               suppose  the EDIT command is written to "remember"
               the  filespecification  given  to  it   from   one
               invocation  to  the  next.   If a user types "EDIT
               SRC:FOO.MAC" and then  shortly  later  types  just
               "EDIT",   DCL  could  (if  desired)  remember  the
               previous string "SRC:FOO.MAC" and  specify  it  as
               the   default   string   in  subsequent  calls  to
               LIB$PARSE_FIELD for  this  particular  field.   If
               between one edit and the next, the user deassigned
               the logical name "SRC", then  the  default  string
               would  no longer be syntactically valid.  I do not
               consider  this  to  be   a   problem,   but   this
                                                                         Page 37


               possibility should be noted.

PAB$A_PMT      Address of descriptor for (sub) prompt string.  If
               this  is  omitted, then this means that the system
               should not prompt for this parameter.   Note  that
               some  utilities  like  to prompt for arguments and
               some do not.  For example, NCP prompts for certain
               missing  arguments,  but PHONE does not prompt for
               missing arguments.

PAB$A_GDW      Address of descriptor  for  guideword.   The  $PAB
               macro normally defaults this to be the same as the
               prompt string.  Specifying  an  explicit  0  means
               that  this field has no guideword.  By convention,
               guidewords are used to turn a computerese  command
               into a command that more-closely resembles a valid
               English sentence.  For example, the DEFINE command
               could be set up to have the syntax

               $ DEFINE (LOGICAL NAME) name (TO BE EQUIVALENT TO)
               string

               if desired.  The prompt for the  second  parameter
               could remain "equivalence-name".

               Another example:

               $ SYNCHRONIZE (WITH JOB) name

               reads better than

               $ SYNCHRONIZE (JOB-NAME) name

               In many cases, however, the guideword would be the
               same as the prompt string.

PAB$A_VBF      Address of descriptor to receive  a  string-valued
               result  of  the parse of this field.  For example,
               if the field type were  HLP$K_FILESPEC,  then  the
               expanded  name  string  gets returned through this
               field.  If the field type  is  HLP$K_KEYWORD,  the
               full  keyword  string  gets returned throught this
               field.

Obscure fields that can be supplied by programmer:

PAB$A_NXT      Address of next PAB in chain.   This  is  used  to
               specify   alternatives.    For  example,  the  USE
               command  in  SYSGEN  allows  a  keyword   (ACTIVE,
               DEFAULT)  or  a  filespecification.   <This  field
               corresponds to the  .CMFNP(CM%LST)  field  in  the
               TOPS-20  implementation.>  When  <HELP>  is typed,
               help  about  each  one  of  the  alternatives   is
                                                                         Page 38


               displayed,  in  order.  When <RECOGNIZE> is typed,
               we attempt to perform recognition one  alternative
               at a time and proceed to the next alternative only
               if there  is  no  possible  match  for  the  first
               alternative.    A   partial   completion  prevents
               seeking   alternatives.    For   example,   typing
               <RECOGNIZE> after

               $ DIR

               to DCL will recognize the characters "ECTORY" even
               though the command could legally have been

               $ DIR="ABC"

               or

               $ DIR:  ALLOCATE MTA2:

               We do not beep at the  user  because,  presumably,
               DCL will list the keyword alternative prior to the
               assignment   statement   alternative   and   label
               alternative  when setting up its PAB chain for the
               first field.

PAB$V_SPO      Syntax parse only.  There  are  some  cases  where
               programs  do  not want to check the validity of an
               entity, but only check that  it  is  syntactically
               correct.  For example, the command

               $ SET DEFAULT XYZ:[ABC]

               is perfectly legal to DCL even though there may be
               no  device  called XYZ currently on the system.  A
               similar  situation  exists   with   the   /DEVICE=
               qualifier to AUTHORIZE.  In such cases, the system
               only   checks   that   the   item   specified   is
               syntactically  correct.   <This bit corresponds to
               the CM%PO bit in the TOPS-20 implementation.>

PAB$V_SDH      Suppress  default   help   text.    A   programmer
               specifying  his own help text can either add to or
               replace the  system's  default  text.   <This  bit
               corresponds  to  the  CM%SDH  bit  in  the TOPS-20
               implementation.>

PAB$V_NOS      Field may not be preceded by spaces.  If this  bit
               is not set, then it is presumed that the parameter
               may be preceded by  any  number  of  spaces.   For
               example,  the  /DEVICE=  qualifier on the username
               prompt  to  LOGINOUT  permits  a  device   and   a
               directory  specification.   Either is optional and
               would probably be coded by two successive calls to
                                                                         Page 39


               LIB$PARSE_FIELD;   however  no  space is permitted
               between these two fields.

PAB$A_HLP      Address of descriptor for programmer's help  text.
               This  longword  can  be  0  if  the program is not
               supplying its own help text.  In  that  case,  the
               system's    default    help   text   is   produced
               exclusively.   <This  field  corresponds  to   the
               .CMHLP  field  in  the TOPS-20 implementation.  No
               bit corresponding to the CM%HPP bit  is  necessary
               because   the  presence  of  a  0  in  this  field
               specifies that there is no  program-specific  help
               text for this field.>

PAB$A_HLP_RTN  Address of programmer's routine to  be  called  to
               supply  help.   This  can  be used by a programmer
               that wants to perform a non-standard form of  help
               or  is  parsing  a type of field not understood by
               the supplied help routines.  This field is  needed
               by  DECset  to allow for supplying help for DECset
               specific  fields  such  as  document   names   and
               database names.

PAB$A_REC_RTN  Address of programmer's routine to  be  called  to
               perform  recognition.   This  can  be  used  by  a
               programmer that wants to  perform  a  non-standard
               form  of recognition while parsing a type of field
               not  understood  by   the   supplied   recognition
               routines.  This field is needed by DECset to allow
               for performing  recognition  for  DECset  specific
               fields such as document names and database names.

PAB$Q_BRK      Terminator break mask quadword (not fully designed
               yet).  <This field corresponds to the .CMBRK field
               in the TOPS-20 implementation.>

PAB$L_CTX      Programmer context longword.  The  programmer  may
               put  anything  he  wants in this longword.  When a
               programmer has multiple alternatives for  a  given
               field  and  links  together several PABs, he finds
               out which PAB actually matched  by  examining  the
               CAB$A_CURPAB  field in the CAB.  He can then index
               into this PAB to  retrieve  his  context  longword
               which  is  probably  more  useful  to him than the
               address of the  matching  PAB.   If  a  programmer
               wants more than a longword of context, he can fill
               this field in with a pointer to his context block.

PAB$A_ERR      Address of routine to be  called  if  there  is  a
               syntax  error  encountered  in the parsing of this
               field.   If  there  are  alternative  PABs  linked
               together,  this  routine is only called if all the
               alternatives  fail.   In  that  case,  the   error
                                                                         Page 40


               routines are called in reverse order, that is, the
               one in the last PAB in the chain is called  first.
               Reserved for future use.

PAB$A_SUC      Address of routine to  be  called  if  this  field
               parses successfully.  Reserved for future use.

PAB$L_STS      Error status.  If  an  RMS  error  occurred,  this
               field  is  set  to the RMS status code.  Otherwise
               this field is set to 0.  This field is  useful  to
               programmers  that want to give more complete error
               messages than the standard error messages returned
               by the recognition package.

PAB$L_STV      Error status value.  If  an  RMS  error  occurred,
               this  field  is  set  to  the  RMS  status  value.
               Otherwise this field is set to 0.  This  field  is
               useful  to  programmers  that  want  to  give more
               complete error messages than  the  standard  error
               messages returned by the recognition package.

Fields returned to the programmer:

PAB$W_VLN      Number of characters returned in the  string-value
               buffer   (specified  by  PAB$A_VBF)  not  counting
               padding in the  case  of  a  fixed  length  string
               descriptor.

PAB$L_VAL      Longword value returned  by  a  successful  parse.
               For  example,  if  the field type is HLP$K_NUMBER,
               then the number parsed  is  left  in  this  field.
               (The ATOM buffer gets the string representation of
               the number as actually entered by  the  user.)  If
               the  field  type is HLP$K_KEYWORD, the longword in
               the programmer's LIB$LOOKUP_KEY  table  associated
               with  the  keyword  that  matched  is left in this
               field.

Fields reserved for future use:

PAB$A_FLINK    Reserved for future use (link to next PAB).   This
               could  be  used  if  we  ever  want  to  allow the
               programmer to describe  his  entire  command  line
               with  one  linked  chain of PABs rather than parse
               the fields one at a time.

PAB$A_BLINK    Reserved for future use  (back  link  to  previous
               PAB).

The following 5 fields were rejected as not being necessary in an
earlier  design  review,  they  are  included  here so that other
reviewers will not wonder why it seems that little provision  has
been made for comma lists.  It was felt that the programmer could
                                                                         Page 41


chain his PABs and loop his code in such a manner  as  to  handle
comma  lists  himself  without  the  need  to  have  them handled
automatically by the recognition package.

PAB$V_SEQ      (Reserved for  future  use)  Field  to  be  parsed
               actually  consists  of  a  sequence of fields, all
               alike.  This would be a  convenience  when  it  is
               necessary  to parse off a comma-list of filespecs,
               for example.  It would be easier to set  this  bit
               than  to  write  code  to loop and make successive
               calls to LIB$PARSE_FIELD.   This  concept  is  not
               fully designed yet.

PAB$V_CMA      (Comma list) This bit only has significance if the
               PAB$V_SEQ  bit  is  set.   This bit means that the
               successive copies of the field must  be  separated
               from  each other by commas.  Spaces may optionally
               precede and  follow  the  commas.   (Reserved  for
               future use)

PAB$V_PLS      (Plus list) This bit only has significance if  the
               PAB$V_SEQ  bit  is  set.   This bit means that the
               successive copies of the field must  be  separated
               from   each  other  by  plus  signs.   Spaces  may
               optionally precede  and  follow  the  plus  signs.
               This bit may be combined with the PAB$V_CMA bit to
               mean that the fields may be separated by commas or
               plus  signs.  This is useful when parsing filespec
               lists that allow commas or plus signs to  separate
               them.  (Reserved for future use)

PAB$A_SEQ      (reserved for future use)  Action  routine  to  be
               called each time a field that is one of a sequence
               of  fields  is   found.    This   bit   only   has
               significance  if  the  PAB$V_SEQ  bit is set.  The
               action routine is called with  3  arguments.   The
               first  argument  is  the  address of the PAB.  The
               second argument is a programmer-supplied longword,
               located  at  PAB$L_SEQ_CTX.  The third argument is
               some sort  of  indicator  specifying  whether  the
               field  was  terminated  by a comma or a plus sign.
               This is not adequately designed yet.

PAB$L_SEQ_CTX  Value passed to the action  routine  specified  at
               PAB$A_SEQ, if any.  (reserved for future use)
                                                                         Page 42


3.7.9  Format Of Generalized LIB$LOOKUP_KEYWORD Table. -

For improved efficiency, and more functionality,  the  format  of
the  standard LIB$LOOKUP_KEY table is being extended in an upward
compatible manner.  Anywhere that this spec refers to  a  keyword
table,  the programmer may supply the old format (LIB$LOOKUP_KEY)
table, or the  new  format  table.   It  is  expected  that  many
existing   programs   already  contain  extensive  LIB$LOOKUP_KEY
tables, and the code has been written so that these programs need
not modify those tables.  <The additional functionality needed is
that functionality provided  by  the  TOPS-20  command  table  as
documented  by  the  TBLUK  JSYS,  as further supplemented by the
COMND JSYS.>

Table lookup service is also provided by a  new  routine,  called
LIB$LOOKUP_KEYWORD.   This  routine is upward compatible with the
standard LIB$LOOKUP_KEY RTL routine, and in  fact  could  replace
that  routine if desired;  however, I have temporarily given it a
different name, should we want to  keep  the  routines  separate.
The calling sequence is exactly the same.

Under the new scheme, the high-order bit of the first longword in
the  keyword  table  determines  whether  the  keyword table is a
generalized keyword table or an old-style keyword table.  If this
bit  is  on,  then the structure is a generalized structure.  The
main structural difference in the  new-format  structure  is  the
addition  of  a single new longword as the second longword in the
structure, containing various flag bits.  There  is  also  a  new
structure  associated with each keyword (see below).  This scheme
should provide no incompatibilities for programmers, since it  is
extremely unlikely that any user program has a keyword table with
2**31 longwords in it.

The format of the generalized keyword table thus looks like:

*********************************
*1*                 max-size    *
*********************************
*   flags       *   cur-size    *
*********************************
*          ptr                  *
*********************************
*          value                *
*********************************
*          ptr                  *
*********************************
*          value                *
*********************************
*          ptr                  *
*********************************
*          value                *
*********************************
                                                                         Page 43


      .
      .
      .

*********************************
*          ptr                  *
*********************************
*          value                *
*********************************

The main body of the table still  contains  pairs  of  longwords;
the  first  longword being a pointer to a counted string, and the
second longword being a value that  is  to  be  returned  to  the
programmer  if  that string is the one that matches.  This value,
however, is the address  of  a  structure  called  the  KIT  (the
keyword item table).

The main addition is a new set of flags that can be specified  by
the programmer.  These flags are described below:

KWD$V_ORDERED  If this bit is on, it means that the  keywords  in
               the  table  are in alphabetical order.  If we know
               that this is true, it can significantly  speed  up
               the  performance  for  keyword  recognition  (when
               there are a large number of entries).  To aid  the
               programmer in getting his entries alphabetical (if
               he is dynamically building his keyword table), two
               routines  are provided:  LIB$KEYWORD_TABLE_ADD and
               LIB$KEYWORD_TABLE_DELETE.   <These  correspond  to
               TBADD  and  TBDEL  in the TOPS-20 implementation.>
               One allows you to add a new entry and  one  allows
               you  to  delete an entry.  Two lengths are kept at
               the beginning of the table, the maximum  size  and
               the  current  size.   There  are also two routines
               provided,      LIB$ALLOCATE_KEYWORD_TABLE      and
               LIB$DEALLOCATE_KEYWORD_TABLE that let you allocate
               and deallocate a keyword table dynamically at  run
               time from virtual memory.

KWD$V_CASE     If this bit is off (the default),  it  means  that
               the source string (the one the programmer supplies
               as his first argument) is to be logically up-cased
               before  performing the match.  (We don't upcase it
               in place.) Presumably, the keywords pointed to  by
               the  table  are all in upper case.  If this bit is
               on,  this  means  that  the  programmers   command
               language  contains  case  sensitive  keywords.  In
               that case an exact match must  occur  bewteen  the
               supplied  keyword  and  the entries in the keyword
               table, and lower case does not match upper case.

KWD$B_MAX      A byte field specifying that there is a  limit  on
               the  number of characters that need match.  A 0 in
                                                                         Page 44


               this field is  the  default  and  means  that  all
               characters  must  match.  This field is needed for
               DCL.  DCL has the property that you can type extra
               characters  after  the  first four characters in a
               command keyword and it will not complain (i.e.

                          SET PROCEDURE/PRIVATE=GROUND

               is treated as a valid command to DCL with no error
               message given.  It is equivalent to

                          SET PROCESS/PRIVILEGE=GROUP

               since all the keywords agree up  to  the  first  4
               characters.)   Personally,  I  feel  that  such  a
               command should give an error message, but that  is
               the  way  DCL  is  documented to work;  so if they
               don't want to change it, we need this field.   DCL
               would  set this field to a 4 to indicate that only
               the first 4 characters must match.

The pointer in the first longword of each pair of  table  entries
now  points  to  a  string  descriptor  rather  than to a counted
string.

The second longword in each pair  of  entries  now  points  to  a
structure called the KIT (Keyword Item Table).

The fields within the KIT are described below.

KIT$L_VAL      The value longword.  This is guaranteed to be  the
               first longword in the KIT.  This value is supplied
               by the user and corresponds to the value  that  he
               used  to  place in the keyword table as the second
               longword of each entry pair.

KIT$V_INV      The  keyword  is  to  be  invisible.   <This   bit
               corresponds  to  the  CM%INV  bit  in  the TOPS-20
               implementation.> This bit would be set if you want
               to  hide a keyword so that it does not appear when
               you type the <HELP> key.  This could  be  used  to
               hide  debugging  keywords  from  users.   The more
               common use for this bit is to suppress the listing
               of  obsolete  keywords  from  the incremental help
               message.   For  example,  in  the   SET   TERMINAL
               command,  the  qualifier /VT52 has been superseded
               by the qualifier  /DEVICE_TYPE=VT52.   By  setting
               this  bit for the /VT52 keyword, it would still be
               accepted by the parser, but the user would not  be
               shown this keyword when he typed <HELP>.  This bit
               is used entirely by LIB$PARSE_FIELD and is ignored
               by LIB$PARSE_LOOKUP_KEY.
                                                                         Page 45


KIT$A_ABV      If non-0, this keyword  is  to  be  considered  an
               abbreviation for another keyword in the table (the
               value of this field is the  address  of  a  string
               descriptor  for  the keyword that this entry is an
               abbreviation of.) <This  bit  corresponds  to  the
               CM%ABR  bit  in  the TOPS-20 implementation.> This
               bit allows you to override  the  otherwise  normal
               command   abbreviation  rule.   For  example,  DCL
               allows the R command to be an abbreviation for RUN
               and typing R means RUN even though there are other
               valid DCL commands beginning with  the  letter  R.
               To  make  this  happen,  you would specify in this
               field that R is really an  abbreviation  for  RUN.
               Another  example  is the debugger which allows "E"
               to be a  valid  abbreviation  for  "EXAMINE"  even
               though  "E"  conflicts  with  the  "EXIT" command.
               Similarly, "SE"  in  MAIL  means  "SEND"  and  not
               "SEARCH".

KIT$V_NOR      (No recognize).  Do not  recognize  this  keyword.
               If  an  exact  match  on  this  keyword  is found,
               LIB$LOOKUP_KEYWORD   will   still    return    the
               LIB$_AMBKEY (ambiguous keyword) status.  <This bit
               corresponds to  the  CM%NOR  bit  in  the  TOPS-20
               implementation.>  This  is  useful  if you want to
               insist that certain dangerous keywords have to  be
               spelled  out.  Thus if you wanted the user to have
               to type "DEL" to mean  "DELETE"  even  though  "D"
               might  be  perfectly  unambiguous to your program,
               you would enter the two keywords "D" and "DE" into
               your keyword table with this bit set.

KIT$V_NEG      Keyword  is  negatable.   The  negation  is   also
               entered  elsewhere  in  the  table  in  its normal
               alphabetical  position  (with  the  KIT$V_NOT  bit
               set).   If the <HELP> key is typed when you are at
               the beginning of the keyword field,  this  bit  is
               used  to  enable  the  help message to combine the
               keyword   and   its   negation   in   the   format
               "[NO]KEYWORD"  in  the  incremental  help display.
               This bit is ignored by LIB$LOOKUP_KEYWORD and used
               only  by  LIB$PARSE_FIELD.  Since efficiency calls
               for the  keywords  to  be  entered  in  the  table
               alphabetically,  this  scheme permits keywords and
               their negations to appear together rather than far
               apart.  This is a hack, pure and simple.

KIT$V_NOT      This keyword is the negation of some other keyword
               in  the  table.   The  negation  must  be  entered
               separately   and   in   alphabetical   order   for
               efficiency  reasons (even though it may be alluded
               to be an earlier  entry  with  the  KIT$V_NEG  bit
               set).
                                                                         Page 46


KIT$V_VAL      The keyword takes a  value.   The  user  enters  a
               value  by  specifying  a colon or equal sign after
               the keyword, followed by the  value.   It  is  the
               programmers responsibility to code additional PABs
               to handle the parsing of the keyword value.   This
               bit  just  tells  the  recognition  package that a
               value is legal so that it can display  an  "="  at
               the  end  of  the  keyword in the incremental help
               text.  An example of a keyword that takes a  value
               is the DCL command

                                 SET CONTROL=T

               where the keyword  parameter  "CONTROL"  takes  an
               otpional  value  of  either  "T"  or  "Y".  A more
               frequent use of this field occurs with  qualifiers
               that take values.

KIT$V_REQ      The keyword takes a required value.  Must  be  set
               in  addition  to  the KIB$V_VAL bit.  Reserved for
               future use.

KIT$A_PFX      The address of a counted string for  the  negation
               prefix.   If 0, the standard negation prefix, "NO"
               is  assumed.   This  field  is  ignored   if   the
               KIT$V_NEG bit is not set.  This field is needed by
               DECset for the commands

               DECset> SET COMMAND/[NON]STANDARD

               and

               DECset> PURGE database/[NOT]NOW

               and

               CUSTOM> SHOW parameter/[UN]SCALED

               and could be used by  DCL  in  a  few  places,  if
               desired,  such as the /NOSTANDARD qualifier to the
               PASCAL   command   could   be   changed   to   (or
               supplemented  by)  /NONSTANDARD  which  is  a real
               word.

KIT$A_EXPL     Reserved for use by DECset.  Address of  a  string
               descriptor  containing an explanation of what this
               keyword  means.    DECset   maintains   its   help
               information  about  commands  with  the  commands,
               rather than in a separate help library  which  can
               become  obsolete  when  the commands change or new
               commands get added.

KIB$B_MIN      Minimum number of characters that must match.   If
                                                                         Page 47


               this field is non-0, then this keyword will not be
               matched unless this minimum number  of  characters
               is  found  correctly.  For example, in DCL, if you
               define    a    symbol     with     the     command
               FOO*BAR="TESTING",  then  this means that you have
               created a new symbol FOOBAR and  the  first  three
               characters,  "FOO"  must  match before the keyword
               FOOBAR is found, even though typing one character,
               F,  might  be  enough  to  uniquely  identify this
               keyword.

KIT$B_MAX      If this field is non-0, it overrides the KWD$B_MAX
               field (if there was one) in the keyword table.  It
               specifies the maximum number  of  characters  that
               need  be  checked  for this keyword to be a match.
               All additional characters are  not  checked.   The
               reason  to  have this override is in case you want
               to merge two sets of keywords into one table,  and
               some   are  the  kind  that  want  to  ignore  all
               characters  after  4,  say,  and  some  want   all
               characters  checked.   This  would  be useful, for
               example, if DCL wanted to  merge  it's  verbs  and
               it's  user-defined  symbols into one large keyword
               table instead of two.




3.7.10  Service Routines -

The following routines  are  available  to  programmers  who  are
writing their own help and recognition routines:

     1.  LIB$COLLECT_INIT

     2.  LIB$COLLECT_STORE

     3.  LIB$COLLECT_ABORT

     4.  LIB$COLLECT_OUTPUT


These routines form a sub-package known as "the collector".  They
are  used  to  collect  recognized  characters  and  decide which
characters are common to all  the  strings  recognized.   Calling
sequences  for these routines can be found in the routine headers
of module LIB$COLLECT in file HLPCOLECT.B32.

DECset will use this interface to handle recognition of  database
names and document names.  DCL might use this interface to handle
recognition  of  DCL  symbols.   The  debugger  might  use   this
interface  to  do  recognition  of  user  symbols, since they are
currently hashed and it would not be convenient to put them  into
                                                                         Page 48


the LIB$LOOKUP_KEY table format.



3.7.11  Problems -


     1.  Quoted string problem.   For  example,  DCL  allows  the
         command

         $ MAIL FOO.BAR "STAN"

         yet the STAN field should permit help and recognition as
         a  username  field  not  as  a  quoted  string field.  I
         probably need a new bit to say that an otherwise  normal
         entity is permitted to be enclosed in double quotes.

     2.  Too many keywords problem.  Some commands will  take  an
         inordinate  number  of  keywords,  such  as the debugger
         which could have thousands of choices for certain fields
         (when  a  user symbol is permitted).  We do not want all
         these choices listed when he types "?".  Do we  suppress
         the  list  of choices when there are more than n?  Do we
         let the user customize this?  Do we pick another key  to
         mean "give me lots of help"?

     3.  Many users have suggested to me that "?" when typed to a
         filespec  should actually list all the choices.  The way
         the code is written, this is actually easy to do, but  I
         didn't  do  it  because  of  the  above  problem  - that
         frequently  there  are  too   many   choices   to   list
         conveniently.  Comments?

     4.  Foreign language customization.   Most  of  my  messages
         come  from  message  files  or are specified by the user
         program.  However there are 3 or 4 messages  built  into
         the  program, such as the message "one of the following"
         and the word "or".  This will not be good when we  allow
         switching  to a foreign language, like French.  However,
         I don't relish all the  extra  overhead  that  would  be
         involved  if I had to pick up the "one of the following"
         message from a message file each time a user  typed  "?"
         so I didn't code it that way.  Ideas?

     5.  Terminal driver problem.   The  terminal  driver  change
         that  we  requested did not get into V3A.  It appears to
         be in FT1 of V4, so the current  inefficiencies  can  be
         fixed for V4.

     6.  RMS BUGS.  RMS currently provides no clean way to  abort
         a  long  file operation.  If a user attempts recognition
         of a filespec with  wildcards  in  a  directory  and  it
         starts  taking  too  long  and he types CTRL/C, the only
                                                                         Page 49


         documented way of cleaning up is  to  have  a  condition
         handler  that reacts to an unwind and tries to close any
         open FABS, but it might  get  "file  activity  precludes
         operation" errors.  If it waits for the file activity to
         finish, then the system is not  properly  responding  to
         CTRL/C  (the user should not have to wait 60 seconds for
         his $ prompt to  come  back  after  a  CTRL/C).   If  it
         doesn't wait for the FAB to free up, but resignals, then
         the code could be entered again before the FAB  is  free
         and screw up on the user's next recognition request.

     7.  Simple Interface and ASTs.  I do not see an easy way  to
         make   the   simple   programmer  interface  scheme  AST
         re-entrant.  It builds a CAB and PAB behind  the  user's
         back  and LIB$PARSE_FIELD reaches into this area (in OWN
         storage) instead of us telling the user he has  to  pass
         the  address  of  a  CAB,  which  he has never heard of.
         Another call to LIB$PARSE_INPUT  from  AST  level  would
         wipe  out  the  main-line's  CAB.  The general interface
         does not have this problem because the CAB is passed  as
         an explicit argument on each call.

     8.  ?  to HELP.  For VMS V3A, the VMS  group  used  the  "?"
         character   in   the  HELP  command  to  mean  something
         different (although similar) from what it would mean  if
         DCL were to use this recognition package.  (((I spoke to
         Halvorsen about this, suggesting that the "?"  character
         in  HELP  be changed to something else and he assured me
         that there would be no problem changing its  meaning  to
         "incremental  help"  should  DCL be modified to use this
         recognition package.)))

     9.  Filetype search chains.  Some  commands  allow  multiple
         filetypes  in  a  parameter  field.   For  example,  the
         command BLISS FOO will first  look  for  a  file  called
         FOO.B32 to compile, and if it doesn't find it, will then
         look  for  a  file  call  FOO.BLI   to   compile.    The
         recognition  package  only  lets you specify one default
         file string in the call to parse a filename, so in  this
         case,   ".B32"   would   probably  be  specified.   Thus
         filenames with the .BLI file type would  be  legal,  but
         would not be recognized when the user types <RECOGNIZE>.
         If there are going to be a lot of cases like this,  then
         we  might  want  to  design something in to allow search
         chains of some sort.  It may be able to  use  V4  search
         lists to implement this feature.

    10.  Centralized  Filespec  parsing.   The  VMS   group   has
         (rightly) requested that all filespec parsing be done in
         one centralized spot  (such  as  in  RMS).   This  would
         prevent  user  programs  from having to change in future
         releases of VMS as extensions are made to the syntax  of
         a  filespecification.  The recognition package currently
                                                                         Page 50


         has to know what a filespec looks like because there are
         no  routines  provided  by RMS or VMS that allows a user
         program to analyze partial filespecifications.




4.0  COMPATIBILITY

There should be a minimum adjustment period for users who migrate
from  -20's  to  VAX'es  since  the  user-level interface is very
similar.



5.0  PACKAGING AND SYSTEM GENERATION

Certain macros and structure declarations should be  included  in
STARLET.   If  the  VMS group prefers, these definitions could be
supplied in a completely separate library.

The code does not have to be linked with SYS.STB.



6.0  DOCUMENTATION

This functional specification plus the routine  headers  for  all
the  routines in the package provides all the documentation about
the recognition package that will be turned over to the RTL group
when this package is submitted to them.




7.0  REFERENCES

TOPS-20 Monitor Calls Reference Manual, AA-4166D-TM.