In the last chapter we introduced the Command as one of the Direct Statements of the ICL language. You will remember that the format was:
command_name [parameter_specification] …
There are two main types of commands:
The difference between them is that built-in commands are always available as they are an intrinsic part of the language, while user-defined commands are only available if you have defined them yourself in some way. The two types will be considered separately in the following two sections.
If you define commands, or use an application that defines commands, there is a danger of ambiguity since you may give a new meaning to an existing command name. Just for the record, here is the search-path that ICL uses when it searches for command definitions:
Don’t worry about those command names, you will learn about them latter.
The built-in commands are listed in Chapter 19. Here is a classification:
All these commands are described in the chapter specified.
|DEFSTRING||Associate command with equivalence string|
|DEFINE||Define command to run a program|
|DEFUSER||Define command to run a subroutine|
|DEFPROC||Define command to run an ICL procedure|
There are three types of command which you can use to define your own commands:
These are described briefly below:
when you enter command, it is as if you had entered equivalence-string.
When you enter command, program program-name is executed.
When you enter command, the shareable image image-name is executed.
When you enter command, the ICL procedure stored in file.ICL is compiled (first time only) and executed.
The DEFINE command is explained further in Chapter 7, and the definition and use of ICL procedures is explained in Chapter 9.
The I/O commands fall into three classes:
These are described in the following sub-sections.
|INPUT||Input string from terminal|
|INPUTI||Input integers from terminal|
|INPUTL||Input logicals from terminal|
|INPUTR||Input reals from terminal|
|Output to terminal|
The last parameter must specify a variable in which the input will be stored and must, therefore, be in parentheses. The earlier parameters form a prompt string.
Commands INPUTR, INPUTI, and INPUTL are used to input real, integer, and logical values. A single command may be used to supply values for more than one variable, so these commands have the general form:
For these three commands, only the first parameter is used to provide the prompt string, so if it has spaces in it, the string must be enclosed in quotes. For example:
INPUTL will accept values of TRUE, FALSE, YES, and NO in either upper or lower case, as well as abbreviations. Output: You can output to the terminal by using the PRINT command:
The parameters are concatenated and printed on the terminal. For example
Another way of writing to the terminal is by using an Immediate statement:
Integers can also be formatted in binary, octal, decimal, or hexadecimal formats using the functions BIN, OCT, DEC, and HEX. These have the form HEX(X,n,m) which would return a string of n characters containing the number X with m significant digits. Parameters n and m may be omitted, in which case they default to the number of digits needed to represent a full 32 bit word. Using these forms together with constants in various bases, ICL can be used to perform conversions between bases. For example:
|SET SCREEN||Select screen mode|
|SET NOSCREEN||Select normal mode|
|SET ATTRIBUTES||Set attributes for text written with LOCATE|
|LOCATE||Write to screen at specified position|
|CLEAR||Clear range of lines|
Screen mode allows more control over the terminal screen than is possible in the normal mode. It also allows more control over the use of the keyboard. Screen mode is implemented using the DEC screen management (SMG$) routines of the run time library, and will work on any terminal compatible with these routines.
Screen mode is selected by the SET SCREEN command. In this mode, the terminal screen is divided into an upper fixed region and a lower scrolling region. The size of the scrolling region may be specified by an optional parameter to SET SCREEN.
will select 10 lines of scrolling region. The size of the scrolling region can be changed by further SET SCREEN commands. SET NOSCREEN is used to leave screen mode and return to normal mode.
Standard terminal I/O operations work exactly as normal in the scrolling region of the screen. However, an additional facility is the ability to examine text which has scrolled off the top of the scrolling region. The Next Screen and Prev Screen keys on a VT200 (or ctrl/N, ctrl/P on other terminals) may be used to move through the text. Any output since screen mode was started is viewable in this way.
To write to the fixed part of the screen, the command LOCATE is used:
The first two parameters specify the row and column at which the text will start. The remaining parameters form the text to be written.
The SET ATTRIBUTES command provides further control over text written with the LOCATE command. This command has a parameter string composed of any combination of the letters R (Reverse Video), B (Bold), U (Underlined), F (Flashing) and D (Double Size). These attributes apply to all LOCATE commands until the next SET ATTRIBUTES command. SET ATTRIBUTES with no parameter gives normal text.
The CLEAR command is used to clear all or part of the fixed region of the screen. For example:
clears lines 6 to 10 of the screen.
|KEY||Define equivalence string for key|
|KEYTRAP||Specify trapping of key in a procedure|
|KEYOFF||Turn off trapping of key in a procedure|
The KEY command may be used to define an equivalence string for any key on the keyboard. For example:
defines the PF1 key so that it issues the PROCS command. The # character is used to indicate a Return character in the equivalence string.
The name of a main keyboard key may be specified as a single character or as an integer representing the ASCII code for the key. Keypad and function keys are specified by names as follows:
The KEYTRAP command and the INKEY() function allow an ICL procedure to test for keyboard input during its execution, without having to issue an INPUT command and thus wait for input to complete.
KEYTRAP specifies the name of a key to be trapped.
KEYOFF turns off the trapping of a specified key.
INKEY() is an integer function which returns zero if no key has been pressed, or the key value if a key has been pressed since the last call. The key value is the ASCII value for ASCII characters, or a number between 256 and 511 for keypad and function keys.
KEYVAL(S) is a function which obtains the value from the key name.
Here is an example of the use of these commands and functions within a procedure:
|CREATE||Create new file and open for output|
|OPEN||Open existing file for input|
|APPEND||Open existing file for output, append text|
|READ||Read line from file|
|READI||Read integers from file|
|READL||Read logicals from file|
|READR||Read reals from file|
|WRITE||Write to file|
will create a file called MYFILE and open it for output — MYFILE is the name used within ICL for the file. In this case, the file will appear in your default directory as MYFILE.DAT. However, the file name may be specified explicitly by adding a second parameter to the commands, for example:
opens an existing file for input and the file is known internally as INFILE.
The APPEND command opens an existing file for output. Anything written to it is appended to the existing contents.
A line of text is written to a file with the WRITE command. WRITE is similar to PRINT, the only difference being that its first parameter specifies the internal name of the file to which the data will be written.
Text is read from files with the commands READ, READR, READI, and READL. These are analogous to the INPUT commands for terminal input. The first parameter specifies the internal name of the file. READ reads a line of text into a single string variable. The other commands read one or more real, integer, or logical values.
When a file is no longer required it may be closed using the CLOSE command which has a single parameter: the internal name of the file.
The following example defines a procedure which uses these commands to read a file containing three real numbers in free format and output the same numbers as a formatted table.
Note that no specific test for completion of the loop is included. When an end-of-file condition is detected on the input file, the procedure will exit and return to the ICL> prompt with an appropriate message1.
|$||Execute a DCL command in $’s subprocess|
|SPAWN||Execute a DCL command in new subprocess|
When using ICL, it is frequently useful to be able to access features of Digital’s command language DCL. Typical operations we may want to do include listing directories, copying files, allocating tape drives, and mounting tapes. The ICL command ‘$’ allows any DCL command to be issued from inside ICL. Its form is simply:
where dcl_command is any command we could issue from the DCL ‘$’ prompt. For example:
There is one restriction — you must use a complete DCL command. You can’t, for example, just type $ COPY and expect DCL to prompt you for the two file specifications. Apart from this, any command acceptable to DCL can be issued in this way.
There is a way around the restriction on prompts mentioned above. This is to use the command ‘SPAWN’ rather than the command ‘DCL’. For example:
in which case you get the ‘_From:’ and ‘_To:’ prompts, just as you do in normal DCL. The disadvantage of SPAWN is that it is slower. This is because SPAWN creates a new subprocess to run each command, whereas DCL creates a permanent subprocess in which all commands are run.
SPAWN has another use — by just typing SPAWN you can get a DCL ‘$’ prompt from which a series of DCL commands can be executed. LOGOUT is used to return control to ICL.
In VMS, a program runs in a process. If that program wishes to run another program or do something else, it must first create a subprocess. ICL is such a program and it runs application programs. The applications thus run in subprocesses, and so do DCL commands issued from ICL. This is the heart of many of the sometimes unexpected properties of ICL.
VMS is not particularly efficient at starting up processes, so loading a program takes time. ADAM deals with this through a structure called a monolith (discussed in Chapter 7).
The worst problems with subprocesses arise when something goes wrong. Uninhibited use of such things as ctrl/C to kill an application can have serious consequences for ICL, resulting in a loss of context and the consequent waste of time getting back to where you started. Ctrl/C returns you to the ICL prompt, while ctrl/Y takes you right out of ICL and back into DCL. A better way to get out of a program is to enter the abort response ‘!!’ when prompted for a parameter (see Chapter 8.)
Note that ctrl/C will only break out of a program and return you to ICL if the program is run as a subprocess of ICL. This is usually the case, but will not be if the command being executed was defined using DEFUSER (as in ASTERIX for example).
|DEFAULT||Set default directory|
You can change your default directory by using the DCL command ‘SET DEFAULT’. This will change the default directory of the DCL subprocess, but not of the process running ICL. Thus, an additional ICL command DEFAULT has been provided. This changes the default directory of both the process running ICL and the DCL subprocess (if one exists). The format for specifying the directory is exactly the same as that accepted by the equivalent DCL command.
|ALLOC||Allocate a device|
|DEALLOC||Deallocate a device|
|MOUNT||Mount a device|
|DISMOUNT||Dismount a device|
Similar problems with processes occur when allocating and mounting tape drives. The DCL command ‘ALLOCATE’ will allocate the device to the DCL subprocess. This may be what you want; for example, if you are going to use another DCL command (such as ‘BACKUP’) to read or write the tape. However, if a tape is to be processed using a FIGARO command, say, it must be allocated to the process running ICL. A set of commands has been provided for this purpose.
ALLOC allocates a device and may specify a generic name; the name of the device actually allocated will be returned in the optional second parameter. For example:
DEALLOC deallocates a device.
MOUNT performs a MOUNT/FOREIGN at the tape’s initialised density. It does not provide the many qualifiers of the DCL command. There are several additional optional parameters for some of these commands.
DISMOUNT has an optional parameter which is used to specify that the tape be dismounted without unloading: