02
Sat, Nov
2 New Articles

Yikes! It's CPF4131!

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

Learn the ins and outs of level-checking.

 

In IBM i, high-level language (HLL) programs are dependent on receiving, at run time, an externally described file (a database file, or a device file, such as a display file, or a printer file) whose format agrees with what was copied into the program at compilation time. For this reason, the system provides a level-checking function that ensures that the format is the same. Level-checking occurs on a record-format basis when the file is opened unless you specify LVLCHK(*NO) when you issue a file override command or create a file. If the level-check values do not match, the program is stopped by a level-check error, aka the CPF4131 error message.

 

CPF4131 might be one of the most frequently encountered error messages for a novice RPG programmer. Level-check errors occurring in a production environment may suggest poor change management. However, as an experienced IBM i programmer, you should know the answers to the following questions related to the level-checking function: 

  • What is actually being checked when level-checking is performed?
  • The system supplies the level-checking function for database files and device files. How does a program indicate to the system whether level-checking is to be performed when it opens a file?
  • How is compatibility achieved across multiple versions of a database file by using LVLCHK(*NO)?

What Is Actually Being Checked When Level-Checking Is Performed?

The system assigns a unique level identifier for each record format when the file it is associated with is created. The system uses the information in the record format description to determine the level identifier. This information includes the total length of the record format, the record format name, the number and order of fields defined, the data type, the size of the fields, the field names, the number of decimal positions in the field, and whether the field allows the null value. Changes to this information in a record format cause the level identifier to change. In other words, the system determines the record format-level identifier (RCDFMT-ID) according to the record format itself; information not related to the record format is not taken into consideration—for example, key-field specifications, select/omit attributes, or join specifications. And what is actually being checked at runtime is the record format-level identifier, which identifies a record format uniquely.

 

At the MI level, record formats are represented by a specific type of permanent space object in the system domain: the record format (*FMT) object (with MI object type/subtype code hex 1951). *FMT objects are one of all the MI object types that comprise a file object at the OS level. System pointers to the *FMT objects referenced by a file object can be found in the associated space of the hex 1901 *FILE object of a file object. At V5R4, a system pointer (SYSPTR) addressing the *FMT object associated with a physical file can be found at offset hex 0380 into the hex 1901 *FILE object's associated space.

 

If you're interested in what's being stored in a *FMT object, you can select a file object, dump the content of it via a dump command (DMPOBJ or DMPSYSOBJ) or the System Service Tools (SST), find the virtual address of the *FMT object(s) referenced by the file in the dump result, and then dump the content of the *FMT object(s) via SST by the virtual address of the *FMT object. For example, following these steps, you can get the content of the *FMT object storing the record format description of a physical file (PF) called A1:

 

First, dump the content of PF A1 via the DMPOBJ command: DMPOBJ A1 *FILE. Here's the DDS source code of PF A1:

 

     A         R REC

     A           FLD1           8A         TEXT('TEXI')

     A                                     COLHDG('HEADACHE')

     A          FLD2         17A         TEXT('DRIVER')

 

Now, find the system pointer to the *FMT object referenced by A1 at offset hex 0380 in A1's associated space. In this example, the value of the system pointer is hex 0000000000000000 2EA46D8979001900. Copy the 5-byte segment identifier (SID), which is the first 5 bytes of the lower-order 8 bytes of the system pointer, to perform the next step. In a system pointer, this 5-byte SID is the base segment ID of the object addressed by the system pointer. The 8-byte Single-Level Store (SLS) virtual address of a *FMT object is the base segment ID followed by 3-byte offset value hex 000000.

 

000380   00000000 00000000 2EA46D89 79001900   00000000 00000000 00000000 00000000

0003A0   00000000 D9C5C340 40404040 4040D500   00000000 00000000 00000000 00000000

 

Start a SST session via the STRSST command and choose the following menu items:

 

1. Start a service tool

4. Display/Alter/Dump

2. Dump to printer

1. Machine Interface (MI) object

25. Space (19)

2. Find by object address

 

At the "Find By Object Address" screen, enter the SLS virtual address of the *FMT object as shown below and press Enter to locate the *FMT object.

 

                             Find By Object Address

 

Output device . . . . . . :   Printer

 

Type choice, press Enter.

 

   Object address . . . 2EA46D8979 000000   0000000000 000000-FFFFFFFFFF FFFFFF

 

At the "Select Format" screen, chose menu item 2, Base structure to dump the content of the *FMT object. The dump result might look like this:

 

SPACE OBJECT                 SUBTYPE: 51     NAME: REC                                 ADDRESS: 2EA46D8979 000000

SEGMENT HEADER   (YYSGHDR)

     TYPE 0001   SIZE 0010   NEWFLAGS 03   FLAGS C0   OBJECT 2EA46D8979 000000   SPACE 2EA46D8979 001000

EPA HEADER   (YYEPAHDR)

     ATT1     81                   JOPT     00                   TYPE     19                   STYP     51

     NAME     REC                                                 SPATT     E0                   SPIN     00

     SPSZ     00001000             PBAU     FF1C                 DVER     0301                 TIME     12/06/14 11:37:30

     UPSG     24A6259CC9 000000   AGSG     0000000000 000000   CTSG     0000000000 000000   OSG       2EA46D8979 000000

     RCV2     0002                 ASP       0000                 PERF     00000000             MDTS     12/06/14 11:37:30

     JPSG     0000000000 000000   CBSG     0000000000 000000   JID       00000000000000000000

     OWAU     FF1C                 IPL NUM   0000002B             AL1S     0000000000 000000   GRAU     0000

     GRP       000000000000         MAXS     0000                 INFO     0000000000000000     ATT2     E0

     COLB     00                   LEVL     00000404             USCNT     0000                 USDAY     0000

     DJID     00                   DENP     0000000000 000000   POSG     0000000000 000000   LTEP     0000000000 000000

     AUR       002B                 JGEN     0000                 TEMP     000000000000000000000000

   2EA46D8979 000000 DISK UNIT 0006 DISK PAGE 003D45AC

   2EA46D8979 000000   0001001003C00090 2EA46D8979000000   0001000000000000 2EA46D8979001000 *.....{. .u_i`............u_i`...*

   2EA46D8979 000020   81001951D9C5C340 4040404040404040   4040404040404040 4040404040404040 *a.. REC                         *

   2EA46D8979 000040   4040E00000001000 00000010FF1C0301   9656BE4BA8D84000 24A6259CC9000000 * $.............o .yQ ..w. I...*

   2EA46D8979 000060   0000000000000000 0000000000000000   2EA46D8979000000 0002000000000000 *.................u_i`...........*

   2EA46D8979 000080   9656BE4BA8E78002 0000000000000000  0000000000000000 0000000000000000 *o .yX .........................*

   2EA46D8979 0000A0   0000FF1C0000002B 0000000000000000   0000000000000000 0000000000000000 *................................*

   2EA46D8979 0000C0   0000000000000000 E000000004040000   0000000000000000 0000000000000000 *........$.......................*

   2EA46D8979 0000E0   0000000000000000 0000000000000000   002B000000000000 0000000000000000 *................................*

ASSOCIATED SPACE

   2EA46D8979 001000 DISK UNIT 0006 DISK PAGE 003D45AD

   2EA46D8979 001000 T 0000000000000000 369E8452BF001900   0000000000000000 0000000000034403 *......... d ................. .*

   2EA46D8979 001020   A700000000000000 0002108001840000   02900019D9C5C340 404040404040F2F4 *x.......... .d... ..REC       24*

   2EA46D8979 001040   F0F4F2C2C5C6F0C3 F3F5F14040404040   4040404040404040 4040404040404040 *042BEF0C351                     *

   2EA46D8979 001060   4040404040404040 4040404040404040   4040404040404040 4040404040000200 *                             ...*

   2EA46D8979 001080   CAC6D3C4F1404040 404040C6D3C4F140   4040404040000403 0000000000080000 * FLD1     FLD1     ...........*

   2EA46D8979 0010A0   0000000000000000 0000000000000000   0000000000000032 0090000000000000 *......................... ......*

   2EA46D8979 0010C0   0000000800C20000 0000000000000344   03A703A700000000 0000000000000000 *.....B......... .x.x............*

   2EA46D8979 0010E0   0000000000000000 0000000000000000   0000000000000000 0000000000000000 *................................*

   2EA46D8979 001100   0000000000000000 00000000000000E3   C5E7C94040404040 4040404040404040 *...............TEXI             *

   2EA46D8979 001120   4040404040404040 4040404040404040   4040404040404040 4040404040404040 *                               *

   2EA46D8979 001140   40C8C5C1C4C1C3C8 C500C6C6D3C4F240   4040404040C6D3C4 F240404040404000 * HEADACHE.FFLD2     FLD2     .*

   2EA46D8979 001160    0403000800080011 0000000000000000   0000000000000000 0000000000000000 *................................*

   2EA46D8979 001180   0032009000000000 00000000000400C2   0000000000000000 034403A703A70000 *... ...........B......... .x.x..*

   2EA46D8979 0011A0   0000000000000000 0000000000000000   0000000000000800 0000000000000000 *................................*

   2EA46D8979 0011C0   0000000000000000 0000000000000000   0000000000000000 00C4D9C9E5C5D940 *.........................DRIVER *

   2EA46D8979 0011E0   4040404040404040 4040404040404040   4040404040404040 4040404040404040 *                               *

   2EA46D8979 001200   4040404040404040 404040C6D3C4F200   0000000000000000 0000000000000000 *           FLD2.................*

   2EA46D8979 001220   00000000B79DF801 6BE4000000000000   0000000000000000 0000000000000000 *.... 8.,U......................*

   2EA46D8979 001240   0000000000000000 0000000000000000   0000000000000000 0000000000000000 *................................*

                       109 LINES   2EA46D8979 001260   TO   2EA46D8979 001FE0   SAME AS ABOVE

****** END OF DUMP ******

 

Note: The above example dump result is retrieved at VRM540, as an internal object type. The format of *FMT objects would possibly change in newer releases.

 

Now, you can investigate the format of the record format description information stored in the *FMT object. For example, the header portion seems to have a fixed length of hex 5F bytes, and the meanings of some of the fields in the header portion can be figured out easily:

 

Offset (Hex)

Data type and length

Usage

00

SYSPTR

System pointer (16 bytes) to a *FILE object or a *DBDIR object [1]

32

BIN(2)

Number of bytes in a record [2]

34

CHAR(10)

Record format name

3E

CHAR(13)

Record format identifier

5D

BIN(2)

Number of fields in the record format [2]

[1] When the record format described by the current *FMT object is reference by a single file object, this field is a system pointer to the hex 1901 *FILE object. When the record format is shared by multiple file objects, e.g., one or more logical files based a physical file that have the same record format with the physical file, this field is a system pointer addressing a database directory (with external type name *DBDIR and MI object type/subtype hex 1950) object called FORMAT-SHARING DIRECTORY. The *DBDIR object stores system pointers to all *FILE object that reference this current *FMT object.

[2] Upper limits of these two values can be found in the Database file sizes page in the IBM i Information Center.

 

Following the header portion are variable-length record-field entries, each starting with a BIN(2) length field that indicates the length of the current record-field entry.

 

How a Program Tells the System Whether to Perform Level-Checking When Opening a File

The system supplies the level-checking function for database files and device files. HLL compilers take advantage of the function to make sure record formats of externally described files found at runtime by an HLL program agree with what the compiler saw when the program was compiled. This way, an HLL program can be stopped as soon as an unexpected record format is detected; therefore, more serious errors due to the program receiving the wrong data content can be avoided. Also, there are conditions in which HLL compilers do not force level-checking upon file-opening; program-described files in COBOL and RPG are an example, and C library routine _Ropen() never takes level-checking into consideration.

 

Whether level-checking is performed when a file is being opened is determined by the following rules:

 

  1. 1.When a file created with parameter LVLCHK(*NO) is opened by an HLL program, the system does not perform level-checking.
  2. 2.When a file whose level-check attribute is overridden by an override command (such as OVRDBF or OVRDSPF) with parameter LVLCHK(*NO) is opened by an HLL program, the system does not perform level-checking.
  3. 3.When opening a file, if a program indicates not to perform level-checking via the User File Control Block (UFCB) through which it accesses the file, level-checking is not performed.
  4. 4.In all other conditions, level-checking is performed by comparing each RCDFMT-ID of the file to be opened with the corresponding RCDFMT-ID supplied by the requesting program in the UFCB.

The User File Control Block (UFCB)

What is UFCB? The following definition of UFCB is quoted from Chapter 12, Input/Output in MI Using the SEPT, of a great e-book, AS/400 Machine-Level Programming, written by Leif Svalgaard:

 

Strictly speaking a file is not an MI concept. At the MI-level, data is stored in spaces, not files. Files are opened, read/written, then closed. At the MI-level there is no concept of opening/closing of files. Files are defined at the OS/400 level (CPF) above the MI. A program (even an MI-program) accesses a file through a User File Control Block (the UFCB). The UFCB defines the filename, library name, possibly a member name, buffer areas and all necessary other control information needed to manage the file. It also provides pointers to the various feedback areas and access to various control structures, such as the Open Data Path (the ODP). The main purpose of the UFCB is to provide device independence for I/O. You use a UFCB for database files, display files, spool files, save files, tape files, etc. The fact that these files often have very different internal structure (the actual objects making up the files) is transparent to the programmer.

 

The UFCB consists of a 208-byte fixed portion, followed by a variable portion made up of a list of optional parameters. Each parameter has the following format: parameter identifier (PARM-ID) and parameter value (PARM-VALUE). The PARM-ID is a predefined BIN(2) value that identifies the parameter. The PARM-VALUE can be of any structural format as defined by the PARM-ID. If the parameter is not used it must be set to its minus value. For example, a PARM-ID of value -59 indicates that the Commitment control parameter is not active and should be skipped. If the parameter is used, its positive value is set in the PARM-ID field and the pertinent information associated with the parameter must also be set; by setting the PARM-ID value to minus, the system knows the length of the structure that will follow and how many bytes to skip. A special PARM-ID, 32767 (or hex 7FFF), indicates the end of the parameter list. Note that although the length of the fixed portion of the UFCB would not likely change across releases, the formats of the UFCB at different releases might be different slightly.

 

For documentation on the UFCB, you can refer to the following resources:

 

l Chapter 12, Input/Output in MI Using the SEPT, Chapter 13, File Conversion and Hashing, and Chapter 16, User-Defined 5250 Datastream I/O, of Leif Svalgaard's e-book discuss the UFCB in detail. Chapter 12 is also available in a presentation handout (handout.doc or handout.pdf) of the e-book for COMMON.

l Another useful reference is the Query (QQQQRY) API's documentation in the Information Center. It covers the parts of the fixed portion and the variable portion of the UFCB. Similar information can be found in source member QSYSINC/H.QQQQRY, which was shipped with the System Openness Includes option of i5/OS.

l Among the posts in the MI400 mailing list dating back to the early 2000s, you can find a lot of MI source examples and discussions about doing file I/O via the UFCB. Just go to http://archive.midrange.com/mi400/index.htm and search with keyword UFCB.

 

Perform or Disable Level-Checking via UFCB Parameters

Programs use two UFCB parameters to control level-checking when opening a file: the Level-check Option (lvlchk) parameter whose PARM-ID is 6, and the Record Formats (rcdfmts) parameter whose PARM-ID is 7. Formats of these UFCB parameters are shown in the following tables.

 

lvlchk

BIN(2)

PARM-ID=6

PARM-VALUE

CHAR(1)

 

 

 

BIT 0

lvlonoff

Level-check option

1=Perform level-checking

0=Do not perform level-checking

 

BITS 1-7

Reserved (binary 0)

 

rcdfmts

BIN(2)

PARM-ID=7

PARM-VALUE

BIN(2)

 

Maxnum=The maximum number of formats

BIN(2)

 

Curnum=The current number of formats

[*]CHAR(23)

 

Formats=Array of format CHAR(10) names and CHAR(13)

 

CHAR(10)

Record format name

 

CHAR(13)

Record format identifier

 

Maxnum indicates the number of array elements in formats. It tells the system the size of storage reserved for the rcdfmts parameter. The value of curnum ranges from zero to the value of maxnum. The system checks the first curnum record format name/ID pairs one by one against the file to open at runtime. For each record format name/ID pair in formats, if the record format name is not found in the file or if the RCDFMT-ID of the record format does not match that of the record format found in the file, the system raise a CPF4131 error message.

 

So, to tell the system to perform level-checking, a program should do two things. It should specify the lvlchk parameter and set the lvlonoff to 1 (i.e., set the PARM-VALUE of lvlchk to hex 80), and it should specify the rcdfmts parameter, set maxnum to the number of array elements in formats, set curnum to the number of record formats to check, and set the value of each record format name/ID pair.

 

To tell the system not to perform level-checking, a program should specify the lvlchk parameter and set the lvlonoff to 0 (i.e., set the PARM-VALUE of lvlchk to hex 00).

 

The following is an example MI program that performs or disables level-checking via UFCB parameters lvlchk and rcdfmts, lvlchk01.emi. It opens a file that has a single record format for read and then closes it via Data Management APIs QDMCOPEN and QDMCLOSE, respectively. LVLCHK01 takes two to four parameters. The first parameter is the target file to open. The second parameter of this program tells it whether or not to perform level-checking when opening the file (set it to hex 00 to disable level-checking, or set it to any other value to perform level-checking). If the second parameter is not hex 00, then the third and fourth parameters are expected to be the name and ID of the record format supplied for level-checking.

 

/**

* @file lvlchk01.emi

*

* Open a file and test RCDFMT-ID.

* e.g.

* Open file with level-checking:

*   CALL PGM(LVLCHK01) PARM(FILE-NAME X'01' RCDFMT-NAME RCDFMT-ID)

* Open file without level-checking:

*   CALL PGM(LVLCHK01) PARM(FILE-NAME X'00')

*/

 

/* My parameter list */

dcl spcptr @file-name parm     ;

dcl spcptr @do-lvlchk parm     ;

dcl spcptr @rcd-id parm         ;

dcl spcptr @rcd-name parm       ;

dcl ol pl-main (

       @file-name,             /* CHAR(10) file name */

       @do-lvlchk,             /* CHAR(1) flag. hex 00 indicates no level-checking */

       @rcd-name,               /* CHAR(10) record format name */

       @rcd-id                 /* CHAR(13) record format ID */

) parm ext min(2)               ;

 

entry *(pl-main) ext           ;

 

       /* Set file-name in the UFCB */

dcl dd ch10 char(10) bas(*)               ;

       cpybla file-name, @file-name->ch10 ;

 

       /* Do level-checking or not? */

dcl dd do-lvlchk char(1) bas(@do-lvlchk) ;

       cmpbla(b) do-lvlchk, x'00' / eq(no-lvlchk) ;

       /* Enable level-checking */

       cpybla lvlonoff, x'80' ;

       /* Set RCDFMT name and ID in the UFCB */

       cpybla rcd-name, @rcd-name->ch10 ;

dcl dd ch13 char(13) bas(*)             ;

       cpybla rcd-id, @rcd-id->ch13     ;

 

       b open-file             ;

no-lvlchk:    

       /* Disable level-checking */

       cpybla lvlonoff, x'00' ;

 

open-file:

       callx sept(open-entry), pl-open-close, * ;

 

brk "LOOK"                     ; /* DSPJOB OPTION(*OPNF) */

 

close-file:    

       callx sept(close-entry), pl-open-close, * ;

 

see-you:      

       rtx *                  ;

 

/* UFCB definition */

dcl dd ufcb char(256) auto bdry(16) ;

       /* Fixed portion of the UFCB, of length 208 bytes */

       dcl spcptr odp           def(ufcb) pos(001) ;

       dcl dd file-name char(10) def(ufcb) pos(129) ;

      dcl dd lib-id   bin(2)   def(ufcb) pos(139) init(-75) ; /* *LIBL, or -72 (S/38) */

       dcl dd lib-name char(10) def(ufcb) pos(141) init("*LIBL") ;

       dcl dd mbr-id   bin(2)   def(ufcb) pos(151) init(-71) ; /* *FIRST, or -73 (S/38) */

       dcl dd mbr-name char(10) def(ufcb) pos(153)           ;

       dcl dd flag1     char(1) def(ufcb) pos(175) init(x'80') ; /* Share and secure flags. Bits 0-2: close options */

       dcl dd flag2     char(1) def(ufcb) pos(176) init(x'20') ; /* Open flags. */

       /* UFCB parameters */

       dcl dd lvlchk   bin(2)   def(ufcb) pos(209) init(6) ; /* Parameter lvlchk */

       dcl dd lvlonoff char(1) def(ufcb) pos(211) init(x'80') ; /* Do level-check */

       dcl dd rcdfmts   bin(2)   def(ufcb) pos(212) init(7) ; /* Parameter rcdfmts */

       dcl dd rcdfmts-t char(27) def(ufcb) pos(214) ; /* PARM-VALUE of rcdfmts */

       dcl dd end-list bin(2)   def(ufcb) pos(241) init(h'7FFF') ; /* End of parameter list */

 

/* PARM-VALUE of rcdfmts */

dcl dd max-num bin(2)     def(rcdfmts-t) pos(1) init(1) ; /* The maximum number of formats. */

dcl dd cur-num bin(2)     def(rcdfmts-t) pos(3) init(1) ; /* The current number of formats. */

       /* Array of CHAR(10) format names and CHAR(13) format IDs */

     dcl dd rcd-name char(10) def(rcdfmts-t) pos(5) ;

       dcl dd rcd-id   char(13) def(rcdfmts-t) pos(15) ;

 

/* System Entry Point Table (SEPT) */

dcl spc pco baspco           ; /* The PCO object */

       dcl spcptr @sept dir ; /* Space pointer addressing the SEPT */

dcl sysptr sept(7000) bas(@sept) ;

 

dcl con close-entry bin(2)   init(11) ; /* SYSPTR to QDMCLOSE in the SEPT is sept(11) */

dcl con open-entry bin(2)   init(12) ; /* SYSPTR to QDMCOPEN in the SEPT is sept(12) */

dcl spcptr @ufcb auto init(ufcb)     ;

dcl ol pl-open-close (@ufcb) arg ; /* Argument list of QDMCLOSE and QDMCOPEN */

 

pend                           ;

 

Compile MI program LVLCHK01 from lvlchk01.emi (via an MI compiler, e.g., mic) and test it.

 

Suppose that you have a database file called A5, which has a single record format called REC, the RCDFMT-ID of which is 28B9A5DECA650. You can do the following tests on A5:

 

1. Open A5 without level-checking: CALL LVLCHK01 (A5 X'00'). To make sure A5 is being opened, start a debug session before calling LVLCHK01 and add a breakpoint at LOOK using the following CL commands:

STRDBG LVLCHK01

ADDBKP STMT(LOOK)

After LVLCHK01 stops at breakpoint LOOK, press F10 and type DSPJOB OPTION(*OPNF) and find file A5 in the Display Open Files screen.

 

2. Open A5 with level-checking and supply the correct record format name/ID: CALL LVLCHK01 (A5 X'01' REC '28B9A5DECA650').

 

3. Open A5 with level-checking and supply the incorrect record format ID: CALL LVLCHK01 (A5 X'01' REC '28B9A5DECA650'). Now you'll get a CPF4131 error message.

 

Also it would be an interesting exercise to implement the above shown MI program in an HLL—for example, RPG or C. An RPG example, lvlchk02.rpgle, is available in Appendix A.

 

Achieve Compatibility Across Multiple Versions of a Database File by Using LVLCHK(*NO)

The method is quite straightforward:

  • Never change field(s) in the existing record format of a database file (DBF).
  • Always append newly added field(s) to the end of the existing record format of the DBF.
  • Specify parameter LVLCHK(*NO) when creating/changing the DBF or overriding it via a file override command.

This way, an HLL program compiled to an older version of the DBF can happily work with all newer versions of it with no worry about the level-check errors. An HLL program that only writes to the DBF can even work with older versions of the DBF (of course, information kept in the fields not in the older version of DBF will be lost).

 

One application of this technique is the manner in which IBM deals with the output files of its numerous display commands whose OUTPUT parameter accepts the *OUTFILE special value, e.g., Display Object Description (DSPOBJD), Display Module (DSPMOD), and Display Journal (DSPJRN). Each of these display commands has one or more template output files in the QSYS library, corresponding to the record format(s) used by the display command. The template output files have no member and are created as LVLCHK(*NO). When a user requests a DSPXXX OUTPUT(*OUTFILE) OUTFILE(SOME_LIB/SOME_FILE) operation, the template file of the command is duplicated as SOME_LIB/SOME_FILE if it isn't already there. Certainly, a member will be added to the duplicated file, which inherits the LVLCHK(*NO) attribute from the template file. If you're interested in knowing the template file(s) of a given display command, the following post by Simon Coulter in the midrange-l mailing list might be helpful for you: http://archive.midrange.com/midrange-l/200105/msg01319.html.

 

The record formats of these output files are likely to change frequently from release to release due to newly added or improved functionalities of the system. But the changes to such a record format would only be new fields being appended to the end of it. For example, check the record format information of the template output file of the DSPOBJD command, QSYS/QADSPOBJ, at V5R2 and V5R4, respectively. You can get the following result.

 

V5R2:

   Record Format List                                                      

                         Record Format Level                              

   Format       Fields   Length Identifier                                

   QLIDOBJD       104     620 43F1FD420BA60                            

     Text . . . . . . . . . . . . . . . . . . . :           Object descript

   Total number of formats . . . . . . . . . . :           1              

   Total number of fields . . . . . . . . . . . :         104              

   Total record length . . . . . . . . . . . . :         620              

 

V5R4:

   Record Format List                                                      

                         Record Format Level                              

   Format       Fields   Length Identifier                                

   QLIDOBJD       112     689 3DE3ECD9C43DE                            

     Text . . . . . . . . . . . . . . . . . . . :           Object descript

   Total number of formats . . . . . . . . . . :           1              

   Total number of fields . . . . . . . . . . . :         112              

   Total record length . . . . . . . . . . . . :         689              

 

 

Although, at V5R4, record format QLIDOBJD contains eight fields more than its V5R2 version, the beginning 104 fields of these two versions of record formats are exactly the same. So an HLL program compiled to the output file of a DSPOBJD command at V5R2 can work with an output file of a DSPOBJD command at V5R4 and vice versa. For the same reason, an HLL program compiled to the output file of a display command at one release can work with an output file of the display command at any release.

 

Appendix A: Source of ILE RPG Example lvlchk02.rpgle

 

Please refer to https://i5toolkit.svn.sourceforge.net/svnroot/i5toolkit/art/lvlchk02.rpgle for the most current version.

 

     /**

     * @file lvlchk02.rpgle

     *

     * This program is the RPG version of ./lvlchk01.emi

     */

     h dftactgrp(*no)

     /if defined(HAVE_I5TOOLKIT)

     /copy mih-pgmexec

     /copy mih-prcthd

     /else

     * Prototype of MI instruction CALLPGMV

     d callpgmv       pr                  extproc('_CALLPGMV')

     d     pgm_ptr                     *

     d     argv                       *   dim(1) options(*varsize)

     d     argc                     10u 0 value

     * Prototype of MI instruction PCOPTR2

     d pcoptr2        pr             *   extproc('_PCOPTR2')

     /endif

 

     d i_main         pr                 extpgm('LVLCHK02')

     d   p_file_name                 10a

     d   p_lvlchk                     1a

     d   p_rcd_name                 10a

     d   p_rcd_id                   13a

 

     d @pco           s               *

     d @sept           s               *   based(@pco)

     d sept           s               *   based(@sept)

     d                                     dim(7000)

     d close_entry    c                   11

     d open_entry     c                   12

     d @ufcb           s               *   inz(%addr(ufcb))

     d                 ds

     * Fixed portion of UFCB

     d ufcb                         256a

     d file_name                    10a   overlay(ufcb:129)

     d lib_id                         5i 0 overlay(ufcb:139)

     d                                     inz(-75)

     d lib_name                     10a   overlay(ufcb:141)

     d                                     inz('*LIBL')

     d mbr_id                         5i 0 overlay(ufcb:151)

     d                                     inz(-71)

     d mbr_name                     10a   overlay(ufcb:153)

     d flags                         2a   overlay(ufcb:175)

     d                                    inz(x'8020')

     * UFCB parameters

     d lvlchk                         5i 0 overlay(ufcb:209)

     d                                     inz(6)

     d lvlonoff                       1a   overlay(ufcb:211)

     d rcdfmts                      5i 0 overlay(ufcb:212)

     d                                     inz(7)

     d maxnum                         5i 0 overlay(ufcb:214)

     d                                     inz(1)

     d curnum                         5i 0 overlay(ufcb:216)

     d                                     inz(1)

     d rcd_name                     10a   overlay(ufcb:218)

     d rcd_id                       13a   overlay(ufcb:228)

     d end_of_list                   5i 0 overlay(ufcb:241)

     d                                    inz(x'7FFF')

 

     d i_main         pi

     d   p_file_name                 10a

     d   p_lvlchk                     1a

     d   p_rcd_name                 10a

     d   p_rcd_id                   13a

 

     /free

          file_name = p_file_name; // set UFCB.file_name

           if p_lvlchk > x'00';

               lvlonoff = x'80';

               rcd_name = p_rcd_name;

               rcd_id   = p_rcd_id;

           else;

               lvlonoff = x'00';

           endif;

 

           // Locate PCO pointer

           @pco = pcoptr2();

          

           // Call QDMCOPEN to open the file

           callpgmv( sept(open_entry) : @ufcb : 1 );

 

           dsply 'DSPJOB OPTION(*OPNF) and look for:' '' p_file_name;

 

         // Call QDMCLOSE to close the file

           callpgmv( sept(close_entry) : @ufcb : 1 );

 

           *inlr = *on;

     /end-free

 

For more examples of using the MI instructions CALLPGMV and PCOPTR2, you can refer to System-builtin Headers and Examples for ILE HLLs. They are prototyped in mih-pgmexec.rpgleinc and mih-prcthd.rpgleinc, respectively.

 

Junlei Li

Junlei Li is a programmer from Tianjin, China, with 10 years of experience in software design and programming. Junlei Li began programming under i5/OS (formerly known as AS/400, iSeries) in late 2005. He is familiar with most programming languages available on i5/OS—from special-purpose languages such as OPM/ILE RPG to CL to general-purpose languages such as C, C++, Java; from strong-typed languages to script languages such as QShell and REXX. One of his favorite programming languages on i5/OS is machine interface (MI) instructions, through which one can discover some of the internal behaviors of i5/OS and some of the highlights of i5/OS in terms of operating system design.

 

Junlei Li's Web site is http://i5toolkit.sourceforge.net/, where his open-source project i5/OS Programmer's Toolkit (https://sourceforge.net/projects/i5toolkit/) is documented.

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

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: