I find COBOL level-88 declarations a bit confusing, which isn’t made any easier by usage that is probably wrong. Here’s an example from code that I was trying to step through in the debugger (anonymized):
WORKING-STORAGE SECTION. 01 data. 10 function-type PIC X(01). 88 option-a VALUE '1'. 88 option-b VALUE '2'. 88 option-c VALUE '3'. 88 option-d VALUE '4'.
With the use like so:
It’s my understanding that this is essentially equivalent to:
IF function-type = '1' AND function-type = '2' AND function-type = '3' NEXT SENTENCE ELSE GO TO meaningless-label-2.
Do I misunderstand the level-88 variables should be used, or is this just a plain old impossible-to-be-true if check? Putting this into a little sample program, confirms that we hit the ELSE:
IDENTIFICATION DIVISION. PROGRAM-ID. TESTPROG. ENVIRONMENT DIVISION. CONFIGURATION SECTION. DATA DIVISION. WORKING-STORAGE SECTION. 01 data. 10 function-type PIC X(01). 88 option-a VALUE '1'. 88 option-b VALUE '2'. 88 option-c VALUE '3'. 88 option-d VALUE '4'. PROCEDURE DIVISION. move '1' to function-type perform meaningless-label-1 thru meaningless-label-6 goback . meaningless-label-1. * IF function-type = '1' AND function-type = '2' AND * function-type = '3' IF option-a AND option-b AND option-c NEXT SENTENCE ELSE GO TO meaningless-label-2. display 'IF was true.' goto meaningless-label-6 . meaningless-label-2. display 'IF was not true.' . meaningless-label-6. EXIT .
I get SYSOUT of:
as I expected. If these were level-88 variables each “belonging” to a different variable, such as:
IDENTIFICATION DIVISION. PROGRAM-ID. TESTPROG. ENVIRONMENT DIVISION. CONFIGURATION SECTION. DATA DIVISION. WORKING-STORAGE SECTION. 01 data. 10 blah PIC X(01). 88 blah-option-a VALUE '1'. 88 blah-option-b VALUE '2'. 10 foo PIC X(01). 88 foo-option-a VALUE '1'. 88 foo-option-b VALUE '2'. 88 foo-option-c VALUE '3'. 10 bar PIC X(01). 88 bar-option-c VALUE '3'. 88 bar-option-d VALUE '4'. PROCEDURE DIVISION. move '1' to blah move '2' to foo move '3' to bar perform meaningless-label-1 thru meaningless-label-6 goback . meaningless-label-1. IF blah-option-a AND foo-option-b AND bar-option-c NEXT SENTENCE ELSE GO TO meaningless-label-2. display 'IF was true.' goto meaningless-label-6 . meaningless-label-2. display 'IF was not true.' . meaningless-label-6. EXIT .
This has the ‘IF was true’ SYSOUT. Perhaps the original coder meant to use OR instead of AND?
The use of the “set” command is ideal with level 88;
10 blah PIC X(01).
88 blah-option-a VALUE ‘1’.
88 blah-option-b VALUE ‘2’.
By using SET blah-option-a TO TRUE, this sets the 10 blah variable to ‘1’. Conversely, if you moved say ‘2’ into blah, the command IF blah-option-b would be TRUE whereas blah-option-a would be FALSE.
So set the conditions will change the parent; move a value to the parent, sets the conditional to either TRUE or FALSE.
Another way of using level 88 is as follows, setting the conditional will set the parent for use in error setting. I use them for setting error codes on INVALID KEY when reading an indexed file.
01 Error-Message PIC X(20).
88 Invalid-Code-Error VALUE “Invalid code entered”.
88 Customer-Not-Found VALUE “Customer not found, try again”.
… later in code ….
ACCEPT some-code.
IF some-code IS NOT EQUAL TO “xxxx” THEN
SET Invalid-Code-Error TO TRUE
DISPLAY Error-Message
END-IF
Thanks Paul, I knew there had to be a more natural way to do the write part of a level 88 value assignment!