OPNQRYF and Named Activation Groups
I ran across an interesting but obvious gotcha while recently rewriting an application. I was using ILE and compiling the objects to use a named activation group. The only program I didnt change was a CL program that ran Open Query File (OPNQRYF) to select records for a report. When I ran the report program, I was surprised to find that the report had printed all the records from the file and ignored the open data path that the OPNQRYF had created. Then, it dawned on me that I was using a named activation group for the RPGLE program, and the CLP was running in the default activation group. My solution to this problem was to change the CLP to a CLLE and compile it to run in the same activation group as the RPGLE program.
This led me to do some testing. Here are the ways I found that let an RPG IV program compiled to use a named activation group use the ODP built by OPNQRYF:
Compile the CLLE program to use the same activation group the RPGLE program uses.
Compile the CLLE and RPGLE sources into modules, and bind the modules into a single program.
Specify OPNSCOPE(*JOB) on the OPNQRYF or Override Database File (OVRDBF) command in a CLP or CLLE program.
The last is probably not a good option, in general. One of the primary purposes of ILE is to isolate different uses of the same resources within a job. Using job-level opens and overrides defeats that purpose.
Bradley V. Stone This email address is being protected from spambots. You need JavaScript enabled to view it. http://prairie.lakes.com/~bvstone
Log OCL Procedure Usage
Keeping a clean system and preparing for major projects (such as the Year 2000 challenge) is difficult if you have no idea whats good and whats garbage. OS/400 can
help you with that chore. The system keeps up with the last time an object is used and how many times it has been used.
However, it doesnt keep up with OCL procedure usage. To fill this void, we wrote the LOGOCLPROC utility. It consists of four objectsphysical file PROCLOG, command LOGOCLPROC, a CL program OCL001CL, and RPG III program OCL001RGshown in Figures 1 through 4.
Include the LOGOCLPROC command at the beginning of any OCL or REXX procedure you want to log. You can see an example of this in Figure 5.
We use generic reporting tools, like Query/400, to view the file. Steve Barnard
Garan, Inc.
Starkville, Mississippi
Help with RPG IV Debugging
IBM recently fixed two RPG IV debugger problems that may have been bugging you. The first problem is that run-time error messages indicate compiler listing line numbers, rather than the source member sequence numbers. This required programmers to recompile a program to find out what line of code was failing. Now, you can specify OPTION(*SRCSTMT) on the control (H) spec if you want the object to contain source sequence numbers.
The second problem is that input and output specs generate debugging breakpoints. IBM added another permissible OPTION keyword*NODEBUGIOin this same fix. OPTION(*NODEBUGIO) prevents the generation of breakpoints on input and output specifications.
If you want to specify both values, separate them with a colon.
OPTION(*SRCSTMT : *NODEBUGIO)
There are also opposite values of *NOSRCSTMT and *DEBUGIO, but you probably wont need them, since they are the default values.
The APAR number is SA70333. The PTF numbers containing the fixes are listed in the table in Figure 6.
Doug Pence and Ron Hawkins
Jon Paris IBM Toronto
Is Your Laptop Client Access Configuration Affecting Your Battery Life?
Earlier this year, IBM issued a fix for a problem involving battery life on laptops running Client Access/400 for Windows 95/NT. For earlier versions of the software, users experienced battery life problems after loading up Client Access. This occurred even if the user wasnt running Client Access.
The problem occurs becauseafter Client Access installationWindows 95/NT loads up the Client Access/400 Task Bar Icon Extension application, CWBUITSK.EXE, into memory. CWBUITSK displays the small AS/400 icon on the Windows 95 toolbar when you are attached to an AS/400. In its earlier versions, CWBUITSK affected battery life on laptops.
This problem was fixed in Client Access/400 in the following service packs:
For V3R1M2: Service pack SF46059 and aboveissued February 1998
For V3R1M3: Service pack SF46891 and aboveissued April 1998 In these service packs, CWBUITSK has been changed to improve laptop battery life. IBM does not state that it solves all battery life issues, but they believe this change may help. After installing the fix, CWBUITSK will still be loaded at startup, but it is idled and will only process information when a Client Access connection is started or disconnected.
For V3R1M0 and V3R1M1 clients, this fix is not available, and IBM has no further plans to issue service packs for these clients. To fix, I recommend you upgrade your Client Access laptop configuration to V3R1M2 or V3R1M3 with the appropriate service packs.
Information on this problem can be found in APAR SA70701 or within the READMESP.TXT files that come with the most recent V3R1M2 and V3R1M3 service packs.
Joe Hertvik Senior Technical Editor Midrange Computing
Calling Native Programs from a S/36 Program, Continued
Last month, I published a program to pack zoned decimal data so S/36 programs could pass packed decimal values to native programs. This month, I publish a companion program, NBR012RG, which converts packed decimal values to zoned decimal (see Figure 7).
An RPG II program must pass character variables instead of packed variables to native programs. Upon return from the native program, the character variables contain packed data. To unpack the data, the RPG II program calls NBR012RG, passing it the following parameters:
A character variable containing a packed decimal value
A zoned decimal variable to contain the unpacked data
The length (number of digits) in the zoned number
A 1 to deactivate NBR011RG, or a 0 to leave it active NBR012RG will return a zoned value in the second parameter. Ted Holt
Senior Technical Editor
Midrange Computing
Resolve Java Class Attribute Ambiguity
The concept of scope is important in Java. Midrange programmers are typically familiar only with global scope, which means that variables defined anywhere in a program are accessible throughout the program. RPG IV programs have local as well as global
scope. Variables defined within an RPG IV subprocedure have local scope (theyre accessible only within that subprocedure), whereas variables defined in the mainline code are still globally accessible.
With Java, a class has attributes that have global scopethat is, the attributes (essentially variables) are accessible to all functions of that class. But a variable defined within a function of that class is accessible only within that function. This goes the same for the function parameters.
Class attributes are usually declared private so that nothing outside the class can modify them. The functions that modify class attributes are usually named setXXX, where XXX is the attribute. The obvious name for the parameter to a set function would be the attribute name.
The Order class in Figure 8 has an orderDate attribute and a setOrderDate function to modify the orderDate attribute. The parameter to setOrderDate is also called orderDate, the same name as the class attribute. Within the setOrderDate function, any references to orderDate would refer to the parameter (local), not to the class attribute (global).
The Java keyword this can be used to resolve the ambiguity between the orderDate parameter and the orderDate class attribute. The Java reserved word this refers to the object itself. The class example in Figure 8 sets the classs orderDate attribute to the passed parameter of the same name.
Other publications suggest using a naming convention to resolve ambiguity of passed parameter variable names. One suggestion is to prefix an a to the beginning of parameter names. I find the prefix makes the code harder to read. I think use of the this qualifier is more clear.
Don Denoncourt Senior Technical Editor Midrange Computing
Is This File a Source File? (Revisited)
In the January 1998 issue of MC, I published a utility command named ISSRCF (see TechTalk: Is This File a Source File?). The command is designed to find out if a given file is a source file, and I wrote the command processing program (CPP) in CL. After it was published, I received a short email from Kurt Wagner (in the United Kingdom), which went as follows:
I just want to add that the OS/400 system file QADBXREF contains a record for each file in the system. There is also a field named DBXTYP that contains an S if the file is a source file. [...] Of course, your utility is working fine for releases prior to V3R1, but I prefer this solution.
Kurt is absolutely right. My ISSRCF command goes through unnecessary gyrations to do what a simple file interrogation can do. If you would rather use the QADBXREF method, change the ISSRCF command so it uses, as a CPP, RPG IV program SRC015RG (see Figure 9). To perform the change, run the following:
CHGCMD +
CMD(xxx/ISSRCF) +
PGM(xxx/SRC015RG)
I wont bore you with describing the workings of SRC015RG, because theyre rather obvious. Just the same, though, Id like to raise a couple of interesting points about QADBXREF:
It contains several variable-length fields. One of them can reach lengths greater than 9,999 bytes. This problem made it necessary to compile SRC015RG with CVTOPT(*VARCHAR).
Some fields are null-capable and, in fact, contain nulls. This feature required ALWNULL(*YES) in the compilation of the program.
As of V4R2, RPG III cannot deal with fields longer than 9,999 bytes. CL cant, either. And no version of COBOL can cope with null fields. Im mentioning all this to explain why I found it necessary to code SRC015RG in RPG IV. If you dont have an RPG IV compiler, you can still use ISSRCF with its original CL CPP. It may not be an elegant solution, but it still works.
Ernie Malaga Senior Technical Editor Midrange Computing
Easy Random Number Generator
I know this type of thing has been written and published in every language known to man (and I know theres an API, too), but CL program NBR010CL (Figure 10) provides an easy way to get a random number in any range from 0 to 32,767.
NBR010CL calls on REXX procedure NBR010RX (Figure 11) to generate a random number in the desired range. REXX returns the random number as a completion code. The STRREXPRC command generates a CPF7CFF on any nonzero completion code, and that completion code can be extracted from the message, beginning in position
Removing the Client Access/400 Windows 95/NT Check Service Pack Level Program
Q: Since I installed the Client Access for Windows 95/NT client on my PC, a Check Version program runs every time I boot up. How do I keep it from running?
A: The Client Access/400 Windows 95/NT client automatically installs a shortcut in your startup folder that points to the Client Access Check Service Pack Level program. This program checks the Service Pack Level of your Client Access installation against the managing system (usually your main AS/400) to see if they are the same. If they match, nothing happens. If they dont match, you will see a prompt that allows you to install the newest Service Pack Level from the managing system to your Windows 95/NT client. This is IBMs attempt to allow your users to automatically update their Client Access/400 PC configurations when an upgrade is installed.
However, many people dislike the additional time it takes to perform the service pack check. In addition, since many companies dont install service packs that often and they like to control when a service pack is loaded on a users PC (for compatibility and debugging purposes), a lot of companies like to remove this program from their users Windows 95/NT startup folders.
31.
Tom Conover Warner/Chappell Music, Inc. Los Angeles, CA
If you want to remove the service program from your Windows startup folder, heres how to do it:
1. Click on the Win95 Start button.
2. Click Settings.
3. Click Taskbar.
4. Click the Start Menu Programs
5. Click Remove.
6. Scroll down until you see StartUp on the Remove Shortcuts/Folders panel.
7. Double-click StartUp.
8. Youll see the Check Version Program icon.
9. Click this once to highlight it, then click the Remove button.
10. Answer Yes to the message Are You Sure You Want To Send This Icon To The Recycle Bin?
If you want, you can empty your recycle bin to permanently remove the shortcut from your system. The check version executable will still be on your system. Emptying the recycle bin will just permanently remove the shortcut that was in Startup.
Shannon ODonnell This email address is being protected from spambots. You need JavaScript enabled to view it.
Joe Hertvik Senior Technical Editor Midrange Computing
PSDS Affects ILE RPG Program Initialization
ILE RPG programs with either no Program Status Data Structure (PSDS) or a very short PSDS go through the initialization (*INIT) part of the cycle very quickly, compared to OPM RPG. Some of the fields in the PSDSfor example, the program, module, library, job name, and numberare expensive to fill in. If the PSDS isnt long enough to contain these fields, ILE RPG doesnt bother to fill them in during initialization, but OPM RPG does.
Barbara Morris IBM Toronto Lab RPG Compiler Development
Editors note: Barbara mentioned this in passing while discussing another topic in MCs Web Forums. The moral of the story seems to be, dont code any more of the PSDS than you have to in RPG IV.
*===============================================================
* To compile:
*
* CRTPF FILE(XXX/PROCLOG) SRCFILE(XXX/QDDSSRC) +
* TEXT(Log OCL procedure usage)
*
*===============================================================
A R RECCNT
A MBRNME 10A COLHDG( Procedure name)
A MBRLIB 10A COLHDG( Library name)
A ORGDAT 8A COLHDG(Date first logged)
A MBRDAT 8A COLHDG(Date last used)
A PRCACC 7S 0 COLHDG( Times accessed)
A USER 10A COLHDG( User)
A K MBRNME
A K MBRLIB /*==================================================================*/
/* To compile: */
/* */
/* CRTCMD CMD(XXX/LOGOCLPROC) PGM(XXX/OCL001CL) + */
/* SRCFILE(XXX/QCMDSRC) TEXT(Log OCL + */
/* procedure usage) */
/* */
/*==================================================================*/
CMD PROMPT(Log OCL Procedure Usage)
PARM KWD(PROC) TYPE(*CHAR) LEN(10) MIN(1) +
PROMPT(Procedure)
PARM KWD(LIB) TYPE(*CHAR) LEN(10) MIN(1) +
PROMPT(Library) /*==================================================================*/
/* To compile: */
/* */
/* CRTCLPGM PGM(XXX/OCL001CL) SRCFILE(XXX/QCLSRC) + */
/* TEXT(Log OCL procedure usage) */
/* */
/*==================================================================*/
PGM PARM(&PROC &LIB)
DCL VAR(&PROC) TYPE(*CHAR) LEN(10)
DCL VAR(&LIB) TYPE(*CHAR) LEN(10)
OVRDBF FILE(PROCLOG) TOFILE(MAGWORK/PROCLOG)
CALL PGM(OCL001RG) PARM(&PROC &LIB)
DLTOVR FILE(PROCLOG)
ENDPGM
*===============================================================
* To compile:
*
* CRTRPGPGM PGM(XXX/OCL001RG) SRCFILE(XXX/QRPGSRC) +
* TEXT(Log OCL procedure usage)
*
*===============================================================
FPROCLOG UF E K DISK A
I SDS
I 254 263 S#USER
I 276 279 S#MD
I 280 281 S#Y
C *ENTRY PLIST
C PARM MBRNME
C PARM MBRLIB
C*
C KEY1 KLIST
C KFLD MBRNME
C KFLD MBRLIB
C*
C KEY1 CHAINRECCNT 99
C*
C MOVE S#USER USER
C S#Y IFGE 40
Figure 1: The procedure logging file, PROCLOG
Figure 2: The LOGOCLPROC command
Figure 3: LOGOCLPROCs command processing program, OCL001CL
C MOVEL19 YEAR 4
C ELSE
C MOVEL20 YEAR
C ENDIF
C MOVE S#Y YEAR
C MOVELYEAR MBRDAT
C MOVE S#MD MBRDAT
C*
C *IN99 IFEQ *ON
C Z-ADD1 PRCACC
C MOVE MBRDAT ORGDAT
C WRITERECCNT
C ELSE
C ADD 1 PRCACC
C UPDATRECCNT
C ENDIF
C*
C MOVE *ON *INLR
C RETRN LOGOCLPROC PROC(xxx) LIB(?CLIB?)
Figure 4: RPG program OCL001RG logs the procedure data to disk
Figure 5: Include a line like this one at the beginning of procedures to be logged
For Current Releases PTF
V3R2M0 SF46001 V3R6M0 SF45749 V3R7M0 SF46327 V4R2M0 SF45191
For Prior Releases
V3R7M0 SF47056 V4R2M0 SF46944 V4R2M0 SF47055
Figure 6: These PTFs enable new compiler options for better debugging
*===============================================================
* To compile:
*
* CRTRPGPGM PGM(XXX/NBR012RG) SRCFILE(XXX/QRPGSRC)
*
*===============================================================
* Convert a packed decimal number to zoned decimal.
* This program is meant to be called by S/36 RPG II programs,
* but must be compiled as an RPG III program.
*
* Parameter list
* Name Length Description
* PACKED * defined as character in RPG II caller
* must be defined as the length of ZONED
* when packed
* ZONED * any zoned decimal value
* ZONELN 2,0 length of ZONED as a 2-digit zoned number
* SETLR 1 1 sets on LR indicator, unloading this
* program from memory
*===============================================================
IZONED DS
I 1 10ZONE01
I 1 20ZONE02
I 1 30ZONE03
I 1 40ZONE04
I 1 50ZONE05
I 1 60ZONE06
I 1 70ZONE07
I 1 80ZONE08
I 1 90ZONE09
I 1 100ZONE10
I 1 110ZONE11
I 1 120ZONE12
I 1 130ZONE13
I 1 140ZONE14
I 1 150ZONE15
I 1 160ZONE16
I 1 170ZONE17
I 1 180ZONE18
I 1 190ZONE19
I 1 200ZONE20
I 1 210ZONE21
I 1 220ZONE22
I 1 230ZONE23
I 1 240ZONE24
I 1 250ZONE25
I 1 260ZONE26
I 1 270ZONE27
I 1 280ZONE28
I 1 290ZONE29
I 1 300ZONE30
IPACKED DS
I P 1 10PACK01
I P 1 20PACK03
I P 1 30PACK05
I P 1 40PACK07
I P 1 50PACK09
I P 1 60PACK11
I P 1 70PACK13
I P 1 80PACK15
I P 1 90PACK17
I P 1 100PACK19
I P 1 110PACK21
I P 1 120PACK23
I P 1 130PACK25
I P 1 140PACK27
I P 1 150PACK29
I P 1 160PACK31
IZONELN DS
I 1 20ZL
C *ENTRY PLIST
C PARM PACKED
C PARM ZONED
C PARM ZONELN
C PARM SETLR 1
C*
C SELEC
C ZL WHEQ 1
C Z-ADDPACK01 ZONE01
C ZL WHEQ 2
C Z-ADDPACK03 ZONE02
C ZL WHEQ 3
C Z-ADDPACK03 ZONE03
C ZL WHEQ 4
C Z-ADDPACK05 ZONE04
C ZL WHEQ 5
C Z-ADDPACK05 ZONE05
C ZL WHEQ 6
C Z-ADDPACK07 ZONE06
C ZL WHEQ 7
C Z-ADDPACK07 ZONE07
C ZL WHEQ 8
C Z-ADDPACK09 ZONE08
C ZL WHEQ 9
C Z-ADDPACK09 ZONE09
C ZL WHEQ 10
C Z-ADDPACK11 ZONE10
C ZL WHEQ 11
C Z-ADDPACK11 ZONE11
C ZL WHEQ 12
C Z-ADDPACK13 ZONE12
C ZL WHEQ 13
C Z-ADDPACK13 ZONE13
C ZL WHEQ 14
C Z-ADDPACK15 ZONE14
C ZL WHEQ 15
C Z-ADDPACK15 ZONE15
C ZL WHEQ 16
C Z-ADDPACK17 ZONE16
C ZL WHEQ 17
C Z-ADDPACK17 ZONE17
C ZL WHEQ 18
C Z-ADDPACK19 ZONE18
C ZL WHEQ 19
C Z-ADDPACK19 ZONE19
C ZL WHEQ 20
C Z-ADDPACK21 ZONE20
C ZL WHEQ 21
C Z-ADDPACK21 ZONE21
C ZL WHEQ 22
C Z-ADDPACK23 ZONE22
C ZL WHEQ 23
C Z-ADDPACK23 ZONE23
C ZL WHEQ 24
C Z-ADDPACK25 ZONE24
C ZL WHEQ 25
C Z-ADDPACK25 ZONE25
C ZL WHEQ 26
C Z-ADDPACK27 ZONE26
C ZL WHEQ 27
C Z-ADDPACK27 ZONE27
C ZL WHEQ 28
C Z-ADDPACK29 ZONE28
C ZL WHEQ 29
C Z-ADDPACK29 ZONE29
C ZL WHEQ 30
C Z-ADDPACK31 ZONE30
C ENDSL
C*
C SETLR IFEQ 1
C SETON LR
C ENDIF
C*
C RETRN class Order {
private int orderNumber;
private int orderDate;
void setOrderDate(int orderDate)
{
this.orderDate = orderDate;
}
*=================================================================
* To compile:
*
* CRTBNDRPG PGM(XXX/SRC015RG) SRCFILE(XXX/QRPGLESRC) +
* TEXT(CPP for ISSRCF command) +
* DFTACTGRP(*NO) ACTGRP(*CALLER) +
* CVTOPT(*VARCHAR) ALWNULL(*YES)
*
*=================================================================
Fqadbxref IF E K DISK
Figure 7: This program converts packed data to zoned decimal format
Figure 8: Using the Java reserved word this
******************************************************************
D answer S 1A
D q_file DS
D file 10A
D filelib 10A
******************************************************************
C *ENTRY PLIST
C PARM q_file
C PARM answer
C key KLIST
C KFLD filelib
C KFLD file
C key CHAIN qadbxref 01
C IF *IN01
C EVAL answer = E
C ELSE
C SELECT
C WHEN dbxtyp = S
C EVAL answer = Y
C WHEN dbxtyp = D
C EVAL answer = N
C OTHER
C EVAL answer = U
C ENDSL
C ENDIF
C EVAL *INLR = *ON /*==================================================================*/
/* To compile: */
/* */
/* CRTCLPGM PGM(XXX/NBR010CL) SRCFILE(XXX/QCLSRC) */
/* */
/*==================================================================*/
PGM PARM(&MINNBR &MAXNBR &RANDNBR)
DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(37)
DCL VAR(&MIN) TYPE(*CHAR) LEN(5)
DCL VAR(&MAX) TYPE(*CHAR) LEN(5)
DCL VAR(&MINNBR) TYPE(*DEC) LEN(5 0)
DCL VAR(&MAXNBR) TYPE(*DEC) LEN(5 0)
DCL VAR(&RANDNBR) TYPE(*DEC) LEN(5 0)
DCL VAR(&MIN_MAX) TYPE(*CHAR) LEN(11)
IF COND(&MINNBR *LT 0 *OR &MINNBR *GT 32767) +
THEN(DO)
GOTO CMDLBL(MINERR)
ENDDO
IF COND(&MAXNBR *LT 0 *OR &MAXNBR *GT 32767) +
THEN(DO)
GOTO CMDLBL(MAXERR)
ENDDO
IF COND(&MINNBR *GT &MAXNBR) THEN(DO)
GOTO CMDLBL(FORMATERR)
ENDDO
CHGVAR VAR(&MIN) VALUE(&MINNBR)
CHGVAR VAR(&MAX) VALUE(&MAXNBR)
CHGVAR VAR(&MIN_MAX) VALUE(&MIN *BCAT &MAX)
CHGVAR VAR(%SST(&MSGDTA 31 5)) VALUE(0)
STRREXPRC SRCMBR(NBR010RX) PARM(&MIN_MAX)
MONMSG MSGID(CPF7CFF) EXEC(DO)
RCVMSG MSGDTA(&MSGDTA)
ENDDO
CHGVAR VAR(&RANDNBR) VALUE(%SST(&MSGDTA 31 5))
RETURN
Figure 9: RPG IV program SRC015RG
MINERR:
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(Minimum +
value has to be a numeric literal between +
0 and 32767) MSGTYPE(*ESCAPE)
MAXERR:
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(Maximum +
value has to be a numeric literal between +
0 and 32767) MSGTYPE(*ESCAPE)
FORMATERR:
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(Minimum +
value cannot be greater than maximum +
value) MSGTYPE(*ESCAPE)
ENDPGM
Figure 10: CL program NBR01CL gives you a random number between 0 and 32,767
parse arg min max
EXIT random(min,max)
LATEST COMMENTS
MC Press Online