PIC

An invalid transformation of a COBOL data description entry

August 28, 2020 COBOL , , , , ,

Here’s a subtle gotcha that we saw recently.  A miraculous tool transformed some putrid DELTA generated COBOL code from GOTO soup into human readable form.  Among the transformations that this tool did, were modifications to working storage data declarations (removing unused variables in the source, and simplifying some others).  One of those transformations was problematic.  In that problematic case the pre-transformed declarations were:

This declaration is basically a union of char[8] with a structure that has four char[2]’s, with the COBOL language imposed restriction that the character values can be only numeric (EBCDIC) digits (i.e. ‘\xF0’, …, ‘\xF9’).  In the code in question none of the U044-BIS* variables (neither the first, nor the aliases) were ever used explicitly, but they were passed into another COBOL program as LINKAGE SECTION variables and used in the called program.

Here’s how the tool initially transformed the declaration:

It turns out that dropping that first PIC and removing the corresponding REDEFINES clause, was an invalid transformation in this case, because the code used INITIALIZE on the level 01 object that contained these variables.

On page 177, of the “178 Enterprise COBOL for z/OS: Enterprise COBOL for z/OS, V6.3 Language Reference”, we have:

(copyright IBM)

FILLER
A data item that is not explicitly referred to in a program. The keyword FILLER is optional. If specified,
FILLER must be the first word following the level-number.

… snip …

In an INITIALIZE statement:
• When the FILLER phrase is not specified, elementary FILLER items are ignored.

The transformation of the code in question would have been correct provided the “INITIALIZE foo” was replaced with “INITIALIZE foo WITH FILLER”.  The bug in the tool was fixed, and the transformed code in question was, in this case, changed to drop all the aliasing:

As a side effect of encountering this issue, I learned a number of things:

  • FILLER is actually a COBOL language keyword, with specific semantics, and not just a variable naming convention.
  • Both ‘INITIALIZE’ and ‘INITIALIZE … WITH FILLER’ are allowed.
  • INITIALIZE (without FILLER) doesn’t do PIC appropriate initialization of FILLER variables (we had binary zeros instead of EBCDIC zeros as a result.)

My first COBOL program.

November 9, 2017 Mainframe , , , , ,

I recently bought Murach’s COBOL reference:

and coded the chapter 1 compound interest calculation myself before looking at the solution.  I was surprised to see that (n)vim has built in syntax highlighting for COBOL.  It even helps position the comments and line starts in the right places, which was handy.

Having been horrified any time in the past that I saw COBOL code, it feels weird to be coding my own hello-world in the language, but it works, and with ALL CAPS output, it looks sufficiently dinosaur’ish to be COBOL:

./interest 
-----------------------------------------------
TO END PROGRAM, ENTER 0.
ENTER THE INVESTMENT AMOUNT.
1000
ENTER THE NUMBER OF YEARS.
1
ENTER THE INTEREST-RATE.
1
FUTURE-VALUE = 0001010.00
-----------------------------------------------
TO END PROGRAM, ENTER 0.
ENTER THE INVESTMENT AMOUNT.
1000
ENTER THE NUMBER OF YEARS.
2
ENTER THE INTEREST-RATE.
1
FUTURE-VALUE = 0001020.10
-----------------------------------------------
TO END PROGRAM, ENTER 0.
ENTER THE INVESTMENT AMOUNT.
0
END OF SESSION.

Notes and questions:

  • I wasn’t sure about when I had to use statement terminators (.’s) in the ELSE body, so I moved the whole basic block to a helper function.
  • I got messed up initially with the syntax for the PIC values at first, as I’d used .’s instead of V’s to specify that my variables were numeric.  This caused cobc (gnu-cobol front end) to complain that INTEREST-AMOUNT was not numeric, and I eventually found the answer in the PIC table of the book.
  • The point of this exercise was probably to use a loop, which I avoided by calculating the value in one shot.  I’ll have to go back and see how to do that.
  • There doesn’t seem to be any notion of function prototype, and the function bodies can be either before or after their calls.
  • Functions are annoyingly, but appropriately (given the requirement to be over the top verbose for many things), called PARAGRAPHs in COBOL.  I wonder what the mainframe does with name mangling, given that symbol names have to be 8 characters, and COBOL function names are up to 30.  Perhaps only the external entry points (the program-id?), have that restriction?
  • cobc’s implementation of -g sucks, and a debug session shows the lines of the generated .c files instead of the COBOL sources.  There ought to at least be #line markers in the generated C sources instead of comments.