Cobol

Cobol programs have multiple ways to make links to other programs, copybooks, datasets, etc. In addition, depending on the compiler and the Cobol flavor (Ansi, Tandem, OpenVMS…), the list of statements may change. AWS Transform for mainframe refactor dependencies engine handles a large list of statements (see below) and can rapidly be extended to support new ones.

Properties attached to Cobol dependencies (variableName on dynamic calls, lineNo) are described in the Dependency properties page.

Program identification

There are two ways to identify a Cobol program: from the file name without the extension and from the identification division at the start of the source file, like the following example.

IDENTIFICATION DIVISION.                
PROGRAM-ID. CBACT02C.                
AUTHOR. AWS.

ENVIRONMENT DIVISION.

Sometimes, the file name and the program id are different but both can be used to address a Cobol program. The dependencies analysis handles that: when a link goes to a Cobol file, a "file name" can be resolved by a "program id" and vice versa. If two different Cobol files have the same file name or program id, both will be considered.

Entry statement

Some Cobol programs can declare entry points, as follows.

 PROCEDURE DIVISION.

DISPLAY 'BEGINNING OF THE PROGRAM'.

ENTRY 'POINT1'.

These entry points are treated like an alternative program id.

Direct dependency

++INCLUDE / -INC / ?SOURCE

The call on ++INCLUDE / -INC and ?SOURCE implies dependencies on copybook files :

  • ++INCLUDE / -INC / ?SOURCE 'COPYBOOK'
  • ++INCLUDE / -INC / ?SOURCE "COPYBOOK"
  • ++INCLUDE / -INC / ?SOURCE COPYBOOK

CALL / CALL PROC / CALL PROCEDURE

The list below uses only the CALL keywords but the dependencies will be the same with CALL PROC or CALL PROCEDURE. We expect to find dependencies of any extension :

  • CALL 'PROGRAM' implies a dependency on a file named "PROGRAM"
  • CALL "PROGRAM" implies a dependency on a file named "PROGRAM"
  • CALL PROGRAM_VAR implies a dynamic dependency involving PROGRAM_VAR variable, refer to the dedicated paragraph.

Those statements can also address an ENTRY defined in an ASM or Cobol file.

CALL … USING …

The CALL ... USING ... implies a dependency on a program file. We expect to find dependencies of any extension. We also handle dynamic code execution with those statements:

  • CALL "PROGRAM" USING MY_STRING_VAR implies a dependency on a file named "PROGRAM" and if MY_STRING_VAR is a string containing dynamic source code, we will also analyze this source code

MY_STRING_VAR can be set using a STRING ... END-STRING statement for string concatenation. We don’t handle cases where those String concatenations depend on each other.

For instance the code below will not generate an "Exec CICS program" dependency:

MOVE "" TO STR_COMMAND                
STRING                
"EXEC CICS LINK PROGRAM"                
DELIMITED BY SIZE                
INTO STR_COMMAND                
END-STRING.

STRING                
"(MY_FILE) END-EXEC."                
DELIMITED BY SIZE                
INTO STR_COMMAND                
END-STRING.

COPY/+COPY/$COPY

The call on COPY, +COPY or $COPY implies dependencies on copybook files or a record object declared in a PF or DSPF file  :

  • COPY 'COPYBOOK' implies a dependency on a copybook file named "COPYBOOK"
  • COPY 'folder:COBCOP.cobcop' implies a dependency on a cobcop file named "COBCOP". The .cobcop in the string is optional.
  • COPY "COPYBOOK" implies a dependency on a copybook file named "COPYBOOK"
  • COPY "folder:COBCOP.cobcop" implies a dependency on a cobcop file named "COBCOP". The .cobcop in the string is optional.
  • COPY COPYBOOK implies a dependency on a copybook file named "COPYBOOK"

Copy ... Of / Copy ... In (DDS prefixes and suffixes)

  • COPY PREFIXED-ID OF FILE or COPY PREFIXED-ID IN FILE implies a dependency on a file named "FILE" and implies a dependency on a record. The record name is found by removing prefix and suffix from PREFIXED-ID.
  • prefixes
    • DD-
    • DDS-
    • DDR-
    • DDSR-
  • suffixes
    • -O
    • -I
    • -I-O
    • -INDICATORS

For example, DDR-RECORD-I-INDICATOR is transformed into RECORD.

ALL-FORMATS

A copybook named ALL-FORMATS does not create a dependency.

COPY ... REPLACING

If a COPY statement is followed by REPLACING ... BY, the content of the targeted copybook will be replaced according to the parameters of this statement:

  • COPY MYCOPYBOOK REPLACING VAR1 BY VALUE VAR2 BY VALUE2

When the replacing name and value are between "==", any character can compose the name and value.

  • COPY MYCOPYBOOK REPLACING ==:VAR1:== BY ==VALUE==

The replacing statements can be chained like the following:

  • COPY MYCOPYBOOK REPLACING ==:VAR1:== BY ==VALUE== ==:VAR2:== BY ==VALUE2==

In this last example, all occurrences of :VAR1: and :VAR2: in the copy file MYCOPYBOOK will be replaced by VALUE and VALUE2.

All the dependencies from the replaced content of the copybook are directly added to the original copybook's dependencies as a "Copy Replacing" dependency.

EXEC CICS

EXEC CICS … DATASET

  • EXEC CICS exec-cics-verb DATASET("file-definition-name") ... END-EXEC implies a dependency on a "CICS_FILE" or "DATASET" object named "file-definition-name"
  • EXEC CICS exec-cics-verb DATASET('file-definition-name') ... END-EXEC implies a dependency on a "CICS_FILE" or "DATASET" object named "file-definition-name"
  • EXEC CICS exec-cics-verb DATASET(variable-name) ... END-EXEC implies a dependency on all "CICS_FILE" or "DATASET" objects referenced by the variable "variable-name"

"exec-cics-verb" can be one of the following

  • DELETE: delete a record that is present in a file
  • ENDBR: terminate the browse
  • READ: read a record
  • READNEXT: read next record
  • READPREV: read the previous record
  • RESETBR: reset record browser
  • REWRITE: rewrite the record
  • STARTBR: start to browse
  • WRITE: write a record
  • UNLOCK: release the exclusive control required by a READ or an UPDATE

Refer to the paragraph dedicated to file definitions.

EXEC CICS … FILE

  • EXEC CICS exec-cics-verb FILE("file-definition-name") ... END-EXEC implies a dependency on a "CICS_FILE" object named "file-definition-name"
  • EXEC CICS exec-cics-verb FILE('file-definition-name') ... END-EXEC implies a dependency on a "CICS_FILE" object named "file-definition-name"
  • EXEC CICS exec-cics-verb FILE(variable-name) ... END-EXEC implies a dependency on all "CICS_FILE" objects referenced by the variable "variable-name"

"exec-cics-verb" can be one of the following

  • DELETE: delete a record that is present in a file
  • ENDBR: terminate the browse
  • READ: read a record
  • READNEXT: read next record
  • READPREV: read the previous record
  • RESETBR: reset record browser
  • REWRITE: rewrite the record
  • STARTBR: start to browse
  • WRITE: write a record
  • UNLOCK: release the exclusive control required by a READ or an UPDATE

We support several calls on LINK PROGRAM, the call itself could be on multiple lines or not. We expect to find dependencies of any extension :

  • EXEC CICS LINK / LOAD / XCTL PROGRAM("PROGRAM") ... END-EXEC implies a dependency on a file named "PROGRAM"
  • EXEC CICS LINK / LOAD / XCTL PROGRAM('PROGRAM') ... END-EXEC implies a dependency on a file named "PROGRAM"
  • EXEC CICS LINK / LOAD / XCTL PROGRAM(PROGRAM_VAR) ... END-EXEC implies a dynamic dependency involving PROGRAM_VAR variable, refer to the dedicated paragraph.
  • EXEC CICS LINK / LOAD / XCTL PROGRAM(PROGRAM_TABLE(INDEX)) ... END-EXEC implies a dynamic dependency involving the PROGRAM_TABLE table. INDEX can be a literal (PROGRAM_TABLE(1)) or a variable. The program names are resolved from the default values of the table and from MOVE 'PROGRAM' TO PROGRAM_TABLE(1) statements, refer to the dedicated paragraph.
  • EXEC CICS LINK / LOAD / XCTL PROGRAM(PROGRAM_VAR IN GROUP) ... END-EXEC (or OF GROUP) implies a dynamic dependency involving PROGRAM_VAR variable, refer to the dedicated paragraph.

Other options may be written between the verb and PROGRAM(...): APPLID, SYSID, COMMAREA, LENGTH, DATALENGTH, CHANNEL, TRANSID, SYNCONRETURN, … up to ten options, with or without an operand. The dependency is the same as when PROGRAM comes first. This covers the EXCI form of the statement:

EXEC CICS LINK
    APPLID     (WS-APP-REGION)
    PROGRAM    (WS-MODULE2)
    COMMAREA   (WS-COMMAREA)
    LENGTH     (LENGTH OF WS-COMMAREA)
END-EXEC

With WS-MODULE2 declared VALUE 'COBOL_PROG2', this creates:

{
    "dependencyType": "Exec CICS program ; [Dynamic] Call",
    "name": "COBOL_PROG2.cob",
    "path": "cobol/COBOL_PROG2.cob",
    "type": "COB"
}

RECEIVE MAP

We support several calls on RECEIVE MAP, the call itself could be on multiple lines or not. We expect to find dependencies of any extension but .CBL, .COB and .CPY :

  • EXEC CICS RECEIVE MAP("MAP") ... END-EXEC implies a dependency on a file named "MAP"
  • EXEC CICS RECEIVE MAP('MAP') ... END-EXEC implies a dependency on a file named "MAP"
  • EXEC CICS RECEIVE MAP(MAP_VAR) ... END-EXEC implies a dynamic dependency involving MAP_VAR variable, refer to the dedicated paragraph.

RECEIVE MAPSET

We support several calls on RECEIVE MAPSET, the call itself could be on multiple lines or not. We expect to find dependencies of any extension but .CBL, .COB and .CPY :

  • EXEC CICS RECEIVE MAPSET("MAPSET") ... END-EXEC implies a dependency on a file named "MAPSET"
  • EXEC CICS RECEIVE MAPSET('MAPSET') ... END-EXEC implies a dependency on a file named "MAPSET"
  • EXEC CICS RECEIVE MAPSET(MAPSET_VAR) ... END-EXEC implies a dynamic dependency involving MAPSET_VAR variable, refer to the dedicated paragraph.

SEND MAP

We support several calls on SEND MAP, the call itself could be on multiple lines or not. We expect to find dependencies of any extension but .CBL, .COB and .CPY :

  • EXEC CICS SEND MAP("MAP") ... END-EXEC implies a dependency on a file named "MAP"
  • EXEC CICS SEND MAP('MAP') ... END-EXEC implies a dependency on a file named "MAP"
  • EXEC CICS SEND MAP(MAP_VAR) ... END-EXEC implies a dynamic dependency involving MAP_VAR variable, refer to the dedicated paragraph.

SEND MAPSET

We support several calls on SEND MAPSET, the call itself could be on multiple lines or not. We expect to find dependencies of any extension but .CBL, .COB and .CPY :

  • EXEC CICS SEND MAPSET("MAPSET") ... END-EXEC implies a dependency on a file named "MAPSET"
  • EXEC CICS SEND MAPSET('MAPSET') ... END-EXEC implies a dependency on a file named "MAPSET"
  • EXEC CICS SEND MAPSET(MAPSET_VAR) ... END-EXEC implies a dynamic dependency involving MAPSET_VAR variable, refer to the dedicated paragraph.

Refer to the paragraph dedicated to file definitions.

EXEC CICS … TRANSID

  • EXEC CICS exec-cics-verb TRANSID("transaction-name") ... END-EXEC implies a dependency on a "TRANSACTION" object named "transaction-name"
  • EXEC CICS exec-cics-verb TRANSID('transaction-name') ... END-EXEC implies a dependency on a "TRANSACTION" object named "transaction-name"
  • EXEC CICS exec-cics-verb TRANSID(variable-name) ... END-EXEC implies a dependency on all "TRANSACTION" objects referenced by the variable "variable-name"

"exec-cics-verb" can be one of the following

  • START: start transaction
  • RETURN: return transaction

EXEC SQL

We support several calls on EXEC SQL, the call itself could be on multiple lines or not. We expect to find the dependencies of any extension. The dependencies are detected for the following operations in the request :

  • EXEC SQL ... FROM TABLE1, TABLE2 ... END-EXEC where TABLE1 and TABLE2 are files corresponding to SQL tables. TABLE2 is optional and if there are only two tables, commas aren’t needed.
  • EXEC SQL ... INSERT INTO TABLE1 ... END-EXEC where TABLE1 is a file corresponding to a SQL table.
  • EXEC SQL ... JOIN TABLE1 T1 ON ... END-EXEC where TABLE1 is a file corresponding to a SQL table and T1 is an optional alias for TABLE1 used in the rest of the request.
  • EXEC SQL ... UPDATE TABLE1 SET ... END-EXEC where TABLE1 is a file corresponding to a SQL table.
  • EXEC SQL DECLARE TABLE1 TABLE ... END-EXEC where TABLE1 is a file corresponding to a SQL table or view.

EXEC SQL CALL

The call on EXEC SQL CALL implies dependencies on SQL files :

  • EXEC SQL CALL SQLFILE(...) END-EXEC. implies a dependency on a SQL file named "SQLFILE".

EXEC SQL INCLUDE

The call on EXEC SQL INCLUDE implies dependencies on copybook files :

  • EXEC SQL INCLUDE 'COPYBOOK' ... END-EXEC implies a dependency on a copybook file named "COPYBOOK"
  • EXEC SQL INCLUDE "COPYBOOK" ... END-EXEC implies a dependency on a copybook file named "COPYBOOK"
  • EXEC SQL INCLUDE COPYBOOK ... END-EXEC implies a dependency on a copybook file named "COPYBOOK"

EXEC SQL SOURCE

The call on EXEC SQL SOURCE implies dependencies on copybook files :

  • EXEC SQL SOURCE = 'COPYBOOK' implies a dependency on a copybook file named "COPYBOOK"
  • EXEC SQL SOURCE = "COPYBOOK" implies a dependency on a copybook file named "COPYBOOK"
  • EXEC SQL SOURCE = COPYBOOK implies a dependency on a copybook file named "COPYBOOK"

NNCOPY

The call on NNCOPY can be found in a COBOL comment and implies dependencies on copybook files :

  • *01 NNCOPY COPYBOOK(SEGMENT) implies a dependency on a copybook file named "COPYBOOK"

ASSIGN TO

The call on ASSIGN TO assignment-name implies a dependency on assignment-name that can be a file, SQL table, or a view.               
Depending on the Cobol version, there are two different syntaxes for assignment-name.

Cobol IBM iSeries / AS400

Format of assignment-name: device-fileName-attribute

device:

  • PRINTER: Program described printer file
  • FORMAT: Externally described printer file
  • DISKETTE: Diskette file
  • DISK: Any physical database file or single format logical database file
  • DATABASE: Any database file (or DDM file)
  • WORKSTATION: Display file or ICF file

fileName: File or database name.

(optional) attribute:

  • SI: Means separate indicator, used for a FORMATFILE or WORKSTATION file
  • ALWNULL: Used for DATABASE

Cobol z/OS

Format of assignment-name: label-indicator-name

label: Documents (for the programmer) the device and device class to which a file is assigned

indicator:

  • S: For QSAM file
  • AS: For VSAM sequential file
  • No indicator: QSAM, VSAM indexed or VSAM relative file

name: File name

SWCOPY

The call on SWCOPY implies dependencies on copybook files :

  • SWCOPY 'COPYBOOK' implies a dependency on a copybook file named "COPYBOOK"
  • SWCOPY "COPYBOOK" implies a dependency on a copybook file named "COPYBOOK"
  • SWCOPY COPYBOOK implies a dependency on a copybook file named "COPYBOOK"

File definition dependencies

File definitions

In Cobol, file definitions are declared in the "FILE SECTION" like                 
000000 FD file-definition-name                
LABEL RECORDS ARE STANDARD.                
000000 01 file-definition-record.                
A link from the Cobol file to an object named 'file-definition-name' typed 'FILE_DEFINITION' will be created. 'file-definition-record' is an alias of 'file-definition-name'.          
The 'file-definition-record' can also be nested in a Copybook like           
000000 FD file-definition-name                
LABEL RECORDS ARE STANDARD.                
000000 COPY file-definition-copy           
Where 'file-definition-copy' is a Copybook starting with 000000 01 file-definition-record..

Cobol statements using file definitions

OPEN (INPUT|OUTPUT|EXTEND|I-O) file-definition-name implies a dependency on a "FILE_DEFINITION" object named "file-definition-name"

  • READ file-definition-name implies a dependency on a "FILE_DEFINITION" object named "file-definition-name"
  • READ SUBFILE  file-definition-name implies a dependency on a "FILE_DEFINITION" object named "file-definition-name"
  • WRITE file-definition-record implies a dependency on a "FILE_DEFINITION" aliased object with an alias named "file-definition-record"
  • WRITE SUBFILE file-definition-record implies a dependency on a "FILE_DEFINITION" aliased object with an alias named "file-definition-record"
  • REWRITE file-definition-record implies a dependency on a "FILE_DEFINITION" aliased object with an alias named "file-definition-record"
  • REWRITE SUBFILE file-definition-record implies a dependency on a "FILE_DEFINITION" aliased object with an alias named "file-definition-record"
  • DELETE file-definition-name implies a dependency on a "FILE_DEFINITION" object named "file-definition-name"
  • START file-definition-name implies a dependency on a "FILE_DEFINITION" object named "file-definition-name"
  • CLOSE file-definition-name implies a dependency on a "FILE_DEFINITION" object named "file-definition-name"

Dynamic dependency

A dynamic dependency is a dependency whose target is only known at runtime. In COBOL, the name of the program to call is stored in a variable that is used in some statements seen in the previous paragraphs. Static analysis of COBOL source can detect some variable values.

variableName

CALL PROGRAM_VAR where PROGRAM_VAR holds the program name is a dynamic call. When it is resolved, the name of the variable used in the statement is kept in the variableName property of the dependency, alongside the resolved program name. A static call on a literal (CALL 'PROGRAM') does not carry the variableName property, since no variable is involved.

For CALL COBOL_PROG1 where the value of COBOL_PROG1 resolves to a program name (here, a program that is not in the project), the dependency is:

{
    "dependencyType" : "Call; [Dynamic] Call",
    "name" : "COBOL_PROG1",
    "path" : null,
    "properties" : {
        "variableName" : "COBOL_PROG1"
    },
    "type" : "Missing Program"
}

This applies to every dynamic dependency resolved from a variable — CALL, EXEC CICS ... PROGRAM(...) and LINK / XCTL.

Attribute default value

01 ATTRIBUTE   PIC X(8) VALUE 'PROGRAM '. This is an initialization of a field named ATTRIBUTE with the value 'PROGRAM '. If ATTRIBUTE is used in a statement implying a dependency, it means that 'PROGRAM ' may be a program name.

The VALUE clause is recognised with or without a space before the literal (VALUE 'PROGRAM' and VALUE'PROGRAM'). Variable names are matched case-insensitively between their declaration and their use in CALL, EXEC CICS ... PROGRAM(...) and MOVE statements.

MOVE

MOVE 'PROGRAM' TO ATTRIBUTE ATTRIBUTE2 or MOVE ATTRIBUTE TO ATTRIBUTE3. If either ATTRIBUTE, ATTRIBUTE2 or ATTRIBUTE3 is used in a statement implying a dependency, it means that 'PROGRAM' may be a program name.

Qualified and subscripted operands are supported on both sides of the MOVE:

  • MOVE 'PROGRAM' TO ATTRIBUTE IN GROUP or MOVE 'PROGRAM' TO ATTRIBUTE OF GROUP
  • MOVE ATTRIBUTE IN GROUP TO ATTRIBUTE2
  • MOVE 'PROGRAM' TO ATTRIBUTE-TABLE(1) where ATTRIBUTE-TABLE is declared with OCCURS

In all cases the value is attached to the unqualified variable name (ATTRIBUTE, ATTRIBUTE-TABLE).

Copybook

All default values and MOVE defined in a copybook are reported to any program using this copybook. In addition, a dynamic call found in a copybook is reported as a dynamic call from each program using this copybook that provides a value for the variable; when no program provides a value, the call stays on the copybook and is reported as "Missing Dynamic Call Value" (see below).

Resolution result

A dynamic dependency resolved from a value found by the analysis is reported with the [Dynamic] marker added to its type ("Call; [Dynamic] Call", "Exec CICS program ; [Dynamic] Call") and points to the program named by the value; when that program is not in the project the target is reported as "Missing Program", like a static call. The only exception is the special case below.

When no value can be found for the variable — no VALUE clause and no MOVE 'literal' TO variable, neither in the program nor in its copybooks — the call cannot be resolved. The dependency is still reported, so that the call site is visible, with the variable name as target and the type "Missing Dynamic Call Value". The variableName property carries the name of the variable.

01 PGM-VAR   PIC X(8).
...
    CALL PGM-VAR.

Creates:

{
    "dependencyType": "Call; [Dynamic] Call",
    "name": "PGM-VAR",
    "path": null,
    "type": "Missing Dynamic Call Value",
    "properties": {
        "variableName": "PGM-VAR"
    }
}

"Missing Dynamic Call Value" therefore means "the analysis could not determine which program is called", whereas "Missing Program" means "the called program is known but is not in the project". See the Dependency properties page for variableName.

Special case

If a MOVE of a literal sets a variable's value just before a dynamic call using the same variable (with only MOVE, SET or CALL statements in between), the dependency analysis considers it like a direct call: the dependency is reported as a plain "Call", without the [Dynamic] marker and without the variableName property. A MOVE of another variable (MOVE VAR2 TO VAR) does not trigger this; the call then follows the rules above.

MOVE "PROGA" TO VAR.
CALL VAR.

Other

  • For relation with IMS refer to the dedicated page.