variablesscopeproceduregnucobol

in gnucobol, sub programs of one parent can't invoke each other


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?


Solution

  • ok, after further inquiring and even consulting gemini, i can fully adopt the following concept:

    1. the main equivalent is a top level defined program.
    2. any variable to be accessible to all code should be put in the main program data division and marked global.
    3. additional full blown programs, from identification division. to end program. may be put in the procedure division of any of the said programs, and be considered nested subprograms.
    4. nested subprograms are accessible from their parent program. to access a nested subprogram from it's siblings subprograms, it should be marked common as in the following example:
    IDENTIFICATION DIVISION.
    PROGRAM-ID. DemoGLOBAL.
    ENVIRONMENT DIVISION.
    DATA DIVISION.
    WORKING-STORAGE SECTION.
    01  global-var GLOBAL                     PIC X(10).
    PROCEDURE DIVISION.
    000-Main.
        MOVE ALL "X" TO global-var
        CALL "DemoSub" END-CALL
        DISPLAY "DemoGLOBAL: " global-var END-DISPLAY
        CALL "DemoSub2" END-CALL
        DISPLAY "DemoGLOBAL: " global-var END-DISPLAY
        CALL "DemoSub3" END-CALL
        DISPLAY "DemoGLOBAL: " global-var END-DISPLAY
        GOBACK
        .
    IDENTIFICATION DIVISION.
    PROGRAM-ID. DemoSub common.
    PROCEDURE DIVISION.
    000-Main.
        MOVE ALL "*" TO global-var.
        GOBACK
        .
    END PROGRAM DemoSub.
    IDENTIFICATION DIVISION.
    PROGRAM-ID. DemoSub2.
    PROCEDURE DIVISION.
    000-Main.
        MOVE ALL "?" TO global-var.
        GOBACK
        .
    END PROGRAM DemoSub2.
    IDENTIFICATION DIVISION.
    PROGRAM-ID. DemoSub3.
    PROCEDURE DIVISION.
    000-Main.
        CALL "DemoSub" END-CALL
        GOBACK
        .
    END PROGRAM DemoSub3.
    END PROGRAM DemoGLOBAL.
    
    

    of course, this was the way to bend experienced cobol to provide a modern style like 'module' with isolated functions / subprograms.

    as my cobol exposure grows, i'd feel more confortable with performing sections and paragraphs, that could run in a module like my example, that has no parameters calling yet.

    the subprograms are suitable to allow calling with parameters.