The following program does just that, but it just lists each substring to SYSPRINT. For this program, the data set contains variable length records.
LISTPARM CSECT
USING *,12
SAVE (14,12),,*
LR 12,15
LA 15,SAVEAREA
ST 13,4(,15)
ST 15,8(,13)
LR 13,15
L 2,0(,1)
OPEN (PRINT,OUTPUT)
LH 5,0(,2)
LTR 5,5
BP SCAN0100
PUT PRINT,MSG01
B EXIT
SCAN0100 LA 5,1(5,2)
LA 4,1
LA 3,2(,2)
LA 6,1
SCAN0200 LR 0,3
SCAN0300 CLI 0(3),C','
BE SCAN0400
BXLE 3,4,SCAN0300
SCAN0400 LR 1,3
SR 1,0
BP SCAN0500
CVD 6,DWORK
OI DWORK+L'DWORK-1,X'0F'
UNPK PARMNO,DWORK
MVC PARMTEXT(4),=C'NULL'
LA 14,PARMTEXT+4
B SCAN0600
SCAN0500 LA 14,PARMTEXT
LR 15,1
MVCL 14,0
CVD 6,DWORK
OI DWORK+L'DWORK-1,X'0F'
UNPK PARMNO,DWORK
SCAN0600 LA 1,MSG02
SR 14,1
STH 14,0(,1)
PUT PRINT,MSG02
LA 6,1(,6)
BXLE 3,4,SCAN0200
EXIT CLOSE PRINT
L 13,4(,13)
RETURN (14,12),T,RC=0
SAVEAREA DC 9D'0'
DWORK DC D'0'
PRINT DCB DSORG=PS,MACRF=PM,DDNAME=SYSPRINT,RECFM=VBA,LRECL=125
MSG01 DC AL2(MSG01L,0),C' NO PARAMETER TEXT WAS SENT'
MSG01L EQU *-MSG01
MSG02 DC AL2(*-*,0),C' PARAMETER '
PARMNO DC CL2' ',C' IS '
PARMTEXT DC CL(125-(*-PARMTEXT))' '
DC 0D'0'
LTORG ,
END LISTPARM
USING *,12
SAVE (14,12),,*
LR 12,15
LA 15,SAVEAREA
ST 13,4(,15)
ST 15,8(,13)
LR 13,15
L 2,0(,1)
OPEN (PRINT,OUTPUT)
LH 5,0(,2)
LTR 5,5
BP SCAN0100
PUT PRINT,MSG01
B EXIT
SCAN0100 LA 5,1(5,2)
LA 4,1
LA 3,2(,2)
LA 6,1
SCAN0200 LR 0,3
SCAN0300 CLI 0(3),C','
BE SCAN0400
BXLE 3,4,SCAN0300
SCAN0400 LR 1,3
SR 1,0
BP SCAN0500
CVD 6,DWORK
OI DWORK+L'DWORK-1,X'0F'
UNPK PARMNO,DWORK
MVC PARMTEXT(4),=C'NULL'
LA 14,PARMTEXT+4
B SCAN0600
SCAN0500 LA 14,PARMTEXT
LR 15,1
MVCL 14,0
CVD 6,DWORK
OI DWORK+L'DWORK-1,X'0F'
UNPK PARMNO,DWORK
SCAN0600 LA 1,MSG02
SR 14,1
STH 14,0(,1)
PUT PRINT,MSG02
LA 6,1(,6)
BXLE 3,4,SCAN0200
EXIT CLOSE PRINT
L 13,4(,13)
RETURN (14,12),T,RC=0
SAVEAREA DC 9D'0'
DWORK DC D'0'
PRINT DCB DSORG=PS,MACRF=PM,DDNAME=SYSPRINT,RECFM=VBA,LRECL=125
MSG01 DC AL2(MSG01L,0),C' NO PARAMETER TEXT WAS SENT'
MSG01L EQU *-MSG01
MSG02 DC AL2(*-*,0),C' PARAMETER '
PARMNO DC CL2' ',C' IS '
PARMTEXT DC CL(125-(*-PARMTEXT))' '
DC 0D'0'
LTORG ,
END LISTPARM
USING *,12
SAVE (14,12),,*
LR 12,15
LA 15,SAVEAREA
ST 13,4(,15)
ST 15,8(,13)
LR 13,15
The preceding code is the usual Assembler entry code that
- Saves the caller's registers in the save area the caller must provide,
- Copies the entry point address the caller supplies in register 15 to register 12 to provide addressability for our program.
- And prepares a new save area so our program can call other programs.
L 2,0(,1)
OPEN (PRINT,OUTPUT)
When our program is called, register 1 points to a parameter list. Since the OPEN macro destroys register 1, our program loads the parameter list into register 2 before it opens the output data set.
LH 5,0(,2)
LTR 5,5
BP SCAN0100
PUT PRINT,MSG01
B EXIT
The parameter list points to a 2 byte data are that contains the length of the parameter text. If the JCL did not specify any text, this length field is 0, and we write an error message.
LA 5,1(5,2)
LA 4,1
LA 3,2(,2)
LA 6,1
This code prepares the registers used to scan the parameter text. Register 5 contains the address of the last byte in the parameter text, register 4 is set to 1, register 3 points to the address of the first byte in the parameter text, and register 6 contains the initial parameter number.
SCAN0200 LR 0,3
SCAN0300 CLI 0(3),C','
BE SCAN0400
BXLE 3,4,SCAN0300
The LR at SCAN0200 copies the start of the current substring to register 0. The code starting at SCAN0300 locates the end of a substring.
SCAN0400 LR 1,3
SR 1,0
BP SCAN0500
The code at SCAN400 copies the end of the substring to register 1 and computes the length of the substring. If the length of the substring is not 0, the code branches to SCAN0500.
CVD 6,DWORK
OI DWORK+L'DWORK-1,X'0F'
UNPK PARMNO,DWORK
MVC PARMTEXT(4),=C'NULL'
LA 14,PARMTEXT+4
B SCAN0600
The code converts the contents of register 6 to a decimal valu and stpres it in the PARMNO data area in the MSG02 message area, then it copies the word NULL to the PARMTEXT area in the message area and sets register 14 to the address of the end of the NULL text.
SCAN0500 LA 14,PARMTEXT
LR 15,1
MVCL 14,0
CVD 6,DWORK
OI DWORK+L'DWORK-1,X'0F'
UNPK PARMNO,DWORK
If you haven't noticed this already, registers 0 and 1 are an even/odd register pair for the second operand of the MVCL instruction. Starting at SCAN0500 the program prepares registers 14 and 15 to be the even/odd register pair for the first operand of an MVCL instruction. The MVCL instruction copies a substring from the parameter text to the output message. Finally, the program converts register 6 to a number starting at PARMNO in the message.
SCAN0600 LA 1,MSG02
SR 14,1
STH 14,0(,1)
PUT PRINT,MSG02
When the program arrives at SCAN0600, register 14 points to the end of the message, so the progran compute the length of the message and stores the message length in the RDW starting at MSG02, and the writes the message.
LA 6,1(,6)
Update the parameter counter in register 6.
BXLE 3,4,SCAN0200
Register 3 points tp the comma at the end of the substring, or it points to the end of the parameter text. This BXLE updates register 3 to point to the first byte in the next substring, and branches if there is more text in the parameter text. If the BXLE does not branch. the program has completed the parameter text scan.
EXIT CLOSE PRINT
L 13,4(,13)
RETURN (14,12),T,RC=0
Close the data set, load the address of the higher save area from the current save area, and restore the registers and return to our caller.
SAVEAREA DC 9D'0'
This is the register save area used by any programs our program calls. The PUT macro, in essence, calls a subroutine to copy a message to a real I/O buffer.
DWORK DC D'0'
This instruction defines an 8 byte work area used by the CVD and UNPK instructions in the program. Technically, a data area specifies as type D is a hexadecimal floating point number, but in our program the data area will contain a packed decimal number.
PRINT DCB DSORG=PS,MACRF=PM,DDNAME=SYSPRINT,RECFM=VBA,LRECL=125
The DCB macro defines a relatively large (96 byte) data area called a DCB.
DSORG=PS specifies a DCB for a sequential data set is being created.
MACRF=PM specifies that the PUT macro using "move" processing is being used with this data set. The program provides a complete message.
DDNAME=SYSPRINT specifies that a data set specified by a DD statement with DD name SYSPRINT will be used for the I/O .
MSG01 DC AL2(MSG01L,0),C' NO PARAMETER TEXT WAS SENT'
MSG01L EQU *-MSG01
These instructions define a message in the variable length message format The first 4 bytes in the MAG01 data area specify a data area called an RDW that contains the message length.
MSG02 DC AL2(*-*,0),C' PARAMETER '
PARMNO DC CL2' ',C' IS '
PARMTEXT DC CL(125-(*-PARMTEXT))' '
These instructions define a message skeleton area. The PARMTEXT area fills out a data area for the maximum possible message. The actual message length is stored in the RDW data area just before the message is sent to the I/O buffer by the PUT macro.
DC 0D'0'
LTORG ,
END LISTPARM
The LTORG Assembler instruction tells the Assembler program to insert the data specified by literals here. The Assembler aligns this data area on a double word boundary; the DC instruction just before the LTORG instruction effectifvely tells the Assembler prgram to insert binary 0s to fill out to a double word boundary