Trailing-Edge
-
PDP-10 Archives
-
tops20tools_v6_9-jan-86_dumper
-
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.