Connect COBOL to database - cobol

I am trying to connect to a database in COBOL, using the embedded SQL processor. The problem is that I can't figure out how to make the connection. The documentation for the CONNECT statement says to use datasource|servername, but what is it actually? I tried using the CONNECT WITH PROMPT, and it opens a configuration screen, but I can't make it to work. How can I make the connection using this SQL embedded processor?
I am using MicroFocus NetExpress compiler, version 5.1.6.14.
The code I am using:
$set SQL
working-storage section.
exec sql
include sqlca
end-exec.
01 SQLCA.
05 SQLCAID PIC X(8) VALUE "SQLCA ".
05 SQLCABC PIC S9(9) COMP-5 VALUE 136.
05 SQLCODE PIC S9(9) COMP-5 VALUE 0.
05 SQLERRM.
49 SQLERRML PIC S9(4) COMP-5.
49 SQLERRMC PIC X(70).
05 SQLERRP PIC X(8).
05 SQLERRD PIC S9(9) COMP-5 OCCURS 6 VALUE 0.
05 SQLWARN.
10 SQLWARN0 PIC X.
10 SQLWARN1 PIC X.
10 SQLWARN2 PIC X.
10 SQLWARN3 PIC X.
10 SQLWARN4 PIC X.
10 SQLWARN5 PIC X.
10 SQLWARN6 PIC X.
10 SQLWARN7 PIC X.
10 SQLWARN8 PIC X.
10 SQLWARN9 PIC X.
10 SQLWARN10 PIC X.
10 SQLWARNA REDEFINES SQLWARN10 PIC X .
05 SQLSTATE PIC X(5).
procedure division.
exec sql
connect to ':ws-base-src' as banco user 'sa.'
end-exec
display SQLCODE
I always get the return code: 19703. From this documentation. It says that it can't make the connection.
The SQLERRM variable has this information; Data source name not found and no default driver specified.
For the CONNECT statement usage, I am following this documentation..

As #James Anderson said, it was a connection configuration problem. Had to do some configuration for access on Microsoft SQL Server and the OCDB connection.

Related

OpenCOBOL can't find my external module to run the program

I'm trying to create a COBOL program using OpenCobol that has an external module when it does a calculation and then brings the result back into the main program using CALL. But everytime I try to run the program it says it can't find the module. I have already changed my module to Program Type "Module" from executable and I have added the module path as a Library path but nothing is working so far
Here is my main program code:
PROGRAM-ID. Project2 AS "Project2".
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
*****The student input file
SELECT STUDENT-FILE-IN
ASSIGN TO "C:\STUFILE.TXT"
ORGANIZATION IS LINE SEQUENTIAL.
*****The program input file
SELECT PROGRAM-FILE-IN
ASSIGN TO "C:\PROGRAM.TXT"
ORGANIZATION IS LINE SEQUENTIAL.
*****The student report output file
SELECT STUDENT-REPORT-FILE-OUT
ASSIGN TO "C:\REPORT.TXT"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
*Student input file
FD STUDENT-FILE-IN.
01 STUDENT-RECORD.
05 STUDENT-NUMBER PIC 9(6).
05 TUITION-OWED-IN PIC 9(4)V99.
05 STUDENT-NAME-IN PIC X(40).
05 PROGRAM-OF-STUDY PIC X(5).
05 COURSE-CODE-1 PIC X(7).
05 COURSE-AVERAGE-1 PIC 9(3).
05 COURSE-CODE-2 PIC X(7).
05 COURSE-AVERAGE-2 PIC 9(3).
05 COURSE-CODE-3 PIC X(7).
05 COURSE-AVERAGE-3 PIC 9(3).
05 COURSE-CODE-4 PIC X(7).
05 COURSE-AVERAGE-4 PIC 9(3).
05 COURSE-CODE-5 PIC X(7).
05 COURSE-AVERAGE-5 PIC 9(3).
*Program input file
FD PROGRAM-FILE-IN.
01 PROGRAM-RECORD-IN.
05 PROGRAM-CODE-IN PIC X(5).
05 PROGRAM-NAME-IN PIC X(20).
*Student report output file
FD STUDENT-REPORT-FILE-OUT.
01 STUDENT-REPORT-RECORD-OUT PIC x(90).
WORKING-STORAGE SECTION.
*Table to hold program records
01 PROGRAM-RECORD.
05 PROGRAM-TABLE.
10 PROGRAM-CODE PIC X(5) OCCURS 20 TIMES.
10 PROGRAM-NAME PIC X(20) OCCURS 20 TIMES.
*The student report record
01 STUDENT-REPORT-RECORD.
05 STUDENT-NAME PIC X(40).
05 FILLER PIC X(2) VALUE SPACES.
05 PROGRAM-NAME-OUT PIC X(20).
05 FILLER PIC X(4) VALUE SPACES.
05 TUITION-OWED PIC Z,ZZ9.99.
*A line to make the output look good
01 HEADER-LINE.
05 FILLER PIC X(90) VALUE ALL "-".
*The column header
01 COLUMN-HEADER.
05 NAME-COLUMN PIC X(42) VALUE "NAME".
05 AVG-COLUMN PIC X(7) VALUE "AVE".
05 PROG-COLUMN PIC X(24) VALUE "PROGRAM NAME".
05 OWED-COLUMN PIC X(12) VALUE "TUITION OWED".
01 CONTROL-FIELDS.
05 STUFILE-EOF-FLAG PIC A(3).
05 PROG-EOF-FLAG PIC A(3).
05 PROG-SUB PIC 9(2).
05 FOUND-PROG-FLAG PIC A(3).
01 COUNTERS.
05 STUDENT-RECORDS-READ-CTR PIC 9(3).
05 STUDENT-REPORTS-WRITTEN-CTR PIC 9(3).
01 WW-SEND-AREA.
05 STUDENT-AVERAGE PIC 9(3).
01 WW-SUB-PROG PIC X(75)
VALUE 'C:\Users\google\Program3Call'.
PROCEDURE DIVISION.
PERFORM 200-INITIALIZATION-RTN.
*Read and process all student records
PERFORM 200-PROCESS-STUDENT-RECORD-RTN
UNTIL STUFILE-EOF-FLAG = "YES".
PERFORM 200-FINISH-RTN.
STOP RUN.
200-INITIALIZATION-RTN.
PERFORM 300-OPEN-FILES-RTN.
*****Load all program records into the table
PERFORM 300-LOAD-PROGRAM-TABLE-RTN
VARYING PROG-SUB FROM 1 BY 1
UNTIL PROG-SUB > 20 OR PROG-EOF-FLAG = "YES".
PERFORM 300-INITIALIZE-REPORT-FILE-RTN.
PERFORM 300-INITIALIZE-COUNTERS-RTN.
200-PROCESS-STUDENT-RECORD-RTN.
PERFORM 300-READ-STUDENT-RECORD-RTN.
IF STUFILE-EOF-FLAG NOT EQUALS "YES"
*********Get the program name
PERFORM 300-GET-PROGRAM-NAME-RTN
VARYING PROG-SUB FROM 1 BY 1 UNTIL
FOUND-PROG-FLAG = "YES" OR PROG-SUB > 20
PERFORM 300-GET-STUDENT-AVERAGE
PERFORM 300-PRINT-STUDENT-REPORT-RTN
END-IF.
200-FINISH-RTN.
PERFORM 300-PRINT-COUNTERS-RTN.
PERFORM 300-CLOSE-FILES-RTN.
300-OPEN-FILES-RTN.
OPEN INPUT STUDENT-FILE-IN.
OPEN INPUT PROGRAM-FILE-IN.
OPEN OUTPUT STUDENT-REPORT-FILE-OUT.
300-LOAD-PROGRAM-TABLE-RTN.
READ PROGRAM-FILE-IN
AT END MOVE "YES" TO PROG-EOF-FLAG
NOT AT END MOVE PROGRAM-CODE-IN TO PROGRAM-CODE (PROG-SUB)
MOVE PROGRAM-NAME-IN TO PROGRAM-NAME (PROG-SUB).
300-INITIALIZE-REPORT-FILE-RTN.
MOVE COLUMN-HEADER TO STUDENT-REPORT-RECORD-OUT.
WRITE STUDENT-REPORT-RECORD-OUT.
MOVE HEADER-LINE TO STUDENT-REPORT-RECORD-OUT.
WRITE STUDENT-REPORT-RECORD-OUT.
300-INITIALIZE-COUNTERS-RTN.
MOVE 0 TO STUDENT-RECORDS-READ-CTR.
MOVE 0 TO STUDENT-REPORTS-WRITTEN-CTR.
300-READ-STUDENT-RECORD-RTN.
READ STUDENT-FILE-IN
AT END MOVE "YES" TO STUFILE-EOF-FLAG
NOT AT END ADD 1 TO STUDENT-RECORDS-READ-CTR.
300-GET-PROGRAM-NAME-RTN.
IF PROGRAM-CODE (PROG-SUB) = PROGRAM-OF-STUDY
MOVE PROGRAM-NAME (PROG-SUB) TO PROGRAM-NAME-OUT
MOVE "YES" TO FOUND-PROG-FLAG
END-IF.
300-GET-STUDENT-AVERAGE.
CALL WW-SUB-PROG USING WW-SEND-AREA.
300-PRINT-STUDENT-REPORT-RTN.
MOVE "NO" TO FOUND-PROG-FLAG.
MOVE STUDENT-NAME-IN TO STUDENT-NAME.
MOVE TUITION-OWED-IN TO TUITION-OWED.
MOVE STUDENT-REPORT-RECORD TO STUDENT-REPORT-RECORD-OUT.
WRITE STUDENT-REPORT-RECORD-OUT.
ADD 1 TO STUDENT-REPORTS-WRITTEN-CTR.
300-PRINT-COUNTERS-RTN.
DISPLAY "Student records read: ", STUDENT-RECORDS-READ-CTR.
DISPLAY "Student reports written: ",
STUDENT-REPORTS-WRITTEN-CTR.
300-CLOSE-FILES-RTN.
CLOSE STUDENT-FILE-IN, PROGRAM-FILE-IN
STUDENT-REPORT-FILE-OUT.
END PROGRAM Project2.
Here is my Call Program:
******************************************************************
* Author: Desiree Hanuman
* Date: August 14th 2021
* Purpose:Call Section code for project 3
* Tectonics: cobc
******************************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. Program3Call.
DATA DIVISION.
LINKAGE SECTION.
01 LS-STUDENT-AVERAGE-AREA.
05 COURSE-AVERAGE-1 PIC 9(3).
05 COURSE-AVERAGE-2 PIC 9(3).
05 COURSE-AVERAGE-3 PIC 9(3).
05 COURSE-AVERAGE-4 PIC 9(3).
05 COURSE-AVERAGE-5 PIC 9(3).
05 STUDENT-AVERAGE PIC 9(3).
PROCEDURE DIVISION.
MAIN-PROCEDURE.
100-STUDENT-AVERAGE.
PERFORM 300-CALCULATE-AVERAGE-RTN.
300-CALCULATE-AVERAGE-RTN.
COMPUTE STUDENT-AVERAGE ROUNDED = (COURSE-AVERAGE-1 +
COURSE-AVERAGE-2 + COURSE-AVERAGE-3 + COURSE-AVERAGE-4 +
COURSE-AVERAGE-5) / 5.
GOBACK.
The normal way to CALL in most COBOL implementations is to just specify the module name - without a path or extension.
Then you either do "static linking" (as in Scott's answer below for OpenCOBOL/GnuCOBOL just specify all sources on the command line and use either -x [fat executable] or -b [fat module, then callable for example with cobcrun], commonly with -static); or do "dynamic linking" (separate compilation of all modules) and specify the module path in a configuration file or by environment variable. For OpenCOBOL/GnuCOBOL this is COB_LIBRARY_PATH.
I am not a user of OpenCobol, but, according to their manual in section 7, there are many ways to accomplish what you want.
But the simplest would be to statically compile and link the main and sub programs in one command line:
cobc -x Project2.cbl Program3Call.cbl
This example work´s for me.
Please keep in mind that the name of the dll file routine module must be same as the routine name.
It is not necessary reconfigure OpenCobol path library.
I use OpenCobol 4.7.6.
The Code:
Main program (file build "MAINPROG.exe")
IDENTIFICATION DIVISION.
PROGRAM-ID. "MAINPROG".
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 X PIC X(1).
01 INPUTS.
05 PRM-LENGTH PIC S9(4) COMP.
05 INPUT1 PIC 9(2).
05 INPUT2 PIC 9(2).
PROCEDURE DIVISION.
MAIN-PARA.
MOVE 12 TO INPUT1.
MOVE 13 TO INPUT2.
CALL 'MFPROG1' USING PRM-LENGTH, INPUT1, INPUT2.
ACCEPT X.
STOP RUN.
END PROGRAM "MAINPROG".
Rutine program (file build module "MFPROG1.dll")
IDENTIFICATION DIVISION.
PROGRAM-ID. "MFPROG1".
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 OUTPUT-DATA PIC 9(4).
LINKAGE SECTION.
01 PARM-BUFFER.
05 PARM-LENGTH PIC S9(4) COMP.
05 PARM-INPUT1 PIC 9(2).
05 PARM-INPUT2 PIC 9(2).
PROCEDURE DIVISION USING PARM-BUFFER.
MAIN-PARA.
COMPUTE OUTPUT-DATA = PARM-INPUT1 + PARM-INPUT2.
DISPLAY 'PARM-INPUT1: ' PARM-INPUT1.
DISPLAY 'PARM-INPUT2: ' PARM-INPUT2.
DISPLAY 'SUM VALUE : ' OUTPUT-DATA.
GOBACK.
END PROGRAM "MFPROG1".

Suggest improvement for simple Cobol program

I'm an "aspiring" programmer currently trying to learn Cobol. The code below is obviously a very simple Cobol program with hard-coded values. However I am curious to know how a more experienced Cobol programmer would improve such simple program. Maybe there are a lot of things I am missing?
Feel free to suggest how you would accomplish it.
IDENTIFICATION DIVISION.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WORK-FIELDS.
05 EMPTY-LINE PIC X(132) VALUE SPACES.
01 HEADLINE.
05 VALUE "Invoice Specification".
01 FOOTER.
05 VALUE "Invoice End".
01 CALC-FIELDS.
10 SPOILER PIC 9(4).
10 WINDSHIELD PIC 9(3).
10 PARTSUM PIC 9(4).
10 DISCOUNT PIC 9(4).
10 TO-PAY-EXKL PIC 9(6).
10 VAT PIC 9(3).
10 TOTAL-TO-PAY PIC 9(4).
01 PRINT-FIELDS.
05 GROUP-1.
10 PIC X(36)
VALUE "01 SPOILER left-front, 1250:-".
10 SPOILER-EDITED PIC Z,ZZZ.99.
10 PIC X(2) VALUE ":-".
05 GROUP-2.
10 PIC X(36)
VALUE "02 Windshield, 390:-".
10 WINDSHIELD-EDITED PIC Z,ZZZ.99.
10 PIC X(2) VALUE ":-".
05 GROUP-3.
10 PIC X(36)
VALUE "Part Sum".
10 PARTSUM-EDITED PIC Z,ZZZ.99.
10 PIC X(2) VALUE ":-".
05 GROUP-4.
10 PIC X(36)
VALUE "Discount 15%".
10 DISCOUNT-EDITED PIC Z,ZZZ.99.
10 PIC X(2) VALUE ":-".
05 GROUP-5.
10 PIC X(36)
VALUE "To Pay exkl VAT".
10 TO-PAY-EDITED PIC Z,ZZZ.99.
10 PIC X(2) VALUE ":-".
05 GROUP-6.
10 PIC X(36)
VALUE "Added VAT 25%".
10 VAT-EDITED PIC Z,ZZZ.99.
10 PIC X(2) VALUE ":-".
05 GROUP-7.
10 PIC X(36)
VALUE "Total Amount to Pay".
10 PIC X(4) VALUE "SEK ".
10 TOTAL-EDITED PIC Z,ZZZ.99.
10 PIC X(2) VALUE ":-".
PROCEDURE DIVISION.
100-GENERATE-INVOICE.
PERFORM 200-CALCULATE.
PERFORM 300-PRINT-VALUES.
STOP RUN.
200-CALCULATE.
MOVE 1250 TO SPOILER
MOVE SPOILER TO SPOILER-EDITED
MOVE 390 TO WINDSHIELD
MOVE WINDSHIELD TO WINDSHIELD-EDITED
ADD SPOILER WINDSHIELD TO PARTSUM
MOVE PARTSUM TO PARTSUM-EDITED
MULTIPLY PARTSUM BY 0.15 GIVING DISCOUNT
MOVE DISCOUNT TO DISCOUNT-EDITED
SUBTRACT DISCOUNT FROM PARTSUM GIVING TO-PAY-EXKL
MOVE TO-PAY-EXKL TO TO-PAY-EDITED
MULTIPLY TO-PAY-EXKL BY 0.25 GIVING VAT
MOVE VAT TO VAT-EDITED
MULTIPLY TO-PAY-EXKL BY 1.25 GIVING TOTAL-TO-PAY
MOVE TOTAL-TO-PAY TO TOTAL-EDITED
.
300-PRINT-VALUES.
DISPLAY HEADLINE
DISPLAY EMPTY-LINE
DISPLAY EMPTY-LINE
DISPLAY GROUP-1
DISPLAY GROUP-2
DISPLAY GROUP-3
DISPLAY GROUP-4
DISPLAY GROUP-5
DISPLAY GROUP-6
DISPLAY EMPTY-LINE
DISPLAY GROUP-7
DISPLAY EMPTY-LINE
DISPLAY EMPTY-LINE
DISPLAY FOOTER
.
We don't know the objective of this code. Things to consider:
Determine objectives
Determine inputs and outputs
Design input file/db access mode (sequential/random/start from a criteria...etc.).
Identify the business rules.
Design the output (will you just produce a result via display only, will you update a database? will you print a report?)
Design a flow for the processing expected.
Code the required parts.
Note that your code above has no PROCEDURE DIVISION.
Maybe some code here could help amongst the ton of code already out there:
Sample Code

COBOL program won't output the detail lines in my report

EDIT: Figured it out. I needed to call the read again at the end of A420-COUNT-MARKS
Edit: Working on a z/OS mainframe that I'm accessing via Vista TN3270. The program is submitted using JCL which was provided by the teacher.
I'm in school for programming and I have a COBOL assignment where my program reads a file full of subject names and codes and a file full of student marks and an associated subject code. It must use this info to create a report that lists all the subjects and count the number of students that received grades of A , B, C, D or F for each subject. It then totals up the amount of each grade at the bottom.
Report example:
01 ABC COLLEGE TESTING CENTER
02 TEST RESULTS SUMMARY DATE: yyyy/mm/dd
03
04 SUBJECT NAME A B C D F
05
06 xxxxxxxxxxxxxxxxxxxx 9,999 9,999 9,999 9,999 9,999
07 xxxxxxxxx 9,999 9,999 9,999 9,999 9,999
19
20 TOTAL 99,999 99,999 99,999 99,999 99,999
The problem is that my program is only outputting the header rows, but won't output the detail rows or the grand total row. I've written functions to perform these things but they're not getting any errors so I have no idea what's going wrong.
Here's my file control and file section:
FILE-CONTROL.
SELECT F01-SUBJ-FILE ASSIGN TO F01SUBJ.
SELECT F02-MARK-FILE ASSIGN TO F02MARK.
SELECT F03-REPT-FILE ASSIGN TO F03REPT.
FILE SECTION.
FD F01-SUBJ-FILE
RECORDING MODE IS F
RECORD CONTAINS 80 CHARACTERS
DATA RECORD IS F01-SUBJ-RECORD.
01 F01-SUBJ-RECORD.
05 F01-SUBJ-CODE PIC X(6).
05 F01-SUBJ-NAME PIC X(20).
05 PIC X(54).
FD F02-MARK-FILE
RECORDING MODE IS F
RECORD CONTAINS 80 CHARACTERS
DATA RECORD IS F02-MARK-RECORD
01 F02-MARK-RECORD.
05 F02-STUD-NAME PIC X(20).
05 F02-SUBJ-CODE PIC X(6).
05 PIC X.
05 F02-DATE-TEST PIC X(8).
05 F02-STUD-MARK PIC 9(3).
05 PIC X(42).
FD F03-REPT-FILE
RECORDING MODE IS F
RECORD CONTAINS 120 CHARACTERS
DATA RECORD IS F03-REPT-RECORD.
01 F03-REPT-RECORD.
05 PIC X(120).
Here's working storage:
WORKING-STORAGE SECTION.
01 W01-EOF-SWITCH.
05 W01-MARK-EOF PIC X VALUE 'N'.
05 W01-SUBJ-EOF PIC X VALUE 'N'.
01 W02-TEST-TABLE.
05 W02-SUBJ-COUNT PIC 99 VALUE 0.
05 W02-SUBJ-MAX PIC 99 VALUE 50.
05 W02-TEST-ROW OCCURS 1 TO 50
DEPENDING ON W02-SUBJ-COUNT
ASCENDING KEY IS W02-SUBJ-CODE
INDEXED BY W02-IDX.
10 W02-SUBJ-CODE PIC X(6) VALUE SPACES.
10 W02-SUBJ-NAME PIC X(20) VALUE SPACES.
10 W02-A-CTR PIC 9999 VALUE 0.
10 W02-B-CTR PIC 9999 VALUE 0.
10 W02-C-CTR PIC 9999 VALUE 0.
10 W02-D-CTR PIC 9999 VALUE 0.
10 W02-F-CTR PIC 9999 VALUE 0.
01 W03-REPT.
05 W03-HEADER-ROW1.
10 PIC X(9) VALUE SPACES.
10 PIC X(3) VALUE 'ABC'.
10 PIC X VALUE SPACES.
10 PIC X(7) VALUE 'COLLEGE'.
10 PIC X VALUE SPACES.
10 PIC X(7) VALUE 'TESTING'.
10 PIC X VALUE SPACES.
10 PIC X(6) VALUE 'CENTER'.
10 PIC X(85) VALUE SPACES.
05 W03-HEADER-ROW2.
10 PIC X(9) VALUE SPACES.
10 PIC X(4) VALUE 'TEST'.
10 PIC X VALUE SPACES.
10 PIC X(7) VALUE 'RESULTS'.
10 PIC X VALUE SPACES.
10 PIC X(7) VALUE 'SUMMARY'.
10 PIC X(11) VALUE SPACES.
10 PIC X(5) VALUE 'DATE:'.
10 PIC X VALUE SPACES.
10 W03-YEAR PIC 9999.
10 PIC X VALUE '/'.
10 W03-MONTH PIC 99.
10 PIC X VALUE '/'.
10 W03-DAY PIC 99.
10 PIC X(64) VALUE SPACES.
05 W03-HEADER-ROW3.
10 PIC X VALUE SPACES.
10 PIC X(7) VALUE 'SUBJECT'.
10 PIC X VALUE SPACES.
10 PIC X(4) VALUE 'NAME'.
10 PIC X(15) VALUE SPACES.
10 PIC X VALUE 'A'.
10 PIC X(7) VALUE SPACES.
10 PIC X VALUE 'B'.
10 PIC X(7) VALUE SPACES.
10 PIC X VALUE 'C'.
10 PIC X(7) VALUE SPACES.
10 PIC X VALUE 'D'.
10 PIC X(7) VALUE SPACES.
10 PIC X VALUE 'F'.
10 PIC X(59) VALUE SPACES.
05 W03-DETAIL-ROW.
10 PIC X VALUE SPACES.
10 W03-SUBJ-NAME PIC X(20).
10 PIC XXX VALUE SPACES.
10 W03-A-CTR PIC Z,ZZ9.
10 PIC XXX VALUE SPACES.
10 W03-B-CTR PIC Z,ZZ9.
10 PIC XXX VALUE SPACES.
10 W03-C-CTR PIC Z,ZZ9.
10 PIC XXX VALUE SPACES.
10 W03-D-CTR PIC Z,ZZ9.
10 PIC XXX VALUE SPACES.
10 W03-F-CTR PIC Z,ZZ9.
10 PIC X(59) VALUE SPACES.
01 W04-SYS-DATE.
05 W04-YEAR PIC 9999.
05 W04-MONTH PIC 99.
05 W04-DAY PIC 99.
01 W05-TOTALS.
05 W05-TOTAL-A PIC 99999 VALUE 0.
05 W05-TOTAL-B PIC 99999 VALUE 0.
05 W05-TOTAL-C PIC 99999 VALUE 0.
05 W05-TOTAL-D PIC 99999 VALUE 0.
05 W05-TOTAL-F PIC 99999 VALUE 0.
Here's procedure division
PROCEDURE DIVISION.
PERFORM A100-OPEN-FILES
PERFORM A200-WRITE-HEADINGS
PERFORM A300-PROCESS-SUBJECTS
PERFORM A400-PROCESS-MARKS
PERFORM A500-WRITE-TOTALS
PERFORM A600-CLOSE-FILES
STOP RUN
.
A100-OPEN-FILES.
* OPENS FILES
OPEN INPUT F01-SUBJ-FILE
F02-MARK-FILE
OPEN OUTPUT F03-REPT-FILE
.
A200-WRITE-HEADINGS.
* WRITES HEADERS TO THE REPORT FILE
MOVE W03-HEADER-ROW1 TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
MOVE FUNCTION CURRENT-DATE (1:8) TO W04-SYS-DATE
MOVE W04-YEAR TO W03-YEAR
MOVE W04-MONTH TO W03-MONTH
MOVE W04-DAY TO W03-DAY
MOVE W03-HEADER-ROW2 TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
MOVE W03-HEADER-ROW3 TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
.
A300-PROCESS-SUBJECTS.
* MOVES SUBJECT NAMES AND CODES INTO W02-TEST-TABLE
PERFORM A310-READ-RECORD
PERFORM UNTIL W01-SUBJ-EOF = 'Y'
IF W02-SUBJ-COUNT < W02-SUBJ-MAX
ADD 1 TO W02-SUBJ-COUNT
SET W02-IDX TO W02-SUBJ-COUNT
MOVE F01-SUBJ-CODE TO W02-SUBJ-CODE(W02-IDX)
MOVE F01-SUBJ-NAME TO W02-SUBJ-NAME(W02-IDX)
ELSE
DISPLAY "ERROR - SUBJECT FILE EXCEEDS MAX OF "
W02-SUBJ-MAX " RECORDS, RECORD IGNORED"
END-IF
PERFORM A310-READ-RECORD
END-PERFORM
.
A310-READ-RECORD.
* READS FROM THE SUBJECT FILE INTO THE SUBJECT RECORD
READ F01-SUBJ-FILE
AT END MOVE 'Y' TO W01-SUBJ-EOF
END-READ
.
A400-PROCESS-MARKS.
PERFORM A410-READ-RECORD
PERFORM A420-COUNT-MARKS
UNTIL W01-MARK-EOF = 'Y'
.
A410-READ-RECORD.
* READS FROM THE MARK FILE INTO THE MARK RECORD
READ F02-MARK-FILE
AT END MOVE 'Y' TO W01-MARK-EOF
END-READ
.
A420-COUNT-MARKS.
* COUNTS GRADE TOTALS
SET W02-IDX TO 1
SEARCH ALL W02-TEST-ROW
AT END DISPLAY 'INVALID INPUT RECORD: ' F02-MARK-RECORD
WHEN W02-SUBJ-CODE(W02-IDX) = F02-SUBJ-CODE
EVALUATE F02-STUD-MARK
WHEN "80" THRU "100"
ADD 1 TO W05-TOTAL-A
ADD 1 TO W02-A-CTR(W02-IDX)
WHEN "70" THRU "79"
ADD 1 TO W05-TOTAL-B
ADD 1 TO W02-B-CTR(W02-IDX)
WHEN "60" THRU "69"
ADD 1 TO W05-TOTAL-C
ADD 1 TO W02-C-CTR(W02-IDX)
WHEN "50" THRU "59"
ADD 1 TO W05-TOTAL-D
ADD 1 TO W02-D-CTR(W02-IDX)
WHEN OTHER
ADD 1 TO W05-TOTAL-F
ADD 1 TO W02-F-CTR(W02-IDX)
END-EVALUATE
END-SEARCH
.
A500-WRITE-TOTALS.
PERFORM A510-WRITE-SUBJ-GRADE-TOTALS
PERFORM A520-WRITE-GRADE-GRAND-TOTALS
.
A510-WRITE-SUBJ-GRADE-TOTALS.
PERFORM VARYING W02-IDX FROM 1 BY 1
UNTIL W02-IDX > W02-SUBJ-COUNT
MOVE W02-SUBJ-NAME(W02-IDX) TO W03-SUBJ-NAME
MOVE W02-A-CTR(W02-IDX) TO W03-A-CTR
MOVE W02-B-CTR(W02-IDX) TO W03-B-CTR
MOVE W02-C-CTR(W02-IDX) TO W03-C-CTR
MOVE W02-D-CTR(W02-IDX) TO W03-D-CTR
MOVE W02-F-CTR(W02-IDX) TO W03-F-CTR
MOVE W03-DETAIL-ROW TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
END-PERFORM
.
A520-WRITE-GRADE-GRAND-TOTALS.
* WRITES THE GRADE GRAND TOTALS TO THE REPORT FILE
* AFTER INSERTING A BLANK ROW
MOVE SPACES TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
MOVE W05-TOTAL-A TO W03-TOTAL-A
MOVE W05-TOTAL-B TO W03-TOTAL-B
MOVE W05-TOTAL-C TO W03-TOTAL-C
MOVE W05-TOTAL-D TO W03-TOTAL-D
MOVE W05-TOTAL-F TO W03-TOTAL-F
MOVE W03-TOTAL-ROW TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
.
A600-CLOSE-FILES.
* CLOSES THE FILES
CLOSE F01-SUBJ-FILE
F02-MARK-FILE
F03-REPT-FILE
.
I'm glad you figured it out, Tom.
I hope you're not turned off and will explore further. FYI, while ISPF, TSO/E, and other classic user interfaces still work (and some people still like them, and they'll continue to work "forever"), nowadays developers often use and prefer graphical user interfaces. There are some free ones, for example IBM Explorer for z/OS and its Remote System Explorer (RSE):
https://developer.ibm.com/mainframe/products/zosexplorer/
That works just fine on its own on a Mac or PC (Linux or Windows), as you prefer (with the RSE part on z/OS). All free. Or, if you wish, you can add a more "COBOL aware" editor (among several other features) if you add the IBM Z Open Development plug-ins:
https://developer.ibm.com/mainframe/products/ibm-z-open-development/
And that works too, free for 90 days. At the end of the 90 days you can either pay the going price to keep those plug-ins or uninstall them and just use the base/free Explorer for z/OS functions.
Maybe this'd be good feedback to your instructor/professor? Yes, your first experience with any programming language can be (for example) via emacs and a terminal emulator. Yes, you can write Apple Swift code (for example) with emacs, ISPF, or vi. However, these classic user interfaces aren't everybody's favorite firsts. Again, if you like a particular UI, and it works for you, no problem! But from a pedagogical perspective it's probably best to start with something more familiar to the audience.
On edit: As another example, if you happen to prefer Microsoft Visual Studio Code, then you can add IBM Z Open Editor free of charge to that IDE.
I figured out what was wrong with my program by placing a DISPLAY at the start of each function which output what function was running. I saw that it was in an infinite loop in A420-COUNT-MARKS and that I forgot to add a PERFORM A410-READ-RECORD at the end of it.

I have written a Cobol Report Writer program, but I cannot compile it

I wrote this after I read that Cobol supports Report Writer, only to discover afterwards the version of z/OS we have here at school doesn't actually support it.
I'm wondering if there is a way for this to easily be converted to basic Cobol or if there is any kind of compiler i might find and use.
Thanks for any help you can offer.
Having seen the REPORT SECTION; yes, it may be easily converted.
For the conversion, a choice needs to be made between using IBM POSITIONING or standard COBOL ADVANCING in the WRITE statement; and END-OF-PAGE exception or writing your own code for moving to the next page.
I adjusted some spacing and made a few corrections to the original. I generated 120 records for test data, all random numbers.
REPORT SECTION.
RD PRODUCT-REPORT
PAGE LIMIT 59
HEADING 1
FIRST DETAIL 6
LAST DETAIL 59.
01 HEAD1 TYPE PH.
03 LINE 1.
05 COLUMN 1 PIC X(5) VALUE 'DATE:'.
05 COLUMN 8 PIC 9(2) SOURCE WS-CD-MONTH.
05 COLUMN 10 PIC X VALUE '/'.
05 COLUMN 11 PIC 9(2) SOURCE WS-CD-DAY.
05 COLUMN 13 PIC X VALUE '/'.
05 COLUMN 14 PIC 9(2) SOURCE WS-CD-YEAR.
05 COLUMN 33 PIC X(19) VALUE 'MASTER PRODUCT LIST'.
05 COLUMN 72 PIC X(5) VALUE 'PAGE:'.
05 COLUMN 77 PIC ZZ9 SOURCE PAGE-COUNTER.
03 LINE 2.
05 COLUMN 1 PIC X(5) VALUE 'TIME:'.
05 COLUMN 9 PIC 9(2) SOURCE WS-CD-HOURS.
05 COLUMN 11 PIC X VALUE ':'.
05 COLUMN 12 PIC 9(2) SOURCE WS-CD-MINUTES.
05 COLUMN 72 PIC X(8) VALUE 'PRODLIST'.
03 LINE 4.
05 COLUMN 1 PIC X(5) VALUE 'CODE:'.
05 COLUMN 8 PIC X(5) VALUE 'TYPE:'.
05 COLUMN 18 PIC X(12) VALUE 'DESCRIPTION:'.
05 COLUMN 66 PIC X(6) VALUE 'PRICE:'.
03 LINE 5.
05 COLUMN 1 PIC X(80) VALUE ALL '='.
01 PRODLINE TYPE DE.
03 LINE PLUS 1.
05 COLUMN 1 PIC X(5) SOURCE PRODCODE.
05 COLUMN 8 PIC X(8) SOURCE PRODTYPE.
05 COLUMN 18 PIC X(32) SOURCE PRODDESC.
05 COLUMN 66 PIC $ZZZ,ZZZ,ZZ9 SOURCE PRODCOST.
Ran the program and got this partial output.
DATE: 11/08/18 MASTER PRODUCT LIST PAGE: 1
TIME: 15:54 PRODLIST
CODE: TYPE: DESCRIPTION: PRICE:
================================================================================
47638 54784935 48116892 $ 1,461,160
26450 06251370 81421270 $ 7,765,877
The IBM COBOL family does provide Report Writer. All you need is a compiler "plug-in". Look for product 5798-DYR COBOL Report writer Precompiler. It works seamlessly. No need to convert any code. Ask for free on-line user manual.

How do I move a PIC X field to a PIC S9 COMP-3 field in COBOL?

My situation is as follows.
I'm reading input from a file into the following working storage field:
WORKING-STORAGE SECTION.
01 WORK-FIELDS.
05 W1-INPUT.
10 TESTCASE-NUMBER PIC X(02).
10 PIC X(01).
10 TESTCASE-ID PIC X(18).
10 PIC X(01).
10 TESTCASE-CONTENT PIC X(20).
Depending on what the TESTCASE-ID contains, I have to eventually move the content of the TESTCASE-CONTENT field into either the AMOUNT-DECIMAL-FORMAT or the AMOUNT-DECIMAL-NUMBER field in the following copybook:
05 (*)AMOUNT.
10 AMOUNT-DECIMAL-FORMAT PIC S9(18) COMP-3.
10 AMOUNT-DECIMAL-NUMBER PIC S9(01) COMP-3.
10 AMOUNT-IN-XML-FORMAT PIC N(20).
I then have to do a call to another program which will process these parameters and fill the AMOUNT-IN-XML-FORMAT field.
Anyway, so my question is: What's the best way to move the content of my PIC X field into my S9 COMP-3 field?
Thanks in advance for your time!

Resources