JES: Just Educational Services

Jonathan E. Sisk's
Pick/BASIC: A Programmer's Guide

Chapter 16 - Using the EXECUTE Statement

Click to enlarge

Program example 13 illustrated the "old" way of performing a SELECT or SSELECT. Almost all versions of Pick now support the EXECUTE statement.

Unfortunately, they do not all have the same syntax, although they are similar in theory.

The EXECUTE statement allows (virtually) any TCL command to be executed from a PICK/BASIC program. Upon completion of the TCL process, the PICK/BASIC program resumes where it left off. The results or output from the TCL process may be "passed" into the program for processing.

Program Example 14 illustrates the "uptown" method of doing the same thing that was done with Example 13.

Fig. 16-1. Program Example 14.

EX.014
001 * EX.014
002 * Using EXECUTE
003 * mm/dd/yy: date last modified
004 * JES: author's initials
005 *
006 PROMPT ":"
007 *
008 PRINT "ENTER BEGINNING DATE" ·
009 INPUT BEGIN.DATE
010 IF BEGIN.DATE = "QUIT" THEN STOP
011 *
012 PRINT "ENTER ENDING DATE" :
013 INPUT END.DATE
014 IF END.DATE = "QUIT" THEN STOP
015 *
016 PRINT "DO YOU WANT THE REPORT PRINTED ? (Y/N=<CR>) ":
017 INPUT PRINTER.FLAG
018 IF PRINTER.FLAG = "" OR PRINTER.FLAG = "Y" THEN PRINTER ON
019 *
020 SENTENCE = \SSELECT STAFF BY NAME WITH BIRTHDAY >= "\
021 SENTENCE = SENTENCE: BEGIN.DATE: \" AND WITH
022 SENTENCE = SENTENCE: \BIRTHDAY <= "\ : END.DATE: \"\
023 *
024 EXECUTE SENTENCE
025 *
026 HEADING "'LC'BIRTHDAYS BETWEEN ":BEGIN.DATE:" AND ":END.DATE:"'L"
027 *
028 OPEN "STAFF" TO STAFF.FILE ELSE STOP 201,"STAFF"
029 DIM STAFF.ITEM(15)
030 *
031 1 READNEXT ITEM.ID ELSE
032 PRINTER OFF
033 PRINT "REPORT COMPLETE."
034 STOP
035
036 *
037 MATREAD STAFF.ITEM FROM STAFF.FILE, ITEM.ID ELSE
038 CRT "ITEM" : ITEM. ID : " IS MISSING FROM THE STAFF FILE"
039 CRT "PRESS RETURN TO CONTINUE OR 'QUIT' TO STOP" :
040 INPUT RESPONSE
041 IF RESPONSE = "QUIT" THEN STOP
042 GOTO 1
043 END
044 *
045 PRINT "STAFF ID : " : ITE`.ID
046 PRINT
047 PRINT "NAME" "L#20": STAFF.ITEM(1)
048 PRINT "ADDRESS" "L#20" : STAFF.ITEM(2)
049 PRINT "CITY" "L#20" : STAFF.ITEM(3)
050 PRINT "STATE" "L#20" : STAFF.ITEM(4)
051 PRINT "ZIP" "L#20" : STAFF.ITEM(5)
052 *
053 PRINT "PRESS ANY KEY FOR NEXT ITEM OR <CTL> X TO QUIT " :
054 PAGE
055 *
056 GOTO 1
057 *
058 END

THE EXECUTE STATEMENT

The "generic" form of the Pick EXECUTE statement has the general format:

EXECUTE "TCL.expression" {RETURNING return.variable} {CAPTURING capture. variable}

Any TCL command may be issued. Upon completion of the TCL process, execution is returned to the program at the next statement after EXECUTE. There are two commands, however, that do not return control; one, of course, is OFF, and the other is LOGTO.

Effectively, Program Example 14, does exactly the same thing that Example 13 did: it generates a "select list" which is passed into the program. The means by which the command was constructed for the EXECUTE statement were as follows:

020 SENTENCE = \SSELECT STAFF BY NAME WITH BIRTHDAY >=
021 SENTENCE = SENTENCE: BEGIN.DATE: \" AND WITH \
022 SENTENCE = SENTENCE: \BIRTHDAY <= "\: END.DATE: \"\

The SELECT and SSELECT statements have a syntactical requirement that "value strings" used in the selection criteria must be enclosed in double quotes.

Suppose, for instance, that you wanted to issue the following sentence at the TCL prompt:

SSELECT STAFF WITH BIRTHDAY>="5/1/51" AND WITH
BIRTHDAY<="12/1/91/"

The value strings in this sentence are "5/1/51" and "12/1/91."

To enclose quotes within a literal string is sometimes a little tricky. For example, attempting to print the literal:

JOE'S BAR & GRILL 

by issuing the statement:

PRINT 'JOE'S BAR & GRILL'

fails the compile phase and reports the message "UNEVEN NUMBER OF DELIMITERS." This happens because of the choice of quotes in the literal string. It may be correctly stated with the statement:

PRINT "JOE'S BAR & GRILL" 

or, the statement:

PRINT \JOE'S BAR & GRILL\

The ""," (backslash) character is treated just like a single or double quote when used as a literal string delimiter. The reason the backslash character was chosen instead of single quotes is that sometimes the string needs to have both single and double quotes embedded. An example of this is when you want to issue an ACCESS sentence which contains a HEADING, such as:

>SORT STAFF BY NAME HEADING "'LC'STAFF REPORT
PAGE 'PL'"

Note that the sentence contains both single and double quotes. To treat this as a literal string requires the backslash as the string delimiter. Shown below is the statement to EXECUTE this sentence:

EXECUTE \SORT STAFF BY NAME HEADING "'LC'STAFF
REPORT PAGE 'PL"'\

The CAPTURING Clause

The CAPTURING clause in an EXECUTE statement is used to direct the output from the TCL process into a variable, For example:

EXECUTE "WHO" CAPTURING OUTPUT

Upon execution of this EXECUTE statement, the output from the WHO verb is placed into the variable, OUTPUT.

Normally, the WHO verb produces output similar to the following:

WHO
9 JES

The "9" indicates the port number, and "JES" indicates the current account name. Now that this output is assigned to the variable, OUTPUT, it may be manipulated or printed. For instance, if the statement:

PRINT OUTPUT 

were issued, the following displays:

9 JES

This could also be manipulated with any of the functions discussed in the earlier chapters. For example, retrieving just the port number could be accomplished with the statement:

PORT = FIELD(OUTPUT," ",1)

which retrieves all the characters up m the first space in the variable OUTPUT, and assigns it to the variable PORT.

Similarly, the account name could be extracted with the statement:

ACCOUNT = FIELD(OUTPUT," ",2)

which retrieves the string of characters from the first through the second space in the variable OUTPUT, and assigns it to the variable ACCOUNT.

When the CAPTURING clause "captures" output that has more than one line, each line feed at the end of an output line is "converted" to an attribute mark. This effectively allows the output to be treated as a dynamic array. Here's an example:

EXECUTE "LISTU" CAPTURING OUTPUT

To print each line of the output separately requires treating OUTPUT as a dynamic array. Figure 16-2 illustrates this principle.

Line 1 equates the constant ATTRIBUTE. MARK to the decimal character 254. Line 2 performs the EXECUTE statement, routing the output to the variable OUTPUT. Line 3 is used to determine how many lines of output were generated by the EXECUTE. Line 4 establishes a FOR-NEXT construct to loop through all the lines of output. Line 5 takes the current value of 1 and extracts the corresponding "attribute" from the dynamic array OUTPUT, After looping through all the attributes, the program stops.

The RETURNING Clause

The optional RETURNING clause in the EXECUTE statement provides a means of dealing with error messages that are generated as a result of a TCL expression. When this clause is used, all error message item-ids (from the ERRMSG file) are returned to the specified variable. When more than one error message item-id is returned, each is separated from the others by a space (much like the Primary Input Buffer). For example:

EXECUTE "SSELECT STAFF BY NAME" RETURNING
ERROR.LIST

Once the statement has been issued, the program may then be instructed to examine the list of error message item-ids. Figure 16-3 illustrates one such technique for examining the error message item-id list.

001    EQUATE ATTRIBUTE.MARK TO CHAR(254)
002 EXECUTE "LISTU" CAPTURING OUTPUT
003 NUMBER.LINES = DCOUNT(OUTPUT,ATTRIBUTE.MARK)
004 FOR I = 1 TO NUMBER.LINES
005 PRINT OUTPUT<I>
006 NEXT I

Fig. 16-2. Printing the dynamic array created with the CAPTURING clause.

001 EXECUTE "SSELECT STAFF BY NAME" CAPTURING OUTPUT RETURNING ERROR.LIST
002 MAX = DCOUNT(ERROR.LIST," ")
003 FOR I = 1 TO MAX
004 ERROR.NUMBER = FIELD(ERROR.LIST," ",I)
005 BEGIN CASE
006 CASE ERROR.NUMBER = "210"
007 PRINT "FILE HAS ACCESS PROTECTION IMPLEMENTED"
008 CASE ERROR.NUMBER = "401"
009 PRINT "NO ITEMS WERE SELECTED"
010 CASE ERROR.NUMBER = "404"
011 NUMBER.ITEMS.SELECTED = FIELD(OUTPUT," ",1)
012 END CASE
013 NEXT I

Fig. 16-3. Examining the error message item-ids.

Line 1 executes the EXECUTE statement, using both the CAPTURING and RETURNING clauses. Line 2 determines the number of error message item-iris that were returned by the TCL command. Line 3 sets up a FOR- NEXT loop, using the variable MAX as the upper end of the loop.

Line 4 assigns the variable ERROR.NUMBER by issuing a FIELD function which extracts all the characters up to the position of the space indicated by the value of I. Then line 5 establishes a CASE construct, where each of the error message item-ids may be individually handled. (The three sample CASE statements just skim the tip of the iceberg in terms of error handling. Naturally, much more logic may be added for each possible error condition.)

SOME IMPORTANT NOTES ABOUT EXECUTE

The EXECUTE statement builds a new "workspace" area for each "level" of EXECUTE. For example, the first time a program' executes an EXECUTE statement, a block of workspace is attached, using frames from the overflow table. If this first level of EXECUTE were to run a PICK/BASIC program that also contained an EXECUTE statement, this "second-level" EXECUTE would also attach another set of workspace frames. As a protective mechanism, most versions of Pick provide a limit to the number of levels of EXECUTE. The Pick AT implementation, for example, limits each process to five levels of EXECUTE. This preventive measure is important; without it, one process could quickly "eat up" the entire disk.

FEEDING THE EXECUTE STATEMENT

All good things come with a price tag. In the case of the EXECUTE statement, this price tag is the DATA statement. Back in the old days, all SELECTs and SSELECTs were done from the PROC language. One obscure PROC instruction, called STON and pronounced "STack ON," was used to handle cases of issuing commands that required some further input. These days, when I teach people about the STON instruction, I relate it to "the mighty Carnac," the Johnny Carson character known for his telepathic abilities. His famous shtik is to hold an envelope up to his forehead and announce, "The answer is . . . "; then he opens the envelope to reveal the "question."

This is similar to the STON statement, which activates the Secondary Output Buffer in PROC (some people call this the S.O.B. for short). When a TCL process, such as a SELECT, is executed from the Primary Output Buffer, the command to deal with the result of the process (in this case, a select list) is placed in the Secondary Output Buffer. (This is like answering the question before it is asked.)

PICK/BASIC does not have a similar requirement. You don't have to worry about any of the nefarious input or output buffers. Rather, when a process like a SELECT is executed with an EXECUTE statement, the command to deal with the result of the process is "fed" from the DATA statement. Here are two lines of code that illustrate this principle:

001 DATA "SAVE-LIST STAFF.LIST"
002 EXECUTE "SSELECT STAFF BY NAME"

Note that the DATA statement containing the "answer" must occur in the program before the EXECUTE statement.

A CONTROVERSIAL STATEMENT ABOUT THE PROC LANGUAGE

The EXECUTE statement is a much more elegant way of handling TCL processes than its predecessor, the PROC language. One controversial point needs to be mentioned: The EXECUTE statement could single-handedly do away with the need for the PROC language. Yes, I know, all of your reports and menus are written in PROC--but that doesn't mean that you can't start doing things in PICK/BASIC with the EXECUTE statement, rather than relying on PROC interaction. The PROC language provided a "bridge" be- tween PICK/BASIC and the ACCESS retrieval language. Now that PICK/BASIC can "talk" to ACCESS without getting confused, PROC is really no longer needed. The most important aspect of eliminating PROCs is that everything can be done in one programming language.


REVIEW QUIZ 14

1) What function does the EXECUTE statement perform?

2) What function does the CAPTURING clause perform in an EXECUTE statement?

3) What function does the HEADING statement perform?

4) What HEADING statement is required to print the following sample heading?

(top line blank)

Aged Trial Balance Report Page n

as of (dd mmm yyyy)

(blank line)

5) What function does the READNEXT function serve?

6) What function does the PAGE statement serve?

Previous chapter Next chapter Top

 

Creative Commons License
Jonathan E. Sisk's "Pick/BASIC: A Programmer's Guide" by Jonathan E. Sisk is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at jes.com.