Chapter 6
ICL Commands

 6.1 Commands
 6.2 Built-in commands
 6.3 User-defined commands
 6.4 Input/Output commands
  6.4.1 Terminal
  6.4.2 Screen mode
  6.4.3 Keyboard facilities
  6.4.4 File
 6.5 DCL commands and VMS processes
  6.5.1 Executing DCL commands
  6.5.2 Processes and subprocesses
  6.5.3 Changing your default directory
  6.5.4 Managing tape drives

6.1 Commands

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.

6.2 Built-in commands

The built-in commands are listed in Chapter 19. Here is a classification:

Information & Escape
— Chapter 5
HELP, EXIT
Defining user commands
— Chapter 6
DEFSTRING, DEFINE, DEFUSER, DEFPROC
I/O
— Chapter 6
Terminal

PRINT, INPUTt
Screen mode

SET SCREEN, SET NOSCREEN, SET ATTRIBUTES, LOCATE, CLEAR
Keyboard facilities

KEY, KEYTRAP, KEYOFF
Files

CREATE, OPEN, APPEND, CLOSE, WRITE, READt
Access to DCL
— Chapter 6
$, SPAWN, DEFAULT,
ALLOC, DEALLOC, MOUNT, DISMOUNT
Parameters
— Chapter 8
SETPAR, GETPAR,
CREATEGLOBAL, SETGLOBAL, GETGLOBAL
Procedures
— Chapter 9
LIST, PROCS, VARS, EDIT, SET EDITOR,
SAVE, LOAD, DELETE,
SET TRACE, SET NOTRACE
Errors & Exceptions
— Chapter 9
SIGNAL
HELP system
— Chapter 9
DEFHELP

All these commands are described in the chapter specified.

6.3 User-defined commands



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:

DEFSTRING
— associates a command with an equivalence string:

    DEFSTRING  command  equivalence-string

when you enter command, it is as if you had entered equivalence-string.

DEFINE
— defines a command which causes a program to be executed:

    DEFINE  command  program-name

When you enter command, program program-name is executed.

DEFUSER
— defines a command which causes a compiled subroutine to be executed:

    DEFUSER  command  image-name

When you enter command, the shareable image image-name is executed.

DEFPROC
— defines a command which causes an ICL procedure to be executed:

    DEFPROC  command  file

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.

6.4 Input/Output commands

The I/O commands fall into three classes:

These are described in the following sub-sections.

6.4.1 Terminal



INPUT Input string from terminal
INPUTI Input integers from terminal
INPUTL Input logicals from terminal
INPUTR Input reals from terminal


PRINT Output to terminal


Input:  The commands for terminal input are INPUT, INPUTR, INPUTI, and INPUTL. Command INPUT reads a line of text from the terminal into a string variable. An example is:
    ICL> INPUT Enter your name> (X)  
    Enter your name>Mike  
    ICL> PRINT (X)  
    Mike  
    ICL>

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:

    ICL> INPUTR  Prompt  (X)  (Y)  (Z)  ...

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:

    ICL> INPUTR ’Give values of X and Y > ’ (X) (Y)  
    Give values of X and Y > 2.3 8.9  
    ICL> PRINT (X) (Y)  
    2.300000 8.900000  
    ICL>

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:

    PRINT  p1  p2  ...

The parameters are concatenated and printed on the terminal. For example

    ICL> X=2  
    ICL> PRINT The square root of (X) is (SQRT(X))  
    The square root of          2 is 1.414214

Another way of writing to the terminal is by using an Immediate statement:

    ICL> =1+2+3  
             6

Formatting Output:  While Fortran regards formatting of numbers for output as part of an output operation, ICL performs formatting using an operator (:) which produces a string result from a numeric operand. Thus, if I is an integer variable, the expression I:5 has as its value the string which is produced by converting I with a field width of 5 characters. It is equivalent to an I5 format in Fortran. Similarly, if X is a real variable, the expression X:10:4 produces the value of X formatted in a Fortran F10.4 format (i.e. a field width of 10 characters with 4 decimal places). The ICL formatting is not precisely equivalent to the Fortran form because ICL will extend the field width if a number is too large to fit in the requested width. For example:
    ICL> =1.234567:5:2  
     1.23  
    ICL> =12.34567:5:2  
    12.35  
    ICL> =123.4567:5:2  
    123.46  
    ICL> =123456.7:5:2  
    123456.70  
    ICL>

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:

    ICL> =%Xffff  
          65535  
    ICL> =hex(65535)  
     0000FFFF  
    ICL> =oct(%XFF,5,5)  
    00377  
    ICL>

6.4.2 Screen mode



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.

    ICL> SET SCREEN 10

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:

    ICL> LOCATE 6 10   This text will be written starting at Row 6 Column 10

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:

    ICL> CLEAR 6 10

clears lines 6 to 10 of the screen.

6.4.3 Keyboard facilities



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:

    ICL> KEY  PF1  PROCS#

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:

   Keypad keys             PF1, PF2, PF3, PF4, KP0, KP1, KP2, KP3, KP4, KP5,  
                           KP6, KP7, KP8, KP9, ENTER, MINUS, COMMA, PERIOD.  
 
   Function Keys (VT200)   F6, F7, F8, F9, F10, F11, F12, F13, F14, HELP,  
                           DO, F17, F18, F19, F20.  
 
   Editing Keypad (VT200)  FIND, INSERT_HERE, REMOVE, SELECT, PREV_SCREEN, NEXT_SCREEN.  
 
   Cursor Keys             UP, DOWN, LEFT, RIGHT.

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:

    { Trap ENTER and LEFT and RIGHT arrow keys  
 
    KEYTRAP ENTER  
    KEYTRAP LEFT  
    KEYTRAP RIGHT  
 
    LOOP  
      K = INKEY()  
      IF K = KEYVAL(’ENTER’) THEN  
      .  
      ELSE IF K = KEYVAL(’LEFT’) THEN  
      .  
      ELSE IF K = KEYVAL(’RIGHT’) THEN  
      .  
      ELSE  
      .  
      ENDIF  
    END LOOP

6.4.4 File



CREATE Create new file and open for output
OPEN Open existing file for input
APPEND Open existing file for output, append text
CLOSE Close file


READ Read line from file
READI Read integers from file
READL Read logicals from file
READR Read reals from file


WRITE Write to file


ICL can read and write text files. In order to access such files, they must first be opened using one of the commands CREATE, OPEN, or APPEND, for example:

    ICL> CREATE MYFILE

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:

    ICL> OPEN  INFILE  DISK$DATA:[ABC]FOR008.DAT

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.

    PROC REFORMAT  
    { Open input file and create output file  
      OPEN INFILE  
      CREATE OUTFILE  
    { Copy lines from input to output  
      LOOP  
        READR INFILE (R1) (R2) (R3)  
        WRITE OUTFILE (R1:10:2) (R2:10:2) (R3:10:2)  
      END LOOP  
    END PROC

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.

6.5 DCL commands and VMS processes

6.5.1 Executing DCL commands



$ 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:

    ICL> $ dcl_command

where dcl_command is any command we could issue from the DCL ‘$’ prompt. For example:

    ICL> $ COPY *.SDF DATADIR:*.SDF  
    ICL> $ RUN MYPROGRAM

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:

    ICL> SPAWN COPY  
    _From: *.SDF  
    _To: DATADIR:*.SDF

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.

6.5.2 Processes and subprocesses

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).

6.5.3 Changing your default directory



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.

6.5.4 Managing tape drives



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:

    ICL> ALLOC MT  
    _MTA0: Allocated  
    ICL> ALLOC MT (DEVICE)  
    _MTA1: Allocated  
    ICL> =DEVICE  
    _MTA1:

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:

    ICL> DISMOU MTA1 NOUNLOAD

1A tidier exit can be arranged by using an exception handler for the EOF exception, see Chapter 9.