26
Fri, Apr
1 New Articles

Programmer's Toolbox: Debugging CL Programs

CL
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Debugging is an art form. Everybody does his or her own thing to get programs to work, and opinions vary widely as to just what the best debugging aid is. I probably won't change anyone's mind about that, but let me describe what I do and some of the tools I use to assist in debugging.

One of the great advances in programming productivity was the addition of a syntax checker when you are entering source. This eliminates a lot of dumb errors being found by the compiler. The AS/400 went a bit further with this concept by allowing commands to be prompted and checked with the command definition object. This provides a good deal of validity checking (including an optional validity checking program) when you enter a command into a source member. These functions help fix a lot of errors while you are keying rather than have the compiler or execution routines find them.

The CL compiler is going to find errors, such as when the variable is not declared, the GOTO label does not exist, or there are too many DOs or ENDDOs.

The missing DCL and label problems are usually easy to fix without a lot of searching in the code. However, the DO/ENDDO problem can be a real nightmare because the CL compiler listing doesn't give you any assistance on finding your DO groups (as compared to the RPG compiler listing).

If you just added some code and the program no longer compiles because of a DO group problem, you probably know where to look. However, in a more complex case, you may have to look at the whole program.

Several years ago, I did a tool in QUSRTOOL named Display CL Pgm DO Cmds (DSPCLPDO), which is also in the TAA Productivity Tools. It shows you the DO groups with a numbering scheme similar to what RPG uses to highlight the DO groups. The command prompt is shown in Figure 1, and some typical output is shown in Figure 2. Printed output occurs from the command, and Display Spooled File (DSPSPLF) is automatically used. I decided a better idea would be to indent the DO groups to get a pictorial view of what the code was doing. This is the

Print CLP DO Groups (PRTCLPDO) command, and it is in the TAA Productivity Tools product. The command prompt for PRTCLPDO is shown in Figure 3, and some typical output is shown in Figure 4. PRTCLPDO is what I use now. It is also helpful when you are trying to review the logic of a CL program.

These commands do not change the source code. If you prefer to indent DO groups in the source code itself, you can use the Indent CLP DO Groups (INDCLPDO) command in the TAA Productivity Tools, or you can use the Format CL Source (FMTCLSRC) command (see "Indent Your CL Code Automatically," MC, April 1997).

Ideally, a program should include a global Monitor Message (MONMSG) command to trap unexpected errors. During debugging, you may want to comment out the global MONMSG so the system will stop and ask you how you want to handle an expected error condition.

When your program encounters an unexpected error, you will probably see the CPA0701 inquiry message. Your choices will be C, D, I, and R (meaning cancel, dump, ignore, and retry, respectively). Move the cursor to the error and press the F1 key to see a further explanation of the error. This may tell you enough to fix the problem, but if it doesn't, press the F10 key to see the job log.

A simple but effective means of tracing what a CL program does is to turn on logging. This is controlled by the LOG parameter on CRTCLPGM. Most people take the default of *JOB, which means that the logging function can be requested by the job in which the program is running. You can request logging by using this command:

CHGJOB LOGCLPGM(*YES)

You can also turn off logging with LOGCLPGM(*NO). These commands are big messy things to key, and I was using them so often that I finally wrote a shorthand command, Log CL Program (LOGCL). The LOGCL command is in both QUSRTOOL and the TAA Productivity Tools. To get the same function as the CHGJOB mouthful, just key this:

LOGCL

The default is to cause logging, but you can also turn it off with LOG(*NO). After turning on logging, you call the program. The logging that is produced occurs in the form of low-level messages. The logging is not perfect, but two good things happen:

o Some statement numbers appear, so you get a reasonable trace of the program.

o Many of the commands are shown with the real data rather than variable names.

Figure 5 shows what happens if you request logging of the simple program shown previously.

Some major things are missing in the logging. CHGVAR commands are not shown. Also, CALL commands are shown, but not the parameter values.

If I am having trouble with a program, I usually try LOGCL first. However, if you use RMVMSG CLEAR(*ALL), it blows away all the messages received in your program message queue. This includes the logging messages. So if your program is completing normally and you have a RMVMSG CLEAR(*ALL) function, logging isn't going to help you.

Sometimes a "dump" of the variables of the program can be helpful. A dump is a report that

shows the messages on the program's message queue and the contents of all variables, in both character and hexadecimal formats.

You can request a dump in two ways. You can include the Dump CL Program (DMPCLPGM) command in a program, or you can select option D when you respond to the inquiry message for an unmonitored escape message. I don't use this too much, but sometimes it helps. On a rare occasion, I have temporarily placed a DMPCLPGM command into my program to try to figure out what was wrong.

If I still can't figure out what is wrong, I use debug commands. Sometimes, I even use the debug functions just to ensure my program is doing what it should be doing. There are several forms of debug commands you can use. What people actually do varies considerably. I do what I am accustomed to and what works well with my programming approach.

I usually program by using two group jobs. I use the Attn key to flip-flop back and forth. I use the ATNPGM tool in QUSRTOOL and the TAA Productivity Tools to handle the Attn key. I use one group job for source entry and to create programs. I use the other group job for command entry (including debug commands). A single keystroke lets me flip to the other job.

I write OPM CL programs. For several years, I used the system-supported Start Debug (STRDBG) command and associated commands such as Add Breakpoint (ADDBKP) and Add Trace (ADDTRC). These commands are awkward. The prompts are confusing, and you have to put quotes around the CL variables to be displayed.

Here's a typical series of commands:

STRDBG PGM(PGMA)
ADDTRC STMT((10100 12500)) +
PGMVAR(('&VARA' '&VARB'))
CALL PGM(PGMA)

For most of the CL programs I write, I don't need to go into debug mode. But occasionally I'll have a tough program to get debugged. When I do, I use the debug facility a lot. So for debug, either I don't use it at all or I use it a lot on a specific program. If I'm using debug, I generally have an iterative process:

o Make a source change

o Re-create the program

o Flip to my other group job

o Set up for debug

o Call the program

o Display the trace data

I may go through this same set of steps many times before the program is finally working. If you do a similar set of steps, the really horrible thing that can occur is you get distracted and miss the message that says the re-create step failed. I always assume the program is going to compile successfully once I am in this iterative mode. If you take the default on CRTCLPGM of REPLACE(*YES) and the re-create fails, the old program is still there. So if you just call the

program or try to debug it, you can waste a lot of time trying to figure out why your source change didn't do anything.

The REPLACE(*YES) function may be good for replacing production programs, but I began to hate it when testing. I finally fixed my test environment so that I always delete the program before attempting a re-create. If the re-create fails, the program isn't there, and I never waste time debugging the old version. If you'd like to use the same technique to delete the old version first, see the Submit Parameters (SBMPARMS) tool in QUSRTOOL or the TAA Productivity Tools.

The other problem I found with this iterative process is that the debug commands are frustrating and awkward to use. For example, if you use STRDBG, the system sets a pointer to the program. If you re-create the program, the pointer isn't good anymore. If you don't end debug and start the debug process again, you won't get any debug information. You can't even use the Change Debug (CHGDBG) command and rename the same program. So the whole process of iterating can be very painful because of what you have to do to make it work.

After getting confused and frustrated, I wrote a front-end to the system debug function. It's called the Breakpoint (BKP) tool, and it's in QUSRTOOL and the TAA Productivity Tools. The BKP tool supports two basic commands, BKP and TRACE.

Both commands cause a combination of End Debug (ENDDBG), which monitors if not in debug mode, STRDBG, and then either ADDBKP or ADDTRC. You always start clean every time you use BKP or TRACE. The CL variable names are entered without quotes or ampersands. So you would just say something like this:

TRACE STMT(10100 12500) +

PGMVAR(VARA VARB) PGM(PGMA)

Then, to iterate, you just say this:

TRACE STMT(xxx xxx)
CALL PGM(PGMA)
DSPTRCDTA

Both the BKP and TRACE commands are smart enough to remember what program you were working on and what variables you want displayed. All you have to do is vary the statement values. If you want to change the variables, you prompt for the command. They are shown by use of a prompt override program. The values are stored in a data area in QTEMP and extracted by the command processing programs.

I prefer the trace rather than a breakpoint or step function for several reasons:

o If I am smart enough to know where to put the breakpoint, I am usually smart enough to see what the problem is and just fix the code.

o If I am confused as to what is happening, the trace shows me what the program is doing by making a little log. I've used step functions, and the problem I have with them is that I get lulled to sleep pressing the Enter key. Then, when I finally realize I am in the wrong place, I can't back up, and there is no log to show how I got to the wrong place or to review what happened. Many times when debugging, I fall into the trap of thinking I understand the problem when I really don't. Having the log of what the program really has done helps solve some of this.

o Because I use group jobs and delete the program as soon as I submit the re-create, there is a

horrible thing I can do to myself if I use a breakpoint. If I stop at a breakpoint, realize what the problem is, flip to the other side, fix the program, re-create, and then flip back, I am suddenly at a breakpoint of a program that does not exist anymore. Sometimes, I can get out successfully with F3, but sometimes, I wind up taking the job down because the program got deleted while I was using it. This problem does not occur when you use a trace because you have ended the program when you are looking at the trace data.

o Sometimes, when it is a very tough problem, I may generate a lot of trace output. Then, I use DSPTRCDTA OUTPUT(*PRINT) and the scan facility within DSPSPLF to find what I am looking for.

o Sometimes, I use the trace function even if my program looks like it is working correctly just to ensure it is executing the instructions I think it should be. You can sometimes find surprises with this technique.

Sample trace output is shown in Figure 6.

The BKP tool also works with any OPM program, and I use it for RPG as well.

You can use the new debugger with OPM CL programs. When you create the program, specify OPTION(*SRCDBG). Then, use the STRDBG command and specify OPMSRC(*YES). You can then use the functions of watch a variable, step, and so on. While there are some real pluses for the new debugger, having to specify the extra parameters is a pain, and it does not have a trace facility. Since I am most likely going to change the source anyway, I prefer the group job approach and the old debug function.

I sometimes place statements in the source to help me debug. For CL programs, I may send messages or use Copy File (CPYF) to QTEMP or *PRINT. For RPG, I may output some extra print lines or add a print file. While this is a good technique, you have to remember to get these debug statements out of your code before you go into production. I try to follow a convention of using a comment with the letters TSTJFS when I add this kind of code. (JFS are my initials.) So when I am ready to go into production, I just scan the source for TSTJFS.

If I have a CL program that is building up a command to execute using QCMDEXC, I like to send myself a message about what the command is, such as this:

CHGVAR VAR(&CMD) +

VALUE('OPNQRYF FILE(' +
*CAT &xxx *TCAT ...
SNDPGMMSG MSG(&CMD) TOPGMQ(*SAME)
CALL PGM(QCMDEXC) PARM(&CMD 500)
RMVMSG CLEAR(*ALL)

When the message is sent to your own program message queue by the function TOPGMQ(*SAME), the message exists along with all the other messages sent to your program. I usually clear all these messages at the end of my program with the Remove Message (RMVMSG) command. However, if the CALL to QCMDEXC ends abnormally, I have a message in the job log that tells me what the command was that I tried to execute. With complex commands like OPNQRYF, this can be very helpful.

Sometimes, I use another form of these audit trail messages in batch programs. I will usually front-end the message with some specific characters to help me find where I am in the job log.

For example, I might send a message as follows:

SNDPGMMSG MSG('%-% Beginning the update program') +

TOPGMQ(*SAME)

If the job aborts, I can scan the job log for %-% and get a good idea of where the program blew up.

Most of the time, I don't have a lot of trouble debugging CL programs. I think this is a combination of the CL language and the type of coding that is normally done in CL. But sometimes, there is a real doozy to solve, and I appreciate some of the good debug things you can do. You have a lot of choices as to how you debug. Get familiar with one you like, and it will have a good payoff for you.

Jim Sloan, president of Jim Sloan, Inc., is a software vendor and consultant. A retired IBMer, Sloan was a software planner on the S/38 when it began as a piece of paper. He also worked on the planning and early releases of the AS/400. In addition, Sloan wrote the TAA tools that exist in QUSRTOOL and is now the owner of the TAA Productivity Tools product. He has been a speaker at COMMON for many years.

Every copy of OS/400 comes with the QUSRTOOL library, which contains the source code for many useful programmer/operator tools. The QUSRTOOL library must be unpackaged, and each tool within the library must be created. For information about how to unpackage the library and create the tools, see source member TTTINFO in source file QATTINFO in library QUSRTOOL.

Many of the tools in the QUSRTOOL library have been removed in OS/400 releases beyond V3R1 (e.g., V3R2 and V3R6), including a large group of tools known as the TAA Tools. For a complete list of the tools that have been removed, see source member AAAAREADME in source file QATTINFO in library QUSRTOOL.

If you are at a release beyond V3R1, you may not be able to find the tools mentioned in this article in the QUSRTOOL library. The tools, however, can be obtained from TAA Productivity Tools, a licensed product from Jim Sloan, Inc.

For more information about TAA Productivity Tools, contact

Jim Sloan, Inc.

c/o Barsa Consulting Group, Inc.

Tel: 914-251-9494; Fax: 914-253-9413

Figure 1: DSPCLPDO command

Display CL Pgm DO Cmds - TAA (DSPCLPDO)

Member............. Name
CLsourcefile......... QCLSRC Name

Library ........... *LIBL Name,*LIBL,*CURLIB
Output(printoutput) ..... *NO *YES,*NO,*,*PRINT

Figure 2: DSPCLPDO output

Display Spooled File
File .....: TSTDBG
Control.....

Find ......
*...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+....

10/21/97 11:55:23 TAASYS5 DSPCLPDO Command

File-QCLSRC Library-SLOANT Member-TSTDBG
DO Grp Err Seq Nbr Statement

1.00 PGM
2.00 DCL VAR(&VARA) TYPE(*CHAR) LEN(5)
3.00 DCL VAR(&JOBD) TYPE(*CHAR) LEN(10)
4.00 DCL VAR(&OUTPUT) TYPE(*CHAR) LEN(6)
5.00 CHGVAR &VARA 'ABCD'
6.00 CHGVAR &OUTPUT '*PRINT'
7.00 CHGVAR &JOBD 'QBATCH'
8.00 CHKOBJ OBJ(&JOBD) OBJTYPE(*JOBD)
B 1 9.00 MONMSG MSGID(CPF9801) EXEC(DO) /* Not found */
B 2 10.00 IF (&VARA *EQ 'XXX') DO /* IF XXX */

2 11.00 CHGVAR &OUTPUT '*'
E 2 12.00 ENDDO /* If XXX */
E 1 13.00 ENDDO /* Not found */

14.00 CALL PGMX PARM(&VARA)
15.00 DSPJOBD JOBD(&JOBD) OUTPUT(&OUTPUT)
16.00 ENDPGM

F3=Exit F12=Cancel F19=Left F20=Right F24=More keys Print CLP DO Groups - TAA (PRTCLPDO)

Member............. Name
CLP source file . . . . . . . . QCLSRC Name

Library ........... *LIBL Name,*LIBL,*CURLIB
Display spooled file . . . . . . *YES *YES, *NO Display Spooled File
File .....: TSTDBG
Control.....

Find ......
*...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+....

10/21/97 11:57:13 TAASYS5 PRTCLPDO - TAA - Print CLP Do Groups Member-TSTDBG

File-QCLSRC Library-SLOANT DSPSPLF-*YES
Seq ErrNte
1.00 PGM
2.00 DCL VAR(&VARA) TYPE(*CHAR) LEN(5)
3.00 DCL VAR(&JOBD) TYPE(*CHAR) LEN(10)
4.00 DCL VAR(&OUTPUT) TYPE(*CHAR) LEN(6)
5.00 CHGVAR &VARA 'ABCD'
6.00 CHGVAR &OUTPUT '*PRINT'
7.00 CHGVAR &JOBD 'QBATCH'
8.00 CHKOBJ OBJ(&JOBD) OBJTYPE(*JOBD)
9.00 MONMSG MSGID(CPF9801) EXEC(DO) /* Not fo
10.00 * IF (&VARA *EQ 'XXX') DO /* IF XXX */
11.00 * * CHGVAR &OUTPUT '*'
12.00 * ENDDO /* If XXX */
13.00 ENDDO /* Not found */
14.00 CALL PGMX PARM(&VARA)
15.00 DSPJOBD JOBD(&JOBD) OUTPUT(&OUTPUT)
16.00 ENDPGM

F3=Exit F12=Cancel F19=Left F20=Right F24=More keys

Figure 3: PRTCLPDO command

Figure 4: PRTCLPDO output

Figure 5: Logging output

800 - CHKOBJ OBJ(QBATCH) OBJTYPE(*JOBD)

1400 - CALL PGM(PGMX) /* The CALL command contains parameters */
1500 - DSPJOBD JOBD(QBATCH) OUTPUT('*PRINT')

- RETURN /* RETURN due to end of CL program */

Display Trace Data

Statement/
Program Instruction Recursion Level Sequence Number
TSTDBG 500 1 1

Startposition ............:1
Length ................:*DCL
Format ................:*CHAR
Variable ...............:&VARA

Type ................: CHARACTER
Length ...............: 5
*...+....1....+....2....+....3....+....4....+....5

''

Statement/
Program Instruction Recursion Level Sequence Number
TSTDBG 600 1 2
Startposition ............:1
Length ................:*DCL
Format ................:*CHAR
*Variable ...............:&VARA

Type ................: CHARACTER
Length ...............: 5
*...+....1....+....2....+....3....+....4....+....5

'ABCD '

Statement/
Program Instruction Recursion Level Sequence Number
TSTDBG 700 1 3
TSTDBG 800 1 4
TSTDBG 1400 1 5
TSTDBG 1500 1 6
TSTDBG 1600 1 7

Figure 6: Trace output

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$0.00 Raised:
$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: