It was 3:47 a.m. on a Monday morning, and the overnight batch at Continental Savings Bank had just crashed. Every single one of the seventy-two programs in the nightly processing cycle had abended with a data exception, and the operations team was...
In This Chapter
- Opening Vignette: The Morning the Entire Bank Went Down
- 18.1 What Is a Copybook?
- 18.2 The COPY Statement
- 18.3 Copybook Search Order and Library Configuration
- 18.4 COPY...REPLACING: Customizing Copybook Content
- 18.5 The REPLACE Statement
- 18.6 Nested COPY Statements
- 18.7 Copybook Design Best Practices
- 18.8 Enterprise Copybook Management
- 18.9 The Shared-Copybooks Directory Concept
- 18.10 Common Copybook Patterns
- 18.11 COPY vs. CALL: When to Share Code by Inclusion vs. by Calling
- 18.12 Copybook Impact Analysis
- 18.13 Common Mistakes and Pitfalls
- 18.14 The Complete Copybook Library Application
- 18.15 Summary
Chapter 18: COPY, REPLACE, and Copybook Management
Opening Vignette: The Morning the Entire Bank Went Down
It was 3:47 a.m. on a Monday morning, and the overnight batch at Continental Savings Bank had just crashed. Every single one of the seventy-two programs in the nightly processing cycle had abended with a data exception, and the operations team was scrambling.
The root cause, as it turned out, was a single copybook. A junior developer had been asked to add a new field to the customer record layout -- a perfectly routine change. The field was added correctly, but the record length in the copybook was not updated to match. Twelve of the seventy-two programs had been recompiled with the new copybook. The other sixty had not. When the updated programs wrote records to a shared file, the other programs tried to read those records using the old layout, and every field after the new one was shifted by ten bytes. Account numbers became phone numbers. Balances became dates. The resulting chaos took three days to untangle.
This story, which has played out in one form or another at organizations around the world, illustrates both the extraordinary power and the extraordinary risk of COBOL's copybook mechanism. A single copybook can define a data structure shared by hundreds of programs. Change that copybook, and every program that uses it is affected. Manage it well, and you have a clean, consistent, maintainable system. Manage it poorly, and you have a ticking time bomb.
In this chapter, you will learn how to use copybooks effectively, how to customize them with COPY...REPLACING and the REPLACE directive, and how to manage them in an enterprise environment where a single copybook change can ripple across an entire application portfolio.
18.1 What Is a Copybook?
A copybook is a file containing COBOL source text that can be included in a program at compile time using the COPY statement. When the compiler encounters a COPY statement, it retrieves the contents of the named copybook and inserts that text into the program, exactly as if the developer had typed it directly.
The concept is analogous to header files in C, import statements in Python, or #include directives in C++, but with important differences. A COBOL copybook is not a module, not a class, and not a library of executable code. It is raw source text that gets physically inserted into the program before compilation. There is no concept of scope, encapsulation, or name visibility. Whatever text is in the copybook becomes part of the program, period.
This simplicity is both the copybook's greatest strength and its most significant limitation. It makes code sharing straightforward and easy to understand. But it also means that if two programs include the same copybook and that copybook changes, both programs must be recompiled -- even if the change does not affect them.
What Can Go in a Copybook?
A copybook can contain any valid COBOL source text. The most common uses are:
- Record layouts (01-level data definitions with their subordinate fields)
- File Description (FD) entries
- WORKING-STORAGE data definitions
- LINKAGE SECTION parameters (for subprogram interfaces)
- Constant definitions (VALUE clauses for error messages, codes, and configuration)
- 88-level condition names
- PROCEDURE DIVISION paragraphs (less common, but valid)
- Screen Section layouts (for interactive programs)
- Report Section definitions
In practice, the overwhelming majority of copybooks contain data definitions -- record layouts that define the structure of files, database tables, message queues, and communication areas. Placing PROCEDURE DIVISION code in copybooks is possible but generally discouraged, because it makes programs harder to read and debug.
The Compilation Process
When the compiler processes a COBOL source file, it works through several phases. The very first phase -- before syntax analysis, before optimization, before code generation -- is text processing. During this phase, the compiler scans the source text for COPY and REPLACE statements and resolves them.
Here is the sequence:
- The compiler reads the source text line by line.
- When it encounters a COPY statement, it locates the named copybook in the copybook library (search path).
- The entire contents of the copybook replace the COPY statement in the source text.
- If the COPY statement includes a REPLACING clause, the specified text substitutions are applied to the copied text.
- If the copied text itself contains COPY statements (nested copies), those are resolved recursively.
- After all COPY statements are resolved, any REPLACE directives are processed.
- The resulting expanded source text is then compiled normally.
The compiler listing (produced with the SOURCE or LIST option) shows the expanded source, so you can see exactly what text was brought in from each copybook. This expanded listing is invaluable for debugging.
18.2 The COPY Statement
Basic Syntax
The COPY statement has the following general format:
COPY copybook-name [OF|IN library-name]
[REPLACING operand-1 BY operand-2 ...].
At its simplest, the statement names the copybook to be included:
COPY CUSTOMER-RECORD.
The period at the end is mandatory. The COPY statement is a compiler-directing statement, not a procedural statement, and it must always end with a period.
Where to Place COPY Statements
COPY statements can appear anywhere in a COBOL program where the copied text would be valid. The most common locations are:
In the FILE SECTION (after an FD entry):
FD CUSTOMER-FILE
RECORDING MODE IS F
RECORD CONTAINS 170 CHARACTERS.
COPY CUSTOMER-RECORD.
In the WORKING-STORAGE SECTION:
WORKING-STORAGE SECTION.
COPY CUSTOMER-RECORD.
COPY ERROR-MESSAGES.
In the LINKAGE SECTION:
LINKAGE SECTION.
COPY CUSTOMER-RECORD.
In the PROCEDURE DIVISION (less common):
PROCEDURE DIVISION.
COPY VALIDATION-LOGIC.
The key rule is: the text in the copybook must be syntactically valid at the point where it is inserted. If a copybook contains a 01-level record definition, it must be placed where a 01-level is valid (in the FILE SECTION, WORKING-STORAGE SECTION, or LINKAGE SECTION -- not in the middle of a paragraph in the PROCEDURE DIVISION).
Example 1: Basic COPY Statement
Let us look at a complete example. Suppose we have a copybook called CUSTOMER-RECORD that defines a 170-byte customer record:
******************************************************************
* COPYBOOK: CUSTOMER-RECORD
******************************************************************
01 CUSTOMER-RECORD.
05 CUST-ID PIC 9(08).
05 CUST-NAME.
10 CUST-LAST-NAME PIC X(25).
10 CUST-FIRST-NAME PIC X(15).
10 CUST-MIDDLE-INIT PIC X(01).
05 CUST-ADDRESS.
10 CUST-STREET PIC X(30).
10 CUST-CITY PIC X(20).
10 CUST-STATE PIC X(02).
10 CUST-ZIP PIC 9(05).
05 CUST-PHONE PIC 9(10).
05 CUST-TYPE PIC X(01).
88 CUST-INDIVIDUAL VALUE 'I'.
88 CUST-BUSINESS VALUE 'B'.
88 CUST-GOVERNMENT VALUE 'G'.
05 CUST-STATUS PIC X(01).
88 CUST-ACTIVE VALUE 'A'.
88 CUST-INACTIVE VALUE 'I'.
88 CUST-CLOSED VALUE 'C'.
05 CUST-OPEN-DATE PIC 9(08).
05 CUST-BALANCE PIC S9(09)V99.
05 FILLER PIC X(10).
A program that uses this copybook simply writes:
FD CUSTOMER-FILE
RECORDING MODE IS F
RECORD CONTAINS 170 CHARACTERS.
COPY CUSTOMER-RECORD.
After the compiler resolves the COPY statement, the program behaves exactly as if the entire 01-level definition had been typed directly after the FD entry. The program can then reference CUST-ID, CUST-LAST-NAME, CUST-BALANCE, and all other fields defined in the copybook.
The complete working program is in code/example-01-basic-copy.cob. It reads a customer file, categorizes records by status, and produces a summary report -- all while using field names defined in the copybook rather than in the program itself.
Copybook Naming and File Extensions
Copybook naming conventions vary by environment:
| Environment | Convention | Example |
|---|---|---|
| z/OS (PDS members) | 1-8 character member name, no extension | CUSTREC |
| GnuCOBOL | File name with .cpy extension |
customer-record.cpy |
| Micro Focus | File name with .cpy or .CPY |
CUSTREC.CPY |
| ACUCOBOL | File name, various extensions | customer-record.cbl |
On z/OS, copybooks are stored as members of a Partitioned Data Set (PDS) or Partitioned Data Set Extended (PDSE). The member name is limited to eight characters, which is why you often see abbreviated names like CUSTREC, TRANREC, or ERRMSG01.
In GnuCOBOL and other open-source implementations, copybooks are ordinary files in the file system. The convention used in this textbook is to use lowercase names with hyphens and the .cpy extension (for example, customer-record.cpy), which matches the COBOL tradition of hyphenated names.
The COPY...OF/IN Clause
On z/OS, you can specify which library contains the copybook:
COPY CUSTREC OF PRODCOPY.
or equivalently:
COPY CUSTREC IN PRODCOPY.
The library name PRODCOPY corresponds to a DD statement in the JCL. This allows you to have multiple copybook libraries and explicitly choose which one to use. In practice, most shops rely on the SYSLIB concatenation rather than specifying library names explicitly, but the OF/IN clause is useful when you need to resolve ambiguity.
18.3 Copybook Search Order and Library Configuration
z/OS: SYSLIB DD Statement
On z/OS, the COBOL compiler searches for copybooks in the libraries specified by the SYSLIB DD statement in the compile JCL. When multiple libraries are concatenated, the compiler searches them in order -- the first library containing a matching member name wins.
//SYSLIB DD DSN=MYAPP.DEV.COPYLIB,DISP=SHR Library 1
// DD DSN=MYAPP.COMMON.COPYLIB,DISP=SHR Library 2
// DD DSN=COMPANY.SHARED.COPYLIB,DISP=SHR Library 3
In this example, if a program contains COPY CUSTREC, the compiler first looks in MYAPP.DEV.COPYLIB. If the member is not found there, it looks in MYAPP.COMMON.COPYLIB, and then in COMPANY.SHARED.COPYLIB. The first match is used.
This layered search order supports a common development pattern:
- Application-specific copybooks in the first library
- Shared application copybooks in the second
- Enterprise-wide copybooks in the third
A developer can create a modified version of a shared copybook in the application-specific library for testing, and it will take precedence over the shared version.
The complete JCL for compiling, linking, and running a program with copybooks is in code/example-01-basic-copy.jcl.
GnuCOBOL: The -I Flag
In GnuCOBOL, the -I flag specifies directories to search for copybooks:
cobc -x -I ./code -I ../../shared-copybooks example-01-basic-copy.cob
Multiple -I flags can be specified, and they are searched in order, just like the SYSLIB concatenation on z/OS. The current directory is always searched first (unless overridden).
You can also set the COB_COPY_DIR environment variable to specify a default copybook search path:
export COB_COPY_DIR=/home/cobol/shared-copybooks
cobc -x example-01-basic-copy.cob
Micro Focus: The COBCPY Environment Variable
Micro Focus Visual COBOL uses the COBCPY environment variable:
set COBCPY=./copybooks;/shared/copybooks;%COBCPY%
18.4 COPY...REPLACING: Customizing Copybook Content
The REPLACING clause is one of the most powerful features of the COPY statement. It performs text substitution on the copybook content as it is being included, allowing a single copybook to be customized for different contexts.
Why REPLACING Is Needed
Consider a common scenario: you have a program that reads two files -- a customer master file and a prospect file. Both files have the same record layout (they share the same copybook). But you cannot simply write:
FD CUSTOMER-MASTER.
COPY CUSTOMER-RECORD.
FD PROSPECT-FILE.
COPY CUSTOMER-RECORD. *> ERROR: Duplicate names!
This would create two sets of identically named fields (CUST-ID, CUST-NAME, CUST-BALANCE, etc.), which is a compile error. You need a way to include the same copybook with different field name prefixes.
Pseudo-Text Replacement
The most common form of REPLACING uses pseudo-text delimiters (==):
COPY CUSTOMER-RECORD
REPLACING ==CUSTOMER-RECORD== BY ==MASTER-RECORD==
==CUST-== BY ==MAST-==.
The == delimiters mark the boundaries of the text to find and replace. In this example, every occurrence of CUSTOMER-RECORD in the copybook is replaced by MASTER-RECORD, and every occurrence of CUST- is replaced by MAST-. So CUST-ID becomes MAST-ID, CUST-BALANCE becomes MAST-BALANCE, and so on.
Now you can include the same copybook twice with different prefixes:
FD CUSTOMER-MASTER.
COPY CUSTOMER-RECORD
REPLACING ==CUSTOMER-RECORD== BY ==MASTER-RECORD==
==CUST-== BY ==MAST-==.
FD PROSPECT-FILE.
COPY CUSTOMER-RECORD
REPLACING ==CUSTOMER-RECORD== BY ==PROSPECT-RECORD==
==CUST-== BY ==PROS-==.
The master file now has fields named MAST-ID, MAST-NAME, MAST-BALANCE, and the prospect file has PROS-ID, PROS-NAME, PROS-BALANCE. Both came from the same copybook, ensuring the layouts are identical.
Multiple REPLACING Pairs
You can specify as many replacement pairs as needed:
COPY CUSTOMER-RECORD
REPLACING ==CUSTOMER-RECORD== BY ==WS-WORK-CUSTOMER==
==CUST-== BY ==WK-==
==PIC X(25)== BY ==PIC X(30)==
==PIC 9(08)== BY ==PIC 9(10)==.
Each pair is processed independently. The replacements are applied in the order specified, but they do not cascade -- the output of one replacement is not fed as input to the next.
Identifier Replacement
In addition to pseudo-text, you can replace identifiers directly:
COPY CUSTOMER-RECORD
REPLACING CUSTOMER-RECORD BY PROSPECT-RECORD.
However, this form is less flexible than pseudo-text replacement because it can only replace complete words (identifiers), not partial text or arbitrary strings. The pseudo-text form (with == delimiters) is strongly preferred because it allows partial-word substitution, which is essential for prefix replacement.
Practical Patterns for REPLACING
Pattern 1: Prefix Substitution (most common)
COPY MY-RECORD
REPLACING ==MY-== BY ==WS-==.
Pattern 2: Creating Working Storage Copies
COPY CUSTOMER-RECORD
REPLACING ==CUSTOMER-RECORD== BY ==WS-CUST-HOLD==
==CUST-== BY ==WS-HOLD-==.
Pattern 3: Level Number Adjustment
COPY FIELD-DEFINITIONS
REPLACING ==01== BY ==05==.
This changes a 01-level group to a 05-level subordinate, allowing it to be nested under another group.
Pattern 4: Generic Copybooks with Placeholders
Some shops design copybooks with deliberate placeholder text:
* In the copybook:
01 :PREFIX:-RECORD.
05 :PREFIX:-ID PIC 9(08).
05 :PREFIX:-NAME PIC X(30).
05 :PREFIX:-STATUS PIC X(01).
Programs then replace the placeholder:
COPY GENERIC-RECORD
REPLACING ==:PREFIX:== BY ==CUST==.
The resulting text defines CUST-RECORD, CUST-ID, CUST-NAME, and CUST-STATUS. This pattern is demonstrated fully in code/example-02-copy-replacing.cob.
Rules and Restrictions for REPLACING
-
Pseudo-text delimiters (
==) must contain at least one text word.== ==(empty pseudo-text) is not valid as the operand being replaced, though it is valid as the replacement (effectively deleting the matched text). -
Partial word matching: In pseudo-text, the text between
==delimiters is matched as a sequence of text words. The match is case-sensitive in most compilers, though some allow case-insensitive matching. -
REPLACING does not affect nested COPYs: If a copybook contains another COPY statement, the REPLACING on the outer COPY does not apply to the text brought in by the inner COPY. Each COPY's REPLACING applies only to its own copybook text.
-
REPLACING applies before compilation: The substitution happens during the text-processing phase, before the compiler analyzes syntax. This means you can replace any text, including partial keywords, picture strings, or even comment text.
18.5 The REPLACE Statement
The REPLACE statement is a separate compiler directive, distinct from COPY...REPLACING. While COPY...REPLACING applies only to text brought in from a copybook, REPLACE applies to all source text from the point of the REPLACE statement forward, including text coded directly in the program and text brought in by COPY statements.
Syntax
REPLACE ==pseudo-text-1== BY ==pseudo-text-2==
[==pseudo-text-3== BY ==pseudo-text-4==] ...
.
REPLACE OFF.
Scope and Behavior
A REPLACE statement takes effect at the point where it appears and remains active until:
- Another REPLACE statement is encountered (which supersedes it), or
- A
REPLACE OFFstatement is encountered, or - The end of the compilation unit is reached.
Unlike COPY...REPLACING, which applies to a specific copybook inclusion, REPLACE is a global directive that affects all subsequent source text.
Processing Order
The COBOL standard defines a precise processing order:
- First, all COPY statements are resolved, with their REPLACING clauses applied to the copied text.
- Then, REPLACE directives are applied to the entire expanded source text.
This means REPLACE can modify text that was brought in by COPY statements. It also means REPLACE cannot affect COPY statements themselves -- by the time REPLACE is processed, all COPY statements have already been resolved.
Practical Example
The REPLACE statement is particularly useful for creating abbreviations or for conditional compilation patterns:
REPLACE ==:CUST:== BY ==WS-CUSTOMER-RECORD==
==:TRANS:== BY ==WS-TRANSACTION-RECORD==.
PROCEDURE DIVISION.
1000-PROCESS.
MOVE :CUST: TO OUTPUT-RECORD.
IF :TRANS: = SPACES
DISPLAY 'No transaction data'
END-IF.
REPLACE OFF.
After REPLACE processing, the code becomes:
PROCEDURE DIVISION.
1000-PROCESS.
MOVE WS-CUSTOMER-RECORD TO OUTPUT-RECORD.
IF WS-TRANSACTION-RECORD = SPACES
DISPLAY 'No transaction data'
END-IF.
A complete example demonstrating REPLACE is in code/example-03-replace.cob.
REPLACE vs. COPY...REPLACING
| Feature | COPY...REPLACING | REPLACE |
|---|---|---|
| Scope | Only the copied text | All subsequent source text |
| Timing | During COPY resolution | After all COPYs resolved |
| Activation | Automatic with COPY | Explicit REPLACE statement |
| Deactivation | Automatic after copy | REPLACE OFF or next REPLACE |
| Multiple active | One per COPY | One at a time |
| Affects original code | No (only copied text) | Yes |
In practice, COPY...REPLACING is far more commonly used than REPLACE. Most COBOL shops use COPY...REPLACING daily and REPLACE rarely, if ever. REPLACE is primarily used for specialized scenarios like debug toggles, abbreviation expansion, or source-level conditional compilation.
18.6 Nested COPY Statements
A copybook can itself contain COPY statements, creating a nesting structure. When the compiler resolves the outer COPY, it encounters the inner COPY statements and resolves them recursively.
How Nesting Works
Consider a "master" copybook called APP-BANKING-WS that pulls in all the data definitions for a banking application:
* Copybook: APP-BANKING-WS
* Master copybook for the banking application
COPY CUSTOMER-RECORD
REPLACING ==CUSTOMER-RECORD== BY ==WS-CUSTOMER==
==CUST-== BY ==WS-CUST-==.
COPY TRANSACTION-RECORD
REPLACING ==TRANSACTION-RECORD== BY ==WS-TRANSACTION==
==TRANS-== BY ==WS-TRANS-==.
COPY ERROR-MESSAGES.
A program can then include all three copybooks with a single statement:
WORKING-STORAGE SECTION.
COPY APP-BANKING-WS.
The compiler resolves this in stages:
COPY APP-BANKING-WSis replaced by the contents ofAPP-BANKING-WS.- The compiler then finds
COPY CUSTOMER-RECORD,COPY TRANSACTION-RECORD, andCOPY ERROR-MESSAGESin the expanded text. - Each of those is resolved in turn, with their respective REPLACING clauses.
Important Rules for Nesting
-
REPLACING on the outer COPY does NOT cascade to inner COPYs. If you write
COPY APP-BANKING-WS REPLACING ==WS-== BY ==MY-==, the replacement applies only to text that is directly inAPP-BANKING-WS, not to text brought in by the nested COPY statements within it. -
Circular references are prohibited. If copybook A copies copybook B, and copybook B copies copybook A, the compiler will detect the circular dependency and report an error.
-
Nesting depth may be limited. IBM Enterprise COBOL allows significant nesting depth, but there may be practical limits. Most real-world applications rarely nest beyond two or three levels.
-
Each nested COPY is independently resolved. The inner COPY statements can have their own REPLACING clauses, and these operate independently of any REPLACING on the outer COPY.
The program code/example-04-nested-copy.cob demonstrates these concepts with a program that uses both direct and nested copybook inclusions.
18.7 Copybook Design Best Practices
Designing good copybooks is an art that pays enormous dividends in maintainability and consistency. Here are the practices that experienced COBOL shops follow.
One Record Layout Per Copybook
The most important rule: each copybook should contain exactly one logical thing. A customer record layout goes in one copybook. A transaction record layout goes in another. Error messages go in a third. Do not combine unrelated definitions in a single copybook.
Why? Because different programs need different combinations of definitions. If your customer record and transaction record are in the same copybook, a program that only needs the customer record is forced to include the transaction record as well. This creates unnecessary dependencies and makes impact analysis more difficult.
Consistent Naming Conventions
Establish and enforce naming conventions for both the copybook names and the fields within them:
Copybook naming:
| Type | Pattern | Example |
|---|---|---|
| Record layout | APP-entity-RECORD |
BNK-CUSTOMER-RECORD |
| Constants | APP-entity-CONST |
BNK-FEE-CONST |
| Error messages | APP-entity-ERRORS |
BNK-TRANS-ERRORS |
| Linkage parameters | APP-entity-PARMS |
BNK-CALC-PARMS |
| Screen layouts | APP-entity-SCREEN |
BNK-INQUIRY-SCREEN |
Field naming within copybooks:
Use a consistent prefix that identifies the entity. For a customer record, all fields start with CUST-. For a transaction record, all fields start with TRANS-. This makes REPLACING easy and predictable: to customize the copybook, you simply replace the prefix.
Documentation Within Copybooks
Every copybook should include a header comment block that documents:
- The copybook name
- Its purpose
- How to use it (the COPY statement syntax)
- The record length (for record-oriented copybooks)
- Version history
- Which programs or applications use it
******************************************************************
* COPYBOOK: CUSTOMER-RECORD
* PURPOSE: Standard customer record layout for the banking
* application.
* USAGE: COPY CUSTOMER-RECORD.
* RECORD LENGTH: 170 bytes
* VERSION: 2.3
* DATE: 2024-01-15
* CHANGES: v2.3 - Added CUST-EMAIL field (2024-01-15)
* v2.2 - Extended CUST-ZIP to 9 digits (2023-06-01)
* v2.1 - Added 88-levels for CUST-TYPE (2023-01-10)
* v2.0 - Major restructure (2022-07-15)
* v1.0 - Initial version (2020-01-01)
******************************************************************
Avoid PROCEDURE DIVISION Code in Copybooks (Usually)
While it is technically valid to put PROCEDURE DIVISION paragraphs in a copybook, doing so is generally a bad practice for several reasons:
-
Readability suffers. When reading a program, you expect to see the logic in the PROCEDURE DIVISION. Hidden logic in copybooks makes the program harder to follow.
-
Debugging is harder. The compiled listing shows the expanded code, but during debugging you are looking at the original source. If a bug is in a copybook paragraph, it is not immediately visible.
-
CALL is usually better. If you need to share executable logic across programs, CALL a subprogram. This provides a clean interface (the LINKAGE SECTION), separate compilation, and the ability to change the subprogram without recompiling the caller.
The exception is very short, standardized code patterns like initialization sequences or standard error-handling paragraphs that are tightly coupled to data definitions in the same copybook.
Design for REPLACING
When designing a copybook, think about how it will be customized with REPLACING. Use a consistent prefix for all field names so that a single REPLACING clause can rename all fields:
* GOOD: Consistent prefix, easy to REPLACE
01 CUST-RECORD.
05 CUST-ID PIC 9(08).
05 CUST-NAME PIC X(30).
05 CUST-BALANCE PIC S9(09)V99.
* BAD: Inconsistent naming, requires multiple REPLACING clauses
01 CUSTOMER-DATA.
05 CID PIC 9(08).
05 CUSTOMER-NAME PIC X(30).
05 ACCT-BALANCE PIC S9(09)V99.
18.8 Enterprise Copybook Management
In a large enterprise, copybook management is not just a technical practice -- it is a governance discipline. Organizations with thousands of COBOL programs and hundreds of copybooks need formal processes to manage changes safely.
Copybook Libraries on z/OS
On z/OS, copybooks are stored in Partitioned Data Sets (PDS) or, more commonly today, Partitioned Data Set Extended (PDSE). A typical organization has multiple copybook libraries organized by environment and purpose:
PROD.COMMON.COPYLIB Enterprise-wide production copybooks
PROD.BANKING.COPYLIB Banking application production copybooks
PROD.INSURANCE.COPYLIB Insurance application production copybooks
TEST.BANKING.COPYLIB Banking application test copybooks
DEV.BANKING.COPYLIB Banking application development copybooks
The JCL SYSLIB concatenation controls which libraries the compiler searches, and the order in which they are searched. This allows developers to work with modified copybooks in their development libraries without affecting production.
Change Management: Impact Analysis
Before changing a copybook, you must know which programs use it. This is called impact analysis, and it is one of the most critical activities in COBOL application maintenance.
On z/OS, the most common approach is to scan the compiler listings or cross-reference databases:
-
SCLM (Software Configuration and Library Manager): IBM's source management tool tracks copybook dependencies automatically.
-
Endevor: Broadcom's change management system maintains a complete dependency graph of programs and copybooks.
-
Custom cross-reference utilities: Many shops build their own tools (like the one in
code/case-study-code.cob) that scan source members for COPY statements and build cross-reference reports. -
Compiler cross-reference listings: The XREF compiler option produces a listing that shows every copybook used by a program.
The impact analysis process for a copybook change typically follows these steps:
- Identify all affected programs: Scan for all programs containing
COPY copybook-name. - Classify the impact: Determine whether the change affects the field layout, adds new fields, or changes field attributes.
- Plan the recompilation: All affected programs must be recompiled with the updated copybook.
- Schedule testing: All affected programs must be tested after recompilation.
- Coordinate the promotion: All recompiled programs and the updated copybook must be promoted together.
Copybook Versioning Strategies
There are two common approaches to copybook versioning:
Strategy 1: In-Place Update (most common)
The copybook is updated in place, and all programs that use it are recompiled. This is the simplest approach and works well when:
- The organization has strong change management tools
- All affected programs can be identified and recompiled
- The change can be promoted atomically (all programs and the copybook go to production together)
Strategy 2: Versioned Names
A new version of the copybook gets a new name (e.g., CUSTREC2), and programs are migrated to the new version individually. This approach is used when:
- The change is incompatible with existing programs
- Not all programs can be updated simultaneously
- A gradual migration is preferred
In practice, most shops use in-place updates for minor changes (adding optional fields to the end of a record, changing comments) and versioned names for breaking changes (changing the record length, reordering fields, changing field types).
Cross-Reference Listings
The compiler's XREF option produces a cross-reference listing that shows, among other things, which copybooks were included in the compilation. A typical cross-reference entry looks like:
COPYBOOK LIBRARY LINE
CUSTREC PROD.COPYLIB 45
TRANREC PROD.COPYLIB 52
ERRMSG01 COMM.COPYLIB 61
This information can be extracted from compiler listings and aggregated across all programs to build a complete copybook dependency database.
18.9 The Shared-Copybooks Directory Concept
Throughout this textbook, we use a shared-copybooks/ directory that contains copybook files shared across multiple chapters. This mirrors the enterprise pattern of having a shared copybook library that all applications can access.
The shared copybooks in this textbook are:
| Copybook | Description | Record Length |
|---|---|---|
ws-customer-record.cpy |
Enterprise-grade customer record | 300 bytes |
ws-transaction-record.cpy |
Financial transaction record | 200 bytes |
ws-common-fields.cpy |
Common utility fields (dates, flags, counters) | ~350 bytes |
These copybooks are designed to be realistic enterprise-grade layouts with:
- Comprehensive field definitions
- 88-level condition names for all coded fields
- REDEFINES for date fields (for both numeric and component access)
- FILLER fields for future expansion
- Detailed header comments
The program code/example-05-shared-copybook-usage.cob demonstrates using all three shared copybooks in a single program. When compiling, you specify the shared-copybooks directory in the include path:
cobc -x -I ./code -I ../../shared-copybooks example-05-shared-copybook-usage.cob
On z/OS, the equivalent is adding the shared copybook library to the SYSLIB concatenation, as shown in code/example-05-shared-copybook-usage.jcl.
18.10 Common Copybook Patterns
Pattern 1: Record Layouts for Files and Databases
The most common use of copybooks. The same record layout is shared by every program that reads or writes a particular file or database table.
* In the copybook:
01 ACCOUNT-RECORD.
05 ACCT-NUMBER PIC 9(10).
05 ACCT-TYPE PIC X(02).
05 ACCT-BALANCE PIC S9(11)V99.
05 ACCT-OPEN-DATE PIC 9(08).
05 ACCT-STATUS PIC X(01).
88 ACCT-OPEN VALUE 'O'.
88 ACCT-CLOSED VALUE 'C'.
88 ACCT-FROZEN VALUE 'F'.
* In the program:
FD ACCOUNT-FILE.
COPY ACCOUNT-RECORD.
Pattern 2: LINKAGE SECTION Parameters for Subprograms
When multiple programs call the same subprogram, the calling programs and the subprogram all need matching LINKAGE SECTION definitions. A copybook ensures they stay synchronized.
* Copybook: CALC-PARMS
01 CALC-INPUT-PARMS.
05 CALC-PRINCIPAL PIC 9(09)V99.
05 CALC-RATE PIC 9V9(06).
05 CALC-TERM PIC 9(03).
01 CALC-OUTPUT-PARMS.
05 CALC-PAYMENT PIC 9(07)V99.
05 CALC-TOTAL-INT PIC 9(09)V99.
05 CALC-RETURN-CODE PIC 9(02).
* In the calling program (WORKING-STORAGE):
COPY CALC-PARMS.
* In the subprogram (LINKAGE SECTION):
COPY CALC-PARMS.
Pattern 3: Constants and Configuration
Copybooks can define constants that multiple programs share, ensuring consistency:
* Copybook: APP-CONSTANTS
01 APP-CONSTANTS.
05 MAX-RETRY-COUNT PIC 9(02) VALUE 03.
05 TIMEOUT-SECONDS PIC 9(04) VALUE 0030.
05 DEFAULT-CURRENCY PIC X(03) VALUE 'USD'.
05 TAX-RATE-2024 PIC 9V9(04) VALUE 0.0725.
05 FED-WIRE-CUTOFF PIC 9(04) VALUE 1700.
Pattern 4: Error Code Definitions
Standardized error codes and messages ensure consistent error handling and reporting across an application. The code/error-messages.cpy copybook demonstrates this pattern with structured error codes, severity levels, and human-readable messages.
Pattern 5: Screen and Report Layouts
For CICS programs (interactive) and batch report programs, copybooks can define screen maps and report line layouts:
* Copybook: INQUIRY-SCREEN
01 INQUIRY-SCREEN-LAYOUT.
05 SCR-TITLE PIC X(40).
05 SCR-CUST-ID-LBL PIC X(15) VALUE 'Customer ID:'.
05 SCR-CUST-ID PIC X(10).
05 SCR-NAME-LBL PIC X(15) VALUE 'Name:'.
05 SCR-NAME PIC X(30).
05 SCR-MESSAGE PIC X(79).
18.11 COPY vs. CALL: When to Share Code by Inclusion vs. by Calling
One of the most important design decisions in COBOL programming is choosing between sharing code via COPY (inclusion at compile time) and sharing code via CALL (invocation at runtime). Each approach has distinct advantages.
Use COPY When:
-
Sharing data definitions. This is the primary use case. Record layouts, constants, and parameter definitions are shared via COPY.
-
The shared text is small and rarely changes. Small utility definitions that are stable over time are good candidates for copybooks.
-
Performance is critical. Copied code is inline -- there is no CALL overhead, no parameter passing, no linkage. For tight loops processing millions of records, inline code from a copybook can be faster than a CALL.
-
The shared text needs customization. COPY...REPLACING allows each program to tailor the shared text to its needs. CALL does not offer this flexibility.
Use CALL When:
-
Sharing executable logic. Business rules, calculation routines, and validation logic are better shared via CALL. This provides a clean interface (LINKAGE SECTION), separate compilation, and the ability to change the subprogram without recompiling every caller.
-
The shared code is large or complex. A 500-line validation routine should be a subprogram, not a copybook. Copying large blocks of code into many programs wastes memory and makes maintenance harder.
-
Independent deployment is needed. With CALL, you can update the subprogram and deploy it independently. With COPY, every program that includes the copybook must be recompiled and redeployed.
-
The logic should be centralized. If a business rule must be applied consistently everywhere, implement it in one subprogram and have all programs CALL it. This guarantees consistency -- a copybook only guarantees consistency if every program is recompiled after every change.
The Hybrid Approach
Many enterprise applications use both patterns together:
- COPY for data definitions (record layouts and parameters)
- CALL for business logic (the subprogram uses the same copybook for its LINKAGE SECTION)
This gives you the best of both worlds: shared data definitions ensure structural consistency, and shared subprograms ensure logical consistency.
18.12 Copybook Impact Analysis
Impact analysis -- determining which programs are affected by a copybook change -- is one of the most critical maintenance activities in a COBOL shop. A single copybook can be referenced by hundreds of programs, and changing it without understanding the impact can be catastrophic (as our opening vignette illustrated).
Manual Impact Analysis
The simplest approach is to search the source library for programs containing the copybook name:
On z/OS, using ISPF SEARCH:
SEARCH 'COPY CUSTREC' IN PROD.COBOL.SOURCE
Using GnuCOBOL tools:
grep -rl "COPY CUSTOMER-RECORD" /path/to/source/*.cob
Automated Impact Analysis
Enterprise-grade change management tools (Endevor, SCLM, ChangeMan) maintain dependency databases that are updated automatically every time a program is compiled. These tools can instantly answer questions like:
- Which programs use copybook X?
- Which copybooks does program Y use?
- If I change copybook X, which load modules need to be rebuilt?
- What is the complete dependency chain from copybook X through all programs to all load modules?
The case study program in code/case-study-code.cob demonstrates a simplified version of this analysis: it scans COBOL source files for COPY statements and builds a cross-reference report.
The Ripple Effect
When analyzing impact, consider the full ripple:
- Direct impact: Programs that COPY the changed copybook must be recompiled.
- Indirect impact: If the changed copybook is nested inside another copybook, programs that COPY the outer copybook are also affected.
- Runtime impact: If the change affects a file layout, all programs that read or write that file are affected -- even if they use a different copybook to define their version of the record (a data-level dependency, not a source-level dependency).
- Cross-system impact: If the file is shared across systems (for example, an extract file sent to another application), the downstream systems are affected too.
18.13 Common Mistakes and Pitfalls
Mistake 1: Circular COPY References
If copybook A contains COPY B and copybook B contains COPY A, the compiler will enter an infinite loop (or, more likely, detect the cycle and report an error). This is rare but can happen when reorganizing copybook libraries.
Mistake 2: Wrong Pseudo-Text Delimiters
The pseudo-text delimiters are ==, not single =:
* WRONG:
COPY CUSTREC REPLACING =CUST-= BY =MAST-=.
* CORRECT:
COPY CUSTREC REPLACING ==CUST-== BY ==MAST-==.
Mistake 3: Forgetting the Period
The COPY statement must end with a period:
* WRONG (no period):
COPY CUSTOMER-RECORD
* CORRECT:
COPY CUSTOMER-RECORD.
Mistake 4: REPLACING with Incomplete Prefix Matching
If your copybook has fields like CUST-ID and CUSTOMER-TYPE, replacing ==CUST-== will change CUST-ID to (say) MAST-ID, but CUSTOMER-TYPE will become MASTOMER-TYPE -- probably not what you intended. Design your copybook field names with consistent, clean prefixes to avoid this.
Mistake 5: Stale Object Code
After changing a copybook, you must recompile every program that uses it. If you recompile some programs but not others, the programs will have different views of the same data structure. This is the single most common cause of data corruption in COBOL batch systems.
Mistake 6: Assuming REPLACING Cascades to Nested COPYs
As discussed in Section 18.6, REPLACING on an outer COPY does not apply to text brought in by nested COPYs. Each COPY statement's REPLACING applies only to its own direct text.
Mistake 7: Placing COPY Where the Text Is Invalid
A COPY statement must appear where the copied text would be syntactically valid. Copying a 01-level definition into the PROCEDURE DIVISION, or copying a PERFORM statement into WORKING-STORAGE, will produce a compile error.
18.14 The Complete Copybook Library Application
The program code/example-06-copybook-library.cob brings together all the concepts in this chapter in a complete, realistic application. It demonstrates:
- Using multiple copybooks for different purposes (record layouts, error messages, constants)
- COPY...REPLACING to create distinct field name sets for input, output, and working storage versions of the same record
- Using 88-level conditions from copybooks for business logic
- Referencing error message constants from a shared copybook
- The classic sequential file update pattern using copybook-defined records
The program performs daily account maintenance: it reads a customer master file and a transaction file, applies deposits, withdrawals, and transfers to customer balances, writes an updated master file, and produces an audit report. Each file's record layout comes from a copybook, and the error messages used throughout the program come from the shared error-messages copybook.
Study this program carefully. It represents the kind of copybook usage you will encounter in real-world enterprise COBOL applications. Every field name in the FILE SECTION and most of the WORKING-STORAGE SECTION originated in a copybook, yet the program reads cleanly because the REPLACING clauses create meaningful, context-appropriate names.
18.15 Summary
The COPY statement is COBOL's mechanism for code reuse at the source level. It allows data definitions, constants, and other source text to be maintained in a single location and shared across multiple programs. The REPLACING clause provides the flexibility to customize the copied text for different contexts, and the REPLACE compiler directive offers global text substitution across the entire source.
Effective copybook management requires:
- Good design: One record per copybook, consistent naming, thorough documentation
- Proper tooling: Compiler include paths (SYSLIB on z/OS, -I on GnuCOBOL), change management systems, cross-reference tools
- Disciplined processes: Impact analysis before changes, coordinated recompilation after changes, version tracking
- Clear governance: Naming standards, change request workflows, promotion procedures
In the chapters ahead, you will see copybooks used routinely as we build increasingly sophisticated applications. The shared copybooks in the shared-copybooks/ directory will appear in programs throughout the rest of this textbook, just as enterprise copybooks appear in programs throughout a real-world application portfolio.
The next chapter covers COBOL's built-in intrinsic functions, which provide powerful data transformation capabilities without the need for external subprograms or copybooks.