libcob: module 'GETSUM' not found - Cobol - 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.

Related

Issue passing parameters to a COBOL program using JCL PARM= on the EXEC statement

I wrote this simple code to print the parameter that I am passing through my JCL, why does it not print the parameter?
The code:
CBL APOST
IDENTIFICATION DIVISION.
PROGRAM-ID. GETAPIT.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
DATA DIVISION.
WORKING-STORAGE SECTION.
LINKAGE SECTION.
01 PARM-BUFFER.
05 PARM-LENGTH PIC S9(4) COMP.
05 PARM-DATA.
10 numb PIC X(6).
10 filler PIC X(250).
PROCEDURE DIVISION using PARM-BUFFER.
MAINLINE SECTION.
DISPLAY "NUMB: " numb of PARM-DATA.
MAINLINE-EXIT.
GOBACK.
//MVSSYNSQ JOB (3911),'&SYSUID',CLASS=F,MSGCLASS=R,NOTIFY=&SYSUID
/*JOBPARM R=51,L=100
//*
//GETAPI1 EXEC PGM=GETAPIT,PARM='000100'
//STEPLIB DD DISP=SHR,DSN=MVJE.ZCONN.LOADLIB
//SYSPRINT DD SYSOUT=*
OUTPUT:
********************************* TOP OF DATA
NUMB:
it's worked with me when I compiled the COBOL program without the CICS integrator option.
Used your test program with another DISPLAY to print the length of the parameter.
CBL APOST
IDENTIFICATION DIVISION.
PROGRAM-ID. GETAPIT.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
DATA DIVISION.
WORKING-STORAGE SECTION.
LINKAGE SECTION.
01 PARM-BUFFER.
05 PARM-LENGTH PIC S9(4) COMP.
05 PARM-DATA.
10 numb PIC X(6).
10 filler PIC X(250).
PROCEDURE DIVISION using PARM-BUFFER.
MAINLINE SECTION.
DISPLAY "LENGTH: " PARM-LENGTH.
DISPLAY "NUMB: " numb of PARM-DATA.
MAINLINE-EXIT.
GOBACK.
With a parm of PARM='12345' I get this output.
LENGTH: 0005
NUMB: 12345
Note, I used a SYSOUT as opposed to SYSPRINT DD statement which is what you had in your JCL.
//SYSOUT DD SYSOUT=*
From what I could gather DISPLAY defaults to STDOUT which would be SYSOUT in JCL.
One other comment about DISPLAY from a z/OS COBOL Programming Guide
To write data to the system logical output device, either omit the
UPON clause or use the UPON clause with destination SYSOUT.
Display "Hello" upon sysout.Copy code The output is directed to the
ddname that you specify in the OUTDD compiler option. You can specify
a file in the hierarchical file system with this ddname.
If the OUTDD ddname is not allocated and you are not running in the
z/OS UNIX environment, a default DD of SYSOUT=* is allocated. If the
OUTDD ddname is not allocated and you are running in the z/OS UNIX
environment, the _IGZ_SYSOUT environment variable is used as follows:
Undefined or set to stdout Output is routed to stdout (file descriptor
1). Set to stderr Output is routed to stderr (file descriptor 2).
Otherwise (set to something other than stdout or stderr) The DISPLAY
statement fails; a severity-3 Language Environment condition is
raised. When DISPLAY output is routed to stdout or stderr, the output
is not subdivided into records. The output is written as a single
stream of characters without line breaks.
If OUTDD and the Language Environment runtime option MSGFILE specify
the same ddname, both DISPLAY output and Language Environment runtime
diagnostics are routed to the Language Environment message file.

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

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'

Programs hangs when opening COBOL Indexed file

I've recently started a COBOL course and, because of my computer configuration (Windows 7 64 Bits and GNU/Linux 64Bits) I have to use Dosbox to compile and execute programs.
Everything is going well but, I'n finding some troubles when I try to open an Indexed file, either I-O or Ouput mode. I can compile and link but at execution time, dosbox get frozen.
My compiler version is MS-COBOL 5.0 and DosBox is 0.74 (last version).
Does anybody have had this issue? Can someone tell how to fix it.
My code is this one.
Thanks in advance.
IDENTIFICATION DIVISION.
PROGRAM-ID. AGENDA.
AUTHOR. JOSE MARIA RAMIREZ MIRA.
DATE-WRITTEN. 06/05/2014.
DATE-COMPILED. 06/05/2014.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. IBM-PC.
OBJECT-COMPUTER. IBM-PC.
SPECIAL-NAMES.
DECIMAL-POINT IS COMMA.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT AGENDA ASSIGN TO DISK "AGENDA.DAT"
ORGANIZATION IS INDEXED
ACCESS IS RANDOM
RECORD KEY IS AG-NICK
FILE STATUS IS AG-STATUS.
DATA DIVISION.
FILE SECTION.
FD AGENDA
RECORD CONTAINS 112 CHARACTERS
LABEL RECORD IS STANDARD
DATA RECORD IS AG-PERSONA.
01 AG-PERSONA.
03 AG-NICK PIC X(25).
03 AG-NOMBRE PIC X(25).
03 AG-APELLIDOS PIC X(50).
03 AG-TELEFONO PIC X(12).
WORKING-STORAGE SECTION.
77 AG-STATUS PIC 99.
88 EXITO VALUE 00.
88 CLAVE-DUPLICADA VALUE 22.
88 CLAVE-NO-ENCONTRADA VALUE 23.
88 SIN-ESPACIO-EN-DISCO VALUE 34.
88 FICHERO-NO-EXISTE VALUE 35.
88 EOF VALUE 10.
PROCEDURE DIVISION.
MAIN-PROCEDURE.
DISPLAY "PROCEDO A ABRIR EL ARCHIVO".
OPEN I-O AGENDA.
IF EXITO THEN
DISPLAY "EL ARCHIVO SE HA ABIERTO"
ELSE
EVALUATE TRUE
WHEN FICHERO-NO-EXISTE
DISPLAY "EL ARCHIVO NO EXISTE"
END-EVALUATE
END-IF.
CLOSE AGENDA.
STOP RUN.
END PROGRAM AGENDA.
Have you tried selecting the file using the OPTIONAL phrase. For example,
SELECT OPTIONAL AGENDA ASSIGN TO DISK "AGENDA.DAT"
ORGANIZATION IS INDEXED
ACCESS IS RANDOM
RECORD KEY IS AG-NICK
FILE STATUS IS AG-STATUS.
The OPTIONAL phrase must be specified for files opened for INPUT, I-O, or EXTEND that need not be present when the program runs.
Against this being the problem is your statement that the problem also occurs with OPEN OUTPUT and the program should in any case be producing some output but as others have remarked the version of COBOL is not well known.
By the way I plugged your program into the online COBOL at http://www.compileonline.com/compile_cobol_online.php
and it worked fine triggering the FICHERO-NO-EXISTE condition name.
But this does raise another point. In my Microfocus manual the file status code of 35 is given as being returned when an OPEN INPUT, I-O or EXTEND is attempted on a NON-OPTIONAL file that does not exist. A file status of 05 is returned if you have used the OPTIONAL phrase and the file does not exist at the time the OPEN is executed.
What is the absolute path to AGENDA.DAT?
Sometimes with legacy DOS programs you can't read/write files inside folders with spaces on its name. Say, if your current folder is C:\ms cobol\ , rename it to C:\mscobol\.
It's worth a try, if this is your case.
DOSBox was designed for gaming.
The problem could be DOSBox missing file and record locking.
DOSBox has more issues like internal file caching, a time bomb with multi-user enabled programs.
You could try vDos: http://sourceforge.net/projects/vdos/.
It is Windows only, but integrates better with it.

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