Debugging from COBOL
Many people dont realize that there are some built-in facilities for debugging a COBOL program. Ive made use of them for years, but sometimes you forget that other people may not be using them. I was just thinking about covering this topic, and then I got an e-mail from Mark Wonsil at 4M Enterprises suggesting that I cover it. Great minds think alike.
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. 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. Its a little faster. 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 you are able to turn it on with a quick change and recompile.
Now the downside to this is that it requires a recompile to be effective. The other fun thing to use with the debugging clause is the DECLARATIVES. Now Ive never found another use for it, but for debugging it is pretty useful. Actually, if someone can tell me something else theyve 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 below).
PROCEDURE DIVISION. DECLARATIVES. DEBUG SECTION. USE FOR DEBUGGING ON ALL PROCEDURES. 000-DEBUG-TRACE. DISPLAY DEBUG-NAME DEBUG-CONTENTS "LINE =" DEBUG-LINE. END DECLARATIVES.
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. Ive never actually played with changing it because it always satisfied my need. As an example, I dont 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, Ive run the
program twice, providing the same input both times.
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:
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 all sorts of things, like seeing if you have a loop somewhere, or are falling through when you shouldnt be. I know its 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 more quickly than single-stepping through a bunch of code.
I hope youve enjoyed this foray 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 arent adding a 31st table entry to a table that has only 30 entries, or you arent 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 too 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 wouldnt fail, and they would be all done. I really hate to think about how much corrupted data is in their system because of that decision.
Shawn Gordon, whose S.M. Gordon & Associates firm supplies HP 3000 utilities, has worked with 3000s since 1983.
Copyright The 3000 NewsWire. All rights reserved.