tnt400.com - AS/400 Tips And Techniques

Sponsored by news400.com

This page is a discussion on the mentioned topic.
Most of the answers are in their original posted form, including any technical/spelling/grammatical errors.
No guarantees are expressed or implied. :-)
Comments, corrections, concerns about this tip?

Got another AS/400 question? Ask it here


What's New?
See what's new at Tips-N-Tech.

AS/400 Tips-N-Tech
AS/400 tips, techniques, and FAQ. Updated frequently.
CODEPage/400
All the code samples you can eat! RPG, CL, DDS, etc. etc.
AS/400 FAQs
The official news400.com FAQs.






All AS/400 Tip Categories / AS/400 Programming / Soft Coding Module Names


Question:

Anyone out there have a solution for this?

I am writing an interactive application that will be made up of around 50 modules. (All RPG) As I complete a module and test it I need it to be available to the users. I have a main selection menu that is a full page sub file. To display the eligible options, I read through a DBF, and if the users authority level is >= the authority required to use the app I write the description of the app to the sub file along with a code to a hidden field in the sub file. Then as I process my READC to see which option the user selected, I call various other modules based on the hidden field.

My question: Has any one done something similar except write the name of the module to the hidden field and called the required module. This way I wouldn't have to add a WHEN to the select group, recompile the menu module and update the program every time I add a new app to this system I could just add a record to a DBF and no recompiling needed.


Answer(s):



If you're going to call a module, you must use CallB or CallP. Both of these instructions require that you hard code the name of the possible modules in your program. Even if you specify a procedure pointer in a CallB statement, you must set the procedure pointer by hard-coding the name of the procedure either in the Inz keyword for the procedure pointer or in an Eval statement in your program. As far as I know, there is no way to do what you want given that you are invoking modules.

It may sound like heresy, but why do these have to be modules? If they were standalone programs, you could set a 10-character variable with the name of a program can use old-fashioned Call. Unless you are invoking the module many times, there won't be a noticable difference in performance between a bound call and a dynamic call.

Mike Cravitz

NEWS/400 Technical Editor




I don't know what mean by invoking a module, but if you want to call a procedure in a module it must be in a program or service program. The procedure to call can be determined at run time. Any procedure in a service program can be called dynamically with a procedure pointer. The procedure name could be in a file or program variable.

Before calling the procedure in the service program you need to "activate" the service program. This can be done two ways. Call any procedure in the service program or use the activate it (you might just create an actsrvpgm) procedure which you bind into every service program). Or, you can activate the service program using the activate program API (This is easiest in C).

After the service program is active you can use the retrieve exports api to retrieve a pointer to the procedure you want to call dynamically.






I think the point you might be missing here is any program that invokes a procedure must know at bind time (before run time!) the name of that procedure unless you either use MI (as was suggested in a previous post) or you use one of the new APIs which allow you to invoke procedures in a service program without binding. Both of these run time techniques are a bit tricky. NEWS/400 has a web posting on how to invoke the APIs. However, it was written by a C programmer for C programmers. One of the things I want to do when I find the time is to figure out how to do this with RPG IV. Take care.

Mike Cravitz

NEWS/400 Technical Editor




Mike, here's an RPG IV procedure that uses the APIs to return a procedure pointer to a procedure in a service program. Note that the "SysPtr" type depends on an unsupported feature where a declared procedure pointer can be used to hold a system pointer. If you use this feature, I recommend that you use a similar technique (using LIKE) so that if the feature goes away and RPG defines a system-pointer type, you only have to change one place. (I wrote this procedure a while back when we first found out about this "feature" - thought I might as well share it. It would need some additional error-checking to be really useful - I leave that as an exercise for the keen programmer :-)

Barbara Morris IBM Toronto Lab RPG Compiler Development

      * File: GetProcPtr
      * Sample invocations for GetProcPtr:
      *    EVAL   ptr = GetProcPtr('MYPROC' : 'MYSRVPGM' : '*LIBL')
      *    EVAL   ptr = GetProcPtr('MYPROC' : Srvpgm : Library)
      *    EVAL   ptr = GetProcPtr(%TRIM(Procname) : SrvPgm : Lib)
      * (Note that the first parameter can't have trailing blanks)
     D GetProcPtr      PR              *   PROCPTR
     D   Procedure                  100A   VARYING CONST
     D   SrvPgm                      10A   CONST
     D   Library                     10A   CONST

      * File: GetPPtr
     H NOMAIN
      /COPY GetProcPtr

      * Define a "System-pointer" type.
     D SysPtr          S               *   PROCPTR  BASED(dummy)

      *-------------------------------------------------------------------
     P GetProcPtr      B                   EXPORT
      *-------------------------------------------------------------------
     D GetProcPtr      PI              *   PROCPTR
     D   Procedure                  100A   VARYING CONST
     D   Srvpgm                      10A   CONST
     D   Library                     10A   CONST

      *-----------------------------------------------------
      * Prototypes and templates for calling ResolveSystemPtr
      * (RSLVSP.H)
      *-----------------------------------------------------
     D RSLVSP2         PR                  EXTPROC('_RSLVSP2')
     D   Ptr                               LIKE(SysPtr)
     D   Template                          LIKE(RslvTemplt) CONST
     D RSLVSP4         PR                  EXTPROC('_RSLVSP4')
     D   Ptr                               LIKE(SysPtr)
     D   Template                          LIKE(RslvTemplt) CONST
     D   LibPtr                            LIKE(SysPtr) CONST

     D RslvTemplt      DS
     D   Gen_Mat_Id                  32A
     D     TypeSubtyp                 2A   OVERLAY(Gen_Mat_Id:1)
     D     Object                    30A   OVERLAY(Gen_Mat_Id:3)
     D   Req_Auth                     2A   INZ(AUTH_NONE)

      * See QSYSINC/MIH/MICOMMON for authority constants
     D AUTH_NONE       C                   X'0000'

      *-----------------------------------------------------
      * Prototype and templates for ActivateBoundProgram
      * (QLEAWI.H)
      *-----------------------------------------------------
     D ActBndPgm       PR                  EXTPROC('QleActBndPgm')
     D   SrvpgmPtr                         LIKE(SysPtr) CONST
     D   ActMark                     10I 0
     D   ABPInfo                           LIKE(ABP_Info)
     D   ABPInfoLen                  10I 0 CONST
     D   ErrorCode                         LIKE(ErrCode)

     D ABP_Info        DS
     D   ABP_Ret                     10I 0 INZ(%size(ABP_INFO))
     D   ABP_Avail                   10I 0
     D                                8A   INZ(*ALLX'00')
     D   ABP_ActGrp                  10I 0
     D   ABP_ActMark                 10I 0
     D                                7A   INZ(*ALLX'00')
     D   ABP_Flags                    1A
     D                                1A   INZ(*ALLX'00')

      *-----------------------------------------------------
      * Prototype and templates for ActivateBoundProgram
      * (QLEAWI.H)
      *-----------------------------------------------------
     D GetExport       PR                  EXTPROC('QleGetExp')
     D   SrvpgmMark                  10I 0
     D   ExportId                    10I 0 CONST
     D   NameLen                     10I 0 CONST
     D   ExportName                 100A   CONST
     D   ExportPtr                     *   PROCPTR CONST
     D   ExportType                  10I 0
     D   ErrorCode                         LIKE(ErrCode)

     D EX_NOT_FOUND    C                   0
     D EX_PROC         C                   1
     D EX_DATA         C                   2
     D EX_NO_ACCESS    C                   3

     D ErrCode         DS
     D   ErrProv                     10I 0 INZ(0)

      *-----------------------------------------------------
      * Local Variables
      *-----------------------------------------------------
     D LibPtr          S                   LIKE(SysPtr)
     D SrvpgmPtr       S                   LIKE(SysPtr)
     D ActMark         S             10I 0
     D ProcPtr         S               *   PROCPTR
     D ExportType      S             10I 0

      *-----------------------------------------------------
      * First, get the pointer to the service program
      *-----------------------------------------------------
     C                   IF        Library = '*LIBL'
      *   They specified *LIBL
     C                   EVAL      TypeSubtyp = x'0203'
     C                   EVAL      Object = Srvpgm
     C                   CALLP     RSLVSP2(SrvpgmPtr : RslvTemplt)

     C                   ELSE
      *   They specified the library ...
      *      Get the pointer to the library
     C                   EVAL      TypeSubtyp = x'0401'
     C                   EVAL      Object = Library
     C                   CALLP     RSLVSP2(LibPtr : RslvTemplt)
     C
      *      Get the pointer to the service program
     C                   EVAL      TypeSubtyp = x'0203'
     C                   EVAL      Object = Srvpgm
     C                   CALLP     RSLVSP4(SrvpgmPtr : RslvTemplt : LibPtr)
     C                   ENDIF

      *-----------------------------------------------------
      * Now, activate the service program
      *-----------------------------------------------------
     C                   CALLP     ActBndPgm(SrvpgmPtr : ActMark :
     C                                       ABP_Info : %size(ABP_Info) :
     C                                       ErrCode)

      *-----------------------------------------------------
      * Finally, get the procedure pointer
      * We're using nameLen+name rather than export-number
      * so we pass 0 as the export number.
      *-----------------------------------------------------
     C                   CALLP     GetExport(ActMark : 0 :
     C                                       %len(Procedure) : Procedure :
     C                                       ProcPtr : ExportType :
     C                                       ErrCode)

      *-----------------------------------------------------
      * Return the procedure pointer
      *-----------------------------------------------------
     C                   IF        ExportType = EX_PROC
     C                   RETURN    ProcPtr
     C                   ELSE
     C                   RETURN    *NULL
     C                   ENDIF

     P GetProcPtr      E


Here's my test program. I created two service programs each containing a procedure called ABC - the procedures just DSPLY the names of their service program.

      * File GetPPtrT
      /COPY GetProcPtr
     D ptr             s               *   PROCPTR
     C     *entry        plist
     C                   parm                    srvpgm           10
     C                   parm                    lib              10
     C                   eval      ptr = GetProcPtr('ABC':srvpgm:lib)
     C                   callb     ptr
     C                   seton                                        lr






Other tips in this category:

Click here to see all categories.

Socket Programming And Timeout Issues
Deleting Duplicate Records From A Table
What are data queues and how to use
Retrieving SMTP Name
RPGLE example for Dynamic Screen Manager API
Calling APIs from CL - with examples!
Compare two strings in RPG character by character
How to search all pgms in QCLSRC for a keyword
Retrieve Database File Description (QDBRTVFD) API
How to redirect the output to STDERR from RPG-IV
Using Multiformat Logical To Join 2 Identical File
D-Spec *LIKE DEFN
RPG: Converting Character to Decimal
Example of ILE RPG CGI Program
Handling ILE RPG Numeric Overflow
Help with Subfile Programming in RPG III
Zoned parameter in ILE RPG
What's the best way to do modulus in CL?
RPG Nesting Source Print Utility
More on changing the SIGNON screen
A silly ILE RPG question
Calling Validation List API From ILE RPG
Soft Coding Module Names
RPG Multidimensional Arrays in Action
Build a Page-Equals-Size Lookup Window
Procedures within an ILE RPG program
Break msg from RPG
Source Debugger for batch jobs
RPGLE debugging
Timing out display sessions in DDS
Building Dynamic Stored Procedures
Put Message in System Log
Dynamic RPGSQL
Randomize function for the AS/400
What's the fastest way to do a simple RPG lookup?
First time Data queue application in RPG
Print file overflow in ILE RPG
Mapping Fields To Arrays in ILE RPG
Named inidicators
STRQMQRY: comparision operator '=' isn't correct?!
DSPDTAARA to an outfile - possible?
PCL ESC codes in RPG
Sharing DB files between two AS/400s
Help: AS/400 subfiles
How do you change the signon screen?
Determining Even/Odd Values in queries
Get day of the week in RPG
Convert UPPERCASE to lowercase
RPG IV help using APIs
Help with data area API
Detecing IFS Files from RPG
SQL in a CL program
Calling AS/400 APIs from ILE RPG
CVTDAT command to convert an *MDY to a *LONGJUL
CPYSPLF Automation
Subfile Window background problem
Using IFS APIs w/ ILE RPG
Packed or unpacked fields?
QRYDFN to source and back
What does the "optimize" parm do?
Determining the calling program
Sockets in RPG?
Sorting a user space
OVRDBF and SECURE() keyword in an ILE environment
RPG record locking
RPG Differences: V2R3 to V3R2 upgrade
Getting the relative record number (RRN)
What is the longest parameter usable in RPG?
A C function that returns a string to an RPG pgm
Problems with ZADD *ZEROS
Can you highlight code in SEU?
Reusing deleted records - OK?
Is there an easy way to change edit codes?
Help - Windowed Subfiles
Logical Files and DDS
AS/400 'machine language' - MI Programming
Library lists and performance
How to use ERRSFL
Updating in CL
Record lock wait time
Message subfile problem
Physical File Joins
CL: Copying User Profiles
Commands and PARM
ILE RPG, RPG IV, vs. RPG/400
RPG and subfiles
Multiple subfiles
Field masking for passwords
SFLMODE keyword in an ILE program
Subfile size
Color coding records in a subfile
MSGLINE in windows
Controlling cursor movement on a display file
API returns error! Why?
Put an RPG Program on the Web
Variable length records in RPG
Differences Between RPG400, RPG IV, and ILE RPG


You are at a news400.com site.
Contact Us | Report Bugs | Submit Comments/Suggestions | Read Site Use Agreement | Read Privacy Policy
Copyright © 2000 Duke Communications International.
This site is best viewed with the latest versions of Netscape or Internet Explorer, 800 x 600 resolution (or higher), and at least 256 colors.
Duke Communications   NEWS/400 | 29th Street Press | Business Finance | DominoPro | Selling AS/400 Solutions | SQL Server Magazine | Windows NT Magazine