Error using OCCURS in a very simple COBOL program - cobol

This is my code where iIam declaring a variable using OCCURS.
IDENTIFICATION DIVISION.
PROGRAM-ID. ARRAYEX.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT StudentFile ASSIGN TO "STUDENTS.DAT"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
WORKING-STORAGE SECTION.
77 WS-FIRSTARR OCCURS 10 TIMES PIC 9(5).
PROCEDURE DIVISION.
DISPLAY "HELLO WORLD".
STOP RUN.
Error:
arrayex.cbl:12: Error: Level 77 item 'WS-FIRSTARR' cannot have OCCURS clause
Any reasons the compilation fails?

A 77 cannot have OCCURS. An 01 cannot have OCCURS. Levels 02-49 can have OCCURS.
Forget level 66 (used for the RENAMES clause) as your should not use it and are unlikely to ever see it.
An 88-level, a Condition Name, cannot have an occurs, but if the field which it is defined on is part of an OCCURS or subordinate to an OCCURS, the 88 will need subscripting like any 02- - 49-level which is also part of, or subordinate to, an OCCURS.
01 a-simple-array-structure.
05 the-data occurs 5 times pic 9(5).
Or you can get more complex.
01 b-structure.
95 the-key pic x(8).
05 some-data pic x(10).
05 some-more-data pic 9(7).
05 a-simple-array.
10 a-simple-array-item occurs 5 times
pic 9(5).
05 a-more-complex-array.
10 complex-entry occurs 10 times.
15 some-complex-data pic xx.
15 another-bit-of-complex-data
pic 9(5).
OCCURS can also be used to define multi-dimensional tables.
05 first-occurs occurs 5 times.
10 second-occurs occurs 5 times.
15 an-item pic xx.
This is still far from the full gamut of OCCURS, so start simple, practice, get it working, become more complex.
There is also OCCURS DEPENDING ON, a variable-length table. One thing at a time. Get a simple OCCURS working, not just the definition, but the use as well, with a field for a subscript, an index for a subscript and a literal for a subscript.
Then get more complex.

COBOL has several "magic" level numbers...
Level-66 items indicate a RENAMES clause is to be expected
Level-77 items are atomic, cannot be subdivided, cannot have an OCCURS clause.
Level-88 indicates a condition-name entry
See pages 5-4 and 5-5 of the programmer's guide.

Related

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).

Is it possible to MOVE to a variable name created during runtime?

I am writing a program that changes the colour of a field if is it a duplicate record. To do this I am using a nested perform to compare each item to each other. When it finds a duplicate I would like to MOVE DFHRED to that specific field for example CRS1AC. My issue is that I don't know how to reference the field I am trying to change the colour of once I've found that is it a duplicate, how do I do this? Here are the fields which are in the MAP file that I am trying to move the colour to if a duplicate exists...
01 CRS1AC PIC X.
01 CRS1BC PIC X.
01 CRS2AC PIC X.
01 CRS2BC PIC X.
01 CRS3AC PIC X.
01 CRS3BC PIC X.
01 CRS4AC PIC X.
01 CRS4BC PIC X.
01 CRS5AC PIC X.
01 CRS5BC PIC X.
here is my table setup...
01 TABLES.
05 TBL-CRS-ENTRIES PIC S9(3) COMP-3 VALUE 5.
05 TBL-CRS-VALUES PIC X(4) OCCURS 10 TIMES.
05 CRS-TBL REDEFINES TBL-CRS-VALUES
PIC X(8) OCCURS 5 TIMES.
05 SUB-1 PIC S9(3) COMP-3 VALUE 1.
05 SUB-2 PIC S9(3) COMP-3 VALUE 1.
& here is the code that checks for duplicates
PERFORM VARYING SUB-1 FROM 1 BY 1 UNTIL SUB-1 > TBL-CRS-ENTRIES
PERFORM VARYING SUB-2 FROM 1 BY 1 UNTIL SUB-2 > SUB-1 - 1
IF CRS-TBL(SUB-1) = CRS-TBL(SUB-2)
*if there is a match it should change the colour to red.
* for example a match at CRS1AC & CRS1BC match CRS3AC & CRS3BC
*this is my attempt at trying make the variable name.
MOVE DFHRED TO CRS(SUB-1)AC
MOVE DFHRED TO CRS(SUB-1)BC
MOVE DFHRED TO CRS(SUB-2)AC
MOVE DFHRED TO CRS(SUB-2)BC
PERFORM 999-DUPLICATE-RECORD
END-IF
END-PERFORM
END-PERFORM.
GOBACK.
So, if 'PSYC 1000' = 'PSYC 1000' & the name of those fields are..
'CRS1AC+CRS1BC = CRS3AC+CRS3BC' <--- these are the fields I want to change the color of.
I've researched this heavily & still cannot find a solution.
Hope this makes sense I know its all over the place, for further clarification please ask & if complete program code is required I can provide it.
No, it is not possible to do what you want how you want.
COBOL is a compiled language. What is relevant about that is that you cannot make up the names of identifiers (variables) at run-time. Once a COBOL program is compiled, that is it, no more changes to the source for that executable version.
Where to go then?
You say this is part of your MAP.
01 CRS1AC PIC X.
01 CRS1BC PIC X.
01 CRS2AC PIC X.
01 CRS2BC PIC X.
01 CRS3AC PIC X.
01 CRS3BC PIC X.
01 CRS4AC PIC X.
01 CRS4BC PIC X.
01 CRS5AC PIC X.
01 CRS5BC PIC X.
But, because of those level-numbers of 01 those aren't part of anything, except the SECTION they belong to within the DATA DIVISION.
So you need to show your full, actual, MAP.
There is not an especially cute way, so what you have to do is REDEFINES the entire MAP, with an OCCURS which represents each screen-line for this portion of the screen (or entire screen, depends on the design) and define those attribute bytes within the OCCURS item.
What is really exciting about this is getting it all to line-up, by hand.
Now your program.
Your loops are wrong. You execute the inner-loop five times for each iteration of the outer-loop. Which means you are doing far more comparisons than necessary.
This is unwieldy:
SUB-2 > SUB-1 - 1
For that line of code, this would be better:
SUB-2 EQUAL TO SUB-1
The fifth outer-iteration is not required at all, because there are no values to compare to other than those which have already been compared (so the result will be the same, so why bother?).
Consider changing the definition of the identifiers (variables) you are using as subscripts and your total of entries to BINARY or COMP or COMP-4 (they all mean the same thing).
Consider giving them more meaningful names than SUB-1, SUB-2. It will make the code "read" better, which always helps.
Here's your data-defintion:
01 TABLES.
05 TBL-CRS-ENTRIES PIC S9(3) COMP-3 VALUE 5.
05 TBL-CRS-VALUES PIC X(4) OCCURS 10 TIMES.
05 CRS-TBL REDEFINES TBL-CRS-VALUES
PIC X(8) OCCURS 5 TIMES.
05 SUB-1 PIC S9(3) COMP-3 VALUE 1.
05 SUB-2 PIC S9(3) COMP-3 VALUE 1.
Some other things to make things easier for yourself:
Don't code identifiers (variables) after an OCCURS. It doesn't greatly matter in itself when there is no DEPENDING ON on the OCCURS, but since it does matter for that, why not be consistent (consistency is great, because when you are looking for a problem and you find inconsistency, it tells something about the writer of that particular bit of code).
Don't REDEFINES items which are defined with OCCURS. Even if you are using an old compiler (either you've put incorrect code here, or you are doing that) that gives you at least a Caution message. Try an experiment. Show that definition to a colleague, and ask them "what does this actually do?" Then show to another. And a third. If they all immediately reply, accurately, what it does, then you have a site with outstanding knowledge. You haven't, so don't do that.
Don't make identifiers signed, unless they can contain negative values. Then the reader can look at the definition and know it can't contain a negative value. Don't fall for "oh, we do it for performance". Name the compiler and show the compile options, and I'll show you what it is "gaining", or losing.
Don't use VALUE clauses for initial values of identifiers used as subscripts. Set them to their initial value before you use them. Unless you have tortuous code setting the value at the end of the current processing so it is ready for the next processing, all you are doing is confusing the human-reader. If there is a VALUE clause, it should be necessary.
Do give everything a good, descriptive, name, if it is being used. If something does not need a name, use FILLER to define it (often).
Your definition could be done like this:
01 some-meaningful-name
05 TBL-CRS-ENTRIES BINARY PIC 9(4) VALUE 5.
05 also-meaningful BINARY PIC 9(4).
05 meaningful-also BINARY PIC 9(4).
05 another-meaningful-name.
10 FILLER OCCURS 10 TIMES.
15 TBL-CRS-VALUES PIC X(4).
05 FILLER REDEFINES another-meaningful-name.
10 FILLER OCCURS 5 TIMES.
15 CRS-TBL PIC X(8).
Source code is for two things: for the compiler to convert into executable code; for the human reader to understand what has been coded. The compiler does not care about formatting the code. So format the code for the human reader. Even little things help:
IF CRS-TBL(SUB-1) = CRS-TBL(SUB-2)
Vs
IF CRS-TBL ( W-ORIGINAL-ITEM )
EQUAL TO CRS-TBL ( W-NEW-ITEM )

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.

Why are my file definitions not working? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I am trying to figure out why my file definitions are incorrect. From what I can tell this is the same way that they were defined in my last program and all will be fixed block records
Code:
FILE-CONTROL.
SELECT INFILE1 ASSIGN TO UT-S-INPUT1.
SELECT INFILE2 ASSIGN TO UT-S-INPUT2.
SELECT OUTPUT-FILE1 ASSIGN TO UT-S-OUTPUT1.
SELECT OUTPUT-FILE2 ASSIGN TO UT-S-OUTPUT2.
DATA DIVISION.
FILE SECTION.
FD INFILE1.
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 INF-LINE1.
05 STATE-1 PIC X(02).
05 KEY-1 PIC X(10).
05 TRANSID1 PIC X(10).
05 FILLER PIC X(58).
FD INFILE2.
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 INF-LINE2.
05 KEY-2 PIC X(10).
05 TRANSID2 PIC X(10).
05 FILLER PIC X(60).
FD OUTPUT-FILE1
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 OUTLINE1 PIC X(80).
FD OUTPUT-FILE2
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 OUTLINE2 PIC X(80).
Error Code: Some of these error codes do not pertain to the file errors but I copied all of them and placed in this section.
20 IGYGR1216-I A "RECORDING MODE" of "F" was assumed for file "INFILE1".
21 IGYDS1089-S "BLOCK" was invalid. Scanning was resumed at the next area "A" item, level-number, or the start of the next
clause.
Same message on line: 31
30 IGYGR1216-I A "RECORDING MODE" of "F" was assumed for file "INFILE2".
283 IGYPA3043-E Data-item "INF-LINE1 (GROUP)" and record "INF-LINE1 (GROUP)" had overlapping storage. Movement of data may
not occur at execution time.
293 IGYPA3043-E Data-item "INF-LINE2 (GROUP)" and record "INF-LINE2 (GROUP)" had overlapping storage. Movement of data may
not occur at execution time.
304 IGYPS2015-I The paragraph or section prior to paragraph or section "X-COMP-FILE" did not contain any statements.
321 IGYPS2121-S "STUB4" was not defined as a data-name. The statement was discarded.
If you remove the period after the file name on our definition statement it should work without compiler errors.
Code:
FD INFILE1
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 INF-LINE1.
05 STATE-1 PIC X(02).
05 KEY-1 PIC X(10).
05 TRANSID1 PIC X(10).
05 FILLER PIC X(58).
FD INFILE2
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 INF-LINE2.
05 KEY-2 PIC X(10).
05 TRANSID2 PIC X(10).
05 FILLER PIC X(60).
This is a common mistake that happens when you look at a green screen all day long. I would recompile this and see if the other errors go away. It is always a good idea to recompile a program and then start fresh. Do you print the compile listing to scan through every-now-and-then. I would I think. The compile listing gives you all of the memory locations and the size of each record. It is very handy.
Code:
30 IGYGR1216-I A "RECORDING MODE" of "F" was assumed for file "INFILE2".
I am not certain on this error but I bet that you have the F a V for fixed block files. I would check this and if that is the case fix it. Do you start from scratch on programs or do you take a working program and then gut out what you do not need and then start working from that perspective. If this is the case you want to make certain that you have the recording mode set correctly for fixed block and variable block files.
321 IGYPS2121-S "STUB4" was not defined as a data-name. The statement was discarded.
The above error is simple that there is no working storage or variable named STUB4.
Hope this helps.

COBOL keyword REDEFINES

May I ask, what is the usage of the keyword REDEFINES in COBOL?
I can not understand the manual's definition.
What is the meaning of the following code?
01 WS_CHARGE_TXT_8X PIC X(08) VALUE "10000000".
01 WS_CHARGE_NUM_8 REDEFINES WS_CHARGE_TXT_8X.
05 WS_CHARGE_8 PIC 9(05)V9(03).
Thank you!
Basically Redefines reuses the spaces so in the above example WS_CHARGE_TXT_8X and WS_CHARGE_8 will point to the same block of memory. This allows you to look at a block of memory in different ways, in this case the variable can be viewed as a text PIC X and a signed numeric PIC S9. The -8X to -8 in the variable name is just stylistic to indicate the variable is being recast to another type or format to other programmers.
In the above example
the value of WS_CHARGE_TXT_8X is
"10000000"
the value of WS_CHARGE_8 is
of 10000.000.
If you moved 123.456 to WS_CHARGE_8 the value of WS_CHARGE_TXT_8X "00123456".
A more useful example is
03 Birth-Date-YYYYMMDD pic 9(8).
03 filler redefines Birth-Date-YYYYMMDD.
05 Birth-Date-YYYY pic 9(4).
05 Birth-Date-MM pic 99.
05 Birth-Date-DD pic 99.
In this case you can access the whole date Birth-Date-YYYYMMDD or the year / month / day individually (Birth-Date-YYYY etc).
It is analogous to union in 'C'.
It saves working storage space, and MOVE statements, and is also useful for transposing arrays of PIC(X), or accessing repeated fields as an array.
In the OP's case a numeric "type" is being created for the char contents of the prototype field.
A REDEFINES allows a different data description for storage which has already been defined.
That might be to allow entirely different data to be held there.
05 RL-AGENT-DATA.
...
05 RL-CUSTOMER-DATA REDEFINES RL-AGENT-DATA.
...
Or to give a description which allows a use of a part of the data, as in Bruce's example.
Or to use a piece of data that is the same, but for a different purpose:
05 INPUT-AMOUNT PIC X(10).
05 INPUT-AMOUNT-NUMERIC REDEFINES PIC 9(8)V99.
Whatever is in INPUT-AMOUNT it can be reported without problem, but only if it is a valid numeric (by testng it for NUMERIC), is INPUT-AMOUNT-NUMERIC used for some purpose.
Note that each 01 subsequent to the first under an FD is an "implicit REDEFINES".
Note also that items in the LINKAGE SECTION have the effect of "redefining" "something", even though if the address of the data is from a CALLing program, the definition is often the same as the original definition, and should usually at least match the PICtures of the original.

Resources