Procedure 3.00.10Unlocking its secrets |
|
From "VS Procedure", Access 86, November 1986 |
|
[ Prior Article ] [ Return to the Catalog of articles ] [ Next Article ] |
For some time, most VS shops have had access to release 3.00.10 of the Procedure interpreter. This release incorporates several improvements that go a long way toward making Procedure a structured, maintainable language. Since little documentation on these features exists at this writing, I have created example procedures to demonstrate their use.
How do you know if you have the current version of Procedure? Since it was shipped with release 6.40 of the operating system, most shops should be using it. If you aren't sure, run PROC in the system library and examine the version number at the top of the screen.
I have grouped the new Procedure features by function. Here are descriptions and examples:
The first extension is a small one: the allowed length of string variables has been increased from 256 to 512 characters. This is handy when you wish to use a large string to carry many variables. Text-hungry procedures such as menus should benefit from this increase.
Several new functions have been added to provide better internal control and improved readability. These include the CALL and END statements, the &LABEL function, and enhancements to the GOTO statement.
The CALL statement allows a section to perform a routine in the same procedure, then return control to the point of origin. This is functionally equivalent to the GOSUB function in BASIC or PERFORM in COBOL. When a CALL is encountered, the procedure branches to the indicated step label, returning on completion to the step after the CALL statement. Using CALL instead of GOTO makes it easier to construct generic routines that are executed from many points in the procedure. The resulting procedure is also easier to understand and modify.
In addition, the GOTO and CALL functions now allow use of a variable that contains the name of the step label, rather than requiring that the label be stated explicitly. To tell if such a "constructed" label is valid, the &LABEL function has been added to allow you to check for the its existence.
Refer to TEST1 (Figure 1), the example procedure for these three functions. In this example, the value of the key pressed by the user is appended to the literal "@". If the label exists, it is called; otherwise, control passes back to S01. In other words, only PF'01, PF'02, or PF'16 will have any effect.
The called section is performed until an END statement is encountered, when control returns to the end of step S01. Note that no END statement is used under step @16; since this is the end of the procedure, the interpreter assumes and end to the CALL.
Several other functions have been added for string manipulations. They are &BYTE, &RANK, ©, &INDEX, &TRANSLATE, and &VERIFY.
The &BYTE function allows you to specify the numeric value of a byte (character) as a decimal integer. This can be used for special purposes, such as displaying a character that is not on the keyboard. The complementary function to &BYTE is &RANK, which returns the decimal integer value of a character. Finally, © duplicates a single character throughout a string variable.
These three functions are shown in procedure TEST2 (Figure 2). This procedure accepts a number from the user, then translates it to the corresponding workstation character of that value. For example, the character "5" is represented by a value of 53. (Notice to hexidecimal heads out there: the value is in DECIMAL, rather than the usual hex value.)
After translating the number to a character through &BYTE, the procedure reverses the process, using the &RANK function to return it to a numeric value. This will be the same number as you entered above, and is here solely for illustrative purposes.
I have chosen a more complex method of demonstrating ©. The character is copied several times into two places within a 16-character variable: one beginning at position 1 and another beginning at position 10. Both run for five positions. Thus, the character '5' would be shown as follows:
The string variable is '55555 55555 'The &INDEX, &TRANSLATE, and &VERIFY functions allow you to determine where text elements lie in a string variable, and act on that information. &INDEX searches a string for occurrences of another string, returning its position if found. &TRANSLATE searches a string, converting occurrences of a specified element with another. &VERIFY allows you to determine if a string contains elements that are not allowed.
These three functions are shown in procedure TEST3 (Figure 3). I have attempted to duplicate a realistic situation: how to test whether a file name contains valid characters. The example file name ("BAD.FILE") is not an acceptable file name on VS systems because of the period in the center. The &VERIFY function tells us this, along with the position of the "bad" element. The file name is then corrected using &TRANSLATE, where the period is converted to an "X". Finally, the starting position of "FIL" is located with the &INDEX function.
Diehard algebraic users will undoubtedly find some use for the &MIN, &MAX, and &MOD functions.
&MIN returns the smaller of two values. &MAX returns the larger of two values. The &MOD function divides one number by another, then returns an integer value of the remainder.
Procedure TEST4 (Figure 4) shows these three functions in use. After accepting two numbers, if performs the three functions and displays the results. (Since I can't think of a practical application for these functions, mere illustration of their abilities will have to do.)
The extensions to Procedure presented above allow the programmer or advanced user to further increase the reliability and maintainability of their procedures. Procedure structure can be improved significantly through the use of the CALL statement, with control statements at the top of the procedure. This allows use of better organizational structure, including most elements of structured design.
Other major gains are increased error-checking abilities. The &INDEX, &VERIFY, and &TRANSLATE functions can be used to provide more thorough checking of input data, as shown with the file name check in the example procedure.
So what's missing? File output is the only major element keeping Procedure from full status as a high-level language. While a limited amount of file creation can be done through CREATE or other utilities, the desirability of direct, simple file creation from a procedure cannot be denied.
Of course, extensions to Procedure always exist in the form of calls to external subroutines. I have created such subroutines to solve needs of my own. If you are interested in seeing these in a future column, please write and tell me so.
Next month we'll feature a procedure that makes advanced use of some of the functions described here.
Figure 1: Procedure Test1 - Example of Program Control
PROCEDURE TEST1 DECLARE &RUNSTEP STRING (03) INITIAL "@ " S01: PROMPT PFKEY = &RUNSTEP(2,2) CENTER BRIGHT LINE "TEST1 - Subroutines";; CENTER LINE "Please select option:";; CENTER "(01) BANG "; CENTER "(02) WHIMPER ";; CENTER "(16) Return to Funway";; IF &LABEL (&RUNSTEP) CALL &RUNSTEP GOTO S01 @1: PROMPT ALARM = "YES" CENTER BLINK "B A N G ! !";; END @2: PROMPT CENTER LINE " "; CENTER LINE "(whimper!)";; END @16: RETURN
Figure 2: Procedure Test2 - Character Tests
PROCEDURE TEST2 DECLARE &CHAR STRING (01) DECLARE &NUMB STRING (03) DECLARE &STR STRING (16) S01: PROMPT CENTER BRIGHT LINE "TEST2 - Character Test";; CENTER "Enter a number from 1 to 127";; CENTER "NUMBER =", NUMERIC &NUMB; IF &NUMB = " " GOTO S99 ASSIGN &CHAR = &BYTE(&NUMB) ASSIGN &NUMB = &RANK(&CHAR) ASSIGN &STR(1) = ©(&CHAR,5) ASSIGN &STR(10) = ©(&CHAR,5) S02: PROMPT CENTER BRIGHT LINE "TEST2 - Character Test";; CENTER "The single character is ", LINE &CHAR;; CENTER "The numeric value of the character is ", LINE &NUMB;; CENTER "The string variable is ", LINE &STR;; S99: RETURN
Figure 3: Procedure Test3 - String Manipulation Options
PROCEDURE TEST3 DECLARE &BADFIL STRING (08) INITIAL "BAD.FILE" DECLARE &GOODFIL STRING (08) DECLARE &COMPARE STRING (39) INITIAL "@#$0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" DECLARE &INDNUMB INTEGER DECLARE &VERNUMB INTEGER S01: ASSIGN &INDNUMB = &INDEX(&BADFIL,"FILE") ASSIGN &VERNUMB = &VERIFY(&BADFIL,&COMPARE) ASSIGN &GOODFIL = &TRANSLATE(&BADFIL,"X",".") S02: PROMPT CENTER BRIGHT LINE "TEST3 - String Manipulation Examples";; CENTER "The original string = ", LINE &BADFIL;; CENTER "'FIL' occurs at position ", LINE &INDNUMB;; CENTER "Non-acceptable data begins at position ", LINE &VERNUMB;; CENTER "The corrected file = ", LINE &GOODFIL;; S99: RETURN
Figure 4: Procedure Test4 - Math Functions
PROCEDURE TEST4 DECLARE &NUMB1, &NUMB2, &NUMB3 STRING (03) S01: PROMPT CENTER BRIGHT LINE "TEST4 - Test Math Functions";; CENTER "First number = ", NUMERIC &NUMB1; CENTER "Second number = ", NUMERIC &NUMB2; S02: PROMPT CENTER BRIGHT LINE "TEST4 - Test Math Functions";; CENTER "The numbers are ", &NUMB1, " and ", &NUMB2;; CENTER "MIN = ", LINE &MIN(&NUMB1, &NUMB2); CENTER "MAX = ", LINE &MAX(&NUMB1, &NUMB2); CENTER "MOD = ", LINE &MOD(&NUMB1, &NUMB2);; S99: RETURN
Copyright © 1986 Dennis S. Barnes
Reprints of this article are permitted without notification
if the source of the information is clearly identified