Specification

<specification>

                ┌◄───── , ─────┐
──┬─<specifier>─┴─<identifier>─┴──────────────┬────────────────────────┤
  ├─<procedure specification>─────────────────┤
  ├─<array specification>─────────────────────┤
  ├─<procedure reference array specification>─┤
  └─<structure block array specification>─────┘

<specifier>

──┬─ ANYTYPE ──────────────────────────────┬───────────────────────────┤
  ├─ CONNECTION ───────────────────────────┤
  ├─ EVENT ────────────────────────────────┤
  ├──────────┬─ FILE ──────────────────────┤
  ├─ DIRECT ─┘                             │
  ├─ FORMAT ───────────────────────────────┤
  ├─ INTERLOCK ────────────────────────────┤
  ├─ LABEL ────────────────────────────────┤
  ├─ LIST ─────────────────────────────────┤
  ├─ PICTURE ──────────────────────────────┤
  ├─ POINTER ──────────────────────────────┤
  ├───────────────┬─ STRING ───────────────┤
  ├─<string type>─┘                        │
  ├─ SWITCH ───────────────────────────────┤
  ├──────────┬─ SWITCH FILE ───────────────┤
  ├─ DIRECT ─┘                             │
  ├─ SWITCH FORMAT ────────────────────────┤
  ├─ SWITCH LIST ──────────────────────────┤
  ├─ TASK ─────────────────────────────────┤
  ├─<word type>────────────────────────────┤
  │ ┌◄──────────────── . ───────────────┐  │
  ├─┴─<structure block type identifier>─┴──┤
  │ ┌◄──────────────── . ────────────────┐ │
  └─┴─<connection block type identifier>─┴─┘

<procedure specification>

──┬──────────────────┬─ PROCEDURE ──<identifier>───────────────────────►
  └─<procedure type>─┘
►─┬──────────────────────────────┬─────────────────────────────────────┤
  └─<formal parameter specifier>─┘

<formal parameter specifier>

──┬─ () ────────────────────┬─ ; ── FORMAL ────────────────────────────┤
  └─<formal parameter part>─┘

<array specification>

                           ┌◄───── , ─────┐
──┬──────────────┬─ ARRAY ─┴─<identifier>─┴────────────────────────────►
  └─<array type>─┘
►─ [ ──<lower bound list>── ] ─────────────────────────────────────────┤

<array type>

──┬─<array class>────────────┬─────────────────────────────────────────┤
  ├─ DIRECT ─┬───────────────┤
  │          └─<array class>─┤
  ├─ EVENT ──────────────────┤
  ├─ INTERLOCK ──────────────┤
  ├───────────────┬─ STRING ─┤
  ├─<string type>─┘          │
  └─ TASK ───────────────────┘

<lower bound list>

  ┌◄─────────── , ──────────┐
──┴─<specified lower bound>─┴──────────────────────────────────────────┤

<specified lower bound>

──┬─<integer>─┬────────────────────────────────────────────────────────┤
  └─ * ───────┘

An array specification must be provided for every formal array. The array specification indicates the number of dimensions in the formal array and indicates the lower bound for each dimension.

If the specified lower bound is an integer, then the corresponding dimension of the formal array equals that integer. An asterisk (*) used as a specified lower bound indicates that the corresponding dimension of the formal array has a lower bound that is passed to the procedure with the actual array.

Array rows that are passed as actual parameters to procedures have their subscripts evaluated at the time of the procedure call, rather than at the time the corresponding formal array is referenced.

The formal parameter specifier causes the compiler to generate more efficient code for passing procedures as parameters. When a procedure is declared FORMAL, the compiler checks the parameters of the actual procedure passed to it at compilation time; otherwise, the parameters are checked at run time. If FORMAL is specified, the formal procedure is called a fully specified formal procedure.

If a formal parameter is a structure block variable, the actual parameter passed to that formal structure block variable must be a structure block array element, a structure block variable, or a structure block reference variable of the same structure block type as the formal parameter.

When a structure block array or a structure block variable is a formal parameter of an imported or exported library procedure, there are restrictions on the items that can be declared within the parent structure block type. The PRIVATE specifier cannot be used for the items declared. Only items allowed in the <export object specification> list of the EXPORT declaration plus three additional items can be declared within the structure block type. The additional items are an embedded structure block array, a structure block variable, and a structure block reference variable. The structure block type of the embedded structure block array, structure block variable, or structure block reference variable has the same restrictions as the parent structure block type.

When the client program using the library procedure is linked to the server program providing the library procedure, only the type and order of the items within the structure block type for the structure block array or structure block variable parameter are checked. If items of the same type within the structure block are declared in a different order in the client program than in the server program, the run-time results can be erroneous.

The use of ANYTYPE as the formal parameter specifier allows for a flexible interface between an exported unsafe procedure in a NEWP library and the invocation of that entry point in an ALGOL program. The actual parameter passed is matched at run time to a WORD variable in the NEWP library procedure. Therefore, the actual parameter can be of any type that ALGOL allows to be passed to a library. The compiler does not perform parameter type checking. If ANYTYPE is specified as a formal parameter, the procedure must be an imported library entry point.

If CONNECTION or <connection block type identifier> is used as the specifier for the formal parameter, an individual connection library must be passed as the actual parameter. The actual parameter must be an indexed library connection variable unless the connection library has been declared with the SINGLE modifier. If the connection library has been declared with the SINGLE modifier, the actual parameter must be an unindexed connection library variable. In addition, the connection parameter must be a call-by-reference parameter. An exported or imported library procedure cannot have a <connection block type identifier> as the specifier for a formal parameter.

When CONNECTION is used as a specifier, the procedure cannot see the elements of the connection library associated with the connection parameter. The procedure can pass the connection parameter to MCP procedures and can access the connection attributes. The procedure cannot use the parameter either to call procedures within the connection library or to access nonconnection attributes.

Nonlibrary procedures—procedures that are neither imported nor exported from a library—can specify either CONNECTION or a <connection block type identifier> for connection parameters. Using CONNECTION restricts the use of the parameter. Library procedures can specify CONNECTION only for a connection parameter.

Procedure Reference Array Specification

<procedure reference array specification>

──┬──────────────────┬─ PROCEDURE ── REFERENCE ── ARRAY ──<identifier>─►
  └─<procedure type>─┘
►─ [ ──<lower bound list>── ] ──<formal parameter specifier>───────────┤

A procedure reference array specification must have a formal parameter specifier.

Structure Block Array Specification

<structure block array specification>

  ┌◄──────────────── . ───────────────┐         ┌◄───── , ─────┐
──┴─<structure block type identifier>─┴─ ARRAY ─┴─<identifier>─┴─ [ ───►
►─<lower bound list>── ] ──────────────────────────────────────────────┤

Structure Block Array Parameters

If a formal parameter is a structure block array, the actual parameter passed to that formal structure block array must be a structure block array designator of the same structure block type as the formal parameter.

Procedure Body

<procedure body>

──┬─<block>─────────────────────────────┬──────────────────────────────┤
  ├─<unlabeled statement>───────────────┤
  ├─ EXTERNAL ──────────────────────────┤
  ├─<dynamic procedure specification>───┤
  ├─<library entry point specification>─┤
  └─<isolated procedure specification>──┘

Procedures can be called recursively; that is, inside the procedure body, a procedure can invoke itself.

The procedure body EXTERNAL is used to declare a procedure that is to be bound in to the program (as opposed to actually appearing within the program) or that is an external code file to be invoked. An attempt to invoke a procedure that is declared external but has not been bound in nor associated with an external code file results in a run-time error.

Dynamic Procedure Specification

<dynamic procedure specification>

── BY CALLING ──<selection procedure identifier>───────────────────────┤

<selection procedure identifier>

──<procedure identifier>───────────────────────────────────────────────┤

A dynamic procedure specification is used in a library program to declare a procedure that is to be exported dynamically. Such a procedure is also called a by-calling procedure. For more information on by-calling procedures, refer to Library Facility. The by-calling procedure cannot be declared FORWARD or PENDING and cannot be a separately compiled procedure. Also, the by-calling procedure cannot be referenced directly in the library program that declares it.

A selection procedure identifier must specify an untyped procedure with two parameters. The first parameter must be a call-by-value EBCDIC string. The second parameter must be a fully specified untyped procedure with one parameter that is a task. When the operating system invokes this selection procedure, the task variable passed to its procedure parameter must already be associated with a library that has been processed using this task variable.

Library Entry Point Specification

<library entry point specification>

──┬─ LIBRARY ──<library identifier>─┬──────────────────────────────────►
  └─ IMPORTED ──────────────────────┘
►─┬────────────────────────────────────────────────────────┬───────────┤
  └─ ( ── ACTUALNAME ── = ── <EBCDIC string literal> ── ) ─┘

A library entry point specification declares a procedure to be an entry point in the library known to this program by the library identifier. The procedure cannot be declared FORWARD, EXTERNAL, or PENDING. The IMPORTED clause is allowed only inside a connection block type.

If a program declares a library and entry points in that library, the object code file for the program contains a structure called a library template, which describes the library and its declared entry points. Each declared library has one template. The template description of an entry point includes the entry point name, a description of the procedure type, and descriptions of the entry point parameters.

When a library entry point is called, the entry point description in the library template of the calling program is compared to the entry point description of the same name in the library directory associated with the referenced library. Refer to EXPORT Declaration for a discussion of library directories. If the entry point does not exist in the library or if the two entry point descriptions are not compatible, then a run-time error is given and the program is terminated.

The name given for an entry point in a library template is the procedure identifier in the entry point declaration, unless an ACTUALNAME clause appears, in which case the name is given by the EBCDIC string literal. The EBCDIC string literal in the ACTUALNAME clause can contain only valid <printable character>s, but must not contain any leading, trailing, or embedded blanks or periods. The entry point name indicated by this string literal is case sensitive.

ISOLATED Procedure Specification

<isolated procedure specification>

── BEGIN ── [ISOLATED] ─┬────────────────────┬─<statement list>── END ─┤
                        └─<declaration list>─┘

An isolated procedure is primarily used in the context of shared libraries that have global data protected by locking mechanisms. However, an isolated procedure can be used in any situation where a procedure from one stack runs on another stack. In the following text, the stack in which the isolated procedure is declared is called the parent stack and the other stack is called the client stack. The ISOLATED procedure attribute is used to protect the parent stack of an isolated procedure from being stopped or discontinued when the client stack on which the isolated procedure is running is stopped or discontinued.

If the parent stack of the isolated procedure is discontinued, then the isolated procedure is discontinued.

If the client stack is stopped by an ST command, the isolated procedure is allowed to run for an additional 5 seconds of CPU time. After 5 seconds of CPU time, the isolated procedure is also stopped.

If the client stack is discontinued, the isolated procedure is allowed to continue to run. After 5 seconds of CPU time, a message is displayed to allow the operator to take any necessary action.

Using the ISOLATED procedure attribute, a library or other IPC program can assume that an isolated procedure will not be interrupted by a DS command while running on a client stack. Also, an isolated procedure will not be delayed by an ST command, provided the procedure does not use more than 5 seconds of CPU time before exiting.

When an isolated procedure fails to exit cleanly, the parent stack of the isolated procedure is discontinued. Failure to exit cleanly includes: a fatal error in the isolated procedure, a fatal error in a procedure invoked above the isolated procedure, or a GO TO statement that cuts back the stack environment of the isolated procedure.

When an isolated procedure is running on a client stack, asynchronous actions such as software interrupts, signals, approval procedures, and change procedures for the client stack are delayed until the isolated procedure exits. Software interrupts declared within an isolated procedure or within procedures invoked above the isolated procedure will never run.

If an isolated procedure uses the DSABLE option of a WAIT or LOCK Interlock function, code in the isolated procedure should be written to exit cleanly if the value returned by the WAIT or LOCK Interlock function indicates that the client stack has been discontinued.

When an isolated procedure is running on a client stack, the isolated semantics apply to the client stack until the isolated procedure exits or the parent stack of the isolated procedure is discontinued. The isolated semantics apply to procedures invoked above the isolated procedure. When multiple isolated procedures are running in a client stack, the isolated semantics apply down to the first isolated procedure of the client stack in which the parent stack has not been discontinued.

An isolated procedure can cause some system operations to be delayed such as a DS command, or an ST command. Therefore, the code for an isolated procedure should be written to run quickly and efficiently, not consuming excessive system resources.