HP OpenVMS Systems Documentation
Guide to the DEC Text Processing Utility
4.9.4 Declarations and Statements
A DECTPU program can consist of a sequence of declarations and statements. These declarations and statements control the action performed in a procedure or a program. The following reserved words are the language elements that when combined properly make up the declarations and statements of DECTPU:
GLOBAL, UNIVERSAL, BEGIN, and END are words reserved for future expansion of the DECTPU language.
The DECTPU declarations and statements are reserved words that you
cannot define. Any attempt to redefine these words results in a
With the MODULE/ENDMODULE declaration, you can group a series of global CONSTANT declarations, VARIABLE declarations, PROCEDURE declarations, and executable statements as one entity. After you compile a module, the compiler will generate two procedures for you. One procedure returns the identification for the module and the other contains all the executable statements for the module. The procedure names generated by the compiler are module-name_MODULE_IDENT and module-name_MODULE_INIT, respectively.
MODULE module-name IDENT string-literal [[declarations]] [[ON_ERROR ...
The declarations part of a module can include any number of global VARIABLE, CONSTANT, and PROCEDURE declarations.
The ON_ERROR/ENDON_ERROR block, if used, must appear after the declarations and before the DECTPU statements that make up the body of the module. Statements that make up the body of a module must be separated with semicolons. For more information on error handlers, see Section 220.127.116.11.
In the following example, the compiler creates two procedures: user_mod_module_ident and user_mod_module_init. User_mod_module_ident returns the string "v1.0". User_mod_module_init calls the routine user_hello.
18.104.22.168 Procedure Declaration
The PROCEDURE/ENDPROCEDURE declaration delimits a series of DECTPU statements so they can be called as a unit. With the PROCEDURE/ENDPROCEDURE combination, you can declare a procedure with a name so that you can call it from another procedure or from the command line of a DECTPU editing interface. Once you have compiled a procedure, you can enter the procedure name as a statement in another procedure, or enter the procedure name after the TPU Statement: prompt on the command line of EVE.
PROCEDURE procedure-name [[ (parameter-list) ]] [[local-declarations]]
The local declarations part of a procedure can include any number of LOCAL and CONSTANT declarations.
The ON_ERROR/ENDON_ERROR block, if used, must appear after the declarations and before the DECTPU statements that make up the body of the procedure. For more information on error handlers, see Section 22.214.171.124.
After the ON_ERROR/ENDON_ERROR block, you can use any kind of DECTPU language statements in the body of a procedure except another ON_ERROR/ENDON_ERROR block. Statements that make up the body of a procedure must be separated with semicolons. For example:
This procedure writes the text "This is Version 1--020" in
the message area.
A procedure name can be any valid identifier that is not a DECTPU
reserved word. Compaq suggests that you use a convention when naming
your procedures. For instance, you might prefix procedure names with
your initials. In this way, you can easily distinguish procedures that
you write from other procedures such as the DECTPU built-in procedures.
For example, if John Smith writes a procedure that creates two windows,
he might name his procedure js_two_windows. This helps ensure
that his procedure name is a unique name. Most of the sample procedures
in this manual have the prefix user_ with procedure names.
Using parameters with procedures is optional. If you use parameters, they can be input parameters, output parameters, or both. For example:
In the preceding procedure, a is an input parameter. It is also an output parameter because it is modified by the procedure input_output. In the same procedure, b is an output parameter.
The scope of procedure parameters is limited to the procedure in which they are defined. The maximum number of parameters in a parameter list is 127. A procedure can declare its parameters as required or optional. Required parameters and optional parameters are separated by a semicolon. Parameters before the semicolon are required parameters; those after the semicolon are optional. If no semicolon is specified, then the parameters are required.
PROCEDURE proc-name [[ ( [[req-param [[...]] ]] [[;opt-param [[...]] ]]
) ]] . . .
A procedure parameter is a place holder or dummy identifier that is replaced by an actual value in the program that calls the procedure. The value that replaces a parameter is called an argument. Arguments can be expressions. There does not have to be any correlation between the names used for parameters and the values used for arguments. All arguments are passed by reference. Example 4-4 shows a simple procedure with parameters.
For example, call the procedure ADD and specify the values 5 and 6 as arguments, as follows:
The string "11" is written to the message buffer.
Any caller of a procedure must use all required parameters to call it. The caller can also use optional parameters. If the required parameters are not present or the procedure is called with too many parameters (more than the sum of the required and optional parameters), then DECTPU issues an error.
If a procedure is called with the required number of parameters, but with less than the maximum number of parameters, then the remaining parameters up to the maximum automatically become "null parameters." A null parameter is a modifiable parameter of data type unspecified. A null parameter can be assigned a value and will become the value it is assigned, but the parameter's value is discarded when the procedure exits.
Null parameters can also be explicitly passed to a procedure. You can do this by omitting a parameter when calling the procedure.
Example 4-5 shows a more complex procedure that uses optional parameters.
To avoid the need to rewrite code, you should write as if this compiler optimization were already implemented. If you need the compiler to evaluate parameters in a particular order, you should force the compiler to evaluate each parameter in order before calling the procedure. To do so, use each parameter in an assignment statement before calling the procedure. For example, suppose you want to call a procedure whose parameter list includes PARAM_1 and PARAM_2. Suppose, too, that PARAM_1 must be evaluated first. To get this result, you could use the following code:
126.96.36.199 Procedures That Return a Result
Procedures that return a result are called function procedures. Example 4-6 shows a procedure that returns a true (1) or false (0) value.
Another way of assigning a value of 1 or 0 to a procedure is to use the DECTPU RETURN language statement followed by a value. See Example 4-13.
188.8.131.52 Recursive Procedures
Procedures that call themselves are called recursive procedures. Example 4-8 shows a procedure named user_reverse that displays a list of responses to the READ_LINE built-in procedure in reverse order. Note the call to the procedure user_reverse within the procedure body.
184.108.40.206 Local Variables
The use of local variables in procedures is optional. If you use local variables, they hold the values that you assign them only in the procedure in which you declare them. The maximum number of local variables that you can use is 255. Local variables are initialized to 0.
If you declare a local variable in a procedure and, in the same procedure, use the EXECUTE built-in to assign a value to a variable with the same name as the local variable, the result of the EXECUTE built-in has no effect on the local variable. Consider the following code fragment:
In this fragment, when the compiler evaluates the string "X := 3", the compiler assumes X is a global variable. The compiler creates a global variable X (if none exists) and assigns the value 3 to the variable. When the MOVE_VERTICAL built-in procedure uses the local variable X, the local variable has the value 0 and the MOVE_VERTICAL built-in has no effect.
The use of constants in procedures is optional. The scope of a constant declared within a procedure is limited to the procedure in which it is defined. See Section 220.127.116.11 for more information on the CONSTANT declaration.
The use of ON_ERROR statements in procedures is optional. If you use an
ON_ERROR statement, you must place it at the top of the procedure just
after any LOCAL and CONSTANT declarations. The ON_ERROR statement
specifies the action or actions to be taken if an ERROR or WARNING
status is returned. See Section 18.104.22.168 for more information on ON_ERROR
The assignment statement assigns a value to a variable. In so doing, it associates the variable with the appropriate data type.
The assignment operator is a combination of two characters: a colon and an equal sign (:=). Do not confuse this operator with the equal sign (=), which is a relational operator that checks for equality.
DECTPU does not do any type checking on the data type being stored. Any data type may be stored in any variable. For example:
This assignment statement stores the string "abc" in
The LOOP/ENDLOOP statements specify the repetitive execution of a statement or statements until the condition specified by EXITIF is met.
LOOP statement_1; statement_2; . . . EXITIF expression;
The EXITIF statement is the mechanism for exiting from a loop. You can place the EXITIF statement anywhere inside a LOOP/ENDLOOP combination. You can also use the EXITIF statement as many times as you like. When the EXITIF statement is true, it causes a branch to the statement following the ENDLOOP statement.
The expression is optional; without it, EXITIF always exits from the loop.
Any DECTPU language statement except an ON_ERROR statement can appear inside a LOOP/ENDLOOP combination. For example:
This procedure uses the EXITIF statement twice. Each expression
following an EXITIF statement defines a condition that causes an exit
from the loop. The statements in the loop are repeated until one of the
EXITIF conditions is met.
The IF/THEN statement causes the execution of a statement or group of statements, depending on the value of a Boolean expression. If the expression is true, the statement is executed; otherwise, program control passes to the statement following the IF/THEN statement.
The ENDIF statement specifies the end of a conditional statement.
IF expression THEN statement_1; . . . statement_n [[ELSE
You can use any DECTPU language statements except ON_ERROR statements in a THEN or ELSE clause. For example:
In this example, nested IF/THEN/ELSE statements test whether a buffer direction should be forward or reverse.
To avoid the need to rewrite code, you should write as if this compiler optimization were already implemented. If you need the compiler to evaluate all clauses of a conditional statement, you should force the compiler to evaluate each clause before using the conditional statement. To do so, use each clause in an assignment statement before using it in a conditional statement. For example, suppose you want the compiler to evaluate both CLAUSE_1 and CLAUSE_2 in a conditional statement. To get this result, you could use the following code:
22.214.171.124 Case Statement
The CASE statement is a selection control structure that lets you list several alternate actions and choose one of them to be executed at run time. In a CASE statement, case labels are associated with the possible executable statements or actions to be performed. The CASE statement then executes the statement or statements labeled with a value that matches the value of the case selector.
The single brackets are not optional for case constants. Example 4-9 shows how to use the CASE statement in a procedure.
CASE constant expressions must evaluate at compile time to either a keyword, a string constant, or an integer constant. All constant expressions in the CASE statement must be of the same data type. There are two special case constants in DECTPU: INRANGE and OUTRANGE. INRANGE matches anything that falls within the case range that does not have a case label associated with it. OUTRANGE matches anything that falls outside the case range. These special case constants are optional.
FROM and TO clauses of a CASE statement are not required. If FROM and TO clauses are not specified, INRANGE and OUTRANGE labels refer to data between the minimum and maximum specified labels.
Example 4-9 shows a sample procedure that uses the CASE statement.
This CASE statement compares the value of the constant selector answers to the case labels (the numbers 0 through 10). If the value of answers is any of the numbers from 0 through 10, the statement to the right of that number is executed. If the value of answers is outside the range of 0 through 10, the statement to the right of [OUTRANGE] is executed. The value of score is written in the message area after the execution of the CASE statement.