× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.


  • Subject: An introduction to MI by example III (part B)...
  • From: "Phil Hall" <hallp@xxxxxxxx>
  • Date: Tue, 23 Nov 1999 09:46:28 -0600

Here's another edition in the on going 'Introducing MI...'
series, to try and help the non-MI programmers (or the
beginners) on the list to understand MI 'code in action'

=============================================

You can request copies (some of which have been updated)
of all "Introducing MI..." postings by clicking on the
following link;

    hallp@ssax.com?SUBJECT=Introducing_MI_Bundle_Request

Or if your email client doesn't support the above link, by
sending an email to;

    hallp@ssax.com

with;

    Introducing MI Bundle Request

in the SUBJECT line.

==============================================

This time we'll take a look at the little program that is the 'driver'
for the sorting program. After cutting out the sort program source, this
code looked all kind of lost and lonely in the clipboard so I felt
guilty about discarding it ! Anyhow, this is an interesting program, as
it could form the basis for a program that could be written and used to
perform dynamic program invocation, i.e. calling a program when you
don't know the name of it at runtime.

As usual, here's the complete original source;

DCL DD RESOLVE-PG CHAR(34);
    DCL DD RESOLVE-TYPE CHAR( 2) DEF(RESOLVE-PG) POS( 1) INIT(X'0201');
    DCL DD RESOLVE-NAME CHAR(30) DEF(RESOLVE-PG) POS( 3);
    DCL DD RESOLVE-AUTH CHAR( 2) DEF(RESOLVE-PG) POS(33) INIT(X'0000');

DCL SPCPTR .PARM1 INIT(PARM1);
DCL DD      PARM1 CHAR(5);
    DCL DD  PARM-NBR-ELEMENTS PKD(7,0) DEF(PARM1) POS(1);
    DCL DD  PARM-DIRECTION    CHAR(1)  DEF(PARM1) POS(5);

DCL SPCPTR .PARM2 INIT(PARM2);
DCL DD      PARM2(500000) ZND(20,0);

DCL SYSPTR .COMBSORT;
DCL OL COMBSORT(.PARM1, .PARM2) ARG;

DCL DD NBR BIN(4);
DCL DD MAX BIN(4) INIT(500000);

ENTRY * EXT;
RESOLVE-PGMS:
    CPYNV      NBR, 0;
NEXT:
    ADDN(S)    NBR, 1;
    SUBN       PARM2(NBR), 1000000, NBR;
    CMPNV(B)   NBR, MAX/LO(NEXT);

    CPYBLAP    RESOLVE-NAME, "COMBSORT" , " ";
    RSLVSP    .COMBSORT, RESOLVE-PG, *, *;
    CPYNV      PARM-NBR-ELEMENTS, P'500000';
    CPYBLA     PARM-DIRECTION, "A";
    CALLX     .COMBSORT, COMBSORT, *;
    RTX        *;

PEND;


OK, lets look at the variable declaration section;

    DCL DD RESOLVE-PG CHAR(34);
        DCL DD RESOLVE-TYPE CHAR( 2) DEF(RESOLVE-PG) POS( 1)
INIT(X'0201');
        DCL DD RESOLVE-NAME CHAR(30) DEF(RESOLVE-PG) POS( 3);
        DCL DD RESOLVE-AUTH CHAR( 2) DEF(RESOLVE-PG) POS(33)
INIT(X'0000');

Nothing new here, just defining a structure called 'RESOLVE-PG', that
has three character variables mapped contiguously across it;
'RESOLVE-TYPE' is set to hex '0201' which is the type/subtype of program
objects on the AS/400, 'RESOLVE-NAME' and 'RESOLVE-AUTH'. This structure
will be used when we get a pointer to a program later in the code.

    DCL SPCPTR .PARM1 INIT(PARM1);
    DCL DD      PARM1 CHAR(5);
        DCL DD  PARM-NBR-ELEMENTS PKD(7,0) DEF(PARM1) POS(1);
        DCL DD  PARM-DIRECTION    CHAR(1)  DEF(PARM1) POS(5);

The above section is laying out the structure for parameter one
'PARM1' - the number of elements in the array and the sort direction,
which we know from the sort program can either 'A' or 'D'. In fact if
you go back and look at the sort program, you'll find that if the value
in 'PARM-DIRECTION' is anything other than 'D' then the sort direction
will be ascending.

NOTE: These parameters are not the incoming parameters to *this*
program, they will be used as parameters when calling the COMBSORT
program.

Next, 'PARM2' is defined;

    DCL SPCPTR .PARM2 INIT(PARM2);
    DCL DD      PARM2(500000) ZND(20,0);

It's being declared as an array with 500000 elements, each being 20
digit zoned. Then we have the variable '.COMBSORT';

    DCL SYSPTR .COMBSORT;

This is being defined as a system pointer (SYSPTR). System pointers are
16 byte pointers to 'real' AS/400 objects, such as programs, files, data
areas, etc. Next up is the definition of the parameter list 'COMBSORT'
we will use to call the sort program, and the order;

    DCL OL COMBSORT(.PARM1, .PARM2) ARG;

Following this we have some general variables being declared;

    DCL DD NBR BIN(4);
    DCL DD MAX BIN(4) INIT(500000);

These variables will be used to fill the array with some test data to be
sorted.

OK, here's a standard entry point;

    ENTRY * EXT;

We now know from previous code, that no parameters are passed to this
program, and then we have a branch target called 'RESOLVE-PGMS:' being
defined;

    RESOLVE-PGMS:
        CPYNV      NBR, 0;

And 0 being copied in to 'NBR'.

The next section;

    NEXT:
        ADDN(S)    NBR, 1;
        SUBN       PARM2(NBR), 1000000, NBR;
        CMPNV(B)   NBR, MAX/LO(NEXT);

Is a little loop that fills from element 1 of PARM2 upwards while 'NBR'
is lower (/LO) than 'MAX'.

Then we get to the code that calls the COMBSORT program;

        CPYBLAP    RESOLVE-NAME, "COMBSORT" , " ";
        RSLVSP    .COMBSORT, RESOLVE-PG, *, *;
        CPYNV      PARM-NBR-ELEMENTS, P'500000';
        CPYBLA     PARM-DIRECTION, "A";
        CALLX     .COMBSORT, COMBSORT, *;

So, the first line copies 'COMBSORT' (the name of the sort program) in
to the variable 'RESOLVE-NAME' padding any extra characters at the end
with " ". Then the MI instruction RSLVSP. This MI instruction locates
the object named in 'RESOLVE-NAME' of object type 'RESOLVE-TYPE' (we'll
ignore the authority variable 'RESOLVE-AUTH' for now). Once the system
locates the object, it returns a system pointer to the object in to our
pointer variable '.COMBSORT'. Then we set the direction for the sort,
"A" (ascending) and invoke the program COMBSORT via the pointer
'.COMBSORT' passing the parameters listed in the 'COMBSORT' operand
list.

Finally the old return and program end code;

        RTX        *;
    PEND;

Remember when I said that this program could be used as the basis for
dynamic program invocations ? Well one of the things we would do is
remove the hard coded "COMBSORT" as the program name. We could then use
a passed in variable, a look-up table, etc. to get the name of the
program to call. Although in this instance making the program name a
variable doesn't aid us in any way, there are times when writing other
programs/applications where you may need the flexibility of dynamic
calls in a generic driver program. And the above code is not that far
removed from what it would look like...

--phil

+---
| 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 thread ...


Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

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.