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

In Reference to the gnuCOBOL FAQ and How To

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

#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
 *
 * *
 * * *
 * * * *
 * * * * *
 * * * * * *
 * * * * * * *
 * * * * * * * *
 * * * * * * * * *

 

Add new comment