Calling REXX from COBOL using REXX SAA API using Cygwin in Windows

Submitted by Dickens A S on Fri, 09/04/2020 - 12:44

Embed inside COBOL code

Inline REXX code as string in COBOL code can be passed to REXX SAA API via C Code

rexxsaa.h is a c Library offers API to invoke REXX from C.

REXX is almost like COBOL it is very useful code to be used as macro in MVS system.

Below code explains how to do it.

#include <stdio.h>
#include <string.h>
#include <rexxsaa.h>

int ocrexxcmd(char *cmds, char *args, char *resfield, int reslen, short *result) {
    APIRET rexxapiret;
    RXSTRING retstr;
    RXSTRING arglist[1];
    RXSTRING instore[2];
    short rexxret = 0;

    int ignore = 0;

    /* For syntax check, no evaluate, taken from 8.4 of the Regina3.4 pdf */
    arglist[0].strptr = "//T";
    arglist[0].strlength = 3;

    arglist[0].strptr = args;
    arglist[0].strlength = strlen(args);

    /* Move the command(s) to the instore array */
    instore[0].strptr = cmds;
    instore[0].strlength = strlen(cmds);
    instore[1].strptr = NULL;
    instore[1].strlength = 0;

    /* Call Rexx. Use argcount 1 and &arglist to call syntax check */
    retstr.strptr = NULL;
    retstr.strlength = 0;
    rexxapiret = RexxStart(1, (PRXSTRING)&arglist, "FILLER",
                              (PRXSTRING)&instore, "COMMAND" /* NULL */,
        RXCOMMAND, NULL, &rexxret, &retstr);

    /* set result back to GnuCOBOL */
    memset(resfield, ' ', reslen);
    if (rexxapiret == 0) {
        memcpy(resfield, retstr.strptr,
              (retstr.strlength > reslen) ? reslen : retstr.strlength);
        *result = rexxret;
    }

    /* Let Rexx do all the memory alllocation */
    if (instore[1].strptr != NULL) { ignore = RexxFreeMemory(instore[1].strptr); }
    if (retstr.strptr != NULL) { ignore = RexxFreeMemory(retstr.strptr); }

    return (int)rexxapiret;
}
/**/

COBOL Code

       identification division.
       program-id. testrexx.

       data division.
       working-storage section.
       01 newline constant as x"0a".
       01 trimmer              usage binary-long.
       01 apicode              usage binary-long.
       01 resultcode           usage binary-short.
       01 argument             pic x(256) value 'OC1.1 args' & x"00".
       01 cmds                 pic x(1024).
       01 rexxstring           pic x(1048576).
       procedure division.

       move "rc=10" & x"0a" &
            "col=0" & x"0a" &
            "ol=''" & x"0a" &
            "Do i=1 To rc-1" & x"0a" &
            "col=0" & x"0a" &
            "Do j=i*(i-1)/2+1 to i*(i+1)/2" & x"0a" &
            "col=col+1" & x"0a" &
            "ol=ol '*'" & x"0a" &
            "end" & x"0a" &
            "ol=ol '0a'x" & x"0a" &
            "end" & x"0a" &
            "return ol" & x"00" to cmds.
       compute
           trimmer = function length(function trim(cmds))
       end-compute
       call "ocrexxcmd"
           using
               by reference cmds
               by reference argument
               by reference rexxstring
               by value function length(rexxstring)
               by reference resultcode
           returning apicode
       end-call
       display function trim(rexxstring trailing) end-display
       goback.
       end program testrexx.

Compile C Code using cobc

$ cobc -c -lregina ocrexx.c

Compile COBOL Code including the .o file from the above compile

$ cobc -x -lregina testrexx.cob ocrexx.o

Run the COBOL EXE

$ ./testrexx
 *
 * *
 * * *
 * * * *
 * * * * *
 * * * * * *
 * * * * * * *
 * * * * * * * *
 * * * * * * * * *

End Of Article

Add new comment