The following command will compile a program named 'pgm.cob'. The extension of the file containing the source code must be '.cob'.
ccbl pgm.cob
Any errors will displayed on the screen. A compile listing of the program can be generated by adding the Lsfo switch and a listing name:
ccbl -Lsfo pgm.list pgm.cob
The following command will execute a program named 'pgm.cob'. The program has already been successfully compiled into object code named 'pgm.obj'
runcbl pgm
So you're trying to perform some sort of math on non-numeric data?
You can use the debugger to track down any error. But as an alternative you can try this approach.
First, write down the hex offset that's part of the error message. It's the location of the statement that is having this error. Next, recompile the program and produce a listing. Pull this listing into an editor and scroll down to the Procedure Division.
Each statement will have a byte offset next to it. The byte offset from the error message will probably be in between two of the ones in the listing though it's possible to have an exact match. If you do have an exact match then that is the statement that's crashing. If your byte offset is in between two offsets in the listing then the one before is the statement you're after. This may be enough information to figure out which numeric field has the non-numeric data.
Why not get an exact match with the offset? Each COBOL statement compiles into several machine instructions which is what the computer is executing. When the computer encounters a problem it tells you the offset of the machine instruction - it doesn't know the offset of the original COBOL statement that generated that instruction. Heck, it doesn't even know that these instructions came from a COBOL program as opposed to C++, Java, etc.
If you still need help in pinpointing the cause of the error you can use the debugger (set a breakpoint on that statement and display the contents of the involved numeric fields) or you can insert a display statement before the statement with the error and display the contents of the numeric fields. Note that adding a statement to your program could change the byte offset of the error when you run it again.
For example, you run your program and receive the dreaded 'non-numeric data' message and you're told it's at 0000028C. You recompile your program to get a listing. You look through that listing and see this:
00000288 MULTIPLY IN-SALARY BY WS-STATE-INCOME-TAX-RATE GIVING WS-STATE-INCOME-TAX 0000028E MOVE WS-STATE-INCOME-TAX TO WS-PRINT-STATE-INCOME-TAX
Add the following statement (in the source code, not the listing) immediately before the multiply:
DISPLAY '*' IN-SALARY '*' WS-STATE-INCOME-TAX-RATE '*'
Don't worry about the 'GIVING' field becuase it's current contents are not a concern. The problem is with one of the fields that are actually part of the calculation. When you recompile and run you should see the problem. For example:
*0000025000* 003* Non-numeric data in numeric field at .....
You see that WS-STATE-INCOME-TAX-RATE contains some spaces, which are not numeric and will cause the MULTIPLY to blow up. Now you have a starting point. Note that DISPLAYs do not do any formatting such as suppressing leading zeroes.
You bracket the fields in the display with some character (like the '*') so that you see exactly what's in those fields. Without those '*' the fact that there were spaces and numbers in that field may have been lost. It also serves as a visual break between fields.
To prepare the program for the debugger it must be compiled with the Zd switch:
ccbl -Zd pgm.cob
To run the program in debug mode use the d switch:
runcbl -d pgm
Refer to your course notes for the debugger commands.
Since COBOL and UNIX have a deep-rooted philosophical difference as to what constitutes a file one has to be careful when having one COBOL program create a file that will be read by another COBOL program when working on the UNIX platform.
If WRITE commands are used the data will be written to the file but there will be no actual end-of-record markers in the file. The data will appear as one long stream of bytes and not as separate, physical records. This is the UNIX view of a file. When a COBOL program attempts to read this file later it may not do it correctly because it expects the records to physically separated. This is the COBOL view of a file.
The COBOL program that creates a file that is to be read by another COBOL program should use the BEFORE ADVANCING 1 LINE clause when writing the records. Don't use AFTER, it will write a null record before writing the data. Note that this increases the size of each record by one byte (the end of record marker) so that needs to be taken into account.
Processing interactively means you're not using files. Input comes from the keyboard and output goes to the display screen. You do not need SELECTs, FDs, OPENs, CLOSEs, READs and WRITEs for these devices.
Input is done through the ACCEPT statement and output through the DISPLAY statement. See the COBOL algortihms page for code to accomplish this.
Two working-storage fields are necessary for each numeric value that is to be received from the keyboard. One will be formatted for suppressing leading zeroes and the other will be straight numerics.
Oddly, the field suppressing the leading zeroes will be the input field even though a 'Z' is normally in PIC clauses for output fields. Defining the input field in this manner will cause COBOL to pad (on the left) the input value with zeroes if it is shorter than the defined length of the field. This is what is desired. If the input field was defined as straight numerics (PIC 9(4) instead of PIC ZZZ9) then any padding necessary will be spaces and done on the right. This makes the field non-numeric and any math done with it will crash the program.
Math can't be done on an editted-field (including PICs with 'Z's) even thought the actual data looks numeric. It needs MOVEd to a straight numeric field before any calculations can be done to/with it.