Inside COBOL #77 (Debugging from COBOL)
Many people don’t realize that there are some built in facilities for doing debugging in a COBOL program. I’ve made use of them for years, but sometimes you forget that other people may not be using them. I had just been thinking about covering this topic, and suddenly I got an email from Mark Wonsil at 4M Enterprises suggesting that I cover it. Great minds think a like.
The first two methods are native, and they are tied to a compile option in the ENVIRONMENT DIVISION, namely the SOURCE-COMPUTER directive. Under normal circumstances you can pretty much put whatever you want here, typically mine says SOURCE-COMPUTER HP-3000. Now to take advantage of the built in debugging features you must first make a modification to this line, it must now read:
SOURCE-COMPUTER. HP-3000 WITH DEBUGGING MODE.
Now what I do is have two lines in the ENVIRONMENT DIVISION one with, and one without the DEBUGGING clause, and just comment one out. It’s a little faster. Now the first trick you can use is by putting a D in column 7 (this is really the first usable column for COBOL under most editors if it is saved numbered. When you do this, the line is considered a comment, unless the program is compiled with the WITH DEBUGGING MODE directive. This allows you to put all sorts of code into your program for tracing and such and then be able to turn it on with a quick change and recompile.
Now of course the downside to this is that it requires a recompile to be affective. The other fun thing to use with the debugging clause is the DECLARATIVES. Now I’ve never found another use for it, but for debugging is pretty useful. Actually, if someone can tell me something else they’ve used DECLARATIVES for, I would be interested in seeing it.
Basically the first line after the PROCEDURE DIVISION has to say DECLARATIVES (see figure 1). I believe I might have got this from the COBOL manual originally, but there are some predefined variables that you can access that will give you some pretty useful information. I’ve never actually played with changing it because it always satisfied my need, as an example, I don’t know if the “USE FOR DEBUGGING ON ALL PROCEDURES” can be changed to specific procedures, but it would make an interesting experiment.
Now the nice thing about the DEBUG SECTION is that you can control it with a run time switch instead of compile time. If you look at figure 2, you will see that I run the program with PARM=1. In the example I’ve run the program twice, providing the same input both times, the program has a prompt of “B>”. The second run has the PARM=1 so you can see how the debug trace works. You will see each paragraph, the line it is on and how you got there, either fall through, perform, or go to.
This is very convenient for seeing if you have a loop somewhere or are falling through when you shouldn’t be, all sorts of things. I know it’s saved my bacon a number of times, and it is a good tool to use before getting into your source level debugger, because it will narrow down where the potential problem is much quicker than single stepping through a bunch of code.
I hope you’ve enjoyed this forray into debugging. One final note I will make is that adding the BOUNDS directive to the $CONTROL line can save your life. Bounds checking will make sure you aren’t adding a 31st table entry to a table that has only 30 entries, or you aren’t trying to put data to the zeroth byte of a character array, all sorts of neat things. I had a client with an enormous COBOL program that was having some trouble. The first thing I did was add bounds checking, and we found out they were trying to put to many entries into a table. I left them to the program, and after a couple of weeks of trying to get the program to stop failing on bounds violations, they finally decided that if they took out the bounds checking, then it wouldn’t fail, and they would be all done. I really hate to think how much corrupted data is in their system because of that decision.
Figure 1 PROCEDURE DIVISION. DECLARATIVES. DEBUG SECTION. USE FOR DEBUGGING ON ALL PROCEDURES. 000-DEBUG-TRACE. DISPLAY DEBUG-NAME DEBUG-CONTENTS " LINE = " DEBUG-LINE. END DECLARATIVES. Figure 2 The Kompany: run backtalk BALKTALK Background Job Communicator 11.60822 Copyright 1992 SMGA B> ? UNKNOWN COMMAND NAME B> help COMMANDS: EXIT HELP KILL QUIT RESET RUN STARTJOB STATUS STOPJOB TIMER VERSION XEQ :MPE command %MPEX command B> exit END OF PROGRAM The Kompany: run backtalk;parm=1 BACKTALK-SECT01 START PROGRAM LINE = 014300 A0000-DEFINE-MACROS FALL THROUGH LINE = 010600 A1000-STARTUP FALL THROUGH LINE = 010600 BALKTALK Background Job Communicator 11.60822 Copyright 1992 SMGA G1100-PROCINFO PERFORM LOOP LINE = 014600 G1100-EXIT FALL THROUGH LINE = 042200 A1100-PROMPT LINE = 017700 B> ? UNKNOWN COMMAND NAME A1100-PROMPT LINE = 038200 B> help H1000-HELP PERFORM LOOP LINE = 025700 COMMANDS: EXIT HELP KILL QUIT RESET RUN STARTJOB STATUS STOPJOB TIMER VERSION XEQ :MPE command %MPEX command H1000-EXIT FALL THROUGH LINE = 045200 A1100-PROMPT LINE = 025800 B> exit C9000-EOJ LINE = 024500 C9000-SKIP FALL THROUGH LINE = 039500 END OF PROGRAM The Kompany: