|
For those of you who actually read my 'Introducing MI...II', you may be wondering how Tim managed to turn twelve lines of code (in Leif's dynamic memory allocation version of GETOWNLIB) into one line of code. Well Tim 'cheated' - sort of ! Let's look at Tim's code first, and then see where the 'cheat' is... DCL DD INVINFO CHAR(16) BDRY(16); DCL SYSPTR INVPGM DEF(INVINFO) POS(1); DCL SPCPTR P#INVINF INIT(INVINFO); /* The attribute info selects the program pointer. DCL DD ATTINFO CHAR(144) BDRY(16); DCL DD NUMATT BIN(4) DEF(ATTINFO) POS(1) INIT(1); DCL DD ATTID BIN(4) DEF(ATTINFO) POS(17) INIT(6); DCL DD ATTLGH BIN(4) DEF(ATTINFO) POS(29) INIT(16); DCL SPCPTR P#ATTINF INIT(ATTINFO); /* The selection criteria controls the invocation level. DCL DD SELECT CHAR(48) BDRY(16); DCL DD SRCINV BIN(4) DEF(SELECT) POS(1) INIT(-1); /* Materialize the INVOCATION stack - current-1 MATINVAT P#INVINF,SELECT,P#ATTINF; Nothing too difficult in this code, just a lot of variable declaring, then the one line of code - the call to 'MATINVAT'. What did Tim do differently ? He called MATINVAT, instead of MATINVS. MATINVAT (MATerialize INVocation ATtributes) materializes a single entry in the call stack, where as if you remember MATINVS materializes the whole stack. If you take a look at the MATINVAT instruction in the MI Reference, you'll find that the way to call the instruction is to pass it a selection template - or in MI speak a attribute selection template. This is similar to when you call some of the OS/400 list API's such as QUSROBJD (list object description) in RPG. You can shorted the list returned from QUSROBJD by passing in a selection parameter to, say, just list the *JOBD objects. In this case, Tim is using the selection template 'ATTINFO', setting the values of the template as follows; DCL DD ATTINFO CHAR(144) BDRY(16); The template 'ATTINFO' is declared as character, 144 in length, aligned on a 16-byte boundary (the alignment is needed to keep the pointer that will be returned 'usable') DCL DD NUMATT BIN(4) DEF(ATTINFO) POS(1) INIT(1); We're only after one type of attribute to be returned, hence 'NUMATT' is initialized to the value of 1. DCL DD ATTID BIN(4) DEF(ATTINFO) POS(17) INIT(6); We want a pointer to the calling program, so 'ATTID' is set to 6 (see the MI ref. for other attribute types you can request) DCL DD ATTLGH BIN(4) DEF(ATTINFO) POS(29) INIT(16); 'ATTLGH' is set to the length of a system pointer, 16 bytes. We also see the variable 'SELECT' being declared as follows; DCL DD SELECT CHAR(48) BDRY(16); DCL DD SRCINV BIN(4) DEF(SELECT) POS(1) INIT(-1); Here, we want the stack entry previous to the current one (the current one will be an entry for the GETOWNLIB itself), so we see 'SRCINV' being set to -1. Finally, when the line of code; MATINVAT P#INVINF,SELECT,P#ATTINF; Is executed, MATINVAT uses 'SELECT' to determine which entry in the call stack to materialize, then uses 'P#ATTINF' (really, the data P#ATTINF points to) to determine what data to actually materialize for the selected stack entry. You might want to re-read that a couple of times until it makes sense. OK, what's the cheat ? Well a few things are missing... 1) The definition of the incoming parameter from the calling program. 2) The 'conversion' of the system pointer 'P#INVINF' from it's pointer representation to a more readable form. If you look back at Leif's code, this was achieved by using the MI instruction 'MATPTR' 3) Copying the name of the library of the calling program into the passed in parameter. So although Tim reduced the code to one line, as the program stands (how he wrote it) it doesn't produce the same results as GETOWNLIB (in fact it won't compile). So what needs to be done to make it 'functionally equivalent' to Leif's GETOWNLIB program ? Well, this would be a good chance to test how much MI you've managed to learn from these 'Introducing MI.." emails. You have all the information you need from Leif's program, plus the 'one-liner' from Tim to create the source. Go on, give it a try ! If you get stuck, I've included what the source should resemble a few pages down... Finally, even when we 'fix' Tim's 'one-liner' to work, it's still only three lines of code ! --phil keep trying before you look !! OK, here's the source I cobbled together from Leif & Tim's code hence the two different variable naming conventions... /*** Declare incoming parameters ***/ DCL DD PARM1 CHAR(10) BAS(.PARM1); DCL DD PARM-LIB-NAME CHAR(10) DEF(PARM1) POS(1); DCL SPCPTR .PARM1 PARM; DCL OL PARMS(.PARM1) EXT PARM MIN(1); /*** Declare variable for MATPTR ***/ DCL SPCPTR .PROGRAM INIT(PROGRAM); DCL DD PROGRAM CHAR(77) BDRY(16); DCL DD PGM-BYTES-PRV BIN(4) DEF(PROGRAM) POS( 1) INIT(77); DCL DD PGM-LIB-NAME CHAR(30) DEF(PROGRAM) POS(12); /*** Declare invocation entry variable ***/ DCL DD INVINFO CHAR(16) BDRY(16); DCL SYSPTR INVPGM DEF(INVINFO) POS(1); DCL SPCPTR .INVINF INIT(INVINFO); /*** The attribute info selects the program pointer ***/ DCL DD ATTINFO CHAR(144) BDRY(16); DCL DD NUMATT BIN(4) DEF(ATTINFO) POS(1) INIT(1); DCL DD ATTID BIN(4) DEF(ATTINFO) POS(17) INIT(6); DCL DD ATTLGH BIN(4) DEF(ATTINFO) POS(29) INIT(16); DCL SPCPTR .ATTINF INIT(ATTINFO); /*** The selection criteria controls the invocation level ***/ DCL DD SELECT CHAR(48) BDRY(16); DCL DD SRCINV BIN(4) DEF(SELECT) POS(1) INIT(-1); /*** program entry point ***/ ENTRY * (PARMS) EXT; /*** Materialize the INVOCATION stack entry current-1 ***/ MATINVAT .INVINF, SELECT, .ATTINF; MATPTR .PROGRAM, INVPGM; CPYBLA PARM-LIB-NAME, PGM-LIB-NAME; RTX *; PEND; +--- | This is the MI Programmers Mailing List! | To submit a new message, send your mail to MI400@midrange.com. | To subscribe to this list send email to MI400-SUB@midrange.com. | To unsubscribe from this list send email to MI400-UNSUB@midrange.com. | Questions should be directed to the list owner/operator: dr2@cssas400.com +---
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.