COBOL Record description entry I cannot decipher - cobol

I am examining this example in Cobol 85 from the NIST TestSuite:
007700 WORKING-STORAGE SECTION. SQ4014.2
007800 SQ4014.2
007900 01 VARIABLES. SQ4014.2
008000 SQ4014.2
008100 03 VKEY SQ4014.2
008200 XXXXX086. SQ4014.2
008300 SQ4014.2
008400 SQ4014.2
008500 PROCEDURE DIVISION. SQ4014.2
008600 SQ4014.2
To me it seems wrong because the the record description entry 03 VKEY should be followed by some keyword, like VALUE. It is instead followed by an identifier (XXXXX086) which I do not know how to interpret.
What does it mean in this context?

I'm not sure where you got the sample from, it looks like it was directly taken from newcob.val. If extracted "as expected" the COBOL line is:
007700 WORKING-STORAGE SECTION. SQ4014.2
007800 SQ4014.2
007900 01 VARIABLES. SQ4014.2
008000 SQ4014.2
008100 03 VKEY SQ4014.2
008200 PIC X(8). SQ4014.2
008300 SQ4014.2
008400 SQ4014.2
008500 PROCEDURE DIVISION. SQ4014.2
so it is as cschneid said: it is to be preprocessed before it is compiled and otherwise would raise an error.
A side note: the test programs say in the header what they test for, this one says:
000400*THE FOLLOWING PROGRAM TESTS THE FLAGGING OF HIGH SQ4014.2
000500*SUBSET FEATURES THAT ARE USED IN SEQUENTIAL SQ4014.2
so it does not expect any errors.
The easiest option to extract it I know of is to get a copy of GnuCOBOL and ideally run the configure part, then running make test in the "tests/cobol85" subdirectory (or use the perl scripts in there to extract the files manually). You'll end up with one subdirectory for each module of the test suite.

As written, that is a compile error. Which may be what is being tested by that particular member of the test suite.
It's also possible it is intended to be modified via a preprocessor. Note other members of the NIST suite with non-standard characters in column 7.
Not all members of the NIST test suite are valid COBOL.

Related

libcob: module 'GETSUM' not found - Cobol

I started to learn Cobol a few days ago and I'm wathcing a video about the basics. The problem that I have is that i'm calling a rountine from another file and when I compile the program I get the error libcob: module 'GETSUM' not found.
I'm using a virtual machine with wsl2 wIth ubuntu 20.04.4 LTS on windows 10. And as compiler I am using GnuCobol 2.2.0
Code of main file :
IDENTIFICATION DIVISION.
PROGRAM-ID. COBOL-TUTORIAL5.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 Num1 PIC 9 VALUE 5.
01 Num2 PIC 9 VALUE 4.
01 Sum1 PIC 99.
PROCEDURE DIVISION.
CALL 'GETSUM' USING Num1, Num2, Sum1.
DISPLAY Num1 " + " Num2 " = " Sum1.
STOP RUN.
Get sum file:
IDENTIFICATION DIVISION.
PROGRAM-ID. GETSUM.
DATA DIVISION.
LINKAGE SECTION.
01 LNum1 PIC 9 VALUE 5.
01 LNum2 PIC 9 VALUE 4.
01 LSum PIC 99.
PROCEDURE DIVISION USING LNum1, LNum2, LSum,.
ADD LNum1 TO LNum2 GIVING LSum.
EXIT PROGRAM.
when I compile the program I get the error libcob: module 'GETSUM' not found
That can't be the case, because this is the COBOL runtime telling you the module is missing, so this only happens when executing, not when compiling.
You have two general options:
cobc -x COBOL-TUTORIAL5.cob GETSUM.cob
--> compile everything at once, creating one big binary. In this case you may want to add -static for both faster runtime and for making sure that you indeed include everything necessary (if not you'd get a linker error, commonly a message like "symbol 'GETSUM' not found").
Compile at least GETSUM.cob as module (cobc GETSUM.cob) and have it either in the current directory when COBOL-TUTORIAL5, or use COB_LIBRARY_PATH to point to the place where the modules are located.
For more details see the GnuCOBOL manual using Multiple source.

Using a translate API to convert from Cobol or gnucobol to other language

I am looking for an example using Cobol either mf cobol or gnucobol. I would like an alternate of VB or C. Old time coboller since Cobol 61. I have looked at the Java and python examples but they are not clear to me.
Parameter sizes, contents, and order are what I am looking for as well as the translation routine or module name.
Vb or c example will do as I have worked with those languages as well.
A cobol example with results expected:
Id division.
Program-Id. Somename.
Environment division.
Data division.
Working-storage section.
01 Some-existing-text pic x(32000) value
"The quick brown fox jumped over the silver moon".
01 input-text-type pic x(20) value "english".
01 resulting-text pic x(32000) value
"Der schnelle braune Fuchs sprang über den silbernen Mond ".
01 destination-text-type pic x(20) value "German".
Procedure division.
Start-here.
Call "translation-routine" using Some-existing-text,
input-text-type,
Resulting-text,
Destination-text-type.
Stop-here.
Stop run.
Take a look at this, i tried it in linux and its working absolutely fine.
First Install Translate Shell:-
Translate Shell is available in the official repositories of popular Linux operating systems.
Use below command to install.
$ sudo apt-get install translate-shell
Now find the cobol code that takes user input and translates from your preferred language to English and vice versa.
ID DIVISION.
PROGRAM-ID. SOMENAME.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 SOME-SAMLPLE-TEXT PIC X(30) VALUE "नमस्ते". /*THIS WORD IS "HI" IN HINDI*/
PROCEDURE DIVISION.
START-HERE.
STRING "TRANS"
" "
SOME-SAMLPLE-TEXT
DELIMITED BY SPACES INTO LINUX-COMMAND.
CALL "SYSTEM" USING LINUX-COMMAND
RETURNING CONVERTED-TEXT.
DISPLAY CONVERTED-TEXT.
STOP RUN.
Output will be "HI"
Below program translates Hindi to Tamil, you can use an variable and make the language code dynamic.
For more language codes goto:https:language codes
ID DIVISION.
PROGRAM-ID. SOMENAME.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 SOME-SAMPLE-TEXT PIC X(30) VALUE "नमस्ते". /*THIS WORD IS "HI" IN HINDI*/
PROCEDURE DIVISION.
START-HERE.
STRING "TRANS"
" "
":"
"te" /*code to convert text to tamil*/
" "
SOME-SAMPLE-TEXT
DELIMITED BY SPACES INTO LINUX-COMMAND.
CALL "SYSTEM" USING LINUX-COMMAND
RETURNING CONVERTED-TEXT.
DISPLAY CONVERTED-TEXT.
STOP RUN.
Output will be "வணக்கம்"
For information on installing google translate in linux please refer :this link
Happy coding........

Cobol: cannot find entry point of a text file

Hi i am learning cobol from tutorialpoints and every program from there works as i've tested them in OpenCobolIDE(some needed a little editing). Then i came across the File Handling chapter and in there the program had a lot of errors. I did manage to rewrite the program until it didn't show me any errors but it doesn't do anything.
Here's my code:
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT STUDENT ASSIGN TO
'C:\Cobol\FIle Handling\input.txt'
ORGANIZATION IS INDEXED
ACCESS IS RANDOM
RECORD KEY IS STUDENT-ID
FILE STATUS IS FS.
DATA DIVISION.
FILE SECTION.
FD STUDENT.
01 STUDENT-FILE.
05 STUDENT-ID PIC 9(5).
05 NAME PIC A(25).
WORKING-STORAGE SECTION.
01 WS-STUDENT-FILE.
05 WS-STUDENT-ID PIC 9(5).
05 WS-NAME PIC A(25).
01 FS PIC 9(02).
PROCEDURE DIVISION.
OPEN I-O STUDENT.
MOVE 20005 TO STUDENT-ID.
READ STUDENT RECORD INTO WS-STUDENT-FILE
KEY IS STUDENT-ID
INVALID KEY DISPLAY 'Invalid Key'
NOT INVALID KEY DISPLAY WS-STUDENT-FILE
END-READ.
CLOSE STUDENT.
STOP RUN.
This is the text file:
20003 Mohtashim M.
20004 Nishant Malik
20005 Amitabh Bachhan
The result should be the text:
20005 Amitabh Bachhan
It's doing something: It's reading the file. But that's all; you didn't ask for it to display or do anything else beyond reading the record into memory. You might want to look at using the DISPLAY statement or maybe create another file to write the output to.
Might I make a couple of suggestions?
In modern COBOL, stylistically, you don't put a period after everything in the procedure division -- you only put it in where it is necessary. For example:
PROCEDURE DIVISION.
OPEN I-O STUDENT
MOVE 20005 TO STUDENT-ID
READ STUDENT RECORD INTO WS-STUDENT-FILE
KEY IS STUDENT-ID
INVALID KEY DISPLAY 'Invalid Key'
NOT INVALID KEY DISPLAY WS-STUDENT-FILE
END-READ
CLOSE STUDENT
STOP RUN
.
Although the compiler doesn't care about spaces and returns, if I were you, I'd try to indent my code a bit better (I like how I indented the above :-) ). It's up to you and a lot of people like to do it differently, but if you are consistent you can spot problems that might sneak through your code.
Edit: I didn't notice that you were reading with a key from a text file. So, either you need to:
read from a pre-built indexed file, or
read the file sequentially and search for what you want by comparing what you read for the student id you wanted.

Opening file for reading in COBOL

I'm using OpenCobolIDE 4.7.4 (it's based on GnuCOBOL) on Windows 10 and trying to compile this program opening a file for reading:
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT STUDENT ASSIGN TO 'input.txt'
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD STUDENT.
01 STUDENT-FILE.
05 STUDENT-ID PIC 9(5).
05 NAME PIC A(25).
WORKING-STORAGE SECTION.
01 WS-STUDENT.
05 WS-STUDENT-ID PIC 9(5).
05 WS-NAME PIC A(25).
01 WS-EOF PIC A(1).
PROCEDURE DIVISION.
OPEN INPUT STUDENT.
PERFORM UNTIL WS-EOF='Y'
READ STUDENT INTO WS-STUDENT
AT END MOVE 'Y' TO WS-EOF
NOT AT END DISPLAY WS-STUDENT
END-READ
END-PERFORM.
CLOSE STUDENT.
STOP RUN.
The input.txt is in the same directory as the source coude, yet I'm still getting the following error:
Main.cob:24: libcob: File does not exist (STATUS = 35) File : 'input.txt'
What am I doing wrong?
OCIDE has a setting for the output directory, the default is "bin" (relative to the source file). Effectively it just passes this setting to the compiler cobc source.cob -o bin\source.exe
You can change this behaviour in settings Menu Preferences -> Compiler:
Output directory
This option let you chose where to put the binaries, by default binaries will be placed into a bin folder next to the source file. You can define another relative or absolute directory if you want.
In any case you can set the actual name in the environment, check GC FAQ - How to map a file name to an external name.
As an alternative you can set the data directory with the environment var COB_FILE_PATH.
Both environment options can be set in settings Menu Preferences -> Run.
Most IDE for other languages happen to run the executable from another directory (where it is built for example).
A simple test is to write a test program, opening a file for writing.
You'll quickly see what happens.
Perhaps better will be to write the full path in the select clause.
select STUDENT ASSIGN TO '/xpto/folder1/input.txt'

Is there a way to parameterize functions in COBOL?

I'm coding routines like:
READ-A.
READ FILE-A
AT END
MOVE 1 TO EOF-A
NOT AT END
ADD 1 TO CN-READ-A
END-READ.
F-READ-A. EXIT.
to read several files and I was wondering if there's a way to code a routine that is able to read the filename from a variable so I don't have to code the same thing for each file. Thanks!
One solution as said above is to use multiple programs or nested program, for which
I have included an example below, which is solution 1.
Another solution is to COBOL classes, which might not be to your liking but I like them, so I've included an example, which is solution 2.
Solution 1:
program-id. TestProgram.
working-storage section.
01 file-name pic x(128).
01 file-lines pic 9(9).
procedure division.
move 0 to file-lines
move "d:\rts_win32.txt" to file-name
call "program1" using file-name file-lines
display file-lines
stop run
end program TestProgram.
program-id. Program1.
file-control.
select file-a assign to myfile
organization is line sequential.
data division.
fd file-a.
01 file-a-line pic x(80).
working-storage section.
01 EOF-A pic 9 value 0.
linkage section.
01 lk-filename pic x(128).
01 CN-READ-A pic 9(9).
procedure division using lk-filename
CN-READ-A.
move lk-filename to myfile
open input file-a
perform READ-A until EOF-A equals 1
close file-a
goback.
READ-A.
READ FILE-A
AT END
MOVE 1 TO EOF-A
NOT AT END
ADD 1 TO CN-READ-A
END-READ.
F-READ-A.
EXIT.
end program Program1.
Solution 2
program-id. TestProgram.:
working-storage section.
01 file-counter type FileLineCounter.
procedure division.
set file-counter to new type FileLineCounter("d:\rts_win32.txt")
display file-counter::LineCount
stop run
end program TestProgram.
class-id FileLineCounter.
file-control.
select file-a assign to myfile
organization is line sequential.
data division.
fd file-a.
01 file-a-line pic x(80).
working-storage section.
01 cn-read-a binary-long property as "LineCount".
method-id New.
01 EOF-A pic 9 value 0.
procedure division using by value filename as string.
set myfile to filename
open input file-a
perform READ-A until EOF-A equals 1
close file-a
goback.
READ-A.
READ FILE-A
AT END
MOVE 1 TO EOF-A
NOT AT END
ADD 1 TO CN-READ-A
END-READ.
F-READ-A.
EXIT.
end method.
end class.
May not be "in the wild" yet with compiler support, but the current ISO Draft 20xx standard includes FUNCTION-ID in place of PROGRAM-ID. It adds a parameter friendly function call computing paradigm to COBOL.
Might not help today, but maybe in the near future. If I'm not mistaken, User Defined Functions are actually from the COBOL 2002 spec, but it seems compiler vendors are hit or miss on support for the feature.
FUNCTION-ID support is in closed trials for OpenCOBOL 2.0, but the timeline for the 2.0 release is undetermined and could be another year or more before it's made public.
The proper Cobol way to parameterize routines is via the nested subprogram.
You can do what you want, but it is dependant upon your compiler and environment, you can pass a file, or a file name, or a DDname.
What platform are you on?
Edit: On z/OS, you can change what FILE-A points to at runtime using putenv() to adjust the dataset name associated with the DDNAME that FILE-A uses.
See:
http://ibmmainframes.com/post-57281.html
http://cicswiki.org/cicswiki1/index.php?title=How_do_I_allocate_a_file_dynamically_using_COBOL%3F
You will need a OPEN-A and CLOSE-A paragraph as well between switching files.
It isn't exactly passing parameters to your read statement, but it lets you reuse your OPEN/READ/WRITE/CLOSE statements for different files. But only serially.
There was a way, under VS COBOL II, where you could pass an FD to a subprogram, that would look something like:
CALL MYREADPGM USING FILE-A
CALL MYREADPGM USING FILE-B
This possible with Enterprise Cobol but IIRC VisualAge does not support that.
I realize this is an old thread, but hopefully someone might find this useful in the future: IBM's Enterprise COBOL on z/OS 6.4 compiler supports user-defined functions (released May 2022). User-defined functions could be a useful alternative to the other suggestion for internal programs. In contrast to program calls, there are compile time checks for parameters to user-defined function invocations. Also, you can invoke the function in a lot of places where you couldn't call a program, like within a
n expression.
Here's an example based on passing a file name to a function. It might be possible to combine this with the PUTENV() suggestion above.
IDENTIFICATION DIVISION.
FUNCTION-ID. READ-FILE.
DATA DIVISION.
LINKAGE SECTION.
1 FILE-NAME PIC X(50).
1 RET PIC 9(9).
PROCEDURE DIVISION USING FILE-NAME RETURNING RET.
* DO STUFF WITH FILE-NAME
* ...
GOBACK
.
END FUNCTION READ-FILE.
IDENTIFICATION DIVISION.
PROGRAM-ID. MAINPROG.
DATA DIVISION.
WORKING-STORAGE SECTION.
1 READ-RESULT PIC 9(9).
PROCEDURE DIVISION.
COMPUTE READ-RESULT = FUNCTION READ-FILE('MYINPUTFILE')
GOBACK
.
END PROGRAM MAINPROG.
More examples can be found in the Programming Guide Chapter 32 Using user-defined functions.
https://www.ibm.com/support/pages/enterprise-cobol-zos-documentation-library#Table642
You could create a data file of filenames, treat each one as an individual record, and then read each file. In the "SELECT ...ASSIGN" you would need to use a working-storage variable for the filename and move the value from the 'file of filenames' into it.
As you are using VisualAge, I assume in UNIX, you might also be able to run the program from the shell (sh,ksh), with the filename as a parameter, and repeatedly run the program from the shell for each file name.

Resources