.ps 60,72
.nj;.lm 0
.c;Argonne National Laboratory
.c;Applied Mathematics Division
.s 2
.c;COMMAND LINE SUBROUTINES
.c;FOR RSX-11M FORTRAN
.s 2
.c;April 1982
.s 2
.c;Martin R. Kraimer
.s 2
.c ;Abstract
.p
This manual describes a number of Fortran command line subroutines
that allow a Fortran programmer to quickly and easily write
interactive programs for the RSX-11M operating system.
RSX-11M is an operating system for the Digital Equipment Corporation
(DEC) PDP-11 series of computers.
These command line subroutines provide terminal input/output and
syntax analysis capabilities.
The terminal I/O subroutines support indirect command files
that can contain imbedded prompt strings.
They also provide TRACE, HELP, and LEARN support.
The syntax analysis subroutines are designed to process input
lines obtained from indirect command files or from a terminal.
.ch INTRODUCTION
.nj;.lm 0
.p
The subroutines described in this manual allow a programmer
to quickly and easily write interactive programs.
The routines can be used both for "command language" and
for "menu-type" programs.
Simple examples of each type of program are given later
in this manual.
The subroutines have been written for use under the PDP-11
RSX-11M operating system,
and are compatible with the Fortran-IV, Fortran-IV-Plus,
and the Fortran-77 compilers.
.p
The subroutines can be divided into the following classes:
.ls 1;.le
Terminal I/O
.le
Syntax Analysis
.le
Character String Manipulation
.le
Command Processing
.els
.lm 5
.s 1
^&Terminal I/O Subroutines\&
.p
The terminal I/O subroutines interact with the terminal.
.p
The PROMPT subroutine prompts for and obtains input from
a terminal.
PROMPT allows indirect command files,
processes three special commands (TRACE, LEARN, and HELP),
and allows prompt strings to be imbedded within
indirect command files.
When TRACE is on, each line taken from an indirect command file
is displayed on the user's terminal.
When LEARN is active, all lines entered by the user are saved
in a file that can later be used as an indirect command file.
HELP invokes the RSX-11M HELP processor.
Indirect command files can
have imbedded prompt strings.
When PROMPT finds an imbedded prompt string, it prompts the user at
his terminal and replaces the prompt with the user's response.
.p
The PLINE subroutine writes on the user's terminal.
.P
USIBEG and USIEND allow the calling program to process
unsolicited terminal input.
This is useful for programs that produce long listings, etc.
By using USIBEG and USIEND, the program can allow the user
to interrupt the program without aborting the program.
.s 1
^&
Syntax Analysis Subroutines
\&
.p
Syntax analysis subroutines are used to perform syntax analysis.
.p
The TOKEN subroutine locates the next token in
the current input line.
The token types are null (i.e., a leading comma),
end-of-line, empty line, octal integer,
decimal integer, floating-point number, name, and special character.
.p
The SYNERR, (Syntax Error) subroutine displays the current input line
with the previous token replaced with question marks.
It can be used to show the user exactly where he
made an error.
.s 1
^&
Character String Manipulation Subroutines
\&
.p
Character string manipulation subroutines provide the Fortran programmer with a
basic set of routines to perform character string manipulation.
They are used extensively by the other subroutines described
in this manual.
.s 1
^&
Command-Processing Subroutines
\&
.p
The command-processing subroutines makes it a little easier
to write command-processing programs.
.lm 0
.p
The command line routines communicate with each other and with
the program using them through common block CLP.
CLP must be thoroughly understood before
the user can understand and use the subroutines described in this manual.
CLP is listed in Appendix A.
Let's briefly describe the variables in CLP.
.p
TYPNUL, TYPEOL, TYPEL, TYPINT, TYPFLT, TYPNAM, and TYPSPC are
the token types recognized by subroutine TOKEN.
.p
TLU is the terminal logical unit.
Any subroutine can perform input or output to this logical unit.
.p
CLPEFN is an event flag usable by any routine that
does an immediate wait on this event flag.
In particular, it is used by subroutine PROMPT.
.p
CNTLZ is a logical variable that is set true when
PROMPT detects an end-of-file in the level 0 indirect
command file or when the user types CNTL/Z.
This is a signal that the program should clean up and
exit.
.p
TRACE is set if trace mode is in affect.
PROMPT uses this to decide if prompts and input lines
should be echoed to the user's terminal.
.p
NXTCHR is a variable that points to the next character
of LINE not yet processed by TOKEN.
.p
TOKLEN is the length of the previous token processed by TOKEN.
.p
TOKTYP is the type of the previous token processed by TOKEN.
.p
INTVAL, FLTVAL, STRVAL, and CHRVAL are the
integer, floating-point, string, and first-character values
of the previous token processed by TOKEN.
.p
USICHR is the most recent character trapped by the
unsolicited terminal input routines.
This variable is described with the USIBEG and USIEND routines.
.ch TERMINAL I/O SUBROUTINES
.nj;.lm 0
.p
This chapter describes six routines: PROMPT, PLINE,
GCML, USIBEG, USIEND, and USIAST.
PROMPT is responsible for getting the next line of input.
PLINE sends an output line to the user's terminal.
GCML is an assembly language interface used by PROMPT
that provides access to the RSX-11M command-line
processing subroutines (described in the
^&RSX-11M I/O Operations Manual\&).
USIBEG and USIEND are used to process unsolicited terminal input.
USIAST is an assembly language routine used by USIBEG.
First, we'll describe the services provided by these subroutines,
and then we'll summarize the algorithms used by each subroutine.
.hl 1 Use of PROMPT Subroutine
.p
Whenever a program wants a new line of terminal input, it issues
the following Fortran statement:
.s 1
.i 5
CALL PROMPT(STR)
.i 0
.s 1
STR is a character string that is used to prompt the
operator for input taken from the terminal.
If the input is taken from an indirect command file,
STR is ignored.
If STR is not a null string, a "?" is appended to the
end of STR.
The characters tsk>, where tsk is the first three characters of the task name,
are always put before STR.
Note that a zero parameter will be accepted as a null string.
As examples, assume that the task name is "TST".
If the call is
.s 1
.i 5
CALL PROMPT(0)
.s 1;.i 0
then the operator will be prompted
.s 1;.i 5
     TST>
.s 1;.i 0
If the call is
.s 1;.i 5
     CALL PROMPT('COMMAND')
.s 1;.i 0
the prompt is
.s 1;.i 5
     TST>COMMAND?
.s 1;.i 0
.i 0
.hl 2 Using Indirect Command Files
.p
PROMPT, in conjunction with GCML, provides support for indirect
command files.
If input is being taken from indirect command files,
STR is ignored.
GCML is initialized to provide support for three levels of indirect
command files.
Indirect command files can be invoked in three ways:
.ls 1;.le
As a parameter on an MCR command line.
.le
In response to a prompt from PROMPT.
.le
As a line in an indirect command file.
.els
.p
An example of the first method, a parameter
on an MCR command line, is:
.i 5
.s 1
>TST @filename
.i 0
.s 1
TST must be an installed task for this to work.
If an indirect command file is invoked this way,
CNTLZ will be
set true when an end-of-file is detected in file "filename".
Thus, unless an indirect command file has imbedded prompt strings,
program TST will run to completion without any operator intervention.
Thus it is possible to write indirect command files
containing requests to run tasks which call PROMPT.
.p
The second method of invoking an indirect command file
is to specify an indirect command file in response to
a prompt issued by PROMPT.
For example,
.i 5
.s 1
TST>@filename
.i 0
.s 1
If this case, each call to prompt, beginning with the initial call,
causes a line of input to be read from file "filename".
This continues until an end-of-file is detected in file "filename".
At this point, a prompt is written to the terminal
and input is accepted from the terminal.
CNTLZ will be set only when the operator enters CNTL/Z.
.p
The last way to invoke an indirect command file is to
invoke it from another indirect command file.
For example, a line of an indirect command file can be
.i 5
.s 1
@filename
.s 1
.i 0
Note that GCML allows only three levels of indirect command files.
For more details about indirect command file
processing, consult the ^&RSX-11M I/O Operations Manual\&.
.i 0
.hl 2 Using TRACE, LEARN, and HELP Commands
.i 5
.p
Upon receiving an input line, PROMPT checks to
see if the line begins with the commands "TRACE", "LEARN", OR "HELP".
If so, the command is processed and PROMPT begins again.
Thus the calling program is not aware that the
command has been processed.
.p
The TRACE command switches the state of the CLP variable TRACE.
TRACE is initially off.
The first TRACE command sets it on,
the next TRACE command sets it off, etc.
When TRACE is on, PROMPT echos all prompts and input lines.
.p
The LEARN command is used to create indirect command files.
LEARN mode is either on or off.
Initially it is off.
The first LEARN command turns it on,
the second turns it off, etc.
When the LEARN mode is turned on, the operator is prompted:
.s 1
    FILE NAME?
.s 1
The operator must respond with the name of the file to be
created.
The default device is "SY:" and the default extension is ".CMD".
While LEARN mode is on, PROMPT writes all prompts,
preceeded by the character ";", to the file.
It also writes all input lines.
All TRACE and HELP commands are also written.
.p
The HELP command invokes the standard RSX-11M help processor.
The first three characters of the task name are inserted after
HELP.
Thus if the operator types
.s 1
    HELP GO
.s 1
The command sent to the help processor is
.s 1
    HELP tsk GO
.s 1
where tsk is the first three characters of the task name.
Note that the HELP command will only work
for installed tasks that have help files on LB:[1,2].
See the ^&RSX-11M MCR Operations Manual\& for details
about creating help files.
.hl 2 Using Imbedded Prompt Strings
.p
Whenever PROMPT receives an input line, it looks
for imbedded prompt strings.
A prompt string is a string of the form "?<string>".
Upon finding such a prompt string, PROMPT prompts
the terminal with
.s 1
    string>
.s 1
and accepts input from the terminal.
The entire prompt string is replaced by the terminal input.
The input line is repeatedly scanned until no more prompt
strings are found.
For example, if the original input line is
.s 1
    CMD ?<ENTER PARM 1>,2,?<ENTER PARM 2>
.s 1
The operator will be prompted twice as follows:
.s 1
    ENTER PARM 1>
.br
    ENTER PARM 2>
.s 1
If the operator responds with the values 25 and 10,
then the resultant line will be:
.s 1
    CMD 25,2,10
.p
Indirect command files can be created either with a standard editor
or by using the LEARN command.
If the LEARN command is used, imbedded prompt strings
can be placed in an input line.
The original line, i.e., the line with the imbedded prompt
strings, is written to the LEARN file.
The operator will still be prompted
for values for the imbedded prompt strings, but the
resultant line is not written to the LEARN file.
.hl 1 Processing Unsolicited Terminal Input
.p
If a program performs a function that can take a long time,
it is desirable to allow the operator to terminate the function
without terminating the program itself.
An example is a listing program.
The operator might give a list command which results
in an extremely long listing.
After viewing a part of the list he wishes to stop the
listing without aborting the program.
The subroutines USIBEG and USIEND allow a program
to do this in an easy manner.
USIBEG traps all terminal input.
The most recent character entered is stored in the variable
USICHR, which is located in the CLP named common block.
This continues until USIEND is called.
The calling program should periodically check the value
of USICHR.
If it is not zero then the user has entered one or more characters.
When USIBEG is called, USICHR is initialized to zero.
CTRL/C, CTRL/S, CTRL/Q, CTRL/X, and CTRL/O
are not trapped by USIBEG but are handled in the normal manner.
.p
A program using USIBEG and USIEND has the following structure:
.sk;.nf
	CALL USIBEG
loop:	IF(USICHR.NE.0)GOTO exit
	do small amount of processing
	GOTO loop
exit:	CALL USIEND
.sk;.f
Please note that no other terminal I/O routines
should be called while USIBEG is active.
.hl 1 Summary of Subroutine Algorithms
.hl 2 Prompt
.p
Syntax: PROMPT(STR)
.p
When PROMPT starts execution, it first determines whether this is
the first call.
If it is, PROMPT determines the first three characters of the task
name under which is is being executed.
PROMPT then constructs the prompt string and calls GCML.
GCML returns the input line in LINE, which is a variable
in CLP.
If GCML detects an end-of-file,
PROMPT sets CNTLZ true and returns.
If no end-of-file is detected, PROMPT looks for
a TRACE, LEARN, or HELP command.
If one is found, the command is processed and PROMPT begins again.
If none is found, PROMPT looks for imbedded prompt strings.
If any are found, they are processed.
After all imbedded prompt strings have been processed, PROMPT returns.
When prompt returns, the CLP common block is initialized
so that the first call to TOKEN will return the first token in LINE.
.hl 2 Put Line
.p
Syntax:PLINE(STR)
.p
The PLINE subroutine outputs STR to the user's
terminal.
STR must be a valid character string
(any ASCII characters terminated by a zero byte).
.hl 2 Get Command Line
.p
The GCML Subroutine is the assembly language interface to the RSX-11M
command line processing facilities.
It is set to allow three levels of indirect command files.
This subroutine is normally called only by PROMPT.
GCML also has entry points, RCML and CCML, which
invoke the RCML$ and CCML$ routines.
See the
^&
RSX-11M I/O Operations Manual
\&
for more details.
.hl 2 Unsolicited Terminal Input
.p
USIBEG calls USIAST.
USIAST provides an AST exit which is entered whenever the
operator strikes a key on TLU.
Each time this happens,
the character is moved to CSICHR.
USIEND removes the AST exit.
.ch SYNTAX ANALYSIS
.nj;.lm 0
.hl 1 Introduction
.p
The subroutines described in this chapter help a programmer
process input lines obtained by PROMPT.
Each time TOKEN is called, it locates and converts the next token
contained in LINE.
If the program detects an illegal token (a token
it is not expecting), SYNERR can be called to show the
user the token that was incorrect.
TOKEN has no parameters.
All communication is performed by using the CLP common block.
As an example of what TOKEN does, assume that the input line is:
.i 5
.s 1
TEST 1,1.0 $,,"100000
.i 0
.p
The first call to TOKEN will set TOKTYP=TYPNAM and STRVAL="TEST".
The second call will set TOKTYP=TYPINT and INTVAL=1.
The third call will set TOKTYP=TYPFLT and FLTVAL=1.0.
The third call returns TOKTYP=TYPSPC and CHRVAL='$'.
The fourth call returns TOKTYP=TYPNUL.
The next call returns TOKTYP=TYPINT and INTVAL=-32768.
The last call returns TOKTYP=TYPEOL.
Note that blanks or blanks and a single comma separate tokens,
except for special characters.
For special characters, the separators are optional.
The description of TOKEN that follows is rather complicated;
it is meant to be complete.
If you keep the above example in mind, the description should
be easier to follow.
A serious effort has been made to make TOKEN do "reasonable"
things for ambiguous cases.
.s 1
.hl 1 Token
.p
This routine gets the next token from LINE.
TOKEN first decides where the next token begins.
It uses the following algorithm to make this decision:
.ls 1;.le
If NXTCHR > 1 and LINE(NXTCHR) = "," and the rest of
LINE is blank, then TOKEN calls PROMPT and starts all over.
.le
If NXTCHR = 1 and LINE(1) = "," then TOKEN begins
with column 1.
.le
If NXTCHR > 1 and LINE(NXTCHR) = "," then TOKEN begins
with the first non-blank character beginning with LINE(NXTCHR+1).
.le
If LINE(NXTCHR) not = "," then TOKEN begins with the first
non-blank character beginning with LINE(NXTCHR).
.le
If a ";" is detected, the semicolon and the remainder of the line is ignored.
.els
.p
These rules allow for the following.
.ls 1;.le
If a line ends with a comma, then TOKEN automatically
calls PROMPT to obtain another line.
.le
If a line begins with a comma, then the first token of that line
will have type TYPNUL.
.le
If a line has two consecutive commas, then the second will
result in a token with type TYPNUL.
.le
If a semicolon is detected, the remainder of the line
is ignored, that is, it is assumed to be a comment.
Note, that if a line begins with a semicolon, the GCML
subroutine ignores the line.
.els
.p
While processing the next token of LINE, TOKEN sets the following
fields in CLP:
.ls 1;.le
NXTCHR is set equal to the index of the first character
of the token following the token currently being analyzed.
It should be noted that a token is terminated by a blank,
a comma, or a special character.
If a token is terminated by a blank, then NXTCHR
will be set equal to the index of the first non-blank
character after this blank.
If a token is terminated by a non-blank character, then
NXTCHR is set equal to the index of this character.
.le
TOKLEN is set equal to the number of characters processed
in this call to TOKEN.
.le
INTVAL, FLTVAL, STRVAL, and CHRVAL are set equal to the
converted value of the token.
.ls 2;.le
INTVAL is set equal to the integer value of the token
if it is a number; otherwise, it is set equal to the
smallest possible integer (-32768).
.le
FLTVAL is set equal to the floating value of the token
if it is a number; otherwise, it is set equal to 1.0E30.
.le
If the token is of type TYPINT, TYPFLT, or TYPNAM,
STRVAL is set equal to the character string of which the token is composed;
otherwise, STRVAL is set equal to the null string.
.le
If TOKTYP is not equal to TYPNAM or TYPSPC, CHRVAL is
set equal to a binary 0 (the lowest possible character).
If TOKTYP=TYPNAM, CHRVAL is set equal to the first character
of STRVAL.  If TOKTYP=TYPSPC, CHRVAL is equal to the special character.
.els;.le
TOKTYP is set equal to the token type, which may
be one of the following:
.ls 2;.le
TYPNUL - Either a line begins with a comma, or two consecutive
non-blank characters beginning with LINE(NXTCHR) are
commas.
.le
TYPEOL - no more non-blank characters in LINE.
Note that this cannot happen if the last non-blank character
in a line is a comma.
.le
TYPEL - LINE is initially blank
.le
TYPINT - token is a valid FORTRAN INTEGER constant.
TOKEN also allows octal integers.
Any field beginning with the character '"' is assumed to be an
octal integer.
.le
TYPFLT - token is a valid FORTRAN REAL constant.
.le
TYPNAM - token begins with an alphabetic character
and is followed by an arbitrary number of alphanumeric
characters.
.le
TYPSPC - token is a special character, i.e., NXTCHR
does not begin a character string that is any of
the above types of token.
.els
.els
.s 1
.hl 1 Syntax Error
.p
The name SYNERR means Syntax Error.
The SYNERR subroutine first displays the current input LINE.
It then replaces the previous token by question marks,
and redisplays the line.
.ch CHARACTER STRING MANIPULATION ROUTINES
.nj;.lm 0
.hl 1 Introduction
.p
Because Fortran does not provide the ability to manipulate
character strings, this library contains a number of subroutines
that process character strings.
A single character is a LOGICAL*1 variable.
A character string is a LOGICAL*1 array that
is terminated by a zero byte.
If an argument of the form 'string'
is passed to a subroutine, Fortran-IV, Fortran-IV-Plus,
and Fortran-77 append a null byte to the character string.
Thus constant strings can be given as arguments to subroutines.
It is the programmer's responsibility to ensure that a
string does not overflow the array in which it is stored,
and that all strings and characters are declared correctly.
If you are using Fortran-77, the character string
must still be declared as LOGICAL*1, not CHARACTER.
CHARACTER variables may not be passed to any subroutines
described in this manual.
.hl 1 String Length
.p
Syntax:  LENSTR(STR,LEN)
.p
The LENSTR subroutine determines the length of a specified
character string.
LEN is set equal to the length of the string STR.
LENSTR looks for the first null (zero byte).
The call
.s 1
.i 5
CALL LENSTR('EXAMPLE',LEN)
.s 1
.i 0
will set LEN equal to 7.
.hl 1 Insert Character
.p
Syntax:  ICHR(STR,IND,CHR)
.p
The ICHR subroutine inserts a specified character before the
indicated character of the specified character string.
CHR is inserted before the INDth character of STR.
If IND > LENGTH (STR), then CHR is concatenated to the end of STR.
If STR is initially "TST", then after
.s 1
.i 5
CALL ICHR(STR,2,'E')
.s 1
.i 0
STR will have the value "TEST".
.i 0
.hl 1 Concatenate Characters
.p
Syntax:  CCCHR(STR,CHR)
.p
The CCCHR subroutine is used to concatenate a specified
character onto the end of a specified character string.
CHR is concatenated onto the end of STR.
If STR is initially "TEST", then after
.i 5
.s 1
CALL CCCHR(STR,'1')
.s 1
.i 0
STR will have the value "TEST1".
.hl 1 Concatenate String
.p
Syntax: CCSTR(STR1,STR2)
.p
The CCSTR subroutine is used to concatenate a specified
character string onto another character string.
STR2 is concatenated onto the end of STR1.
If STR is initially "NEW" then after
.s 1
     CALL CCSTR(STR,' TEST')
.s 1
.i 0
STR will have the value "NEW TEST".
.hl 1 Get Substring
.p
Syntax:  GSTR(STR1,BEG,END,STR2)
.p
The GSTR subroutine gets the substring beginning
and ending with the specified characters of the
specified string.
STR2 is set equal to the substring of STR1 whose first
character is BEG and whose last character is END. No
check is made to see if BEG and END are within STR1.
After the call,
.i 5
.s 1
CALL GSTR('ABCDEF',3,4,STR)
.s 1
.i 0
STR will have the value 'CD'.
.hl 1 Delete Substring
.p
Syntax:  DSTR(STR,BEG,END)
.p
The DSTR subroutine deletes a substring beginning and ending
with the specified characters of the specified string.
The substring of STR from BEG to END is deleted.
For example, if the string is "ABCDE" and the call is
.s 1
.i 5
CALL DSTR(STR,2,3)
.s 1
.i 0
then STR will have the value "ADE".
.hl 1 Insert String
.p
Syntax:  ISTR(STR,IND,STR2)
.p
Subroutine ISTR inserts a specified character string
before the indicated characters of another specified character string.
It inserts STR2 into STR1 before the INDth character of STR1.
If IND > LENGTH(STR), then STR2 is concatenated to the end of STR1.
If STR is initially "MARTIN KRAIMER", then after
.i 5
.s 1
CALL ISTR(STR,8,'R. ')
.s 1
.i 0
STR will have the value "MARTIN R. KRAIMER".
.hl 1 Move String
.p
Syntax:  MSTR(STR1,STR2)
.p
The MSTR subroutine replaces one specified character
string with another specified string.
It moves STR1 to STR2.
After a call to MSTR, STR2 will have exactly the same value as STR1.
.hl 1 Blank Removal
.p
Syntax:  RLBS(STR) and RTBS(STR)
.p
The RLBS subroutine removes all leading blanks from
the specified string, STR, while the RTBS
subroutine
removes all trailing blanks from the specified string, STR.
.hl 1 Get Index of Character
.p
Syntax:  GICHR(STR,CHR,IND)
.p
The GICHR subroutine is used to determine the position
or index of the indicated character within the specified string.
It gets the index of CHR within STR.
STR is searched for the first character equal to CHR.
IND is set equal to the location within STR.
If the character does not appear within STR,
IND is set equal to zero.
After the statement
.s 1
.i 5
CALL GICHR('12/25/41','/',IND)
.i 0
.s 1
IND will have the value 3.
.i 0
.hl 1 Compare Strings
.p
Syntax:  CMPSTR(STR1,STR2,IRES)
.p
The CMPSTR subroutine compares two strings and indicates
whether they match or not.
IRES is set equal to (-1,0,1) if STR1 is (<,=,>) STR2.
The comparison is first on the collating sequence and then on
the lengths of the strings.
.i 5
.s 1
Examples:
.s 1
CMPSTR('ABCD','ABCD',IRES)##IRES=0
.br
CMPSTR('ABCD','ABCF',IRES)##IRES=-1
.br
CMPSTR('ABDD','ABCD',IRES)##IRES=+1
.br
CMPSTR('ABC','ABCD',IRES)###IRES=-1
.i 0
.hl 1 Convert String to Integer
.p
Syntax:  CSTI(STR,IVAL)
.p
The CSTI subroutine converts an integer character string
to an integer value.
It converts STR to an INTEGER value and stores it in IVAL.
Note that STR must represent a valid integer.
After the call,
.i 5
.s 1
CALL CSTI('123',IVAL)
.i 0
.s 1
IVAL will be equal to 123.
IVAL must be an INTEGER*2 variable.
.i 0
.hl 1 Convert String to Octal
.p
Syntax:  CSTO(STR,IVAL)
.p
The CSTO subroutine convert an octal integer character string
to an octal integer.
It converts STR to an OCTAL integer and stores it in IVAL.
Note that STR must represent a valid octal integer.
After the call,
.s 1
.i 5
CALL CSTO('177777',IVAL)
.i 0
.s 1
IVAL will be equal to -1.
IVAL must be an INTEGER*2 variable.
.i 0
.hl 1 Convert String to Real Number
.p
Syntax:  CSTR(STR,RVAL)
.p
The CSTR subroutine converts a floating-point character string
to a real number.
It converts STR to a REAL value and stores it in RVAL.
STR must represent a floating point number in standard
fortran format.
After the call,
.s 1
.i 5
CALL CSTR('1.0E-01',RVAL)
.i 0
.s 1
RVAL will have the value 0.1.
.i 0
.hl 1 Convert Integer to String
.p
Syntax:  CITS(STR,IVAL)
.p
The CITS subroutine converts an integer value to a
character string.
It converts the INTEGER IVAL to a character string
and stores it in STR.
After the call,
.s 1
.i 5
CALL CITS(STR,652)
.i 0
.s 1
STR will have the value 652.
.i 0
.hl 1 Convert Real Number to String
.p
Syntax:  CRTS(STR,RVAL)
.p
The CRTS subroutine converts a real number
to a character string.
It converts the REAL RVAL to a character string
and stores it in STR.
After the call,
.s 1
.i 5
CALL CRTS(STR,123.5)
.i 0
.s 1
STR will have the value 123.5.
.i 0
.ch COMMAND PROCESSORS
.nj;.lm 0
.p
This chapter briefly discusses programs designed as command
processors.
A command processor is a program that accepts lines of
the form
.i 5
.s 1
cmd parm1 parm2 ...
.i 0
.s 1
where each input line consists of a command and an arbitrary
number of parameters.
The command processor is expected to execute each command and then
prompt for the next command.
The next two sections describe subroutines that make
it somewhat easier to write command processors.
The last section of this chapter describes a simple command processor.
.hl 1 Get Next Command Line
.p
Syntax:  GNCL(CMDLST,COMCP,CMDNUM)
.p
GNCL means "Get Next Command Line".
CMDLST is a character string containing the list of commands
accepted by the caller.
Each command in the list is separated by a blank.
COMCP is the name of a subroutine that GNCL calls to look
for additional commands.  CMDNUM is set equal to the index
in CMD of the command found by GNCL.
For example, the statement
.i 5
.s 1
CALL GNCL('DATE TIME',COMCP,CMDNUM)
.s 1
.i 0
states that the caller is willing to process two commands:
DATE and TIME.
It also gives the name of another routine, COMCP that
is willing to process additional commands.
.p
GNCL calls PROMPT to get the next input line.
If CNTLZ is set, GNCL sets CMDNUM=-1 and returns.
If a null line is detected, (i.e., the user enters only the return key),
GNCL sets CMDNUM=0 and returns.
.p
If neither of these conditions are true, GNCL calls TOKEN.
It compares the token with the commands in CMDLST.
If a match is found, GNCL sets CMDNUM equal to the position
of the command in CMDLST and returns.
In the above example if PROMPT returns LINE as
.s 1
.i 5
TIME 10:30:00
.i 0
.s 1
GNCL sets CMDNUM=2.
Note that the next call to TOKEN returns the next
token after the command name.
.p
If GNCL does not find the command in CMDLST,
it calls COMCP with the statement
.s 1
.i 5
CALL COMCP(FOUND)
.i 0
.s 1
When COMCP is called, STRVAL contains the command to be processed.
If COMCP sets FOUND true, GNCL begins again by
calling PROMPT.
If COMCP does not set FOUND true,
GNCL calls SYNERR and tells the operator
that this is an illegal command.
It then begins again by calling PROMPT.
.p
It should now be clear that GNCL never returns to the caller
until it finds a command the caller is willing to process
or until a null line or end-of-file is detected.
The calling program should clean up and exit if an end-of-file
is detected.
It can do whatever the programmer wants if a null line is detected.
.p
COMCP is useful if multiple command processors
accept a common set of commands.
For example if multiple programs are processing the
same set of data files, a subroutine can be written
to accept commands that manipulate the data files.
Each program lets this subroutine process the data file commands,
and only processes additional commands.
.hl 1 Get Next Parameter
.p
Syntax: GNP(PMTSTR,TYPE)
.p
GNP means Get Next Parameter.
This subroutine calls TOKEN to get the next parameter
from the current input line.
If the token has TOKTYP=TYPE then GNP returns.
If TOKTYP is not equal to TYPE then GNP does the following:
If TOKTYP is not equal to TYPEOL,
GNP calls SYNERR and prints an error message.
In either case GNP calls PROMPT with PMTSTR as an argument.
It then calls TOKEN and proceeds as above, i.e.
it will not return until the operator returns a parameter
of the appropriate type.
.p
.pg
For example assume that a program is processing a command
of the form:
.s 1
####DATE yy mm dd
.s 1
Where yy, mm, dd are expected to be the year, month, and day
given as integers.
Assume that GNCL has already been called and the program branches
to the following section of code which is expected to process the
DATE command:
.s 1;.nf
	CALL GNP('ENTER YEAR',TYPINT)
	YEAR=INTVAL
	CALL GNP('ENTER MONTH',TYPINT)
	MONTH=INTVAL
	CALL GNP('ENTER DAY',TYPINT)
	DAY=INTVAL
.s 1;.f
.hl 1 Example Command Processor
.p
The example command processor (Figure 1)
accepts two commands: DATE and TIME.
If either command is given without parameters,
the currently defined date or time is listed.
If parameters are given, the currently defined date or
time is changed.
The date is given in the form MM/DD/YY or in the
form MM DD YY.
The time is given in the form HH:MM:SS or in the
form HH MM SS.
Note that, because of the rules used by TOKEN, the
parameters can be separated by commas instead of blanks.
Thus the following are all legal commands:
.s 1
    DATE
.br
    TIME
.br
    DATE 1/15/82
.br
    TIME 11:40:00
.br
    DATE 1,15,82
.br
    TIME 11 40   0
.p
The DATE and TIME are initialized to be zero.
COMCP is a dummy subroutine that does nothing.
.pg;.c;FIGURE 1: SAMPLE COMMAND PROCESSOR
.s 2
.nf
	PROGRAM	COMAND
C	CLP DECLARATIONS FOR COMMAND LINE PROCESSING
	COMMON/CLP/
      1	TYPNUL,TYPEOL,TYPEL,TYPINT,TYPFLT,TYPNAM,TYPSPC,
      2	TLU,CLPEFN,CNTLZ,TRACE,
      3	LINE,NXTCHR,TOKLEN,TOKTYP,INTVAL,FLTVAL,STRVAL,CHRVAL
	INTEGER*2 TYPNUL,TYPEOL,TYPEL,TYPINT,TYPFLT,TYPNAM,TYPSPC
	INTEGER*2 TLU,CLPEFN,NXTCHR,TOKLEN,TOKTYP,INTVAL
	LOGICAL*1 LINE(82),STRVAL(82),CHRVAL
	LOGICAL	CNTLZ,TRACE
	REAL FLTVAL
C	LOCAL DECLARATIONS
	INTEGER*2 DATE(3),TIME(3)
	EXTERNAL DUMMY
	INTEGER*2 CMDNUM
	DATA DATE/3*0/,TIME/3*0/
C	BEGIN
1000	CALL GNCL('DATE	TIME',DUMMY,CMDNUM)
	IF(CMDNUM.EQ.-1)STOP
	IF(CMDNUM.EQ.0)GO TO 1000
	GOTO(1100,1200)CMDNUM
1100	CALL TOKEN
C	IF NO PARAMETERS ARE GIVEN JUST	PRINT DATE
	IF(TOKTYP.NE.TYPEOL)GO TO 1110
	WRITE(TLU,110)DATE
110	FORMAT(1H ,'DATE: ',I2,'/',I2,'/',I2)
	GO TO 1000
1110	DO 1150	I=1,3
	IF(TOKTYP.EQ.TYPINT)GO TO 1120
	CALL SYNERR
	CALL PLINE('ILLEGAL PARAMETER')
	GO TO 1000
1120	DATE(I)=INTVAL
	CALL TOKEN
	IF(CHRVAL.EQ.'/')CALL TOKEN
1150	CONTINUE
	GO TO 1000
.pg
.c; Figure 1, Continued:  SAMPLE COMMAND PROCESSOR PROGRAM
.s 2
.nf
1200	CALL TOKEN
C	IF NO PARAMETERS ARE GIVEN JUST	PRINT TIME
	IF(TOKTYP.NE.TYPEOL)GO TO 1210
	WRITE(TLU,120)TIME
120	FORMAT(1H ,'TIME: ',I2,':',I2,':',I2)
	GO TO 1000
1210	DO 1250	I=1,3
	IF(TOKTYP.EQ.TYPINT)GO TO 1220
	CALL SYNERR
	CALL PLINE('ILLEGAL PARAMETER')
	GO TO 1000
1220	TIME(I)=INTVAL
	CALL TOKEN
	IF(CHRVAL.EQ.':')CALL TOKEN
1250	CONTINUE
	GO TO 1000
	END
 
	SUBROUTINE DUMMY(FOUND)
	LOGICAL	FOUND
C	THIS ROUTINE DOES NOTHING
	END
.ch MENU PROCESSORS
.nj;.lm 0
.p
In this manual, a "menu processor" means a program that
prompts the operator for all input.
It is particularly useful for novice operators or
for programs that are used infrequently.
Because the operator is prompted for all input,
he does not have to remember any commands.
The example given below performs the same functions as
the command processor example given in Chapter 5,
but it is written as a menu processor rather than as a command processor.
When the program is started, it prompts the operator as follows:
.i 5
.s 1
CMD>1=SET DATE,2=PRINT DATE,3=SET TIME,4=PRINT TIME?
.i 0
.p
If the operator enters a CNTL/Z, the program terminates.
If the operator enters a null line, he is again prompted
for a command.
If the operator gives a parameter value that is not an integer
between 1 and 4, he receives a message that he has entered
an illegal parameter and is again prompted for a new command.
.p
If the operator enters the value 1,
he is prompted:
.i 5
.s 1
CMD>DATE(MM/DD/YY)?
.i 0
.s 1
The program calls TOKEN to retrieve each parameter.
If an illegal parameter is detected,
SYNERR is called, an error message is printed,
and the operator is prompted for a new command.
.p
The program listing (Figure 2) can be studied to see how
the remaining commands are processed.
.pg;.c;FIGURE 2: SAMPLE MENU PROCESSOR PROGRAM
.s 2
.nf
	PROGRAM	MENU
C	CLP DECLARATIONS FOR COMMAND LINE PROCESSING
	COMMON/CLP/
      1	TYPNUL,TYPEOL,TYPEL,TYPINT,TYPFLT,TYPNAM,TYPSPC,
      2	TLU,CLPEFN,CNTLZ,TRACE,
      3	LINE,NXTCHR,TOKLEN,TOKTYP,INTVAL,FLTVAL,STRVAL,CHRVAL
	INTEGER*2 TYPNUL,TYPEOL,TYPEL,TYPINT,TYPFLT,TYPNAM,TYPSPC
	INTEGER*2 TLU,CLPEFN,NXTCHR,TOKLEN,TOKTYP,INTVAL
	LOGICAL*1 LINE(82),STRVAL(82),CHRVAL
	LOGICAL	CNTLZ,TRACE
	REAL FLTVAL
C	LOCAL DECLARATIONS
	INTEGER*2 DATE(3),TIME(3)
	DATA DATE/3*0/,TIME/3*0/
C	BEGIN
1000	CALL PROMPT('1=SET DATE,2=PRINT	DATE,3=SET TIME,4=PRINT	TIME')
	CALL TOKEN
	IF(CNTLZ)STOP
	IF(TOKTYP.EQ.TYPEL)GO TO 1000
	IF(INTVAL.GE.1.AND.INTVAL.LE.4)GO TO 1010
	CALL PLINE('ILLEGAL COMMAND. MUST BE >=1 AND <=4')
	GO TO 1000
1010	GO TO(1100,1200,1300,1400)INTVAL
1100	CALL PROMPT('DATE(MM/DD/YY)')
	CALL TOKEN
	IF(TOKTYP.EQ.TYPEL)GO TO 1000
1110	DO 1150	I=1,3
	IF(TOKTYP.EQ.TYPINT)GO TO 1120
	CALL SYNERR
	CALL PLINE('ILLEGAL PARAMETER')
	GO TO 1100
1120	DATE(I)=INTVAL
	CALL TOKEN
	IF(CHRVAL.EQ.'/')CALL TOKEN
1150	CONTINUE
	GO TO 1000
1200	WRITE(TLU,110)DATE
110	FORMAT(1H ,'DATE: ',I2,'/',I2,'/',I2)
	GO TO 1000
.pg;.c;Figure 2, Continued: SAMPLE MENU PROCESSOR PROGRAM
.s 2
1300	CALL PROMPT('TIME(HH:MM:SS)')
	CALL TOKEN
	IF(TOKTYP.EQ.TYPEL)GO TO 1000
1310	DO 1350	I=1,3
	IF(TOKTYP.EQ.TYPINT)GO TO 1320
	CALL SYNERR
	CALL PLINE('ILLEGAL PARAMETER')
	GO TO 1300
1320	TIME(I)=INTVAL
	CALL TOKEN
	IF(CHRVAL.EQ.':')CALL TOKEN
1350	CONTINUE
	GO TO 1000
1400	WRITE(TLU,130)TIME
130	FORMAT(1H ,'TIME: ',I2,':',I2,':',I2)
	GO TO 1000
	END
.ch OPERATIONAL PROCEDURES
.nj;.lm 0
.p
 To use the routines described in this manual, the
programmer must include the CLP common definitions with
his Fortran source program and must give the task builder
a library containing the routines.
.p
If Fortran-IV-Plus or Fortran-77 are being used,
the Fortran INCLUDE statement can be used to include
the definitions for CLP.
If Fortran-IV is being used, the programmer must use a
standard editor to include the definitions.
The definitions are in the file 'CLP.COM'.
.p
The following is the indirect command file used
to task-build the COMAND example given previously.
It can be used as a model for other programs.
LIB is the library containing the routines described in this chapter.
F4POTS is the Fortran-IV-Plus library.
Note that logical units 1, 2, and 3 are used.
The RSX-11M command line routines use unit 1.
This can be changed by changing the macro call GCMLB$ in GCML.
Logical unit 2 is the terminal logical unit.
Logical unit 3 is used by the LEARN command.
The terminal logical unit is defined in a DATA statement in
PROMPT.
The LEARN logical unit is also defined by a statement in PROMPT.
.nf
.s 1
COMAND/CP/FP=COMAND,LIB/LB
LB:[1,1]F4POTS/LB
/
ASG=TI:1:2,SY:3
RESLIB=LB:[1,1]FCSRES/RO:7
TASK=...CMD
//
.f
.p
All files needed to use the routines described in this manual
are stored under a single UIC.
Three files CLP.COM, CLP.INI, and CLP.DEF contain the Fortran
definitions, initialization statements, and comment statements
for common block CLP.
Command files are available to generate an object module library.
File CREATEFOR.CMD will create a library for Fortran-IV
and CREATEF4P.CMD will create a library for Fortran-IV-Plus.
.appendix INCLUDE LIBRARY
.nj;.lm 0
.nf
.s 1
C CLP DECLARATIONS FOR COMMAND LINE PROCESSING
	COMMON/CLP/
	1 TYPNUL,TYPEOL,TYPEL,TYPINT,TYPFLT,TYPNAM,TYPSPC,
	2 TLU,CLPEFN,CNTLZ,TRACE,
	3 LINE,NXTCHR,TOKLEN,TOKTYP,INTVAL,FLTVAL,STRVAL,CHRVAL,USICHR
	INTEGER*2 TYPNUL,TYPEOL,TYPEL,TYPINT,TYPFLT,TYPNAM,TYPSPC
	INTEGER*2 TLU,CLPEFN,NXTCHR,TOKLEN,TOKTYP,INTVAL
	LOGICAL*1 LINE(82),STRVAL(82),CHRVAL,USICHR
	LOGICAL CNTLZ,TRACE
	REAL FLTVAL
.s 1
C INITIAL VALUES FOR CLP COMMON
	DATA TYPNUL/0/,TYPEOL/1/,TYPEL/2/,TYPINT/3/
	DATA TYPFLT/4/,TYPNAM/5/,TYPSPC/6/
	DATA TLU/2/,CLPEFN/1/,CNTLZ/.FALSE./,TRACE/.FALSE./
	DATA LINE/82*0/,NXTCHR/1/,TOKLEN/0/,TOKTYP/0/
	DATA INTVAL/0/,FLTVAL/0.0/,STRVAL/82*0/,CHRVAL/0/
.s 1
C DEFINITION OF VARIABLES IN CLPCOM
C TYPNUL - NULL PARAMETER. I.E. ,,
C TYPEOL - END OF LINE
C TYPEL  - EMPTY LINE
C TYPINT - INTEGER
C TYPFLT - FLOATING POINT NUMBER
C TYPNAM - NAME. VALUE IS STORED IN STRVAL
C TYPSPC - SPECIAL TYPE. VALUE IS STORED IN CHRVAL
C TLU    - TERMINAL LOGICAL UNIT
C CLPEFN - EVENT FLAG USABLE BY ANYONE WHO WAITS IMMEDIATELY
C CNTLZ  - HAS USER GIVEN CNTL/Z
C TRACE  - TRACE LINES FROM COMMAND FILE?
C LINE   - CURRENT COMMAND LINE
C NXTCHR - NEXT CHARACTER OF LINE FOR TOKEN
C TOKLEN - LENGTH OF PREVIOUS TOKEN
C TOKTYP - TYPE OF PREVIOUS TOKEN
C INTVAL - INTEGER VALUE OF PREVIOUS TOKEN
C FLTVAL - FLOATING POINT VALUE OF PREVIOUS TOKEN
C STRVAL - STRING VALUE OF PREVIOUS TOKEN
C CHRVAL - CHARACTER VALUE OF PREVIOUS TOKEN
C USICHR - UNSOLICITED INTERRUPT CHARACTER
.appendix SUMMARY OF LIBRARY SUBROUTINES
.nj;.lm 0
.nf
^&
Subroutine Name		Operation Performed
\&
.s 1
.c; TERMINAL I/O
.s 1
PROMPT(STR)		Prompts	and accepts input.
PLINE(STR)		Sends STR to terminal.
USIBEG			Begin Unsolicited Terminal Input
USIEND			End Unsolicited Terminal Input
.s 2
.c; SYNTAX ANALYSIS
.s 1
TOKEN			Gets next token.
SYNERR			Reports	syntax error.
.s 2
.c; CHARACTER STRING SUBROUTINES
.s 1
LENSTR(STR,LEN)		Sets LEN equal to length of STR.
ICHR(STR,IND,CHR)	Inserts	CHR before IND'th char of STR.
CCCHR(STR,CHR)		Concatenates CHR onto end of STR.
CCSTR(STR1,STR2)	Concatenates STR2 onto end of STR1.
GSTR(STR1,BEG,END,STR2)	Gets substring delimited by BEG	and END.
DSTR(STR,BEG,END)	Deletes	substring delimited by BEG and END.
ISTR(STR1,IND,STR2)	Inserts	STR2 before IND'th CHR of STR1.
MSTR(STR1,STR2)		Moves STR1 to STR2.
RLBS(STR)		Removes	leading	blanks from STR.
RTBS(STR)		Removes	trailing blanks	from STR.
GICHR(STR,CHR,IND)	Gets index of CHR within STR.
CMPSTR(STR1,STR2,IRES)	Sets IRES=(-1,0,1) IF STR1 (<,=,>) STR2
CSTI(STR,IVAL)		Converts string	to integer value.
CSTO(STR,IVAL)		Converts string	to octal value.
CSTR(STR,RVAL)		Converts string	to real	value.
CITS(STR,IVAL)		Converts integer to string.
CRTS(STR,RVAL)		Converts real value to string.
.s 2
.c; COMMAND PROCESSOR
.s 1
GNCL(CMDLST,		Gets next command line.
     COMCP,CMDNUM)
GNP(PMTSTR,TYPE)	Get Next Parameter
