=======================================================================
                README for EAGSTC and EAGSTCR:
                the C/C++ -> REXX/370 MVS Stubs
=======================================================================

   contents:

         1)    Introduction
         2)    Requirements
         3)    Installation
         4)    Overview / Background
         5)    Compiling & linking a REXX function
         5.1)     with the EAGSTC stub
         5.2)     with the EAGSTCR stub
         6)    Return values
         6.1)     EVALBLOCKs
         6.2)     EVALFREE routine
         6.3)     Error codes
         7)    Samples
         8)    Pitfalls and limitations
         9)    Getting Help

=======================================================================
1)    Introduction
=======================================================================

   Sometimes life could be so easy, even for hardcore C programmers,
   if they'd be able to do some nitty little system task by simply
   using REXX, while coding the main processing in C/C++.

   ...well...life IS that easy:

   :-)  Calling the external REXX function seems as if it was a regular
        call to an external function, requiring OS linkage.

   :-)  Bind your C/C++ application with that compiled external REXX
        function into one single load module!

   :-)  The external function's prototypes may declare variable length
        argument lists.

   ...one feature you might expect is NOT offered:

   :-(  No support for 'by-reference' parameter passing, i.e. you can
        only get back information from the called function in form of
        a return value that is explicitly returned by that function.

=======================================================================
2)    Requirements
=======================================================================

   This software is designed for the following platform:

      - OS/390

   You need to have the following products installed:

      -  C/C++ compiler for OS/390

      -  REXX/370 compiler

   if you want to achieve increased runtime performance for the
   compiled REXX you also need:

      -  REXX/370 library for OS/390

   otherwise the ALTERNATE library, shipped with the REXX/370 compiler
   product, suffices (but you need to compile the REXX functions with
   the ALTERNATE option in effect).

=======================================================================
3)    Installation
=======================================================================

   1. After downloading the CRStub.zip package unpack the ZIP file on
      a workstation (AIX, Linux, Win32). It contains:

      -  Assembler sources:
         -  eagstc.asm     -> non recursive C/C++ -> REXX stub
         -  eagstcr.asm    ->     recursive C/C++ -> REXX stub
         -  eagstefp.asm   -> original EFPL  REXX -> REXX stub
         -  evalfree.asm   -> module to free allocated EVALBLOCKS

      -  JCL job to build the load module versions of the EAGSTC
         and EAGSTCR stubs.

      -  Samples in the subdirectory '.../samples'.

      -  Documentation - this Readme file and the samples.

   2. If you do not already have a data set for ASSEMBLER sources, you
      have to allocate one - you can use the following characteristics:

         Organization  . . . : PO
         Record format . . . : FB
         Record length . . . : 80
         Block size  . . . . : 27920

      Now you are ready to upload the files
         EAGSTC.ASM
         EAGSTCR.ASM
         EAGSTEFP.ASM
         EVALFREE.ASM
      into that data set (member names of course without '.ASM').

   3. If you do not already have a data set for LOAD modules, you have
      to allocate one - you can use the following characteristics:

         Organization  . . . : PO
         Record format . . . : U
         Record length . . . : 0
         Block size  . . . . : 23200

   4. If you do not already have a data set for JCL jobs, you have to
      allocate one - you can use the following characteristics:

         Organization  . . . : PO
         Record format . . . : FB
         Record length . . . : 80
         Block size  . . . . : 27920

   5. Adapt the JCL job '_as.jcl' to your configuration:

      -  Copy '_as.jcl' to 'as.jcl' and edit it on your workstation.

      -  The job card depends on your JES installation. Ask your
         system administrator if you don't know what should look like.

      -  All '__uid__' strings in the job have to be replaced with
         the data set qualifiers you chose for allocating your own
         assembler source and load module data sets.

      -  'ASM' has been used as library type qualifier for assembler
         sources, and 'STUB' for the load modules - if your library
         type qualifiers are different adapt them also.

      -  The assemby step needs the ddname SYSLIB where it searches
         for assembler macros. You'll also have to adapt the data set
         name (SYS1.MACLIB) given on this DD statement, if the job
         stops with a JCL error, stating that the SYSLIB data set could
         not be found or the assembler cannot resolve the macros.

      -  Upload this job into your JCL job data set.

   6. Submit this job - it should end with a maximum RC = 4.
      The JESMSGLG ddname in the SDSF job output should be similar
      to the following (shortened) one:

          STEPNAME PROCSTEP    RC   EXCP   CONN    TCB    SRB  CLOCK
          ALLOC                00      0      0    .00    .00     .0
          ASM0                 00    107    215    .00    .00     .0
          L0                   00     32     66    .00    .00     .0
          ASM1                 00    411    905    .00    .00     .0
          L1                   04     34     65    .00    .00     .0
          ASM2                 00    338    711    .00    .00     .0
          L2                   04     31     63    .00    .00     .0
          ASM3                 00    171    341    .00    .00     .0
          L3                   04     57     99    .00    .00     .0

      The RC = 4 (warning) origins from the linkage editor steps for
      EAGSTC, EAGSTCR and EAGSTEFP:

      IEW2454W 9203 SYMBOL EAGOBJ UNRESOLVED.
                                 NO AUTOCALL (NCAL) SPECIFIED.

      This does simply mean that there is an external reference to
      'EAGOBJ' that has not been resolved by now - this symbol will be
      resolved when linking the stub with a compiled REXX function.
      Since the 'NCAL' option has been specified this unresolved
      external reference causes only a warning message else a severe
      error message would be raised.

   7. Now, with the assembled and linked versions of the stubs you
      are ready to link C/C++ modules with compiled REXX functions!

      For testing purposes you can leave the load modules in your
      private data set and access them from there.
      However, if you want every user to have access to the new
      functionality the stub modules have to be installed on the
      corresponding REXX/370 installation data set (...SEAGLMD).

=======================================================================
4)    Overview / Background
=======================================================================

   There are 2 versions of this stub:

   1. EAGSTC:  Lets you call a compiled REXX function from a C/C++
               program - but this REXX function may NOT call itself.

   2. EAGSTCR: Same as EAGSTC but additionaly supporting being called
               from another or the same (recursive) REXX function.
               Every time it gets invoked it has to decide from where,
               REXX or C/C++.

   After the appropriate stub module is linked with compiled REXX
   object code it can be linked with compiled and pre-linked C/370
   code, that contains unresolved external references.

   -  Information on how to compile the external REXX functions and
      link them with one of the stubs is described in 5.1 and 5.2.
   -  For information on how compile and pre-link C/C++ sources refer
      to the samples provided in this package (see 6.) and your
      compiler's and binder's User's Guide and References.

   The result is one executable load module including the C/C++ as well
   as the compiled REXX and the stub code and thus having all externals
   resolved.

   |---------|    When C/C++ calls a function being coded in REXX it
   |         |    will in reality jump (BASR) to the beginnig of the
   |  C/C++  |    stub code. The stub translates the parameter list
   |         |    from a standard OS parmlist to an REXX EFPL
   |---------|    (extended function parameter list), set up the REXX
   |         |    environment and then call IRXEXEC to execute compiled
   |  Stub   |    REXX code - it branches to the compiled 'preloaded'
   |         |    REXX code (since it's contained in the load module,
   |---------|    that already resides in memory, it's said to be pre-
   |         |    loaded). After execution the stub prepares the
   |  REXX   |    outcome (return value or abend), so that the calling
   |         |    C/C++ program can handle it.
   |---------|

   You need a prototype for each external REXX function in the C/C++
   program to enable the compiler to check the argument types for each
   invocation of that function already at compile time:

      extern <return_type> <rexx_function_name>(<c_parm_list>);

      <rexx_function_name>
         Function names are limited to 8 characters. This limitation is
         introduced with the 8 character limitation for CSECT names.
         You may choose lower and upper case characters for the
         function name as you like.

      <return_type>
      <c_parm_list>
         Only the types VOID or CHAR* may be used for declaration of
         arguments and the return type. Since REXX treats every
         variable's content as a string the char* and void types should
         be sufficient.

      Some prototype samples:

         extern void  extFun_0(void);
         extern void  extFun_1(char*);
         extern char* extFun_2(void);
         extern char* extFun_3(char*, char*);

      You may even declare the external function to have a variable
      length argument list using the ',...' syntax:

         extern char* extFun_4(char*, ...);

      -> REXX can gather the actual number of passed arguments using
         the ARG built-in function (see CRexx4.c and ArbArgs.rex for
         an example).

   And, secondly, you need to tell the C/370 compiler that it has to
   generate a standard OS parameter list (-> OS-linkage) when calling
   such an external REXX function:

      #pragma linkage(<rexx_function_name>, OS)

   With the #pragma you tell the C compiler that this function wants
   its arguments passed using MVS's standard calling convention. That
   means for instance that register 0 points to a list of pointers,
   that point to the actual parameter values, with the end of this
   pointer list being indicated by a pointer having the high order bit
   (HOB) set (=1). However, you don't need any knowledge about Asm in
   the MVS environment to make use of this stubs...so don't worry...

=======================================================================
5)    Compiling & linking a REXX function
=======================================================================
5.1)     with the EAGSTC stub
=======================================================================

   If the original REXX function member is named 'ABC':
      __uid__.EXEC(ABC)
   and you also have following PO data sets allocated:
      __uid__.OBJS    - for object modules
      __uid__.LOAD    - for load modules
   and
      SYS.REXX.V130.
   is the data set prefix, where the REXX compiler can be found,
   then use following JCL statements:

   compile step:
   -------------
       //COMP    EXEC PGM=REXXCOMP,
       //             PARM='NOCEXEC OBJECT XREF'
       //STEPLIB   DD DSN=SYS.REXX.V130.SFANLMD,DISP=SHR
       //SYSTERM   DD SYSOUT=*
       //SYSPRINT  DD SYSOUT=*
       //SYSIN     DD DSN=__uid__.EXEC(ABC),DISP=SHR
       //SYSPUNCH  DD DSN=__uid__.OBJS(ABC),DISP=SHR

   link edit step:
   ---------------
       //LINK    EXEC PGM=HEWL,
       //             PARM='LIST,MAP,RENT,AMODE=31,RMODE=ANY'
       //SYSUT1    DD UNIT=SYSDA,SPACE=(1024,(200,20))
       //SYSPRINT  DD SYSOUT=*
       //SYSLMOD   DD DSN=__uid__.LOAD(ABC),DISP=SHR
       //OBJS      DD DSN=__uid__.OBJS,DISP=SHR
       //SYSLIB    DD DSN=SYS.REXX.V130.SEAGLMD,DISP=SHR
       //SYSLIN    DD *
          CHANGE   EAGSTUB(ABC),EAGOBJ($ABC)
          INCLUDE  SYSLIB(EAGSTC)
          CHANGE   ABC($ABC)
          INCLUDE  OBJS(ABC)
          ENTRY    ABC
       /*

   By using the two CHANGE cards we achieved the following:
   -  the first one replaced all occurances of
         'EAGSTUB' with 'ABC' and
         'EAGOBJ'  with '$ABC'
      in the stub's code - so the stub is now named after the original
      REXX function and its reference to the compiled REXX function
      gets a new name (prefixed with '$' and cut in length to a maximum
      of 8 characters).
   -  the second one replaced all occurances of
         'ABC' with '$ABC'
      in the compiled REXX function's code. BUT that means also any
      references and therefore a recursive call in the REXX function
      will also have been replaced and directly resolve to the compiled
      REXX function's CSECT. This won't work, since for calling an
      external compiled REXX functions from another REXX program you
      need to link it with the EFPL stub.

   => for external REXX functions that will be called by other REXX
      functions or by themselves recursively, use the EAGSTCR stub.

=======================================================================
5.2)     with the EAGSTCR stub
=======================================================================

   If the original REXX function member is named:
       __uid__.EXEC(ABC)
   and you also have following PO data sets allocated:
       __uid__.EXTF    - for renamed external functions
       __uid__.OBJS    - for object modules
       __uid__.LOAD    - for load modules
   and
       SYS.REXX.V130.
   is the data set prefix, where the REXX compiler can be found, then
   use following JCL statements:

   copy step:
   ----------
       //COPY    EXEC PGM=IEBCOPY
       //SYSPRINT  DD SYSOUT=*
       //SRC       DD DSN=__uid__.EXEC,DISP=SHR
       //TRG       DD DSN=__uid__.EXTF,DISP=SHR
       //SYSIN     DD *
         COPY     OUTDD=TRG,INDD=SRC
         SELECT   MEMBER=((ABC,$ABC))
       /*

   Copying the REXX function member and giving it a new name is
   necessary to allow recursive references (they still use the original
   function name) to resolve to the stub code's CSECT instead to the
   beginning of the REXX function's object code.

   compile step:
   -------------
       //COMP    EXEC PGM=REXXCOMP,
       //             PARM='NOCEXEC OBJECT XREF DLINK'
       //STEPLIB   DD DSN=SYS.REXX.V130.SFANLMD,DISP=SHR
       //SYSTERM   DD SYSOUT=*
       //SYSPRINT  DD SYSOUT=*
       //SYSIN     DD DSN=__uid__.EXTF($ABC),DISP=SHR
       //SYSPUNCH  DD DSN=__uid__.OBJS($ABC),DISP=SHR

   Be sure to use the "DLINK" option for compilation.

   link edit step:
   ---------------
       //LINK    EXEC PGM=HEWL,
       //             PARM='LIST,AMODE=31,RMODE=ANY,RENT,MAP'
       //SYSUT1    DD UNIT=SYSDA,SPACE=(1024,(200,20))
       //SYSPRINT  DD SYSOUT=*
       //SYSLMOD   DD DSN=__uid__.LOAD(ABC),DISP=SHR
       //OBJS      DD DSN=__uid__.OBJS,DISP=SHR
       //SYSLIB    DD DSN=SYS.REXX.V130.SEAGLMD,DISP=SHR
       //SYSLIN    DD *
          CHANGE   EAGSTUB(ABC),EAGOBJ($ABC)
          INCLUDE  SYSLIB(EAGSTCR)
          INCLUDE  OBJS($ABC)
          ENTRY    ABC
          NAME     ABC(R)
       /*

   By using the CHANGE card we replaced all occurances of
      'EAGSTUB' with 'ABC' and
      'EAGOBJ'  with '$ABC'
   in the stub's code - so the stub is now named after the original
   REXX function and its reference to the real compiled REXX function
   gets the name used in the copy step.

=======================================================================
6)    Return values
=======================================================================
6.1)     EVALBLOCKs
=======================================================================

   The REXX runtime system, REXX/370 library or alternate library,
   allocate a memory block, called EVALBLOCK, that holds the result
   returned by a RETURN or EXIT statement from a REXX function.
   The C->REXX stubs initialize such EVALBLOCKS with a size that is
   too small to hold any return value, but big enough to gather the
   information of how many bytes are necessary for the return value.
   So when IRXEXEC has finished processing the external function, the
   stubs call IRXRLT to obtain the complete EVALBLOCK.
   That means, that each time you call an external REXX function from
   your C/C++ application, and this function returns a result value,
   a memory block of the size 16 + (length of result) bytes has been
   allocated.

=======================================================================
6.2)     EVALFREE routine
=======================================================================

   To avoid that your storage gets completely filled up you have to
   free this blocks. You can use the provided EVALFREE module.
   EVALFREE provides a secure way to get rid of EVALBLOCK memory blocks
   that have been allocated by EAGSTC or EAGSTCR for returning a result
   from an external REXX function.
   The stubs receive the EVALBLOCKs from IRXRLT and mark these blocks
   with the message 'REXX IS COOL' - so the EVALFREE module can check
   whether a given pointer is really one that has been returned by
   one of these stubs.
   It is written in assembler and therefore also requires standard OS
   linkage parameter lists. To make this module available to your C/C++
   program you'll also have to declare this external symbol using the
   following #pragma statement and prototype:

      #pragma linkage(evalfree, OS)
      extern  int     evalfree(char*);

   If, for example, you have an external REXX function called 'longRet'
   that returns a string (char*) and you want to get rid of the
   allocated string, then use something like the following code:

      char *ptr = longRet("20");
      int    rc = evalfree(ptr);

   In case of success EVALFREE returns 0.
   In case of error   EVALFREE returns 1.

   For information on how to link this module with your application
   refer to the JCL jobs contained in the samples.

=======================================================================
6.3)     Error codes
=======================================================================

   To determine whether the result string pointer returned by the
   external REXX function is a valid char* pointer or just an error
   indicator, you have to check the high order bit (HOB).
   If the HOB is set that means an error has occured and the returned
   value is rather a description of the error that has happened than a
   pointer to character data.

   You can use something like the following macro 'IS_HOB_ON' to check
   if the HOB is set or not:

      #define IS_HOB_ON(ptr) ((long)ptr & 0x80000000 ? 1 : 0)

   There are 4 types of error indicators, recognizable by the low order
   4 bits of most significant byte of the returned 32 bit value - that
   is the second hex digit in hex representation of these 32 bit:

      81000000x0  -  memory shortage problem, a stub internal GETMAIN
                     request couldn't be satidfied.
      82000000x0  -  IRXINIT ended with error.
      8300####x0  -  IRXEXEC ended with error - the error code returned
                     by IRXEXEC is contained in the lower 2 bytes of
                     the return code (indicated by '####')
      84000000x0  -  IRXRLT  ended with error.

   If the REXX function terminated with an error you can obtain the
   REXX error code using the following code:

      char *ptr = longRet("20");
      if ((long)ptr & 0xFF000000 == 0x83000000)
      {
         printf("IRXEXEC ended with REXX error: %d\n",
                (long)ptr & 0x00FFFFFF) - 20000);
      }

   Refer to the header file CRStub.h for an example of how to deal with
   return values.

=======================================================================
7)    Samples
=======================================================================

   There are 7 samples provided in this package.
   For each of them there is besides the C/370 and REXX sources a JCL
   job that builds the final load module. These jobs themselves have
   been built using the RxMake utility, which can also be downloaded
   from our REXX family internet pages.

       |   C/370   |   REXX   | EAGSTC | EAGSTCR |   JCL   |  MAKE   |
   ----|-----------|----------|--------|---------|---------|---------|
    1. |  CREXX1   |  noParm  |   X    |         |  make1  |  samp1  |
   ----|-----------|----------|--------|---------|---------|---------|
    2. |  CREXX2   |  longRet |   X    |         |  make2  |  samp2  |
   ----|-----------|----------|--------|---------|---------|---------|
    3. |  CREXX3   |  sayn    |        |    X    |  make3  |  samp3  |
   ----|-----------|----------|--------|---------|---------|---------|
    4. |  CREXX4   |  longRet |   X    |         |  make4  |  samp4  |
       |           |  sayn    |        |    X    |         |         |
   ----|-----------|----------|--------|---------|---------|---------|
    5. |  CREXX56  |  arbArgs |   X    |         |  make5  |  samp5  |
   ----|-----------|----------|--------|---------|---------|---------|
    6. |  CREXX56  |  arbArgs |        |    X    |  make6  |  samp6  |
   ----|-----------|----------|--------|---------|---------|---------|
    7. |  CREXX7   |  reverse |   X    |         |  make7  |  samp7  |
   ----|-----------|----------|--------|---------|---------|---------|

=======================================================================
8)    Pitfalls and limitations
=======================================================================

   1.) passing NULL as value for char* type argument:

     Since the EAGSTCR stub provides support for both - being called
     from C/C++ and from REXX - it has to decide at runtime from where
     it actually has been invoked.
     You can trick the mechanism by passing NULL pointers as char*
     type parameters:
     -> in that case the stub will suppose being called from REXX,
        which will lead to an abend!
     -> just always use an empty string ("") instead of NULL.

   2.) longest return value length:

     The longest return value length is 2^32 = 4294967296 bytes.

=======================================================================
9)    Getting Help
=======================================================================

   The documentation used for developing this stubs was:

      -  IBM Compiler and Library for SAA REXX/370 - User's Guide and
         Reference                                 (SH19-8160)
      -  OS/390 V2R9.0 TSO/E REXX User's Guide     (SC28-1974)
      -  OS/390 V2R10.0 TSO/E REXX Reference       (SC28-1975)

   Visit our REXX family webpages at:

      http://www.ibm.com/software/ad/rexx/

   If you experience difficulties in using this package you can get
   help by writing an e-mail to:

      rexxhelp@vnet.ibm.com

   Also any suggestions for improvement or bug-reports are welcome.
   HAVE FUN WITH REXX!
