Support This Project Get i5/OS Programmer's Toolkit at SourceForge.net. Fast, secure and Free Open Source software downloads

Analyzing the BOM Table Component

The breakpoint offset mapping (BOM) table component of an OPM MI component stores the mappings from breakpoints of an OPM MI program to corresponding MI instruction numbers. A breakpoint in an MI program is produced by a break directive statement (BRK) in the MI source of the program. The BRK directive statement allows symbolic breakpoints to be defined. The following diagram and table show the break directive statement:
BRK string1;
Remarks:
string1 is the name of the breakpoint.
The BOM table component can be used by compilers to relate high-level language statement numbers to instruction numbers. For example, the OPM RPG compiler and the OPM CL compiler stores the sequence number of source records as HLL statement numbers (breakpoint names in the MI source). While the OPM COBOL compiler generates HLL statement numbers according to a collection of validated source statements; for example, empty lines are omitted.

The BOM table has the 2 formats depending on the BOM table flags (matpg?bom-flag). If the flag indicates to use new BOM table format, then the first bit of the MI instruction number is not a flag, so numbers up to 64k-1 can be used. The 2 BOM formats are defined as bom-entry0-t, and bom-entry1-t in mip-h.emi like the following:

Todo:
link
dcl spc bom-entry0-t bas(*)     ;
        /*
 bit 0. Format flag.
  0 = HLL statement number is in character format
  1 = HLL statement number is in numeric format
         */
        dcl dd bome0?mi-inst bin(2) unsgnd dir ;
        dcl dd bome0?hll-stmt-str char(10) dir ;
        dcl dd bome0?hll-stmt-num bin(2) def(bome0?hll-stmt-str) ;

dcl spc bom-entry1-t bas(*)     ;
        dcl dd bome1?mi-inst bin(2) unsgnd dir ;
        /*
 bit 0. Format flag.
  0 = HLL statement number is in character format
  1 = HLL statement number is in numeric format
         */
        dcl dd bome1?fmt char(1) dir      ;
        dcl dd bome1?hll-stmt-str char(10) dir ;
        dcl dd bome1?hll-stmt-num bin(2) def(bome1?hll-stmt-str) ;

The following is an example MI program (tmip03.emi) that parses the BOM table component of OPM RPG program t143rpg.rpg.

/*
 @file tmip03.emi

 Parse the BOM of an OPM MI program template.
 */

entry *(pl-main) ext            ;

dcl spcptr .pgm-name parm       ;
dcl spcptr .pgm-type parm       ;
dcl ol pl-main(
        .pgm-name,
        .pgm-type
) parm ext ;

dcl dd pgm-name char(10) bas(.pgm-name) ;
dcl dd pgm-type char(2) bas(.pgm-type)  ;

dcl dd rt char(34) auto         ;
dcl sysptr pgm auto             ;
        cpybrep rt, x'00'       ;
        cpybla  rt(1:2), pgm-type ;
        cpyblap rt(3:30),
          pgm-name, ' ' ;
        rslvsp  pgm, rt, *, *   ;
brk '1'                         ;

dcl spcptr p auto               ;
dcl dd len bin(4) auto          ;
        modasa p, 8             ;
        cpynv p->matpg?bytes-in, 8 ;
        matpg p, pgm               ;

        cpynv len, p->matpg?bytes-out ;
        modasa p, -8                  ;
        modasa p, len                 ;
        cpynv p->matpg?bytes-in, len  ;
        matpg  p, pgm                 ;
brk '2'                               ;

        /* does tmpl-extension exists? */
        tstbts(b) p->matpg?pgm-attr, 10 / zer(see-you) ;

        /* determine BOM format */
dcl dd new-bom-fmt char(1) auto ;
        tstbts(i) p->matpg?bom-flag, 0
          / nzer(new-bom-fmt) ;

        /* determin length of a BOM entry */
dcl dd bome-len bin(2) auto     ;
        cmpbla(b) new-bom-fmt, '1'
          / eq(=+3) ;
        addn(s) bome-len, 2     ;
        b =+2                   ;
:
        addn(s) bome-len, 3     ;
:
        addn(s) bome-len, p->matpg?bome-len ;

        /* locate the BOM component */
dcl spcptr pos auto             ;
        addspp pos, p,
          p->matpg?bom-off      ;
dcl dd n bin(4) auto            ;
        cpynv n, 0              ;
bom-loop:
        /* determine breakpoint format */
dcl dd char-fmt char(1) auto    ;
        cmpbla(b) new-bom-fmt, '1'
          / eq(=+3)             ;
        tstbts(i) pos->bome0?mi-inst, 0
          / eq(char-fmt)      ; /* old BOM format */
        b =+2                   ;
:
        tstbts(i) pos->bome1?fmt, 0
          / eq(char-fmt)        ;
:
        /* print a BOM entry */
        calli print-bom-entry, *, print-bom-entry-ptr ;

        addn(s) n, bome-len     ;
        cmpnv(b) n, p->matpg?bom-len
          / nlo(end-bom-loop)   ;
        addspp pos, pos, bome-len ;
        b bom-loop              ;
end-bom-loop:       

see-you:        
        neg(s) len              ;
        modasa p, len           ;
        rtx *                   ;

dcl dd msg char(64) auto        ;
        dcl dd msg-inst znd(6) def(msg) pos(1)    ;
        dcl dd msg-bkp  char(10) def(msg) pos(26) ;

/*
 print-bom-entry

 @pre char-fmt, pos, p->matpg?bome-len
 */
dcl insptr print-bom-entry-ptr auto ;
entry print-bom-entry int           ;

dcl spcptr hll-stmt-ptr auto    ;
dcl dd hll-stmt-num char(2) bas(hll-stmt-ptr) ;
dcl spcptr msg-bkp-ptr auto                  ;

        cpybrep msg, " "        ;

        cmpbla(b) new-bom-fmt, '1'
          / eq(=+5)             ;
        setspp hll-stmt-ptr, pos->bome0?hll-stmt-str ;
        clrbts pos->bome0?mi-inst, 0                 ;
        cpynv msg-inst, pos->bome0?mi-inst           ;
        b =+3                   ;
:
        setspp hll-stmt-ptr, pos->bome1?hll-stmt-str ;
        cpynv msg-inst, pos->bome1?mi-inst           ;
:
        /* breakpoint name or number */
        cmpbla(b) char-fmt, '1'
          / neq(numeric-bkp) ;
        setspp msg-bkp-ptr, msg-bkp ;
        %memcpy(msg-bkp-ptr,
                hll-stmt-ptr,
                p->matpg?bome-len) ;
        b end-bkp         ;
numeric-bkp:
        cvthc msg-bkp, hll-stmt-num ;
end-bkp:

        %sendmsg(msg, 64)       ;

        b print-bom-entry-ptr   ;

/include mip-h.emi              ;

pend                            ;

Call TMIP03 like the following:

CALL TMIP03 ('T143RPG' X'0201')

The output of TMIP03 is the following:

000001                   .ENTRY 
000003                   .STOP  
000005                   PROG DS
000005                   .DUMP  
000022                   *GETIN 
000030                   .ERX   
000037                   *TOTC  
000038                   *TOTL  
000039                   *OFL 
000041                   *DETC
000042                   200  
000043                   300  
000044                   400  
000045                   500  
000046                   600  
000047                   700  
000056                   800  
000069                   900  
000082                   1000 
000084                   *DETL
000089                   .SORT   
000089                   S.ARR   
000103                   *INIT   
000134                   .SENDMSG
000138                   *CANCL  
000146                   *TERM   
000150                   .FILERR 
000151                   .ERR    
000178                   .END0002
000182                   .END0001
000185                   .DEACTPG
000192                   .EXCPTON

Support This Project
Generated on Mon Aug 22 08:26:47 2011 for i5/OS Programmer's Toolkit: OPM MI Disassembler by  doxygen 1.5.9