REXXMACS - Asm macro for REXX services REXXMACS is a set of macros to help you accessing REXX services from an assembler program. Most are for REXX variable access, but there are others. Two macros are required for seting up the environment - RXINIT and REXXMACS, the rest are used as needed. Two additional external macro SETREG and STRCOPY are required, get them here: https://harders-jensen.com/ REXXMACS is an assembler copybook, use as follows: Print off Copy RexxMacs Print on Overview REXXMACS Define data areas and dummy sections (required) RXEXEC Start a REXX pgm from a (non-TSO) program. RXINIT Setup interface (required) RXRETVAL Set return value RXSAY Say text RXSTACK Access the data stack RXSTEMGET Build stemname, then get data RXSTEMNAME Build stem name RXSTEMNUM Build stem number RXSTEMPUT Build stemname, then write data RXTERM Terminate with return code RXVDROP Drop (delete) a variable. RXVGET Get variable RXVGETDS Get variable directly to getmained area. RXVNEXT Get variables in sequence, not by name RXVPUT Write variable Detailed description of commands, incl samples Unless otherwise stated then 'addr' and 'len' operands can be actual - Actual address or value. 'literal' - Quoted text. (r) - Register containing value. F.addr - Load from fullword at 'addr'. H.addr - Load from unsigned fullword at 'addr'. Unsigned means that value can be from 0 to 65535. B.addr - Load from unsigned byte at 'addr'. Unsigned means that value can be from 0 to 255. RXINIT - Initialize REXX interface and optionally retrieve parameter(s). Syntax label RXINIT PARMAREA=addr | (addr,len) PARMLIST=((addr1,len11),..,(addrn,lenn)) PARMVECT=(addr,count) NOREXX=addr NOPARM=addr All parameters are optional. PARMAREA - copies the parameters area to a field in your program. PARMLIST - copies the parameters to fields generatd by the macro in the area generated by the REXXMACS DS call. You must supply name and length for each field. Each field will be preceeded by a 1-byte length field named field_DL. PARMVECT - For each parameter, store the address of the data and the length of the data. The hi-order bit of the last used pair is set to 1 (aka the VL bit). NOPARM - jump to this address if there is no parameter. NOREXX - jump to this address if the REXX anvironmant cannot be initilized. Registers before call r1 - from pgm start Registers after call r0 - zero if REXX was initialized, nonzero if not. r15 - length of data if PARMAREA was specified. Samples Copy 1st or only parameter to 'parmstr'. ereg 0,1 RxInit parmarea=parmstr lr r2,r15 length of data parmstr dc cl120 RexxMacs ds RexxMacs dsect Copy 1-3 only parameters to generated fields RxInit parmlist((verb,12),(parm1,20),(parm2,120)) llc r2,verb_dl length of verb Build name pointer and length pairs for 2 parameters RxInit parmvect=(prmvct,2) lm r2,r3,prmvct addr,length of 1st parm lm r4,r5,prmvct+8 addr,length of 2nd parm prmvct dc 4a(0) RXRETVAL - Setup return value. Syntax label RXRETVAL addr,len Sample mvc rcc,=c'12' set rc 12 mvi rcl,2 length of value llc r2,rcl RXRETVAL rcc,(r2) rcl dc al1(1) default length rcc dc cl8'0' default rc=0 RXSAY - Write text to screen. Syntax label RXSAY addr|text[,len] Sample RXSAY 'Just testing' use literal la r2,text llc r3,textl RXSAY (r2),(r3) use registers RXSAY text,b.textl use label and load byte textl dc al1(80) text dc cl80' ' RXSTACK - Access the REXX data stack. Syntax label RXSTACK what[,DATA=(addr,len),LR=reg what - function PULL, PUSH, QUEUE or QUEUED. DATA - address and length of data for PULL, QUEUE, PUSH and QUEUED. Must be a fullword if QUEUED. LR - register (2-12) to get length of returned data. Registers after call r15 return code When function is PULL and DATA=null r0 data length r1 data address When function is PULL and DATA=something r0 rc from strcopy 1 data truncated, field zrx_datal contains the original width. r1 data address When function is QUEUED r1 count Sample RxStack queued r1 = count lr r7,r1 RxStack pull lr r3,r15 rc lr r4,r1 -> data lr r5,r0 length RxStack queue,data=(wrk1k,(r2)) RXSTEMGET - Build stemname, then get data You can supply the full name using the NAME operand, or make the macro build the name from the BASE and the NUM or PNUM operands. Syntax label RXSTEMGET NAME=,BASE=,NUM=|PNUM=,DATA= NAME - address and length of the variable name. STEMA - address and length of the variable name build-up area. It must be wide enough to hold both the basename and the suffix. BASE - address and length of the base, incl the dot. DATA - address and length of the data buffer. NUM - the binary number to use for building the stem name. PNUM - address of the packed decimal number to use for building the stem name. Registers after call r0 - Size of returned data. r15 - rc Sample mvc varname,=c'NYVAR' RxStemGet name=(varname,5),data=(vardata,l'vardata) lr r3,r0 data length ap stmpnum,=p'1' RxStemGet stema=varname,base=(stmbase,l'stmbase), pnum=stmpnum,data=(vardata,l'vardata) lr r3,r0 data length l r1,stmbnum ahi r1,1 st r1,stmbnum RxStemGet stema=varname,base=(stmbase,l'stmbase), num=f.stmbnum,data=(vardata,l'vardata) lr r3,r0 data length varname ds cl100 stmbase dc c'WORKSTEM.' stmpnum dc pl4'0' stmbnum dc a(0) vardata dc cl100'Kilroy was here' RXSTEMNAME - Build stemname Syntax label RxStemName BASE=,STEMA=,NUM=|PNUM= STEMA - address and length of the variable name build-up area. It must be wide enough to hold both the basename and the suffix. BASE - address and length of the base, incl the dot. NUM - the binary number to use for building the stem name. PNUM - address of the packed decimal number to use for building the stem name. Registers after call r0 - Size of generated name Sample ap stmpnum,=p'1' RxStemName stema=varname,base=(stmbase,l'stmbase), pnum=stmpnum lr r7,r0 length of name varname ds cl100 stmbase dc c'WORKSTEM.' stmpnum dc pl4'0' RXSTEMNUM - Build a decimal number stripped of leading zeroes. Syntax label RxStemNum addr,len,BIN=|DEC= addr - address of an area wide enough to hold the number. bin - a binary number. dec - address of a packed decimal number. Registers after call r15 - Width of generated number. Sample l r4,bnum RxStemNum varnum,bin=(r4) RxStemNum varnum,dec=pnum bnum dc a(1234) pnum dc pl4'0' RXSTEMPUT - Build stemname, then write variable. You can supply the full name using the NAME operand, or make the macro build the name from the BASE and the NUM or PNUM operands. Syntax label RXSTEMPUT NAME=,STEMA,BASE=,NUM=|PNUM=,DATA= NAME - address and length of the variable name. STEMA - address and length of the variable name build-up area. It must be wide enough to hold both the basename and the suffix. DATA - address and length of the data. BASE - address and length of the base, incl the dot. NUM - the binary number to use for building the stem name. PNUM - address of the packed decimal number to use for building the stem name. Registers after call r15 - rc Sample mvc varname,=c'NYVAR' RxStemPut name=(varname,5),data=(vardata,l'vardata) ap stmpnum,=p'1' RxStemGet name=varname,base=(stmbase,l'stmbase), pnum=stmpnum,data=(vardata,l'vardata) l r1,stmbnum ahi r1,1 st r1,stmbnum RxStemGet name=varname,base=(stmbase,l'stmbase), num=f.stmbnum,data=(vardata,l'vardata) varname ds cl100 stmbase dc c'WORKSTEM.' stmpnum dc pl4'0' stmbnum dc a(0) vardata dc cl100'Kilroy was here' RXVDROP - Drop (delete) a variable. Syntax label RXVDROP NAME= NAME - address and length of the variable name. RXVGET - Copy a variable to program area. Syntax label RXVGET NAME=,DATA= NAME - address and length of the variable name. DATA - address and length of the data buffer. Registers after call r0 - Size of returned data. r15 - rc Sample mvc varname,=c'NYVAR' RxVGet name=(varname,5),data=(vardata,l'vardata) lr r3,r0 data length vardata dc cl100'Kilroy was here' RXVGETDS - Copy a variable to getmained storage. The area is 31-bit. You must FREEMAIN the storage yourself after usage. Syntax label RXVGETDS NAME=addr|'text',AR=areg,LR=lreg,PFXL=len name same as for the rxvget macro. areg register 2-12 to contain the address. lreg register 2-12 to contain the length. pfxl length of prefix in new buffer (area before var-data) as number, equated or (reg). Registers after call areg address of getmained area (=prefix) lreg length incl prefix Sample RxVGetDs name='TESTVAR1',ar=r2,lr=r3,pfxl=varpfxl ahi r3,-1 mvc data,(*-*),0(r2) ex r3,*-6 . . . data ds cl120 varblk dsect varpfx ds 0a varlen ds a varpfxl equ *-varpfx vardata ds 0c RXVNEXT - Get variables in sequence or get statistics. Retrieve all REXX variables from current environment. Note that if you use any other REXX variable access it will terminate RXVNEXT, this is an unfortunate IBM restriction. Get statistics for REXX variables. The macro must read all variables to get the information, though no actual data is written to the program. Syntax label RXVNEXT NAME=,DATA= RXVNEXT STATS,NL=,DL=,TDL=,COUNT= NAME - address and length of the variable name. DATA - address and length of the data buffer. NL - register to contain the size of the widest variable name. DL - register to contain the size of the largest variable data. TDL - register to contain the combined size of all data. Must be 0 before first call. COUNT - register to contain the numer of variables. Both the name and the data fields will be filled in by the function. You can test field zrx_shvret for bit zrx_eof to determine end of list, or test r15 for value 1. You can test field zrx_shvret for bit zrx_trubc to detect truncation, or test r15 for value 2. Registers after call r15 - return code, 1 means that the variable retrieved is the last, 2 means that the name or the data was truncated. If rc=2 then field zrx_ShVbVnl contains the required name buffer length and field zrx_ShVbVbl contains the required data buffer length. r0 data length r1 name length If trunction occurred, then you can use the call RXVGET NAME='0',DATA=(0,0) to reset internal values before you acquire a bigger name or data buffer and start RXVNEXT all over again. Sample getnext RxVNext name=(namebfr,l'namebfr),data=(databfr,l'databfr) cfi r15,1 j eof cfi r15,2 j trunc lr r2,r0 copy data length lr r3,r1 copy name length namebfr dc cl40' ' databfr dc cl100' ' RXVPUT - Write program area to variable. Syntax label RXVPUT NAME=,DATA= NAME - address and length of the variable name. DATA - address and length of the data buffer. Registers after call r15 - rc Sample mvc varname(5),=cl5'NYVAR' mvc vardata(15),=cl15'Kilroy was here' la r2,5 la r3,15 RxVPUt name=(varname,(r2)),data=(vardata,(r3)) varvar dc cl40' ' vardata dc cl100' ' RXEXEC - Start a REXX pgm from a program 2 calls must be made - DS and CALL. Syntax lbl RXEXEC NAME=name,DD=dd,SUB=sub,ARGB=argb,MODE=mode, [,PARM=parm] lbl RXEXEC BUILD,NAME=name,DD=dd,SUB=sub,ARGB=argb,MODE=mode, [,PARM=parm] lbl RXEXEC CALL[,PARM=parm] RXEXEC DS,EVBSZ=,ARGN=,WRKSZ= RXEXEC SETPARM,PARM=addr | (addr,len) none Fill in control block data and link to IRXEXEC. BUILD Fill in control block data. CALL Call IRXEXEC using pre-built control blocks. DS Define control blocks. SETPARM Add one parm to the call data. name Required membername to execute. Must be 8 chars, need not be uppercase. dd Optional ddname to load from. Must be 8 uppercase chars. sub Optional subcom. Must be 8 uppercase chars. argb Address of argument list, default is the block created by RXEXEC DS. argn Number of arguments. The macro will add space for the terminator. Note that you must update the argument fields and terminator yourself, see the sample below. evbsz Size of the data area in the generated evaluation block. Default is 400. wrksz Size of generated work ara for call, must be ge 6144 if defined. Optional. mode 0 - exec is being invoked as a command. 1 - exec is being invoked as a function call - default. 2 - exec is being invoked as a subroutine, i.e. CALL. See notes for the parm 3 below. Sample RxExec name=execname,parm=arg1 lr r5,r15 return code l r3,zrx_ex_evalb+8 retval length bctr r3,0 mvc retval(*-*).zrx_ex_evalb+16 ex r3,*-6 . . . arg1 dc cl40'This is argument 1' argument 1 retval dc cl100' ' execname dc cl8'RxExecPg' RXEXEC ds,evbsz=400,argn=4,wrksz=8*1024,mode=1 REXXMACS DS . . . REXXMACS DSECT REXXMACS - Generate data- and dummy sections Both data- and dummy sections are required. Syntax RexxMacs ds Generate data section RexxMacs dsect Generate dummy section Sample program snippet RxInit parmstr=arg1 r1 from pgm start is required ltr r0,r0 jnz *not REXX* RxSay 'Howdy folks' RxVget name='testvar',data=arg2 RxSay arg2pt,l'arg2pt+larg2 mvc rc,=c'04' RxRetval rc,l'rc set return rc '00' . . . RexxMacs ds initmsg dc c'Howdy folks' rc dc c'00' arg1 dc cl240' ' arg2pt dc c'testvar=' arg2 dc cl120' ' . . . RexxMacs ds RexxMacs dsect More samples Build a stemname using a decimal qualifier, then write the var. ap stmnum,=p'1' RxStemname base=(basename,l'basename), pnum=stmnum,stema=wrkname lr r2,r0 copy length of name RxVput name=(wrkname,(r2)),data=text1 wrkname ds cl200 basename dc c'NAMES.' stmnum dc pl4'0' text1 dc cl20'Kilroy was here' SAY text in string with a length in gr2 RxSay textstr,(r2) Read all variables do forever RxVNext name=namevar,data=wrk if (tm,zrx_shvret,zrx_eof,o) end of list leave endif if (ltr,r15,15,z) if good rc mvc namelen,zrx_ShVbVnl copy name length mvc datalen,zrx_ShVbVbl copy data length *do something* else leave endif enddo namelen ds a datalen ds a namevar ds cl200 wrk ds cl2048