Compiling CLLE source calling a SubProcedure

Hello experts:

I have a CLLE Source DISTCM of type QCLSRC that is calling a subprocedure SPLFDIST
inside SQLRPGLE source DISTRM.

The SQLRPGLE source DISTRM has NOMAIN specified. I therefore compiled this one
using Option 15 (Create Module).

I then tried to compile DISTCM using the following command:

CRTPGM PGM(MYLIB/DISTCM) MODULE(MYLIB/DISTRM)

I get the following error message when I execute the above command.

"Program DISTCM not created."

Can anyone provide me some tips on compiling DISTCM?

Thank You
Inayat081501Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ShadowProgrammerCommented:
You need to look at the job log and/or the compilation listing to identify the error(s) that stopped the program being created...

Tony
tliottaCommented:
Inayat:

The joblog should give the reason, but I'd guess you could fix the problem by changing your compile command from:

 ==>  CRTPGM PGM(MYLIB/DISTCM) MODULE(MYLIB/DISTRM)

to:

 ==>  CRTPGM PGM(MYLIB/DISTCM) MODULE(MYLIB/DISTCM MYLIB/DISTRM)

This implies that you have first compiled the MYLIB/DISTCM module. This module contains the CALLPRC command that calls the procedure in the second module. Both modules must be bound together to create the program.

Tom

Inayat081501Author Commented:

tliotta:

Thank you very much. I was able to create the PGM for DISTCM following your
suggestion of binding the two modules together. Now how could I step through
DISTCM?

Normally, to run a CL in debug mode, I would do the following steps:
-Key in a 14 across the source, press F4
-Change the parameter Debugging mode to *LIST
-Run STRDBG, set a breakpoint and exit pressing F3
-Call the program from the command line.

But I have not tried stepping through code in the scenario I am currently
working on - I mean to debug a CL program created using CRTPGM. Could you
please point me in the right direction?

Thank you
Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

tliottaCommented:
Inayat:

There are a number of "programming environments" under OS/400. The two that are most commonly known are Original Programming Model (OPM) and Integrated Language Environment (ILE). You are creating programs for ILE.

In OPM, programs are compiled from source. In ILE, programs are not compiled -- instead, modules are compiled and various modules can be bound together to create programs. In ILE, programs don't have any 'source' that can be debugged. But modules do have source and can be debugged. By debugging the modules, you can effectively debug the programs containing those modules.

In order to debug a module, the module must be compiled in a way that supports debugging. You compiled a CL module by using the CRTCLMOD command. CRTCLMOD has a DBGVIEW() parameter where you specify what debug data is going to be included in the module. When I want debugging included, I almost always specify DBGVIEW(*ALL). (That allows multiple kinds of debugging that are useful to me.) You might want to use DBGVIEW(*LIST) when you create the module so that a compiler list of the source is included in the compiled module.

With your DISTCM module now containing useful debug info, you might be able to insert it into your program:

 ==>  updpgm  PGM(MYLIB/DISTCM) MODULE(MYLIB/DISTCM)

If the program wasn't created to allow updating, you'll need to run CRTPGM again in order to get your new module into the program.

Once your module (or both modules) has the right debug data in it, you can use the STRDBG command and select modules to debug.

Tom
Inayat081501Author Commented:
Tom:

Thank you very much for your response. Really appreciate your patiently walking me through
the basics!

OK, here is what I have done so far:

 1. Created DISTCM module using option 15.
 2. Created DISTRM module using option 15.
 3. Created program using the following command:
     CRTPGM PGM(MYLIB/DISTCM) MODULE(MYLIB/DISTCM MYLIB/DISTRM) ENTMOD(MYLIB/DISTCM)

I included the ENTMOD parameter because I got an error at one point complaining that this
is missing.
      
Could you please tell me how should I modify the above commands and re-execute them to
compile the modules in a way that supports debugging?

Once I have issued the new commands to support debugging, I only have to run the
command STRDBG DISTCM, set breakpoints, press F3 to exit and then call the program
from command line,  Are these step correct? OR is the procedure something different?

Awaiting your reply,

Thank you - Inayat
tliottaCommented:
Inayat:

 1. Created DISTCM module using option 15.

When using PDM options, press <F4> rather than <Enter>. This will prompt the command and let you modify parameter values. Once the command is prompted, you can press <F10> to show additional parameters beyond the basic ones. Scroll down to reach DBGVIEW() and type *LIST and then press <Enter>

Alternatively, you could type DBGVIEW(*LIST) on the PDM command line before typing option 15 and pressing <Enter>. That will add what's on the command line to the command string.

Once the program is created from modules that have debug info, type:

 ==>  strdbg MYLIB/DISTCM

and press <Enter>. That should take you into debug where you can set breakpoints and other things. When you're ready for the program to run, press <F12> to get back out to the command line. Debug mode is started and the program has been prepared for it. To run the program:

 ==>  call MYLIB/DISTCM

The program will start and run until it reaches a breakpoint. The debug display will open again.

You are apparently familiar with the older debug, the STRISDB command. Things cannot work the same in ILE. You might feel that you are limited by the newer debug, but there are definite advantages. The biggest advantage by far in the newer debug is how the various GUI debug tools are supported. These are available in CODE/400 and WDSC client, and they can be excellent once you work through how to use them.

But the basic STRDBG is usually all I need anyway. Review the <help> for a lot of info.

Tom

Inayat081501Author Commented:
Tom:

Firstly, I must say that I will increase the points for the excellent and elaborate explanation you are giving me!
 
Okay, I have compiled DISTCM with the following command:

CRTCLMOD DISTCM SRCFILE(MYLIB/QCLSRC) DBGVIEW(*LIST), so far so good.

Now my questions:

1. DISTCM is calling a "Subprocedure" in DISTRM.  And DISTRM is SQLRPGLE type. Now do I have to compile the module DISTRM also using DBGVIEW(*LIST) ? Or I have to do this IF ONLY I am going to step into it using breakpoints? In other words can I chose to specify DBGVIEW(*LIST) for specific modules in an ILE Program?

2. I tried executing the following command for DISTRM including the DBGVIEW(*LIST) parameter:
 
CRTRPGMOD DISTRM SRCFILE(MYLIB/QRPGLESRC) DBGVIEW(*LIST)

but I got this error ==> Compilation stopped. Severity 30 errors found in program.

I did F1 on the message and I found the following details:
                                                                             
 Message . . . . :   Compilation stopped. Severity 30 errors found in program.
 Cause . . . . . :   The RPG compiler found at least one error in the program  
   of severity greater than that specified in the GENLVL option on the        
   CRTRPGMOD or CRTBNDRPG command.                                            
 Recovery  . . . :   Correct the errors in the program. Compile again.

NOTE: But If I simply create the module using option 15 , the module DISTRM gets created successfully. I did not understand this!

3. What if I wanted to set a breakpoint in DISTRM also, and jump between DISTCM and DISTRM in debug mode?

Thank You very much, Tom

- Inayat
     
tliottaCommented:
Inayat:

1) Each module can be debugged separately. Some might be compiled with debug data, others might not. This allows developers to "hide" parts that don't need to be seen. But if you want to debug a given module, it must be compiled with debug data.

2) CRTRPGMOD won't compile DISTRM. It isn't an RPG source member. It's SQLRPGLE. Use the CRTSQLRPGI command instead. You can see the command when you use PDM option 15 if you press <F4> instead of <Enter>. The source has embedded SQL, so it needs to be sent through the SQL preprocessor and SQL will pass it on to the RPG compiler automatically. BUT ...

The SQL preprocessor doesn't handle debug very well. What people often do is run CRTSQLRPGI in order to generate RPG source. The source will be stored in a member in the source file named on the TOSRCFILE() parameter. This member will have the same name as the original member, so take care that you don't point back to the same source file. Usually, OPTION(*NOGEN) will also be specified. That tells the preprocessor not to call the RPG compiler after it builds the source file member.

That new source file member can then be compiled into a true RPG module with CRTRPGMOD and you can specify the debug options you like.

3) You will be able to select from a list of modules when debug starts. Study the function keys to learn how to jump to various features. You can set breakpoints in any of them that are allowed by debug data. You'll jump back and forth however the flow goes and however you set breakpoints.

Tom
Inayat081501Author Commented:
Tom,

Pressing F4 for PDM option 15 for DISTRM, I see that the source file name and
library have the following values:

       To source file . . . . . . . . .   QSQLTEMP1    
         Library  . . . . . . . . . . .     QTEMP
        
Now, I already have a source member DISTRM in MYLIB.

Here are my questions for you:

1. So you suggest me specifying a slightly different name, say DISTRM2 in the
   "To source file" parameter for CRTSQLRPGI command. Right?

2. And after I generate the new source file member DISTRM2, I can compile this one
   into a true RPG module with CRTRPGMOD?

3. So my CRTPGM command will now look as below, correct?

CRTPGM PGM(MYLIB/REPTPGM) MODULE(MYLIB/DISTCM MYLIB/DISTRM2) ENTMOD(MYLIB/DISTCM)

Please confirm the answers to the above questions and I will try out.

Thank You very much

- Inayat
tliottaCommented:
Inayat:

(My apologies; I was unavailable for a couple days.)

The name of the module won't change.

The SQL preprocessor reads your original source member. It modifies the embedded SQL statements to convert them into RPG source statements. The SQL statements in your RPG source are essentially macros that are interpreted by the SQL preprocessor when you run the CRTSQLRPGI command.

The preprocessor generates a new RPG source member. By default, it puts that source member into QSQLTEMP1 in QTEMP and then calls the RPG compiler. The member in QSQLTEMP1 is what gets compiled by RPG, not the member in your source file.

If you run CRTSQLRPGI and tell it OPTION(*NOGEN), the RPG compiler doesn't get called so no *MODULE gets created. The only thing that gets done is that a new source member gets built in QSQLTEMP1.

But QSQLTEMP1 is in QTEMP.

Usually, the CRTSQLRPGI command is submitted to batch. That causes the QTEMP library to go away after the command finishes. If you want to see the RPG source, you have to specify a source file that isn't in QTEMP. Also, if you want to run the CRTRPGMOD command, you need to have the source generated somewhere other than QTEMP.

You don't get to choose the name of the temporary source member. It's going to have the same member name as the original. You can only choose the name of the source file. Since the source member name won't change, you will still create a module named DISTRM.

Tom
Inayat081501Author Commented:
Thank you for your response.

I appreciate your patience. Please bear with me.  I am taking this step by step without rushing through.
Based on the explanation you have given, is the following command okay?

CRTSQLRPGI SRCFILE(QRPGLESRC) SRCMBR(DISTRM) OPTION(*NOGEN) TOSRCFILE(MYLIB/DISTRMNEW)

where DISTRMNEW is the new RPG source generated in libraray MYLIB.

Once I have issued the above command correctly, I will then run CRTRPGMOD on DISTRMNEW.

- Inayat
Inayat081501Author Commented:
Hi Tom:

Please ignore my previous comment. Okay here is what I have done so far. I issued the following three commands. There were no errors:

CRTSQLRPGI OBJ(DISTRMNEW) SRCFILE(MYLIB/QRPGLESRC) SRCMBR(DISTRM) OPTION(*NOGEN) TOSRCFILE(MYLIB/DISTRMNEW)                                  

CRTRPGMOD MYLIB/DISTRMNEW SRCFILE(MYLIB/DISTRMNEW) DBGVIEW(*LIST)   <=== I used DBGVIEW(*LIST) here.

CRTPGM PGM(MYLIB/REPTPGM) MODULE(MYLIB/DISTCM MYLIB/DISTRMNEW) ENTMOD (MYLIB/DISTCM)
                             
But now here is my question. How do I set a breakpoint in DISTRMNEW? I am able to set breakpoints in DISTCM but not in DISTRMNEW.
In one of your previous comments you said <<You will be able to select from a list of modules when debug starts.>>
I couldn't figure this out!!

- Inayat
Inayat081501Author Commented:
Hi Tom,

I have found out how to debug multiple modules in a program. Thank you very much.

However, I would still need your assistance to verify if the above 3 commands look good for you. Then I will close this question.

- Inayat
tliottaCommented:
Inayat:

It looks like there's one problem (maybe just a typo)...

Your CRTRPGMOD command is creating a module named MYLIB/DISTRMNEW. However, you do not specify the SRCMBR() parameter. That causes it to default to "*MODULE" which is DISTRMNEW. I don't see where that source member is ever generated.

The source member that is generated by the CRTSQLRPGI command is named DISTRM and it is placed in a source file named MYLIB/DISTRMNEW. Your command apparently should be:

CRTRPGMOD MYLIB/DISTRMNEW SRCFILE(MYLIB/DISTRMNEW) srcmbr( distrm )  DBGVIEW(*LIST)

Of course, you could also rename the member in MYLIB/DISTRMNEW.

Tom
Inayat081501Author Commented:
Hi Tom,

Thank you for your response.

I was able to run that command CRTRPGMOD with no error.
In fact I got a success message after I issued it.  Next, I was able to bind the CLLE and DISTRMNEW into a program and then was able to step into both the modules. I was also able to read the variable values in DISTCM that were returned by DISTRMNEW. Am I missing something here?

I am going to try out the test again adding the SRCMBR() parameter as you suggest and will let you know.

After I close this question, I have phase 2 of my project for which I will have to ask a new question to this forum. This has gotten quite lengthy. But I learned a lot of stuff from you :)

- Inayat

tliottaCommented:
Inayat:

As long as a source member exists that is named DISTRMNEW and it has no syntax or other errors, the CRTRPGMOD command would complete without error. I just don't see where the source member came from in your sequence of commands. Make sure you are compiling the expected source member.

The source member dates in source file MYLIB/DISTRMNEW can help determine this.

Tom
Inayat081501Author Commented:
Tom,

I get the following error when I tried the command after making the change:

"Unable to open member DISTRM of file DISTRMNEW in library MYLIB. "

and here is the command:

CRTRPGMOD MYLIB/DISTRMNEW SRCFILE(MYLIB/DISTRMNEW) SRCMBR(DISTRM) DBGVIEW(*LIST)

Perhaps the command I issued right before this one (which is in a previous comment above) also needs some adjustment!

- Inayat                                                        

tliottaCommented:
Inayat:

The previous command:

   CRTSQLRPGI OBJ(DISTRMNEW) SRCFILE(MYLIB/QRPGLESRC) SRCMBR(DISTRM) OPTION(*NOGEN) TOSRCFILE(MYLIB/DISTRMNEW)

This has SRCMBR(DISTRM) for original member name. This member name should be the name of the new member that gets created in TOSRCFILE(MYLIB/DISTRMNEW). But you are saying that there is no DISTRM member in MYLIB/DISTRMNEW. Instead, you are getting a member named DISTRMNEW.

If that is all true, then something else is happening that is hidden. There is no parameter that allows you to specify a new member name on the standard IBM CRTSQLRPGI command at least in version 5 of OS/400. (I checked V5R1 through V5R4.) The <help> text for the TOSRCFILE() parameter states that the member name should be the same as the SRCMBR() name.

I would suggest deleting the MYLIB/DISTRMNEW file and running the same CRTSQLRPGI command again. The only result should be that the source file is recreated and a new member should be added. Then display the list of members to see what member was created and make sure the member dates are correct.

Look over the joblog to locate _any_ unusual error messages.

You might have a custom version of CRTSQLRPGI or there might be a missing DB2 PTF.

Tom

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Inayat081501Author Commented:
Tom:

Thank you for patiently getting back to me.

I had the SRCFILE and SRCMBR messed up in my mind. I actually meant to have DISTRMNEW as a member and not as a file. Your statement <<There is no parameter that allows you to specify a new member ... ... ... >> cleared up the confusion. It is better to have a source file just for SQLRPGLE conversion to RPGLE? Say, I call this SQLRPG2RPG.

I ran the following the 2 commands successfully:

CRTSQLRPGI OBJ(DISTRMNEW) SRCFILE(MYLIB/QRPGLESRC) SRCMBR(DISTRM) OPTION(*NOGEN) TOSRCFILE(MYLIB/SQLRPG2RPG)                          

CRTRPGMOD MYLIB/DISTRMNEW SRCFILE(MYLIB/SQLRPG2RPG) SRCMBR(DISTRMNEW) DBGVIEW(*LIST)

Are the above commands 100 percent correct?

I have doubled the points. I should be coming back with a new question. Thank you very much :)

- Inayat
tliottaCommented:
Inayat:

CRTSQLRPGI ... SRCMBR(DISTRM)
CRTRPGMOD ... SRCMBR(DISTRMNEW)

Ahhh... I learned something today. I can't believe I never tried it before.

The IBM <help> text for CRTSQLRPGI is misleading. You used the command:

  ==>  CRTSQLRPGI OBJ(DISTRMNEW)

The name that you supplied for the OBJ() parameter is different from the source member name. The command creates a member the same as the OBJ() but the text says it will be the same as SRCMBR(). IBM's text is wrong and I never noticed it because I always had the same names for both parameters.

We've both spent more time than necessary because IBM made a mistake and I didn't catch it until today.

Yes, your commands are correct. But that brings up a possible problem.

Someday IBM might issue a PTF that "fixes" how the command works. If they do, your sequence of commands might fail. I suggest that you always use the same name for the OBJ() and SRCMBR() parameters so your commands will always work.

Tom
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
IBM System i

From novice to tech pro — start learning today.