Cobol Treating Multiple Lines as One Line When it Should Not - cobol

Trying to code a cobol program and it keeps treating multiple lines as one line when compiling with opencobol (have to use opencobol, I've heard GNU is better), giving errors
The code is
IDENTIFICATION DIVISION.
PROGRAM-ID. InteractiveProcessing.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT INVENTORY-FILE
ASSIGN TO "C:\COBOL\INVENTORY-FILE.DAT"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD INVENTORY-FILE.
01 FILE-OUTPUT.
05 PART-NO PIC X(5).
05 PART-DESC PIC X(15).
05 QTY-ON-HAND PIC 9(5).
05 UNIT-PRICE PIC 999V99.
WORKING-STORAGE SECTION.
01 MORE-DATA PIC X(3) VALUE 'YES'.
PROCEDURE DIVISION.
100-MAIN-MODULE.
OPEN OUTPUT INVENTORY-FILE
PERFORM UNTIL MORE-DATA = 'NO '
PERFORM 200-INVENTORY-MODULE
DISPLAY 'ENTER MORE DATA? (YES/NO)'
ACCEPT MORE-DATA
END-PERFORM
CLOSE INVENTORY-FILE
STOP RUN.
200-INVENTORY-MODULE.
DISPLAY 'ENTER PART NUM (5 CHARACTERS)'
ACCEPT PART-NO
DISPLAY 'ENTER PART DESCRIPTION (15 CHARACTERS)'
ACCEPT PART-DESC
DISPLAY 'ENTER QUANTITY ON HAND(INTEGER, UP TO 5 DIGITS)'
ACCEPT QTY-ON-HAND
DISPLAY 'ENTER UNIT PRICE (5 DIGITS, 2 AFTER DECIMAL)'
ACCEPT UNIT-PRICE
WRITE FILE-OUTPUT.
The errors I keep getting say
'ENTER' undefined
and
syntax error, unexpected UNIT
The line the errors are appearing on is
DISPLAY 'ENTER QUANTITY ON HAND(INTEGER, UP TO 5 DIGITS)'
The errors are from ENTER and UNIT from two lines down and I can't figure out why this is happening. Changing the quotation marks from single to double on just that line then gives an unexpected end of file error as well.

The problem was that I used tab to align the PIC clauses. Had the same issue in another program. Solved by backspacing the tabs then just using the spacebar to get the clauses to the right spot. Looks the same in the end but actually ran this way.

Related

COBOL error with numeric variable, not numeric

problem
I'm a beginner in COBOL and I'm running into this annoying problem which I can not find a solution for.
I want to add the value of the amount of sales to another numeric variable so that I can use it as a condition for a perform loop but when it tries to add that value to this new variable it triggers this error:
"libcob: PROG-PAGOS-F.cbl: 57: 'WS-CANTIDAD-VENTAS' not numeric: '2 '
WARNING - Implicit CLOSE of REG-VENDEDORES ('REG-MAESTRO.DAT')"
and I can not find a way around it; I'm stuck.
current code (not finished)
What this program is supposed to do is output data of employees' salary, sells, price of each sell into a file and then do some other operations with them but I can't do any progress because of this error, I'd love some help, and perhaps some advices to makes this code better. Thank you!
My variables are in Spanish because I'm Argentinian, sorry if it's hard to understand.
IDENTIFICATION DIVISION.
PROGRAM-ID. PROG-PAGOS-F.
AUTHOR. LUCAS GALEANO.
DATE-WRITTEN. 1/2/2023.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT REG-VENDEDORES ASSIGN TO "REG-MAESTRO.DAT"
ORGANIZATION IS LINE SEQUENTIAL.
SELECT REG-VENTAS ASSIGN TO "REG-VENTAS-MAESTRO.DAT"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD REG-VENDEDORES.
01 VENDEDORES PIC 9(11).
FD REG-VENTAS.
01 COBRO-VENTAS PIC 9(5).
WORKING-STORAGE SECTION.
01 WS-VENDEDORES.
05 WS-EMPLEADO PIC 999.
05 WS-SUELDO-BASE PIC 9(5).
05 WS-CANTIDAD-VENTAS PIC 999.
77 WS-COBROS PIC 9(5).
77 WS-SUM-VENTAS PIC 99.
77 WS-CONTADOR PIC 99 VALUE ZEROS.
01 WS-TABLAS.
05 WS-REGISTRO-COBROS PIC 9(5)
OCCURS 100 TIMES.
PROCEDURE DIVISION.
BEGIN-OUTPUT.
OPEN OUTPUT REG-VENDEDORES.
DISPLAY "INGRESE DATOS SOLICITADOS".
PERFORM INGRESO-DATOS-EMPLEADOS.
PERFORM UNTIL WS-VENDEDORES EQUALS SPACES
WRITE VENDEDORES FROM WS-VENDEDORES
PERFORM INGRESO-DATOS-EMPLEADOS
END-PERFORM.
DISPLAY "INGRESE COBROS DE CADA VENTA:".
PERFORM INGRESO-VENTAS WITH TEST AFTER
UNTIL WS-CONTADOR EQUALS WS-SUM-VENTAS
MOVE WS-COBROS TO WS-REGISTRO-COBROS(1)
CLOSE REG-VENDEDORES.
STOP RUN.
INGRESO-DATOS-EMPLEADOS.
DISPLAY "EEE$$$$$VVV".
ACCEPT WS-VENDEDORES.
ADD WS-CANTIDAD-VENTAS TO WS-SUM-VENTAS.
INGRESO-VENTAS.
ADD 1 TO WS-CONTADOR.
DISPLAY "$$$$$".
ACCEPT WS-COBROS.
example input data
INGRESE DATOS SOLICITADOS
EEE$$$$$VVV
1 400002
There is no implicit conversion in ACCEPT data-item, so you need to convert - and validate it on your own (or switch to "extended" screenio with ACCEPT data-item AT / SCREEN SECTION, but then the result would be depending on the actual COBOL environment).
The easiest option to convert (will sip leading/trailing spaces and invalid data) is something like the following:
ACCEPT WS-VENDEDORES. *> all data may now be invalid
MOVE FUNCTION NUMVAL (WS-EMPLEADO) TO WS-EMPLEADO
MOVE FUNCTION NUMVAL (WS-SUELDO-BASE) TO WS-SUELDO-BASE
MOVE FUNCTION NUMVAL (WS-CANTIDAD-VENTAS) TO WS-CANTIDAD-VENTAS
*> all data is now valid
For validation you may want to use FUNCITON TEST-NUMVAL (data-to-verify).
In any case I'd suggest to check out SCREEN SECTION, as this would allow you to input the data in three separate fields and commonly would do validation and conversion "on the fly".

COBOL: Can a GDG file descriptor (FD) reference multiple generations?

I have a program which reads a GDG file and moves data to working storage. I am interested to know if it can be made to repeat this process for multiple generations of the GDG using a reference to the file definition. Perhaps there is a way to use subscripts on the file definition? My thought is there must be a method to move different file definitions into a reference variable from which to access the files.
Code Sample based on suggested, setenv solution
FILE-CONTROL.
SELECT DATAIN ASSIGN TO UT-S-DATAIN.
DATA DIVISION.
FILE-SECTION.
FD DATAIN
BLOCK CONTAINS 0 RECORDS
RECORD CONTAINS 133 CHARACTERS
LABEL RECORDS ARE STANDARD
DATA RECORD IS DATA-REC.
01 DATA-REC PIC X(133).
WORKING-STORAGE SECTION.
01 ENV-VARS.
02 ENV-NAME PIC X(9).
02 ENV-VALUE PIC X(100).
02 ENV-OVERWRITE PIC S9(8) COMPUTATIONAL VALUE 1.
PROCEDURE DIVISION.
MOVE Z"DATAIN" TO ENV-NAME
MOVE Z"DSN(PROGRAMMER.TEST.GDGFILE(-1)),SHR" TO ENV-VALUE
MOVE 1 TO ENV-OVERWRITE
CALL "setenv" USING ENV-NAME ENV-VALUE ENV-OVERWRITE.
Notes
Pay special attention when moving DSN value to ENV-VALUE. On my first swing I left out the closing parentheses, most likely because of JCL muscle memory.
Be sure to empty out your DD statement in JCL/Step.
In mainframe COBOL, the FD refers to a SELECT which refers to a DD statement attached to the EXEC PGM statement for your program in the invoking JCL. The DD statement may refer to one or many GDGs. This is determined at compile time.
What I think you are asking for is dynamic allocation of a file at runtime. There are a couple of ways to accomplish that, one is BPXWDYN.
Identification Division.
Program-ID. SOMETEST.
Environment Division.
Input-Output Section.
File-Control.
Select MY-FILE Assign SYSUT1A.
Data Division.
File Section.
FD MY-FILE
Record 80
Block 0
Recording F.
01 MY-FILE-REC PIC X(080).
Working-Storage Section.
01 CONSTANTS.
05 BPXWDYN-PGM PIC X(008) VALUE 'BPXWDYN '.
05 ALCT-LIT-PROC PIC X(035)
VALUE 'ALLOC FI(SYSUT1A) SHR MSG(WTP) DSN('.
05 FREE-LIT-PROC PIC X(016)
VALUE 'FREE FI(SYSUT1A)'.
05 A-QUOTE PIC X(001) VALUE "'".
01 WORK-AREAS.
05 WS-DSN PIC X(044) VALUE 'MY.GDG.BASE'.
05 WS-GDG-NB PIC 999 VALUE ZEROS.
05 BPXWDYN-PARM.
10 PIC S9(004) COMP-5 VALUE +100.
10 BPXWDYN-PARM-TXT PIC X(100).
Procedure Division.
* Construct the allocation string for BPXWDYN.
MOVE SPACES TO BPXWDYN-PARM-TXT
STRING
ALCT-LIT-PROC
DELIMITED SIZE
WS-DSN
DELIMITED SPACE
'(-'
DELIMITED SIZE
WS-GDG-NB
DELIMITED SIZE
')'
DELIMITED SIZE
INTO
BPXWDYN-PARM-TXT
END-STRING
CALL BPXWDYN-PGM USING
BPXWDYN-PARM
END-CALL
IF RETURN-CODE = 0
CONTINUE
ELSE
[error handling]
END-IF
[file I/O with MY-FILE]
MOVE SPACES TO BPXWDYN-PARM-TXT
MOVE FREE-LIT-PROC TO BPXWDYN-PARM-TXT
CALL BPXWDYN-PGM USING
BPXWDYN-PARM
END-CALL
IF RETURN-CODE = 0
CONTINUE
ELSE
[error handling]
END-IF
GOBACK.
This is just freehand, so there may be a syntax error, but I hope I've made the idea clear.
There is another technique, using the C RTL function setenv, documented by IBM here. It looks like it might be simpler but I've never done it that way.

The system detected a protection exception

I am trying to use the SORT feature of COBOL.
IDENTIFICATION DIVISION.
PROGRAM-ID. ******.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO IFILE.
SELECT OUT-FILE ASSIGN TO OFILE.
SELECT SORT-FILE ASSIGN TO SORTWK.
DATA DIVISION.
FILE SECTION.
SD SORT-FILE.
01 SORT-REC.
05 S-NAME PIC X(20).
05 S-ADDRESS PIC X(20).
05 S-ID PIC 9(9).
05 S-CREDITS PIC 99.
05 FILLER PIC X(29).
FD IN-FILE.
01 IN-REC.
05 IN-NAME PIC X(20).
05 IN-ADDRESS PIC X(20).
05 IN-ID PIC 9(9).
05 IN-CREDITS PIC 99.
05 FILLER PIC X(29).
FD OUT-FILE.
01 OUT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-WORK-AREA.
05 EOF-SW PIC X VALUE SPACES.
01 WS-DETAIL-LINES.
05 RPT-LINE.
10 OUT-NAME PIC X(20).
10 OUT-ADDRESS PIC X(20).
10 OUT-ID PIC 9(9).
10 OUT-CREDITS PIC 99.
10 FILLER PIC X(29) VALUE SPACES.
PROCEDURE DIVISION.
MAIN-RTN.
SORT SORT-FILE
ON ASCENDING KEY S-ID
INPUT PROCEDURE READ-RELEASE
OUTPUT PROCEDURE RETURN-WRITE.
STOP RUN.
OPEN-FILES-RTN.
OPEN INPUT IN-FILE.
OPEN OUTPUT OUT-FILE.
OPEN-FILES-RTN-EXIT. EXIT.
READ-RELEASE.
PERFORM OPEN-FILES-RTN.
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'.
READ-RELEASE-RTN-EXIT. EXIT.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW.
RELEASE SORT-REC FROM IN-REC.
RETURN-WRITE.
MOVE SPACES TO EOF-SW.
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'.
PERFORM CLOSE-FILES-RTN.
RETURN-WRITE-RTN-EXIT. EXIT.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW.
WRITE OUT-REC.
WRITE-FL-RTN-EXIT. EXIT.
CLOSE-FILES-RTN.
CLOSE IN-FILE OUT-FILE.
CLOSE-FILES-RTN-EXIT. EXIT.
I am able to compile this program but when it comes to execute, it gives the following error:
CEE3204S The system detected a protection exception (System Completion
Code=0C4). From compile unit SU98PGM6 at entry point SU98PGM6
at compile unit offset +0005517A at address 1F45517A.
I have searched about this error but I couldn't figure out what is causing this problem in my program.
I have made some changes after taking note of the comments, but am still getting the same problem with this changed code.
READ-RELEASE.
PERFORM OPEN-FILES-RTN.
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'.
READ-RELEASE-RTN-EXIT. EXIT.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW
NOT AT END PERFORM PROCESS-INPUT.
PROCESS-INPUT.
MOVE IN-NAME TO S-NAME.
MOVE IN-ADDRESS TO S-ADDRESS.
MOVE IN-ID TO S-ID.
MOVE IN-CREDITS TO S-CREDITS.
RELEASE SORT-REC.
PROCESS-INPUT-RTN-EXIT. EXIT.
RETURN-WRITE.
MOVE SPACES TO EOF-SW.
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'.
PERFORM CLOSE-FILES-RTN.
RETURN-WRITE-RTN-EXIT. EXIT.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW
NOT AT END PERFORM PROCESS-OUTPUT.
WRITE-FL-RTN-EXIT. EXIT.
PROCESS-OUTPUT.
MOVE S-NAME TO OUT-NAME.
MOVE S-ADDRESS TO OUT-ADDRESS.
MOVE S-ID TO OUT-ID.
MOVE S-CREDITS TO OUT-CREDITS.
WRITE OUT-REC.
PROCESS-OUTPUT-RTN-EXIT. EXIT.
Here is my JCL
//******** JOB 1,'*****',NOTIFY=*******
//JOBLIB DD DSN=*******.*******.*******,DISP=SHR
//STEP0 EXEC PGM=SU98PGM6
//IFILE DD DSN=*******.*******.*******.*******(*******),DISP=SHR
//SORTWK DD DSN=*******.*******.*******.*******,DISP=SHR
//OFILE DD DSN=*******.*******.*******.*******,
// DISP=(NEW,CATLG,DELETE),
// DCB=(BLKSIZE=0,LRECL=80,RECFM=FB),
// SPACE=(CYL,(1,1),RLSE),
// UNIT=SYSDA
/*
The output for the //SYSOUT DD can be confusing when using COBOL, SORT (DFSORT or SyncSORT) and Language Environment which may give you run-time messages, as they all use SYSOUT by default, and the messages will appear intermingled.
Fortunately, you can change the default behaviour, as shown here for DFSORT and Language Envrionment (there are many ways in LE to specify the option, the most flexible is a //CEEOPTS DD in your JCL): https://stackoverflow.com/a/29521423/1927206
COBOL itself has a compiler option, OUTDD. the value defaults to SYSOUT, but you can specify any OUTDD(xxxx)
OK, having seen your JCL and your comments about how a DISPLAY statement in your program affects the data, I've managed a partial reproduce.
I use DFSORT, and I don't get your exact behaviour so I'm going to assume you use SYNCSORT.
The behaviour I can get having removed the //SYSOUT DD from my JCL is this message:
IGZ0026W The SORT-RETURN special register was never referenced, but
the current content indicated the sort or merge operation in program
STOB87 on line number 46 was unsuccessful.
When I add the //SYSOUT back into the JCL, the program runs successfully.
When I take the //SYSOUT out and add a DISPLAY before the SORT, the program works. This is because if there is no //SYSOUT in the JCL the first DISPLAY which is executed will cause one to be dynamically created (the output will appear in the spool as though it were a separate JOB, with the same name and jobnumber).
In my case DFSORT is complaining about the missing //SYSOUT. With the DISPLAY, the //SYSOUT is not missing at the time DFSORT starts.
I have to assume that SYNCSORT is facing a similar issue, but the run-time COBOL message is not produced and SYNCSORT itself fails on the next RELEASE.
Although this seems like a simple and common issue, because we always copy a piece of JCL to make a new piece of JCL, //SYSOUT is always there.
Consult the Enterprise COBOL Programming Guide, Chapter 12 I think, and see how to use SORT-RETURN to confirm that the SORT completed successfully.
I'm pretty sure that if you include the //SYSOUT in your JCL you will no longer get the abend, whether or not you have a DISPLAY.
The reason for the high "offset" is that the abend processor is unable to identify the entry-point of your SORT product, so keeps searching backwards to find something it can identify, and locates your program entry-point and then calculates the incorrect offset. This can also happen when CALLing some Assembler programs.
Firstly, to your S0C4, which is a Protection Exception, which means you are attempting to access storage which doesn't "belong" to you for the access you want.
You are getting a S0C4 in program SU98PGM6. You have cunningly obliterated your PROGRAM-ID name when posting here, which probably hasn't helped.
SU98PGM6 is not your program. The abend (Abnormal End) is at offset X'0005517A' in the failing program. That means, from the "start" of the program (the Entry Point) the instruction at offset/displacement X'0005517A' is the one which attempted the bad thing. That offset, which in decimal is 348538, indicates a fairly large program. Your program is very small.
There are many ways that this can come about. For instance, you may have copied the JCL from somewhere else, and failed to change the EXEC PGM=. You may have a program of the same name as yours earlier in the STEPLIB concatenation. You may have compiled the wrong program. Etc.
When you get an abend, always confirm that the compile listing you have is for the program that abended. An easy and useful way to do this is:
01 W-WHEN-COMPILED PIC X(8)BX(8).
...
* where it can only be executed once:
MOVE WHEN-COMPILED TO W-WHEN-COMPILED
DISPLAY
"yourname COMPILED ON "
W-WHEN-COMPILED
"yourname" you replace with the text following PROGRAM-ID.
The output will be like this:
yourname COMPILED ON 11/24/15 10.35.26
That will match the date/time in the heading on each page of the compile listing.
If you run a program and don't get that output, or you get output but it is not the output expected, then you know your program is not the one running.
Now to your program.
You do not need to use input/output procedures to be able to SORT
You should always use the FILE STATUS clause of the SELECT statement, and always check the file-status fields (one per file) that you define, after each IO operation. Testing the file-status field for an input file will allow you to identify end-of-file without the need for the tortuous AT END/NOT AT END construct
If you use sort procedures, COBOL does the IO. If you don't, and use compiler option FASTSRT, your SORT product will do the IO, which will be much more efficient than COBOL.
Unless you are selecting or reformatting records, you don't need the sort procedures
Since you are using INTO, which does an implicit MOVE of the record, you don't need to also MOVE the data individually
COBOL, since compilers supporting the 1985 Standard, which I'm fairly sure you will have, have "scope terminators". Prior to that, the only scope-terminator was the full-stop/period. These days, use the explicit, specific scope-terminators when using "imperative statements" and for all conditional statements. In your case, replace use READ/END-READ, RETURN/END-RETURN
Only use full-stops/periods in the PROCEDURE DIVISION where they are required, and not on a line of code. This aids the moving/copying of code from one location to another
Use 88-level condition-names for tests, rather than literals. You can make the name exactly meaningful, so nobody ever has to wonder what 'F' means in a particular context
To simply SORT a file in a COBOL program, look at SORT ... USING ... GIVING... and use compiler option FASTSRT (if possible).
You are not yet aware of the implications of paragraphs (or SECTIONs) and the EXIT statement.
When using PERFORM or a SORT PROCEDURE execution is transferred to the code in the paragraph, and returns control when the next paragraph is reached.
Your "exit" paragraphs as you have coded are never used, but someone looking at the code will assume (if they are silly, and a lot of people will make the assumption) that you have used THRU and they'll stick in a GO TO the "exit" paragraph. Then they'll be surprised that the program behaves badly (if they're luck) and will eventually work out that they have used GO TO to transfer control out of the range of the PERFORM/PROCEDURE.
If your local standards enforce the use of exit-paragraphs, then you must use THRU in your PERFORM and PROCEDURE statements.
Exit-paragraphs are entirely useless, and do nothing but provide a target-label for a GO TO, meaning that someone in the future will likely use a GO TO for "convenience".
Here's your original program with the exit-paragraphs removed:
IDENTIFICATION DIVISION.
PROGRAM-ID. ******.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO IFILE.
SELECT OUT-FILE ASSIGN TO OFILE.
SELECT SORT-FILE ASSIGN TO SORTWK.
DATA DIVISION.
FILE SECTION.
SD SORT-FILE.
01 SORT-REC.
05 S-NAME PIC X(20).
05 S-ADDRESS PIC X(20).
05 S-ID PIC 9(9).
05 S-CREDITS PIC 99.
05 FILLER PIC X(29).
FD IN-FILE.
01 IN-REC.
05 IN-NAME PIC X(20).
05 IN-ADDRESS PIC X(20).
05 IN-ID PIC 9(9).
05 IN-CREDITS PIC 99.
05 FILLER PIC X(29).
FD OUT-FILE.
01 OUT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-WORK-AREA.
05 EOF-SW PIC X VALUE SPACES.
01 WS-DETAIL-LINES.
05 RPT-LINE.
10 OUT-NAME PIC X(20).
10 OUT-ADDRESS PIC X(20).
10 OUT-ID PIC 9(9).
10 OUT-CREDITS PIC 99.
10 FILLER PIC X(29) VALUE SPACES.
PROCEDURE DIVISION.
SORT SORT-FILE
ON ASCENDING KEY S-ID
INPUT PROCEDURE READ-RELEASE
OUTPUT PROCEDURE RETURN-WRITE
GOBACK
.
OPEN-FILES-RTN.
OPEN INPUT IN-FILE
OPEN OUTPUT OUT-FILE
.
READ-RELEASE.
PERFORM OPEN-FILES-RTN
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'
.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW
END-READ
RELEASE SORT-REC FROM IN-REC
.
RETURN-WRITE.
MOVE SPACES TO EOF-SW
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'
PERFORM CLOSE-FILES-RTN
.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW
END-RETURN
WRITE OUT-REC
.
CLOSE-FILES-RTN.
CLOSE IN-FILE OUT-FILE
.
I've also changed the STOP RUN to GOBACK, which is much more flexible, and removed your first paragraph-name, as it is unnecessary and for people new to COBOL implies too much (COBOL itself has no concept of "main" as it may be pertinent in other languages you may know).

Read a file with three records, only one of expected records output

IDENTIFICATION DIVISION.
PROGRAM-ID. PROGRAM1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT EMP-GRADE ASSIGN TO 'input.txt'
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS WS-STATUS.
DATA DIVISION.
FILE SECTION.
FD EMP-GRADE.
01 NEWFILE.
05 FS-EMPID PIC 9(5).
05 FS-NAME PIC A(5).
05 FS-STREAM PIC X(5).
05 FS-GRADE PIC A(1).
05 FILLER PIC X(64).
WORKING-STORAGE SECTION.
01 WS-EOF PIC A(1) VALUE "N".
01 WS-STATUS PIC X(2).
PROCEDURE DIVISION.
MAIN-PARA.
OPEN INPUT EMP-GRADE.
PERFORM PARA1 THRU PARA1-EXIT UNTIL WS-EOF="Y".
CLOSE EMP-GRADE.
STOP RUN.
MAIN-PARA-EXIT.
EXIT.
PARA1.
READ EMP-GRADE
AT END MOVE "Y" TO WS-EOF
NOT AT END
IF FS-GRADE='A'
DISPLAY FS-EMPID , FS-NAME , FS-STREAM , FS-GRADE
END-IF
END-READ.
PARA1-EXIT.
EXIT.
input provided:
1234 sita comp A
2345 tina main B
5689 riya math A
but the output is coming :
1234 sita comp A
It is reading only the first record.
As Brian Tiffin is hinting at in the comments, it is your data which is the problem.
This:
05 FILLER PIC X(64).
Means that your records should be 64 bytes longer than they are.
If you have a fixed-length record, or only fixed-length records, under an FD, then the data all have to be the same length, and equal to what you have defined in your program.
It means, and behaviour depends on compiler, you only have one record as far as the COBOL program is concerned.
A good way to spot such things is to always count your input records, and count your output records, and records which should not be selected for output. You can then easily tell if anything has fallen between a crack.
Leaving that aside, here's your program with some adjustments:
IDENTIFICATION DIVISION.
PROGRAM-ID. PROGRAM1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT EMP-GRADE ASSIGN TO 'input.txt'
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS WS-STUDENT-GRADE-STATUS.
DATA DIVISION.
FILE SECTION.
FD EMP-GRADE.
01 NEWFILE.
05 FS-EMPID PIC 9(5).
05 FS-NAME PIC X(5).
05 FS-STREAM PIC X(5).
05 FS-GRADE PIC X(1).
05 FILLER PIC X(64).
WORKING-STORAGE SECTION.
01 WS-STUDENT-GRADE-STATUS PIC X(2).
88 END-OF-STUDENT-GRADE-FILE VALUE "10".
88 ERROR-ON-STUDENT-GRADE-FILE VALUE ZERO.
PROCEDURE DIVISION.
OPEN INPUT EMP-GRADE
* perform a paragraph to check FILE STATUS field is zero, using an 88.
PERFORM PRIMING-READ
PERFORM PROCESS-STUDENT-GRADE-FILE
UNTIL END-OF-STUDENT-GRADE-FILE
CLOSE EMP-GRADE
* perform a paragraph to check FILE STATUS field is zero, using an 88.
GOBACK
.
PRIMING-READ.
PERFORM READ-STUDENT-GRADE
.
READ-STUDENT-GRADE.
READ EMP-GRADE
* perform a paragraph to check FILE STATUS field is zero, using an 88.
.
PROCESS-STUDENT-GRADE-FILE.
IF FS-GRADE='A'
* To see the problem with your data, DISPLAY the 01-level
DISPLAY NEWFILE
DISPLAY FS-EMPID
FS-NAME
FS-STREAM FS-GRADE
END-IF
PERFORM READ-STUDENT-GRADE
.
If you use the FILE STATUS field, you should check it. Since you use it, you can use it to check for end-of-file without the AT END. If you use a "priming read" you don't need the AT END/NOT AT END tangle. If you code the minimum of full-stops/periods in the PROCEDURE DIVISION, you won't have a problem with them. Commas are never needed, so don't use them. Format your program for human readability. Use good descriptive names for everything. The THRU on a PERFORM invites the use of GO TO. As a learning, avoid the invitation.
If your class itself enforces particular ways to code COBOL, you'll have to use those ways. If so, I'd suggest you do both. The first couple of times at least, submit both to your tutor. Even if they tell you not to do that, continue doing dual examples when given tasks (just don't submit them any more). There is no reason for you to start off with bad habits.
Keep everything simple. If your code looks bad, make it look good through simplification and formatting.
Remember also that COBOL is all about fixed-length stuff. Get's us back to your original problem.

Assigning a value to a PIC clause less than specified length

I'm a beginner to COBOL, and i'm wondering what would happen if i did something like the following:
(I know that the below code isnt runnable cobol, its just there for example)
foo pic x(5)
accept foo
and the user types in a string that is only 3 characters long (e.g. yes)
would the value of foo be just "yes"? or would it fill the all 5 characters as specified at creation (for example: "(space)(space)yes" or "yes(space)(space)", or is it something else?
Thanks!
here is my code
000100 IDENTIFICATION DIVISION.
000200 *--------------------
000300 PROGRAM-ID. ZIPCODES.
000400 *--------------------
000500 ENVIRONMENT DIVISION.
000600 *--------------------
000700 CONFIGURATION SECTION.
000800 INPUT-OUTPUT SECTION.
000900 FILE-CONTROL.
001000 SELECT PRT ASSIGN TO UT-S-PRTAREA.
001100
001200 DATA DIVISION.
001300 *-------------
001400 FILE SECTION.
001500 FD PRT
001600 RECORD CONTAINS 80 CHARACTERS
001700 DATA RECORD IS LINE-PRT.
001800 01 LINE-PRT PIC X(80).
001900
002000 WORKING-STORAGE SECTION.
002100 *-----------------------
002200 EXEC SQL INCLUDE SQLCA END-EXEC.
002300
002310 01 done.
002320 02 donevar PIC x(5) VALUE 'done '.
002400 01 ZIP-RECORD.
002500 02 ZIP PIC X(5).
002600 02 ZCITY PIC X(20).
002700 02 ZSTATE PIC X(2).
002800 02 ZLOCATION PIC X(35).
002900
003000 01 H1.
003100 02 COLUMN-1 PIC X(8) VALUE 'Zip-Code'.
003200 02 FILLER PIC X(2).
003300 02 COLUMN-2 PIC X(5) VALUE 'State'.
003400 02 FILLER PIC X(2).
003500 02 COLUMN-3 PIC X(4) VALUE 'City'.
003600 02 FILLER PIC X(16).
003700 02 COLUMN-4 PIC X(14) VALUE 'Location Text'.
003800 02 FILLER PIC X(29).
003900
004000 01 L1.
004100 02 ZIP-L1 PIC X(5).
004200 02 FILLER PIC X(5).
004300 02 STATE-L1 PIC X(2).
004400 02 FILLER PIC X(5).
004500 02 CITY-L1 PIC X(20).
004600 02 LOCTXT-L1 PIC X(35).
004700 02 FILLER PIC X(28).
004800
004900 PROCEDURE DIVISION.
005000 *------------------
005100 BEGIN.
005200 OPEN OUTPUT PRT.
005220 PERFORM ZIP-LOOKUP UNTIL ZIP = done.
005600 PROG-END.
005700 CLOSE PRT.
005800 GOBACK.
005900 *****************************************************
006000 * zip code lookup *
006100 *****************************************************
006200 ZIP-LOOKUP.
006300 DISPLAY 'enter 5 digit zip code'
006400 ACCEPT ZIP
006500 EXEC SQL
006600 SELECT * INTO :ZIP-RECORD FROM ZBANK.ZIPCODE
006700 WHERE ZIP = :ZIP
006800 END-EXEC.
006801 PERFORM PRINT-H1.
006802 PERFORM PRINT-L1.
006900 PRINT-H1.
007000 MOVE H1 TO LINE-PRT
007100 WRITE LINE-PRT.
007200 PRINT-L1.
007300 MOVE ZIP TO ZIP-L1
007400 MOVE ZSTATE TO STATE-L1
007500 MOVE ZCITY TO CITY-L1
007510 STRING ZSTATE DELIMITED BY " ",", ",
007520 ZCITY DELIMITED BY SIZE INTO LOCTXT-L1
007700 MOVE L1 TO LINE-PRT
007800 WRITE LINE-PRT.
I'm trying to write the zstate before the zcity, and having it keep asking for ZIP codes as long as the input isnt 'done'
The first 5 characters entered will be moved to FOO. If fewer than 5 characters are entered then they will be placed in the left hand positions of FOO and the remaining characters (to the right) will be filled with spaces. If the user enters more than 5 charcters then only the first 5 are moved.
So to use your example if the user typed "yes" then FOO would contain "yesbb"
Best thing to do is try it!
Edit in response to updated question...
I think your problem is that the condition needed to terminate the loop is set in the beginning of the loop body and
not at the end. Here are a couple of commonly used techniques to solve this problem:
Pre loop read
DISPLAY 'Enter a 5 digit zip code'
ACCEPT ZIP
PERFORM ZIP-LOOKUP UNTIL ZIP = done.
...
...
ZIP-LOOKUP.
EXEC SQL
SELECT * INTO :ZIP-RECORD FROM ZBANK.ZIPCODE
WHERE ZIP = :ZIP
END-EXEC.
PERFORM PRINT-H1.
PERFORM PRINT-L1.
* Now get next zip code or 'done'
DISPLAY 'Enter a 5 digit zip code'
ACCEPT ZIP
.
Guard against setting terminating condition within the loop
PERFORM ZIP-LOOKUP UNTIL ZIP = done.
...
...
ZIP-LOOKUP.
DISPLAY 'Enter a 5 digit zip code'
ACCEPT ZIP
IF ZIP NOT = DONE
EXEC SQL
SELECT * INTO :ZIP-RECORD FROM ZBANK.ZIPCODE
WHERE ZIP = :ZIP
END-EXEC
PERFORM PRINT-H1
PERFORM PRINT-L1
END-IF
.
Either one of the above should solve your problem. However, I would suggest trying to update your coding style to include
COBOL-85 constructs. The first example above might be coded as follows:
DISPLAY 'Enter a 5 digit zip code'
ACCEPT ZIP
PERFORM UNTIL ZIP = done
EXEC SQL
SELECT * INTO :ZIP-RECORD FROM ZBANK.ZIPCODE
WHERE ZIP = :ZIP
END-EXEC
PERFORM PRINT-H1
PERFORM PRINT-L1
DISPLAY 'Enter a 5 digit zip code'
ACCEPT ZIP
END-PERFORM
.
The ZIP-LOOKUP paragraph has been in-lined into the PERFORM statement. For short sections of code I find this style much more
readable.
Also notice single sentence paragraphs (only one period at the end of a paragraph). When COBOL-85 scope terminators are used (eg. END-xxx)
the need for mulitple sentences per paragraph goes away - and in fact - they should be avoided.
Another COBOL construct that you could make use of here is the 88 LEVEL. You could use it as follows:
01 ZIP-RECORD.
02 ZIP PIC X(5).
88 DONE VALUE 'done '.
...
...
You no longer need donevar at all. Replace your original test:
IF ZIP = DONE
with:
IF DONE
The above will be true whenever the variable ZIP contains the value "donebb". One advantage of
doing this (other than saving one variable declaration) is that a single 88 LEVEL name can be assigned
several values, as in:
01 ZIP-RECORD.
02 ZIP PIC X(5).
88 DONE VALUE 'done ',
'quit ',
'stop '.
When the user enters any one of done, quit or stop the 88 level name DONE evaluates to true.
Finally, I presume this is just a skeleton of the program and that the finished version will be checking for I/O errors, bad SQL codes
and do basic ZIP code validation. If not, you can expect a lot of trouble down the road.
COBOL Reference material
Unfortunately there are very few good up to date resources for learning COBOL. However, one of the
books I would recommend is Advanced Cobol 3rd Edition by DeWard Brown.
This book provides many examples and explanations regarding COBOL program development. It also identifies whether a
construct is rarely used, obsolete or essential. This is good to know since you should be developing new code using modern COBOL
programming techniques (I continue to see a lot of new COBOL developed using pre-COBOL 85 coding practice - and it is horrible).
An open source
guide is the OpenCOBOL Programmers Guide. This targets OpenCOBOL but
much of it is applicable to any flavour of COBOL.
Finally, there are several vendors guides and manuals, many of which are available on the internet. For
example Enterprise COBOL for z/OS Language Reference and
Enterprise COBOL for z/OS Programming guide are
freely available. Microfocus COBOL
guides are also available. Search any you will find...

Resources