JCL - supply instream data to cataloged PROC - procedure

I’m trying to replicate a case given by the book “Murach’s OS/390 and z/os JCL” (page 259), with the following code.
Briefly, I want to supply the instream dataset in the invoking job to the procedure invoked. And I have no clue why it’s not working.
Have anyone any suggestion?
(I know how to make it work without the instream dataset, but I want to replicate the case in the book)
INVOKING JOB
XXXXXXX.PE000.UTILITY(SRCHCALL)
000001 //JOB1 JOB
000002 // JCLLIB ORDER=(XXXXXXX.PE000.UTILITY)
000003 //STEP01 EXEC PROVA
000004 //SRCHCA1.OUT1 DD *
000005 CIAO
000006 /*
000007 //
PROCEDURE INVOKED
XXXXXXX.PE000.UTILITY(PROVA)
000001 //EXMPLE PROC
000002 //SRCHCA1 EXEC PGM=IEFBR14
000003 //OUTDD DD DDNAME=OUT1
JCL LISTING
1 //JOB1 JOB
2 // JCLLIB ORDER=(XXXXXXXX.PE000.UTILITY)
3 //STEP01 EXEC PROVA
4 XXEXMPLE PROC
5 XXSRCHCA1 EXEC PGM=IEFBR14
6 XXOUTDD DD DDNAME=OUT1
7 //SRCHCA1.OUT1 DD *
In the JCL listing, I was expecting to see also the string “CIAO”.
The code above is showing the exact syntax of the book, but by substituting the OUT1 in line 4 with OUTDD, I get to override line 3 of the proc only with the job’s overriding statement but not the next line (“CIAO”).
JCL LISTING (2)
5 XXSRCHCA1 EXEC PGM=IEFBR14
6 //SRCHCA1.OUTDD DD *
X/OUTDD DD DDNAME=OUT1

Instream data is separated from the JCL by JES2/3 when it reads and interprets the JCL stream. The actual data for each instream data set is stored separately on the JES spool space. Think of this as a temporary data set. JES "links" the DD-statement to the corresponding data. The actual data is never reproduced in the JCL listing.
You can change your procedure PROVA to look like this:
//EXMPLE PROC
//SRCHCA1 EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSUT1 DD DDNAME=OUT1
//SYSUT2 DD SYSOUT=*
Then rerun your first JCL and you should see the text "CIAO" in the job output.
You can also run the second example, but here you will have to write:
//SRCHCA1.SYSUT1 DD *
CIAO
/*
Again, you should see "CIAO" in a separate output file ind the job output.
(Note that I have not actually run my samples.)

Related

PC COBOL program to JCL

I have the following simple COBOL program - written for the PC. It simply reads a file from the computer and writes to the file:
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CUSTOMER-FILE ASSIGN TO
"C:Customers.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD CUSTOMER-FILE.
01 CUSTOMER-RECORD.
05 FIRST-NAME PIC X(20).
05 LAST-NAME PIC X(20).
WORKING-STORAGE SECTION.
01 WS-CUSTOMER-RECORD.
05 WS-FIRST-NAME PIC X(20).
05 WS-LAST-NAME PIC X(20).
01 WS-EOF PIC X.
PROCEDURE DIVISION.
OPEN OUTPUT CUSTOMER-FILE
PERFORM UNTIL CUSTOMER-RECORD = SPACES
DISPLAY "Enter the first and last name for the customer"
ACCEPT CUSTOMER-RECORD
WRITE CUSTOMER-RECORD
END-PERFORM
CLOSE CUSTOMER-FILE
DISPLAY "Output from the Customer File:"
OPEN INPUT CUSTOMER-FILE.
PERFORM UNTIL WS-EOF = 'Y'
READ CUSTOMER-FILE INTO WS-CUSTOMER-RECORD
AT END MOVE 'Y' TO WS-EOF
NOT AT END DISPLAY WS-CUSTOMER-RECORD
END-READ
END-PERFORM.
CLOSE CUSTOMER-FILE.
GOBACK.
My question: I'm not too familiar with JCL. So if I were to put this program on a mainframe, what would I do for the JCL?
I presume your Identification Division got lost in a cut & paste incident on its way to Stack Overflow; you'll need that.
The current incarnation of IBM Enterprise COBOL does not allow free format source so in order to get your code to compile you would have to reformat and follow the traditional fixed format.
Rather than referring to your data file by name, your Assign clause must refer to a name (limited to 8 characters) which corresponds to a DD name in your JCL. Pick something meaningful, to the extent you can in 8 characters, maybe CUSTOMER.
Since you're running with JCL, your Accept statement will work a bit differently. Probably data will come from a SYSIN DD.
Your JCL will look something like this...
[job card, which is shop-specific]
//TOMSPGM EXEC PGM=yourProgramName
//STEPLIB DD DISP=SHR,DSN=mainframe.dataset.where.you.bound.your.program
//SYSIN DD *
[your customer records]
//CUSTOMER DD DISP=(NEW,CATLG,DELETE),
// DSN=mainframe.dataset.where.your.data.should.end.up,
// LRECL=40,
// AVGREC=U,
// RECFM=FB,
// SPACE=(40,(10,10),RLSE) Adjust to your needs
//SYSOUT SYSOUT=*
//CEEDUMP SYSOUT=*
I'm not sure how this will work with your creating the customer file and then reading it in the same program. In 30 years of mainframe work I've never seen that.
Adding to answer from #cschneid.
Great to see AVGREC is being used on the DD statement to allocate space for the data set. This is much better than using the old-fashioned CYL, or TRK units.
Unfortunately, IMHO, the IBM z/OS architects missed to implement a more modern was to specify space: KiB, or MiB. (ISPF supports KB, and MB as space unit, JCL doesn't.)
With AVGREC you tell the system that the SPACE= primary and secondary space values are number of records, instead of physical units such as tracks, or cylinders.
//CUSTOMER DD ...
// AVGREC=U,
// SPACE=(40,(10,20),RLSE)
Above statement tells the system that the records written will have an average length of 40 bytes (this completely is independent of RECFM=, or LRECL=!). With AVGREC=U (U means units), this further tells the system to allocate initial (primary) space for 10 records, and to add additional space for 20 records each time more space is needed (with an upper limit).
Physical allocations are still in tracks, or cylinders under the hood. The system calculates tracks, or cylinders needed from
"average record length" * "number of records" * avgrec-unit
For the primary allocation, this is
40 * 10 * 1 = 400 bytes
Good. But how can we specify our space needs in KiB or MiB using these keywords?
Remember that the average record length in the SPACE= parameter is completely unreleated to the actual record length specified via LRECL=. Great, so we can freely choose the average record length, and set it to, say, 1. And let us also change the wording "number of records* in above forumla to "number of units". The formula becomes:
1 * "number of units" * avgrec-unit
or
"number of units" * avgrec-unit
AVGREC= supports the units U (1), K (1024), and M (1024*1024). So, to allocate space in megabytes (MiB), we simply code:
//CUSTOMER DD ...
// AVGREC=M,
// SPACE=(1,(10,20),RLSE)
This will allocate 10 MiB primary space, and 20 MiB secondary space. Each allocation is rounded up to the next integral number of tracks, or cylinders, depending on physical disk structures. You simply don't have to care anymore. Neat, isn't it?

An error rc=20 when I want to show an ispf panel from a cobol program

I want to display an ispf panel with a cobol program. With REXX is easy, no problems, but with cobol is not showing the panel.
When I submit the jcl, the compile and link step gives no errors but when it try to run an error is received: MAXCC=0020. In the jesysmsg I found
...
IEF236I ALLOC. FOR CBLMINE STEP2
IGD103I SMS ALLOCATED TO DDNAME STEPLIB
IEF237I JES2 ALLOCATED TO SYSOUT
IEF237I DMY ALLOCATED TO CEEDUMP
IEF237I DMY ALLOCATED TO SYSUDUMP
IEF142I CBLMINE STEP2 - STEP WAS EXECUTED - COND CODE 0020
IGD104I Z30952.PATO RETAINED,DDNAME=STEPLIB
IEF285I Z30952.CBLMINE.JOB04408.D0000103.? SYSOUT
...
According with the IBM manual the error is: ERROR. I/O error writing to update file, FILEDEF missing, or APNDUPD process option cancelled because of inconsistent file attributes.
Any practical help (with an example please)?
With an ispf panel :
)ATTR DEFAULT(+_%)
% TYPE(TEXT) COLOR(PINK) INTENS(HIGH)
$ TYPE(INPUT) INTENS(HIGH) PAD(_)
! TYPE(INPUT) INTENS(LOW) PAD(' ')
)BODY
%-------------------- *TITLE FOR ENTRY PANEL* --------------------------
%COMMAND ===>_ZCMD
%
&ZUSER &ZTIME &ZSCREEN &ZWIDTH &ZUS4S7
+ THIS DIRECTION LINE TELLS THE USER HOW TO USE THE PANEL:
%XXXXX:_X %YYY:$YYY %ZZZ:$ZZ%AAAAAAAA:$AAAAAAAA +
)END
With a cobol program:
IDENTIFICATION DIVISION.
PROGRAM-ID. CBLEX003
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
77 PST1 PIC X(6) VALUE 'LIBDEF'.
77 PST2 PIC X(7) VALUE 'ISPPLIB'.
77 PST3 PIC X(7) VALUE 'DATASET'.
77 PST4 PIC X(15) VALUE 'Z30952.MINE.GML'.
77 PST5 PIC X(16) VALUE 'DISPLAY PANEL01'.
77 ISPLINK PIC X(7) VALUE 'ISPLINK'.
PROCEDURE DIVISION.
CALL ISPLINK USING PST1 PST2 PST3 PST4.
CALL ISPLINK USING PST5.
STOP RUN.
With a jcl:
//CBLMINE JOB 1,NOTIFY=&SYSUID,MSGLEVEL=(1,1)
//SETVAR SET THEPGM=CBLEX003
//SETVAR SET WHERES=&SYSUID..MINE.GML
//SETVAR SET LINKRU=&SYSUID..PATO
//COBRUN EXEC IGYWCL
//COBOL.SYSIN DD DSN=&WHERES(&THEPGM),DISP=SHR
//LKED.SYSLMOD DD DSN=&LINKRU(&THEPGM),DISP=SHR
// IF RC = 0 THEN
//STEP2 EXEC PGM=&THEPGM
//STEPLIB DD DSN=&LINKRU,DISP=SHR
//SYSOUT DD SYSOUT=*,OUTLIM=15000
//CEEDUMP DD DUMMY
//SYSUDUMP DD DUMMY
// ELSE
// ENDIF
If you want to use ISPF services like ISPLINK you must execute in an ISPF environment. IBM's documentation provides an example here, reproduced below.
//USERAA JOB (AA04,BIN1,000000),'I. M. USERAA',
// CLASS=L,MSGCLASS=A,NOTIFY=USERAA,MSGLEVEL=(1,1)
//*-------------------------------------------------------*/
//* EXECUTE ISPF COMMAND IN THE BACKGROUND */
//*-------------------------------------------------------*/
//*
//ISPFBACK EXEC PGM=IKJEFT01,DYNAMNBR=25,REGION=1024K
//*- - ALLOCATE PROFILE, PANELS, MSGS, PROCS, AND TABLES -*/
//ISPPROF DD DSN=USERAA.ISPF.PROFILE,DISP=OLD
//ISPPLIB DD DSN=ISP.SISPPENU,DISP=SHR
//ISPMLIB DD DSN=ISP.SISPMENU,DISP=SHR
//ISPSLIB DD DSN=ISP.SISPSENU,DISP=SHR
// DD DSN=ISP.SISPSLIB,DISP=SHR
//ISPTLIB DD DSN=USERAA.ISPF.TABLES,DISP=SHR
// DD DSN=ISP.SISPTENU,DISP=SHR
// DD DSN=ISP.SISPTLIB,DISP=SHR
//ISPTABL DD DSN=USERAA.ISPF.TABLES,DISP=SHR
//*
//*- - ALLOCATE ISPF LOG DATA SET - - - - - - - - - - - -*/
//ISPLOG DD DSN=USERAA.ISPF.LOG,DISP=SHR
//*
//*- - ALLOCATE DIALOG PROGRAM AND TSO COMMAND LIBRARIES -*/
//ISPLLIB DD DSN=USERAA.ISPF.LOAD,DISP=SHR
//SYSEXEC DD DSN=ISP.SISPEXEC,DISP=SHR
//SYSPROC DD DSN=ISP.SISPCLIB,DISP=SHR
//*
//*- - ALLOCATE TSO BACKGROUND OUTPUT AND INPUT DS - - - -*/
//SYSTSPRT DD DSNAME=USERAA.ISPF.ISPFPRNT,DISP=SHR
//SYSTSIN DD *
PROFILE PREFIX(USERAA) /* ESTABLISH PREFIX */
ISPSTART CMD(%TBUPDATE) /* INVOKE CLIST DIALOG */
/*
You must supply a valid jobcard and the correct ISPF library concatenations for your shop. Also, I believe you would use ISPSTART PGM(CBLEX003) instead of what the IBM sample has for starting a CLIST.
If you don't know your shop's ISPF library concatenations, you can probably determine them from what is displayed by the ISRDDN command from any ISPF command line.
There is also an ISPF Dialog Test facility, usually on the main ISPF menu. You can use this to test your panel.
I agree with what Bruce and cschneid have been stating. You can not invoke an ISPF service from a COBOL pgm using JCL unless the JCL is running ISPF in batch mode as in the example provided by cschneid. Without the ISPF environment ISPLINK will set rc=20 because it can not find an ISPF environment. Test your program via ISPF option 7 or write an exec to run it where you LIBDEF ISPLLIB to point at the load library containing your linked COBOL pgm.
address ISPEXEC
"LIBDEF ISPLLIB DATASET ID('userid.TEST.LOAD')"
"SELECT PGM(mycbl)"
"LIBDEF ISPLLIB"
You would normally not run a DISPLAY service via batch as you have been advised. It can be done by supplying all the values for the panel fields and then simulating an ENTER or END with the CONTROL service, but it would be easy to get in a DISPLAY loop if not careful.

Baffled: SPSS (2265) Unrecognized or invalid variable format

A year ago, we analyzed with SPSS 22 some data with 100+ variables on 5 lines. We used the GUI and laboriously entered variable names and output formats. This year, we are using SPSS 23 after a mandatory upgrade. We have similar data, and want to use a syntax file instead. We copied the GET DATA output from last year, made a few changes, and ran. No deal. We get the notorious and almost completely unhelpful error message in the title. (It continues "The format is invalid. For numeric formats, the width or decimals value may be invalid." Not line number, Not indication of the problem).
We are not using big numbers. We are not using macros, as in this SO question. We tried replacing F1.0 with N1. There are no ','s in the file (hence, no F3,1-like typos). I have searched the web. Does anyone know what else the problem might be?
The failing GET DATA statement, with filename and middle elided.
GET DATA /TYPE=TXT
/FILE="E: ... .txt"
/ENCODING='UTF8'
/DELCASE=VARIABLES 123
/DELIMITERS="\t"
/ARRANGEMENT=DELIMITED
/FIRSTCASE=1
/IMPORTCASE=ALL
/VARIABLES=
ID A4
Group A2
Quality A2
V4 A5
oarea F4.1
oallarea F4.1
olthmean F5.3
olthmax F5.3
...
x N1
o N1
S N1
Z N1
w N1.
F5.5 was not valid. Fixing that and program ran.

Cobol RELEASE statement?

I am working on my first project with Cobol Sort VSAM files. I ran into a keyword RELEASE.
The way the book read that I have is the "The release statement transfers records from the INPUT PROCEDURE to the input Phase of the sort operation.
My Question is: That takes what ever I have in my Sort-Rec (or whatever I called it) and sends it directly into the OUTPUT PROCEDURE part of my SORT?
Seems confusing to me here.
Cobol Code:
SORT SORT-FILE ASCENDING KEY SORT-PROVIDER
INPUT PROCEDURE IS PROC-THE-REC THRU PTR-X
OUTPUT PROCEDURE IS WRITE-THE-RPT THRU WTR-X.
MOVE CC-CERT-NO TO SAVE-CERT-NO.
MOVE CC-CERT-STATUS TO SAVE-CERT-STATUS.
MOVE CC-CERT-BEGIN-DATE TO SAVE-CERT-BEGIN-DATE.
MOVE CC-CERT-END-DATE TO SAVE-CERT-END-DATE.
MOVE CC-CERT-FUNDING TO SAVE-CERT-FUNDING.
MOVE CC-PROV-NUMB TO SAVE-PROV-NUMB.
MOVE CC-PROV-RES-CNTY TO SAVE-PROV-RES-CNTY.
MOVE CC-PROV-TYPE TO SAVE-PROV-TYPE.
MOVE CC-WORKER-USERID TO SAVE-WORKER-USERID.
MOVE CC-WORKER-NAME TO SAVE-WORKER-NAME.
RELEASE SORT-REC.
Following from Bill,
When using a sort in Cobol is a bit like having two or three separate programs in the one program.
Pre-Sort (PROC-THE-REC in your case)
|
V
Sort
|
V
Post sort (WRITE-THE-RPT in your case)
The RELEASE statement "Writes" a record to the "Sort" step.
In Unix you could achieve the same thing by
writing 2 separate programs (Pre and post sort)
Replacing the Release with Writes
piping the output from the Pre-Sort to the sort.
On the mainframe you would use 3 JCL steps and temporary files.
On the mainframe, most sites I worked at discourage (ban) the use of the Cobol sort verb and you would write 2 programs and use the utility sort.
The release statement transfers records from the INPUT PROCEDURE to
the input Phase of the sort operation.
The input Phase of a sort is where SORT gets its data from, in this case.
COBOL Program
Loop-construct
Some COBOL code
Release
Next
The sort is actually an external program. In the case of the Mainframe,
it is the installed SORT product (usually DFSORT or SyncSort)
Input Phase of SORT
SORT
Output Phase of SORT
Another-Loop-construct
Some COBOL code
Return
Next
COBOL Program
Your input procedure will process, release, and then continue. When all data has been released, the sort will take place. The sorted records will be presented back to your program at the point of the RETURN statement you will have coded, and this will continue (return, stuff after return, another return, repeat until finished) until all the sorted file is processed (assuming that nothing goes wrong an you want to stop early).
normally, COBOL sort procedures are :
SORT SORTFILE ON SORT-ID, SORT-NAME, SORT-PHONE
INPUT PROCEDURE IS READ-IN
OUTPUT PROCEDURE IS PRINT-SORTED.
READ-IN SECTION.
loop:
READ INPUTFILE.
MOVE IN-ID TO SORT-ID.
MOVE IN-NAME TO SORT-NAME.
MOVE IN-PHONE TO SORT-PHONE.
RELEASE SORT-REC.
PRINT-SORTED SECTION.
loop:
RETURN SORT-REC.
DISPLAY "id#: " SORT-ID.
DISPLAY "Name: " SORT-NAME.
DISPLAY "Phone: " SORT-PHONE.
An INPUT PROCEDURE supplies records to the sort process by writing them to the work file declared in the SORT's SD entry. But to write the records to the work file a special verb - the RELEASE verb is used.
An operational template for an INPUT PROCEDURE, which gets records from and input file and RELEASEs them to the work file, is shown below.
OPEN INPUT InFileName
READ InFileName
PERFORM UNTIL TerminatingCondition
Process input record to create SDWorkRec
RELEASE SDWorkRec
READ InFileName
END-PERFORM
CLOSE InFileName
For further details on the SORT see my tutorial at http://www.csis.ul.ie/cobol/course/SortMerge.htm

8086 Assembly time print interruption

I want to print the system time in hh:mm format, and store it in AM array or PM array, depending on what time it is.
Here is what i have:
assume cs:code, ds:data
data segment
hour db ?
min db ?
AM db ?
PM db ?
data ends
code segment
start:
mov ah, 2Ch ;
int 21h
mov hour, CH
mov min, CL
I know that function 2Ch returns CH = hour. CL = minute. DH = second. DL = 1/100 seconds
How can i use this, to print the current time ?
Any ideas?
(I am using TASM, TLINK, and turbo debugger)
You'll need to look up some kind of system call for writing to a console (I think there are actually some BIOS routines that do this if you're not running under a mainstream OS) or link your code with a library that provides a printing function and invoke that.
That's how you printing string: An Introduction to Assembly Instructions
That's how you printing decimal number: Print decimal in 8086 emulator

Resources