I'm currently trying to achieve a pattern to write modest these days' programs in cobol.
By these days' programs I mean a source file with a few variables and procedures visible to each other.
The closest to my aim is a list of programs, each able to call each other, while the operating system is calling the first one.
To share the same variables, I had to mark them external. The drawback is, they are probably accessible in other sources eventually linked together.
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 MY-NAME PIC X(10) VALUE 'MAIN'.
01 CALLS PIC 9(3) EXTERNAL.
PROCEDURE DIVISION.
MOVE 0 TO CALLS.
CALL 'CALL-SHOW' USING MY-NAME, 'CALL-SHOW'.
CALL 'ROUTINE1' USING MY-NAME.
CALL 'ROUTINE2' USING MY-NAME.
END PROGRAM MAIN.
IDENTIFICATION DIVISION.
PROGRAM-ID. CALL-SHOW.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 CALLS PIC 9(3) EXTERNAL.
LINKAGE SECTION.
01 CALLER PIC X(10).
01 CALLED PIC X(10).
PROCEDURE DIVISION
USING CALLER, CALLED.
ADD 1 TO CALLS.
DISPLAY CALLS ' CALLS' END-DISPLAY.
DISPLAY CALLER ' CALLED ' CALLED END-DISPLAY.
GOBACK.
END PROGRAM CALL-SHOW.
IDENTIFICATION DIVISION.
PROGRAM-ID. ROUTINE1.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 MY-NAME PIC X(10) VALUE 'ROUTINE1'.
01 CALLS PIC 9(3) EXTERNAL.
LINKAGE SECTION.
01 CALLER PIC X(10).
PROCEDURE DIVISION USING CALLER.
CALL 'CALL-SHOW' USING CALLER, MY-NAME.
CALL 'CALL-SHOW' USING MY-NAME, 'CALL-SHOW'.
CALL 'ROUTINE2' USING MY-NAME.
GOBACK.
END PROGRAM ROUTINE1.
IDENTIFICATION DIVISION.
PROGRAM-ID. ROUTINE2.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 MY-NAME PIC X(10) VALUE 'ROUTINE2'.
01 CALLS PIC 9(3) EXTERNAL.
LINKAGE SECTION.
01 CALLER PIC X(10).
PROCEDURE DIVISION USING CALLER.
CALL 'CALL-SHOW' USING CALLER, MY-NAME.
CALL 'CALL-SHOW' USING MY-NAME, 'CALL-SHOW'.
GOBACK.
END PROGRAM ROUTINE2.
Another approach I tried is a program with global variables and a few other programs embedded within it's procedure division. Here the global variables are happily visible within that program, but the subprograms seem to be visible in the parent program only.
IDENTIFICATION DIVISION.
PROGRAM-ID. DemoGLOBAL.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 Arg GLOBAL PIC X(10).
PROCEDURE DIVISION.
000-Main.
MOVE ALL "X" TO Arg
CALL "DemoSub" END-CALL
DISPLAY "DemoGLOBAL: " Arg END-DISPLAY
CALL "DemoSub2" END-CALL
DISPLAY "DemoGLOBAL: " Arg END-DISPLAY
CALL "DemoSub3" END-CALL
GOBACK
.
IDENTIFICATION DIVISION.
PROGRAM-ID. DemoSub.
PROCEDURE DIVISION.
000-Main.
MOVE ALL "*" TO Arg.
GOBACK
.
END PROGRAM DemoSub.
IDENTIFICATION DIVISION.
PROGRAM-ID. DemoSub2.
PROCEDURE DIVISION.
000-Main.
MOVE ALL "?" TO Arg.
GOBACK
.
END PROGRAM DemoSub2.
IDENTIFICATION DIVISION.
PROGRAM-ID. DemoSub3.
PROCEDURE DIVISION.
000-Main.
*> CALL "DemoSub" END-CALL
GOBACK
.
END PROGRAM DemoSub3.
END PROGRAM DemoGLOBAL.
Is there a better approach have data and procedures source-wide?
EXTERNAL
variables are visible to the whole runtime unit (= the process / pid) and can be accessed by any program. It is "stored" in the runtime and its size must be identical in all programs (otherwise the first with a different size will either abort or cannot be CALL
ed, depending on the implementation).
GLOBAL
is nicely described by the standard - just the way you found it working:
A global name is available to every program contained within the program that declares it.
It is not 100% clear what you want to achieve; but it seems you want a common data used in all programs. The standard option would be that the "main" program (started from the operating system) has the data (defined in a copybook) in its WORKING-STORAGE
(providing definition and data) while the other programs have it in LINKAGE
(providing definition only) and reference it in PROCEDURE DIVISION USING
(using the data passed by the program on CALL ... USING
).
If you ever need to share the data between independent processes, you'd have LINKAGE
only and share the data via operating system (or COBOL implementation) specific functions (like shmget
on posix environments), with the first program allocating the memory dynamically.