100% found this document useful (1 vote)
448 views800 pages

Enterprise Cobol Programming Guide

COBOL programming guide

Uploaded by

Martin Beltramo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
448 views800 pages

Enterprise Cobol Programming Guide

COBOL programming guide

Uploaded by

Martin Beltramo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 800

Enterprise COBOL for z/OS 

Programming Guide
Version 3 Release 3

SC27-1412-02
Enterprise COBOL for z/OS 

Programming Guide
Version 3 Release 3

SC27-1412-02
Note!
Before using this information and the product it supports, be sure to read the general information under “Notices” on page
725.

Third Edition (February 2004)


This edition applies to Version 3 Release 3 of IBM Enterprise COBOL for z/OS (program number 5655-G53) and to
all subsequent releases and modifications until otherwise indicated in new editions. Make sure that you are using
the correct edition for the level of the product.
You can order publications online at www.ibm.com/shop/publications/order/, or order by phone or fax. IBM
Software Manufacturing Solutions takes publication orders between 8:30 a.m. and 7:00 p.m. Eastern Standard Time
(EST). The phone number is (800)879-2755. The fax number is (800)445-9269.
You can also order publications through your IBM representative or the IBM branch office serving your locality.
© Copyright International Business Machines Corporation 1991, 2004. All rights reserved.
US Government Users Restricted Rights – Use, duplication or disclosure restricted by GSA ADP Schedule Contract
with IBM Corp.
Contents
Tables . . . . . . . . . . . . . . . xiii Initializing a structure (INITIALIZE) . . . . . 27
Assigning values to elementary or group data
About this document . . . . . . . . xv items (MOVE) . . . . . . . . . . . . 27
Assigning arithmetic results (MOVE or
Accessibility . . . . . . . . . . . . . . xv
COMPUTE) . . . . . . . . . . . . . 28
Using assistive technologies . . . . . . . . xv
Assigning input from a screen or file (ACCEPT) 29
Keyboard navigation of the user interface . . . xv
Displaying values on a screen or in a file (DISPLAY) 30
Accessibility of this document . . . . . . . xv
Displaying data on the system logical output
How this document will help you . . . . . . xvi
device . . . . . . . . . . . . . . . 31
Abbreviated terms . . . . . . . . . . . . xvi
Using WITH NO ADVANCING . . . . . . 31
Comparison of commonly used terms . . . . . xvii
Using intrinsic functions (built-in functions) . . . 32
How to read syntax diagrams . . . . . . . . xvii
Types of intrinsic functions . . . . . . . . 33
How examples are shown . . . . . . . . . xviii
Nesting functions . . . . . . . . . . . 33
Accessing softcopy documentation and support
Using tables (arrays) and pointers . . . . . . . 33
information . . . . . . . . . . . . . . xix
Storage and its addressability . . . . . . . . 34
Summary of changes . . . . . . . . . . . xix
Settings for RMODE . . . . . . . . . . . 35
Version 3 Release 3 (February 2004) . . . . . xix
Storage restrictions for passing data . . . . . 35
Version 3 Release 2 (September 2002) . . . . xix
Location of data areas . . . . . . . . . . 35
Version 3 Release 1 (November 2001) . . . . . xx
Storage for LOCAL-STORAGE data . . . . . 35
How to send your comments . . . . . . . . xxi
Storage for external data . . . . . . . . . 35
Storage for QSAM input-output buffers . . . . 36
Part 1. Coding your program . . . . 1
Chapter 3. Working with numbers and
Chapter 1. Structuring your program . . 5 arithmetic . . . . . . . . . . . . . 37
Identifying a program . . . . . . . . . . . 5 Defining numeric data . . . . . . . . . . . 37
Identifying a program as recursive . . . . . . 6 Displaying numeric data . . . . . . . . . . 38
Marking a program as callable by containing Controlling how numeric data is stored . . . . . 39
programs . . . . . . . . . . . . . . 6 Formats for numeric data . . . . . . . . . . 40
Setting a program to an initial state . . . . . . 6 External decimal (DISPLAY) items . . . . . . 40
Changing the header of a source listing . . . . 7 External floating-point (DISPLAY) items . . . . 40
Describing the computing environment . . . . . 7 Binary (COMP) items . . . . . . . . . . 41
Example: FILE-CONTROL entries . . . . . . 8 Native binary (COMP-5) items . . . . . . . 41
Specifying the collating sequence . . . . . . 8 Packed-decimal (COMP-3) items . . . . . . 42
Defining symbolic characters . . . . . . . 10 Floating-point (COMP-1 and COMP-2) items . . 42
Defining a user-defined class . . . . . . . 10 Examples: numeric data and internal
Defining files to the operating system . . . . 10 representation . . . . . . . . . . . . 42
Describing the data . . . . . . . . . . . . 12 Data format conversions . . . . . . . . . . 43
Using data in input and output operations . . . 13 Conversions and precision . . . . . . . . 44
Comparison of WORKING-STORAGE and Sign representation and processing . . . . . . 45
LOCAL-STORAGE . . . . . . . . . . . 15 NUMPROC(PFD) . . . . . . . . . . . 45
Using data from another program . . . . . . 17 NUMPROC(NOPFD) . . . . . . . . . . 45
Processing the data . . . . . . . . . . . . 18 NUMPROC(MIG) . . . . . . . . . . . 46
How logic is divided in the PROCEDURE Checking for incompatible data (numeric class test) 46
DIVISION . . . . . . . . . . . . . . 18 Performing arithmetic . . . . . . . . . . . 47
Declaratives . . . . . . . . . . . . . 22 COMPUTE and other arithmetic statements . . 47
Arithmetic expressions . . . . . . . . . 48
Chapter 2. Using data . . . . . . . . 23 Numeric intrinsic functions . . . . . . . . 48
Using variables, structures, literals, and constants . 23 Math and date Language Environment services 49
Variables . . . . . . . . . . . . . . 23 Examples: numeric intrinsic functions . . . . 51
Data structure: data items and group items . . . 23 Fixed-point versus floating-point arithmetic . . . 53
Literals . . . . . . . . . . . . . . . 24 Floating-point evaluations . . . . . . . . 54
Constants . . . . . . . . . . . . . . 24 Fixed-point evaluations . . . . . . . . . 54
Figurative constants . . . . . . . . . . 25 Arithmetic comparisons (relation conditions) . . 54
Assigning values to data items . . . . . . . . 25 Examples: fixed-point and floating-point
Examples: initializing data items . . . . . . 26 evaluations . . . . . . . . . . . . . 55

© Copyright IBM Corp. 1991, 2004 iii


Using currency signs . . . . . . . . . . . 55 Evaluating single characters for collating
Example: multiple currency signs . . . . . . 56 sequence . . . . . . . . . . . . . . 99
Finding the largest or smallest data item . . . 99
Chapter 4. Handling tables . . . . . . 59 Finding the length of data items . . . . . . 101
Defining a table (OCCURS) . . . . . . . . . 59 Finding the date of compilation . . . . . . 102
Nesting tables . . . . . . . . . . . . . 60
Subscripting . . . . . . . . . . . . . 60 Chapter 7. Processing character data
Indexing . . . . . . . . . . . . . . 61 in an international environment . . . 103
Referring to an item in a table . . . . . . . . 61 Unicode and encoding of language characters . . 105
Subscripting . . . . . . . . . . . . . 62 Using national data (Unicode) in COBOL . . . . 106
Indexing . . . . . . . . . . . . . . 63 National data items . . . . . . . . . . 106
Putting values into a table . . . . . . . . . 64 National literals . . . . . . . . . . . 106
Loading a table dynamically . . . . . . . . 64 National characters as figurative constants . . 106
Initializing a table (INITIALIZE) . . . . . . 64 Storage of national data . . . . . . . . . 107
Assigning values when you define a table Converting national data . . . . . . . . . 107
(VALUE) . . . . . . . . . . . . . . 65 Converting alphanumeric and integer to
Example: PERFORM and subscripting . . . . 66 national data (MOVE) . . . . . . . . . 107
Example: PERFORM and indexing. . . . . . 67 Converting alphanumeric to national data
Creating variable-length tables (DEPENDING ON) 68 (NATIONAL-OF) . . . . . . . . . . . 108
Loading a variable-length table . . . . . . . 69 Converting national to alphanumeric data
Assigning values to a variable-length table . . . 70 (DISPLAY-OF) . . . . . . . . . . . . 108
Searching a table . . . . . . . . . . . . 71 Conversion exceptions . . . . . . . . . 108
Doing a serial search (SEARCH) . . . . . . 71 Example: converting national data . . . . . 109
Doing a binary search (SEARCH ALL) . . . . 72 Processing UTF-8 data . . . . . . . . . . 109
Processing table items using intrinsic functions . . 73 Processing Chinese GB 18030 data . . . . . . 110
Example: intrinsic functions . . . . . . . . 73 Comparing national data items . . . . . . . 111
Comparing national operands . . . . . . . 111
Chapter 5. Selecting and repeating Comparing national and numeric operands . . 111
program actions . . . . . . . . . . 75 Comparing national and alphabetic or
Selecting program actions . . . . . . . . . 75 alphanumeric operands . . . . . . . . . 111
Coding a choice of actions . . . . . . . . 75 Comparing national and group operands . . . 111
Coding conditional expressions . . . . . . . 79 Processing alphanumeric data items that contain
Repeating program actions . . . . . . . . . 83 DBCS data . . . . . . . . . . . . . . 112
Choosing inline or out-of-line PERFORM . . . 83
Coding a loop . . . . . . . . . . . . 84 Chapter 8. Processing files . . . . . 113
Coding a loop through a table . . . . . . . 85 File organization and input-output devices . . . 113
Executing multiple paragraphs or sections . . . 85 Choosing file organization and access mode . . . 115
Format for coding input and output . . . . . 116
Chapter 6. Handling strings . . . . . . 87 Allocating files . . . . . . . . . . . . . 117
Joining data items (STRING) . . . . . . . . 87 Checking for input or output errors . . . . . . 118
Example: STRING statement . . . . . . . . 88
Splitting data items (UNSTRING) . . . . . . . 89 Chapter 9. Processing QSAM files . . 119
Example: UNSTRING statement . . . . . . 89 Defining QSAM files and records in COBOL . . . 119
Manipulating null-terminated strings . . . . . . 91 Establishing record formats . . . . . . . . 120
Example: null-terminated strings . . . . . . 92 Setting block sizes . . . . . . . . . . . 127
Referring to substrings of data items . . . . . . 93 Coding input and output statements for QSAM
Reference modifiers. . . . . . . . . . . 94 files . . . . . . . . . . . . . . . . 129
Example: arithmetic expressions as reference Opening QSAM files . . . . . . . . . . 130
modifiers . . . . . . . . . . . . . . 94 Dynamically creating QSAM files with
Example: intrinsic functions as reference CBLQDA . . . . . . . . . . . . . . 130
modifiers . . . . . . . . . . . . . . 95 Adding records to QSAM files. . . . . . . 131
Tallying and replacing data items (INSPECT) . . . 95 Updating QSAM files . . . . . . . . . 131
Examples: INSPECT statement . . . . . . . 96 Writing QSAM files to a printer or spooled data
Converting data items (intrinsic functions) . . . . 97 set . . . . . . . . . . . . . . . . 131
Converting to uppercase or lowercase Closing QSAM files . . . . . . . . . . 132
(UPPER-CASE, LOWER-CASE) . . . . . . . 97 Handling errors in QSAM files . . . . . . . 133
Converting to reverse order (REVERSE) . . . . 97 Working with QSAM files . . . . . . . . . 133
Converting to numbers (NUMVAL, NUMVAL-C) 97 Defining and allocating QSAM files . . . . . 134
Converting from one code page to another . . . 98 Retrieving QSAM files . . . . . . . . . 136
Evaluating data items (intrinsic functions) . . . . 99 Ensuring file attributes match your program 137

iv Programming Guide
Using striped extended-format QSAM data sets 139 Describing the input to sorting or merging . . . 183
Accessing HFS files using QSAM . . . . . . . 140 Example: describing sort and input files for
Labels for QSAM files . . . . . . . . . . 141 SORT . . . . . . . . . . . . . . . 183
Using trailer and header labels . . . . . . 141 Coding the input procedure . . . . . . . . 184
Format of standard labels . . . . . . . . 143 Describing the output from sorting or merging . . 185
Processing QSAM ASCII files on tape . . . . . 144 Coding the output procedure . . . . . . . . 185
Requesting the ASCII alphabet . . . . . . 144 Coding considerations when using DFSORT . . 186
Defining the record formats . . . . . . . 144 Example: coding the output procedure when
Defining the ddname . . . . . . . . . . 144 using DFSORT . . . . . . . . . . . . 186
Processing ASCII file labels . . . . . . . . . 145 Restrictions on input and output procedures . . . 187
Defining sort and merge data sets . . . . . . 187
Chapter 10. Processing VSAM files 147 Sorting variable-length records . . . . . . . 188
VSAM files . . . . . . . . . . . . . . 148 Requesting the sort or merge . . . . . . . . 188
Defining VSAM file organization and records . . 149 Setting sort or merge criteria . . . . . . . 189
Specifying sequential organization for VSAM Example: sorting with input and output
files . . . . . . . . . . . . . . . 150 procedures . . . . . . . . . . . . . 190
Specifying indexed organization for VSAM files 150 Choosing alternate collating sequences . . . . 190
Specifying relative organization for VSAM files 151 Sorting on windowed date fields . . . . . . 191
Specifying access modes for VSAM files . . . 153 Preserving the original sequence of records with
Defining record lengths for VSAM files . . . . 154 equal keys . . . . . . . . . . . . . 191
Coding input and output statements for VSAM Determining whether the sort or merge was
files . . . . . . . . . . . . . . . . 155 successful . . . . . . . . . . . . . . 192
File position indicator . . . . . . . . . 157 Stopping a sort or merge operation prematurely 192
Opening a file (ESDS, KSDS, or RRDS) . . . . 158 Improving sort performance with FASTSRT . . . 193
Reading records from a VSAM file . . . . . 160 FASTSRT requirements for JCL . . . . . . 193
Updating records in a VSAM file . . . . . . 161 FASTSRT requirements for sort input and
Adding records to a VSAM file . . . . . . 162 output files . . . . . . . . . . . . . 193
Replacing records in a VSAM file. . . . . . 162 Checking for sort errors with NOFASTSRT . . . 195
Deleting records from a VSAM file . . . . . 163 Controlling sort behavior . . . . . . . . . 195
Closing VSAM files . . . . . . . . . . 163 Sort special registers . . . . . . . . . . 196
Handling errors in VSAM files . . . . . . . 164 Changing DFSORT defaults with control
Protecting VSAM files with a password . . . . 164 statements . . . . . . . . . . . . . 197
Example: password protection for a VSAM Allocating storage for sort or merge operations 197
indexed file . . . . . . . . . . . . . 165 Allocating space for sort files . . . . . . . 198
Working with VSAM data sets under z/OS and Using checkpoint/restart with DFSORT . . . . 198
UNIX . . . . . . . . . . . . . . . . 165 Sorting under CICS . . . . . . . . . . . 199
Defining VSAM files . . . . . . . . . . 166 CICS SORT application restrictions . . . . . 199
Creating alternate indexes . . . . . . . . 167
Allocating VSAM files . . . . . . . . . 169 Chapter 13. Handling errors . . . . . 201
Sharing VSAM files through RLS . . . . . . 170 Requesting dumps . . . . . . . . . . . 201
Improving VSAM performance . . . . . . . 171 Creating a formatted dump. . . . . . . . 201
Creating a system dump . . . . . . . . 202
Chapter 11. Processing line-sequential Handling errors in joining and splitting strings . . 202
files . . . . . . . . . . . . . . . 175 Handling errors in arithmetic operations . . . . 203
Example: checking for division by zero . . . . 203
Defining line-sequential files and records in
Handling errors in input and output operations 203
COBOL . . . . . . . . . . . . . . . 175
Using the end-of-file condition (AT END) . . . 206
Allowable control characters . . . . . . . 176
Coding ERROR declaratives . . . . . . . 207
Describing the structure of a line-sequential file 176
Using file status keys . . . . . . . . . . 208
Defining and allocating line-sequential files . . . 177
Example: file status key . . . . . . . . . 209
Coding input-output statements for line-sequential
Using VSAM return codes (VSAM files only) 209
files . . . . . . . . . . . . . . . . 177
Example: checking VSAM status codes . . . . 210
Opening line-sequential files . . . . . . . 178
Coding INVALID KEY phrases . . . . . . 212
Reading records from line-sequential files . . . 178
Example: FILE STATUS and INVALID KEY . . 212
Adding records to line-sequential files . . . . 179
Handling errors when calling programs . . . . 213
Closing line-sequential files. . . . . . . . 179
Writing routines for handling errors . . . . . . 213
Handling errors in line-sequential files . . . . . 180

Chapter 12. Sorting and merging files 181 Part 2. Compiling and debugging
Sort and merge process . . . . . . . . . . 182 your program . . . . . . . . . . 215
Describing the sort or merge file . . . . . . . 182

Contents v
Chapter 14. Compiling under z/OS 217 Example: compiling and linking a COBOL class
Compiling with JCL . . . . . . . . . . . 217 definition under UNIX . . . . . . . . . 259
Using a cataloged procedure . . . . . . . 218 Running OO applications under UNIX . . . . 259
Writing JCL to compile programs . . . . . . 228 Compiling, linking, and running OO applications
Compiling under TSO . . . . . . . . . . 229 using JCL or TSO/E . . . . . . . . . . . 261
Example: ALLOCATE and CALL for compiling Compiling OO applications using JCL or TSO/E 261
under TSO . . . . . . . . . . . . . 230 Preparing and running OO applications using
Example: CLIST for compiling under TSO . . . 230 JCL or TSO/E . . . . . . . . . . . . 262
Starting the compiler from an assembler program 231 Example: compiling, linking, and running an
Defining compiler input and output . . . . . . 232 OO application using JCL . . . . . . . . 263
Data sets used by the compiler under z/OS . . 233
Defining the source code data set (SYSIN) . . . 235 Chapter 17. Compiler options . . . . 267
Specifying source libraries (SYSLIB) . . . . . 235 Option settings for COBOL 85 Standard
Defining the output data set (SYSPRINT) . . . 236 conformance. . . . . . . . . . . . . . 269
Directing compiler messages to your terminal Conflicting compiler options . . . . . . . . 269
(SYSTERM) . . . . . . . . . . . . . 236 ADATA . . . . . . . . . . . . . . . 270
Creating object code (SYSLIN or SYSPUNCH) 236 ADV . . . . . . . . . . . . . . . . 271
Creating an associated data file (SYSADATA) 237 ARITH . . . . . . . . . . . . . . . 271
Defining the output Java data set (SYSJAVA) 237 AWO . . . . . . . . . . . . . . . . 272
Defining the debug data set (SYSDEBUG) . . . 237 BUFSIZE . . . . . . . . . . . . . . . 273
Specifying compiler options under z/OS . . . . 238 CICS . . . . . . . . . . . . . . . . 273
Specifying compiler options with the PROCESS CODEPAGE . . . . . . . . . . . . . . 274
(CBL) statement . . . . . . . . . . . 238 COMPILE . . . . . . . . . . . . . . 275
Example: specifying compiler options using JCL 239 CURRENCY . . . . . . . . . . . . . . 276
Example: specifying compiler options under DATA . . . . . . . . . . . . . . . . 277
TSO . . . . . . . . . . . . . . . 239 DATEPROC . . . . . . . . . . . . . . 278
Compiler options and compiler output under DBCS . . . . . . . . . . . . . . . . 279
z/OS . . . . . . . . . . . . . . . 239 DECK . . . . . . . . . . . . . . . . 279
Compiling multiple programs (batch compilation) 241 DIAGTRUNC . . . . . . . . . . . . . 280
Example: batch compilation . . . . . . . 242 DLL . . . . . . . . . . . . . . . . 281
Specifying compiler options in a batch DUMP . . . . . . . . . . . . . . . 281
compilation . . . . . . . . . . . . . 242 DYNAM . . . . . . . . . . . . . . . 282
Example: precedence of options in a batch EXIT . . . . . . . . . . . . . . . . 283
compilation . . . . . . . . . . . . . 243 EXPORTALL . . . . . . . . . . . . . 283
Example: LANGUAGE option in a batch FASTSRT . . . . . . . . . . . . . . . 284
compilation . . . . . . . . . . . . . 244 FLAG . . . . . . . . . . . . . . . . 284
Correcting errors in your source program . . . . 245 FLAGSTD . . . . . . . . . . . . . . 285
Generating a list of compiler error messages . . 246 INTDATE . . . . . . . . . . . . . . 287
Messages and listings for compiler-detected LANGUAGE . . . . . . . . . . . . . 287
errors . . . . . . . . . . . . . . . 246 LIB . . . . . . . . . . . . . . . . . 288
Format of compiler error messages . . . . . 246 LINECOUNT . . . . . . . . . . . . . 289
Severity codes for compiler error messages . . 247 LIST . . . . . . . . . . . . . . . . 289
MAP . . . . . . . . . . . . . . . . 290
Chapter 15. Compiling under UNIX 249 NAME . . . . . . . . . . . . . . . 291
Setting environment variables under UNIX . . . 249 NSYMBOL . . . . . . . . . . . . . . 291
Specifying compiler options under UNIX . . . . 250 NUMBER . . . . . . . . . . . . . . 292
Compiling and linking with the cob2 command 251 NUMPROC . . . . . . . . . . . . . . 293
Defining input and output . . . . . . . . 251 OBJECT . . . . . . . . . . . . . . . 294
Creating a DLL . . . . . . . . . . . . 252 OFFSET . . . . . . . . . . . . . . . 294
Example: using cob2 to compile under UNIX 252 OPTIMIZE . . . . . . . . . . . . . . 295
cob2 . . . . . . . . . . . . . . . 253 OUTDD . . . . . . . . . . . . . . . 296
cob2 input and output files . . . . . . . . 254 PGMNAME . . . . . . . . . . . . . . 297
Compiling using scripts . . . . . . . . . . 255 PGMNAME(COMPAT) . . . . . . . . . 297
PGMNAME(LONGUPPER). . . . . . . . 298
Chapter 16. Compiling, linking, and PGMNAME(LONGMIXED) . . . . . . . 298
QUOTE/APOST . . . . . . . . . . . . 299
running OO applications . . . . . . 257 RENT . . . . . . . . . . . . . . . . 299
Compiling, linking, and running OO applications RMODE . . . . . . . . . . . . . . . 300
under UNIX . . . . . . . . . . . . . . 257 SEQUENCE . . . . . . . . . . . . . . 301
Compiling OO applications under UNIX . . . 257 SIZE . . . . . . . . . . . . . . . . 302
Preparing OO applications under UNIX . . . 258 SOURCE . . . . . . . . . . . . . . . 302

vi Programming Guide
SPACE . . . . . . . . . . . . . . . 303 Calling to or from COBOL programs . . . . 361
SQL . . . . . . . . . . . . . . . . 303 Coding nested programs . . . . . . . . 361
SSRANGE . . . . . . . . . . . . . . 304 Coding a COBOL program to run above the
TERMINAL . . . . . . . . . . . . . . 305 16-MB line . . . . . . . . . . . . . 362
TEST . . . . . . . . . . . . . . . . 306 Determining the success of ECI calls. . . . . 362
THREAD . . . . . . . . . . . . . . . 309 Compiling with the CICS option . . . . . . . 362
TRUNC . . . . . . . . . . . . . . . 310 Compiling a sequence of programs . . . . . 363
TRUNC example 1 . . . . . . . . . . 312 Separating CICS suboptions . . . . . . . 364
TRUNC example 2 . . . . . . . . . . 312 Integrated CICS translator . . . . . . . . 364
VBREF . . . . . . . . . . . . . . . 313 Using the separate CICS translator . . . . . . 365
WORD . . . . . . . . . . . . . . . 313 CICS reserved-word table . . . . . . . . . 366
XREF . . . . . . . . . . . . . . . . 314 Handling errors by using CICS HANDLE . . . . 367
YEARWINDOW . . . . . . . . . . . . 315 Example: handling errors by using CICS
ZWB . . . . . . . . . . . . . . . . 316 HANDLE . . . . . . . . . . . . . 368

Chapter 18. Compiler-directing Chapter 21. Programming for a DB2


statements . . . . . . . . . . . . 317 environment . . . . . . . . . . . . 371
Coding SQL statements . . . . . . . . . . 371
Chapter 19. Debugging . . . . . . . 321 Using SQL INCLUDE with the DB2 coprocessor 371
Debugging with source language . . . . . . . 322 Using character data . . . . . . . . . . 372
Tracing program logic . . . . . . . . . 322 Using binary items . . . . . . . . . . 373
Finding and handling input-output errors . . . 323 Determining the success of SQL statements . . 373
Validating data . . . . . . . . . . . . 323 Compiling with the SQL option . . . . . . . 373
Finding uninitialized data . . . . . . . . 323 Compiling in batch . . . . . . . . . . 374
Generating information about procedures . . . 324 Separating DB2 suboptions . . . . . . . . 374
Debugging using compiler options . . . . . . 325 DB2 coprocessor . . . . . . . . . . . 375
Finding coding errors . . . . . . . . . 326
Finding line sequence problems . . . . . . 327 Chapter 22. Developing COBOL
Checking for valid ranges . . . . . . . . 327 programs for IMS. . . . . . . . . . 377
Selecting the level of error to be diagnosed . . 328 Compiling and linking COBOL programs for
Finding program entity definitions and running under IMS . . . . . . . . . . . 377
references . . . . . . . . . . . . . 329 Using object-oriented COBOL and Java under IMS 378
Listing data items . . . . . . . . . . . 330 Calling a COBOL method from an IMS Java
Getting listings . . . . . . . . . . . . . 331 application . . . . . . . . . . . . . 378
Example: short listing . . . . . . . . . 332 Building a mixed COBOL and Java application
Example: SOURCE and NUMBER output . . . 335 that starts with COBOL . . . . . . . . . 379
Example: embedded map summary . . . . . 337 Writing mixed-language applications . . . . 380
Terms used in MAP output . . . . . . . . 338
Symbols used in LIST and MAP output . . . 338 Chapter 23. Running COBOL
Example: nested program map . . . . . . 340
Reading LIST output . . . . . . . . . . 340
programs under UNIX . . . . . . . . 383
Example: XREF output - data-name Running in UNIX environments . . . . . . . 383
cross-references . . . . . . . . . . . . 352 Setting and accessing environment variables . . . 384
Example: XREF output - program-name Setting environment variables that affect
cross-references . . . . . . . . . . . . 353 execution . . . . . . . . . . . . . . 384
Example: embedded cross-reference . . . . . 353 Resetting environment variables . . . . . . 385
Example: OFFSET compiler output . . . . . 354 Accessing environment variables . . . . . . 385
Example: VBREF compiler output . . . . . 355 Example: accessing environment variables . . . 385
Preparing to use the debugger . . . . . . . . 355 Calling UNIX/POSIX APIs . . . . . . . . . 386
fork(), exec(), and spawn() . . . . . . . . 386
Samples . . . . . . . . . . . . . . 387
Part 3. Targeting COBOL programs Accessing main program parameters . . . . . 388
for certain environments . . . . . 357 Example: accessing main program parameters 388

Chapter 20. Developing COBOL Part 4. Structuring complex


programs for CICS . . . . . . . . . 359 applications . . . . . . . . . . . 391
Coding COBOL programs to run under CICS . . 359
Coding file input and output . . . . . . . 360 Chapter 24. Using subprograms . . . 393
Retrieving the system date and time . . . . . 360
Main programs, subprograms, and calls . . . . 394
Displaying the contents of data items . . . . 361

Contents vii
Ending and reentering main programs or Choosing THREAD to support multithreading . . 439
subprograms . . . . . . . . . . . . . 394 Transferring control with multithreading . . . . 439
Transferring control to another program . . . . 396 Using cancel with threaded programs . . . . 439
Making static calls . . . . . . . . . . . 397 Ending a program . . . . . . . . . . . 439
Making dynamic calls . . . . . . . . . 397 Preinitializing the COBOL environment . . . 440
AMODE switching . . . . . . . . . . 399 Processing files with multithreading . . . . . . 440
Performance considerations of static and File definition storage . . . . . . . . . 440
dynamic calls . . . . . . . . . . . . 401 Recommended usage for file access . . . . . 441
Making both static and dynamic calls . . . . 401 Example: usage patterns of file input and
Examples: static and dynamic CALL statements 402 output with multithreading. . . . . . . . 441
Calling nested COBOL programs . . . . . . 403 Handling COBOL limitations with multithreading 442
Making recursive calls . . . . . . . . . . 407
Calling to and from object-oriented programs . . 407
Part 5. Using XML and COBOL
Using procedure and function pointers . . . . . 407
Deciding which type of pointer to use . . . . 408 together . . . . . . . . . . . . . 445
Calling a C function pointer . . . . . . . 408
Calling to alternate entry points . . . . . . 409 Chapter 28. Processing XML input 447
Making programs reentrant . . . . . . . . 409 XML parser in COBOL . . . . . . . . . . 447
Accessing XML documents . . . . . . . . . 449
Chapter 25. Sharing data . . . . . . 411 Parsing XML documents . . . . . . . . . 449
Passing data . . . . . . . . . . . . . . 411 Processing XML events . . . . . . . . . 450
Describing arguments in the calling program 413 Writing procedures to process XML . . . . . 456
Describing parameters in the called program 413 Understanding the encoding of XML documents 462
Testing for OMITTED arguments . . . . . . 414 Coded character sets for XML documents . . . 463
Coding the LINKAGE SECTION . . . . . . . 414 Code-page-sensitive characters in XML markup 464
Coding the PROCEDURE DIVISION for passing Specifying the code page . . . . . . . . 464
arguments . . . . . . . . . . . . . . 415 Handling errors in parsing XML documents . . . 465
Grouping data to be passed . . . . . . . 415 Unhandled exceptions . . . . . . . . . 467
Handling null-terminated strings . . . . . . 415 Handling exceptions . . . . . . . . . . 468
Using pointers to process a chained list . . . 416 Terminating XML parsing . . . . . . . . 468
Passing return code information . . . . . . . 419 Code-page conflict exception . . . . . . . 469
Understanding the RETURN-CODE special
register . . . . . . . . . . . . . . 419 Chapter 29. Producing XML output 471
Using PROCEDURE DIVISION RETURNING . . Generating XML output . . . . . . . . . . 471
.. . . . . . . . . . . . . . . . . 420 Example: generating XML . . . . . . . . 473
Specifying CALL . . . RETURNING . . . . . 420 Enhancing XML output . . . . . . . . . . 476
Sharing data by using the EXTERNAL clause. . . 420 Example: enhancing XML output . . . . . . 477
Sharing files between programs (external files) . . 421 Controlling the encoding of generated XML output 480
Example: using external files . . . . . . . 421 Handling errors in generating XML output . . . 480

Chapter 26. Creating a DLL or a DLL Part 6. Developing object-oriented


application . . . . . . . . . . . . 425 programs . . . . . . . . . . . . 483
Dynamic link libraries (DLLs) . . . . . . . . 425
Compiling programs to create DLLs . . . . . . 426
Linking DLLs . . . . . . . . . . . . . 427 Chapter 30. Writing object-oriented
Example: sample JCL for a procedural DLL programs . . . . . . . . . . . . . 485
application . . . . . . . . . . . . . . 428 Example: accounts . . . . . . . . . . . . 486
Prelinking certain DLLs . . . . . . . . . . 429 Subclasses . . . . . . . . . . . . . 487
Using CALL identifier with DLLs . . . . . . 429 Defining a class . . . . . . . . . . . . 488
Search order for DLLs in HFS . . . . . . . 430 CLASS-ID paragraph for defining a class . . . 490
Using DLL linkage and dynamic calls together . . 430 REPOSITORY paragraph for defining a class 490
Using procedure or function pointers with DLLs 431 WORKING-STORAGE SECTION for defining
Calling DLLs from non-DLLs . . . . . . . 432 class instance data . . . . . . . . . . . 492
Example: calling DLLs from non-DLLs . . . . 432 Example: defining a class . . . . . . . . 493
Using COBOL DLLs with C/C++ programs . . . 434 Defining a class instance method . . . . . . . 493
Using DLLs in OO COBOL applications . . . . 434 METHOD-ID paragraph for defining a class
instance method . . . . . . . . . . . 494
Chapter 27. Preparing COBOL INPUT-OUTPUT SECTION for defining a class
instance method . . . . . . . . . . . 495
programs for multithreading . . . . . 437
Multithreading . . . . . . . . . . . . . 437

viii Programming Guide


DATA DIVISION for defining a class instance Requesting deferred restart . . . . . . . . 549
method . . . . . . . . . . . . . . 495 Formats for requesting deferred restart . . . . 550
PROCEDURE DIVISION for defining a class Resubmitting jobs for restart . . . . . . . 551
instance method . . . . . . . . . . . 496 Example: restarting a job at a specific
Overriding an instance method . . . . . . 497 checkpoint step . . . . . . . . . . . . 551
Overloading an instance method . . . . . . 498 Example: requesting a step restart . . . . . 551
Coding attribute (get and set) methods . . . . 499 Example: resubmitting a job for a step restart 551
Example: defining a method . . . . . . . 500 Example: resubmitting a job for a checkpoint
Defining a client . . . . . . . . . . . . 502 restart . . . . . . . . . . . . . . . 552
REPOSITORY paragraph for defining a client 503
DATA DIVISION for defining a client . . . . 504 Chapter 33. Processing two-digit-year
Comparing and setting object references . . . 505 dates . . . . . . . . . . . . . . . 553
Invoking methods (INVOKE) . . . . . . . 506
Millennium language extensions (MLE) . . . . 554
Creating and initializing instances of classes . . 508
Principles and objectives of these extensions . . 554
Freeing instances of classes . . . . . . . . 509
Resolving date-related logic problems . . . . . 555
Example: defining a client . . . . . . . . 510
Using a century window . . . . . . . . 556
Defining a subclass . . . . . . . . . . . 510
Using internal bridging . . . . . . . . . 557
CLASS-ID paragraph for defining a subclass . . 511
Moving to full field expansion. . . . . . . 558
REPOSITORY paragraph for defining a subclass 512
Using year-first, year-only, and year-last date fields 560
WORKING-STORAGE SECTION for defining
Compatible dates . . . . . . . . . . . 561
subclass instance data . . . . . . . . . 512
Example: comparing year-first date fields . . . 562
Defining a subclass instance method . . . . 513
Using other date formats . . . . . . . . 562
Example: defining a subclass (with methods) 513
Example: isolating the year . . . . . . . . 562
Defining a factory section . . . . . . . . . 514
Manipulating literals as dates . . . . . . . . 563
WORKING-STORAGE SECTION for defining
Assumed century window . . . . . . . . 564
factory data . . . . . . . . . . . . . 515
Treatment of nondates . . . . . . . . . 565
Defining a factory method . . . . . . . . 516
Setting triggers and limits . . . . . . . . . 565
Example: defining a factory (with methods) . . 518
Example: using limits . . . . . . . . . 566
Wrapping procedure-oriented COBOL programs 523
Using sign conditions . . . . . . . . . 567
Structuring OO applications . . . . . . . . 524
Sorting and merging by date . . . . . . . . 567
Examples: COBOL applications that you can run
Example: sorting by date and time . . . . . 568
using the java command . . . . . . . . 524
Performing arithmetic on date fields . . . . . . 569
Allowing for overflow from windowed date
Chapter 31. Communicating with Java fields . . . . . . . . . . . . . . . 569
methods . . . . . . . . . . . . . 527 Specifying the order of evaluation . . . . . 570
Accessing JNI services . . . . . . . . . . 527 Controlling date processing explicitly . . . . . 571
Handling Java exceptions . . . . . . . . 528 Using DATEVAL . . . . . . . . . . . 571
Managing local and global references . . . . 530 Using UNDATE . . . . . . . . . . . 571
Java access controls . . . . . . . . . . 531 Example: DATEVAL . . . . . . . . . . 572
Sharing data with Java . . . . . . . . . . 531 Example: UNDATE . . . . . . . . . . 572
Coding interoperable data types in COBOL and Analyzing and avoiding date-related diagnostic
Java . . . . . . . . . . . . . . . 532 messages . . . . . . . . . . . . . . . 572
Declaring arrays and strings for Java . . . . 532 Avoiding problems in processing dates . . . . . 574
Manipulating Java arrays . . . . . . . . 534 Avoiding problems with packed-decimal fields 574
Manipulating Java strings . . . . . . . . 536 Moving from expanded to windowed date fields 574
Example: J2EE client written in COBOL . . . . 539
COBOL client (ConverterClient.cbl) . . . . . 539
Part 8. Improving performance and
Java client (ConverterClient.java) . . . . . . 541
productivity . . . . . . . . . . . 577
Part 7. Specialized processing . . 543
Chapter 34. Tuning your program . . . 579
Using an optimal programming style . . . . . 579
Chapter 32. Interrupts and Using structured programming . . . . . . 580
checkpoint/restart . . . . . . . . . 545 Factoring expressions . . . . . . . . . . 580
Setting checkpoints . . . . . . . . . . . 545 Using symbolic constants . . . . . . . . 580
Designing checkpoints . . . . . . . . . 546 Grouping constant computations . . . . . . 580
Testing for a successful checkpoint . . . . . 546 Grouping duplicate computations . . . . . 581
DD statements for defining checkpoint data sets 547 Choosing efficient data types . . . . . . . . 581
Messages generated during checkpoint . . . . 548 Computational data items . . . . . . . . 581
Restarting programs . . . . . . . . . . . 548 Consistent data types . . . . . . . . . . 582
Requesting automatic restart . . . . . . . 549

Contents ix
Arithmetic expressions . . . . . . . . . 582 Preventing overlay when adding elements to a
Exponentiations . . . . . . . . . . . 582 variable table . . . . . . . . . . . . 615
Handling tables efficiently . . . . . . . . . 583
Optimization of table references . . . . . . 584 Appendix C. Converting double-byte
Optimizing your code . . . . . . . . . . 586 character set (DBCS) data . . . . . . 619
Optimization . . . . . . . . . . . . 586
DBCS notation . . . . . . . . . . . . . 619
Example: PERFORM procedure integration . . 588
Alphanumeric to DBCS data conversion
Choosing compiler features to enhance
(IGZCA2D) . . . . . . . . . . . . . . 619
performance . . . . . . . . . . . . . . 588
IGZCA2D syntax . . . . . . . . . . . 619
Performance-related compiler options . . . . 589
IGZCA2D return codes . . . . . . . . . 620
Evaluating performance . . . . . . . . . 592
Example: IGZCA2D . . . . . . . . . . 621
Running efficiently with CICS, IMS, or VSAM . . 592
DBCS to alphanumeric data conversion (IGZCD2A) 622
CICS . . . . . . . . . . . . . . . 592
IGZCD2A syntax . . . . . . . . . . . 622
IMS . . . . . . . . . . . . . . . 593
IGZCD2A return codes . . . . . . . . . 623
VSAM . . . . . . . . . . . . . . . 593
Example: IGZCD2A . . . . . . . . . . 623

Chapter 35. Simplifying coding . . . . 595 Appendix D. XML reference material 625
Eliminating repetitive coding . . . . . . . . 595
XML PARSE exceptions that allow continuation 625
Example: using the COPY statement . . . . . 596
XML PARSE exceptions that do not allow
Using Language Environment callable services . . 597
continuation . . . . . . . . . . . . . . 628
Sample list of Language Environment callable
XML conformance . . . . . . . . . . . . 631
services . . . . . . . . . . . . . . 598
XML GENERATE exceptions . . . . . . . . 633
Calling Language Environment services . . . 599
Example: Language Environment callable
services . . . . . . . . . . . . . . 600 Appendix E. EXIT compiler option . . 635
Using the user-exit work area . . . . . . . . 636
Calling from exit modules . . . . . . . . . 637
Part 9. Appendixes . . . . . . . . 601 Processing of INEXIT . . . . . . . . . . . 637
Parameter list for INEXIT . . . . . . . . 637
Appendix A. Intermediate results and Processing of LIBEXIT . . . . . . . . . . 638
arithmetic precision . . . . . . . . 603 Processing of LIBEXIT with nested COPY
Terminology used for intermediate results . . . . 604 statements . . . . . . . . . . . . . 639
Example: calculation of intermediate results . . . 605 Parameter list for LIBEXIT . . . . . . . . 640
Fixed-point data and intermediate results . . . . 605 Processing of PRTEXIT . . . . . . . . . . 641
Addition, subtraction, multiplication, and Parameter list for PRTEXIT . . . . . . . . 641
division . . . . . . . . . . . . . . 605 Processing of ADEXIT . . . . . . . . . . 642
Exponentiation . . . . . . . . . . . . 606 Parameter list for ADEXIT . . . . . . . . 643
Example: exponentiation in fixed-point Error handling for exit modules . . . . . . . 644
arithmetic . . . . . . . . . . . . . 607 Using the EXIT compiler option with CICS and
Truncated intermediate results . . . . . . . 608 SQL statements . . . . . . . . . . . . . 644
Binary data and intermediate results . . . . 608 INEXIT . . . . . . . . . . . . . . 644
Intrinsic functions evaluated in fixed-point LIBEXIT . . . . . . . . . . . . . . 644
arithmetic . . . . . . . . . . . . . . 608 PRTEXIT . . . . . . . . . . . . . . 645
Integer functions . . . . . . . . . . . 608 ADEXIT . . . . . . . . . . . . . . 645
Mixed functions . . . . . . . . . . . 609 Example: INEXIT user exit . . . . . . . . . 645
Floating-point data and intermediate results . . . 610
Exponentiations evaluated in floating-point Appendix F. JNI.cpy . . . . . . . . 649
arithmetic . . . . . . . . . . . . . 611
Intrinsic functions evaluated in floating-point Appendix G. COBOL SYSADATA file
arithmetic . . . . . . . . . . . . . 611 contents . . . . . . . . . . . . . 655
Arithmetic expressions in nonarithmetic statements 611
Existing compiler options affecting the SYSADATA
file . . . . . . . . . . . . . . . . . 655
Appendix B. Complex OCCURS SYSADATA record types . . . . . . . . . 656
DEPENDING ON . . . . . . . . . . 613 Example: SYSADATA . . . . . . . . . . 657
Example: complex ODO . . . . . . . . . . 613 SYSADATA record descriptions . . . . . . . 658
How length is calculated . . . . . . . . 614 Common header section . . . . . . . . . . 659
Setting values of ODO objects . . . . . . . 614 Job identification record - X’0000’ . . . . . . . 660
Effects of change in ODO object value . . . . . 614 ADATA identification record - X’0001’ . . . . . 661
Preventing index errors when changing ODO Compilation unit start/end record - X’0002’ . . . 662
object value . . . . . . . . . . . . . 615 Options record - X’0010’ . . . . . . . . . . 662

x Programming Guide
External symbol record - X’0020’ . . . . . . . 672 Preparing to run IGYTCARB . . . . . . . 709
Parse tree record - X’0024’ . . . . . . . . . 673 IGYTSALE: nested program application . . . . 711
Token record - X’0030’ . . . . . . . . . . 687 Input data for IGYTSALE . . . . . . . . 713
Source error record - X’0032’ . . . . . . . . 687 Reports produced by IGYTSALE . . . . . . 715
Source record - X’0038’ . . . . . . . . . . 688 Preparing to run IGYTSALE . . . . . . . 719
COPY REPLACING record - X’0039’ . . . . . . 688 Language elements and concepts that are
Symbol record - X’0042’ . . . . . . . . . . 689 illustrated . . . . . . . . . . . . . . 720
Symbol cross-reference record - X’0044’ . . . . . 700
Nested program record - X’0046’ . . . . . . . 701 Notices . . . . . . . . . . . . . . 725
Library record - X’0060’ . . . . . . . . . . 702 Trademarks . . . . . . . . . . . . . . 726
Statistics record - X’0090’ . . . . . . . . . 703
EVENTS record - X’0120’ . . . . . . . . . 703
Glossary . . . . . . . . . . . . . 727
Appendix H. Sample programs . . . . 705
List of resources . . . . . . . . . . 751
IGYTCARA: batch application . . . . . . . . 705
Enterprise COBOL for z/OS . . . . . . . . 751
Input data for IGYTCARA . . . . . . . . 706
Related publications . . . . . . . . . . . 751
Report produced by IGYTCARA . . . . . . 707
Preparing to run IGYTCARA . . . . . . . 708
IGYTCARB: interactive program . . . . . . . 709 Index . . . . . . . . . . . . . . . 753

Contents xi
xii Programming Guide
Tables
1. FILE-CONTROL entries . . . . . . . . 8 44. Compiler options . . . . . . . . . . 267
2. FILE SECTION entries . . . . . . . . 14 45. Mutually exclusive compiler options 270
3. Assignment to data items in a program 25 46. Values of the LANGUAGE compiler option 288
4. Effect of RMODE and RENT compiler 47. Severity levels of compiler messages 328
options on the RMODE attribute . . . . . 35 48. Using compiler options to get listings 331
5. Ranges in value of COMP-5 data items 41 49. Terms used in MAP output . . . . . . 338
6. Internal representation of numeric items 42 50. Symbols used in LIST and MAP output 338
7. NUMCLS(PRIM) and valid signs . . . . . 46 51. Signature information bytes for compiler
8. NUMCLS(ALT) and valid signs . . . . . 47 options . . . . . . . . . . . . . 344
9. Order of evaluation of arithmetic operators 48 52. Signature information bytes for the DATA
10. Numeric intrinsic functions . . . . . . . 49 DIVISION . . . . . . . . . . . . 345
11. Compatibility of math intrinsic functions and 53. Signature information bytes for the
callable services . . . . . . . . . . . 50 ENVIRONMENT DIVISION . . . . . . 346
12. INTDATE(ANSI) and compatibility of date 54. Signature information bytes for
intrinsic functions and callable services . . . 51 PROCEDURE DIVISION verbs . . . . . 346
13. INTDATE(LILIAN) and compatibility of date 55. Signature information bytes for more
intrinsic functions and callable services . . . 51 PROCEDURE DIVISION items . . . . . 348
14. Hexadecimal values of the euro sign . . . . 56 56. Calls between COBOL and assembler under
15. COBOL statements and national data 103 CICS . . . . . . . . . . . . . . 361
16. Intrinsic functions and national data 104 57. Compiler options required for the integrated
17. Encoding and size of alphanumeric and CICS translator . . . . . . . . . . . 363
national data . . . . . . . . . . . 107 58. Compiler options required for the separate
18. File organization, access mode, and record CICS translator . . . . . . . . . . . 366
format . . . . . . . . . . . . . . 115 59. TRUNC compiler options recommended for
19. QSAM file allocation . . . . . . . . . 134 the separate CICS translator . . . . . . 366
20. Maximum record length of QSAM files 137 60. Compiler options required with the DB2
21. Handling of QSAM user labels . . . . . 142 coprocessor . . . . . . . . . . . . 374
22. Identifiers for standard tape labels . . . . 143 61. Samples with POSIX function calls . . . . 387
23. Comparison of VSAM data set types 149 62. Effects of termination statements. . . . . 394
24. VSAM file organization, access mode, and 63. Methods for passing data in the CALL
record format . . . . . . . . . . . 150 statement . . . . . . . . . . . . . 412
25. Steps for using variable-length RRDS 152 64. Compiler options for DLL applications 426
26. Definition of VSAM fixed-length records 154 65. Binder options for DLL applications 427
27. Definition of VSAM variable-length records 155 66. Special registers used by the XML parser 456
28. I/O statements for VSAM sequential files 156 67. Supported EBCDIC code pages . . . . . 463
29. I/O statements for VSAM relative and 68. Hexadecimal values of special characters for
indexed files . . . . . . . . . . . 156 code page CCSIDs . . . . . . . . . 464
30. Statements to load records into a VSAM file 159 69. Aliases for XML encoding declarations 465
31. Statements to update records in a VSAM 70. Encoding of generated XML output . . . . 480
file . . . . . . . . . . . . . . . 161 71. Structure of class definitions . . . . . . 488
32. Methods for improving VSAM performance 172 72. Structure of instance method definitions 493
33. Methods for checking for sort errors with 73. Structure of COBOL clients . . . . . . 502
NOFASTSRT . . . . . . . . . . . 195 74. Structure of factory definitions . . . . . 515
34. Methods for controlling sort behavior 196 75. Structure of factory method definitions 516
35. Compiler data sets . . . . . . . . . 233 76. JNI services for local and global references 531
36. Block size of fixed-length compiler data sets 235 77. Interoperable data types in COBOL and Java 532
37. Block size of variable-length compiler data 78. Interoperable arrays and strings in COBOL
sets . . . . . . . . . . . . . . . 235 and Java . . . . . . . . . . . . . 532
38. Types of compiler output under z/OS 239 79. Noninteroperable array types in COBOL
39. Severity codes for compiler error messages 247 and Java . . . . . . . . . . . . . 533
40. Input files to the cob2 command . . . . . 254 80. JNI array services . . . . . . . . . . 534
41. Output files from the cob2 command 255 81. Services that convert between jstring
42. Commands for compiling and linking a references and national data . . . . . . 536
class definition . . . . . . . . . . . 258 82. Services that convert between jstring
43. java command options for customizing the references and alphanumeric data . . . . 537
JVM . . . . . . . . . . . . . . 260

© Copyright IBM Corp. 1991, 2004 xiii


83. Advantages and disadvantages of Year 2000 100. ADEXIT processing . . . . . . . . . 642
solutions . . . . . . . . . . . . . 556 101. ADEXIT parameter list . . . . . . . . 643
84. Performance-related compiler options 589 102. SYSADATA record types . . . . . . . 656
85. Performance-tuning worksheet . . . . . 592 103. SYSADATA common header section 659
86. Language Environment callable services 598 104. SYSADATA job identification record 661
87. IGZCA2D return codes . . . . . . . . 620 105. ADATA identification record . . . . . . 662
88. IGZCD2A return codes . . . . . . . . 623 106. SYSADATA compilation unit start/end
89. XML PARSE exceptions that allow record . . . . . . . . . . . . . . 662
continuation . . . . . . . . . . . . 625 107. SYSADATA options record . . . . . . . 662
90. XML PARSE exceptions that do not allow 108. SYSADATA external symbol record 672
continuation . . . . . . . . . . . . 628 109. SYSADATA parse tree record . . . . . . 673
91. XML GENERATE exceptions . . . . . . 633 110. SYSADATA token record . . . . . . . 687
92. INEXIT processing . . . . . . . . . 637 111. SYSADATA source error record . . . . . 687
93. INEXIT parameter list . . . . . . . . 638 112. SYSADATA source record . . . . . . . 688
94. LIBEXIT processing . . . . . . . . . 638 113. SYSADATA COPY REPLACING record 688
95. LIBEXIT processing with nonnested COPY 114. SYSADATA symbol record . . . . . . . 689
statements . . . . . . . . . . . . 639 115. SYSADATA symbol cross-reference record 700
96. LIBEXIT processing with nested COPY 116. SYSADATA nested program record . . . . 701
statements . . . . . . . . . . . . 640 117. SYSADATA library record . . . . . . . 702
97. LIBEXIT parameter list . . . . . . . . 640 118. SYSADATA statistics record . . . . . . 703
98. PRTEXIT processing . . . . . . . . . 641 119. SYSADATA EVENTS record . . . . . . 703
99. PRTEXIT parameter list . . . . . . . . 642

xiv Programming Guide


About this document
Welcome to IBM Enterprise COBOL for z/OS, IBM’s latest host COBOL compiler!

This version of IBM COBOL adds new COBOL function to help integrate COBOL
business processes and Web-oriented business processes by:
v Simplifying the componentization of COBOL programs and enabling
interoperability with Java components
v Promoting the exchange and use of data in standardized formats, including
XML and Unicode

Accessibility
| Accessibility features help a user who has a physical disability, such as restricted
| mobility or limited vision, to use software products successfully. The accessibility
| features in z/OS provide accessibility for Enterprise COBOL.

| The major accessibility features in z/OS enable users to:


| v Use assistive technology products such as screen readers and screen magnifier
| software.
| v Operate specific or equivalent features by using only the keyboard.
| v Customize display attributes such as color, contrast, and font size.

Using assistive technologies


| Assistive technology products work with the user interfaces that are found in
| z/OS. For specific guidance information, consult the documentation for the
| assistive technology product that you use to access z/OS interfaces.

Keyboard navigation of the user interface


| Users can access z/OS user interfaces by using TSO/E or ISPF. For information
| about accessing TSO/E and ISPF interfaces, refer to the following publications:
| v z/OS TSO/E Primer
| v z/OS TSO/E User’s Guide
| v z/OS ISPF User’s Guide Volume I

| These guides describe how to use TSO/E and ISPF, including the use of keyboard
| shortcuts or function keys (PF keys). Each guide includes the default settings for
| the PF keys and explains how to modify their functions.

Accessibility of this document


| The English-language XHTML format of this document that is provided with
| WebSphere Studio Enterprise Developer is accessible to visually impaired
| individuals who use a screen reader.

| To enable your screen reader to accurately read syntax diagrams, source code
| examples, and text that contains the period and comma PICTURE symbols, you
| must set the screen reader to speak all punctuation.

© Copyright IBM Corp. 1991, 2004 xv


How this document will help you
This document will help you write and compile Enterprise COBOL programs. It
will also help you define object-oriented classes and methods, invoke methods, and
refer to objects in your programs.

This document assumes experience in developing application programs and some


knowledge of COBOL. It focuses on using Enterprise COBOL to meet your
programming objectives and not on the definition of the COBOL language. For
complete information on COBOL syntax, see IBM Enterprise COBOL Language
Reference.

For information on migrating programs to Enterprise COBOL, see IBM Enterprise


COBOL Compiler and Run-Time Migration Guide.

IBM z/OS Language Environment provides the run-time environment and


run-time services that are required to run your Enterprise COBOL programs. You
will find information on link-editing and running programs in the IBM z/OS
Language Environment Programming Guide and IBM z/OS Language Environment
Programming Reference.

For a comparison of commonly used Enterprise COBOL and IBM z/OS Language
Environment terms, see “Comparison of commonly used terms” on page xvii.

Abbreviated terms
Certain terms are used in a shortened form in this document. Abbreviations for the
product names used most frequently are listed alphabetically in the following
table:

Term used Long form


CICS CICS Transaction Server
Enterprise COBOL IBM Enterprise COBOL for z/OS
Language Environment IBM z/OS Language Environment
MVS MVS/ESA
UNIX z/OS UNIX System Services

OS/390 Version 2 Release 10 and z/OS Version 1 Release 1 and later are referred to
collectively as “z/OS” throughout this document. The e-server zSeries and the
S/390 hardware are referred to collectively as “zSeries.”

In addition to these abbreviated terms, the term “COBOL 85 Standard” is used to


refer to the combination of the following standards:
v ISO 1989:1985, Programming languages - COBOL
v ISO/IEC 1989/AMD1:1992, Programming languages - COBOL - Intrinsic
function module
v ISO/IEC 1989/AMD2:1994, Programming languages - COBOL - Correction and
clarification amendment for COBOL
v ANSI INCITS 23-1985, Programming Languages - COBOL
v ANSI INCITS 23a-1989, Programming Languages - Intrinsic Function Module for
COBOL

xvi Programming Guide


v ANSI INCITS 23b-1993, Programming Language - Correction Amendment for
COBOL

The ISO standards are identical to the American National standards.

Other terms, if not commonly understood, are shown in italics the first time that
they appear, and are listed in the glossary at the back of this document.

Comparison of commonly used terms


To better understand the terms used throughout the IBM z/OS Language
Environment and IBM Enterprise COBOL for z/OS publications and what terms
are meant to be equivalent, see the following table:

Language Environment term Enterprise COBOL equivalent


Aggregate Group item
Array A table created using the OCCURS clause
Array element Table element
Enclave Run unit
External data WORKING-STORAGE data defined with EXTERNAL clause
Local data Any non-EXTERNAL data item
Pass parameters directly, by value BY VALUE
Pass parameters indirectly, by BY REFERENCE
reference
Pass parameters indirectly, by value BY CONTENT
Routine Program
Scalar Elementary item

How to read syntax diagrams


The following rules apply to syntax diagrams:
v Read the syntax diagrams from left to right, from top to bottom, following the
path of the line.
The >>—- symbol indicates the beginning of a syntax diagram.
The —-> symbol indicates that the syntax diagram is continued on the next line.
The >—- symbol indicates that the syntax diagram is continued from the
previous line.
The —->< symbol indicates the end of a syntax diagram.
Diagrams of syntactical units other than complete statements start with the >—-
symbol and end with the —-> symbol.
v Required items appear on the horizontal line (the main path):

 required_item 

v Optional items appear below the main path:

 required_item 
optional_item

About this document xvii


v If you can choose from two or more items, they appear vertically, in a stack. If
you must choose one of the items, one item of the stack appears on the main
path:

 required_item required_choice1 
required_choice2

If choosing one of the items is optional, the entire stack appears below the main
path:

 required_item 
optional_choice1
optional_choice2

If one of the items is the default, it appears above the main path and the
remaining choices are shown below:

default_choice
 required_item 
optional_choice
optional_choice

v An arrow returning to the left, above the main line, indicates an item that can be
repeated:

 required_item  repeatable_item 

If the repeat arrow contains a comma, you must separate repeated items with a
comma:

 required_item  repeatable_item 

v Keywords appear in uppercase (for example, FROM). They must be spelled exactly
as shown. Variables appear in lowercase italics (for example, column-name). They
represent user-supplied names or values.
v If punctuation marks, parentheses, arithmetic operators, or other such symbols
are shown, you must enter them as part of the syntax.

How examples are shown


This document shows numerous examples of sample COBOL statements, program
fragments, and small programs to illustrate the coding techniques being discussed.
The examples of program code are written in lowercase, uppercase, or mixed case
to demonstrate that you can write your programs in any of these ways.

To more clearly separate some examples from the explanatory text, they are
presented in a monospace font.

COBOL keywords and compiler options that appear in text are generally shown in
SMALL UPPERCASE. Other terms such as program variable names are sometimes
shown in an italic font for clarity.

xviii Programming Guide


Accessing softcopy documentation and support information
IBM Enterprise COBOL for z/OS provides PDF and BookManager versions of the
library on the product site at
www.ibm.com/software/awdtools/cobol/zos/library/.

You can check that Web site for the latest editions of the documents. In the
BookManager version of a document, the content of some tables and syntax
diagrams might be aligned improperly due to variations in the display technology.

Support information is also available on the product site at


www.ibm.com/software/awdtools/cobol/zos/support/.

Summary of changes
This section lists the key changes that have been made to Enterprise COBOL. The
changes that are discussed in this document have an associated cross-reference for
your convenience. The latest technical changes are marked by a revision bar in the
left margin.

Version 3 Release 3 (February 2004)


| v XML support has been enhanced. A new statement, XML GENERATE, converts the
| content of COBOL data records to XML format. XML GENERATE creates XML
| documents encoded in Unicode UTF-16 or in one of several single-byte EBCDIC
| code pages (Chapter 29, “Producing XML output,” on page 471).
| v The XML PARSE statement supports XML files encoded in Unicode UTF-16 or any
| of several single-byte EBCDIC code pages. Support is not provided for ASCII
| code pages.
| v There are new and improved features of Debug Tool:
| – Performance is improved when you use COBOL SYSDEBUG files.
| – You can more easily debug programs that use national data: When you
| display national data in a formatted dump or by using the Debug Tool LIST
| command, the data is automatically converted to EBCDIC representation
| using the code page specified by the CODEPAGE compiler option. You can use
| the Debug Tool MOVE command to assign values to national data items, and
| you can move national data items to or from group data items. You can use
| national data as a comparand in Debug Tool conditional commands such as
| IF and EVALUATE.
| – You can debug mixed COBOL-Java applications, COBOL class definitions, and
| COBOL programs that contain object-oriented syntax.
| For further details about these enhancements to debugging support, see Debug
| Tool User’s Guide.
| v DB2 Version 8 SQL features are supported when you use the integrated DB2
| coprocessor.
| v The syntax for specifying options in the COBJVMINITOPTIONS environment
| variable has changed (“Running OO applications that start with a COBOL
| program” on page 260).

Version 3 Release 2 (September 2002)


v The compiler has been enhanced to support new features of Debug Tool, and
features of Debug Tool Utilities and Advanced Functions:

About this document xix


– Playback support lets you record and replay application execution paths and
data values.
– Automonitor support displays the values of variables that are referenced in
the current statement during debugging.
– Programs that have been compiled with the OPTIMIZE and
TEST(NONE,SYM,. . .) options are supported for debugging (“TEST” on page
306).
– The Debug Tool GOTO command is enabled for programs that have been
compiled with the NOOPTIMIZE option and the TEST option with any of its
suboptions (“TEST” on page 306). (In earlier releases, the GOTO command was
not supported for programs compiled with TEST(NONE,. . .).)
For further details about these enhancements to debugging support, see Debug
Tool User’s Guide.
v Extending Java interoperability to IMS: Object-oriented COBOL programs can
run in an IMS Java dependent region. The object-oriented COBOL and Java
languages can be mixed in a single application (“Using object-oriented COBOL
and Java under IMS” on page 378).
v Enhanced support for Java interoperability:
– The OPTIMIZE compiler option is fully supported for programs that contain
OO syntax for Java interoperability.
– Object references of type jobjectArray are supported for interoperation
between COBOL and Java (“Declaring arrays and strings for Java” on page
532).
– OO applications that begin with a COBOL main factory method can be
invoked with the java command (“Structuring OO applications” on page
524).
– A new environment variable, COBJVMINITOPTIONS, is provided, enabling
the user to specify options that will be used when COBOL initializes a Java
virtual machine (JVM) (“Running OO applications under UNIX” on page
259).
– OO applications that begin with a COBOL program can, with some
limitations, be bound as modules in a PDSE and run using batch JCL
(“Preparing and running OO applications using JCL or TSO/E” on page 262).
v Unicode enhancement for working with DB2: The code pages for host variables
are handled implicitly when you use the DB2 integrated coprocessor. SQL
DECLARE statements are necessary only for variables described with USAGE
DISPLAY or USAGE DISPLAY-1 when COBOL and DB2 code pages do not match
(“Coding SQL statements” on page 371).

Version 3 Release 1 (November 2001)


v Interoperation of COBOL and Java by means of object-oriented syntax,
permitting COBOL programs to instantiate Java classes, invoke methods on Java
objects, and define Java classes that can be instantiated in Java or COBOL and
whose methods can be invoked in Java or COBOL (Chapter 30, “Writing
object-oriented programs,” on page 485)
v Ability to call services provided by the Java Native Interface (JNI) to obtain
additional Java capabilities, with a copybook JNI.cpy and special register
JNIEnvPtr to facilitate access (“Accessing JNI services” on page 527)
v XML support, including a high-speed XML parser that allows programs to
consume inbound XML messages, verify that they are well formed, and
transform their contents into COBOL data structures; with support for XML

xx Programming Guide
documents encoded in Unicode UTF-16 or several single-byte EBCDIC or ASCII
code pages (Chapter 28, “Processing XML input,” on page 447)
v Support for compilation of programs that contain CICS statements, without the
need for a separate translation step (“Integrated CICS translator” on page 364)
– Compiler option CICS, enabling integrated CICS translation and specification
of CICS options (“CICS” on page 273)
v Support for Unicode provided by NATIONAL data type and national (N, NX) literals,
intrinsic functions DISPLAY-OF and NATIONAL-OF for character conversions, and
compiler options NSYMBOL and CODEPAGE (Chapter 7, “Processing character data in
an international environment,” on page 103)
– Compiler option CODEPAGE to specify the code page used for encoding national
literals, and alphanumeric and DBCS data items and literals (“CODEPAGE”
on page 274)
– Compiler option NSYMBOL to control whether national or DBCS processing
should be in effect for literals and data items that use the N symbol
(“NSYMBOL” on page 291)
v Multithreading support: support of POSIX threads and asynchronous signals,
permitting applications with COBOL programs to run on multiple threads
within a process (Chapter 27, “Preparing COBOL programs for multithreading,”
on page 437)
– Compiler option THREAD, enabling programs to run in Language Environment
enclaves with multiple POSIX threads or PL/I subtasks (“THREAD” on page
309)
v VALUE clauses for BINARY data items that permit numeric literals to have a value
of magnitude up to the capacity of the native binary representation, rather than
being limited to the value implied by the number of 9s in the PICTURE clause
(“Formats for numeric data” on page 40)
v A 4-byte FUNCTION-POINTER data item that can contain the address of a COBOL
or non-COBOL entry point, providing easier interoperability with C function
pointers (“Using procedure and function pointers” on page 407)
v The following support is no longer provided (as documented in Enterprise
COBOL Compiler and Run-Time Migration Guide):
– SOM-based object-oriented syntax and services
– Compiler options CMPR2, ANALYZE, FLAGMIG, TYPECHK, and IDLGEN
v Changed default values for the following compiler options: DBCS (“DBCS” on
page 279), FLAG(I,I) (“FLAG” on page 284), RENT (“RENT” on page 299), and
XREF(FULL) (“XREF” on page 314)

For a history of changes to previous COBOL compilers, see Enterprise COBOL


Compiler and Run-Time Migration Guide.

How to send your comments


Your feedback is important in helping us to provide accurate, high-quality
information. If you have comments about this document or any other Enterprise
COBOL documentation, contact us in one of these ways:
v Fill out the Readers’ Comment Form at the back of this document, and return it
by mail or give it to an IBM representative. If the form has been removed,
address your comments to:
IBM Corporation
H150/090

About this document xxi


555 Bailey Avenue
San Jose, CA 95141-1003
USA
v Fax your comments to this U.S. number: (800)426-7773.
v Use the Online Readers’ Comment Form at
www.ibm.com/software/awdtools/rcf/.

Be sure to include the name of the document, the publication number of the
document, the version of Enterprise COBOL, and, if applicable, the specific
location (for example, page number) of the text that you are commenting on.

When you send information to IBM, you grant IBM a nonexclusive right to use or
distribute the information in any way it believes appropriate without incurring any
obligation to you.

xxii Programming Guide


Part 1. Coding your program
Chapter 1. Structuring your program . . . . . 5 Types of intrinsic functions . . . . . . . . 33
Identifying a program . . . . . . . . . . . 5 Nesting functions . . . . . . . . . . . 33
Identifying a program as recursive . . . . . . 6 Using tables (arrays) and pointers . . . . . . . 33
Marking a program as callable by containing Storage and its addressability . . . . . . . . 34
programs . . . . . . . . . . . . . . 6 Settings for RMODE . . . . . . . . . . . 35
Setting a program to an initial state . . . . . . 6 Storage restrictions for passing data . . . . . 35
Changing the header of a source listing . . . . 7 Location of data areas . . . . . . . . . . 35
Describing the computing environment . . . . . 7 Storage for LOCAL-STORAGE data . . . . . 35
Example: FILE-CONTROL entries . . . . . . 8 Storage for external data . . . . . . . . . 35
Specifying the collating sequence . . . . . . 8 Storage for QSAM input-output buffers . . . . 36
Example: specifying the collating sequence . . 9
Defining symbolic characters . . . . . . . 10 Chapter 3. Working with numbers and arithmetic 37
Defining a user-defined class . . . . . . . 10 Defining numeric data . . . . . . . . . . . 37
Defining files to the operating system . . . . 10 Displaying numeric data . . . . . . . . . . 38
Varying the input or output file at run time . 11 Controlling how numeric data is stored . . . . . 39
Optimizing buffer and device space . . . . 12 Formats for numeric data . . . . . . . . . . 40
Describing the data . . . . . . . . . . . . 12 External decimal (DISPLAY) items . . . . . . 40
Using data in input and output operations . . . 13 External floating-point (DISPLAY) items . . . . 40
FILE SECTION entries . . . . . . . . . 14 Binary (COMP) items . . . . . . . . . . 41
Comparison of WORKING-STORAGE and Native binary (COMP-5) items . . . . . . . 41
LOCAL-STORAGE . . . . . . . . . . . 15 Packed-decimal (COMP-3) items . . . . . . 42
Example: storage sections . . . . . . . . 15 Floating-point (COMP-1 and COMP-2) items . . 42
Using data from another program . . . . . . 17 Examples: numeric data and internal
Sharing data in separately compiled programs 17 representation . . . . . . . . . . . . 42
Sharing data in nested programs . . . . . 17 Data format conversions . . . . . . . . . . 43
Sharing data in recursive or multithreaded Conversions and precision . . . . . . . . 44
programs . . . . . . . . . . . . . 17 Conversions that preserve precision . . . . 44
Processing the data . . . . . . . . . . . . 18 Conversions that result in rounding . . . . 44
How logic is divided in the PROCEDURE Sign representation and processing . . . . . . 45
DIVISION . . . . . . . . . . . . . . 18 NUMPROC(PFD) . . . . . . . . . . . 45
Imperative statements . . . . . . . . . 19 NUMPROC(NOPFD) . . . . . . . . . . 45
Conditional statements . . . . . . . . 19 NUMPROC(MIG) . . . . . . . . . . . 46
Compiler-directing statements . . . . . . 20 Checking for incompatible data (numeric class test) 46
Scope terminators . . . . . . . . . . 21 Performing arithmetic . . . . . . . . . . . 47
Declaratives . . . . . . . . . . . . . 22 COMPUTE and other arithmetic statements . . 47
Arithmetic expressions . . . . . . . . . 48
Chapter 2. Using data . . . . . . . . . . 23 Numeric intrinsic functions . . . . . . . . 48
Using variables, structures, literals, and constants . 23 Nesting functions and arithmetic expressions 49
Variables . . . . . . . . . . . . . . 23 ALL subscripting and special registers . . . 49
Data structure: data items and group items . . . 23 Math and date Language Environment services 49
Literals . . . . . . . . . . . . . . . 24 Math-oriented callable services . . . . . . 50
Constants . . . . . . . . . . . . . . 24 Date callable services . . . . . . . . . 51
Figurative constants . . . . . . . . . . 25 Examples: numeric intrinsic functions . . . . 51
Assigning values to data items . . . . . . . . 25 General number handling . . . . . . . 51
Examples: initializing data items . . . . . . 26 Date and time . . . . . . . . . . . 52
Initializing a structure (INITIALIZE) . . . . . 27 Finance . . . . . . . . . . . . . . 52
Assigning values to elementary or group data Mathematics . . . . . . . . . . . . 53
items (MOVE) . . . . . . . . . . . . 27 Statistics . . . . . . . . . . . . . 53
Assigning arithmetic results (MOVE or Fixed-point versus floating-point arithmetic . . . 53
COMPUTE) . . . . . . . . . . . . . 28 Floating-point evaluations . . . . . . . . 54
Assigning input from a screen or file (ACCEPT) 29 Fixed-point evaluations . . . . . . . . . 54
Displaying values on a screen or in a file (DISPLAY) 30 Arithmetic comparisons (relation conditions) . . 54
Displaying data on the system logical output Examples: fixed-point and floating-point
device . . . . . . . . . . . . . . . 31 evaluations . . . . . . . . . . . . . 55
Using WITH NO ADVANCING . . . . . . 31 Using currency signs . . . . . . . . . . . 55
Using intrinsic functions (built-in functions) . . . 32 Example: multiple currency signs . . . . . . 56

© Copyright IBM Corp. 1991, 2004 1


Chapter 4. Handling tables. . . . . . . . . 59 Example: arithmetic expressions as reference
Defining a table (OCCURS) . . . . . . . . . 59 modifiers . . . . . . . . . . . . . . 94
Nesting tables . . . . . . . . . . . . . 60 Example: intrinsic functions as reference
Subscripting . . . . . . . . . . . . . 60 modifiers . . . . . . . . . . . . . . 95
Indexing . . . . . . . . . . . . . . 61 Tallying and replacing data items (INSPECT) . . . 95
Referring to an item in a table . . . . . . . . 61 Examples: INSPECT statement . . . . . . . 96
Subscripting . . . . . . . . . . . . . 62 Converting data items (intrinsic functions) . . . . 97
Indexing . . . . . . . . . . . . . . 63 Converting to uppercase or lowercase
Putting values into a table . . . . . . . . . 64 (UPPER-CASE, LOWER-CASE) . . . . . . . 97
Loading a table dynamically . . . . . . . . 64 Converting to reverse order (REVERSE) . . . . 97
Initializing a table (INITIALIZE) . . . . . . 64 Converting to numbers (NUMVAL, NUMVAL-C) 97
Assigning values when you define a table Converting from one code page to another . . . 98
(VALUE) . . . . . . . . . . . . . . 65 Evaluating data items (intrinsic functions) . . . . 99
Initializing each table item individually . . . 65 Evaluating single characters for collating
Initializing a table at the 01 level . . . . . 65 sequence . . . . . . . . . . . . . . 99
Initializing all occurrences of a table element 65 Finding the largest or smallest data item . . . 99
Example: PERFORM and subscripting . . . . 66 MAX and MIN . . . . . . . . . . . 100
Example: PERFORM and indexing. . . . . . 67 ORD-MAX and ORD-MIN . . . . . . . 100
Creating variable-length tables (DEPENDING ON) 68 Returning variable-length results with
Loading a variable-length table . . . . . . . 69 alphanumeric functions . . . . . . . . 100
Assigning values to a variable-length table . . . 70 Finding the length of data items . . . . . . 101
Searching a table . . . . . . . . . . . . 71 Finding the date of compilation . . . . . . 102
Doing a serial search (SEARCH) . . . . . . 71
Example: serial search . . . . . . . . . 71 Chapter 7. Processing character data in an
Doing a binary search (SEARCH ALL) . . . . 72 international environment . . . . . . . . 103
Example: binary search . . . . . . . . 72 Unicode and encoding of language characters . . 105
Processing table items using intrinsic functions . . 73 Using national data (Unicode) in COBOL . . . . 106
Example: intrinsic functions . . . . . . . . 73 National data items . . . . . . . . . . 106
National literals . . . . . . . . . . . 106
Chapter 5. Selecting and repeating program National characters as figurative constants . . 106
actions . . . . . . . . . . . . . . . 75 Storage of national data . . . . . . . . . 107
Selecting program actions . . . . . . . . . 75 Converting national data . . . . . . . . . 107
Coding a choice of actions . . . . . . . . 75 Converting alphanumeric and integer to
Using nested IF statements . . . . . . . 76 national data (MOVE) . . . . . . . . . 107
Using the EVALUATE statement . . . . . 77 Converting alphanumeric to national data
Coding conditional expressions . . . . . . . 79 (NATIONAL-OF) . . . . . . . . . . . 108
Switches and flags . . . . . . . . . . 80 Converting national to alphanumeric data
Defining switches and flags . . . . . . . 80 (DISPLAY-OF) . . . . . . . . . . . . 108
Example: switches . . . . . . . . . . 81 Overriding the default code page . . . . . 108
Example: flags . . . . . . . . . . . 81 Conversion exceptions . . . . . . . . . 108
Resetting switches and flags . . . . . . . 81 Example: converting national data . . . . . 109
Example: set switch on . . . . . . . . 82 Processing UTF-8 data . . . . . . . . . . 109
Example: set switch off . . . . . . . . 82 Processing Chinese GB 18030 data . . . . . . 110
Repeating program actions . . . . . . . . . 83 Comparing national data items . . . . . . . 111
Choosing inline or out-of-line PERFORM . . . 83 Comparing national operands . . . . . . . 111
Example: inline PERFORM statement . . . . 84 Comparing national and numeric operands . . 111
Coding a loop . . . . . . . . . . . . 84 Comparing national and alphabetic or
Coding a loop through a table . . . . . . . 85 alphanumeric operands . . . . . . . . . 111
Executing multiple paragraphs or sections . . . 85 Comparing national and group operands . . . 111
Processing alphanumeric data items that contain
Chapter 6. Handling strings . . . . . . . . 87 DBCS data . . . . . . . . . . . . . . 112
Joining data items (STRING) . . . . . . . . 87
Example: STRING statement . . . . . . . . 88 Chapter 8. Processing files . . . . . . . . 113
STRING program results . . . . . . . . 88 File organization and input-output devices . . . 113
Splitting data items (UNSTRING) . . . . . . . 89 Choosing file organization and access mode . . . 115
Example: UNSTRING statement . . . . . . 89 Format for coding input and output . . . . . 116
UNSTRING program results . . . . . . . 91 Allocating files . . . . . . . . . . . . . 117
Manipulating null-terminated strings . . . . . . 91 Checking for input or output errors . . . . . . 118
Example: null-terminated strings . . . . . . 92
Referring to substrings of data items . . . . . . 93 Chapter 9. Processing QSAM files . . . . . 119
Reference modifiers. . . . . . . . . . . 94 Defining QSAM files and records in COBOL . . . 119

2 Programming Guide
Establishing record formats . . . . . . . . 120 Specifying relative organization for VSAM files 151
Logical records . . . . . . . . . . . 120 Fixed-length and variable-length RRDS . . . 152
Requesting fixed-length format . . . . . 121 Simulating variable-length RRDS . . . . . 152
Requesting variable-length format . . . . 122 Specifying access modes for VSAM files . . . 153
Requesting spanned format. . . . . . . 124 Example: using dynamic access with VSAM
Requesting undefined format . . . . . . 126 files . . . . . . . . . . . . . . 154
Setting block sizes . . . . . . . . . . . 127 Defining record lengths for VSAM files . . . . 154
Letting z/OS determine block size . . . . 127 Defining fixed-length records . . . . . . 154
Setting block size explicitly . . . . . . . 127 Defining variable-length records . . . . . 155
Taking advantage of LBI. . . . . . . . 128 Coding input and output statements for VSAM
Block size and the DCB RECFM files . . . . . . . . . . . . . . . . 155
subparameter . . . . . . . . . . . 129 File position indicator . . . . . . . . . 157
Coding input and output statements for QSAM Opening a file (ESDS, KSDS, or RRDS) . . . . 158
files . . . . . . . . . . . . . . . . 129 Opening an empty file . . . . . . . . 158
Opening QSAM files . . . . . . . . . . 130 Statements to load records into a VSAM file 159
Dynamically creating QSAM files with Opening a loaded file (a file with records) 160
CBLQDA . . . . . . . . . . . . . . 130 Reading records from a VSAM file . . . . . 160
Adding records to QSAM files. . . . . . . 131 Updating records in a VSAM file . . . . . . 161
Updating QSAM files . . . . . . . . . 131 Adding records to a VSAM file . . . . . . 162
Writing QSAM files to a printer or spooled data Adding records sequentially . . . . . . 162
set . . . . . . . . . . . . . . . . 131 Adding records randomly or dynamically 162
Controlling the page size . . . . . . . 132 Replacing records in a VSAM file. . . . . . 162
Controlling the vertical positioning of records 132 Deleting records from a VSAM file . . . . . 163
Closing QSAM files . . . . . . . . . . 132 Closing VSAM files . . . . . . . . . . 163
Handling errors in QSAM files . . . . . . . 133 Handling errors in VSAM files . . . . . . . 164
Working with QSAM files . . . . . . . . . 133 Protecting VSAM files with a password . . . . 164
Defining and allocating QSAM files . . . . . 134 Example: password protection for a VSAM
Parameters for creating QSAM files . . . . 135 indexed file . . . . . . . . . . . . . 165
Retrieving QSAM files . . . . . . . . . 136 Working with VSAM data sets under z/OS and
Parameters for retrieving QSAM files . . . 136 UNIX . . . . . . . . . . . . . . . . 165
Ensuring file attributes match your program 137 Defining VSAM files . . . . . . . . . . 166
Processing existing files . . . . . . . . 137 Creating alternate indexes . . . . . . . . 167
Defining variable-length (format-V) records 138 Example: entries for alternate indexes . . . 168
Defining format-U records . . . . . . . 138 Allocating VSAM files . . . . . . . . . 169
Defining fixed-length records . . . . . . 138 Sharing VSAM files through RLS . . . . . . 170
Processing new files . . . . . . . . . 138 Preventing update problems with VSAM files
Processing files dynamically created by in RLS mode . . . . . . . . . . . 170
COBOL . . . . . . . . . . . . . 139 Restrictions when using RLS . . . . . . 171
Using striped extended-format QSAM data sets 139 Handling errors in VSAM files in RLS mode 171
Allocation of buffers for QSAM files . . . . 140 Improving VSAM performance . . . . . . . 171
Accessing HFS files using QSAM . . . . . . . 140
Labels for QSAM files . . . . . . . . . . 141 Chapter 11. Processing line-sequential files . . 175
Using trailer and header labels . . . . . . 141 Defining line-sequential files and records in
Getting a user-label track . . . . . . . 142 COBOL . . . . . . . . . . . . . . . 175
Handling user labels . . . . . . . . . 142 Allowable control characters . . . . . . . 176
Format of standard labels . . . . . . . . 143 Describing the structure of a line-sequential file 176
Standard user labels . . . . . . . . . 143 Defining and allocating line-sequential files . . . 177
Processing QSAM ASCII files on tape . . . . . 144 Coding input-output statements for line-sequential
Requesting the ASCII alphabet . . . . . . 144 files . . . . . . . . . . . . . . . . 177
Defining the record formats . . . . . . . 144 Opening line-sequential files . . . . . . . 178
Defining the ddname . . . . . . . . . . 144 Reading records from line-sequential files . . . 178
Processing ASCII file labels . . . . . . . . . 145 Adding records to line-sequential files . . . . 179
Closing line-sequential files. . . . . . . . 179
Chapter 10. Processing VSAM files . . . . . 147 Handling errors in line-sequential files . . . . . 180
VSAM files . . . . . . . . . . . . . . 148
Defining VSAM file organization and records . . 149 Chapter 12. Sorting and merging files . . . . 181
Specifying sequential organization for VSAM Sort and merge process . . . . . . . . . . 182
files . . . . . . . . . . . . . . . 150 Describing the sort or merge file . . . . . . . 182
Specifying indexed organization for VSAM files 150 Describing the input to sorting or merging . . . 183
Alternate keys . . . . . . . . . . . 151 Example: describing sort and input files for
Alternate index . . . . . . . . . . . 151 SORT . . . . . . . . . . . . . . . 183

Part 1. Coding your program 3


Coding the input procedure . . . . . . . . 184
Describing the output from sorting or merging . . 185
Coding the output procedure . . . . . . . . 185
Coding considerations when using DFSORT . . 186
Example: coding the output procedure when
using DFSORT . . . . . . . . . . . . 186
Restrictions on input and output procedures . . . 187
Defining sort and merge data sets . . . . . . 187
Sorting variable-length records . . . . . . . 188
Requesting the sort or merge . . . . . . . . 188
Setting sort or merge criteria . . . . . . . 189
Example: sorting with input and output
procedures . . . . . . . . . . . . . 190
Choosing alternate collating sequences . . . . 190
Sorting on windowed date fields . . . . . . 191
Preserving the original sequence of records with
equal keys . . . . . . . . . . . . . 191
Determining whether the sort or merge was
successful . . . . . . . . . . . . . . 192
Stopping a sort or merge operation prematurely 192
Improving sort performance with FASTSRT . . . 193
FASTSRT requirements for JCL . . . . . . 193
FASTSRT requirements for sort input and
output files . . . . . . . . . . . . . 193
QSAM requirements . . . . . . . . . 194
VSAM requirements . . . . . . . . . 195
Checking for sort errors with NOFASTSRT . . . 195
Controlling sort behavior . . . . . . . . . 195
Sort special registers . . . . . . . . . . 196
Changing DFSORT defaults with control
statements . . . . . . . . . . . . . 197
Default characteristics of the IGZSRTCD data
set . . . . . . . . . . . . . . . 197
Allocating storage for sort or merge operations 197
Allocating space for sort files . . . . . . . 198
Using checkpoint/restart with DFSORT . . . . 198
Sorting under CICS . . . . . . . . . . . 199
CICS SORT application restrictions . . . . . 199

Chapter 13. Handling errors . . . . . . . . 201


Requesting dumps . . . . . . . . . . . 201
Creating a formatted dump. . . . . . . . 201
Creating a system dump . . . . . . . . 202
Handling errors in joining and splitting strings . . 202
Handling errors in arithmetic operations . . . . 203
Example: checking for division by zero . . . . 203
Handling errors in input and output operations 203
Using the end-of-file condition (AT END) . . . 206
Coding ERROR declaratives . . . . . . . 207
Using file status keys . . . . . . . . . . 208
Example: file status key . . . . . . . . . 209
Using VSAM return codes (VSAM files only) 209
Example: checking VSAM status codes . . . . 210
Coding INVALID KEY phrases . . . . . . 212
INVALID KEY and ERROR declaratives . . 212
NOT INVALID KEY . . . . . . . . . 212
Example: FILE STATUS and INVALID KEY . . 212
Handling errors when calling programs . . . . 213
Writing routines for handling errors . . . . . . 213

4 Programming Guide
Chapter 1. Structuring your program
A COBOL program consists of four divisions, each with a specific logical function:
v IDENTIFICATION DIVISION
v ENVIRONMENT DIVISION
v DATA DIVISION
v PROCEDURE DIVISION

Only the IDENTIFICATION DIVISION is required.

To define a COBOL class or method, you need to define some divisions differently
than you do for a program.

RELATED TASKS
“Identifying a program”
“Describing the computing environment” on page 7
“Describing the data” on page 12
“Processing the data” on page 18
“Defining a class” on page 488
“Defining a class instance method” on page 493
“Structuring OO applications” on page 524

Identifying a program
Use the IDENTIFICATION DIVISION to name your program and, if you want, give
other identifying information.

You can use the optional AUTHOR, INSTALLATION, DATE-WRITTEN, and DATE-COMPILED
paragraphs for descriptive information about your program. The data you enter on
the DATE-COMPILED paragraph is replaced with the latest compilation date.
IDENTIFICATION DIVISION.
Program-ID. Helloprog.
Author. A. Programmer.
Installation. Computing Laboratories.
Date-Written. 08/21/2003.
Date-Compiled. 02/27/2004.

Use the PROGRAM-ID paragraph to name your program. The program name that you
assign is used in these ways:
v Other programs use the name to call your program.
v The name appears in the header on each page, except the first page, of the
program listing generated when the program is compiled.
v If you use the NAME compiler option, the name is placed on the NAME
linkage-editor or binder control statement to identify the object module created
by the compilation.
Tip: Do not use program names that start with prefixes used by IBM products. If
you try to use programs whose names start with any of the following, your CALL
statements might resolve to IBM library or compiler routines rather than to your
intended program:

AFB AFH CBC CEE EDC

© Copyright IBM Corp. 1991, 2004 5


IBM IFY IGY IGZ ILB

Tip: When the program name is case sensitive, avoid mismatches with the name
the compiler is looking for. Verify that the appropriate setting of the PGMNAME
compiler option is used.

RELATED TASKS
“Changing the header of a source listing” on page 7
“Identifying a program as recursive”
“Marking a program as callable by containing programs”
“Setting a program to an initial state”

RELATED REFERENCES
Compiler limits (Enterprise COBOL Language Reference)
Conventions for program names (Enterprise COBOL Language Reference)

Identifying a program as recursive


Code the RECURSIVE attribute on the PROGRAM-ID clause to specify that your
program can be recursively reentered while a previous invocation is still active.

You can code RECURSIVE only on the outermost program of a compilation unit.
Neither nested subprograms nor programs that contain nested subprograms can be
recursive. You must code RECURSIVE for programs that you compile with the THREAD
option.

RELATED TASKS
“Sharing data in recursive or multithreaded programs” on page 17
“Making recursive calls” on page 407

Marking a program as callable by containing programs


Use the COMMON attribute on the PROGRAM-ID clause to specify that your program can
be called by the containing program or by any program in the containing program.
The COMMON program cannot be called by any program contained in itself.

Only contained programs can have the COMMON attribute.

RELATED CONCEPTS
“Nested programs” on page 404

Setting a program to an initial state


Use the INITIAL attribute to specify that whenever a program is called, it is placed
in its initial state. If the program contains programs, these are also placed in their
initial states.

A program is in its initial state when the following has occurred:


v Data items having VALUE clauses are set to the specified value.
v Changed GO TO statements and PERFORM statements are set to their initial states.
v Non-EXTERNAL files are closed.

6 Programming Guide
Changing the header of a source listing
The header on the first page of your source statement listing contains the
identification of the compiler and the current release level, plus the date and time
of compilation and the page number. For example:

PP 5655-G53 IBM Enterprise COBOL for z/OS 3.3.0 Date 02/27/2004 Time 15:05:19 Page 1

You can customize the header on succeeding pages of the listing with the
compiler-directing TITLE statement.

RELATED REFERENCES
TITLE statement (Enterprise COBOL Language Reference)

Describing the computing environment


In the ENVIRONMENT DIVISION you describe the aspects of your program that
depend on the computing environment.

Use the CONFIGURATION SECTION to specify the following items:


v Computer for compiling your program (in the SOURCE-COMPUTER paragraph)
v Computer for running your program (in the OBJECT-COMPUTER paragraph)
v Special items such as the currency sign and symbolic characters (in the
SPECIAL-NAMES paragraph)
v User-defined classes (in the REPOSITORY paragraph)

Use the FILE-CONTROL and I-O-CONTROL paragraphs of the INPUT-OUTPUT SECTION to


do the following:
v Identify and describe the characteristics of your program files.
v Associate your files with the external QSAM, VSAM, or HFS (hierarchical file
system) data sets where they physically reside.
The terms file, in COBOL terminology, and data set or HFS file, in operating
system terminology, have essentially the same meaning and are used
interchangeably in this documentation.
For Customer Information Control System (CICS) and online Information
Management System (IMS) message processing programs (MPP), code only the
ENVIRONMENT DIVISION header and, optionally, the CONFIGURATION SECTION. CICS
does not allow COBOL definition of files. IMS allows COBOL definition of files
only for batch programs.
v Provide information to control efficient transmission of the data records between
your program and the external medium.

“Example: FILE-CONTROL entries” on page 8

RELATED TASKS
“Specifying the collating sequence” on page 8
“Defining symbolic characters” on page 10
“Defining a user-defined class” on page 10
“Defining files to the operating system” on page 10

RELATED REFERENCES
Sections and paragraphs (Enterprise COBOL Language Reference)

Chapter 1. Structuring your program 7


Example: FILE-CONTROL entries
The following table shows FILE-CONTROL entries for a QSAM sequential file, a
VSAM indexed file, and a line-sequential file.
Table 1. FILE-CONTROL entries
QSAM file VSAM file Line-sequential file
1 1
SELECT PRINTFILE SELECT COMMUTER-FILE SELECT PRINTFILE1
ASSIGN TO UPDPRINT2 ASSIGN TO COMMUTER2 ASSIGN TO UPDPRINT2
ORGANIZATION IS SEQUENTIAL3 ORGANIZATION IS INDEXED3 ORGANIZATION IS LINE SEQUENTIAL3
ACCESS IS SEQUENTIAL.4 ACCESS IS RANDOM4 ACCESS IS SEQUENTIAL.4
RECORD KEY IS COMMUTER-KEY5
FILE STATUS IS5
COMMUTER-FILE-STATUS
COMMUTER-VSAM-STATUS.

1. The SELECT clause chooses a file in the COBOL program to be associated with an external data set.
2. The ASSIGN clause associates the program’s name for the file with the external name for the actual data file. You
can define the external name with a DD statement or an environment variable.
3. The ORGANIZATION clause describes the file’s organization. For QSAM files, the ORGANIZATION clause is optional.
4. The ACCESS MODE clause defines the manner in which the records are made available for processing: sequential,
random, or dynamic. For QSAM and line-sequential files, the ACCESS MODE clause is optional. These files always
have sequential organization.
5. For VSAM files, you might have additional statements in the FILE-CONTROL paragraph depending on the type of
VSAM file you use.

RELATED TASKS
Chapter 9, “Processing QSAM files,” on page 119
Chapter 10, “Processing VSAM files,” on page 147
Chapter 11, “Processing line-sequential files,” on page 175
“Describing the computing environment” on page 7

Specifying the collating sequence


You can use the PROGRAM COLLATING SEQUENCE clause and the ALPHABET clause of the
SPECIAL-NAMES paragraph to establish the collating sequence used in the following
operations on alphanumeric items:
v Nonnumeric comparisons explicitly specified in relation conditions and
condition-name conditions
v HIGH-VALUE and LOW-VALUE settings
v SEARCH ALL
v SORT and MERGE unless overridden by a COLLATING SEQUENCE phrase on the SORT
or MERGE statement

“Example: specifying the collating sequence” on page 9

The sequence that you use can be based on one of these alphabets:
v EBCDIC: references the collating sequence associated with the EBCDIC character
set
v NATIVE: references the same collating sequence as EBCDIC
v STANDARD-1: references the collating sequence associated with the ASCII
character set defined by ANSI INCITS X3.4, Coded Character Sets - 7-bit American
National Standard Code for Information Interchange (7-bit ASCII)

8 Programming Guide
v STANDARD-2: references the collating sequence associated with the character set
defined by ISO/IEC 646 — Information technology — ISO 7-bit coded character set
for information interchange, International Reference Version
v An alteration of the EBCDIC sequence that you define in the SPECIAL-NAMES
paragraph

The PROGRAM COLLATING SEQUENCE clause does not affect comparisons that involve
national operands.

RELATED TASKS
“Choosing alternate collating sequences” on page 190
“Comparing national data items” on page 111

Example: specifying the collating sequence


The following example shows the ENVIRONMENT DIVISION coding used to specify a
collating sequence where uppercase and lowercase letters are similarly handled for
comparisons and for sorting or merging. When you change the EBCDIC sequence
in the SPECIAL-NAMES paragraph, the overall collating sequence is affected, not just
the collating sequence of the characters included in the SPECIAL-NAMES paragraph.
IDENTIFICATION DIVISION.
. . .
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.

Source-Computer. IBM-390.
Object-Computer. IBM-390.

Program Collating Sequence Special-Sequence.


Special-Names.
Alphabet Special-Sequence Is
“A” Also “a”
“B” Also “b”
“C” Also “c”
“D” Also “d”
“E” Also “e”
“F” Also “f”
“G” Also “g”
“H” Also “h”
“I” Also “i”
“J” Also “j”
“K” Also “k”
“L” Also “l”
“M” Also “m”
“N” Also “n”
“O” Also “o”
“P” Also “p”
“Q” Also “q”
“R” Also “r”
“S” Also “s”
“T” Also “t”
“U” Also “u”
“V” Also “v”
“W” Also “w”
“X” Also “x”
“Y” Also “y”
“Z” Also “z”.

RELATED TASKS
“Specifying the collating sequence” on page 8

Chapter 1. Structuring your program 9


Defining symbolic characters
Use the SYMBOLIC CHARACTERS clause to give symbolic names to any character of the
specified alphabet. Use ordinal position to identify the character. Position 1
corresponds to character X’00’.

For example, to give a name to the backspace character (X’16’ in the EBCDIC
alphabet), code:
SYMBOLIC CHARACTERS BACKSPACE IS 23

Defining a user-defined class


Use the CLASS clause to give a name to a set of characters listed in the clause. For
example, name the set of digits by using this code:
CLASS DIGIT IS “0” THROUGH “9”

The class-name can be referenced only in a class condition. This user-defined class
is not the same as an object-oriented class.

Defining files to the operating system


For all files that you process in your COBOL program, you need to define the files
to the operating system with an appropriate system data definition:
v DD statement for z/OS JCL.
v ALLOCATE command under TSO.
v Environment variable for z/OS or UNIX. The contents can define either an MVS
data set or a file in the HFS (hierarchical file system).

The following shows the relationship of a FILE-CONTROL entry to the system data
definition and to the FD entry in the FILE SECTION.
v JCL DD statement:
(1)
//OUTFILE DD DSNAME=MY.OUT171,UNIT=SYSDA,SPACE=(TRK,(50,5)),
// DCB=(BLKSIZE=400)
/*
. . .
v Environment variable (export command):
(1)
export OUTFILE=DSNAME(MY.OUT171),UNIT(SYSDA),SPACE(TRK,(50,5))
. . .
v COBOL code:
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CARPOOL
ASSIGN TO OUTFILE (1)
ORGANIZATION IS SEQUENTIAL.
. . .
DATA DIVISION.
FILE SECTION.
FD CARPOOL (2)
LABEL RECORD STANDARD
BLOCK CONTAINS 0 CHARACTERS
RECORD CONTAINS 80 CHARACTERS
(1) The ddname in the DD statement or the environment variable name in the
export command, corresponds to the assignment-name in the ASSIGN clause:
v //OUTFILE DD DSNAME=OUT171 . . ., or

10 Programming Guide
v export OUTFILE= . . .

This assignment-name points to the ddname OUTFILE in the DD statement or


the environment variable name OUTFILE in the export command:
ASSIGN TO OUTFILE
(2) When you specify a file in a COBOL FILE-CONTROL entry, you must
describe the file in an FD entry for file-name.
SELECT CARPOOL
. . .
FD CARPOOL

RELATED TASKS
“Optimizing buffer and device space” on page 12

Varying the input or output file at run time


The file-name you code in your SELECT clause is used as a constant throughout your
COBOL program, but you can associate the name of the file on the DD statement or
export command with a different file at run time.

Changing a file-name in your COBOL program requires changing the input


statements and output statements and recompiling the program. Alternatively, you
can change the dsname in the DD statement or the dsname path-name in your export
command.

Rules for using different files: The name you use in the assignment-name of the
ASSIGN clause must be the same as the ddname in the DD statement or the
environment variable in the export command. You can change the actual file by
using the DSNAME in the DD statement or the DSNAME or path name in the
environment variable.

The file-name that you use with the SELECT clause (such as SELECT MASTER) must be
the same as in the FD file-name entry.

Two files should not use the same ddname or environment variable name in their
SELECT clauses; otherwise, results could be unpredictable. For example, if DISPLAY
is directed to SYSOUT, do not use SYSOUT as the ddname or environment variable
name on the SELECT clause for a file.

“Example: using different input files”

Example: using different input files: Consider a COBOL program that is used in
exactly the same way for several different master files. It contains this SELECT
clause:
SELECT MASTER
ASSIGN TO DA-3330-S-MASTERA

Assume the three possible input files are MASTER1, MASTER2, and MASTER3. You must
code one of the following DD statements in the job step that calls for program
execution, or issue one of the following export commands from the same shell
from which you run the program, prior to running the program:
//MASTERA DD DSNAME=MY.MASTER1,. . .
export MASTERA=DSN(MY.MASTER1),. . .

//MASTERA DD DSNAME=MY.MASTER2,. . .

Chapter 1. Structuring your program 11


export MASTERA=DSN(MY.MASTER2),. . .

//MASTERA DD DSNAME=MY.MASTER3,. . .
export MASTERA=DSN(MY.MASTER3),. . .

Any reference in the program to MASTERA will therefore be a reference to the file
currently assigned to ddname or environment variable name MASTERA.

Notice that in this example, you cannot use the PATH(path) form of the export
command to reference a line-sequential file in the HFS, because you cannot specify
an organization field (S- or AS-) with a line-sequential file.

Optimizing buffer and device space


Use the APPLY WRITE-ONLY clause to make optimum use of buffer and device space
when creating a sequential file with blocked variable-length records. With APPLY
WRITE-ONLY specified, a buffer is truncated only when the next record does not fit
in the unused portion of the buffer. Without APPLY WRITE-ONLY specified, a buffer is
truncated when it does not have enough space for a maximum-size record.

The APPLY WRITE-ONLY clause has meaning only for sequential files that have
variable-length records and are blocked.

The AWO compiler option applies an implicit APPLY WRITE-ONLY clause to all eligible
files. The NOAWO compiler option has no effect on files that have the APPLY
WRITE-ONLY clause specified. The APPLY WRITE-ONLY clause takes precedence over
the NOAWO compiler option.

The APPLY-WRITE ONLY clause can cause input files to use a record area rather than
process the data in the buffer. This use might affect the processing of both input
files and output files.

RELATED REFERENCES
“AWO” on page 272

Describing the data


Define the characteristics of your data and group your data definitions into one of
the sections in the DATA DIVISION:
v Define data used in input-output operations (FILE SECTION).
v Define data developed for internal processing:
– To have storage be statically allocated and exist for the life of the run unit
(WORKING-STORAGE SECTION).
– To have storage be allocated each time a program is entered, and deallocated
on return from the program (LOCAL-STORAGE SECTION).
v Describe data from another program (LINKAGE SECTION).

The Enterprise COBOL compiler limits the maximum size of DATA DIVISION
elements.

RELATED CONCEPTS
“Comparison of WORKING-STORAGE and LOCAL-STORAGE” on page 15

RELATED TASKS
“Using data in input and output operations” on page 13
“Using data from another program” on page 17

12 Programming Guide
RELATED REFERENCES
Compiler limits (Enterprise COBOL Language Reference)

Using data in input and output operations


Define the data you use in input and output operations in the FILE SECTION:
v Name the input and output files your program will use. Use the FD entry to give
names to your files that the input-output statements in the PROCEDURE DIVISION
can refer to.
Data items defined in the FILE SECTION are not available to PROCEDURE DIVISION
statements until the file has been successfully opened.
v In the record description following the FD entry, describe the fields of the records
in the file:
– You can code a level-01 description of the entire record, and then in the
WORKING-STORAGE SECTION code a working copy that describes the fields of the
record in more detail. Use the READ INTO statement to bring the records into
WORKING-STORAGE. Processing occurs on the copy of data in WORKING-STORAGE.
A WRITE FROM statement then writes processed data into the record area
defined in the FILE SECTION.
– The record-name established is the object of WRITE and REWRITE statements.
– For QSAM files only, you can set the record format in the RECORDING MODE
clause. If you omit the RECORDING MODE clause, the compiler determines the
record format based on the RECORD clause and on the level-01 record
descriptions.
– For QSAM files, you can set a blocking factor for the file in the BLOCK
CONTAINS clause. If you omit the BLOCK CONTAINS clause, the file defaults to
unblocked. However, you can override this with z/OS data management
facilities (including a DD file job control statement).
– For line-sequential files, you can set a blocking factor for the file in the BLOCK
CONTAINS clause. When you code BLOCK CONTAINS 1 RECORDS, or BLOCK
CONTAINS n CHARACTERS, where n is the length of one logical record, WRITE
statements result in the record being transferred immediately to the file,
rather than being buffered. This technique is useful when you want each
record written immediately, such as to an error log.

Programs in the same run unit can share, or have access to, common files. The
method for doing this depends on whether the programs are part of a nested
(contained) structure or are separately compiled (including programs compiled as
part of a batch sequence).

You can use the EXTERNAL clause for separately compiled programs. A file that is
defined as EXTERNAL can be referenced by any program in the run unit that
describes the file.

You can use the GLOBAL clause for programs in a nested, or contained, structure. If
a program contains another program (directly or indirectly), both programs can
access a common file by referencing a GLOBAL file name.

RELATED CONCEPTS
“Nested programs” on page 404

RELATED TASKS
“Sharing files between programs (external files)” on page 421

Chapter 1. Structuring your program 13


RELATED REFERENCES
“FILE SECTION entries”

FILE SECTION entries


Entries in the FILE SECTION are summarized in the table below.
Table 2. FILE SECTION entries
Clause To define Notes
FD The file-name to be referred to Must match file-name in the SELECT
in PROCEDURE DIVISION clause. file-name is associated with a
input-output statements (OPEN, ddname through the assignment-name.
CLOSE, READ, also START and
DELETE for VSAM)
BLOCK CONTAINS Size of physical record QSAM: If provided, must match
information on JCL or data set label. If
not provided, the system determines
the optimal block size for you.

Line sequential: Can be specified to


control buffering for WRITE statements.

VSAM: Handled as comments.


RECORD CONTAINS Size of logical records (fixed If provided, must match information on
n length) JCL or data set label. If n is equal to 0,
LRECL must be coded on JCL or data set
label.
RECORD IS Size of logical records If provided, must match information on
VARYING (variable length) JCL or data set label; compiler checks
match with record descriptions.
RECORD CONTAINS Size of logical records If provided, must match information on
n TO m (variable length) JCL or data set label; compiler checks
match with record descriptions.
LABEL RECORDS Labels for QSAM files VSAM: Handled as comments
STANDARD Labels exist QSAM: Handled as comments
OMITTED Labels do not exist QSAM: Handled as comments
data-name Labels defined by the user QSAM: Allowed for (optional) tape or
disk
VALUE OF An item in the label records Comments only
associated with file
DATA RECORDS Names of records associated Comments only
with file
LINAGE Depth of logical page QSAM only
CODE-SET ASCII or EBCDIC files QSAM only.

When an ASCII file is identified with


the CODE-SET clause, the corresponding
DD statement might need to have
DCB=(OPTCD=Q. . .) or
DCB=(RECFM=D. . .) coded if the file
was not created using VS COBOL II,
COBOL for OS/390 & VM, or IBM
Enterprise COBOL for z/OS.
RECORDING MODE Physical record description QSAM only

14 Programming Guide
RELATED CONCEPTS
“Labels for QSAM files” on page 141

Comparison of WORKING-STORAGE and LOCAL-STORAGE


WORKING-STORAGE for programs is allocated at the start of the run unit. Any data
items with VALUE clauses are initialized to the appropriate value at that time. For
the duration of the run unit, WORKING-STORAGE items persist in their last-used state.
Exceptions are:
v A program with INITIAL specified in the PROGRAM-ID paragraph
In this case, WORKING-STORAGE data items are reinitialized each time that the
program is entered.
v A subprogram that is dynamically called and then canceled
In this case, WORKING-STORAGE data items are reinitialized on the first reentry into
the program following the CANCEL.

WORKING-STORAGE is deallocated at the termination of the run unit.

See the related tasks for information about WORKING-STORAGE in COBOL class
definitions.

A separate copy of LOCAL-STORAGE data is allocated for each call of a program or


invocation of a method, and is freed on return from the program or method. If you
specify a VALUE clause on a LOCAL-STORAGE item, the item is initialized to that value
on each call or invocation. If a VALUE clause is not specified, the initial value of the
item is undefined.

Threading: Each invocation of a program that runs simultaneously on multiple


threads shares access to a single copy of WORKING-STORAGE data. Each invocation
has a separate copy of LOCAL-STORAGE data.

“Example: storage sections”

RELATED TASKS
“WORKING-STORAGE SECTION for defining class instance data” on page 492
Chapter 27, “Preparing COBOL programs for multithreading,” on page 437
“Ending and reentering main programs or subprograms” on page 394

RELATED REFERENCES
Working-storage section (Enterprise COBOL Language Reference)
Local-storage section (Enterprise COBOL Language Reference)

Example: storage sections


The following is an example of a recursive program that uses both
WORKING-STORAGE and LOCAL-STORAGE.
CBL pgmn(lu)
*********************************
* Recursive Program - Factorials
*********************************
IDENTIFICATION DIVISION.
Program-Id. factorial recursive.
ENVIRONMENT DIVISION.
DATA DIVISION.
Working-Storage Section.
01 numb pic 9(4) value 5.
01 fact pic 9(8) value 0.
Local-Storage Section.

Chapter 1. Structuring your program 15


01 num pic 9(4).
PROCEDURE DIVISION.
move numb to num.

if numb = 0
move 1 to fact
else
subtract 1 from numb
call ’factorial’
multiply num by fact
end-if.

display num ’! = ’ fact.


goback.
End Program factorial.

The program produces the following output:


0000! = 00000001
0001! = 00000001
0002! = 00000002
0003! = 00000006
0004! = 00000024
0005! = 00000120

The following tables show the changing values of the data items in LOCAL-STORAGE
and WORKING-STORAGE in the successive recursive calls of the program, and in the
ensuing gobacks. During the gobacks, fact progressively accumulates the value of
5! (five factorial).

Value for num in Value for numb in Value for fact in


Recursive calls LOCAL-STORAGE WORKING-STORAGE WORKING-STORAGE
Main 5 5 0
1 4 4 0
2 3 3 0
3 2 2 0
4 1 1 0
5 0 0 0

Value for num in Value for numb in Value for fact in


Gobacks LOCAL-STORAGE WORKING-STORAGE WORKING-STORAGE
5 0 0 1
4 1 0 1
3 2 0 2
2 3 0 6
1 4 0 24
Main 5 0 120

RELATED CONCEPTS
“Comparison of WORKING-STORAGE and LOCAL-STORAGE” on page 15

16 Programming Guide
Using data from another program
How you share data depends on the type of program. You share data differently in
programs that are separately compiled than you do for programs that are nested or
for programs that are recursive or multithreaded.

RELATED TASKS
“Sharing data in separately compiled programs”
“Sharing data in nested programs”
“Sharing data in recursive or multithreaded programs”

Sharing data in separately compiled programs


Many applications consist of separately compiled programs that call and pass data
to one another. Use the LINKAGE SECTION in the called program to describe the data
passed from another program. In the calling program, use a CALL . . . USING or
INVOKE . . . USING statement to pass the data.

RELATED TASKS
“Passing data” on page 411

Sharing data in nested programs


Some applications consist of nested programs, that is, programs that are contained
in other programs. Level-01 data items can include the GLOBAL attribute. This
attribute allows any nested program that includes the declarations to access these
data items.

A nested program can also access data items in a sibling program (one at the same
nesting level in the same containing program) that is declared with the COMMON
attribute.

RELATED CONCEPTS
“Nested programs” on page 404

Sharing data in recursive or multithreaded programs


If your program has the RECURSIVE attribute or is compiled with the THREAD
compiler option, data that is defined in the LINKAGE SECTION is not accessible on
subsequent invocations of the program.

To address a record in the LINKAGE SECTION, use either of these techniques:


v Pass an argument to the program and specify the record in an appropriate
position in the USING phrase in the program.
v Use the format-5 SET statement.

If your program has the RECURSIVE attribute or is compiled with the THREAD
compiler option, the address of the record is valid for a particular instance of the
program invocation. The address of the record in another execution instance of the
same program must be reestablished for that execution instance. Unpredictable
results will occur if you refer to a data item for which the address has not been
established.

RELATED CONCEPTS
“Multithreading” on page 437

RELATED TASKS
“Making recursive calls” on page 407
“Processing files with multithreading” on page 440

Chapter 1. Structuring your program 17


RELATED REFERENCES
SET statement (Enterprise COBOL Language Reference)
“THREAD” on page 309

Processing the data


In the PROCEDURE DIVISION of a program, you code the executable statements that
process the data you have defined in the other divisions. The PROCEDURE DIVISION
contains one or two headers and the logic of your program.

The PROCEDURE DIVISION begins with the division header and a procedure-name
header. The division header for a program can simply be:
PROCEDURE DIVISION.

You can code your division header to receive parameters with the USING phrase or
to return a value with the RETURNING phrase.

To receive an argument that was passed by reference (the default) or by content,


code the division header for a program in either of these ways:
PROCEDURE DIVISION USING dataname
PROCEDURE DIVISION USING BY REFERENCE dataname

Be sure to define dataname in the LINKAGE SECTION of the DATA DIVISION.

To receive a parameter that was passed by value, code the division header for a
program as follows:
PROCEDURE DIVISION USING BY VALUE dataname

To return a value as a result, code the division header as follows:


PROCEDURE DIVISION RETURNING dataname2

You can also combine USING and RETURNING in a PROCEDURE DIVISION header:
PROCEDURE DIVISION USING dataname RETURNING dataname2

Be sure to define dataname and dataname2 in the LINKAGE SECTION of the DATA
DIVISION.

RELATED CONCEPTS
“How logic is divided in the PROCEDURE DIVISION”

RELATED TASKS
“Eliminating repetitive coding” on page 595

How logic is divided in the PROCEDURE DIVISION


The PROCEDURE DIVISION of a program is divided into sections and paragraphs,
which contain sentences and statements:
Section
Logical subdivision of your processing logic.
A section has a section header and is optionally followed by one or more
paragraphs.
A section can be the subject of a PERFORM statement. One type of section is
for declaratives.

18 Programming Guide
Paragraph
Subdivision of a section, procedure, or program.
A paragraph has a name followed by a period and zero or more sentences.
A paragraph can be the subject of a statement.
Sentence
Series of one or more COBOL statements ending with a period.
Statement
Performs a defined step of COBOL processing, such as adding two
numbers.
A statement is a valid combination of words, beginning with a COBOL
verb. Statements are imperative (indicating unconditional action),
conditional, or compiler-directing. Using explicit scope terminators instead
of periods to show the logical end of a statement is preferred.
Phrase
A subdivision of a statement.

RELATED CONCEPTS
“Compiler-directing statements” on page 20
“Scope terminators” on page 21
“Imperative statements”
“Conditional statements”
“Declaratives” on page 22

RELATED REFERENCES
PROCEDURE DIVISION structure (Enterprise COBOL Language Reference)

Imperative statements
An imperative statement indicates an unconditional action to be taken (such as
ADD, MOVE, INVOKE, or CLOSE).

An imperative statement can be ended with an implicit or explicit scope


terminator.

A conditional statement that ends with an explicit scope terminator becomes an


imperative statement called a delimited scope statement. Only imperative statements
(or delimited scope statements) can be nested.

RELATED CONCEPTS
“Conditional statements”
“Scope terminators” on page 21

Conditional statements
A conditional statement is either a simple conditional statement (IF, EVALUATE,
SEARCH) or a conditional statement made up of an imperative statement that
includes a conditional phrase or option.

You can end a conditional statement with an implicit or explicit scope terminator.
If you end a conditional statement explicitly, it becomes a delimited scope
statement (which is an imperative statement).

You can use a delimited scope statement in these ways:


v To delimit the range of operation for a COBOL conditional statement and to
explicitly show the levels of nesting

Chapter 1. Structuring your program 19


For example, use an END-IF statement instead of a period to end the scope of an
IF statement within a nested IF.
v To code a conditional statement where the COBOL syntax calls for an imperative
statement
For example, code a conditional statement as the object of an inline PERFORM:
PERFORM UNTIL TRANSACTION-EOF
PERFORM 200-EDIT-UPDATE-TRANSACTION
IF NO-ERRORS
PERFORM 300-UPDATE-COMMUTER-RECORD
ELSE
PERFORM 400-PRINT-TRANSACTION-ERRORS
END-IF
READ UPDATE-TRANSACTION-FILE INTO WS-TRANSACTION-RECORD
AT END
SET TRANSACTION-EOF TO TRUE
END-READ
END-PERFORM
An explicit scope terminator is required for the inline PERFORM statement, but it is
not valid for the out-of-line PERFORM statement.

For additional program control, you can use the NOT phrase with conditional
statements. For example, you can provide instructions to be performed when a
particular exception does not occur, such as NOT ON SIZE ERROR. The NOT phrase
cannot be used with the ON OVERFLOW phrase of the CALL statement, but it can be
used with the ON EXCEPTION phrase.

Do not nest conditional statements. Nested statements must be imperative


statements (or delimited scope statements) and must follow the rules for
imperative statements.

The following statements are examples of conditional statements if they are coded
without scope terminators:
v Arithmetic statement with ON SIZE ERROR
v Data-manipulation statements with ON OVERFLOW
v CALL statements with ON OVERFLOW
v I/O statements with INVALID KEY, AT END, or AT END-OF-PAGE
v RETURN with AT END

RELATED CONCEPTS
“Imperative statements” on page 19
“Scope terminators” on page 21

RELATED TASKS
“Selecting program actions” on page 75

RELATED REFERENCES
Conditional statements (Enterprise COBOL Language Reference)

Compiler-directing statements
A compiler-directing statement is not part of the program logic. A
compiler-directing statement causes the compiler to take specific action about the
program structure, COPY processing, listing control, or control flow.

RELATED REFERENCES
Chapter 18, “Compiler-directing statements,” on page 317
Compiler-directing statements (Enterprise COBOL Language Reference)

20 Programming Guide
Scope terminators
Scope terminators can be explicit or implicit. Explicit scope terminators end a verb
without ending a sentence. They consist of END followed by a hyphen and the
name of the verb being terminated, such as END-IF. An implicit scope terminator is
a period (.) that ends the scope of all previous statements not yet ended.

Each of the two periods in the following program fragment ends an IF statement,
making the code equivalent to the code after it that instead uses explicit scope
terminators:
IF ITEM = “A”
DISPLAY “THE VALUE OF ITEM IS ” ITEM
ADD 1 TO TOTAL
MOVE “C” TO ITEM
DISPLAY “THE VALUE OF ITEM IS NOW ” ITEM.
IF ITEM = “B”
ADD 2 TO TOTAL.
IF ITEM = “A”
DISPLAY “THE VALUE OF ITEM IS ” ITEM
ADD 1 TO TOTAL
MOVE “C” TO ITEM
DISPLAY “THE VALUE OF ITEM IS NOW ” ITEM
END-IF
IF ITEM = “B”
ADD 2 TO TOTAL
END-IF

If you use implicit terminators, the end of statements can be unclear. As a result,
you might end statements unintentionally, changing your program’s logic. Explicit
scope terminators make a program easier to understand and prevent unintentional
ending of statements. For example, in the program fragment below, changing the
location of the first period in the first implicit scope example changes the meaning
of the code:
IF ITEM = “A”
DISPLAY “VALUE OF ITEM IS ” ITEM
ADD 1 TO TOTAL.
MOVE “C” TO ITEM
DISPLAY “ VALUE OF ITEM IS NOW ” ITEM
IF ITEM = “B”
ADD 2 TO TOTAL.

The MOVE statement and the DISPLAY statement after it are performed regardless of
the value of ITEM, despite what the indentation indicates, because the first period
terminates the IF statement.

For improved program clarity and to avoid unintentional ending of statements, use
explicit scope terminators, especially within paragraphs. Use implicit scope
terminators only at the end of a paragraph or the end of a program.

Be careful when coding an explicit scope terminator for an imperative statement


that is nested within a conditional statement. Ensure that the scope terminator is
paired with the statement for which it was intended. In the following example, the
scope terminator will be paired with the second READ statement, though the
programmer intended it to be paired with the first.
READ FILE1
AT END
MOVE A TO B
READ FILE2
END-READ

Chapter 1. Structuring your program 21


To ensure that the explicit scope terminator is paired with the intended statement,
the preceding example can be recoded in this way:
READ FILE1
AT END
MOVE A TO B
READ FILE2
END-READ
END-READ

RELATED CONCEPTS
“Conditional statements” on page 19
“Imperative statements” on page 19

Declaratives
Declaratives provide one or more special-purpose sections that are executed when
an exception condition occurs.

Start each declarative section with a USE statement that identifies the function of
the section; in the procedures, specify the actions to be taken when the condition
occurs.

RELATED TASKS
“Finding and handling input-output errors” on page 323

RELATED REFERENCES
Declaratives (Enterprise COBOL Language Reference)

22 Programming Guide
Chapter 2. Using data
This information is intended to help non-COBOL programmers relate terms used
in other programming languages to COBOL terms for data. It introduces COBOL
fundamentals for:
v Variables, structures, literals, and constants
v Assigning and displaying values
v Intrinsic (built-in) functions
v Tables (arrays) and pointers

RELATED CONCEPTS
“Storage and its addressability” on page 34

RELATED TASKS
“Using variables, structures, literals, and constants”
“Assigning values to data items” on page 25
“Displaying values on a screen or in a file (DISPLAY)” on page 30
“Using intrinsic functions (built-in functions)” on page 32
“Using tables (arrays) and pointers” on page 33
Chapter 7, “Processing character data in an international environment,” on page
103

Using variables, structures, literals, and constants


Most high-level programming languages share the concept of data being
represented as variables, structures, literals, and constants. The data in a COBOL
program can be alphabetic, alphanumeric, national, or numeric. You can also define
index data items, and data items described with USAGE POINTER, USAGE
FUNCTION-POINTER, USAGE PROCEDURE-POINTER, or USAGE OBJECT REFERENCE. You
place all data definitions in the DATA DIVISION of your program.

Variables
A variable is a data item; its value can change during a program. The values are
restricted, however, to the data type that you define when you give the data item a
name and a length. For example, if a customer name is a data item in your
program, you could code:
Data Division.
. . .
01 Customer-Name Pic X(20).
01 Original-Customer-Name Pic X(20).
. . .
Procedure Division.
. . .
Move Customer-Name to Original-Customer-Name
. . .

Data structure: data items and group items


Related data items can be parts of a hierarchical data structure. A data item that
does not have any subordinate items is called an elementary data item. A data item
that is composed of subordinated data items is called a group item. A record can be
either an elementary data item or a group of data items.

© Copyright IBM Corp. 1991, 2004 23


In this example, Customer-Record is a group item composed of two group items
(Customer-Name and Part-Order), each of which contains elementary data items.
You can refer to the entire group item or to parts of the group item as shown in
the MOVE statements in the PROCEDURE DIVISION.
Data Division.
File Section.
FD Customer-File
Record Contains 45 Characters.
01 Customer-Record.
05 Customer-Name.
10 Last-Name Pic x(17).
10 Filler Pic x.
10 Initials Pic xx.
05 Part-Order.
10 Part-Name Pic x(15).
10 Part-Color Pic x(10).
Working-Storage Section.
01 Orig-Customer-Name.
05 Surname Pic x(17).
05 Initials Pic x(3).
01 Inventory-Part-Name Pic x(15).
. . .
Procedure Division.
. . .
Move Customer-Name to Orig-Customer-Name
Move Part-Name to Inventory-Part-Name
. . .

Literals
A literal is a character string whose value is given by the characters themselves.
When you know the value you want to use for a data item, use a literal
representation of the data value in the PROCEDURE DIVISION. You do not need to
define it or refer to a data-name. For example, you can prepare an error message
for an output file this way:
Move “Name is not valid” To Customer-Name

You can compare a data item to a certain number this way:


01 Part-number Pic 9(5).
. . .
If Part-number = 03519 then display “Part number was found”

In these examples, “Name is not valid” is an alphanumeric literal, and 03519 is a


numeric literal.

Constants
A constant is a data item that has only one value. COBOL does not define a
construct specifically for constants. However, most COBOL programmers define a
data item with an initial VALUE (as opposed to initializing a data item by using the
INITIALIZE statement). For example:
Data Division.
. . .
01 Report-Header pic x(50) value “Company Sales Report”.
. . .
01 Interest pic 9v9999 value 1.0265.

24 Programming Guide
Figurative constants
Certain commonly used constants and literals are provided as reserved words
called figurative constants: ZERO, SPACE, HIGH-VALUE, LOW-VALUE, QUOTE, NULL, and ALL.
Because they represent fixed values, figurative constants do not require a data
definition. For example:
Move Spaces To Report-Header

RELATED REFERENCES
Classes and categories of data (Enterprise COBOL Language Reference)
PICTURE clause (Enterprise COBOL Language Reference)
Literals (Enterprise COBOL Language Reference)
Figurative constants (Enterprise COBOL Language Reference)

Assigning values to data items


After you have defined a data item, you can assign a value to it at any time.
Assignment takes many forms in COBOL, depending on what you want to do.
Table 3. Assignment to data items in a program
What you want to do How to do it
To assign values to a data item or large data area Use one of these ways:
v INITIALIZE statement
v MOVE statement
v STRING or UNSTRING statement
v VALUE clause (to set data items to the values you want
them to have when the program is in its initial state)
To assign the results of arithmetic Use the COMPUTE statement.
To replace characters or groups of characters in a data Use the INSPECT statement.
item
To receive values from a file Use the READ (or READ INTO) statement.
To receive values from a system input device or a file Use the ACCEPT statement.
To establish a constant Use the VALUE clause in the definition of the data item,
| and do not use the data item as a receiver in the
| program. Such an item gives the equivalent of a constant
| even though the compiler does not enforce read-only
| constants.
To place a value associated with a table element in an Use the SET statement.
index
To set the status of an external switch to ON or OFF
To move data to a condition-name to make the condition
true
To set a POINTER, PROCEDURE-POINTER, or
FUNCTION-POINTER data item to an address
To associate an OBJECT REFERENCE data item with an
object instance

“Examples: initializing data items” on page 26

RELATED TASKS
“Initializing a structure (INITIALIZE)” on page 27
“Assigning values to elementary or group data items (MOVE)” on page 27
“Joining data items (STRING)” on page 87
“Splitting data items (UNSTRING)” on page 89
Chapter 2. Using data 25
“Assigning arithmetic results (MOVE or COMPUTE)” on page 28
“Tallying and replacing data items (INSPECT)” on page 95
“Assigning input from a screen or file (ACCEPT)” on page 29
Chapter 7, “Processing character data in an international environment,” on page
103

RELATED REFERENCES
Enterprise COBOL Language Reference

Examples: initializing data items


Initializing a data item to blanks or zeros:
INITIALIZE identifier-1

IDENTIFIER-1 PICTURE IDENTIFIER-1 before IDENTIFIER-1 after


9(5) 12345 00000
X(5) AB123 bbbbb1
99XX9 12AB3 bbbbb1
XXBX/XX ABbC/DE bbbb/bb1
**99.9CR 1234.5CR **00.0bb1
A(5) ABCDE bbbbb1
+99.99E+99 +12.34E+02 +00.00E+00

1. The symbol b represents a blank space.

Initializing a right-justified field:


01 ANJUST PIC X(8) JUSTIFIED RIGHT.
01 ALPHABETIC-1 PIC A(4) VALUE “ABCD”.
. . .
INITIALIZE ANJUST
REPLACING ALPHANUMERIC DATA BY ALPHABETIC-1

ALPHABETIC-1 ANJUST before ANJUST after


1
ABCD bbbbbbbb bbbbABCD1

1. The symbol b represents a blank space.

Initializing an alphanumeric data item:


01 ALPHANUMERIC-1 PIC X.
01 ALPHANUMERIC-3 PIC X(1) VALUE “A”.
. . .
INITIALIZE ALPHANUMERIC-1
REPLACING ALPHANUMERIC DATA BY ALPHANUMERIC-3

ALPHANUMERIC-3 ALPHANUMERIC-1 before ALPHANUMERIC-1 after


A y A

Initializing a numeric data item:


01 NUMERIC-1 PIC 9(8).
01 NUM-INT-CMPT-3 PIC 9(7) COMP VALUE 1234567.
. . .
INITIALIZE NUMERIC-1
REPLACING NUMERIC DATA BY NUM-INT-CMPT-3

26 Programming Guide
NUM-INT-CMPT-3 NUMERIC-1 before NUMERIC-1 after
1234567 98765432 01234567

Initializing an edited alphanumeric data item:


01 ALPHANUM-EDIT-1 PIC XXBX/XXX.
01 ALPHANUM-EDIT-3 PIC X/BB VALUE “M/bbb”.
. . .
INITIALIZE ALPHANUM-EDIT-1
REPLACING ALPHANUMERIC-EDITED DATA BY ALPHANUM-EDIT-3

ALPHANUM-EDIT-3 ALPHANUM-EDIT-1 before ALPHANUM-EDIT-1 after


1 1
M/bb ABbC/DEF M/bb/bbb1

1. The symbol b represents a blank space.

RELATED TASKS
“Initializing a structure (INITIALIZE)”

Initializing a structure (INITIALIZE)


You can reset the values of all subordinate data items in a group item by applying
the INITIALIZE statement to the group item. However, it is inefficient to initialize
an entire group unless you really need all the items in the group initialized.

The following example shows how you can reset fields in a transaction record
produced by a program to spaces and zeros. The fields are not identical in each
record produced.
01 TRANSACTION-OUT.
05 TRANSACTION-CODE PIC X.
05 PART-NUMBER PIC 9(6).
05 TRANSACTION-QUANTITY PIC 9(5).
05 PRICE-FIELDS.
10 UNIT-PRICE PIC 9(5)V9(2).
10 DISCOUNT PIC V9(2).
10 SALES-PRICE PIC 9(5)V9(2).
. . .
INITIALIZE TRANSACTION-OUT

Record TRANSACTION-OUT before TRANSACTION-OUT after


1 R001383000240000000000000000 b0000000000000000000000000001
2 R001390000480000000000000000 b0000000000000000000000000001
3 S001410000120000000000000000 b0000000000000000000000000001
4 C001383000000000425000000000 b0000000000000000000000000001
5 C002010000000000000100000000 b0000000000000000000000000001

1. The symbol b represents a blank space.

Assigning values to elementary or group data items (MOVE)


Use the MOVE statement to assign values to elementary data items or group data
items.

For example, the following statement assigns the contents of the data item
Customer-Name to the data item Orig-Customer-Name:
Move Customer-Name to Orig-Customer-Name

Chapter 2. Using data 27


If Customer-Name were longer than Orig-Customer-Name, truncation would occur on
the right. If it were shorter, the extra character positions on the right would be
filled with spaces.

When you move a group item to another group item, be sure that the subordinate
data descriptions are compatible. The compiler performs all MOVE statements
regardless of whether the items fit, even if a destructive overlap could occur at run
time.

For data items that contain numbers, moves can be more complicated because
there are several ways numbers are represented. In general, the algebraic values of
numbers are moved if possible (as opposed to the digit-by-digit move performed
with character data):
01 Item-x Pic 999v9.
. . .
Move 3.06 to Item-x

This move would result in Item-x containing the value 3.0, represented by 0030.

You can move an alphanumeric item or an integer item to a national data item; the
item is converted. You can move a national data item only to another national data
item. In either case padding or truncation might occur, and you must ensure that
truncation does not occur within a character.

The following example shows a data item in the Greek language that moves into a
national data item:
CBL CODEPAGE(00875)
. . .
01 Data-in-Unicode Pic N(100) usage national.
01 Data-in-Greek Pic X(100).
. . .
Read Greek-file into Data-in-Greek
Move Data-in-Greek to Data-in-Unicode

RELATED CONCEPTS
“Unicode and encoding of language characters” on page 105

RELATED REFERENCES
MOVE statement (Enterprise COBOL Language Reference)
“CODEPAGE” on page 274
“Converting national data” on page 107

Assigning arithmetic results (MOVE or COMPUTE)


When assigning a number to a data item, consider using the COMPUTE statement
instead of the MOVE statement. For example, the following two statements
accomplish the same thing in most cases:
Move w to z
Compute z = w

The MOVE statement carries out the assignment with truncation. You can, however,
specify the DIAGTRUNC compiler option to request that the compiler issue a warning
diagnostic for MOVE statements that might truncate numeric receivers.

When significant left-order digits would be lost in execution, the COMPUTE statement
can detect the condition and allow you to handle it.

28 Programming Guide
When you use the ON SIZE ERROR phrase of the COMPUTE statement, the compiler
generates code to detect a size-overflow condition. If the condition occurs, the code
in the ON SIZE ERROR phrase is performed, and the content of z remains
unchanged. If the ON SIZE ERROR phrase is not specified, the assignment is carried
out with truncation. There is no ON SIZE ERROR support for the MOVE statement.

You can also use the COMPUTE statement to assign the result of an arithmetic
expression (or intrinsic function) to a data item. For example:
Compute z = y + (x ** 3)
Compute x = Function Max(x y z)

Results of date, time, and mathematical calculations, as well as other operations,


can be assigned to data items using Language Environment callable services. These
Language Environment services are available through a standard COBOL CALL
statement, and the values they return are passed in the parameters in the CALL
statement. For example, you can call the Language Environment service CEESIABS
to find the absolute value of a data item by coding the statement:
Call ’CEESIABS’ Using Arg, Feedback-code, Result.

As a result of this call, the data item Result is assigned to be the absolute value of
the value that is in the data item Arg; the data item Feedback-code contains the
return code indicating whether the service completed successfully. You have to
define all the data items in the DATA DIVISION using the correct descriptions
according to the requirements of the particular callable service you are using. For
the example above, the data items could be defined like this:
77 Arg Pic s9(9) Binary.
77 Feedback-code Pic x(12) Display.
77 Result Pic s9(9) Binary.

RELATED REFERENCES
“DIAGTRUNC” on page 280
Intrinsic functions (Enterprise COBOL Language Reference)
Callable services (Language Environment Programming Reference)

Assigning input from a screen or file (ACCEPT)


One way to assign a value to a data item is to read the value from a screen or a
file. To enter data from the screen, first associate the monitor with a
mnemonic-name in the SPECIAL-NAMES paragraph. Then use ACCEPT to assign the
line of input entered at the screen to a data item.

For example:
Environment Division.
Configuration Section.
Special-Names.
Console is Names-Input.
. . .
Accept Customer-Name From Names-Input

To read from a file instead of the screen, make the following change:
v Change Console to device, where device is any valid system device (for example,
SYSIN). For example:
SYSIN is Names-Input
Note that device can be a ddname that references a hierarchical file system (HFS)
path. If this DD is not defined and your program is running in a UNIX

Chapter 2. Using data 29


environment, stdin is the input source. If this DD is not defined and your
program is not running in a UNIX environment, the ACCEPT statement fails.

When you assign a value to a national data item, input data from the console is
converted from EBCDIC to Unicode representation (UTF-16), based on the value of
the CODEPAGE option. This is the only situation where conversion of national data is
done when you use the ACCEPT statement, because the input is known to be
coming from a screen.

If you want conversion done when the input data is from any other device, use the
NATIONAL-OF intrinsic function.

RELATED CONCEPTS
“Unicode and encoding of language characters” on page 105

RELATED TASKS

RELATED REFERENCES
“CODEPAGE” on page 274
SPECIAL-NAMES paragraph (Enterprise COBOL Language Reference)

Displaying values on a screen or in a file (DISPLAY)


You can display the value of a data item on a screen or write it to a file by using
the DISPLAY statement. For example:
Display “No entry for surname ’” Customer-Name
“’ found in the file.”.

If the content of the data item Customer-Name is JOHNSON, then the statement
above displays the following message on the system logical output device:
No entry for surname ’JOHNSON’ found in the file.

To write data to a destination other than the system logical output device, use the
UPON clause with a destination other than SYSOUT. For example, the following
statement writes to the file specified in the SYSPUNCH DD statement:
Display “Hello” upon syspunch.

You can specify a file in the hierarchical file system (HFS) with this ddname. For
example, with the following definition, your DISPLAY output is written to the HFS
file /u/userid/cobol/demo.lst:
//SYSPUNCH DD PATH=’/u/userid/cobol/demo.lst’,
// PATHOPTS=(OWRONLY,OCREAT,OTRUNC),PATHMODE=SIRWXU,
// FILEDATA=TEXT

The following statement writes to the job log or console and to the TSO screen if
you are running under TSO:
Display “Hello” upon console.

When you display the value of a national data item to the console, it is converted
from Unicode representation (UTF-16) to EBCDIC, based on the value of the
CODEPAGE option. This is the only situation where conversion of national data is
done when you use the DISPLAY statement, because the output is known to be
directed to a screen.

If you want a national data item to be converted when you direct output to a
different device, use the DISPLAY-OF intrinsic function, such as in this example:
30 Programming Guide
01 Data-in-Unicode pic N(10) usage national.
. . .
Display function Display-of(Data-in-Unicode, 00037)

Displaying data on the system logical output device


To write data to the system logical output device, either omit the UPON clause or
use the UPON clause with destination SYSOUT. For example:
Display “Hello” upon sysout.

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 (HFS) with this
ddname.

If the OUTDD ddname is not allocated and you are not running in a UNIX
environment, a default DD of SYSOUT=* is allocated.

If the OUTDD ddname is not allocated and you are running in a 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; rather the output is written as a single stream of characters without
line breaks.

If OUTDD and the Language Environment run-time option MSGFILE both specify the
same ddname, DISPLAY output and Language Environment run-time diagnostics
are both routed to the Language Environment message file.

Using WITH NO ADVANCING


If you specify the WITH NO ADVANCING phrase and the output is going to a ddname,
the printer control character + (plus) is placed into the first output position from
the next DISPLAY statement. + is the ANSI-defined printer control character that
suppresses line spacing before a record is printed.

If you specify the WITH NO ADVANCING phrase and the output is going to stdout or
stderr, a new-line character is not appended to the end of the stream. A subsequent
DISPLAY statement might add additional characters to the end of the stream.

If you do not specify WITH NO ADVANCING and the output is going to a ddname, the
printer control character ’ ’ (space) is placed into the first output position from the
next DISPLAY statement, indicating single-spaced output.

For example:
DISPLAY “ABC”
DISPLAY “CDEF” WITH NO ADVANCING
DISPLAY “GHIJK” WITH NO ADVANCING
DISPLAY “LMNOPQ”
DISPLAY “RSTUVWX”

Chapter 2. Using data 31


If you use the statements above, the result sent to the output device is:
ABC
CDEF
+GHIJK
+LMNOPQ
RSTUVMX

The output printed depends on how the output device interprets printer control
characters.

If you do not specify the WITH NO ADVANCING phrase and the output is going to
stdout or stderr, a new-line character is appended to the end of the stream.

RELATED CONCEPTS
“Unicode and encoding of language characters” on page 105

RELATED TASKS
“Setting and accessing environment variables” on page 384
“Coding COBOL programs to run under CICS” on page 359
“Converting national data” on page 107

RELATED REFERENCES
DISPLAY statement (Enterprise COBOL Language Reference)
“OUTDD” on page 296
“CODEPAGE” on page 274

Using intrinsic functions (built-in functions)


Some high-level programming languages have built-in functions that you can
reference in your program as if they were variables that have defined attributes
and a predetermined value. In COBOL, these functions are called intrinsic functions.
They provide capabilities for manipulating strings and numbers.

Because the value of an intrinsic function is derived automatically at the time of


reference, you do not need to define functions in the DATA DIVISION. Define only
the nonliteral data items that you use as arguments. Figurative constants are not
allowed as arguments.

A function-identifier is the combination of the COBOL reserved word FUNCTION


followed by a function name (such as Max), followed by any arguments to be used
in the evaluation of the function (such as x, y, z).

The groups of highlighted words in the following examples are referred to as


function-identifiers.
Unstring Function Upper-case(Name) Delimited By Space Into Fname Lname
Compute A = 1 + Function Log10(x)
Compute M = Function Max(x y z)

A function-identifier represents both the invocation of the function and the data
value returned by the function. Because it actually represents a data item, you can
use a function-identifier in most places in the PROCEDURE DIVISION where a data
item having the attributes of the returned value can be used.

The COBOL word function is a reserved word, but the function-names are not
reserved. You can use them in other contexts, such as for the name of a data item.
For example, you could use Sqrt to invoke an intrinsic function and to name a
data item in your program:
32 Programming Guide
Working-Storage Section.
01 x Pic 99 value 2.
01 y Pic 99 value 4.
01 z Pic 99 value 0.
01 Sqrt Pic 99 value 0.
. . .
Compute Sqrt = 16 ** .5
Compute z = x + Function Sqrt(y)
. . .

Types of intrinsic functions


A function-identifier represents a value that is of one of these types: alphanumeric,
national, numeric, or integer. You can include a substring specification (reference
modifier) in a function-identifier for alphanumeric or national functions. Numeric
intrinsic functions are further classified according to the type of numbers they
return.

The functions MAX, MIN, DATEVAL, and UNDATE can return either type of value
depending on the type of arguments you supply.

The functions DATEVAL, UNDATE, and YEARWINDOW are provided with the millennium
language extensions to assist with manipulating and converting windowed date
fields.

Nesting functions
Functions can reference other functions as arguments as long as the results of the
nested functions meet the requirements for the arguments of the outer function.
For example:
Compute x = Function Max((Function Sqrt(5)) 2.5 3.5)

In this case, Function Sqrt(5) returns a numeric value. Thus, the three arguments
to the MAX function are all numeric, which is an allowable argument type for this
function.

RELATED TASKS
“Processing table items using intrinsic functions” on page 73
“Converting data items (intrinsic functions)” on page 97
“Evaluating data items (intrinsic functions)” on page 99

Using tables (arrays) and pointers


In COBOL, arrays are called tables. A table is a set of logically consecutive data
items that you define in the DATA DIVISION by using the OCCURS clause.

Pointers are data items that contain virtual storage addresses. You define them
explicitly with the USAGE IS POINTER clause in the DATA DIVISION or implicitly as
ADDRESS OF special registers.

You can perform the following operations on pointer data items:


v Pass them between programs by using the CALL . . . BY REFERENCE statement
v Move them to other pointers by using the SET statement
v Compare them to other pointers for equality by using a relation condition
v Initialize them to contain an address that is not valid by using VALUE IS NULL

Use pointer data items to:

Chapter 2. Using data 33


v Accomplish limited base addressing, particularly if you want to pass and receive
addresses of a record area that is defined with OCCURS DEPENDING ON and is
therefore variably located.
v Handle a chained list.

RELATED TASKS
“Defining a table (OCCURS)” on page 59
“Using procedure and function pointers” on page 407

Storage and its addressability


When you run your COBOL programs, the programs and the data that they use
reside in virtual storage. Storage that you use with COBOL can be either below the
16-MB line or above the 16-MB line but below the 2-GB bar. Two modes of
addressing are available to address this storage: 24-bit and 31-bit.

You can address storage below (but not above) the 16-MB line with 24-bit
addressing. You can address storage either above or below the 16-MB line with
31-bit addressing. Unrestricted storage is addressable by 31-bit addressing and
therefore encompasses all the storage available to your program, both above and
below the 16-MB line.

Enterprise COBOL does not directly exploit the 64-bit virtual addressing capability
of z/OS, however COBOL applications running in 31-bit or 24-bit addressing mode
are fully supported on 64-bit z/OS systems.

Addressing mode (AMODE) is the attribute that tells which hardware addressing mode
is supported by your program: 24-bit addressing, 31-bit addressing, or either 24-bit
or 31-bit addressing. This attribute is AMODE 24, AMODE 31, or AMODE ANY,
respectively. The object program, the load module, and the executing program each
has an AMODE attribute. All Enterprise COBOL object programs are AMODE ANY.

Residency mode (RMODE) is the attribute of a program load module that identifies
where in virtual storage the program will reside: below the 16-MB line, or either
below or above. This attribute is RMODE 24 or RMODE ANY.

Enterprise COBOL uses Language Environment services to control the storage used
at run time. Thus COBOL compiler options and Language Environment run-time
options influence the AMODE and RMODE attributes of your program and data, alone
and in combination:
DATA Compiler option that influences the location of storage for WORKING-STORAGE
| data, I-O buffers, and parameter lists for programs compiled with RENT.
| RMODE Compiler option that influences the residency mode and also influences the
| location of storage for WORKING-STORAGE data, I-O buffers, and parameter
| lists for programs compiled with NORENT.
RENT Compiler option to generate a reentrant program.
HEAP Run-time option that controls storage for the run-time heap. For example,
COBOL WORKING-STORAGE is allocated from heap storage.
STACK Run-time option that controls storage for the run-time stack. For example,
COBOL LOCAL-STORAGE is allocated from stack storage.
ALL31 Run-time option that specifies whether an application can run entirely in
AMODE 31.

34 Programming Guide
Settings for RMODE
The RMODE and RENT options determine the RMODE attribute of your program:
Table 4. Effect of RMODE and RENT compiler options on the RMODE attribute
RMODE compiler option RENT compiler option RMODE attribute
RMODE(AUTO) NORENT RMODE 24
RMODE(AUTO) RENT RMODE ANY
RMODE(24) RENT or NORENT RMODE 24
RMODE(ANY) RENT or NORENT RMODE ANY

Storage restrictions for passing data


Do not pass parameters that are allocated in storage above the 16-MB line to AMODE
24 subprograms. Force the WORKING-STORAGE data and parameter lists below the line
for programs that run in 31-bit addressing mode and pass data to programs that
run in AMODE 24:
v Compile reentrant programs (RENT) with DATA(24).
v Compile nonreentrant programs (NORENT) with RMODE(24) or RMODE(AUTO).
v Nonreentrant programs (NORENT) compiled with RMODE(ANY) must be link-edited
with RMODE 24. The data areas for NORENT programs are above the 16-MB line or
below the 16-MB line depending on where the program is loaded, even if the
program was compiled with DATA(24). The DATA option does not affect programs
compiled with NORENT.

Location of data areas


For reentrant programs, the DATA compiler option and the HEAP run-time option
control whether storage for data areas such as WORKING-STORAGE SECTION and FD
record areas is obtained from below the 16-MB line or from unrestricted storage.
Compile programs with RENT or RMODE(ANY) if they will be run with 31-bit
addressing in virtual storage addresses above the 16-MB line. The DATA option does
not affect programs compiled with NORENT.

When you specify the run-time option HEAP(,,BELOW), the DATA compiler option has
| no effect; the storage for WORKING-STORAGE SECTION data areas is allocated from
below the 16-MB line. However, with HEAP(,,ANYWHERE) as the run-time option,
storage for data areas is allocated from below the 16-MB line if you compiled the
program with the DATA(24) compiler option, or from unrestricted storage if you
compiled with the DATA(31) compiler option.

Storage for LOCAL-STORAGE data


The location of LOCAL-STORAGE data items is controlled by the STACK run-time
option and the AMODE of the program. LOCAL-STORAGE data items are acquired in
unrestricted storage when the STACK(,,ANYWHERE) run-time option is in effect and
the program is running in AMODE 31. Otherwise LOCAL-STORAGE is acquired below
the 16-MB line. The DATA compiler option does not influence the location of
LOCAL-STORAGE data.

Storage for external data


In addition to affecting how storage is obtained for dynamic data areas
(WORKING-STORAGE, FD record areas, and parameter lists), the DATA compiler option

Chapter 2. Using data 35


can also influence where storage for EXTERNAL data is obtained. Storage required for
EXTERNAL data is obtained from unrestricted storage if the following conditions are
met:
v The program is compiled with the DATA(31) and RENT compiler options or the
RMODE(ANY) and NORENT compiler options.
v The HEAP(,,ANYWHERE) run-time option is in effect.
v The ALL31(ON) run-time option is in effect.

In all other cases, the storage for EXTERNAL data is obtained from below the 16-MB
line. When you specify the ALL31(ON) run-time option, all the programs in the run
unit must be capable of running in 31-bit addressing mode.

Storage for QSAM input-output buffers


The DATA compiler option can also influence where input-output buffers for QSAM
files are obtained. See the related references below for information about allocation
of buffers for QSAM files and the DATA compiler option.

RELATED CONCEPTS
AMODE considerations for heap storage (Language Environment Programming Guide)
“AMODE switching” on page 399

RELATED TASKS
Chapter 24, “Using subprograms,” on page 393
Chapter 25, “Sharing data,” on page 411

RELATED REFERENCES
“Allocation of buffers for QSAM files” on page 140
“DATA” on page 277
“RENT” on page 299
“RMODE” on page 300
“Performance-related compiler options” on page 589
HEAP (Language Environment Programming Reference)
STACK (Language Environment Programming Reference)
ALL31 (Language Environment Programming Reference)
z/OS DFSMS: Program Management

36 Programming Guide
Chapter 3. Working with numbers and arithmetic
In general, you can view COBOL numeric data as a series of decimal digit
positions. However, numeric items can also have special properties such as an
arithmetic sign or a currency sign.

This section describes how to define, display, and store numeric data so that you
can perform arithmetic operations efficiently:
v Use the PICTURE clause and the characters 9, +, -, P, S, and V to define numeric
data.
v Use the PICTURE clause and editing characters (such as Z, comma, and period)
along with MOVE and DISPLAY statements to display numeric data.
v Use the USAGE clause with various formats to control how numeric data is stored.
v Use the numeric class test to validate that data values are appropriate.
v Use ADD, SUBTRACT, MULTIPLY, DIVIDE, and COMPUTE statements to perform
arithmetic.
v Use the CURRENCY SIGN clause and appropriate PICTURE characters to designate
the currency you want.

RELATED TASKS
“Defining numeric data”
“Displaying numeric data” on page 38
“Controlling how numeric data is stored” on page 39
“Checking for incompatible data (numeric class test)” on page 46
“Performing arithmetic” on page 47
“Using currency signs” on page 55

Defining numeric data


Define numeric items by using the PICTURE clause with the character 9 in the data
description to represent the decimal digits of the number. Do not use an X, which
is for alphanumeric items:
05 Count-y Pic 9(4) Value 25.
05 Customer-name Pic X(20) Value “Johnson”.

You can code up to 18 digits in the PICTURE clause when you compile using the
default compiler option ARITH(COMPAT) (referred to as compatibility mode). When
you compile using ARITH(EXTEND) (referred to as extended mode), you can code up
to 31 digits in the PICTURE clause.

Other characters of special significance that you can code are:


P Indicates leading or trailing zeroes
S Indicates a sign, positive or negative
V Implies a decimal point

The s in the following example means that the value is signed:


05 Price Pic s99v99.

The field can therefore hold a positive or a negative value. The v indicates the
position of an implied decimal point, but does not contribute to the size of the
© Copyright IBM Corp. 1991, 2004 37
item because it does not require a storage position. An s usually does not
contribute to the size of a numeric item, because by default it does not require a
storage position.

However, if you plan to port your program or data to a different machine, you
might want to code the sign as a separate position in storage. In this case, the sign
takes 1 byte:
05 Price Pic s99V99 Sign Is Leading, Separate.

This coding ensures that the convention your machine uses for storing a
nonseparate sign will not cause unexpected results on a machine that uses a
different convention.

Separate signs are also preferable for data items that will be printed or displayed.

You cannot use the PICTURE clause with internal floating-point data (COMP-1 or
COMP-2). However, you can use the VALUE clause to provide an initial value for a
floating-point literal:
05 Compute-result Usage Comp-2 Value 06.23E-24.

“Examples: numeric data and internal representation” on page 42

RELATED CONCEPTS
Appendix A, “Intermediate results and arithmetic precision,” on page 603

RELATED TASKS
“Displaying numeric data”
“Controlling how numeric data is stored” on page 39
“Performing arithmetic” on page 47

RELATED REFERENCES
“Sign representation and processing” on page 45
“ARITH” on page 271
“NUMPROC” on page 293

Displaying numeric data


You can define numeric items with certain editing symbols (such as decimal points,
commas, dollar signs, and debit or credit signs) to make the data easier to read
and understand when you display it or print it. For example, in the code below,
Edited-price is a numeric-edited item:
05 Price Pic 9(5)v99.
05 Edited-price Pic $zz,zz9.99.
. . .
Move Price To Edited-price
Display Edited-price

If the contents of Price are 0150099 (representing the value 1,500.99), then
$ 1,500.99 is displayed when you run the code. The z in the PICTURE clause of
Edited-price indicates the suppression of leading zeros.

You cannot use numeric-edited items as operands in arithmetic expressions or in


ADD, SUBTRACT, MULTIPLY, DIVIDE, or COMPUTE statements. You use numeric-edited
items primarily for displaying or printing numeric data. (You can specify the
clause USAGE IS DISPLAY for numeric-edited items; however, it is implied. It means
that the items are stored in character format.)

38 Programming Guide
You can move numeric-edited items to numeric or numeric-edited items. In the
following example, the value of the numeric-edited item is moved to the numeric
item:
Move Edited-price to Price
Display Price

If these two statements immediately followed the statements in the previous


example, then Price would be displayed as 0150099, representing the value
1,500.99.

“Examples: numeric data and internal representation” on page 42

RELATED TASKS
“Controlling how numeric data is stored”
“Defining numeric data” on page 37
“Performing arithmetic” on page 47

RELATED REFERENCES
MOVE statement (Enterprise COBOL Language Reference)

Controlling how numeric data is stored


You can control how the computer stores numeric data items by coding the USAGE
clause in your data description entries. You might want to control the format for
any of several reasons such as these:
v Arithmetic on computational data types is more efficient than on USAGE DISPLAY
data types.
v Packed-decimal format requires less storage per digit than USAGE DISPLAY data
types.
v Packed-decimal format converts to and from DISPLAY format more efficiently
than binary format does.
v Floating-point format is well suited for arithmetic operands and results with
widely varying scale, while maintaining the maximal number of significant
digits.
v You might need to preserve data formats when you move data from one
machine to another.

The numeric data you use in your program will have one of the following formats
available with COBOL:
v External decimal (USAGE DISPLAY)
v External floating point (USAGE DISPLAY)
v Internal decimal (USAGE PACKED-DECIMAL)
v Binary (USAGE BINARY)
v Native binary (USAGE COMP-5)
v Internal floating point (USAGE COMP-1, USAGE COMP-2)

COMP and COMP-4 are synonymous with BINARY, and COMP-3 is synonymous with
PACKED-DECIMAL.

The compiler converts displayable numbers to the internal representation of their


numeric values before using them in arithmetic operations. Therefore it is often
more efficient if you define data items as BINARY or PACKED-DECIMAL rather than as
DISPLAY. For example:

Chapter 3. Working with numbers and arithmetic 39


05 Initial-count Pic S9(4) Usage Binary Value 1000.

Regardless of which USAGE clause you use to control the internal representation of a
value, you use the same PICTURE clause conventions and decimal value in the
VALUE clause (except for floating-point data, for which you cannot use a PICTURE
clause).

“Examples: numeric data and internal representation” on page 42

RELATED CONCEPTS
“Formats for numeric data”
“Data format conversions” on page 43
Appendix A, “Intermediate results and arithmetic precision,” on page 603

RELATED TASKS
“Defining numeric data” on page 37
“Displaying numeric data” on page 38
“Performing arithmetic” on page 47

RELATED REFERENCES
“Conversions and precision” on page 44
“Sign representation and processing” on page 45

Formats for numeric data


The following are the available formats for numeric data.

External decimal (DISPLAY) items


When USAGE DISPLAY is in effect for a data item (either because you have coded it,
or by default), each position (byte) of storage contains one decimal digit. This
means the items are stored in displayable form.

External decimal (also known as zoned decimal) items are primarily intended for
receiving and sending numbers between your program and files, terminals, or
printers. You can also use external decimal items as operands and receivers in
arithmetic processing. However, if your program performs a lot of intensive
arithmetic and efficiency is a high priority, COBOL’s computational numeric types
might be a better choice for the data items used in the arithmetic.

External floating-point (DISPLAY) items


Displayable numbers coded in a floating-point format are called external
floating-point items. As with external decimal items, you define external
floating-point items explicitly by coding USAGE DISPLAY or implicitly by omitting
the USAGE clause. You cannot use the VALUE clause for external floating-point items.

In the following example, Compute-Result is implicitly defined as an external


floating-point item. Each byte of storage contains one of the characters (except for
the v).
05 Compute-Result Pic -9v9(9)E-99.

The minus signs (-) do not mean that the mantissa and exponent must necessarily
be negative numbers. Instead, they mean that when the number is displayed, the
sign appears as a blank for positive numbers or a minus sign for negative
numbers. If you instead code a plus sign (+), the sign appears as a plus sign for
positive numbers or a minus sign for negative numbers.

40 Programming Guide
As with external decimal numbers, external floating-point numbers have to be
converted (by the compiler) to an internal representation of their numeric value
before they can be used in arithmetic operations. If you compile with the default
option ARITH (COMPAT), external floating-point numbers are converted to long
(64-bit) floating-point format. If you compile with ARITH (EXTEND), they are instead
converted to extended-precision (128-bit) floating-point format.

Binary (COMP) items


BINARY, COMP, and COMP-4 are synonyms. Binary-format numbers occupy 2, 4, or 8
bytes of storage. If the PICTURE clause specifies that an item is signed, the leftmost
bit is used as the operational sign.

A binary number with a PICTURE description of four or fewer decimal digits


occupies 2 bytes; five to nine decimal digits, 4 bytes; and 10 to 18 decimal digits, 8
bytes. Binary items with nine or more digits require more handling by the
compiler. Testing them for the SIZE ERROR condition and rounding is more
cumbersome than with other types.

You can use binary items, for example, for indexes, subscripts, switches, and
arithmetic operands or results.

Use the TRUNC(STD|OPT|BIN) compiler option to indicate how binary data (BINARY,
COMP, or COMP-4) is to be truncated.

Native binary (COMP-5) items


Data items that you declare as USAGE COMP-5 are represented in storage as binary
data. However, unlike USAGE COMP items, they can contain values of magnitude up
to the capacity of the native binary representation (2, 4, or 8 bytes) rather than
being limited to the value implied by the number of 9s in the PICTURE clause.

When you move or store numeric data into a COMP-5 item, truncation occurs at the
binary field size rather than at the COBOL PICTURE size limit. When you reference
a COMP-5 item, the full binary field size is used in the operation.

COMP-5 is thus particularly useful for binary data items originating in non-COBOL
programs where the data might not conform to a COBOL PICTURE clause.

The table below shows the ranges of values possible for COMP-5 data items.
Table 5. Ranges in value of COMP-5 data items
PICTURE Storage representation Numeric values
S9(1) through S9(4) Binary halfword (2 bytes) -32768 through +32767
S9(5) through S9(9) Binary fullword (4 bytes) -2,147,483,648 through +2,147,483,647
S9(10) through Binary doubleword (8 -9,223,372,036,854,775,808 through
S9(18) bytes) +9,223,372,036,854,775,807
9(1) through 9(4) Binary halfword (2 bytes) 0 through 65535
9(5) through 9(9) Binary fullword (4 bytes) 0 through 4,294,967,295
9(10) through 9(18) Binary doubleword (8 0 through 18,446,744,073,709,551,615
bytes)

You can specify scaling (that is, decimal positions or implied integer positions) in
the PICTURE clause of COMP-5 items. If you do so, you must appropriately scale the

Chapter 3. Working with numbers and arithmetic 41


maximal capacities listed above. For example, a data item you describe as PICTURE
S99V99 COMP-5 is represented in storage as a binary halfword, and supports a range
of values from -327.68 through +327.67.

Large literals in VALUE clauses: Literals specified in VALUE clauses for COMP-5 items
can, with a few exceptions, contain values of magnitude up to the capacity of the
native binary representation. See Enterprise COBOL Language Reference for the
exceptions.

Regardless of the setting of the TRUNC compiler option, COMP-5 data items behave
like binary data does in programs compiled with TRUNC(BIN).

Packed-decimal (COMP-3) items


PACKED-DECIMAL and COMP-3 are synonyms. Packed-decimal items occupy 1 byte of
storage for every two decimal digits you code in the PICTURE description, except
that the rightmost byte contains only one digit and the sign. This format is most
efficient when you code an odd number of digits in the PICTURE description, so
that the leftmost byte is fully used. Packed-decimal items are handled as
fixed-point numbers for arithmetic purposes.

Floating-point (COMP-1 and COMP-2) items


COMP-1 refers to short floating-point format and COMP-2 refers to long floating-point
format, which occupy 4 and 8 bytes of storage, respectively. The leftmost bit
contains the sign and the next 7 bits contain the exponent; the remaining 3 or 7
bytes contain the mantissa.

COMP-1 and COMP-2 data items are stored in zSeries hexadecimal format.

RELATED CONCEPTS
Appendix A, “Intermediate results and arithmetic precision,” on page 603

RELATED REFERENCES
VALUE clause (Enterprise COBOL Language Reference)
“TRUNC” on page 310

Examples: numeric data and internal representation


The following table shows the internal representation of numeric items.
Table 6. Internal representation of numeric items
PICTURE and USAGE and
Numeric type optional SIGN clause Value Internal representation
External PIC S9999 DISPLAY + 1234 F1 F2 F3 C4
decimal - 1234 F1 F2 F3 D4
1234 F1 F2 F3 C4
PIC 9999 DISPLAY 1234 F1 F2 F3 F4
PIC S9999 DISPLAY + 1234 C1 F2 F3 F4
SIGN LEADING - 1234 D1 F2 F3 F4
PIC S9999 DISPLAY + 1234 4E F1 F2 F3 F4
SIGN LEADING SEPARATE - 1234 60 F1 F2 F3 F4
PIC S9999 DISPLAY + 1234 F1 F2 F3 F4 4E
SIGN TRAILING SEPARATE - 1234 F1 F2 F3 F4 60

42 Programming Guide
Table 6. Internal representation of numeric items (continued)
PICTURE and USAGE and
Numeric type optional SIGN clause Value Internal representation
Binary PIC S9999 BINARY + 1234 04 D2
COMP - 1234 FB 2E
COMP-4
COMP-5 + 123451 30 39
- 123451 CF C7
PIC 9999 BINARY 1234 04 D2
COMP
COMP-4
COMP-5 600001 EA 60
Internal PIC S9999 PACKED-DECIMAL + 1234 01 23 4C
decimal COMP-3 - 1234 01 23 4D
PIC 9999 PACKED-DECIMAL + 1234 01 23 4F
COMP-3 - 1234 01 23 4F
Internal COMP-1 + 1234 43 4D 20 00
floating
point
Internal COMP-2 + 1234 43 4D 20 00 00 00 00 00
floating - 1234 C3 4D 20 00 00 00 00 00
point
External PIC +9(2).9(2)E+99 DISPLAY + 1234 4E F1 F2 4B F3
floating F4 C5 4E F0 F2
point
- 1234 60 F1 F2 4B F3
F4 C5 4E F0 F2

1. The example demonstrates that COMP-5 data items can contain values of magnitude up to the capacity of the
native binary representation (2, 4, or 8 bytes), rather than being limited to the value implied by the number of 9s
in the PICTURE clause.

Data format conversions


When the code in your program involves the interaction of items with different
data formats, the compiler converts these items as follows:
v Temporarily, for comparisons and arithmetic operations
v Permanently, for assignment to the receiver in a MOVE or COMPUTE statement

A conversion is actually a move of a value from one data item to another. The
compiler performs any conversions that are required during the execution of
arithmetic or comparisons with the same rules that are used for MOVE and COMPUTE
statements.

When possible, the compiler performs a move to preserve numeric value as


opposed to a direct digit-for-digit move.

Conversion generally requires additional storage and processing time because data
is moved to an internal work area and converted before the operation is
performed. The results might also have to be moved back into a work area and
converted again.

Chapter 3. Working with numbers and arithmetic 43


Conversions between fixed-point data formats (external decimal, packed decimal,
or binary) are without loss of precision as long as the target field can contain all
the digits of the source operand.

A loss of precision is possible in conversions between fixed-point data formats and


floating-point data formats (short floating point, long floating point, or external
floating point). These conversions happen during arithmetic evaluations that have
a mixture of both fixed-point and floating-point operands.

RELATED REFERENCES
“Conversions and precision”
“Sign representation and processing” on page 45

Conversions and precision


Because both fixed-point and external floating-point items have decimal
characteristics, references to fixed-point items in the following examples include
external floating-point items also unless stated otherwise.

When the compiler converts from fixed-point to internal floating-point format,


fixed-point numbers in base 10 are converted to the numbering system used
internally.

When the compiler converts short form to long form for comparisons, zeros are
used for padding the shorter number.

When a USAGE COMP-1 data item is moved to a fixed-point data item with more
than nine digits, the fixed-point data item will receive only nine significant digits,
and the remaining digits will be zero.

When a USAGE COMP-2 data item is moved to a fixed-point data item with more
than 18 digits, the fixed-point data item will receive only 18 significant digits, and
the remaining digits will be zero.

Conversions that preserve precision


If a fixed-point data item with six or fewer digits is moved to a USAGE COMP-1 data
item and then returned to the fixed-point data item, the original value is recovered.

If a USAGE COMP-1 data item is moved to a fixed-point data item of nine or more
digits and then returned to the USAGE COMP-1 data item, the original value is
recovered.

If a fixed-point data item with 15 or fewer digits is moved to a USAGE COMP-2 data
item and then returned to the fixed-point data item, the original value is recovered.

If a USAGE COMP-2 data item is moved to a fixed-point (not external floating-point)


data item of 18 or more digits and then returned to the USAGE COMP-2 data item,
the original value is recovered.

Conversions that result in rounding


If a USAGE COMP-1 data item, a USAGE COMP-2 data item, an external floating-point
data item, or a floating-point literal is moved to a fixed-point data item, rounding
occurs in the low-order position of the target data item.

If a USAGE COMP-2 data item is moved to a USAGE COMP-1 data item, rounding occurs
in the low-order position of the target data item.

44 Programming Guide
If a fixed-point data item is moved to an external floating-point data item and the
PICTURE of the fixed-point data item contains more digit positions than the PICTURE
of the external floating-point data item, rounding occurs in the low-order position
of the target data item.

RELATED CONCEPTS
Appendix A, “Intermediate results and arithmetic precision,” on page 603

Sign representation and processing


Sign representation affects the processing and interaction of your numeric data.

Given X’sd’, where s is the sign representation and d represents the digit, the valid
sign representations for external decimal (USAGE DISPLAY without the SIGN IS
SEPARATE clause) are:
Positive:
C, A, E, and F
Negative:
D and B

The COBOL NUMPROC compiler option affects sign processing for external decimal
and internal decimal data. NUMPROC has no effect on binary data or floating-point
data.

NUMPROC(PFD)
Given X’sd’, where s is the sign representation and d represents the digit, when you
use NUMPROC(PFD), the compiler assumes that the sign in your data is one of three
preferred signs:
Signed positive or 0:
X’C’
Signed negative:
X’D’
Unsigned or alphanumeric:
X’F’

Based on this assumption, the compiler uses whatever sign it is given to process
data. The preferred sign is generated only where necessary (for example, when
unsigned data is moved to signed data). Using the NUMPROC(PFD) option can save
processing time, but you must use preferred signs with your data for correct
processing.

NUMPROC(NOPFD)
When the NUMPROC(NOPFD) compiler option is in effect, the compiler accepts any
valid sign configuration. The preferred sign is always generated in the receiver.
NUMPROC(NOPFD) is less efficient than NUMPROC(PFD), but you should use it whenever
data that does not use preferred signs might exist.

If an unsigned, external-decimal sender is moved to an alphanumeric receiver, the


sign is unchanged (even with NUMPROC(NOPFD)).

Chapter 3. Working with numbers and arithmetic 45


NUMPROC(MIG)
When NUMPROC(MIG) is in effect, the compiler generates code that is similar to that
produced by OS/VS COBOL. This option can be especially useful if you migrate
OS/VS COBOL programs to IBM Enterprise COBOL for z/OS.

RELATED REFERENCES
“NUMPROC” on page 293

Checking for incompatible data (numeric class test)


The compiler assumes that the values you supply for a data item are valid for the
item’s PICTURE and USAGE clauses, and assigns the values without checking for
validity. When you give an item a value that is incompatible with its data
description, references to that item in the PROCEDURE DIVISION are undefined and
your results will be unpredictable.

It can happen that values are passed into your program and assigned to items that
have incompatible data descriptions for those values. For example, nonnumeric
data might be moved or passed into a field that is defined as numeric. Or a signed
number might be passed into a field that is defined as unsigned. In both cases, the
receiving fields contain invalid data. Ensure that the contents of a data item
conform to its PICTURE and USAGE clauses before using the data item in any further
processing steps.

You can use the numeric class test to perform data validation. For example:
Linkage Section.
01 Count-x Pic 999.
. . .
Procedure Division Using Count-x.
If Count-x is numeric then display “Data is good”

The numeric class test checks the contents of a data item against a set of values
that are valid for the particular PICTURE and USAGE of the data item. For example, a
packed-decimal item is checked for hexadecimal values X’0’ through X’9’ in the
digit positions, and for a valid sign value in the sign position (whether separate or
nonseparate).

For external decimal, external floating-point, and packed-decimal items, the


numeric class test is affected by the NUMPROC compiler option and the NUMCLS option
(which is set at installation time). To determine the NUMCLS setting used at your
installation, consult your system programmer.

If NUMCLS(PRIM) is in effect at your installation, use the following table to find the
values that the compiler considers valid for the sign.
Table 7. NUMCLS(PRIM) and valid signs
NUMPROC(NOPFD) NUMPROC(PFD) NUMPROC(MIG)
Signed C, D, F C, D, +0 (positive C, D, F
zero)
Unsigned F F F
Separate sign +, - +, -, +0 (positive +, -
zero)

46 Programming Guide
If NUMCLS(ALT) is in effect at your installation, use the following table to find the
values that the compiler considers valid for the sign.
Table 8. NUMCLS(ALT) and valid signs
NUMPROC(NOPFD) NUMPROC(PFD) NUMPROC(MIG)
Signed A to F C, D, +0 (positive A to F
zero)
Unsigned F F F
Separate sign +, - +, -, +0 (positive +, -
zero)

RELATED REFERENCES
“NUMPROC” on page 293

Performing arithmetic
You can use any of several COBOL language features to perform arithmetic:
v “COMPUTE and other arithmetic statements”
v “Arithmetic expressions” on page 48
v “Numeric intrinsic functions” on page 48
v “Math and date Language Environment services” on page 49

COMPUTE and other arithmetic statements


Use the COMPUTE statement for most arithmetic evaluations rather than ADD,
SUBTRACT, MULTIPLY, and DIVIDE statements. Often you can code one COMPUTE
statement instead of several individual statements.

The COMPUTE statement assigns the result of an arithmetic expression to one or


more data items:
Compute z = a + b / c ** d - e
Compute x y z = a + b / c ** d - e

Some arithmetic might be more intuitive using arithmetic statements other than
COMPUTE. For example:

COMPUTE Equivalent arithmetic statements

Compute Increment = Add 1 to Increment


Increment + 1

Compute Balance = Subtract Overdraft


Balance - Overdraft from Balance

Compute IncrementOne = Add 1 to IncrementOne,


IncrementOne + 1 IncrementTwo,
Compute IncrementTwo = IncrementThree
IncrementTwo + 1
Compute IncrementThree =
IncrementThree + 1

You might also prefer to use the DIVIDE statement (with its REMAINDER phrase) for
division in which you want to process a remainder. The REM intrinsic function also
provides the ability to process a remainder.

Chapter 3. Working with numbers and arithmetic 47


RELATED CONCEPTS
“Fixed-point versus floating-point arithmetic” on page 53
Appendix A, “Intermediate results and arithmetic precision,” on page 603

Arithmetic expressions
You can use arithmetic expressions in many (but not all) places in statements
where numeric data items are allowed. For example, you can use arithmetic
expressions as comparands in relation conditions:
If (a + b) > (c - d + 5) Then. . .

Arithmetic expressions can consist of a single numeric literal, a single numeric data
item, or a single intrinsic function reference. They can also consist of several of
these items connected by arithmetic operators. Arithmetic operators are evaluated
in the following order of precedence:
Table 9. Order of evaluation of arithmetic operators
Operator Meaning Order of evaluation
Unary + or - Algebraic sign First
** Exponentiation Second
/ or * Division or multiplication Third
Binary + or - Addition or subtraction Last

Operators at the same level of precedence are evaluated from left to right;
however, you can use parentheses to change the order of evaluation. Expressions
in parentheses are evaluated before the individual operators are evaluated.
Parentheses, necessary or not, make your program easier to read.

RELATED CONCEPTS
“Fixed-point versus floating-point arithmetic” on page 53
Appendix A, “Intermediate results and arithmetic precision,” on page 603

Numeric intrinsic functions


You can use numeric intrinsic functions only in places where numeric expressions
are allowed. These functions can save you time because you don’t have to code the
many common types of calculations that they provide.

Numeric intrinsic functions return a signed numeric value. They are treated as
temporary numeric data items.

Many of the capabilities of numeric intrinsic functions are also provided by


Language Environment callable services.

Numeric functions are classified into these categories:


Integer
Those that return an integer
Floating point
Those that return a long (64-bit) or extended-precision (128-bit)
floating-point value (depending on whether you compile using the default
option ARITH(COMPAT) or using ARITH(EXTEND))
Mixed Those that return an integer, a floating-point value, or a fixed-point
number with decimal places, depending on the arguments

48 Programming Guide
You can use intrinsic functions to perform several different arithmetic operations,
as outlined in the following table.
Table 10. Numeric intrinsic functions
Number handling Date and time Finance Mathematics Statistics
LENGTH CURRENT-DATE ANNUITY ACOS MEAN
MAX DATE-OF-INTEGER PRESENT-VALUE ASIN MEDIAN
MIN DATE-TO-YYYYMMDD ATAN MIDRANGE
NUMVAL DATEVAL COS RANDOM
NUMVAL-C DAY-OF-INTEGER FACTORIAL RANGE
ORD-MAX DAY-TO-YYYYDDD INTEGER STANDARD-DEVIATION
ORD-MIN INTEGER-OF-DATE INTEGER-PART VARIANCE
INTEGER-OF-DAY LOG
UNDATE LOG10
WHEN-COMPILED MOD
YEAR-TO-YYYY REM
YEARWINDOW SIN
SQRT
SUM
TAN

“Examples: numeric intrinsic functions” on page 51

Nesting functions and arithmetic expressions


You can reference one function as the argument of another. A nested function is
evaluated independently of the outer function, except when determining whether a
mixed function should be evaluated using fixed-point or floating-point
instructions.

You can also nest an arithmetic expression as an argument to a numeric function:


Compute x = Function Sum(a b (c / d))

In this example, there are only three function arguments: a, b, and the arithmetic
expression (c / d).

ALL subscripting and special registers


You can reference all the elements of a table (or array) as function arguments by
using the ALL subscript.

You can use the integer special registers as arguments wherever integer arguments
are allowed.

RELATED CONCEPTS
“Fixed-point versus floating-point arithmetic” on page 53
Appendix A, “Intermediate results and arithmetic precision,” on page 603

RELATED REFERENCES
“ARITH” on page 271

Math and date Language Environment services


Many of the capabilities of COBOL intrinsic functions are also provided by
Language Environment callable services. Language Environment callable services
provide a means of assigning arithmetic results to data items. They include
mathematical functions, and date and time operations.

Chapter 3. Working with numbers and arithmetic 49


Math-oriented callable services
For most COBOL intrinsic functions there are corresponding math-oriented callable
services you can use that produce the same results, as shown in the following
table. When you compile with the default option ARITH(COMPAT), COBOL
floating-point intrinsic functions return long (64-bit) results. When you compile
with option ARITH(EXTEND), COBOL floating-point intrinsic functions (with the
exception of RANDOM) return extended-precision (128-bit) results.

So for example (considering the first row of the table), if you compile using
ARITH(COMPAT), CEESDACS returns the same result as ACOS. If you compile using
ARITH(EXTEND), CEESQACS returns the same result as ACOS.
Table 11. Compatibility of math intrinsic functions and callable services
Corresponding Corresponding Results same for intrinsic
COBOL intrinsic long-precision Language extended-precision Language function and callable
function Environment callable service Environment callable service service?
ACOS CEESDACS CEESQACS Yes
ASIN CEESDASN CEESQASN Yes
ATAN CEESDATN CEESQATN Yes
COS CEESDCOS CEESQCOS Yes
LOG CEESDLOG CEESQLOG Yes
LOG10 CEESDLG1 CEESQLG1 Yes
1
RANDOM CEERAN0 none No
REM CEESDMOD CEESQMOD Yes
SIN CEESDSIN CEESQSIN Yes
SQRT CEESDSQT CEESQSQT Yes
TAN CEESDTAN CEESQTAN Yes

1. RANDOM returns a long (64-bit) floating-point result even if you pass it a 31-digit argument and compile using
option ARITH(EXTEND).

Both the RANDOM intrinsic function and CEERAN0 service generate random
numbers between zero and one. However, because each uses its own algorithm,
RANDOM and CEERAN0 produce different random numbers from the same seed.

Even for functions that produce the same results, how you use intrinsic functions
and Language Environment callable services differs. The rules for the data types
required for intrinsic function arguments are less restrictive. For numeric intrinsic
functions, you can use arguments that are of any numeric data type. When you
invoke a Language Environment callable service with a CALL statement, however,
you must ensure that the parameters match the numeric data types required by
that service (generally COMP-1 or COMP-2).

The error handling of intrinsic functions and Language Environment callable


services sometimes differs. If you pass an explicit feedback token when calling the
Language Environment math services, you must check the feedback code after
each call and take explicit action to deal with errors. However, if you call with the
feedback token explicitly OMITTED, you do not need to check the token; Language
Environment automatically signals any errors.

50 Programming Guide
Date callable services
Both the COBOL date intrinsic functions and the Language Environment date
callable services are based on the Gregorian calendar. However, the starting dates
can differ depending on the setting of the INTDATE compiler option. When the
default setting of INTDATE(ANSI) is in effect, COBOL uses January 1, 1601 as day 1.
When INTDATE(LILIAN) is in effect, COBOL uses October 15, 1582 as day 1.
Language Environment always uses October 15, 1582 as day 1.

This means that if you use INTDATE(LILIAN), you get equivalent results from
COBOL intrinsic functions and Language Environment callable date services.

The following table shows the results when INTDATE(ANSI) is in effect.


Table 12. INTDATE(ANSI) and compatibility of date intrinsic functions and callable
services
COBOL intrinsic Language Environment callable
function service Results
INTEGER-OF-DATE CEECBLDY Compatible
DATE-OF-INTEGER CEEDATE with picture string YYYYMMDD Incompatible
DAY-OF-INTEGER CEEDATE with picture string YYYYDDD Incompatible
INTEGER-OF-DATE CEEDAYS Incompatible

The following table shows the results when INTDATE(LILIAN) is in effect.


Table 13. INTDATE(LILIAN) and compatibility of date intrinsic functions and callable
services
COBOL intrinsic Language Environment callable
function service Results
DATE-OF-INTEGER CEEDATE with picture string YYYYMMDD Compatible
DAY-OF-INTEGER CEEDATE with picture string YYYYDDD Compatible
INTEGER-OF-DATE CEEDAYS Compatible
INTEGER-OF-DATE CEECBLDY Incompatible

RELATED CONCEPTS
“Fixed-point versus floating-point arithmetic” on page 53
Appendix A, “Intermediate results and arithmetic precision,” on page 603

RELATED TASKS
“Using Language Environment callable services” on page 597

RELATED REFERENCES
“ARITH” on page 271

Examples: numeric intrinsic functions


The following examples and accompanying explanations show intrinsic functions
in each of several categories.

General number handling


Suppose you want to find the maximum value of two prices (represented as
alphanumeric items with dollar signs), put this value into a numeric field in an

Chapter 3. Working with numbers and arithmetic 51


output record, and determine the length of the output record. You can use
NUMVAL-C (a function that returns the numeric value of an alphanumeric string) and
the MAX and LENGTH functions to do this:
01 X Pic 9(2).
01 Price1 Pic x(8) Value “$8000”.
01 Price2 Pic x(8) Value “$2000”.
01 Output-Record.
05 Product-Name Pic x(20).
05 Product-Number Pic 9(9).
05 Product-Price Pic 9(6).
. . .
Procedure Division.
Compute Product-Price =
Function Max (Function Numval-C(Price1) Function Numval-C(Price2))
Compute X = Function Length(Output-Record)

Additionally, to ensure that the contents in Product-Name are in uppercase letters,


you can use the following statement:
Move Function Upper-case (Product-Name) to Product-Name

Date and time


The following example shows how to calculate a due date that is 90 days from
today. The first eight characters returned by the CURRENT-DATE function represent
the date in a four-digit year, two-digit month, and two-digit day format (YYYYMMDD).
The date is converted to its integer value; then 90 is added to this value and the
integer is converted back to the YYYYMMDD format.
01 YYYYMMDD Pic 9(8).
01 Integer-Form Pic S9(9).
. . .
Move Function Current-Date(1:8) to YYYYMMDD
Compute Integer-Form = Function Integer-of-Date(YYYYMMDD)
Add 90 to Integer-Form
Compute YYYYMMDD = Function Date-of-Integer(Integer-Form)
Display ’Due Date: ’ YYYYMMDD

Finance
Business investment decisions frequently require computing the present value of
expected future cash inflows to evaluate the profitability of a planned investment.
The present value of an amount that you expect to receive at a given time in the
future is that amount, which, if invested today at a given interest rate, would
accumulate to that future amount.

For example, assume that a proposed investment of $1,000 produces a payment


stream of $100, $200, and $300 over the next three years, one payment per year
respectively. The following COBOL statements calculate the present value of those
cash inflows at a 10% interest rate:
01 Series-Amt1 Pic 9(9)V99 Value 100.
01 Series-Amt2 Pic 9(9)V99 Value 200.
01 Series-Amt3 Pic 9(9)V99 Value 300.
01 Discount-Rate Pic S9(2)V9(6) Value .10.
01 Todays-Value Pic 9(9)V99.
. . .
Compute Todays-Value =
Function
Present-Value(Discount-Rate Series-Amt1 Series-Amt2 Series-Amt3)

You can use the ANNUITY function in business problems that require you to
determine the amount of an installment payment (annuity) necessary to repay the
principal and interest of a loan. The series of payments is characterized by an
equal amount each period, periods of equal length, and an equal interest rate each

52 Programming Guide
period. The following example shows how you can calculate the monthly payment
required to repay a $15,000 loan in three years at a 12% annual interest rate (36
monthly payments, interest per month = .12/12):
01 Loan Pic 9(9)V99.
01 Payment Pic 9(9)V99.
01 Interest Pic 9(9)V99.
01 Number-Periods Pic 99.
. . .
Compute Loan = 15000
Compute Interest = .12
Compute Number-Periods = 36
Compute Payment =
Loan * Function Annuity((Interest / 12) Number-Periods)

Mathematics
The following COBOL statement demonstrates that you can nest intrinsic
functions, use arithmetic expressions as arguments, and perform previously
complex calculations simply:
Compute Z = Function Log(Function Sqrt (2 * X + 1)) + Function Rem(X 2)

Here in the addend the intrinsic function REM (instead of a DIVIDE statement with a
REMAINDER clause) returns the remainder of dividing X by 2.

Statistics
Intrinsic functions make calculating statistical information easier. Assume you are
analyzing various city taxes and want to calculate the mean, median, and range
(the difference between the maximum and minimum taxes):
01 Tax-S Pic 99v999 value .045.
01 Tax-T Pic 99v999 value .02.
01 Tax-W Pic 99v999 value .035.
01 Tax-B Pic 99v999 value .03.
01 Ave-Tax Pic 99v999.
01 Median-Tax Pic 99v999.
01 Tax-Range Pic 99v999.
. . .
Compute Ave-Tax = Function Mean (Tax-S Tax-T Tax-W Tax-B)
Compute Median-Tax = Function Median (Tax-S Tax-T Tax-W Tax-B)
Compute Tax-Range = Function Range (Tax-S Tax-T Tax-W Tax-B)

Fixed-point versus floating-point arithmetic


Many statements in a program could involve arithmetic. For example, each of the
following types of COBOL statements requires some arithmetic evaluation:
v General arithmetic
compute report-matrix-col = (emp-count ** .5) + 1
add report-matrix-min to report-matrix-max giving report-matrix-tot
v Expressions and functions
compute report-matrix-col = function sqrt(emp-count) + 1
compute whole-hours = function integer-part((average-hours) + 1)
v Arithmetic comparisons
if report-matrix-col < function sqrt(emp-count) + 1
if whole-hours not = function integer-part((average-hours) + 1)

How you code arithmetic in a program (whether an arithmetic statement, an


intrinsic function, an expression, or some combination of these nested within each
other) determines whether the evaluation is done in floating-point or fixed-point
arithmetic.

Chapter 3. Working with numbers and arithmetic 53


Floating-point evaluations
In general, if your arithmetic coding has either of the characteristics listed below, it
is evaluated in floating-point arithmetic:
v An operand or result field is floating point.
An operand is floating point if you code it as a floating-point literal or if you
code it as a data item that is defined as USAGE COMP-1, USAGE COMP-2, or external
floating point (USAGE DISPLAY with a floating-point PICTURE).
An operand that is a nested arithmetic expression or a reference to a numeric
intrinsic function results in floating-point arithmetic when any of the following
conditions is true:
– An argument in an arithmetic expression results in floating point.
– The function is a floating-point function.
– The function is a mixed function with one or more floating-point arguments.
v An exponent contains decimal places.
An exponent contains decimal places if you use a literal that contains decimal
places, give the item a PICTURE containing decimal places, or use an arithmetic
expression or function whose result has decimal places.

An arithmetic expression or numeric function yields a result with decimal places if


any operand or argument (excluding divisors and exponents) has decimal places.

Fixed-point evaluations
In general, if an arithmetic operation contains neither of the characteristics listed
above for floating point, the compiler causes it to be evaluated in fixed-point
arithmetic. In other words, arithmetic evaluations are handled as fixed point only if
all the operands are fixed point, the result field is defined to be fixed point, and
none of the exponents represent values with decimal places. Nested arithmetic
expressions and function references must also represent fixed-point values.

Arithmetic comparisons (relation conditions)


When you compare numeric expressions using a relational operator, the numeric
expressions (whether they are data items, arithmetic expressions, function
references, or some combination of these) are comparands in the context of the
entire evaluation. That is, the attributes of each can influence the evaluation of the
other: both expressions are evaluated in fixed point, or both are evaluated in
floating point. This is also true of abbreviated comparisons even though one
comparand does not explicitly appear in the comparison. For example:
if (a + d) = (b + e) and c

This statement has two comparisons: (a + d) = (b + e), and (a + d) = c.


Although (a + d) does not explicitly appear in the second comparison, it is a
comparand in that comparison. Therefore, the attributes of c can influence the
evaluation of (a + d).

The compiler handles comparisons (and the evaluation of any arithmetic


expressions nested in comparisons) in floating-point arithmetic if either comparand
is a floating-point value or resolves to a floating-point value.

The compiler handles comparisons (and the evaluation of any arithmetic


expressions nested in comparisons) in fixed-point arithmetic if both comparands
are fixed-point values or resolve to fixed-point values.

54 Programming Guide
Implicit comparisons (no relational operator used) are not handled as a unit,
however; the two comparands are treated separately as to their evaluation in
floating-point or fixed-point arithmetic. In the following example, five arithmetic
expressions are evaluated independently of one another’s attributes, and then are
compared to each other.
evaluate (a + d)
when (b + e) thru c
when (f / g) thru (h * i)
. . .
end-evaluate

“Examples: fixed-point and floating-point evaluations”

RELATED REFERENCES
“Arithmetic expressions in nonarithmetic statements” on page 611

Examples: fixed-point and floating-point evaluations


Assume you define the data items for an employee table in the following manner:
01 employee-table.
05 emp-count pic 9(4).
05 employee-record occurs 1 to 1000 times
depending on emp-count.
10 hours pic +9(5)e+99.
. . .
01 report-matrix-col pic 9(3).
01 report-matrix-min pic 9(3).
01 report-matrix-max pic 9(3).
01 report-matrix-tot pic 9(3).
01 average-hours pic 9(3)v9.
01 whole-hours pic 9(4).

These statements are evaluated using floating-point arithmetic:


compute report-matrix-col = (emp-count ** .5) + 1
compute report-matrix-col = function sqrt(emp-count) + 1
if report-matrix-tot < function sqrt(emp-count) + 1

These statements are evaluated using fixed-point arithmetic:


add report-matrix-min to report-matrix-max giving report-matrix-tot
compute report-matrix-max =
function max(report-matrix-max report-matrix-tot)
if whole-hours not = function integer-part((average-hours) + 1)

Using currency signs


Many programs need to process financial information and present that information
using the appropriate currency signs. With COBOL currency support (and the
appropriate code page for your printer or display unit), you can use one or more
of the following signs in a program:
v Symbols such as the dollar sign ($)
v Currency signs of more than one character (such as USD or EUR)
v Euro sign, established by the Economic and Monetary Union (EMU)

To specify the symbols for displaying financial information, use the CURRENCY SIGN
clause (in the SPECIAL-NAMES paragraph in the CONFIGURATION SECTION) with the
PICTURE characters that relate to the symbols. In the following example, the
PICTURE character $ indicates that the currency sign $US is to be used:

Chapter 3. Working with numbers and arithmetic 55


Currency Sign is “$US” with Picture Symbol “$”.
. . .
77 Invoice-Amount Pic $$,$$9.99.
. . .
Display “Invoice amount is ” Invoice-Amount.

In this example, if Invoice-Amount contained 1500.00, the display output would be:
Invoice amount is $US1,500.00

By using more than one CURRENCY SIGN clause in your program, you can allow for
multiple currency signs to be displayed.

You can use a hexadecimal literal to indicate the currency sign value. This could be
useful if the data-entry method for the source program does not allow the entry of
the intended characters easily. The following example shows the hexadecimal value
X’9F’ used as the currency sign:
Currency Sign X’9F’ with Picture Symbol ’U’.
. . .
01 Deposit-Amount Pic UUUUU9.99.

If there is no corresponding character for the euro sign on your keyboard, you
need to specify it as a hexadecimal value in the CURRENCY SIGN clause. The
hexadecimal value for the euro sign is either X’9F’ or X’5A’ depending on the code
page in use, as shown in the following table.
Table 14. Hexadecimal values of the euro sign
Code page Modified
| CCSID Applicable countries from Euro sign
1140 USA, Canada, Netherlands, Portugal, Australia, 037 X’9F’
New Zealand
1141 Austria, Germany 273 X’9F’
1142 Denmark, Norway 277 X’5A’
1143 Finland, Sweden 278 X’5A’
1144 Italy 280 X’9F’
1145 Spain, Latin America - Spanish 284 X’9F’
1146 UK 285 X’9F’
1147 France 297 X’9F’
1148 Belgium, Canada, Switzerland 500 X’9F’
1149 Iceland 871 X’9F’

“Example: multiple currency signs”

Example: multiple currency signs


The following example shows how you can display values in both euro currency
(as EUR) and Swiss francs (as CHF):
IDENTIFICATION DIVISION.
PROGRAM-ID. EuroSamp.
Environment Division.
Configuration Section.
Special-Names.
Currency Sign is “CHF ” with Picture Symbol “F”
Currency Sign is “EUR ” with Picture Symbol “U”.
Data Division.

56 Programming Guide
Working-Storage Section.
01 Deposit-in-Euro Pic S9999V99 Value 8000.00.
01 Deposit-in-CHF Pic S99999V99.
01 Deposit-Report.
02 Report-in-Franc Pic -FFFFF9.99.
02 Report-in-Euro Pic -UUUUU9.99.
. . .
01 EUR-to-CHF-Conv-Rate Pic 9V99999 Value 1.53893.
. . .
PROCEDURE DIVISION.
Report-Deposit-in-CHF-and-EUR.
Move Deposit-in-Euro to Report-in-Euro
. . .
Compute Deposit-in-CHF Rounded
= Deposit-in-Euro * EUR-to-CHF-Conv-Rate
On Size Error
Perform Conversion-Error
Not On Size Error
Move Deposit-in-CHF to Report-in-Franc
Display “Deposit in Euro = ” Report-in-Euro
Display “Deposit in Franc = ” Report-in-Franc
End-Compute
. . .
Goback.
Conversion-Error.
Display “Conversion error from EUR to CHF”
Display “Euro value: ” Report-in-Euro.

The above example produces the following display output:


Deposit in Euro = EUR 8000.00
Deposit in Franc = CHF 12311.44

The exchange rate used in this example is for illustrative purposes only.

Chapter 3. Working with numbers and arithmetic 57


58 Programming Guide
Chapter 4. Handling tables
A table is a collection of data items that have the same description, such as account
totals or monthly averages. A table is the COBOL equivalent of an array of
elements. It consists of a table name and subordinate items called table elements.

In the example above, SAMPLE-TABLE-ONE is the group item that contains the table.
TABLE-COLUMN names the table element of a one-dimensional table that occurs three
times.

Rather than define repetitious items as separate, consecutive entries in the DATA
DIVISION, you can use the OCCURS clause in the DATA DIVISION entry to define a
table. This practice has these advantages:
v The code clearly shows the unity of the items (the table elements).
v You can use subscripts and indexes to refer to the table elements.
v You can easily repeat data items.

Tables are important for increasing the speed of a program, especially one that
looks up records.

RELATED TASKS
“Defining a table (OCCURS)”
“Referring to an item in a table” on page 61
“Putting values into a table” on page 64
“Nesting tables” on page 60
“Creating variable-length tables (DEPENDING ON)” on page 68
“Searching a table” on page 71
“Processing table items using intrinsic functions” on page 73
“Handling tables efficiently” on page 583

Defining a table (OCCURS)


To code a table, give the table a group name and define a subordinate item (the
table element) that is to be repeated n times. table-name is the group name in the
following example:
01 table-name.
05 element-name OCCURS n TIMES.
. . . (subordinate items of the table element might follow)

The table element definition (which includes the OCCURS clause) is subordinate to
the group item that contains the table. The OCCURS clause cannot appear in a
level-01 description.

© Copyright IBM Corp. 1991, 2004 59


To create tables of two to seven dimensions, use nested OCCURS clauses.

RELATED TASKS
“Creating variable-length tables (DEPENDING ON)” on page 68
“Nesting tables”
“Putting values into a table” on page 64
“Referring to an item in a table” on page 61
“Searching a table” on page 71

RELATED REFERENCES
OCCURS clause (Enterprise COBOL Language Reference)

Nesting tables
To create a two-dimensional table, define a one-dimensional table in each
occurrence of another one-dimensional table. For example:

In SAMPLE-TABLE-TWO, TABLE-ROW is an element of a one-dimensional table that


occurs two times. TABLE-COLUMN is an element of a two-dimensional table that
occurs three times in each occurrence of TABLE-ROW.

To create a three-dimensional table, define a one-dimensional table in each


occurrence of another one-dimensional table, which is itself contained in each
occurrence of another one-dimensional table. For example:

In SAMPLE-TABLE-THREE, TABLE-DEPTH is an element of a one-dimensional table that


occurs two times. TABLE-ROW is an element of a two-dimensional table that occurs
two times within each occurrence of TABLE-DEPTH. TABLE-COLUMN is an element of a
three-dimensional table that occurs three times within each occurrence of
TABLE-ROW.

Subscripting
In a two-dimensional table, the two subscripts correspond to the row and column
numbers. In a three-dimensional table, the three subscripts correspond to the
depth, row, and column numbers.

60 Programming Guide
The following valid references to SAMPLE-TABLE-THREE use literal subscripts. The
spaces are required in the second example.
TABLE-COLUMN (2, 2, 1)
TABLE-COLUMN (2 2 1)

In either table reference, the first value (2) refers to the second occurrence within
TABLE-DEPTH, the second value (2) refers to the second occurrence within TABLE-ROW,
and the third value (1) refers to the first occurrence within TABLE-COLUMN.

The following reference to SAMPLE-TABLE-TWO uses variable subscripts. The reference


is valid if SUB1 and SUB2 are data names that contain positive integer values within
the range of the table.
TABLE-COLUMN (SUB1 SUB2)

Indexing
Consider the following three-dimensional table, SAMPLE-TABLE-FOUR:
01 SAMPLE-TABLE-FOUR
05 TABLE-DEPTH OCCURS 3 TIMES INDEXED BY INX-A.
10 TABLE-ROW OCCURS 4 TIMES INDEXED BY INX-B.
15 TABLE-COLUMN OCCURS 8 TIMES INDEXED BY INX-C PIC X(8).

Suppose you code the following relative indexing reference to SAMPLE-TABLE-FOUR:


TABLE-COLUMN (INX-A + 1, INX-B + 2, INX-C - 1)

This reference causes the following computation of the displacement to the


TABLE-COLUMN element:
(contents of INX-A) + (256 * 1)
+ (contents of INX-B) + (64 * 2)
+ (contents of INX-C) - (8 * 1)

This calculation is based on the following element lengths:


v Each occurrence of TABLE-DEPTH is 256 bytes in length (4 * 8 * 8).
v Each occurrence of TABLE-ROW is 64 bytes in length (8 * 8).
v Each occurrence of TABLE-COLUMN is 8 bytes in length.

RELATED TASKS
“Defining a table (OCCURS)” on page 59
“Referring to an item in a table”
“Putting values into a table” on page 64
“Creating variable-length tables (DEPENDING ON)” on page 68
“Searching a table” on page 71
“Processing table items using intrinsic functions” on page 73
“Handling tables efficiently” on page 583

RELATED REFERENCES
OCCURS clause (Enterprise COBOL Language Reference)

Referring to an item in a table


A table element has a collective name, but the individual items within it do not
have unique data names.

To refer to an item, you have a choice of three techniques:


v Use the data name of the table element, along with its occurrence number
(called a subscript) in parentheses. This technique is called subscripting.
Chapter 4. Handling tables 61
v Use the data name of the table element, along with a value (called an index) that
is added to the address of the table to locate an item (the displacement from the
beginning of the table). This technique is called indexing, or subscripting using
index-names.
v Use both subscripts and indexes together.

RELATED TASKS
“Indexing” on page 63
“Subscripting”

Subscripting
The lowest possible subscript value is 1, which points to the first occurrence of the
table element. In a one-dimensional table, the subscript corresponds to the row
number.

You can use a data-name or a literal for a subscript.

If a data item with a literal subscript is of fixed length, the compiler resolves the
location of the data item.

When you use a data-name as a variable subscript, you must describe the data
name as an elementary numeric integer. The most efficient format is COMPUTATIONAL
(COMP) with a PICTURE size smaller than five digits. You cannot use a subscript with
a data-name that is used as a subscript.

The code generated for the application resolves the location of a variable subscript
at run time.

You can increment or decrement a literal or variable subscript by a specified


integer amount. For example:
TABLE-COLUMN (SUB1 - 1, SUB2 + 3)

You can change part of a table element rather than the whole element. Simply refer
to the character position and length of the substring to be changed within the
subscripted element. For example:
01 ANY-TABLE.
05 TABLE-ELEMENT PIC X(10)
OCCURS 3 TIMES
VALUE “ABCDEFGHIJ”.
. . .
MOVE “??” TO TABLE-ELEMENT (1) (3 : 2).

The MOVE statement moves the value ?? into table element number 1, beginning at
character position 3, for a length of 2:

RELATED TASKS
“Indexing” on page 63

62 Programming Guide
“Putting values into a table” on page 64
“Searching a table” on page 71
“Handling tables efficiently” on page 583

Indexing
You create an index using OCCURS INDEXED BY.

For example:
05 TABLE-ITEM PIC X(8)
OCCURS 10 INDEXED BY INX-A.

The compiler calculates the value contained in the index as the occurrence number
(subscript) minus 1, multiplied by the length of the table element. Therefore, for
the fifth occurrence of TABLE-ITEM, the binary value contained in INX-A is (5 - 1) * 8,
or 32.

You can use this index to index another table only if both table descriptions have
the same number of table elements, and the table elements are the same length.

If you use USAGE IS INDEX to create an index, you can use the index data item with
any table. For example:
77 INX-B USAGE IS INDEX.
. . .
| SET INX-A TO 10
| SET INX-B TO INX-A.
| PERFORM VARYING INX-A FROM 1 BY 1 UNTIL INX-A > INX-B
| DISPLAY TABLE-ITEM (INX-A)
. . .
END-PERFORM.

| INX-A is used to traverse table TABLE-ITEM above, but could be used to traverse
| other tables also. INX-B is used to hold the index of the last element of the table.
| The advantage of this type of coding is that calculation of offsets of table elements
| is minimized, and no conversion is necessary for the UNTIL condition.

You can increment or decrement an index-name by an unsigned numeric literal.


The literal is considered to be an occurrence number. It is converted to an index
value before being added to or subtracted from the index-name.

Initialize the index-name with a SET, PERFORM VARYING, or SEARCH ALL statement.
You can then also use it in SEARCH or relational condition statements. To change the
value, use a PERFORM, SEARCH, or SET statement.

Use the SET statement to assign to an index the value that you stored in the index
data item defined by USAGE IS INDEX. For example, when you load records into a
variable-length table, you can store the index value of the last record read in a data
item defined as USAGE IS INDEX. Then you can test for the end of the table by
comparing the current index value with the index value of the last record. This
technique is useful when you look through or process the table.

Because you are comparing a physical displacement, you can use index data items
only in SEARCH and SET statements or for comparisons with indexes or other index
data items. You cannot use index data items as subscripts or indexes.

RELATED TASKS
“Subscripting” on page 62

Chapter 4. Handling tables 63


“Putting values into a table”
“Searching a table” on page 71
“Processing table items using intrinsic functions” on page 73
“Handling tables efficiently” on page 583

RELATED REFERENCES
INDEXED BY phrase (Enterprise COBOL Language Reference)
INDEX phrase (Enterprise COBOL Language Reference)

Putting values into a table


Use one of these methods to put values into a table:
v Load the table dynamically.
v Initialize the table (INITIALIZE statement).
v Assign values when you define the table (VALUE clause).

RELATED TASKS
“Loading a table dynamically”
“Loading a variable-length table” on page 69
“Initializing a table (INITIALIZE)”
“Assigning values when you define a table (VALUE)” on page 65
“Assigning values to a variable-length table” on page 70

Loading a table dynamically


If the initial values of your table are different with each execution of your
program, you can define the table without initial values. You can then read the
changed values into the table before your program refers to the table.

To load a table, use the PERFORM statement and either subscripting or indexing.

When reading data to load your table, test to make sure that the data does not
exceed the space allocated for the table. Use a named value (rather than a literal)
for the item count. Then, if you make the table bigger, you need to change only
one value, instead of all references to a literal.

“Example: PERFORM and subscripting” on page 66


“Example: PERFORM and indexing” on page 67

RELATED REFERENCES
PERFORM with VARYING phrase (Enterprise COBOL Language Reference)

Initializing a table (INITIALIZE)


You can load your table with a value during execution with the INITIALIZE
statement. For example, to fill a table with 3s, you can use this code:
INITIALIZE TABLE-ONE REPLACING NUMERIC DATA BY 3.

The INITIALIZE statement cannot load a variable-length table (one that was defined
using OCCURS DEPENDING ON).

RELATED REFERENCES
INITIALIZE statement (Enterprise COBOL Language Reference)

64 Programming Guide
Assigning values when you define a table (VALUE)
If your table contains stable values (such as days and months), set the specific
values the table holds when you define it.

See static values in tables in one of these ways:


v Initialize each table item individually.
v Initialize an entire table at the 01 level.
v Initialize all occurrences of a given table element to the same value.

Initializing each table item individually


If the table is small, you can use this technique:
1. Declare a record that contains the same items as are in the table.
2. Set the initial value of each item in a VALUE clause.
3. Code a REDEFINES entry to make the record into a table.

For example:
***********************************************************
*** E R R O R F L A G T A B L E ***
***********************************************************
01 Error-Flag-Table Value Spaces.
88 No-Errors Value Spaces.
05 Type-Error Pic X.
05 Shift-Error Pic X.
05 Home-Code-Error Pic X.
05 Work-Code-Error Pic X.
05 Name-Error Pic X.
05 Initials-Error Pic X.
05 Duplicate-Error Pic X.
05 Not-Found-Error Pic X.
01 Filler Redefines Error-Flag-Table.
05 Error-Flag Occurs 8 Times
Indexed By Flag-Index Pic X.

(In this example, the items could all be initialized with one VALUE clause at the 01
level, because each item is being initialized to the same value.)

To initialize larger tables, use MOVE, PERFORM, or INITIALIZE statements.

Initializing a table at the 01 level


Code a level-01 record and assign to it, through the VALUE clause, the contents of
the whole table. Then, in a subordinate level data item, use an OCCURS clause to
define the individual table items.

For example:
01 TABLE-ONE VALUE “1234”.
05 TABLE-TWO OCCURS 4 TIMES PIC X.

Initializing all occurrences of a table element


You can use the VALUE clause on a table element to initialize the element to the
indicated value. For example:
01 T2.
05 T-OBJ PIC 9 VALUE 3.
05 T OCCURS 5 TIMES
DEPENDING ON T-OBJ.
10 X PIC XX VALUE “AA”.
10 Y PIC 99 VALUE 19.
10 Z PIC XX VALUE “BB”.

Chapter 4. Handling tables 65


The above code causes all the X elements (1 through 5) to be initialized to AA, all
the Y elements (1 through 5) to be initialized to 19, and all the Z elements (1
through 5) to be initialized to BB. T-OBJ is then set to 3.

RELATED REFERENCES
REDEFINES clause (Enterprise COBOL Language Reference)
PERFORM statement (Enterprise COBOL Language Reference)
INITIALIZE statement (Enterprise COBOL Language Reference)
OCCURS clause (Enterprise COBOL Language Reference)

Example: PERFORM and subscripting


This example traverses an error flag table using subscripting until an error code
that has been set is found. If an error code is found, the corresponding error
message is moved to a print report field.
. . .
***********************************************************
*** E R R O R F L A G T A B L E ***
***********************************************************
01 Error-Flag-Table Value Spaces.
88 No-Errors Value Spaces.
05 Type-Error Pic X.
05 Shift-Error Pic X.
05 Home-Code-Error Pic X.
05 Work-Code-Error Pic X.
05 Name-Error Pic X.
05 Initials-Error Pic X.
05 Duplicate-Error Pic X.
05 Not-Found-Error Pic X.
01 Filler Redefines Error-Flag-Table.
05 Error-Flag Occurs 8 Times
77 ERROR-ON Pic X Value “E”.
Indexed By Flag-Index Pic X.
***********************************************************
*** E R R O R M E S S A G E T A B L E ***
***********************************************************
01 Error-Message-Table.
05 Filler Pic X(25) Value
“Transaction Type Invalid”.
05 Filler Pic X(25) Value
“Shift Code Invalid”.
05 Filler Pic X(25) Value
“Home Location Code Inval.”.
05 Filler Pic X(25) Value
“Work Location Code Inval.”.
05 Filler Pic X(25) Value
“Last Name - Blanks”.
05 Filler Pic X(25) Value
“Initials - Blanks”.
05 Filler Pic X(25) Value
“Duplicate Record Found”.
05 Filler Pic X(25) Value
“Commuter Record Not Found”.
01 Filler Redefines Error-Message-Table.
05 Error-Message Occurs 8 Times
Indexed By Message-Index Pic X(25).
. . .
PROCEDURE DIVISION.
. . .
Perform
Varying Sub From 1 By 1
Until No-Errors
If Error-Flag (Sub) = Error-On
Move Space To Error-Flag (Sub)

66 Programming Guide
Move Error-Message (Sub) To Print-Message
Perform 260-Print-Report
End-If
End-Perform
. . .

Example: PERFORM and indexing


This example traverses an error flag table using indexing until an error code that
has been set is found. If an error code is found, the corresponding error message is
moved to a print report field.
. . .
***********************************************************
*** E R R O R F L A G T A B L E ***
***********************************************************
01 Error-Flag-Table Value Spaces.
88 No-Errors Value Spaces.
05 Type-Error Pic X.
05 Shift-Error Pic X.
05 Home-Code-Error Pic X.
05 Work-Code-Error Pic X.
05 Name-Error Pic X.
05 Initials-Error Pic X.
05 Duplicate-Error Pic X.
05 Not-Found-Error Pic X.
01 Filler Redefines Error-Flag-Table.
05 Error-Flag Occurs 8 Times
Indexed By Flag-Index Pic X.
***********************************************************
*** E R R O R M E S S A G E T A B L E ***
***********************************************************
01 Error-Message-Table.
05 Filler Pic X(25) Value
“Transaction Type Invalid”.
05 Filler Pic X(25) Value
“Shift Code Invalid”.
05 Filler Pic X(25) Value
“Home Location Code Inval.”.
05 Filler Pic X(25) Value
“Work Location Code Inval.”.
05 Filler Pic X(25) Value
“Last Name - Blanks”.
05 Filler Pic X(25) Value
“Initials - Blanks”.
05 Filler Pic X(25) Value
“Duplicate Record Found”.
05 Filler Pic X(25) Value
“Commuter Record Not Found”.
01 Filler Redefines Error-Message-Table.
05 Error-Message Occurs 8 Times
Indexed By Message-Index Pic X(25).
. . .
PROCEDURE DIVISION.
. . .
Set Flag-Index To 1
Perform Until No-Errors
Search Error-Flag
When Error-Flag (Flag-Index) = Error-On
Move Space To Error-Flag (Flag-Index)
Set Message-Index To Flag-Index
Move Error-Message (Message-Index) To
Print-Message
Perform 260-Print-Report
End-Search
End-Perform
. . .

Chapter 4. Handling tables 67


Creating variable-length tables (DEPENDING ON)
If you do not know before run time how many times a table element occurs, you
need to set up a variable-length table definition. To do this, use the OCCURS
DEPENDING ON (ODO) clause. For example:
X OCCURS 1 TO 10 TIMES DEPENDING ON Y

In this example, X is called the ODO subject, and Y is the ODO object.

Two factors affect the successful manipulation of variable-length records:


v Correct calculation of record lengths
The length of the variable portions of a group item is the product of the object
of the DEPENDING ON phrase and the length of the subject of the OCCURS clause.
v Conformance of the data in the object of the OCCURS DEPENDING ON clause to its
PICTURE clause
If the content of the ODO object does not match its PICTURE clause, the program
could abnormally terminate. You must ensure that the ODO object correctly
specifies the current number of occurrences of table elements.

The following example shows a group item (REC-1) that contains both the subject
and object of the OCCURS DEPENDING ON clause. The way the length of the group
item is determined depends on whether it is sending or receiving data.
WORKING-STORAGE SECTION.
01 MAIN-AREA.
03 REC-1.
05 FIELD-1 PIC 9.
05 FIELD-2 OCCURS 1 TO 5 TIMES
DEPENDING ON FIELD-1 PIC X(05).
01 REC-2.
03 REC-2-DATA PIC X(50).

If you want to move REC-1 (the sending item in this case) to REC-2, the length of
REC-1 is determined immediately before the move, using the current value in
FIELD-1. If the content of FIELD-1 conforms to its PICTURE (that is, if FIELD-1
contains an external decimal item), the move can proceed based on the actual
length of REC-1. Otherwise, the result is unpredictable. You must ensure that the
ODO object has the correct value before you initiate the move.

When you do a move to REC-1 (the receiving item in this case), the length of REC-1
is determined using the maximum number of occurrences. In this example, that
would be five occurrences of FIELD-2, plus FIELD-1, for a length of 26 bytes.

In this case, you need not set the ODO object (FIELD-1) before referencing REC-1 as
a receiving item. However, the sending field’s ODO object (not shown) must be set
to a valid numeric value between 1 and 5 for the ODO object of the receiving field
to be validly set by the move.

However, if you do a move to REC-1 (again the receiving item) where REC-1 is
followed by a variably located group (a type of complex ODO), the actual length of
REC-1 is calculated immediately before the move. In the following example, REC-1
and REC-2 are in the same record, but REC-2 is not subordinate to REC-1 and is
therefore variably located:
01 MAIN-AREA
03 REC-1.
05 FIELD-1 PIC 9.
05 FIELD-3 PIC 9.

68 Programming Guide
05 FIELD-2 OCCURS 1 TO 5 TIMES
DEPENDING ON FIELD-1 PIC X(05).
03 REC-2.
05 FIELD-4 OCCURS 1 TO 5 TIMES
DEPENDING ON FIELD-3 PIC X(05).

When you do a MOVE to REC-1 in this case, the actual length of REC-1 is calculated
immediately before the move using the current value of the ODO object (FIELD-1).
The compiler issues a message letting you know that the actual length was used.
This case requires that you set the value of the ODO object before using the group
item as a receiving field.

The following example shows how to define a variable-length table when the ODO
object (here LOCATION-TABLE-LENGTH) is outside the group.
DATA DIVISION.
FILE SECTION.
FD LOCATION-FILE
RECORDING MODE F
BLOCK 0 RECORDS
RECORD 80 CHARACTERS
LABEL RECORD STANDARD.
01 LOCATION-RECORD.
05 LOC-CODE PIC XX.
05 LOC-DESCRIPTION PIC X(20).
05 FILLER PIC X(58).
. . .
WORKING-STORAGE SECTION.
01 FLAGS.
05 LOCATION-EOF-FLAG PIC X(5) VALUE SPACE.
88 LOCATION-EOF VALUE “FALSE”.
01 MISC-VALUES.
05 LOCATION-TABLE-LENGTH PIC 9(3) VALUE ZERO.
05 LOCATION-TABLE-MAX PIC 9(3) VALUE 100.
*****************************************************************
*** L O C A T I O N T A B L E ***
*** FILE CONTAINS LOCATION CODES. ***
*****************************************************************
01 LOCATION-TABLE.
05 LOCATION-CODE OCCURS 1 TO 100 TIMES
DEPENDING ON LOCATION-TABLE-LENGTH PIC X(80).

RELATED CONCEPTS
Appendix B, “Complex OCCURS DEPENDING ON,” on page 613

RELATED TASKS
“Assigning values to a variable-length table” on page 70
“Loading a variable-length table”
Enterprise COBOL Compiler and Run-Time Migration Guide

RELATED REFERENCES
OCCURS DEPENDING ON clause (Enterprise COBOL Language Reference)

Loading a variable-length table


You can use a do-until structure (a TEST AFTER loop) to control the loading of a
variable-length table. For example, after the following code runs,
LOCATION-TABLE-LENGTH contains the subscript of the last item in the table.
DATA DIVISION.
FILE SECTION.
FD LOCATION-FILE
RECORDING MODE F
BLOCK 0 RECORDS

Chapter 4. Handling tables 69


RECORD 80 CHARACTERS
LABEL RECORD STANDARD.
01 LOCATION-RECORD.
05 LOC-CODE PIC XX.
05 LOC-DESCRIPTION PIC X(20).
05 FILLER PIC X(58).
. . .
WORKING-STORAGE SECTION.
01 FLAGS.
05 LOCATION-EOF-FLAG PIC X(5) VALUE SPACE.
88 LOCATION-EOF VALUE “YES”.
01 MISC-VALUES.
05 LOCATION-TABLE-LENGTH PIC 9(3) VALUE ZERO.
05 LOCATION-TABLE-MAX PIC 9(3) VALUE 100.
*****************************************************************
*** L O C A T I O N T A B L E ***
*** FILE CONTAINS LOCATION CODES. ***
*****************************************************************
01 LOCATION-TABLE.
05 LOCATION-CODE OCCURS 1 TO 100 TIMES
DEPENDING ON LOCATION-TABLE-LENGTH PIC X(80).
. . .
PROCEDURE DIVISION.
. . .
Perform Test After
Varying Location-Table-Length From 1 By 1
Until Location-EOF
Or Location-Table-Length = Location-Table-Max
Move Location-Record To
Location-Code (Location-Table-Length)
Read Location-File
At End Set Location-EOF To True
End-Read
End-Perform

Assigning values to a variable-length table


You can use a VALUE clause on a group item that contains an OCCURS clause with the
DEPENDING ON phrase. Each subordinate structure that contains the DEPENDING ON
phrase is initialized using the maximum number of occurrences. If you define the
entire table with the DEPENDING ON phrase, all the elements are initialized using the
maximum defined value of the DEPENDING ON object.

If the ODO object has a VALUE clause, it is logically initialized after the ODO subject
has been initialized. For example, in the following code:
01 TABLE-THREE VALUE “3ABCDE”.
05 X PIC 9.
05 Y OCCURS 5 TIMES
DEPENDING ON X PIC X.

the ODO subject Y(1) is initialized to ’A’, Y(2) to ’B’, . . ., Y(5) to ’E’, and finally
the ODO object X is initialized to 3. Any subsequent reference to TABLE-THREE (such
as in a DISPLAY statement) refers to the first three elements, Y(1) through Y(3).

RELATED TASKS
Enterprise COBOL Compiler and Run-Time Migration Guide

RELATED REFERENCES
OCCURS DEPENDING ON clause (Enterprise COBOL Language Reference)

70 Programming Guide
Searching a table
COBOL provides two search techniques for tables: serial and binary.

To do serial searches, use SEARCH and indexing. For variable-length tables, you can
use PERFORM with subscripting or indexing.

To do binary searches, use SEARCH ALL and indexing.

A binary search can be considerably more efficient than a serial search. For a serial
search, the number of comparisons is of the order of n, the number of entries in
the table. For a binary search, the number of comparisons is only of the order of
the logarithm (base 2) of n. A binary search, however, requires that the table items
already be sorted.

RELATED TASKS
“Doing a serial search (SEARCH)”
“Doing a binary search (SEARCH ALL)” on page 72

Doing a serial search (SEARCH)


Use the SEARCH statement to do a serial search beginning at the current index
setting. To modify the index setting, use the SET statement.

The conditions in the WHEN option are evaluated in the order in which they appear:
v If none of the conditions is satisfied, the index is increased to correspond to the
next table element, and the WHEN conditions are evaluated again.
v If one of the WHEN conditions is satisfied, the search ends. The index remains
pointing to the table element that satisfied the condition.
v If the entire table has been searched and no conditions were met, the AT END
imperative statement is executed if there is one. If you do not use AT END,
control passes to the next statement in your program.

You can reference only one level of a table (a table element) with each SEARCH
statement. To search multiple levels of a table, use nested SEARCH statements.
Delimit each nested SEARCH statement with END-SEARCH.

If the found condition comes after some intermediate point in the table, you can
speed up the search. Use the SET statement to set the index to begin the search
after that point.

Arranging the table so that the data used most often is at the beginning also
enables more efficient serial searching. If the table is large and is presorted, a
binary search is more efficient.

“Example: serial search”

RELATED REFERENCES
SEARCH statement (Enterprise COBOL Language Reference)

Example: serial search


Suppose you define a three-dimensional table, each with its own index (set to 1, 4,
and 1, respectively). The innermost table (TABLE-ENTRY3) has an ascending key. The
object of the search is to find a particular string in the innermost table.

Chapter 4. Handling tables 71


01 TABLE-ONE.
05 TABLE-ENTRY1 OCCURS 10 TIMES
INDEXED BY TE1-INDEX.
10 TABLE-ENTRY2 OCCURS 10 TIMES
INDEXED BY TE2-INDEX.
15 TABLE-ENTRY3 OCCURS 5 TIMES
ASCENDING KEY IS KEY1
INDEXED BY TE3-INDEX.
20 KEY1 PIC X(5).
20 KEY2 PIC X(10).
. . .
PROCEDURE DIVISION.
. . .
SET TE1-INDEX TO 1
SET TE2-INDEX TO 4
SET TE3-INDEX TO 1
MOVE “A1234” TO KEY1 (TE1-INDEX, TE2-INDEX, TE3-INDEX + 2)
MOVE “AAAAAAAA00” TO KEY2 (TE1-INDEX, TE2-INDEX, TE3-INDEX + 2)
. . .
SEARCH TABLE-ENTRY3
AT END
MOVE 4 TO RETURN-CODE
WHEN TABLE-ENTRY3(TE1-INDEX, TE2-INDEX, TE3-INDEX)
= “A1234AAAAAAAA00”
MOVE 0 TO RETURN-CODE
END-SEARCH

Values after execution:


TE1-INDEX = 1
TE2-INDEX = 4
TE3-INDEX points to the TABLE-ENTRY3 item
that equals “A1234AAAAAAAA00”
RETURN-CODE = 0

Doing a binary search (SEARCH ALL)


When you use SEARCH ALL to do a binary search, you do not need to set the index
before you begin. The index used is always the one associated with the first index
name in the OCCURS clause. The index varies during execution to maximize the
search efficiency.

To use the SEARCH ALL statement, your table must already be ordered on the key or
keys coded in the OCCURS clause. You can use any key in the WHEN condition, but
you must test all preceding data-names in the KEY option, if any. The test must be
an equal-to condition, and the KEY data-name must be either the subject of the
condition or the name of a conditional variable with which the tested
condition-name is associated. The WHEN condition can also be a compound
condition, formed from simple conditions with AND as the only logical connective.
The key and its object of comparison must be compatible.

“Example: binary search”

RELATED REFERENCES
SEARCH statement (Enterprise COBOL Language Reference)

Example: binary search


Suppose you define a table that contains 90 elements of 40 bytes each, with three
keys. The primary and secondary keys (KEY-1 and KEY-2) are in ascending order,
but the least significant key (KEY-3) is in descending order:
01 TABLE-A.
05 TABLE-ENTRY OCCURS 90 TIMES
ASCENDING KEY-1, KEY-2

72 Programming Guide
DESCENDING KEY-3
INDEXED BY INDX-1.
10 PART-1 PIC 99.
10 KEY-1 PIC 9(5).
10 PART-2 PIC 9(6).
10 KEY-2 PIC 9(4).
10 PART-3 PIC 9(18).
10 KEY-3 PIC 9(5).

You can search this table using the following instructions:


SEARCH ALL TABLE-ENTRY
AT END
PERFORM NOENTRY
WHEN KEY-1 (INDX-1) = VALUE-1 AND
KEY-2 (INDX-1) = VALUE-2 AND
KEY-3 (INDX-1) = VALUE-3
MOVE PART-1 (INDX-1) TO OUTPUT-AREA
END-SEARCH

If an entry is found in which the three keys are equal to the given values (VALUE-1,
VALUE-2, and VALUE-3), PART-1 of that entry will be moved to OUTPUT-AREA. If
matching keys are not found in any of the entries in TABLE-A, the NOENTRY routine
is performed.

Processing table items using intrinsic functions


You can use an intrinsic function to process an alphanumeric or numeric table
item. However, the data description of the table item must be compatible with the
argument requirements for the function.

Use a subscript or index to reference an individual data item as a function


argument. For example, assuming Table-One is a 3x3 array of numeric items, you
can find the square root of the middle element with this statement:
Compute X = Function Sqrt(Table-One(2,2))

You might often need to process the data in tables iteratively. For intrinsic
functions that accept multiple arguments, you can use the ALL subscript to
reference all the items in the table or a single dimension of the table. The iteration
is handled automatically, making your code shorter and simpler.

You can mix scalars and array arguments for functions that accept multiple
arguments:
Compute Table-Median = Function Median(Arg1 Table-One(ALL))

“Example: intrinsic functions”

RELATED TASKS
“Using intrinsic functions (built-in functions)” on page 32

RELATED REFERENCES
Intrinsic functions (Enterprise COBOL Language Reference)

Example: intrinsic functions


This example sums a cross-section of Table-Two:
Compute Table-Sum = FUNCTION SUM (Table-Two(ALL, 3, ALL))

Chapter 4. Handling tables 73


Assuming that Table-Two is a 2x3x2 array, the statement above causes the
following elements to be summed:
Table-Two(1,3,1)
Table-Two(1,3,2)
Table-Two(2,3,1)
Table-Two(2,3,2)

This example computes values for all employees.


01 Employee-Table.
05 Emp-Count Pic s9(4) usage binary.
05 Emp-Record Occurs 1 to 500 times
depending on Emp-Count.
10 Emp-Name Pic x(20).
10 Emp-Idme Pic 9(9).
10 Emp-Salary Pic 9(7)v99.
. . .
Procedure Division.
Compute Max-Salary = Function Max(Emp-Salary(ALL))
Compute I = Function Ord-Max(Emp-Salary(ALL))
Compute Avg-Salary = Function Mean(Emp-Salary(ALL))
Compute Salary-Range = Function Range(Emp-Salary(ALL))
Compute Total-Payroll = Function Sum(Emp-Salary(ALL))

74 Programming Guide
Chapter 5. Selecting and repeating program actions
Use COBOL control language to choose program actions based on the outcome of
logical tests, to iterate over selected parts of your program and data, and to
identify statements to be performed as a group. These controls include:
v IF statement
v EVALUATE statement
v Switches and flags
v PERFORM statement

RELATED TASKS
“Selecting program actions”
“Repeating program actions” on page 83

Selecting program actions


You can provide for different program actions depending on the tested value of
one or more data items.

The IF and EVALUATE statements in COBOL test one or more data items by means
of a conditional expression.

RELATED TASKS
“Coding a choice of actions”
“Coding conditional expressions” on page 79

RELATED REFERENCES
IF statement (Enterprise COBOL Language Reference)
EVALUATE statement (Enterprise COBOL Language Reference)

Coding a choice of actions


Use IF . . . ELSE to code a choice between two processing actions. (The word
THEN is optional in a COBOL program.)
IF condition-p
statement-1
ELSE
statement-2
END-IF

When one of the processing choices is no action, code the IF statement with or
without ELSE. Because the ELSE clause is optional, you can code the following:
IF condition-q
statement-1
END-IF

This coding is suitable for simple programming cases. For complex logic, you
probably need to use the ELSE clause. For example, suppose you have nested IF
statements with an action for only one of the processing choices; you could use the
ELSE clause and code the null branch of the IF statement with the CONTINUE
statement:

© Copyright IBM Corp. 1991, 2004 75


IF condition-q
statement-1
ELSE
CONTINUE
END-IF

Use the EVALUATE statement to code a choice among three or more possible
conditions instead of just two. The EVALUATE statement is an expanded form of the
IF statement that allows you to avoid nesting IF statements for such coding, a
common source of logic errors and debugging problems.

With the EVALUATE statement, you can test any number of conditions in a single
statement and have separate actions for each. In structured programming terms,
this is a case structure. It can also be thought of as a decision table.

“Example: EVALUATE using THRU phrase” on page 78


“Example: EVALUATE using multiple WHEN statements” on page 78
“Example: EVALUATE testing several conditions” on page 78

RELATED TASKS
“Coding conditional expressions” on page 79
“Using the EVALUATE statement” on page 77
“Using nested IF statements”

Using nested IF statements


When an IF statement has another IF statement as one of its possible processing
branches, these IF statements are said to be nested. Theoretically, there is no limit
to the depth of nested IF statements. However, when the program has to test a
variable for more than two values, EVALUATE is the better choice.

Use nested IF statements sparingly. The logic can be difficult to follow, although
explicit scope terminators and proper indentation help.

The following pseudocode depicts a nested IF statement:


IF condition-p
IF condition-q
statement-1
ELSE
statement-2
END-IF
statement-3
ELSE
statement-4
END-IF

Here an IF is nested, along with a sequential structure, in one branch of another


IF. In a structure like this, the END-IF closing the inner nested IF is very important.
Use END-IF instead of a period, because a period would end the outer IF structure
as well.

The following figure shows the logic structure for nested IF statements.

76 Programming Guide
RELATED TASKS
“Coding a choice of actions” on page 75

RELATED REFERENCES
Explicit scope terminators (Enterprise COBOL Language Reference)

Using the EVALUATE statement


Use the EVALUATE statement to test several conditions and design a different action
for each, a construct often known as a case structure. The expressions to be tested
are called selection subjects; the answer selected is called a selection object. You can
code multiple subjects and multiple objects in the same structure.

You can code the EVALUATE statement to handle the case where multiple conditions
lead to the same processing by using the THRU phrase and by using multiple WHEN
statements.

When evaluated, each pair of selection subjects and selection objects must belong
to the same class (numeric, character, CONDITION TRUE or FALSE).

The execution of the EVALUATE statement ends when:


v The statements associated with the selected WHEN phrase are performed.
v The statements associated with the WHEN OTHER phrase are performed.
v No WHEN conditions are satisfied.

WHEN phrases are tested in the order they are coded. Therefore, you should order
these phrases for the best performance: code first the WHEN phrase containing
selection objects most likely to be satisfied, then the next most likely, and so on. An
exception is the WHEN OTHER phrase, which must come last.

RELATED TASKS
“Coding a choice of actions” on page 75

Chapter 5. Selecting and repeating program actions 77


Example: EVALUATE using THRU phrase: This example shows how you can use
the THRU phrase to easily code several conditions in a range of values that lead to
the same processing action. In this example, CARPOOL-SIZE is the selection subject;
1, 2, and 3 THRU 6 are the selection objects.
EVALUATE CARPOOL-SIZE
WHEN 1
MOVE “SINGLE” TO PRINT-CARPOOL-STATUS
WHEN 2
MOVE “COUPLE” TO PRINT-CARPOOL-STATUS
WHEN 3 THRU 6
MOVE “SMALL GROUP” TO PRINT-CARPOOL STATUS
WHEN OTHER
MOVE “BIG GROUP” TO PRINT-CARPOOL STATUS
END-EVALUATE

The following nested IF statements represent the same logic:


IF CARPOOL-SIZE = 1 THEN
MOVE “SINGLE” TO PRINT-CARPOOL-STATUS
ELSE
IF CARPOOL-SIZE = 2 THEN
MOVE “COUPLE” TO PRINT-CARPOOL-STATUS
ELSE
IF CARPOOL-SIZE >= 3 and CARPOOL-SIZE <= 6 THEN
MOVE “SMALL GROUP” TO PRINT-CARPOOL-STATUS
ELSE
MOVE “BIG GROUP” TO PRINT-CARPOOL-STATUS
END-IF
END-IF
END-IF

Example: EVALUATE using multiple WHEN statements: You can use multiple
WHEN statements when several conditions lead to the same processing action. This
gives you more flexibility than using the THRU phrase, because the conditions do
not have to evaluate to values that fall in a range or evaluate to alphanumeric
values.
EVALUATE MARITAL-CODE
WHEN “M”
ADD 2 TO PEOPLE-COUNT
WHEN “S”
WHEN “D”
WHEN “W”
ADD 1 TO PEOPLE-COUNT
END-EVALUATE

The following nested IF statements represent the same logic:


IF MARITAL-CODE = “M” THEN
ADD 2 TO PEOPLE-COUNT
ELSE
IF MARITAL-CODE = “S” OR
MARITAL-CODE = “D” OR
MARITAL-CODE = “W” THEN
ADD 1 TO PEOPLE-COUNT
END-IF
END-IF

Example: EVALUATE testing several conditions: In this example both selection


subjects in a WHEN phrase must satisfy the TRUE, TRUE condition before the phrase is
performed. If both subjects do not evaluate to TRUE, the next WHEN phrase is
processed.
Identification Division.
Program-ID. MiniEval.
Environment Division.

78 Programming Guide
Configuration Section.
Source-Computer. IBM-390.
Data Division.
Working-Storage Section.
01 Age Pic 999.
01 Sex Pic X.
01 Description Pic X(15).
01 A Pic 999.
01 B Pic 9999.
01 C Pic 9999.
01 D Pic 9999.
01 E Pic 99999.
01 F Pic 999999.
Procedure Division.
PN01.
Evaluate True Also True
When Age < 13 Also Sex = “M”
Move “Young Boy” To Description
When Age < 13 Also Sex = “F”
Move “Young Girl” To Description
When Age > 12 And Age < 20 Also Sex = “M”
Move “Teenage Boy” To Description
When Age > 12 And Age < 20 Also Sex = “F”
Move “Teenage Girl” To Description
When Age > 19 Also Sex = “M”
Move “Adult Man” To Description
When Age > 19 Also Sex = “F”
Move “Adult Woman” To Description
When Other
Move “Invalid Data” To Description
End-Evaluate
Evaluate True Also True
When A + B < 10 Also C = 10
Move “Case 1” To Description
When A + B > 50 Also C = ( D + E ) / F
Move “Case 2” To Description
When Other
Move “Case Other” To Description
End-Evaluate
Stop Run.

Coding conditional expressions


Using the IF and EVALUATE statements, you can code program actions that will be
performed depending on the truth value of a conditional expression. The following
are some of the conditions that you can specify:
v Relation conditions, such as:
– Numeric comparisons
– Alphanumeric comparisons
– DBCS comparisons
– National comparisons
v Class conditions; for example, to test whether a data item:
– IS NUMERIC
– IS ALPHABETIC
– IS DBCS
– IS KANJI
– IS NOT KANJI
v Condition-name conditions, to test the value of a conditional variable that you
define

Chapter 5. Selecting and repeating program actions 79


v Sign condition, to test whether a numeric operand IS POSITIVE, NEGATIVE, or
ZERO
v Switch-status condition, to test the status of UPSI switches that you name in the
SPECIAL-NAMES paragraph
v Complex conditions, such as:
– Negated conditions; for example, NOT (A IS EQUAL TO B)
– Combined conditions (conditions combined with logical operators AND or OR)

RELATED CONCEPTS
“Switches and flags”

RELATED TASKS
“Defining switches and flags”
“Resetting switches and flags” on page 81
“Checking for incompatible data (numeric class test)” on page 46
“Comparing national data items” on page 111

RELATED REFERENCES
Rules for condition-name values (Enterprise COBOL Language Reference)
Switch-status condition (Enterprise COBOL Language Reference)
Sign condition (Enterprise COBOL Language Reference)
Comparing numeric and alphanumeric operands (Enterprise COBOL Language
Reference)
Combined conditions (Enterprise COBOL Language Reference)
Class condition (Enterprise COBOL Language Reference)

Switches and flags


Some program decisions are based on whether the value of a data item is true or
false, on or off, yes or no. Control these two-way decisions with level-88 items
with meaningful names (condition-names) to act as switches.

Other program decisions depend on the particular value or range of values of a


data item. When you use condition-names to give more than just on or off values
to a field, the field is generally referred to as a flag.

Flags and switches make your code easier to change. If you need to change the
values for a condition, you have to change only the value of that level-88
condition-name.

For example, suppose a program uses a condition-name to test a field for a given
salary range. If the program must be changed to check for a different salary range,
you need to change only the value of the condition-name in the DATA DIVISION.
You do not need to make changes in the PROCEDURE DIVISION.

RELATED TASKS
“Defining switches and flags”
“Resetting switches and flags” on page 81

Defining switches and flags


In the DATA DIVISION, define level-88 items to give meaningful names (condition
names) to values that will act as switches or flags.

To test for more than two values, as flags, assign more than one condition name to
a field by using multiple level-88 items.

80 Programming Guide
The reader can easily follow your code if you choose meaningful condition names
and if the values assigned have some association with logical values.

“Example: switches”
“Example: flags”

Example: switches
To test for an end-of-file condition for an input file named Transaction-File, you
could use the following data definitions:
WORKING-STORAGE Section.
01 Switches.
05 Transaction-EOF-Switch Pic X value space.
88 Transaction-EOF value “y”.

The level-88 description says a condition named Transaction-EOF is turned on


when Transaction-EOF-Switch has value ’y’. Referencing Transaction-EOF in your
PROCEDURE DIVISION expresses the same condition as testing for
Transaction-EOF-Switch = “y”. For example, the following statement causes the
report to be printed only if your program has read to the end of the
Transaction-File and if the Transaction-EOF-Switch has been set to ’y’:
If Transaction-EOF Then
Perform Print-Report-Summary-Lines

Example: flags
Consider a program that updates a master file. The updates are read from a
transaction file. The transaction file’s records contain a field for the function to be
performed: add, change, or delete. In the record description of the input file code a
field for the function code using level-88 items:
01 Transaction-Input Record
05 Transaction-Type Pic X.
88 Add-Transaction Value “A”.
88 Change-Transaction Value “C”.
88 Delete-Transaction Value “D”.

The code in the PROCEDURE DIVISION for testing these condition-names might look
like this:
Evaluate True
When Add-Transaction
Perform Add-Master-Record-Paragraph
When Change-Transaction
Perform Update-Exisitng-Record-Paragraph
When Delete-Transaction
Perform Delete-Master-Record-Paragraph
End-Evaluate

Resetting switches and flags


Throughout your program, you might need to reset switches or change flags back
to the original values they have in their data descriptions. To do so, use either a
SET statement or define your own data item to use.

When you use the SET condition-name TO TRUE statement, the switch or flag is set
back to the original value that was assigned in its data description.

For a level-88 item with multiple values, SET condition-name TO TRUE assigns the
first value (here, A):
88 Record-is-Active Value “A” “O” “S”

Chapter 5. Selecting and repeating program actions 81


Using the SET statement and meaningful condition-names makes it easy for the
reader to follow your code.

“Example: set switch on”


“Example: set switch off”

Example: set switch on


The SET statement in the following example does the same thing as Move “y” to
Transaction-EOF-Switch:
01 Switches
05 Transaction-EOF-Switch Pic X Value space.
88 Transaction-EOF Value “y”.
. . .
Procedure Division.
000-Do-Main-Logic.
Perform 100-Initialize-Paragraph
Read Update-Transaction-File
At End Set Transaction-EOF to True
End-Read

The following example shows how to assign a value for a field in an output record
based on the transaction code of an input record.
01 Input-Record.
05 Transaction-Type Pic X(9).
. . .
01 Data-Record-Out.
05 Data-Record-Type Pic X.
88 Record-Is-Active Value “A”.
88 Record-Is-Suspended Value “S”.
88 Record-Is-Deleted Value “D”.
05 Key-Field Pic X(5).
. . .
Procedure Division.
. . .
Evaluate Transaction-Type of Input-Record
When “ACTIVE”
Set Record-Is-Active to TRUE
When “SUSPENDED”
Set Record-Is-Suspended to TRUE
When “DELETED”
Set Record-Is-Deleted to TRUE
End-Evaluate

Example: set switch off


You could use a data item called SWITCH-OFF throughout your program to set
on/off switches to off, as in the following code:
01 Switches
05 Transaction-EOF-Switch Pic X Value space.
88 Transaction-EOF Value “y”.
01 SWITCH-OFF Pic X Value “n”.
. . .
Procedure Division.
. . .
Move SWITCH-OFF to Transaction-EOF-Switch

This code resets the switch to indicate that the end of the file has not been reached.

82 Programming Guide
Repeating program actions
Use the PERFORM statement to run a paragraph and then implicitly return control to
the next executable statement. In effect, the PERFORM statement is a way of coding a
closed subroutine that you can enter from many different parts of the program.

Use the PERFORM statement to loop (repeat the same code) a set number of times or
to loop based on the outcome of a decision.

PERFORM statements can be inline or out-of-line.

RELATED TASKS
“Choosing inline or out-of-line PERFORM”
“Coding a loop” on page 84
“Coding a loop through a table” on page 85
“Executing multiple paragraphs or sections” on page 85

RELATED REFERENCES
PERFORM statement (Enterprise COBOL Language Reference)

Choosing inline or out-of-line PERFORM


The inline PERFORM statement has the same general rules as the out-of-line PERFORM
statement except for one area: statements within the inline PERFORM statement are
executed rather than those within the range of the procedure named in the
out-of-line PERFORM statement.

To determine whether to code an inline or out-of-line PERFORM statement, consider


the following questions:
v Is the PERFORM statement used from several places?
Use out-of-line PERFORM when you use the same piece of code from several
places in your program.
v Which placement of the statement will be easier to read?
Use an out-of-line PERFORM if the logical flow of the program will be less clear
because the PERFORM extends over several screens. If, however, the PERFORM
paragraph is short, an inline PERFORM can save the trouble of skipping around in
the code.
v What are the efficiency tradeoffs?
Avoid the overhead of branching around an out-of-line PERFORM if performance is
an issue. But remember, even out-of-line PERFORM coding can improve code
optimization, so efficiency gains should not be overemphasized.

In the 1974 COBOL standard, the PERFORM statement is out-of-line and thus requires
an explicit branch to a separate paragraph and has an implicit return. If the
performed paragraph is in the subsequent sequential flow of your program, it is
also executed in that flow of the logic. To avoid this additional execution, you
must place the paragraph outside the normal sequential flow (for example, after
the GOBACK) or code a branch around it.

The subject of an inline PERFORM is an imperative statement. Therefore, you must


code statements (other than imperative statements within an inline PERFORM) with
explicit scope terminators. Each paragraph performs one logical function.

“Example: inline PERFORM statement” on page 84

Chapter 5. Selecting and repeating program actions 83


Example: inline PERFORM statement
This example shows the structure of an inline PERFORM statement with the required
scope terminators and the required END-PERFORM statement.
Perform 100-Initialize-Paragraph
* The following is an inline PERFORM
Perform Until Transaction-EOF
Read Update-Transaction-File Into WS-Transaction-Record
At End
Set Transaction-EOF To True
Not At End
Perform 200-Edit-Update-Transaction
If No-Errors
Perform 300-Update-Commuter-Record
Else
Perform 400-Print-Transaction-Errors
* End-If is a required scope terminator
End-If
Perform 410-Re-Initialize-Fields
* End-Read is a required scope terminator
End-Read
End-Perform

Coding a loop
Use the PERFORM . . . TIMES statement to execute a paragraph a certain number of
times:
PERFORM 010-PROCESS-ONE-MONTH 12 TIMES
INSPECT . . .

When control reaches the PERFORM statement, the code for the paragraph
010-PROCESS-ONE-MONTH is executed 12 times before control is transferred to the
INSPECT statement.

Use the PERFORM . . . UNTIL statement to execute a paragraph until a condition


you choose is satisfied. You can use either of the following forms:
PERFORM . . . WITH TEST AFTER . . . UNTIL . . .
PERFORM . . . [WITH TEST BEFORE] . . . UNTIL . . .

Use the PERFORM . . . WITH TEST AFTER . . . UNTIL if you want to execute the
paragraph at least once and then test before any subsequent execution. This
statement is equivalent to the do-until structure:

In the following example, the implicit WITH TEST BEFORE phrase provides a
do-while structure:
PERFORM 010-PROCESS-ONE-MONTH
UNTIL MONTH GREATER THAN 12
INSPECT . . .

When control reaches the PERFORM statement, the condition (MONTH EQUAL DECEMBER)
is tested. If the condition is satisfied, control is transferred to the INSPECT
statement. If the condition is not satisfied, 010-PROCESS-ONE-MONTH is executed, and

84 Programming Guide
the condition is tested again. This cycle continues until the condition tests as true.
(To make your program easier to read, you might want to code the WITH TEST
BEFORE clause.)

Coding a loop through a table


You can use PERFORM . . . VARYING to initialize a table. In this form of the PERFORM
statement, a variable is increased or decreased and tested until a condition is
satisfied.

Thus you use the PERFORM statement to control a loop through a table. You can use
either of the following forms:
PERFORM . . . WITH TEST AFTER . . . VARYING . . . UNTIL . . .
PERFORM . . . [WITH TEST BEFORE] . . . VARYING . . . UNTIL .

The following code shows an example of looping through a table to check for
invalid data:
PERFORM TEST AFTER VARYING WS-DATA-IX
FROM 1 BY 1
UNTIL WS-DATA-IX = 12
IF WS-DATA (WS-DATA-IX) EQUALS SPACES
SET SERIOUS-ERROR TO TRUE
DISPLAY ELEMENT-NUM-MSG5
END-IF
END-PERFORM
INSPECT . . .

In the code above, when control reaches the PERFORM statement, WS-DATA-IX is set
equal to 1 and the PERFORM statement is executed. Then the condition
(WS-DATA-IX = 12) is tested. If the condition is true, control drops through to the
INSPECT statement. If it is false, WS-DATA-IX is increased by 1, the PERFORM statement
is executed, and the condition is tested again. This cycle of execution and testing
continues until WS-DATA-IX is equal to 12.

In terms of the application, this loop controls input-checking for the 12 fields of
item WS-DATA. Empty fields are not allowed, and this section of code loops through
and issues error messages as appropriate.

Executing multiple paragraphs or sections


In structured programming, the paragraph you execute is usually a single
paragraph. However, you can execute a group of paragraphs, a single section, or a
group of sections using the PERFORM . . . THRU statement.

When you use PERFORM . . . THRU use a paragraph-EXIT statement to clearly


indicate the end point for the series of paragraphs.

Intrinsic functions can make the coding of the iterative processing of tables simpler
and easier.

Chapter 5. Selecting and repeating program actions 85


RELATED TASKS
“Processing table items using intrinsic functions” on page 73

86 Programming Guide
Chapter 6. Handling strings
COBOL provides language constructs for performing the following operations
associated with string data items:
v Joining and splitting data items
v Manipulating null-terminated strings, such as counting or moving characters
v Referring to substrings by their ordinal position and, if needed, length
v Tallying and replacing data items, such as counting the number of times a
specific character occurs in a data item
v Converting data items, such as changing to uppercase or lowercase
v Evaluating data items, such as determining the length of a data item

RELATED TASKS
“Joining data items (STRING)”
“Splitting data items (UNSTRING)” on page 89
“Manipulating null-terminated strings” on page 91
“Referring to substrings of data items” on page 93
“Tallying and replacing data items (INSPECT)” on page 95
“Converting data items (intrinsic functions)” on page 97
“Evaluating data items (intrinsic functions)” on page 99
Chapter 7, “Processing character data in an international environment,” on page
103

Joining data items (STRING)


Use the STRING statement to join all or parts of several data items into one data
item. One STRING statement can save you several MOVE statements.

The STRING statement transfers data items into the receiving item in the order that
you indicate. In the STRING statement you can also specify the following:
v Delimiters that cause a sending field to be ended and another to be started
v Actions to be taken when the single receiving field is filled before all of the
sending characters have been processed (ON OVERFLOW condition)

You can specify a national item for any literal or identifier operand except the
POINTER identifier. However, if you specify a national item, you must specify all of
the literal and identifier operands (except the POINTER identifier) as national.

“Example: STRING statement” on page 88

RELATED TASKS
“Handling errors in joining and splitting strings” on page 202

RELATED REFERENCES
STRING statement (Enterprise COBOL Language Reference)

© Copyright IBM Corp. 1991, 2004 87


Example: STRING statement
In the following example, the STRING statement selects and formats information
from record RCD-01 as an output line: line number, customer name and address,
invoice number, next billing date, and balance due. The balance is truncated to the
dollar figure shown.

In the FILE SECTION, the following record is defined:


01 RCD-01.
05 CUST-INFO.
10 CUST-NAME PIC X(15).
10 CUST-ADDR PIC X(35).
05 BILL-INFO.
10 INV-NO PIC X(6).
10 INV-AMT PIC $$,$$$.99.
10 AMT-PAID PIC $$,$$$.99.
10 DATE-PAID PIC X(8).
10 BAL-DUE PIC $$,$$$.99.
10 DATE-DUE PIC X(8).

In the WORKING-STORAGE SECTION, the following fields are defined:


77 RPT-LINE PIC X(120).
77 LINE-POS PIC S9(3).
77 LINE-NO PIC 9(5) VALUE 1.
77 DEC-POINT PIC X VALUE “.”.

The record RCD-01 contains the following information (the symbol b indicates a
blank space):
J.B.bSMITHbbbbb
444bSPRINGbST.,bCHICAGO,bILL.bbbbbb
A14275
$4,736.85
$2,400.00
09/22/76
$2,336.85
10/22/76

In the PROCEDURE DIVISION, the programmer initializes RPT-LINE to SPACES and sets
LINE-POS, the data item to be used as the POINTER field, to 4. (By coding the
POINTER phrase of the STRING statement, you can use the explicit pointer field to
control placement of data in the receiving field.) Then, the programmer codes this
STRING statement:
STRING
LINE-NO SPACE CUST-INFO INV-NO SPACE DATE-DUE SPACE
DELIMITED BY SIZE
BAL-DUE
DELIMITED BY DEC-POINT
INTO RPT-LINE
WITH POINTER LINE-POS.

STRING program results


When the STRING statement is performed, items are moved into RPT-LINE as shown
in the table below.

Item Positions
LINE-NO 4-8
Space 9
CUST-INFO 10 - 59
INV-NO 60 - 65

88 Programming Guide
Item Positions
Space 66
DATE-DUE 67 - 74
Space 75
Portion of BAL-DUE that precedes the decimal point 76 - 81

After the STRING statement is performed, the value of LINE-POS is 82, and RPT-LINE
appears as shown below.

Splitting data items (UNSTRING)


Use the UNSTRING statement to split one sending field into several receiving fields.
One UNSTRING statement can save you several MOVE statements.

In the UNSTRING statement you can specify the following:


v Delimiters that, when encountered in the sending field, cause the current
receiving field to stop receiving and the next to begin receiving
v Fields that store the number of characters placed in receiving fields
v A field that stores a count of the total number of characters transferred
v Special actions to take if all the receiving fields are filled before the end of the
sending item is reached

You can specify national items as the sending field, receiving fields, and delimiters.
However, if you specify a national item, you must specify all of these operands as
national.

“Example: UNSTRING statement”

RELATED CONCEPTS
“Unicode and encoding of language characters” on page 105

RELATED TASKS
“Handling errors in joining and splitting strings” on page 202
Enterprise COBOL Compiler and Run-Time Migration Guide

RELATED REFERENCES
UNSTRING statement (Enterprise COBOL Language Reference)

Example: UNSTRING statement


In the following example, selected information is taken from the input record.
Some is organized for printing and some for further processing.

In the FILE SECTION, the following records are defined:

Chapter 6. Handling strings 89


* Record to be acted on by the UNSTRING statement:
01 INV-RCD.
05 CONTROL-CHARS PIC XX.
05 ITEM-INDENT PIC X(20).
05 FILLER PIC X.
05 INV-CODE PIC X(10).
05 FILLER PIC X.
05 NO-UNITS PIC 9(6).
05 FILLER PIC X.
05 PRICE-PER-M PIC 99999.
05 FILLER PIC X.
05 RTL-AMT PIC 9(6).99.
*
* UNSTRING receiving field for printed output:
01 DISPLAY-REC.
05 INV-NO PIC X(6).
05 FILLER PIC X VALUE SPACE.
05 ITEM-NAME PIC X(20).
05 FILLER PIC X VALUE SPACE.
05 DISPLAY-DOLS PIC 9(6).
*
* UNSTRING receiving field for further processing:
01 WORK-REC.
05 M-UNITS PIC 9(6).
05 FIELD-A PIC 9(6).
05 WK-PRICE REDEFINES FIELD-A PIC 9999V99.
05 INV-CLASS PIC X(3).
*
* UNSTRING statement control fields
77 DBY-1 PIC X.
77 CTR-1 PIC S9(3).
77 CTR-2 PIC S9(3).
77 CTR-3 PIC S9(3).
77 CTR-4 PIC S9(3).
77 DLTR-1 PIC X.
77 DLTR-2 PIC X.
77 CHAR-CT PIC S9(3).
77 FLDS-FILLED PIC S9(3).

In the PROCEDURE DIVISION, the programmer writes the following UNSTRING


statement:
* Move subfields of INV-RCD to the subfields of DISPLAY-REC
* and WORK-REC:
UNSTRING INV-RCD
DELIMITED BY ALL SPACES OR “/” OR DBY-1
INTO ITEM-NAME COUNT IN CTR-1
INV-NO DELIMITER IN DLTR-1 COUNT IN CTR-2
INV-CLASS
M-UNITS COUNT IN CTR-3
FIELD-A
DISPLAY-DOLS DELIMITER IN DLTR-2 COUNT IN CTR-4
WITH POINTER CHAR-CT
TALLYING IN FLDS-FILLED
ON OVERFLOW GO TO UNSTRING-COMPLETE.

Before issuing the UNSTRING statement, the programmer places the value 3 in
CHAR-CT (the POINTER field) to avoid working with the two control characters in
INV-RCD. A period (.) is placed in DBY-1 for use as a delimiter, and the value 0
(zero) is placed in FLDS-FILLED (the TALLYING field). The data is then read into
INV-RCD, as shown below.

90 Programming Guide
UNSTRING program results
When the UNSTRING statement is performed, the following steps take place:
1. Positions 3 through 18 (FOUR-PENNY-NAILS) of INV-RCD are placed in ITEM-NAME,
left justified in the area, and the four unused character positions are padded
with spaces. The value 16 is placed in CTR-1.
2. Because ALL SPACES is coded as a delimiter, the five contiguous SPACE characters
in positions 19 through 23 are considered to be one occurrence of the delimiter.
3. Positions 24 through 29 (707890) are placed in INV-NO. The delimiter character,
/, is placed in DLTR-1, and the value 6 is placed in CTR-2.
4. Positions 31 through 33 are placed in INV-CLASS. The delimiter is a SPACE, but
because no field has been defined as a receiving area for delimiters, the SPACE
in position 34 is bypassed.
5. Positions 35 through 40 (475120) are examined and placed in M-UNITS. The
value 6 is placed in CTR-3. The delimiter is a SPACE, but because no field has
been defined as a receiving area for delimiters, the SPACE in position 41 is
bypassed.
6. Positions 42 through 46 (00122) are placed in FIELD-A and right justified in the
area. The high-order digit position is filled with a 0 (zero). The delimiter is a
SPACE, but because no field has been defined as a receiving area for delimiters,
the SPACE in position 47 is bypassed.
7. Positions 48 through 53 (000379) are placed in DISPLAY-DOLS. The period (.)
delimiter character in DBY-1 is placed in DLTR-2, and the value 6 is placed in
CTR-4.
8. Because all receiving fields have been acted on and two characters of data in
INV-RCD have not been examined, the ON OVERFLOW exit is taken, and execution
of the UNSTRING statement is completed.

After the UNSTRING statement is performed, the fields contain the values shown
below.

Field Value
DISPLAY-REC 707890 FOUR-PENNY-NAILS 000379
WORK-REC 475120000122BBA
CHAR-CT (the POINTER field) 55
FLDS-FILLED (the TALLYING field) 6

Manipulating null-terminated strings


You can construct and manipulate null-terminated strings (passed to or from a C
program, for example), by various mechanisms:
v Use null-terminated literal constants (Z“. . . ”).
v Use an INSPECT statement to count the number of characters in a null-terminated
string:

Chapter 6. Handling strings 91


MOVE 0 TO char-count
INSPECT source-field TALLYING char-count
FOR CHARACTERS
BEFORE X“00”
v Use an UNSTRING statement to move characters in a null-terminated string to a
target field, and get the character count:
WORKING-STORAGE SECTION.
01 source-field PIC X(1001).
01 char-count COMP-5 PIC 9(4).
01 target-area.
02 individual-char OCCURS 1 TO 1000 TIMES DEPENDING ON char-count
PIC X.
. . .
PROCEDURE DIVISION.
. . .
UNSTRING source-field DELIMITED BY X“00”
INTO target-area
COUNT IN char-count
ON OVERFLOW
DISPLAY “source not null terminated or target too short”
. . .
END-UNSTRING
v Use a SEARCH statement to locate trailing null or space characters. Define the
string being examined as a table of single characters.
v Check each character in a field in a loop (PERFORM). You can examine each
character in the field by using a reference modifier such as source-field (I:1).

“Example: null-terminated strings”

RELATED REFERENCES
Alphanumeric literals (Enterprise COBOL Language Reference)

Example: null-terminated strings


The following example shows several ways you can manipulate null-terminated
strings:
01 L pic X(20) value z’ab’.
01 M pic X(20) value z’cd’.
01 N pic X(20).
01 N-Length pic 99 value zero.
01 Y pic X(13) value ’Hello, World!’.
. . .
* Display null-terminated string
Inspect N tallying N-length
for characters before initial x’00’
Display ’N: ’ N(1:N-Length) ’ Length: ’ N-Length
. . .
* Move null-terminated string to alphanumeric, strip null
Unstring N delimited by X’00’ into X
. . .
* Create null-terminated string
String Y delimited by size
X’00’ delimited by size
into N.
. . .
* Concatenate two null-terminated strings to produce another
String L delimited by x’00’
M delimited by x’00’
X’00’ delimited by size
into N.

92 Programming Guide
Referring to substrings of data items
Refer to a substring of a character-string data item (including alphanumeric, DBCS,
and national data items) by using a reference modifier. Intrinsic functions that
return character-string values can include a reference modifier.

The following example shows how to use a reference modifier to refer to a


substring of a data item:
Move Customer-Record(1:20) to Orig-Customer-Name

As this example shows, you code two values separated by a colon, in parentheses,
immediately following the data item:
v Ordinal position (from the left) of the character that you want the substring to
start with
v Length of the desired substring

The length is optional. If you omit the length, the substring extends to the end of
the item. Omit the length when possible as a simpler and less error-prone coding
technique.

You can code either of the two values as a variable or as an arithmetic expression.

Because numeric function identifiers can be used anywhere that arithmetic


expressions are allowed, you can use them in the reference modifier as the leftmost
character position or as the length.

You can also refer to substrings of table entries, including variable-length entries.
To refer to a substring of a table entry, you must code the subscript expression
before the reference modifier. For example, assuming that PRODUCT-TABLE is a
properly coded table of character strings, to move D to the fourth character in the
second string in the table, you could code this statement:
MOVE ’D’ to PRODUCT-TABLE (2), (4:1)

Both numbers in the reference modifier must have a value of at least 1. Their sum
should not exceed the total length of the data item by more than 1 so that you do
not reference beyond the end of the desired substring.

If the leftmost character position or the length value is a fixed-point noninteger,


truncation occurs to create an integer. If either is a floating-point noninteger,
rounding occurs to create an integer.

The following options detect out-of-range reference modifiers, and flag violations
with a run-time message:
v SSRANGE compiler option
v CHECK run-time option

You can reference-modify national data items. The reference modifier position and
length for a national item are expressed in terms of national characters.

RELATED CONCEPTS
“Reference modifiers” on page 94
“Unicode and encoding of language characters” on page 105

RELATED TASKS
“Referring to an item in a table” on page 61
Chapter 6. Handling strings 93
RELATED REFERENCES
“SSRANGE” on page 304
Reference modification (Enterprise COBOL Language Reference)
Function definitions (Enterprise COBOL Language Reference)

Reference modifiers
Assume that you want to retrieve the current time from the system and display its
value in an expanded format. You can retrieve the current time with the ACCEPT
statement, which returns the hours, minutes, seconds, and hundredths of seconds
in this format:
HHMMSSss

However, you might prefer to view the current time in this format:
HH:MM:SS

Without reference modifiers, you would have to define data items for both formats.
You would also have to write code to convert from one format to the other.

With reference modifiers, you do not need to provide names for the subfields that
describe the TIME elements. The only data definition you need is for the time as
returned by the system. For example:
01 REFMOD-TIME-ITEM PIC X(8).

The following code retrieves and expands the time value:


ACCEPT REFMOD-TIME-ITEM FROM TIME.
DISPLAY “CURRENT TIME IS: ”
* Retrieve the portion of the time value that corresponds to
* the number of hours:
REFMOD-TIME-ITEM (1:2)
“:”
* Retrieve the portion of the time value that corresponds to
* the number of minutes:
REFMOD-TIME-ITEM (3:2)
“:”
* Retrieve the portion of the time value that corresponds to
* the number of seconds:
REFMOD-TIME-ITEM (5:2)

“Example: arithmetic expressions as reference modifiers”


“Example: intrinsic functions as reference modifiers” on page 95

RELATED TASKS
“Referring to substrings of data items” on page 93
“Using national data (Unicode) in COBOL” on page 106

RELATED REFERENCES
Reference modification (Enterprise COBOL Language Reference)

Example: arithmetic expressions as reference modifiers


Suppose that a field contains some right-justified characters, and you want to
move the characters to another field where they will be left justified. You can do
that using reference modifiers and an INSPECT statement.

Suppose the program has the following data:

94 Programming Guide
01 LEFTY PIC X(30).
01 RIGHTY PIC X(30) JUSTIFIED RIGHT.
01 I PIC 9(9) USAGE BINARY.

The program counts the number of leading spaces and, using arithmetic
expressions in a reference modifier, moves the right-justified characters into
another field, justified to the left:
MOVE SPACES TO LEFTY
MOVE ZERO TO I
INSPECT RIGHTY
TALLYING I FOR LEADING SPACE.
IF I IS LESS THAN LENGTH OF RIGHTY THEN
MOVE RIGHTY ( I + 1 : LENGTH OF RIGHTY - I ) TO LEFTY
END-IF

The MOVE statement transfers characters from RIGHTY, beginning at the position
computed as I + 1 for a length that is computed as LENGTH OF RIGHTY - I, into the
field LEFTY.

Example: intrinsic functions as reference modifiers


The following code fragment causes a substring of Customer-Record to be moved
into the data item WS-name. The substring is determined at run time.
05 WS-name Pic x(20).
05 Left-posn Pic 99.
05 I Pic 99.
. . .
Move Customer-Record(Function Min(Left-posn I):Function Length(WS-name)) to WS-name

If you want to use a noninteger function in a position requiring an integer


function, you can use the INTEGER or INTEGER-PART function to convert the result to
an integer. For example:
Move Customer-Record(Function Integer(Function Sqrt(I)): ) to WS-name

RELATED REFERENCES
INTEGER-PART (Enterprise COBOL Language Reference)
INTEGER (Enterprise COBOL Language Reference)

Tallying and replacing data items (INSPECT)


Use the INSPECT statement to do the following tasks:
v Fill selected portions of a data item with a value. If you specify a national data
item, you must also specify a national value.
v Replace portions of a data item with a corresponding portion of another data
item. If you specify any national items or literals in the statement, you must
specify all items as national.
v Count the number of times a specific character (zero, space, or asterisk, for
example) occurs in a data item. For a national data item, the count is in national
characters.

“Examples: INSPECT statement” on page 96

RELATED CONCEPTS
“Unicode and encoding of language characters” on page 105

RELATED REFERENCES
INSPECT statement (Enterprise COBOL Language Reference)

Chapter 6. Handling strings 95


Examples: INSPECT statement
The following examples show some uses of the INSPECT statement.

In the following example, the INSPECT statement is used to examine and replace
characters in data item DATA-2. The number of times a leading 0 occurs in the data
item is accumulated in COUNTR. Every instance of the character A that follows the
first instance of the character C is replaced by the character 2.
77 COUNTR PIC 9 VALUE ZERO.
01 DATA-2 PIC X(11).
. . .
INSPECT DATA-2
TALLYING COUNTR FOR LEADING “0”
REPLACING FIRST “A” BY “2” AFTER INITIAL “C”

DATA-2 before COUNTR after DATA-2 after


00ACADEMY00 2 00AC2DEMY00
0000ALABAMA 4 0000ALABAMA
CHATHAM0000 0 CH2THAM0000

In the following example, the INSPECT statement is used to examine and replace
characters in data item DATA-3. Every character in the data item that precedes the
first instance of a quotation mark (“) is replaced by the character 0.
77 COUNTR PIC 9 VALUE ZERO.
01 DATA-3 PIC X(8).
. . .
INSPECT DATA-3
REPLACING CHARACTERS BY ZEROS BEFORE INITIAL QUOTE

DATA-3 before COUNTR after DATA-3 after


456”ABEL 0 000“ABEL
ANDES”12 0 00000“12
”TWAS BR 0 “TWAS BR

The following example shows the use of INSPECT CONVERTING with AFTER and
BEFORE phrases to examine and replace characters in data item DATA-4. All
characters in the data item that follow the first instance of the character / but that
precede the first instance of the character ? (if any) are translated from lowercase
to uppercase.
01 DATA-4 PIC X(11).
. . .
INSPECT DATA-4
CONVERTING
”abcdefghijklmnopqrstuvwxyz“ TO
”ABCDEFGHIJKLMNOPQRSTUVWXYZ“
AFTER INITIAL ”/“
BEFORE INITIAL”?“

DATA-4 before DATA-4 after


a/five/?six a/FIVE/?six
r/Rexx/RRRr r/REXX/RRRR
zfour?inspe zfour?inspe

96 Programming Guide
Converting data items (intrinsic functions)
You can use intrinsic functions to convert character-string data items to:
v Uppercase or lowercase
v Reverse order
v Numbers
v One code page to another

You can also use the INSPECT statement to convert characters.

“Examples: INSPECT statement” on page 96

You can use the NATIONAL-OF and DISPLAY-OF intrinsic functions to convert to and
from national (Unicode) strings.

RELATED CONCEPTS
“Unicode and encoding of language characters” on page 105

Converting to uppercase or lowercase (UPPER-CASE,


LOWER-CASE)
01 Item-1 Pic x(30) Value “Hello World!”.
01 Item-2 Pic x(30).
. . .
Display Item-1
Display Function Upper-case(Item-1)
Display Function Lower-case(Item-1)
Move Function Upper-case(Item-1) to Item-2
Display Item-2

The code above displays the following messages on the system logical output
device:
Hello World!
HELLO WORLD!
hello world!
HELLO WORLD!

The DISPLAY statements do not change the actual contents of Item-1, but affect only
how the letters are displayed. However, the MOVE statement causes uppercase
letters to be moved to the actual contents of Item-2.

Converting to reverse order (REVERSE)


The following code reverses the order of the characters in Orig-cust-name.
Move Function Reverse(Orig-cust-name) To Orig-cust-name

For example, if the starting value is JOHNSONbbb, the value after the statement is
performed is bbbNOSNHOJ, where b represents a blank space.

When you reverse the order of a national string, the result is a national string.

Converting to numbers (NUMVAL, NUMVAL-C)


The NUMVAL and NUMVAL-C functions convert character strings to numbers. Use these
functions to convert alphanumeric data items that contain free-format
character-representation numbers to numeric form, and process them numerically.
For example:

Chapter 6. Handling strings 97


01 R Pic x(20) Value “- 1234.5678”.
01 S Pic x(20) Value “ $12,345.67CR”.
01 Total Usage is Comp-1.
. . .
Compute Total = Function Numval(R) + Function Numval-C(S)

Use NUMVAL-C when the argument includes a currency symbol or comma, or both,
as shown in the example. You can also place an algebraic sign before or after the
character string, and the sign will be processed. The arguments must not exceed 18
digits when you compile with the default option ARITH(COMPAT) (compatibility mode)
nor 31 digits when you compile with ARITH(EXTEND) (extended mode), not including
the editing symbols.

NUMVAL and NUMVAL-C return long (64-bit) floating-point values in compatibility


mode, and return extended-precision (128-bit) floating-point values in extended
mode. A reference to either of these functions, therefore, represents a reference to a
numeric data item.

When you use NUMVAL or NUMVAL-C, you do not need to statically declare numeric
data in a fixed format, nor input data in a precise manner. For example, suppose
you define numbers to be entered as follows:
01 X Pic S999V99 leading sign is separate.
. . .
Accept X from Console

The user of the application must enter the numbers exactly as defined by the
PICTURE clause. For example:
+001.23
-300.00

However, using the NUMVAL function, you could code:


01 A Pic x(10).
01 B Pic S999V99.
. . .
Accept A from Console
Compute B = Function Numval(A)

The input could then be:


1.23
-300

Converting from one code page to another


You can nest the DISPLAY-OF and NATIONAL-OF intrinsic functions to easily convert
from any code page to any other code page. For example, the following code
converts an EBCDIC string to an ASCII string:
77 EBCDIC-CCSID PIC 9(4) BINARY VALUE 1140.
77 ASCII-CCSID PIC 9(4) BINARY VALUE 819.
77 Input-EBCDIC PIC X(80).
77 ASCII-Output PIC X(80).
* Convert EBCDIC to ASCII
Move Function
Display-of
( Function National-of
(Input-EBCDIC EBCDIC-CCSID),
ASCII-CCSID
)
to ASCII-output

98 Programming Guide
RELATED CONCEPTS
“Formats for numeric data” on page 40

RELATED TASKS
“Assigning input from a screen or file (ACCEPT)” on page 29
“Displaying values on a screen or in a file (DISPLAY)” on page 30
“Converting national data” on page 107

RELATED REFERENCES
NUMVAL (Enterprise COBOL Language Reference)
NUMVAL-C (Enterprise COBOL Language Reference)
“ARITH” on page 271

Evaluating data items (intrinsic functions)


You can use several intrinsic functions in evaluating data items:
v CHAR and ORD for evaluating integers and single alphanumeric characters with
respect to the collating sequence used in your program
v MAX, MIN, ORD-MAX, and ORD-MIN for finding the largest and smallest items in a
series of data items, including national data items
v LENGTH for finding the length of data items, including national data items
v WHEN-COMPILED for finding the date and time the program was compiled

RELATED CONCEPTS
“Unicode and encoding of language characters” on page 105

RELATED TASKS
“Evaluating single characters for collating sequence”
“Finding the largest or smallest data item”
“Finding the length of data items” on page 101
“Finding the date of compilation” on page 102

Evaluating single characters for collating sequence


To find out the ordinal position of a given character in the collating sequence, use
the ORD function with the character as the argument. ORD returns an integer
representing that ordinal position. One convenient way to find a character’s ordinal
position is to use a one-character substring of a data item as the argument to ORD:
IF Function Ord(Customer-record(1:1)) IS > 194 THEN . . .

If you know the ordinal position in the collating sequence of a character, and want
to know the character that it corresponds to, use the CHAR function with the integer
ordinal position as the argument. CHAR returns the desired character:
INITIALIZE Customer-Name REPLACING ALPHABETIC BY Function Char(65)

RELATED REFERENCES
CHAR (Enterprise COBOL Language Reference)
ORD (Enterprise COBOL Language Reference)

Finding the largest or smallest data item


If you want to know which of two or more alphanumeric, alphabetic, or national
data items has the largest value, use the MAX or ORD-MAX function. Supply the data
items in question as arguments. If you want to know which item contains the
smallest value, use the MIN or ORD-MIN function. These functions evaluate the values

Chapter 6. Handling strings 99


according to the collating sequence. You can also use MAX, ORD-MAX, MIN, or ORD-MIN
for numbers. In that case, the algebraic values of the arguments are compared.

MAX and MIN


The MAX and MIN functions return the contents of one of the arguments that you
supply.

For example, suppose you have these data definitions:


05 Arg1 Pic x(10) Value “THOMASSON ”.
05 Arg2 Pic x(10) Value “THOMAS ”.
05 Arg3 Pic x(10) Value “VALLEJO ”.

The following statement assigns VALLEJObbb to the first 10 character positions of


Customer-record, where b represents a blank space:
Move Function Max(Arg1 Arg2 Arg3) To Customer-record(1:10)

If you use MIN instead, then THOMASbbbb is assigned.

If you specify a national item for any argument, you must specify all arguments as
national.

ORD-MAX and ORD-MIN


The functions ORD-MAX and ORD-MIN return an integer that represents the ordinal
position of the argument with the largest or smallest value in the list of arguments
that you supply (counting from the left).

If you used the ORD-MAX function in the example above, you would receive a syntax
error message at compile time; the reference to a numeric function is in an invalid
place. The following is a valid use of the ORD-MAX function:
Compute x = Function Ord-max(Arg1 Arg2 Arg3)

This code assigns the integer 3 to x if the same arguments are used as in the
previous example. If you use ORD-MIN instead, the integer 2 is returned. The above
examples would probably be more realistic if Arg1, Arg2, and Arg3 were instead
successive elements of an array (table).

If you specify a national item for any argument, you must specify all arguments as
national.

Returning variable-length results with alphanumeric functions


The results of alphanumeric functions could be of varying lengths and values
depending on the function arguments.

In the following example, the amount of data moved to R3 and the results of the
COMPUTE statement depend on the values and sizes of R1 and R2:
01 R1 Pic x(10) value “e”.
01 R2 Pic x(05) value “f”.
01 R3 Pic x(20) value spaces.
01 L Pic 99.
. . .
Move Function Max(R1 R2) to R3
Compute L = Function Length(Function Max(R1 R2))

Here, R2 is evaluated to be larger than R1. Therefore:


v The string ’fbbbb’ is moved to R3, where b represents a blank space. (The unfilled
character positions in R3 are padded with spaces.)

100 Programming Guide


v L evaluates to the value 5.

If R1 contained ’g’ instead of ’e’, then R1 would evaluate as larger than R2, and:
v The string ’gbbbbbbbbb’ would be moved to R3. (The unfilled character positions
in R3 would be padded with spaces.)
v The value 10 would be assigned to L.

You might be dealing with variable-length output from alphanumeric functions.


Plan your program accordingly. For example, you might need to think about using
variable-length files when the records you are writing could be of different lengths:
File Section.
FD Output-File Recording Mode V.
01 Short-Customer-Record Pic X(50).
01 Long-Customer-Record Pic X(70).
. . .
Working-Storage Section.
01 R1 Pic x(50).
01 R2 Pic x(70).
. . .
If R1 > R2
Write Short-Customer-Record from R1
Else
Write Long-Customer-Record from R2
End-if

RELATED TASKS
“Performing arithmetic” on page 47
“Processing table items using intrinsic functions” on page 73

RELATED REFERENCES
ORD-MAX (Enterprise COBOL Language Reference)
ORD-MIN (Enterprise COBOL Language Reference)

Finding the length of data items


You can use the LENGTH function in many contexts (including numeric data and
tables) to determine the length of string items.

The following COBOL statement demonstrates moving a data item into that field
in a record that holds customer names:
Move Customer-name To Customer-record(1:Function Length(Customer-name))

The LENGTH function returns the length of a national item in national characters.

You can also use the LENGTH OF special register, which returns the length in bytes
even for national data. Coding either Function Length(Customer-name) or LENGTH
OF Customer-name returns the same result for alphanumeric items: the length of
Customer-name in bytes.

You can use the LENGTH function only where arithmetic expressions are allowed.
However, you can use the LENGTH OF special register in a greater variety of
contexts. For example, you can use the LENGTH OF special register as an argument
to an intrinsic function that allows integer arguments. (You cannot use an intrinsic
function as an operand to the LENGTH OF special register.) You can also use the
LENGTH OF special register as a parameter in a CALL statement.

Chapter 6. Handling strings 101


RELATED TASKS
“Performing arithmetic” on page 47
“Processing table items using intrinsic functions” on page 73

RELATED REFERENCES
LENGTH (Enterprise COBOL Language Reference)

Finding the date of compilation


If you want to know the date and time when a program was compiled, you can
use the WHEN-COMPILED function. The result returned has 21 character positions,
with the first 16 positions in the following format:
YYYYMMDDhhmmsshh

These characters show the four-digit year, month, day, and time (in hours, minutes,
seconds, and hundredths of seconds) of compilation.

The WHEN-COMPILED special register is another means you can use to find the date
and time of compilation. It has the following format:
MM/DD/YYhh.mm.ss

The WHEN-COMPILED special register supports only a two-digit year, and carries the
time out only to seconds. This special register be used only as the sending field in
a MOVE statement.

RELATED REFERENCES
WHEN-COMPILED (Enterprise COBOL Language Reference)

102 Programming Guide


Chapter 7. Processing character data in an international
environment
Enterprise COBOL supports Unicode at run time. Unicode provides a consistent
and efficient way to encode plain text. Using Unicode, you can develop software
that will work with various national languages.

Use these COBOL facilities to code and compile programs with encoding of
national character data and culturally sensitive collation orders for such character
data:
v National data type, defined with USAGE NATIONAL and PICTURE symbol N
v National literals, specified with literal prefix N or NX
v Intrinsic functions:
– NATIONAL-OF to return a character string in UTF-16 representation
– DISPLAY-OF to convert a national string to a selected code page (EBCDIC,
ASCII, EUC, or UTF-8)
v Compiler options:
– CODEPAGE to specify the code page to use for alphanumeric and double-byte
character set (DBCS) data in your program
– NSYMBOL to control whether national or DBCS processing is used for the N
symbol in literals and PICTURE clauses

In addition, when you are working with national data, certain coding situations
such as handling strings, sorting and merging, and passing data require special
attention.
Table 15. COBOL statements and national data
COBOL
statement Can be national Comment For more information
ACCEPT identifier-1 Converted from EBCDIC “Assigning input from a screen or file
only if the CONSOLE option (ACCEPT)” on page 29
is specified directly or
indirectly.
CALL identifier-2, identifier-3, “Passing data” on page 411
identifier-4, identifier-5;
literal-2, literal-3
COPY . . operand-1, operand-2 COPY statement (Enterprise COBOL
.REPLACING Language Reference)
DISPLAY identifier-1 Converted to EBCDIC only “Displaying values on a screen or in a
if the CONSOLE option is file (DISPLAY)” on page 30
specified directly or
indirectly.
INITIALIZE REPLACING If you specify REPLACING “Examples: initializing data items” on
NATIONAL, identifier-2 and page 26
literal-1 must be of class
national, and vice versa.
INSPECT Identifiers and literals other If any of these is of class “Tallying and replacing data items
than identifier-3 (the national, all must be. (INSPECT)” on page 95
TALLYING identifier)

© Copyright IBM Corp. 1991, 2004 103


Table 15. COBOL statements and national data (continued)
COBOL
statement Can be national Comment For more information
INVOKE method-name as identifier-2 “Invoking methods (INVOKE)” on
or literal-1; identifier-3 or page 506
literal-2 in the BY VALUE
phrase
MERGE Merge keys The COLLATING SEQUENCE “Setting sort or merge criteria” on
phrase does not apply. page 189
MOVE Both the sender and If the sender is a national “Assigning values to elementary or
receiver data item, the receiver must group data items (MOVE)” on page 27
be also.
Format-2 Both the key data item and A search argument can be “Doing a binary search (SEARCH
(binary) SEARCH the search argument an alphanumeric or ALL)” on page 72
national item when the
corresponding key is a
national item. If a search
argument is a national
item, the corresponding key
must be a national data
item.
SORT Sort keys The COLLATING SEQUENCE “Setting sort or merge criteria” on
phrase does not apply. page 189
STRING Any identifiers and literals If any of these is of class “Joining data items (STRING)” on
other than identifier-4 (the national, all must be. page 87
POINTER identifier)
UNSTRING Delimiters (identifier-2, If any of these is of class “Splitting data items (UNSTRING)” on
identifier-3), data receiving national, all must be. page 89
fields (identifier-4), delimiter
receiving fields) identifier-5;
literal-3, literal-4

The use of national data affects these intrinsic functions:


Table 16. Intrinsic functions and national data
Argument type can
Intrinsic function be national? Function type For more information
LENGTH Yes Integer “Finding the length of data items” on page
101
LOWER-CASE, Yes National “Converting to uppercase or lowercase
UPPER-CASE (UPPER-CASE, LOWER-CASE)” on page 97
MAX, MIN Yes National “Finding the largest or smallest data item”
on page 99
ORD-MAX, ORD-MIN Yes Integer “Finding the largest or smallest data item”
on page 99
REVERSE Yes National “Converting to reverse order (REVERSE)”
on page 97

RELATED CONCEPTS
“Unicode and encoding of language characters” on page 105

104 Programming Guide


RELATED TASKS
“Using national data (Unicode) in COBOL” on page 106
“Converting national data” on page 107
“Processing UTF-8 data” on page 109
“Processing Chinese GB 18030 data” on page 110
“Comparing national data items” on page 111
“Processing alphanumeric data items that contain DBCS data” on page 112
Appendix C, “Converting double-byte character set (DBCS) data,” on page 619

RELATED REFERENCES
“CODEPAGE” on page 274
“NSYMBOL” on page 291

Unicode and encoding of language characters


Enterprise COBOL provides basic run-time support for Unicode, which can handle
| tens of thousands of characters covering all commonly used characters and
| symbols in the world compared to the up to 256 characters that ASCII and
EBCDIC support.

Each character set is a defined set of characters, but is not associated with a coded
representation. A coded character set (also referred to here as a code page) is a set of
unambiguous rules that relate the characters of the set to their coded
representation. Each code page has a name and is like a table that sets up the
symbols for representing a character set; each symbol is a unique bit pattern, or
code point. (Each IBM code page also has a coded character set identifier (CCSID),
which is a value from 1 to 65,536.)

There are several encoding schemes in Unicode, called Unicode Transformation


Format (UTF), such as UTF-8, UTF-16, and UTF-32. Enterprise COBOL uses UTF-16
(CCSID 1200) in big-endian format as the representation for the national data type.

UTF-8 represents ASCII invariant characters a-z, A-Z, 0-9, and certain special
characters such as ’ @ , . + - = / * ( ) identically as in ASCII. UTF-16 represents
such characters as X’00nn’ where X’nn’ is the representation of the character in
ASCII.

For example, the string ’ABC’ in UTF-16 would be NX’004100420043’. In UTF-8 it


would be X’414243’.

One or more encoding units are used to represent a character in a coded character
set. For UTF-16, an encoding unit takes 2 bytes of storage. Any character defined
in any EBCDIC, ASCII, or EUC code page is represented in one UTF-16 encoding
unit when the character is converted to the national data representation.

| Cross-platform considerations: Enterprise COBOL does not support UTF-16 with


| byte order marks or UTF-16 in little-endian format (UTF-16LE) in national data
| items. If you are porting UTF-16 data or UTF-16LE data from another platform,
| you must convert that data to UTF-16 big-endian format.

RELATED TASKS
Chapter 7, “Processing character data in an international environment,” on page
103

Chapter 7. Processing character data in an international environment 105


Using national data (Unicode) in COBOL
In Enterprise COBOL, you can specify Unicode data by means of:
v National data items
v National literals
v Figurative constants as national characters

These declarations affect the amount of storage needed.

National data items


Define data items with USAGE NATIONAL to hold Unicode strings. Code a PICTURE
clause that consists only of one or more PICTURE symbols N.

If you specify a PICTURE clause but do not specify a USAGE clause for data items
that consist only of one or more PICTURE symbols N, you can use the compiler
option NSYMBOL(NATIONAL) to ensure that the items are treated as national data
items (instead of as DBCS items).

National literals
To specify national literals, use the prefix character N and compile with the option
NSYMBOL(NATIONAL). For example, you can use either of these notations:
N“character-data”
N’character-data’

When you use NSYMBOL(DBCS), the literal prefix character N specifies a DBCS literal,
not a national literal.

To specify a national literal as a hexadecimal value, use the prefix character NX. For
example, you can use either of these notations:
NX“hexadecimal-digits”
NX’hexadecimal-digits’

Each of the following MOVE statements sets the data item X to the Unicode value
AB:
01 X pic NN usage national.
. . .
Move NX“00410042” to X
Move N“AB” to X
Move “AB” to X

Do not use alphanumeric hexadecimal literals in contexts that call for a national
literal, because such usage is easily misunderstood. For example, the statement:
Move X“C1C2C3C4” to X

also results in moving Unicode AB (not the bit pattern C1C2C3C4) to X.

National characters as figurative constants


You can use the figurative constant ALL literal for national literals. It represents all
or part of the string that is generated by successive concatenations of the encoding
units that make up the literal.

When you use the figurative constant QUOTE, SPACE, or ZERO in a context that
requires national characters, the figurative constant represents a national character
value. However, you cannot use the figurative constants HIGH-VALUE and LOW-VALUE

106 Programming Guide


in a context that requires national characters, such as a MOVE statement, an implicit
MOVE, or a relation condition with national operands.

You cannot use national literals in the SPECIAL-NAMES paragraph.

Storage of national data


Use this table to compare alphanumeric (DISPLAY), DBCS (DISPLAY-1), and Unicode
(NATIONAL) encoding and to plan your storage usage:
Table 17. Encoding and size of alphanumeric and national data
Characteristic DISPLAY DISPLAY-1 NATIONAL
Character encoding unit 1 byte 2 bytes 2 bytes
1
Code page EBCDIC EBCDIC DBCS UTF-16BE
Encoding units per character 1 1 1 or 22
Bytes per character 1 byte 2 bytes 2 or 4 bytes

1. Use the CODEPAGE compiler option to specify the code page for the EBCDIC code page
applicable to alphanumeric or DBCS data. National literals in your source program are
converted to UTF-16 for use at run time.
2. Most characters are represented in UTF-16 using one encoding unit. In particular, the
following characters are represented using a single UTF-16 encoding unit per character:
v COBOL characters A-Z, a-z, 0-9, space, + -*/= $,;.“()><:’
| v All characters that are converted from an EBCDIC, ASCII, or EUC code page

RELATED CONCEPTS
“Unicode and encoding of language characters” on page 105

RELATED TASKS
“Converting national data”
“Comparing national data items” on page 111
“Processing UTF-8 data” on page 109

RELATED REFERENCES
“CODEPAGE” on page 274
“NSYMBOL” on page 291

Converting national data


You can convert alphanumeric, DBCS, and integer data items to national strings by
using the MOVE statement. (Such implicit conversions also take place in other
COBOL statements, such as a comparison of an alphanumeric data item with a
national data item.) You can also convert to and from national (Unicode) strings by
using the intrinsic functions NATIONAL-OF and DISPLAY-OF, respectively. Using the
intrinsic functions allows you to specify a code page for the conversion that is
different from the code page in effect with the CODEPAGE compiler option.

Converting alphanumeric and integer to national data (MOVE)


You can use the MOVE statement to convert alphanumeric, DBCS, and integer items
to national. When you move an alphanumeric item to a national item, it is
converted to the representation of the national data receiver (UTF-16 Unicode).
When you move an alphanumeric-edited item, numeric integer, or numeric-edited
item to a national item, it is treated as if it were first moved to an alphanumeric
data item of the size not requiring padding or truncation.

Chapter 7. Processing character data in an international environment 107


If the number of characters of the converted data is less than the size of the
national data item that you specify, the data is padded with default Unicode
UTF-16 space characters (NX’0020’). If the number of characters of the converted
data is more than the size of the national item, the trailing characters are truncated.
You need to ensure that such truncation does not occur within a character.

Converting alphanumeric to national data (NATIONAL-OF)


Use the NATIONAL-OF intrinsic function to convert an alphabetic, alphanumeric, or
DBCS item to a character string represented in Unicode (UTF-16). Specify the
source code page as an argument, if the source is encoded in a different code page
than is in effect with the CODEPAGE compiler option.

Converting national to alphanumeric data (DISPLAY-OF)


Use the DISPLAY-OF intrinsic function to convert a national item to a character
string represented in the code page that you specify. If you specify an EBCDIC or
ASCII code page that combines SBCS and DBCS characters, the returned string
might contain a mixture of SBCS and DBCS characters. The DBCS substrings are
delimited by shift-in and shift-out characters if the code page in effect for the
function is an EBCDIC code page.

Overriding the default code page


In some cases, you might need to convert data to or from a code page that differs
from the CCSID specified as the CODEPAGE option value. To do this, convert the
item by using a conversion function in which you specify the code page for the
item explicitly.

If you specify a code page as an argument to DISPLAY-OF and it differs from the
code page that is in effect with the CODEPAGE compiler option, do not use the
DISPLAY-OF function result in any operations that involve implicit conversion (such
as an assignment to, or comparison with, a national data item). Such operations
assume the EBCDIC code page that is specified in the CODEPAGE compiler option.

Conversion exceptions
Implicit or explicit conversion between national and alphanumeric data could fail
and generate a severity-3 Language Environment condition. Failures could occur if
any of the follow occur:
v Unicode Conversion Services was not installed on your system.
v The code page that you specified (implicitly or explicitly) is not a valid code
page.
v The combination of the CCSID that you specified explicitly or implicitly (such as
by using the CODEPAGE compiler option) and the UTF-16 Unicode CCSID (1200)
was not configured on your system as a valid conversion pair for the Unicode
Conversion Services on the system.

A character that does not have a counterpart in the target CCSID does not result in
a conversion exception. Such a character is converted to a substitution character of
the target code page.

“Example: converting national data” on page 109

RELATED TASKS
Customizing Unicode support for COBOL (Enterprise COBOL Customization Guide)

108 Programming Guide


RELATED REFERENCES
“CODEPAGE” on page 274

Example: converting national data


The following example shows the use of the NATIONAL-OF and DISPLAY-OF intrinsic
functions and the MOVE statement for converting to and from Unicode strings. It
also demonstrates the need for explicit conversions when you operate on strings
encoded in multiple code pages in the same program.
CBL CODEPAGE(00037)
* . . .
01 Data-in-Unicode pic N(100) usage national.
01 Data-in-Greek pic X(100).
01 other-data-in-US-English pic X(12) value “PRICE in $ =”.
* . . .
Read Greek-file into Data-in-Greek
Move function National-of(Data-in-Greek, 00875)
to Data-in-Unicode
* . . . process Data-in-Unicode here . . .
Move function Display-of(Data-in-Unicode, 00875)
to Data-in-Greek
Write Greek-record from Data-in-Greek

The above example works correctly: Data-in-Greek is converted as data


represented in CCSID 00875 (Greek) explicitly. However, the following statement
would result in an incorrect conversion (unless all the characters in the item
happen to be among those with a common representation in the Greek and the
English code pages):
Move Data-in-Greek to Data-in-Unicode

Data-in-Greek is converted to Unicode by this MOVE statement based on the CCSID


00037 (U.S. English) to UTF-16 conversion. This conversion would not produce the
expected results because Data-in-Greek is actually encoded in CCSID 00875.

If you can correctly set the CODEPAGE compiler option to CCSID 00875 (that is, the
rest of your program also handles EBCDIC data in Greek), you can code the same
example correctly as follows:
CBL CODEPAGE(00037)
* . . .
01 Data-in-Unicode pic N(100) usage national.
01 Data-in-Greek pic X(100).
* . . .
Read Greek-file into Data-in-Greek
* . . . process Data-in-Greek here ...
* . . . or do the following (if need to process data in Unicode)
Move Data-in-Greek to Data-in-Unicode
* . . . process Data-in-Unicode
Move function Display-of(Data-in-Unicode) to Data-in-Greek
Write Greek-record from Data-in-Greek

Processing UTF-8 data


When you need to process UTF-8 data, first convert the data to UTF-16 Unicode in
a national data item. After processing the national data, convert it back to UTF-8
for output. For the conversions, use the intrinsic functions NATIONAL-OF and
DISPLAY-OF. Use code page 1208 for UTF-8 data.

You need to do two steps to convert ASCII or EBCDIC data to UTF-8:

Chapter 7. Processing character data in an international environment 109


1. Use the function NATIONAL-OF to convert the ASCII or EBCDIC string to
national (UTF-16).
2. Use the function DISPLAY-OF to convert the national string (UTF-16) to UTF-8.

The following example illustrates these steps, converting Greek EBCDIC data to
UTF-8:

RELATED TASKS
“Converting national data” on page 107

Processing Chinese GB 18030 data


Enterprise COBOL does not have any explicit support for GB 18030, but does
support processing GB 18030 characters in the following ways:
v You can use DBCS data to process GB 18030 characters that are represented in
CCSID 1388.
v You can use Unicode data to define and process GB 18030 characters that are
represented in CCSID 01200 (GB 18030 characters that do not require UTF-16
surrogates).
v You can process data in any code page (including CCSID 1388) by converting it
to Unicode, processing the data as Unicode, then converting it back to the
original code page representation.
When you need to process Chinese GB 18030 data that requires conversion, first
convert the input data to UTF-16 Unicode in a national data item. After
processing the national data, convert it back to Chinese GB 18030 for output. For
the conversions, use the intrinsic functions NATIONAL-OF and DISPLAY-OF, and
specify code page 1388 as the second argument of each.
The following example illustrates these conversions:

GB 18030 characters are encoded through the existing Chinese EBCDIC code page,
CCSID 1388, which has been expanded to include the GB 18030 characters that do
not require UTF-16 surrogate values. Surrogate values in UTF-16 are those characters
that require two 2-byte encoding units (4 bytes) for each character.

RELATED TASKS
“Converting national data” on page 107

110 Programming Guide


Comparing national data items
You can compare national data items explicitly or implicitly with other national
data items in relation conditions. You can code conditional expressions that use
national data items in the following statements:
v EVALUATE
v IF
v INSPECT
v PERFORM
v SEARCH
v STRING
v UNSTRING

You can compare national data items explicitly or implicitly with certain
nonnational items in relation conditions in the following statements:
v EVALUATE
v IF
v PERFORM
v SEARCH

All comparisons that involve a national operand are national comparisons. The
operands must follow the rules for valid comparisons. The PROGRAM COLLATING
SEQUENCE does not affect comparisons that involve national operands.

Comparing national operands


When you compare two national operands of the same length, they are determined
to be equal if all pairs of the corresponding characters are equal. Otherwise,
comparison of the binary values of the first pair of unequal characters determines
the operand with the larger binary value.

When you compare operands of unequal lengths, the shorter operand is treated as
if it were padded on the right with default Unicode UTF-16 space characters
(NX’0020’) to the length of the longer operand.

Comparing national and numeric operands


You can compare national literals or national data items to integer literals or
numeric data items of USAGE DISPLAY. The numeric operand is treated as if it were
moved to an elementary alphanumeric item, and an alphanumeric comparison is
done.

Comparing national and alphabetic or alphanumeric operands


You can compare national literals or data items to alphabetic or alphanumeric data
items. The alphabetic or alphanumeric operand is treated as if it were moved to an
elementary national item, and a national comparison is done.

Comparing national and group operands


You can compare a national literal or data item to a group. The national operand is
treated as if it were moved to a group item of the same size as the group operand,
and the two groups are compared.

Chapter 7. Processing character data in an international environment 111


RELATED TASKS
“Using national data (Unicode) in COBOL” on page 106
“Coding a choice of actions” on page 75
“Tallying and replacing data items (INSPECT)” on page 95
“Coding a loop” on page 84
“Doing a serial search (SEARCH)” on page 71
“Joining data items (STRING)” on page 87
“Splitting data items (UNSTRING)” on page 89

RELATED REFERENCES
Relation condition (Enterprise COBOL Language Reference)
Comparison of numeric and alphanumeric operands (Enterprise COBOL Language
Reference)

Processing alphanumeric data items that contain DBCS data


If you use byte-oriented alphanumeric operations (for example, STRING, UNSTRING,
or reference modification) on an alphanumeric data item that contains DBCS
characters, results are unpredictable. You should instead do these steps:
1. Convert the item to Unicode in a national data item by using a MOVE statement
or the NATIONAL-OF function.
2. Process the national item as needed.
3. Convert the result back to alphanumeric by using the DISPLAY-OF function.

RELATED TASKS
“Joining data items (STRING)” on page 87
“Splitting data items (UNSTRING)” on page 89
“Referring to substrings of data items” on page 93
“Converting national data” on page 107

112 Programming Guide


Chapter 8. Processing files
Reading and writing data is an essential part of every program. Your program
retrieves information, processes it as you request, and then produces the results.

The source of the information and the target for the results can be one or more of
the following:
v Another program
v Direct-access storage device
v Magnetic tape
v Printer
v Terminal
v Card reader or punch

The information as it exists on an external device is in a physical record or block, a


collection of information that is handled as a unit by the system during input or
output operations.

Your COBOL program does not directly handle physical records. It processes
logical records. A logical record can correspond to a complete physical record, part
of a physical record, or to parts or all of one or more physical records. Your
COBOL program handles logical records exactly as you have defined them.

In COBOL, a collection of logical records is a file, a sequence of pieces of


information that your program can process.

RELATED CONCEPTS
“File organization and input-output devices”

RELATED TASKS
“Choosing file organization and access mode” on page 115
“Allocating files” on page 117
“Checking for input or output errors” on page 118

File organization and input-output devices


Depending on the input-output devices, your file organization can be sequential,
line sequential, indexed, or relative. Decide on the file types and devices to be used
when you design your program.

You have the following choices of file organization:


Sequential file organization
The chronological order in which records are entered when a file is created
establishes the arrangement of the records. Each record except the first has
a unique predecessor record, and each record except the last has a unique
successor record. Once established, these relationships do not change.
The access (record transmission) mode allowed for sequential files is
sequential only.

© Copyright IBM Corp. 1991, 2004 113


Line-sequential file organization
Line-sequential files are sequential files that reside on the hierarchical file
system (HFS) and that contain only characters as data. Each record ends
with a new-line character.
The only access (record transmission) mode allowed for line-sequential files
is sequential.
Indexed file organization
Each record in the file contains a special field whose contents form the
record key. The position of the key is the same in each record. The index
component of the file establishes the logical arrangement of the file, an
ordering by record key. The actual physical arrangement of the records in
the file is not significant to your COBOL program.
An indexed file can also use alternate indexes in addition to the record key.
These keys let you access the file using a different logical ordering of the
records.
The access (record transmission) modes allowed for indexed files are
sequential, random, or dynamic. When you read or write indexed files
sequentially, the sequence is that of the key values.
Relative file organization
Records in the file are identified by their location relative to the beginning
of the file. The first record in the file has a relative record number of 1, the
tenth record has a relative record number of 10, and so on.
The access (record transmission) modes allowed for relative files are
sequential, random, or dynamic. When relative files are read or written
sequentially, the sequence is that of the relative record number.

With IBM Enterprise COBOL for z/OS, requests to the operating system for the
storage and retrieval of records from input-output devices are handled by the two
access methods QSAM and VSAM, and the UNIX file system.

The device type upon which you elect to store your data could affect the choices of
file organization available to you. Direct-access storage devices provide greater
flexibility in the file organization options. Sequential-only devices limit
organization options but have other characteristics, such as the portability of tapes,
that might be useful.
Sequential-only devices
Terminals, printers, card readers, and punches are called unit-record devices
because they process one line at a time. Therefore, you must also process
records one at a time sequentially in your program when it reads from or
writes to unit-record devices.
On tape, records are ordered sequentially, so your program must process
them sequentially. Use QSAM physical sequential files when processing
tape files. The records on tape can be fixed length or variable length. The
rate of data transfer is faster than it is for cards.
Direct-access storage devices
Direct-access storage devices hold many records. The record arrangement
of files stored on these devices determines the ways that your program can
process the data. When using direct-access devices, you have greater
flexibility within your program, because your can use several types of file
organization:
v Sequential (VSAM or QSAM)

114 Programming Guide


v Line sequential (UNIX)
v Indexed (VSAM)
v Relative (VSAM)

RELATED TASKS
“Allocating files” on page 117
Chapter 9, “Processing QSAM files,” on page 119
Chapter 10, “Processing VSAM files,” on page 147
Chapter 11, “Processing line-sequential files,” on page 175
“Choosing file organization and access mode”

Choosing file organization and access mode


Consider the following guidelines when determining which file organization and
access mode to use in your application:
v If your application accesses records (fixed-length or variable-length records) only
sequentially and does not insert records between existing ones, a QSAM or
VSAM sequential file is the simplest type.
v If you are developing an application for UNIX that sequentially accesses records
that contain only printable characters and certain control characters,
line-sequential files work the best.
v If your application requires both sequential and random access (fixed-length or
variable-length records), a VSAM indexed file is the most flexible type.
v If your application randomly inserts and deletes records, a relative file works
well.

If a large percentage of a file is referenced or updated in your application,


sequential processing is faster than random or dynamic access. If a small
percentage of records is processed during each run of your application, use
random or dynamic access.

The following table shows the possible file organizations, access modes, and record
formats for COBOL files.
Table 18. File organization, access mode, and record format
Sequential Random Dynamic Fixed Variable
File organization access access access length length
QSAM (physical X X X
sequential)
Line sequential X X1 X
VSAM sequential (ESDS) X X X
VSAM indexed (KSDS) X X X X X
VSAM relative (RRDS) X X X X X

1. The data itself is in variable format but can be read into and written from COBOL
fixed-length records.

RELATED REFERENCES
“Format for coding input and output” on page 116
“Allowable control characters” on page 176

Chapter 8. Processing files 115


Format for coding input and output
The following code shows the general format of input-output coding. Explanations
of the user-supplied information follow the code.
IDENTIFICATION DIVISION.
. . .
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT filename ASSIGN TO assignment-name (1) (2)
ORGANIZATION IS org ACCESS MODE IS access (3) (4)
FILE STATUS IS file-status (5)
. . .
DATA DIVISION.
FILE SECTION.
FD filename
01 recordname (6)
nn . . . fieldlength & type (7) (8)
nn . . . fieldlength & type
. . .
WORKING-STORAGE SECTION
01 file-status PICTURE 99.
. . .
PROCEDURE DIVISION.
. . .
OPEN iomode filename (9)
. . .
READ filename
. . .
WRITE recordname
. . .
CLOSE filename
. . .
STOP RUN.

The user-supplied information in the code above is as follows:


(1) filename
Any legal COBOL name. You must use the same file name on the SELECT
and the FD statements, and on the READ, OPEN, and CLOSE statements. In
addition, the file name is required if you use the START or DELETE
statements. This name is not necessarily the actual name of the data set as
known to the system. Each file requires its own SELECT, FD, and
input-output statements.
(2) assignment-name
Any name you choose, provided that it follows COBOL and system
naming rules. The name can be 1-30 characters long if it is a user-defined
word, or 1-160 characters long if it is a literal. You code the name part of
the assignment-name on a DD statement, in an ALLOCATE command (TSO) or
as an environment variable (for example, in an export command) (UNIX).
(3) org The organization can be SEQUENTIAL, LINE SEQUENTIAL, INDEXED, or
RELATIVE. This clause is optional for QSAM files.
(4) access
The access mode can be SEQUENTIAL, RANDOM, or DYNAMIC. For sequential file
processing, including line-sequential, you can omit this clause.
(5) file-status
The two-character COBOL FILE STATUS key.
(6) recordname
The name of the record used in the WRITE and REWRITE statements.

116 Programming Guide


(7) fieldlength
The logical length of the field.
(8) type
The record format of the file. If you break the record entry beyond the
level-01 description, each element should map accurately against the fields
in the record.
(9) iomode
The INPUT or OUTPUT mode. If you are only reading from a file, code INPUT.
If you are only writing to it, code OUTPUT or EXTEND. If you are both reading
and writing, code I-O, except for organization LINE SEQUENTIAL.

RELATED TASKS
Chapter 9, “Processing QSAM files,” on page 119
Chapter 10, “Processing VSAM files,” on page 147
Chapter 11, “Processing line-sequential files,” on page 175

Allocating files
For any type of file (sequential, line sequential, indexed, or relative) in your z/OS
or UNIX applications, you can define the external name with either a ddname or
an environment variable name. The external name is the name in the
assignment-name of the ASSIGN clause.

If the file is in the HFS, you can use either a DD definition or an environment
variable to define the file by specifying its path name with the PATH keyword.

The environment variable name must be uppercase. The allowable attributes for its
value depend on the organization of the file being defined.

Because you can define the external name in either of two ways, the COBOL run
time goes through the following steps to find the definition of the file:
1. If the ddname is explicitly allocated, it is used. The definition can be from a DD
statement in JCL, an ALLOCATE command from TSO/E, or a user-initiated
dynamic allocation.
2. If the ddname is not explicitly allocated and an environment variable of the
same name is set, the value of the environment variable is used.
The file is dynamically allocated using the attributes specified by the
environment variable. At a minimum, you must specify either the PATH() or
DSN() option. All options and attributes must be in uppercase, except for the
path-name suboption of the PATH option, which is case sensitive. You cannot
specify a temporary data set name in the DSN() option.
File status code 98 results from any of the following:
v The contents (including a value of null or all blanks) of the environment
variable are not valid.
v The dynamic allocation of the file fails.
v The dynamic deallocation of the file fails.
The COBOL run time checks the contents of the environment variable at each
OPEN statement. If a file with the same external name was dynamically allocated
by a previous OPEN statement and the contents of the environment variable
have changed since that OPEN, the run time dynamically deallocates the
previous allocation and reallocates the file using the options currently set in the
environment variable. If the contents of the environment variable have not
changed, the run time uses the current allocation.

Chapter 8. Processing files 117


3. If neither a ddname nor an environment variable is defined, the following
occurs:
v If the allocation is for a QSAM file and the CBLQDA run-time option is in
effect, CBLQDA dynamic allocation processing takes place for those eligible
files. This type of “implicit” dynamic allocation persists for the life of the run
unit and cannot be reallocated.
v Otherwise the allocation fails.

The COBOL run time deallocates all dynamic allocations at run unit termination,
except “implicit” CBLQDA allocations.

RELATED TASKS
“Setting and accessing environment variables” on page 384
“Defining and allocating QSAM files” on page 134
“Dynamically creating QSAM files with CBLQDA” on page 130
“Allocating VSAM files” on page 169

Checking for input or output errors


After each input or output statement is performed, the FILE STATUS key is updated
with a value that indicates the success or failure of the operation. Using a FILE
STATUS clause, test the FILE STATUS key after each input or output statement, and
call an error-handling procedure if a nonzero file status code is returned.

With VSAM files, you can use a second data-name in the FILE STATUS clause to get
additional VSAM return code information.

Another way of handling errors in input and output operations is to code ERROR
(synonymous with EXCEPTION) declaratives, as explained in the references below.

RELATED TASKS
“Handling errors in input and output operations” on page 203
“Coding ERROR declaratives” on page 207
“Using file status keys” on page 208

118 Programming Guide


Chapter 9. Processing QSAM files
Queued sequential access method (QSAM) files are unkeyed files in which the
records are placed one after another, according to entry order. Your program can
process these files only sequentially, retrieving (with the READ statement) records in
the same order as they are in the file. Each record is placed after the preceding
record.

To process QSAM files in your program, use COBOL language statements that:
v Identify and describe the QSAM files in the ENVIRONMENT DIVISION and the DATA
DIVISION.
v Process the records in these files in the PROCEDURE DIVISION.

After you have created a record, you cannot change its length or its position in the
file, and you cannot delete it. You can, however, update QSAM files on
direct-access storage devices (using REWRITE), though not in the HFS.

QSAM files can be on tape, direct-access storage devices (DASDs), unit-record


devices, and terminals. QSAM processing is best for tables and intermediate
storage.

You can also access byte-stream files in the HFS using QSAM. These files are
binary byte-oriented sequential files with no record structure. The record
definitions that you code in your COBOL program and the length of the variables
that you read into and write from determine the amount of data transferred.

RELATED CONCEPTS
“Labels for QSAM files” on page 141
Using access methods (z/OS DFSMS: Using Data Sets)

RELATED TASKS
“Defining QSAM files and records in COBOL”
“Coding input and output statements for QSAM files” on page 129
“Handling errors in QSAM files” on page 133
“Working with QSAM files” on page 133
“Processing QSAM ASCII files on tape” on page 144
“Processing ASCII file labels” on page 145

Defining QSAM files and records in COBOL


Use the FILE-CONTROL entry to:
v Define the files in your COBOL program as QSAM files.
v Associate the files with the external file-names (ddnames or environment
variable names). (An external file-name is the name by which a file is known to
the operating system.)

In the following example, COMMUTER-FILE-MST is your program’s name for the file;
COMMUTR is the external name.

© Copyright IBM Corp. 1991, 2004 119


FILE-CONTROL.
SELECT COMMUTER-FILE-MST
ASSIGN TO S-COMMUTR
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL.

Your ASSIGN clause name can include an S- before the external name (ddname or
environment variable name) to document that the file is a QSAM file.

Both the ORGANIZATION and ACCESS MODE clauses are optional.

RELATED TASKS
“Establishing record formats”
“Setting block sizes” on page 127

Establishing record formats


In the FD entry in the DATA DIVISION, code the record format and whether the
records are blocked. In the associated record description entry or entries, define the
record-name and record length.

You can code a record format of F, V, S, or U in the RECORDING MODE clause. COBOL
determines the record format from the RECORD clause or from the record
descriptions associated with your FD entry for the file. If you want the records to
be blocked, code the BLOCK CONTAINS clause in your FD entry.

The following example shows how the FD entry might look for a file with
fixed-length records:
FILE SECTION.
FD COMMUTER-FILE-MST
RECORDING MODE IS F
BLOCK CONTAINS 0 RECORDS
RECORD CONTAINS 80 CHARACTERS.
01 COMMUTER-RECORD-MST.
05 COMMUTER-NUMBER PIC X(16).
05 COMMUTER-DESCRIPTION PIC X(64).

A recording mode of S is not supported for files in the HFS. The above example is
appropriate for such a file.

RELATED CONCEPTS
“Logical records”

RELATED TASKS
“Requesting fixed-length format” on page 121
“Requesting variable-length format” on page 122
“Requesting spanned format” on page 124
“Requesting undefined format” on page 126
“Defining QSAM files and records in COBOL” on page 119

Logical records
The term logical record is used in a slightly different way in the COBOL language
and in z/OS QSAM. For format-V and format-S files, the QSAM logical record
includes a 4-byte prefix in front of the user data portion of the record that is not
included in the definition of a COBOL logical record. For format-F and format-U
files, and for HFS byte-stream files, the definitions of QSAM logical record and
COBOL logical record are identical.

120 Programming Guide


In this information, QSAM logical record refers to the QSAM definition, and logical
record refers to the COBOL definition.

RELATED REFERENCES
“Layout of format-F records”
“Layout of format-V records” on page 123
“Layout of format-S records” on page 125
“Layout of format-U records” on page 126

Requesting fixed-length format


Fixed-length records are in format F. Use RECORDING MODE F to explicitly request
this format.

You can omit the RECORDING MODE clause. The compiler determines the recording
mode to be F if the length of the largest level-01 record associated with the file is
not greater than the block size coded in the BLOCK CONTAINS clause, and you take
one of the following actions:
v Use the RECORD CONTAINS integer clause (RECORD clause format 1).
When you use this clause, the file is always fixed format with record length
integer, even if there are multiple level-01 record description entries with
different lengths associated with the file.
v Omit the RECORD CONTAINS integer clause, but code the same fixed size and no
OCCURS DEPENDING ON clause for all level-01 record description entries associated
with the file. This fixed size is the record length.

In an unblocked format-F file, the logical record is the same as the block.

In a blocked format-F file, the number of logical records in a block (the blocking
factor) is constant for every block in the file, except the last block, which might be
shorter. Files in the HFS are never blocked.

RELATED CONCEPTS
“Logical records” on page 120

RELATED TASKS
“Requesting variable-length format” on page 122
“Requesting spanned format” on page 124
“Requesting undefined format” on page 126
“Establishing record formats” on page 120

RELATED REFERENCES
“Layout of format-F records”

Layout of format-F records: The layout of format-F QSAM records is shown


below.

Chapter 9. Processing QSAM files 121


RELATED CONCEPTS
“Logical records” on page 120

RELATED TASKS
“Requesting fixed-length format” on page 121
Fixed-length record formats (z/OS DFSMS: Using Data Sets)

RELATED REFERENCES
“Layout of format-V records” on page 123
“Layout of format-S records” on page 125
“Layout of format-U records” on page 126

Requesting variable-length format


Variable-length records can be in format V or format D. Format-D records are
variable-length records on ASCII tape files. Format-D records are processed in the
same way as format-V records. Use RECORDING MODE V for both.

You can omit the RECORDING MODE clause. The compiler determines the recording
mode to be V if the largest level-01 record associated with the file is not greater
than the block size set in the BLOCK CONTAINS clause, and you take one of the
following actions:
v Use the RECORD IS VARYING clause (RECORD clause format 3).
If you provide values for integer-1 and integer-2 (RECORD IS VARYING FROM
integer-1 TO integer-2), the maximum record length is the value coded for
integer-2, regardless of the lengths coded in the level-01 record description
entries associated with the file.
If you omit integer-1 and integer-2, the maximum record length is determined to
be the size of the largest level-01 record description entry associated with the
file.
v Use the RECORD CONTAINS integer-1 TO integer-2 clause (RECORD clause format 2).
Make integer-1 and integer-2 match the minimum length and the maximum
length of the level-01 record description entries associated with the file. The
maximum record length is the integer-2 value.
v Omit the RECORD clause, but code multiple level-01 records (associated with the
file) that are of different sizes or contain an OCCURS DEPENDING ON clause.
The maximum record length is determined to be the size of the largest level-01
record description entry associated with the file.

When you specify a READ INTO statement for a format-V file, the record size read
for that file is used in the MOVE statement generated by the compiler. Consequently,
you might not get the result you expect if the record just read does not correspond
to the level-01 record description. All other rules of the MOVE statement apply. For
example, when you specify a MOVE statement for a format-V record read in by the
READ statement, the size of the record moved corresponds to its level-01 record
description.

When you specify a READ statement for a format-V file followed by a MOVE of the
level-01 record, the actual record length is not used. The program will attempt to
move the number of bytes described by the level-01 record description. If this
number exceeds the actual record length and extends outside the area addressable
by the program, results are unpredictable. If the number of bytes described by the
level-01 record description is shorter than the physical record read, truncation of
bytes beyond the 01-level description occurs. To find the actual length of a
variable-length record, specify data-name-1 in format 3 of the RECORD clause of the
File Definition (FD).
122 Programming Guide
RELATED TASKS
“Requesting fixed-length format” on page 121
“Requesting spanned format” on page 124
“Requesting undefined format” on page 126
“Establishing record formats” on page 120

RELATED REFERENCES
“Layout of format-V records”
Moving from the VS COBOL II run time (Enterprise COBOL Compiler and Run-Time
Migration Guide)

Layout of format-V records: Format-V QSAM records have control fields (shown
below) preceding the data. The QSAM logical record length is determined by
adding 4 bytes (for the control fields) to the record length defined in your
program, but you must not include these 4 bytes in the description of the record
and record length.

CC The first 4 bytes of each block contain control information.


LL Represents 2 bytes designating the length of the block (including the
’CC’ field).
BB Represents 2 bytes reserved for system use.
cc The first 4 bytes of each logical record contain control information.
ll Represents 2 bytes designating the logical record length (including the
’cc’ field).
bb Represents 2 bytes reserved for system use.

The block length is determined as follows:


v Unblocked format-V records: CC + cc + the data portion
v Blocked format-V records: CC + the cc of each record + the data portion of each
record

The operating system provides the control bytes when the file is written; the
control byte fields do not appear in your description of the logical record in the
DATA DIVISION of your program. COBOL allocates input and output buffers large
enough to accommodate the control bytes. These control fields in the buffer are not
available for you to use in your program. When variable-length records are written
on unit record devices, control bytes are neither printed nor punched. They appear,
however, on other external storage devices, as well as in buffer areas of storage. If
you move V-mode records from an input buffer to a WORKING-STORAGE area, they’ll
be moved without the control bytes.

Files in the HFS are never blocked.

Chapter 9. Processing QSAM files 123


RELATED CONCEPTS
“Logical records” on page 120

RELATED TASKS
“Requesting variable-length format” on page 122

RELATED REFERENCES
“Layout of format-F records” on page 121
“Layout of format-S records” on page 125
“Layout of format-U records” on page 126

Requesting spanned format


Spanned records are in format S. A spanned record is a QSAM logical record that
can be contained in one or more physical blocks. You can code RECORDING MODE S
for spanned records in QSAM files assigned to magnetic tape or to direct access
devices. Do not request spanned records for files in the HFS.

You can omit the RECORDING MODE clause. The compiler determines the recording
mode to be S if the maximum record length plus 4 is greater than the block size set
in the BLOCK CONTAINS clause.

For files with format S in your program, the compiler determines the maximum
record length with the same rules used for format V. The length is based on your
usage of the RECORD clause.

When creating files containing format-S records, and a record is larger than the
remaining space in a block, COBOL writes a segment of the record to fill the block.
The rest of the record is stored in the next block or blocks, depending on its length.
COBOL supports QSAM spanned records up to 32,760 bytes long.

When retrieving files with format-S records, your program can retrieve only
complete records.

Benefits of format-S files: You can efficiently use external storage and still
organize your files with logical record lengths by defining files with format-S
records:
v You can set block lengths to efficiently use track capacities on direct access
devices.
v You are not required to adjust the logical record lengths to device-dependent
physical block lengths. One logical record can span two or more physical blocks.
v You have greater flexibility when you want to transfer logical records between
direct access storage types.

You will, however, have additional overhead in processing format-S files.

Format-S files and READ INTO: By specifying a READ INTO statement for a
format-S file, the record size just read for that file is used in the MOVE statement
generated by the compiler. Consequently, you might not get the result you expect
if the record just read does not correspond to the level-01 record description. All
other rules of the MOVE statement apply.

RELATED CONCEPTS
“Logical records” on page 120
“Spanned blocked and unblocked files” on page 125

124 Programming Guide


RELATED TASKS
“Requesting fixed-length format” on page 121
“Requesting variable-length format” on page 122
“Requesting undefined format” on page 126
“Establishing record formats” on page 120

RELATED REFERENCES
“Layout of format-S records”

Spanned blocked and unblocked files: A spanned blocked QSAM file is made
up of blocks, each containing one or more logical records or segments of logical
records. The logical records can be either fixed or variable in length and their size
can be smaller than, equal to, or larger than the physical block size. There are no
required relationships between logical records and physical block sizes.

A spanned unblocked file is made up of physical blocks, each containing one


logical record or one segment of a logical record. The logical records can be either
fixed or variable in length. When the physical block contains one logical record,
the block length is determined by the logical record size. When a logical record has
to be segmented, the system always writes the largest physical block possible. The
system segments the logical record when the entire logical record cannot fit on a
track.

RELATED CONCEPTS
“Logical records” on page 120

RELATED TASKS
“Requesting spanned format” on page 124

Layout of format-S records: Spanned records are preceded by control fields, as


shown below.

Each block is preceded by a block descriptor field. There is only one block
descriptor field at the beginning of each physical block.

Each segment of a record in a block, even if the segment is the entire record, is
preceded by a segment descriptor field. There is one segment descriptor field for
each record segment in the block. The segment descriptor field also indicates
whether the segment is the first, the last, or an intermediate segment.

You do not describe these fields in the DATA DIVISION of your COBOL program,
and the fields are not available for you to use in your program.

RELATED TASKS
“Requesting spanned format” on page 124

RELATED REFERENCES
“Layout of format-F records” on page 121
“Layout of format-V records” on page 123
“Layout of format-U records” on page 126

Chapter 9. Processing QSAM files 125


Requesting undefined format
Format-U records have undefined or unspecified characteristics. With format U,
you can process blocks that do not meet format-F or format-V specifications.

When you use format-U files, each block of storage is one logical record. A read of
a format-U file returns the entire block as a record, and a write to a format-U file
writes a record out as a block.

The compiler determines the recording mode to be U only if you code RECORDING
MODE U.

It is recommended that you not use format U to update or extend a file that was
written with a different record format. If you use format U to update a file that
was written with a different format, the RECFM in the data set label could be
changed or the data set could contain records written in different formats.

The record length is determined in your program based on how you use the
RECORD clause:
v If you use the RECORD CONTAINS integer clause (RECORD clause format 1), the record
length is the integer value, regardless of the lengths of the level-01 record
description entries associated with the file.
v If you use the RECORD IS VARYING clause (RECORD clause format 3), the record
length is determined based on whether you code integer-1 and integer-2.
If you code integer-1 and integer-2 (RECORD IS VARYING FROM integer-1 TO
integer-2), the maximum record length is the integer-2 value, regardless of the
lengths of the level-01 record description entries associated with the file.
If you omit integer-1 and integer-2, the maximum record length is determined to
be the size of the largest level-01 record description entry associated with the
file.
v If you use the RECORD CONTAINS integer-1 TO integer-2 clause (RECORD clause
format 2), with integer-1 and integer-2 matching the minimum length and the
maximum length of the level-01 record description entries associated with the
file, the maximum record length is the integer-2 value.
v If you omit the RECORD clause, the maximum record length is determined to be
the size of the largest level-01 record description entry associated with the file.

Format-U files and READ INTO: When you specify a READ INTO statement for a
format-U file, the size of the record just read for that file is used in the MOVE
statement generated by the compiler. Consequently, you might not get the result
you expect if the record just read does not correspond to the level-01 record
description. All other rules of the MOVE statement apply.

RELATED TASKS
“Requesting fixed-length format” on page 121
“Requesting variable-length format” on page 122
“Requesting spanned format” on page 124
“Establishing record formats” on page 120

RELATED REFERENCES
“Layout of format-U records”

Layout of format-U records: Each block of external storage is handled as a logical


record. There are no record-length or block-length fields.

126 Programming Guide


RELATED CONCEPTS
“Logical records” on page 120

RELATED TASKS
“Requesting undefined format” on page 126

RELATED REFERENCES
“Layout of format-F records” on page 121
“Layout of format-V records” on page 123
“Layout of format-S records” on page 125

Setting block sizes


In COBOL, you establish the size of a physical record with the BLOCK CONTAINS
clause. If you omit this clause, the compiler assumes that the records are not
blocked. Blocking QSAM files on tape and disk can enhance processing speed and
minimize storage requirements. You can block UNIX system services files
(including those in the HFS), PDSE members, and spooled data sets, but doing so
has no effect on how the system stores the data.

If you set the block size explicitly in the BLOCK CONTAINS clause, it must not be
greater than the maximum block size for the device. The block size set for a
format-F file must be an integral multiple of the record length.

If your program uses QSAM files on tape, use a physical block size of at least 12 to
18 bytes. Otherwise, the block will be skipped over when a parity check occurs
while doing one of the following:
v Reading a block of records of fewer than 12 bytes
v Writing a block of records of fewer than 18 bytes

Generally larger blocks give you better performance. Blocks of only a few kilobytes
are particularly inefficient; you should choose a block size of at least tens of
kilobytes. If you specify record blocking and omit the block size, the system will
pick a block size that is optimal for device utilization and for data transfer speed.

Letting z/OS determine block size


We recommend that to maximize performance, you not explicitly set the block size
for a blocked file in your COBOL source program. For new blocked data sets, it is
simpler to allow z/OS to supply a system-determined block size. To use this
feature, follow these guidelines:
v Code BLOCK CONTAINS 0 in your source program.
v Do not code RECORD CONTAINS 0 in your source program.
v Do not code a BLKSIZE value in the JCL DD statement.

Setting block size explicitly


If you prefer to set a block size explicitly, your program will be most flexible if you
follow these guidelines:
v Code BLOCK CONTAINS 0 in your source program.
v Code a BLKSIZE value in the ddname definition (the JCL DD statement).

Chapter 9. Processing QSAM files 127


For extended-format data sets on z/OS DFSMS adds a 32-byte block suffix to the
physical record. If you specify a block size explicitly (using JCL or ISPF), do not
include the size of this block suffix in the block size. This block suffix is not
available for you to use in your program. DFSMS allocates the space used to read
in the block suffix. However, when you calculate how many blocks of a
extended-format data set will fit on a track of a direct access device, you need to
include the size of the block suffix in the block size.

If you specify a block size larger than 32760 directly on your BLOCK CONTAINS
clause or indirectly with the use of BLOCK CONTAINS n RECORDS, and you do not
meet both the following conditions, the OPEN of the data set fails with file status
code 90:
v You use OS/390 V2R10.0 DFSMS or later.
v You define the data set to be tape.

For existing blocked data sets, it is simplest to:


v Code BLOCK CONTAINS 0 in your source program.
v Code no BLKSIZE value in the ddname definition.

When you omit the BLKSIZE from the ddname definition, the block size is
automatically obtained by the system from the data set label.

Taking advantage of LBI


You can improve the performance of tape data sets by using OS/390 V2R10.0
DFSMS or later, which provides the large block interface (LBI) for large block sizes.
When it is available, the COBOL run time automatically uses this facility for those
tape files for which you use system-determined block size. LBI is also used for
those files for which you explicitly define a block size in JCL or a BLOCK CONTAINS
clause. Use of the LBI allows block sizes to exceed 32760 if the tape device
supports it.

The LBI is not used in all cases. An attempt to use a block size greater than 32760
in the following cases is diagnosed at compile time or results in a failure at OPEN:
v Spanned records
v OPEN I-O

Using a block size that exceeds 32760 might result in your not being able to read
the tape on another system. A tape that you create with a block size greater than
32760 can be read only on an MVS system that uses OS/390 V2R10.0 DFSMS or
later and has a tape device that supports block sizes greater than 32760. If you
specify a block size that is too large for the file, the device, or the operating system
level, a run-time message is issued.

To limit a system-determined block size to 32760, do not specify BLKSIZE anywhere,


and set one of the following to 32760. The block-size limit is the first nonzero value
supplied in the following order of precedence:
1. Specify the BLKSZLIM keyword on your DD statement for the data set.
2. Have your systems programmer set BLKSZLIM for the data class using the
BLKSZLIM keyword.
3. Have your systems programmer set a block-size limit for the system in the
DEVSUPxx member of SYS1.PARMLIB using the keyword TAPEBLKSZLIM.

128 Programming Guide


If no BLKSIZE or BLKSZLIM value is available from any source, the system limits
BLKSIZE to 32760. You can then enable block sizes larger than 32760 in one of two
ways:
v Specify a BLKSZLIM value greater than 32760 in the DD statement for the file and
use BLOCK CONTAINS 0 in your COBOL source.
v Specify a value greater than 32760 for the BLKSIZE in the DD statement or in the
BLOCK CONTAINS clause in your COBOL source.

BLKSZLIM is device-independent.

Block size and the DCB RECFM subparameter


Under z/OS, you can code the S or T option in the DCB RECFM subparameter:
v Use the S (standard) option in the DCB RECFM subparameter for a format-F record
with only standard blocks (ones that have no truncated blocks or unfilled tracks
in the file, except for the last block of the file). S is also supported for records on
tape. It is ignored if the records are not on DASD or tape.
Using this standard block option might improve input-output performance,
especially for direct access devices.
v The T (track overflow) option for QSAM files is no longer useful.

RELATED TASKS
“Defining QSAM files and records in COBOL” on page 119
z/OS DFSMS: Using Data Sets

RELATED REFERENCES
BLOCK CONTAINS clause (Enterprise COBOL Language Reference)

Coding input and output statements for QSAM files


Code the following input and output statements to process a QSAM file or a
byte-stream file in the HFS using QSAM:
OPEN Makes the file available to your program.
You can open all QSAM files as INPUT, OUTPUT, or EXTEND (depending on
device capabilities).
You can also open QSAM files on direct access storage devices as I-O. You
cannot open HFS files as I-O; you will receive a file status of 37 if you
attempt to do so.
READ Reads a record from the file.
With sequential processing, your program reads one record after another in
the same order in which they were entered when the file was created.
WRITE Creates a record in the file.
Your program writes new records to the end of the file.
REWRITE
Updates a record. You cannot update a file in the HFS using REWRITE.
CLOSE Releases the connection between the file and your program.

RELATED TASKS
“Opening QSAM files” on page 130
“Adding records to QSAM files” on page 131

Chapter 9. Processing QSAM files 129


“Updating QSAM files” on page 131
“Writing QSAM files to a printer or spooled data set” on page 131
“Closing QSAM files” on page 132

RELATED REFERENCES
OPEN statement (Enterprise COBOL Language Reference)
READ statement (Enterprise COBOL Language Reference)
WRITE statement (Enterprise COBOL Language Reference)
REWRITE statement (Enterprise COBOL Language Reference)
CLOSE statement (Enterprise COBOL Language Reference)
Status key (Common processing facilities) (Enterprise COBOL Language Reference)

Opening QSAM files


Before your program can use any READ, WRITE, or REWRITE statements to process
records in a file, it must first open the file with an OPEN statement.

An OPEN statement works if both of the following are true:


v The file is available or has been dynamically allocated.
v The fixed file attributes coded in the ddname definition or the data set label for a
file match the attributes coded for that file in the SELECT and FD statements of
your COBOL program.
Mismatches in the file organization attributes, code set, maximum record size, or
record type (fixed or variable) result in a file status code 39, and the OPEN
statement fails. Mismatches in maximum record size and record type are not
considered errors when opening files in the HFS.
For fixed-length QSAM files, when you code RECORD CONTAINS 0 in the FD, the
record size attributes are not in conflict. The record size is taken from the DD
statement or the data set label, and the OPEN statement is successful.

Code CLOSE WITH LOCK so that the file cannot be opened again while the program
is running.

Use the REVERSED option of the OPEN statement to process tape files in reverse order.
Execution of the OPEN statement will then position the file at its end. Subsequent
READ statements read the data records in reverse order, starting with the last record.
The REVERSED option is supported only for files with fixed-length records.

RELATED TASKS
“Dynamically creating QSAM files with CBLQDA”

RELATED REFERENCES
OPEN statement (Enterprise COBOL Language Reference)

Dynamically creating QSAM files with CBLQDA


A file is considered to be available on z/OS when it has been identified to the
operating system using a DD statement, an export command (an environment
variable), or a TSO ALLOCATE command. (For availability, a DD statement with a
misspelled ddname is equivalent to a missing DD statement; an environment
variable with a value that is not valid is equivalent to an unset variable.)

Sometimes a QSAM file is unavailable on the operating system, but the COBOL
language defines that the file be created. The file is implicitly created for you if
you use the run-time option CBLQDA and one of the following circumstances exists:
v The file is being opened for OUTPUT, regardless of the OPTIONAL phrase.

130 Programming Guide


v An OPTIONAL file is being opened as EXTEND or I-O.
Optional files are files that are not necessarily present each time the program is
run. You can define files opened in INPUT, I-O, or EXTEND mode as optional by
using the SELECT OPTIONAL phrase in the FILE-CONTROL paragraph.

The file is allocated with the system default attributes established at your
installation and the attributes coded in the SELECT and FD statements in your
program.

Do not confuse this implicit allocation mechanism with the dynamic allocation of
files through the use of environment variables. That explicit dynamic allocation
requires a valid environment variable to be set. This CBLQDA support is used only
when the QSAM file is unavailable as defined above, which includes no valid
environment variable being set.

Under z/OS, files created using the CBLQDA option are temporary data sets and do
not exist after the program has run.

RELATED TASKS
“Opening QSAM files” on page 130

Adding records to QSAM files


To add to a QSAM file, open the file as EXTEND and use the WRITE statement to add
records immediately after the last record in the file.

To add records to a file opened as I-O, you must first close the file and open it as
EXTEND.

RELATED REFERENCES
READ statement (Enterprise COBOL Language Reference)
WRITE statement (Enterprise COBOL Language Reference)

Updating QSAM files


You can update QSAM files that reside on direct access storage devices only. You
cannot update files in the HFS.

Replace an existing record with another record of the same length by doing these
steps:
1. Open the file as I-O.
2. Use REWRITE to update an existing record in the file. (The last file processing
statement before REWRITE must have been a successful READ statement.)

You cannot open as I-O an extended format data set that you allocate in the
compressed format.

RELATED REFERENCES
REWRITE statement (Enterprise COBOL Language Reference)

Writing QSAM files to a printer or spooled data set


COBOL provides language statements to control the size of a printed page and
control the vertical positioning of records.

Chapter 9. Processing QSAM files 131


Controlling the page size
Use the LINAGE clause of the FD entry to control the size of your printed page: the
number of lines in the top and bottom margins and in the footing area of the page.
When you use the LINAGE clause, COBOL handles the file as if you had also
requested the ADV compiler option.

If you use the LINAGE clause in combination with WRITE BEFORE/AFTER ADVANCING
nn LINES, be careful about the values you set. With the ADVANCING nn LINES clause,
COBOL first calculates the sum of LINAGE-COUNTER plus nn. Subsequent actions
depend on the size of nn. The END-OF-PAGE imperative statement is performed after
the LINAGE-COUNTER is increased. Consequently, the LINAGE-COUNTER could be
pointing to the next logical page instead of to the current footing area when the
END-OF-PAGE statement is performed.

AT END-OF-PAGE or NOT AT END-OF-PAGE imperative statements are performed only


if the write operation completes successfully. If the write operation is unsuccessful,
control is passed to the end of the WRITE statement, omitting all conditional
phrases.

Controlling the vertical positioning of records


Use the WRITE ADVANCING statement to control the vertical positioning of each
record you write on a printed page.

. . . BEFORE ADVANCING prints the record before the page is advanced.


. . . AFTER ADVANCING prints the record after the page is advanced.

Specify the number of lines the page is advanced with an integer (or an identifier
with a mnemonic-name) following ADVANCING. If you omit the ADVANCING option from
your WRITE statement, you get the equivalent of:
AFTER ADVANCING 1 LINE

RELATED REFERENCES
WRITE statement (Enterprise COBOL Language Reference)

Closing QSAM files


Use the CLOSE statement to disconnect your program from the QSAM file. If you
try to close a file that is already closed, you will get a logic error.

If you do not close a QSAM file, the file is automatically closed for you under the
following conditions, except for files defined in any OS/VS COBOL programs in
the run unit:
v When the run unit ends normally, the run time closes all open files that are
defined in any COBOL programs in the run unit.
v If the run unit ends abnormally and you have set the TRAP(ON) run-time option,
the run time closes all open files that are defined in any COBOL programs in the
run unit.
v When Language Environment condition handling is completed and the
application resumes in a routine other than where the condition occurred, the
run time closes all open files that are defined in any COBOL programs in the
run unit that might be called again and reentered.
You can change the location where the program resumes running (after a
condition is handled) by moving the resume cursor with the Language
Environment CEEMRCR callable service or by using HLL language constructs
such as a C longjmp.

132 Programming Guide


v When you use CANCEL for a COBOL subprogram, the run time closes any open
nonexternal files that are defined in that program.
v When a COBOL subprogram with the INITIAL attribute returns control, the run
time closes any open nonexternal files that are defined in that program.
v When a thread of a multithreaded application ends, both external and
nonexternal files that you opened from within that same thread are closed.

File status key data items that you define in the WORKING-STORAGE SECTION are set
when these implicit CLOSE operations are performed, but your EXCEPTION/ERROR
and LABEL declaratives are not invoked.

If you open a QSAM file in a multithreaded application, you must close it from the
same thread of execution from which the file was opened. Attempting to close the
file from a different thread results in a close failure with file-status condition 90.

RELATED REFERENCES
CLOSE statement (Enterprise COBOL Language Reference)

Handling errors in QSAM files


When an input-statement or output-statement operation fails, COBOL does not
take corrective action for you. You choose whether or not your program will
continue running after a less-than-severe input or output error occurs.

COBOL provides these ways for you to intercept and handle certain QSAM input
and output errors:
v End of file phrase (AT END)
v EXCEPTION/ERROR declarative
v FILE STATUS clause
v INVALID KEY phrase

If you do not code a FILE STATUS key or a declarative, serious QSAM processing
errors will cause a message to be issued and a Language Environment condition to
be signaled, which will cause an abend if you specify the run-time option
ABTERMENC(ABEND).

If you use the FILE STATUS clause or the EXCEPTION/ERROR declarative, code
EROPT=ACC in the DCB of the DD statement for that file. Otherwise, your COBOL
program will not be able to continue processing after some error conditions.

If you use the FILE STATUS clause, be sure to check the key and take appropriate
action based on its value. If you do not check the key, your program might
continue, but the results will probably not be what you expected.

RELATED TASKS
“Handling errors in input and output operations” on page 203

Working with QSAM files


This section describes:
v “Defining and allocating QSAM files” on page 134
v “Retrieving QSAM files” on page 136
v “Ensuring file attributes match your program” on page 137

Chapter 9. Processing QSAM files 133


v “Using striped extended-format QSAM data sets” on page 139

RELATED REFERENCES
“Allocation of buffers for QSAM files” on page 140

Defining and allocating QSAM files


You can define a QSAM file or a byte-stream file in the HFS using either a DD
statement or an environment variable. When you use an environment variable, the
name must be in uppercase. Allocation of these files follows the general rules for
the allocation of COBOL files. When you use an environment variable to define a
QSAM file, specify the MVS data set as follows:

DSN(dataset-name) or DSN(dataset-name(member-name)). dataset-name must be fully


qualified and cannot be a temporary data set (that is, it must not start with &).

You can optionally specify the following attributes in any order following the DSN:
v A disposition value, one of: NEW, OLD, SHR, or MOD
v TRACKS or CYL
v SPACE(nnn,mmm)
v VOL(volume-serial)
v UNIT(type)
v KEEP, DELETE, CATALOG, or UNCATALOG
v STORCLAS(storage-class)
v MGMTCLAS(management-class)
v DATACLAS(data-class)

You can use either an environment variable or a DD definition to define a file in the
HFS. To do this, define one of the following with a name that matches the external
name on your ASSIGN clause:
v A DD allocation that uses PATH=’absolute-path-name’ and FILEDATA=BINARY
v An environment variable with a value PATH(pathname), where pathname is an
absolute path name (starting with /).

For compatibility with releases of COBOL before COBOL for OS/390 & VM
Version 2 Release 2, you can also specify FILEDATA=TEXT when using a DD allocation
for HFS files, but this use is not recommended. To process text files in the HFS, use
LINE SEQUENTIAL organization. If you do use QSAM to process text files in the HFS,
you cannot use environment variables to define the files.

When you define a QSAM file, use the specified parameters to do the following:
Table 19. QSAM file allocation
What you want to do DD parameter to use EV keyword to use
Name the file DSNAME (data set name) DSN
Select the type and quantity of UNIT UNIT for type only
input-output devices to be
allocated for the file.
Give instructions for the volume in VOLUME, or let the system VOL
which the file will reside and for choose an output volume.
volume mounting.

134 Programming Guide


Table 19. QSAM file allocation (continued)
What you want to do DD parameter to use EV keyword to use
Allocate the type and amount of SPACE SPACE for the amount of
space the file needs. (For direct space (primary and
access storage devices only.) secondary only); TRACKS
or CYL for the type of
space
Specify the type (and some of the LABEL n/a
contents of) the label associated
with the file.
Indicate whether you want to DISP NEW, OLD, SHR, MOD plus
catalog, pass, or keep the file after KEEP, DELETE, CATALOG, or
the job step is completed. UNCATALOG
Complete any data control block DCB subparameters n/a
information that you want to add.

Some of the information about the QSAM file must always be coded in the
FILE-CONTROL entry, the FD entry, and other COBOL clauses. Other information
must be coded in the DD statement or environment variable for output files. For
input files, the system can obtain information from the file label (for standard label
files). If DCB information is provided in the DD statement for input files, it overrides
information on the data set label. For example, the amount of space allocated for a
new direct-access device file can be set in the DD statement by the SPACE parameter.

You cannot express certain characteristics of QSAM files in the COBOL language,
but you can code them in the DD statement for the file using the DCB parameter. Use
the subparameters of the DCB parameter to provide information that the system
needs for completing the data set definition, including the following:
v Block size (BLKSIZE=), if BLOCK CONTAINS 0 RECORDS was coded at compile time
(which is recommended)
v Options to be executed if an error occurs in reading or writing a record
v TRACK OVERFLOW or standard blocks
v Mode of operation for a card reader or punch

DCB attributes coded for a DD DUMMY do not override those coded in the FD entry of
your COBOL program.

RELATED TASKS
“Setting block sizes” on page 127
“Defining QSAM files and records in COBOL” on page 119
“Allocating files” on page 117

RELATED REFERENCES
“Parameters for creating QSAM files”
MVS JCL Reference

Parameters for creating QSAM files


The following DD statement parameters are frequently used to create QSAM files.

Chapter 9. Processing QSAM files 135


dataset-name
DSNAME=
dataset-name(member-name)
DSN= &&name
&&name(member-name)

UNIT= ( name[,unitcount] )
VOLUME= ( [PRIVATE] [,RETAIN] [,vol-sequence-num] [,volume-count] ...
VOL=
... ,SER=(volume-serial[,volume-serial]...)
(
,REF= dsname
*.ddname
*.stepname.ddname
*.stepname.procstep.ddname

SPACE= ( TRK ,(primary-quantity[,secondary-quantity][,directory-quantity]))


CYL
average-record-length

LABEL= ( [Data-set-sequence-number,] NL ,EXPDT= yyddd (


SL yyyy/ddd
SUL ,RETPD=xxxx

DISP= ( NEW ,DELETE ,DELETE )


MOD ,KEEP ,KEEP
,PASS ,CATLG
,CATLG

DCB= ( subparameter-list )

RELATED TASKS
“Defining and allocating QSAM files” on page 134

Retrieving QSAM files


You retrieve QSAM files, cataloged or not, by using job control statements or
environment variables.
Cataloged files
All data set information, such as volume and space, is stored in the catalog
and file label. All you have to code are the data set name and a
disposition. When you use a DD statement, this is the DSNAME parameter and
the DISP parameter. When you use an environment variable, this is the DSN
parameter and one of the parameters OLD, SHR, or MOD.
Noncataloged files
Some information is stored in the file label, but you must code the unit
and volume information as well as the dsname and disposition.

If you are using JCL, and you created the file in the current job step or in a
previous job step in the current job, you can refer to the previous DD statement for
most of the data set information. You do, however, need to code DSNAME and DISP.

RELATED REFERENCES
“Parameters for retrieving QSAM files”

Parameters for retrieving QSAM files


The following DD statement parameters are used to retrieve previously created files.

136 Programming Guide


RELATED TASKS
“Retrieving QSAM files” on page 136

Ensuring file attributes match your program


When the fixed file attributes coded in the DD statement or the data set label for a
file and the attributes coded for that file in the SELECT and FD statements of your
COBOL program are not consistent, an OPEN statement in your program might not
work. Mismatches in the attributes for file organization, record format (fixed or
variable), record length, or the code set result in a file status code 39, and the OPEN
statement fails. An exception exists for files in the HFS: mismatches in record
format and record length do not cause an error.

To prevent common file status 39 problems, follow the guidelines listed below for
processing files that are existing, new, or dynamically created by COBOL.

Remember that information in the JCL or environment variable overrides


information in the data set label.

Processing existing files


When your program processes an existing file, code the description of the file in
your COBOL program to be consistent with the file attributes of the data set. Use
these guidelines to define the maximum record length.
Table 20. Maximum record length of QSAM files
For this format Specify this
V or S Exactly 4 bytes smaller than the length attribute of the data set
F Same as the length attribute of the data set
U Same as the length attribute of the data set

Chapter 9. Processing QSAM files 137


Defining variable-length (format-V) records
The easiest way to define variable-length records in your program is to use RECORD
IS VARYING FROM integer-1 TO integer-2 in the FD entry and set an appropriate value
for integer-2. For example, assume that you have determined the length attribute of
the data set to be 104 (LRECL=104). Remembering that the maximum record length
is determined from the RECORD IS VARYING clause (in which values are set) and not
from the level-01 record descriptions, you could define a format-V file in your
program with this code:
FILE SECTION.
FD COMMUTER-FILE-MST
RECORDING MODE IS V
RECORD IS VARYING FROM 4 TO 100 CHARACTERS.
01 COMMUTER-RECORD-A PIC X(4).
01 COMMUTER-RECORD-B PIC X(75).

Defining format-U records


Assume that the existing file in the previous example was format-U instead of
format-V. If the 104 bytes are all user data, you could define the file in your
program with this code:
FILE SECTION.
FD COMMUTER-FILE-MST
RECORDING MODE IS U
RECORD IS VARYING FROM 4 TO 104 CHARACTERS.
01 COMMUTER-RECORD-A PIC X(4).
01 COMMUTER-RECORD-B PIC X(75).

Defining fixed-length records


To define fixed-length records in your program, use either the RECORD CONTAINS
integer clause, or omit this clause and code all level-01 record descriptions to be the
same fixed size. In either case, use a value that equals the value of the length
attribute of the data set. When you intend to use the same program to process
different files at run time and the files have differing fixed-length record lengths,
the recommended way to avoid record-length conflicts is to code RECORD CONTAINS
0.

If the existing file is an ASCII data set (DCB=(OPTCD=Q)), you must use the CODE-SET
clause in the program’s FD entry for the file.

Processing new files


When your COBOL program will write records to a new file that is made available
before the program is run, ensure that the file attributes you code in the DD
statement, the environment variable, or the allocation do not conflict with the
attributes you have coded in your program. Usually, you need to code only a
minimum of parameters when predefining your files.

When you do need to explicitly set a length attribute for the data set (for example,
you are using an ISPF allocation panel or if your DD statement is for a batch job in
which the program uses RECORD CONTAINS 0):
v For format-V and format-S files, set a length attribute that is 4 bytes larger than
that defined in the program.
v For format-F and format-U files, set a length attribute that is the same as that
defined in the program.
v If you open your file as OUTPUT and write it to a printer, the compiler might add
1 byte to the record length to account for the carriage control character,
depending on the ADV compiler option and the COBOL language used in your
program. In such a case, take the added byte into account when coding the
LRECL.

138 Programming Guide


For example, suppose your program contains the following code for a file with
variable-length records:
FILE SECTION.
FD COMMUTER-FILE-MST
RECORDING MODE IS V
RECORD CONTAINS 10 TO 50 CHARACTERS.
01 COMMUTER-RECORD-A PIC X(10).
01 COMMUTER-RECORD-B PIC X(50).

The LRECL in your DD statement or allocation should be 54.

Processing files dynamically created by COBOL


When you have not made a file available with a DD statement or a TSO ALLOCATE
command and your COBOL program defines that the file be created, Enterprise
COBOL dynamically allocates the file. When the file is opened, the file attributes
coded in your program are used. You do not have to worry about file attribute
conflicts.

RELATED TASKS
“Requesting fixed-length format” on page 121
“Requesting variable-length format” on page 122
“Requesting undefined format” on page 126
“Dynamically creating QSAM files with CBLQDA” on page 130

Using striped extended-format QSAM data sets


A striped extended-format QSAM data set is an extended-format QSAM data set
that is spread over multiple volumes, allowing parallel data access.

Striped extended-format QSAM data sets can benefit an application with these
characteristics:
v The application processes files that contain large volumes of data.
v The time for the input and output operations to the files significantly affects
overall performance.

For you to gain the maximum benefit from using QSAM striped data sets, DFSMS
needs to be able to allocate the required number of buffers above the 16-MB line.

When you develop applications that contain files allocated to QSAM striped data
sets, follow these guidelines:
v Avoid using a QSAM striped data set for a file that cannot have buffers
allocated above the 16-MB line.
v Omit the RESERVE clause in the FILE-CONTROL paragraph entry for the file.
Omitting the RESERVE clause allows DFSMS to determine the optimum number
of buffers for the data set.
v Compile your program with the DATA(31) and RENT compiler options, and make
the load module AMODE 31.
v Specify the ALL31(ON) run-time option if the file is an EXTERNAL file with
format-F, format-V, or format-U records.

Notice that all striped data sets are extended format data sets, but not all extended
format data sets are striped.

RELATED TASKS
z/OS DFSMS: Using Data Sets (performance considerations)

Chapter 9. Processing QSAM files 139


RELATED REFERENCES
“Allocation of buffers for QSAM files”

Allocation of buffers for QSAM files


DFSMS automatically allocates buffers for storing input and output for QSAM files
above or below the 16-MB line as appropriate for the file being used. Most QSAM
files have buffers allocated above the 16-MB line. Exceptions are:
v Programs running in AMODE 24.
v Programs compiled with the DATA(24) and RENT options.
v Programs compiled with the NORENT and RMODE(24) options.
v Programs compiled with the NORENT and RMODE(AUTO) options.
v EXTERNAL files, when the ALL31(OFF) run-time option is being specified. To
specify the ALL31(ON) run-time option, all programs in the run unit must be
capable of running in 31-bit addressing mode.
v Files allocated to the TSO terminal.
v A file with format-S (spanned) records, if the file is any of the following:
– An EXTERNAL file (even if the ALL31(ON) option is specified)
– A file specified in a SAME RECORD AREA clause of the I-O-CONTROL paragraph
– A blocked file that is opened I-O and updated using the REWRITE statement

RELATED CONCEPTS
“Storage and its addressability” on page 34

RELATED TASKS
“Using striped extended-format QSAM data sets” on page 139

Accessing HFS files using QSAM


You can process byte-stream files in the hierarchical file system (HFS) as
ORGANIZATION SEQUENTIAL files using QSAM. To do this, specify as the
assignment-name on the ASSIGN clause one of the following:
ddname
A DD allocation that identifies the file with the keywords PATH= and
FILEDATA=BINARY
Environment variable name
An environment variable with the run-time value of the HFS path for the
file

Observe the following restrictions:


v Spanned record format is not supported.
v OPEN I-O and REWRITE are not supported. If you attempt one of these operations,
you will get the following file status conditions:
– 37 from OPEN I-O
– 47 from REWRITE (because you could not have successfully opened the file as
I-O)

Usage notes
v File status 39 (fixed file attribute conflict) is not enforced for either of the
following:
– Record-length conflict
– Record-type conflict (fixed versus variable)

140 Programming Guide


v A READ returns the number of bytes equal to that of the maximum logical record
size for the file except for the last record, which might be shorter.
For example, suppose your file definition has 01 record descriptions of 3, 5, and
10 bytes long, and you write the following three records: ’abc’, ’defgh’, and
’ijklmnopqr’, in that order. Your first READ of this file returns ’abcdefghij’, your
second READ returns ’klmnopqr ’, and your third READ results in the AT END
condition.

For compatibility with releases of IBM COBOL before COBOL for OS/390 & VM
Version 2 Release 2, you can also specify FILEDATA=TEXT when using a DD allocation
for HFS files, but this use is not recommended. To process text files in the HFS, use
the LINE SEQUENTIAL organization. If you use QSAM to process text files in the
HFS, you cannot use environment variables to define the files.

RELATED TASKS
“Allocating files” on page 117
“Defining and allocating QSAM files” on page 134
Accessing HFS files via BSAM and QSAM (z/OS DFSMS: Using Data Sets)

Labels for QSAM files


You can use labels to identify magnetic tape and direct access volumes and data
sets. The operating system uses label processing routines to identify and verify
labels and locate volumes and data sets.

There are two kinds of labels: standard and nonstandard. IBM Enterprise COBOL
for z/OS does not support nonstandard user labels. In addition, standard user
labels contain user-specified information about the associated data set.

Standard labels consist of volume labels and groups of data set labels. Volume
labels precede or follow data on the volume, and identify and describe the volume.
The data set labels precede or follow each data set on the volume, and identify and
describe the data set.
v The data set labels that precede the data set are called header labels.
v The data set labels that follow the data set are called trailer labels.
They are similar to the header labels, except that they also contain a count of
blocks in the data set.
v The data set label groups can optionally include standard user labels.
v The volume label groups can optionally include standard user labels.

RELATED TASKS
“Using trailer and header labels”

RELATED REFERENCES
“Format of standard labels” on page 143

Using trailer and header labels


You can create, examine, or update user labels when the beginning or end of a
data set or volume (reel) is reached. End-of-volume or beginning-of-volume exits
are allowed. You can also create or examine intermediate trailers and headers.

You can create, examine, or update up to eight header labels and eight trailer
labels on each volume of the data set. (QSAM EXTEND works in a manner identical
to OUTPUT except that the beginning-of-file label is not processed.) Labels reside on

Chapter 9. Processing QSAM files 141


the initial volume of a multivolume data set. This volume must be mounted as
CLOSE if trailer labels are to be created, examined, or updated. Trailer labels for files
opened as INPUT or I-O are processed when a CLOSE statement is performed for the
file that has reached an AT END condition.

If you code a header or trailer with the wrong position number, the result is
unpredictable. (Data management might force the label to the correct relative
position.)

When you use standard label processing, code the label type of the standard and
user labels (SUL) on the DD statement that describes the data set.

Getting a user-label track


If you use a LABEL subparameter of SUL for direct access volumes, a separate
user-label track will be allocated when the data set is created. This additional track
is allocated at initial allocation and for sequential data sets at end-of-volume
(volume switch). The user-label track (one per volume of a sequential data set) will
contain both user header and user trailer labels. If a LABEL name is referenced
outside the user LABEL declarative, results are unpredictable.

Handling user labels


The USE AFTER LABEL declarative provides procedures for handling user labels on
supported files. The AFTER option indicates processing of standard user labels.

List the labels as data-names in the LABEL RECORDS clause in the FD entry for the file.
Table 21. Handling of QSAM user labels
When the file is
opened as: And: Result:
INPUT USE . . . LABEL declarative is The label is read and control is
coded for the OPEN option or for passed to the LABEL declarative.
the file.
OUTPUT USE . . . LABEL declarative is A buffer area for the label is
coded for the OPEN option or for provided and control is passed to
the file. the LABEL declarative.
INPUT or I-O CLOSE statement is performed Control is passed to the LABEL
for the file that has reached the declarative for processing trailer
AT END condition. labels.

You can specify a special exit by using the statement GO TO MORE-LABELS. When
this statement results in an exit from a label DECLARATIVE SECTION, the system does
one of the following:
v Writes the current beginning or ending label and then reenters the USE section at
its beginning to create more labels. After creating the last label, the system exits
by performing the last statement of the section.
v Reads an additional beginning or ending label, and then reenters the USE section
at its beginning to check more labels. When processing user labels, the system
reenters the section only if there is another user label to check. Hence, a program
path that flows through the last statement in the section is not needed.

If a GO TO MORE-LABELS statement is not performed for a user label, the


DECLARATIVE SECTION is not reentered to check or create any immediately
succeeding user labels.

142 Programming Guide


RELATED CONCEPTS
“Labels for QSAM files” on page 141

Format of standard labels


Standard labels are 80-character records that are recorded in EBCDIC or ASCII. The
first four characters are always used to identify the labels. The figure below shows
these identifiers for tape.
Table 22. Identifiers for standard tape labels
Identifier Description
VOL1 Volume label
HDR1 or HDR2 Data set header labels
EOV1 or EOV2 Data set trailer labels (end-of-volume)
EOF1 or EOF2 Data set trailer labels (end-of-data-set)
UHL1 to UHL8 User header labels
UTL1 to UTL8 User trailer labels

The format of the label for a direct-access volume is the almost the same as the
format of the label group for a tape volume label group. The difference is that a
data set label of the initial DASTO volume label consists of the data set control
block (DSCB). The DSCB appears in the volume table of contents (VTOC) and
contains the equivalent of the tape data set header and trailer, in addition to
control information such as space allocation.

Standard user labels


User labels are optional within the standard label groups.

The format used for user header labels (UHL1-8) and user trailer labels (UTL1-8)
consists of a label 80 characters in length recorded in either:
v EBCDIC on DASD or on IBM standard labeled tapes
v ASCII or ISO/ANSI labeled tapes

The first 3 bytes consist of the characters that identify the label as either:
v UHL for a user header label (at the beginning of a data set)
v UTL for a user trailer label (at the end-of-volume or end-of-data set)

The next byte contains the relative position of this label within a set of labels of the
same type. One through eight labels are permitted.

The remaining 76 bytes consist of user-specified information.

Standard user labels are not supported for QSAM striped data sets.

RELATED CONCEPTS
“Labels for QSAM files” on page 141

Chapter 9. Processing QSAM files 143


Processing QSAM ASCII files on tape
If your program processes an QSAM ASCII file, do the following:
1. Request the ASCII alphabet.
2. Define the record formats.
3. Define the ddname (with JCL).

In addition, if your program processes numeric data items from ASCII files, use the
separately signed numeric data type (SIGN IS LEADING SEPARATE).

The CODEPAGE compiler option has no effect on the code page used for conversions
between ASCII and EBCDIC for ASCII tape support. See the z/OS DFSMS
documentation for information about how CCSIDs used for the ASCII tape support
are selected and what the default CCSIDs are.

Requesting the ASCII alphabet


In the SPECIAL-NAMES paragraph, code STANDARD-1 for ASCII:
ALPHABET-NAME IS STANDARD-1

In the FD statement for the file, code:


CODE-SET IS ALPHABET-NAME

Defining the record formats


Process QSAM ASCII tape files with any of these record formats:
v Fixed length (format F)
v Undefined (format U)
v Variable length (format V)

If you are using variable-length records, you cannot explicitly code format D;
instead, code RECORDING MODE V. The format information is internally converted to
D mode. D-mode records have a 4-byte record descriptor for each record.

Defining the ddname


Under z/OS, processing ASCII files requires special JCL coding. Code these
subparameters of the DCB parameter in the DD statement:
BUFOFF=[L|n]
L A 4-byte block prefix that contains the block length (including the
block prefix).
n The length of the block prefix:
v For input, from 0 through 99
v For output, either 0 or 4

Use this value if you coded BLOCK CONTAINS 0.

BLKSIZE=n
n The size of the block, including the length of the block prefix.

LABEL=[AL|AUL|NL]

144 Programming Guide


AL American National Standard (ANS) labels.
AUL ANS and user labels.
NL No labels.

OPTCD=Q
Q This value is required for ASCII files and is the default if the file is
created using Enterprise COBOL.

RELATED TASKS
“Processing ASCII file labels”
Converting Character Data (z/OS DFSMS: Using Data Sets)

Processing ASCII file labels


Standard label processing for ASCII files is the same as standard label processing
for EBCDIC files. The system translates ASCII code into EBCDIC before processing.

All ANS user labels are optional. ASCII files can have user header labels (UHLn)
and user trailer labels (UTLn). There is no limit to the number of user labels at the
beginning and the end of a file; you can write as many labels as you need. All user
labels must be 80 bytes in length.

To create or verify user labels (user label exit), code a USE AFTER STANDARD LABEL
procedure. You cannot use USE BEFORE STANDARD LABEL procedures.

ASCII files on tape can have:


v ANS labels
v ANS and user labels
v No labels

Any labels on an ASCII tape must be in ASCII code only. Tapes containing a
combination of ASCII and EBCDIC cannot be read.

RELATED TASKS
“Processing QSAM ASCII files on tape” on page 144

Chapter 9. Processing QSAM files 145


146 Programming Guide
Chapter 10. Processing VSAM files
Virtual storage access method (VSAM) is an access method for files on
direct-access storage devices. With VSAM you can:
v Load a file
v Retrieve records from a file
v Update a file
v Add, replace, and delete records in a file

VSAM processing has these advantages over QSAM:


v Protection of data against unauthorized access
v Compatibility across systems
v Independence of devices (no need to be concerned with block size and other
control information)
v Simpler JCL (information needed by the system is provided in integrated
catalogs)
v Ability to use indexed file organization or relative file organization

The lists below show how VSAM terms differ from COBOL terms and other terms
that you might be familiar with.

VSAM term COBOL term Similar non-VSAM term


Data set File Data set
Entry-sequenced data set (ESDS) Sequential file QSAM data set
Key-sequenced data set (KSDS) Indexed file ISAM data set
Relative-record data set (RRDS) Relative file BDAM data set
| Control interval Block
Control interval size (CISZ) Block size
Buffers (BUFNI/BUFND) BUFNO
Access method control block (ACB) Data control block (DCB)
Cluster (CL) Data set
Cluster definition Data set allocation
AMP parameter of JCL DD statement DCB parameter of JCL DD statement
Record size Record length

The term file in this VSAM information refers to either a COBOL file or a VSAM
data set.

If you have complex requirements or frequently use VSAM, review the VSAM
publications for your operating system.

RELATED CONCEPTS
“VSAM files” on page 148

RELATED TASKS
“Defining VSAM file organization and records” on page 149
“Coding input and output statements for VSAM files” on page 155
“Protecting VSAM files with a password” on page 164
“Handling errors in VSAM files” on page 164

© Copyright IBM Corp. 1991, 2004 147


“Working with VSAM data sets under z/OS and UNIX” on page 165
“Improving VSAM performance” on page 171

RELATED REFERENCES
z/OS DFSMS: Using Data Sets
z/OS DFSMS Macro Instructions for Data Sets
z/OS DFSMS: Access Method Services for Catalogs

VSAM files
The physical organization of VSAM data sets differs considerably from those used
by other access methods. VSAM data sets are held in control intervals (CI) and
control areas (CA). The size of these is normally determined by the access method,
and the way in which they are used is not visible to you.

You can use three types of file organization with VSAM.


VSAM sequential file organization
(Also referred to as VSAM ESDS (entry-sequenced data set) organization.)
In VSAM sequential file organization, the records are stored in the order in
which they were entered. VSAM entry-sequenced data sets are equivalent
to QSAM sequential files. The order of the records is fixed.
VSAM indexed file organization
(Also referred to as VSAM KSDS (key-sequenced data set) organization.) In
a VSAM indexed file (KSDS), the records are ordered according to the
collating sequence of an embedded prime key field, which you define. The
prime key consists of one or more consecutive characters in the records.
The prime key uniquely identifies the record and determines the sequence
in which it is accessed with respect to other records. A prime key for a
record might be, for example, an employee number or an invoice number.
VSAM relative file organization
(Also referred to as VSAM fixed-length or variable-length RRDS
(relative-record data set) organization.) A VSAM relative-record data set
(RRDS) contains records ordered by their relative key. The relative key is
the relative record number that represents the location of the record
relative to where the file begins. The relative record number identifies the
fixed- or variable-length record.
In a VSAM fixed-length RRDS, records are placed in a series of
fixed-length slots in storage. Each slot is associated with a relative record
number. For example, in a fixed-length RRDS containing 10 slots, the first
slot has a relative record number of 1, and the tenth slot has a relative
record number of 10.
In a VSAM variable-length RRDS, the records are ordered according to
their relative record number. Records are stored and retrieved according to
the relative record number that you set.
Throughout this documentation, the term VSAM relative-record data set (or
RRDS) is used to mean both relative-record data sets with fixed-length
records and with variable-length records, unless they need to be
differentiated.

The following table compares the different types of VSAM data sets in terms of
several characteristics.

148 Programming Guide


Table 23. Comparison of VSAM data set types
Entry-sequenced data set Key-sequenced data set Relative-record data set
Characteristic (ESDS) (KSDS) (RRDS)
Order of records Order in which they are Collating sequence by key Order of relative record
written field number
Access Sequential By key through an index By relative record number,
which is handled like a key
Alternate indexes Can have one or more Can have one or more Cannot have alternate indexes
alternate indexes, although alternate indexes
not supported in COBOL
Relative byte RBA cannot change. RBA can change. RRN cannot change.
address (RBA) and
relative record
number (RRN) of a
record
Space for adding Uses space at the end of the Uses distributed free space For fixed-length RRDS, uses
records data set for inserting records and empty slots in the data set
changing their lengths in
place For variable-length RRDS, uses
distributed free space and
changes the lengths of added
records in place
Space from deleting You cannot delete a record, Space from a deleted or Space from a deleted record
records but you can reuse its space shortened record is can be reused.
for a record of the same automatically reclaimed in a
length. control interval.
Spanned records Can have spanned records Can have spanned records Cannot have spanned records
Reuse as work file Can be reused unless it has Can be reused unless it has Can be reused
an alternate index, is an alternate index, is
associated with key ranges, or associated with key ranges, or
exceeds 123 extents per exceeds 123 extents per
volume volume

RELATED TASKS
“Specifying sequential organization for VSAM files” on page 150
“Specifying indexed organization for VSAM files” on page 150
“Specifying relative organization for VSAM files” on page 151
“Defining VSAM files” on page 166

Defining VSAM file organization and records


Use the FILE-CONTROL entry in the ENVIRONMENT DIVISION to define the VSAM file
organization and access modes for the files in your COBOL program.

In the FILE SECTION of the DATA DIVISION, code a file description (FD) entry for the
file. In the associated record description entry or entries, define the record-name and
record length. Code the logical size of the records with the RECORD clause.

Important: You can process VSAM data sets in Enterprise COBOL programs only
after you define them with access method services.

The following table summarizes VSAM file organization, access modes, and record
formats (fixed or variable length).

Chapter 10. Processing VSAM files 149


Table 24. VSAM file organization, access mode, and record format
Sequential Random Dynamic Fixed Variable
File organization access access access length length
VSAM sequential Yes No No Yes Yes
(ESDS)
VSAM indexed Yes Yes Yes Yes Yes
(KSDS)
VSAM relative Yes Yes Yes Yes Yes
(RRDS)

RELATED TASKS
“Specifying sequential organization for VSAM files”
“Specifying indexed organization for VSAM files”
“Specifying relative organization for VSAM files” on page 151
“Using file status keys” on page 208
“Using VSAM return codes (VSAM files only)” on page 209
“Defining VSAM files” on page 166
“Specifying access modes for VSAM files” on page 153

Specifying sequential organization for VSAM files


Identify VSAM ESDS files in your COBOL program with the ORGANIZATION IS
SEQUENTIAL clause.

You can access (read or write) records in sequential files only sequentially.

After you place a record in the file, you cannot shorten, lengthen, or delete it.
However, you can update (REWRITE) a record if the length does not change. New
records are added at the end of the file.

The following example shows typical FILE-CONTROL entries for a VSAM sequential
file (ESDS):
SELECT S-FILE
ASSIGN TO SEQUENTIAL-AS-FILE
ORGANIZATION IS SEQUENTIAL
ACCESS IS SEQUENTIAL
FILE STATUS IS FSTAT-CODE VSAM-CODE.

RELATED CONCEPTS
“VSAM files” on page 148

Specifying indexed organization for VSAM files


Identify VSAM KSDS in your COBOL program with the ORGANIZATION IS INDEXED
clause.

Code a prime key for the record by using the clause:


RECORD KEY IS data-name

Here data-name is the name of the key field as you defined it in the record
description entry in the DATA DIVISION. The collation of index record keys is based
on the binary value of the key, regardless of the class or the category of the key.

150 Programming Guide


The following example shows the statements for a VSAM indexed file (KSDS) that
is accessed dynamically. In addition to the primary key, COMMUTER-NO, there is an
alternate key, LOCATION-NO:
SELECT I-FILE
ASSIGN TO INDEXED-FILE
ORGANIZATION IS INDEXED
ACCESS IS DYNAMIC
RECORD KEY IS IFILE-RECORD-KEY
ALTERNATE RECORD KEY IS IFILE-ALTREC-KEY
FILE STATUS IS FSTAT-CODE VSAM-CODE.

Alternate keys
In addition to the primary key, you can also code one or more alternate keys to use
for retrieving records. Using alternate keys, you can access the indexed file to read
records in some sequence other than the prime key sequence. For example, you
could access the file through employee department rather than through employee
number. Alternate keys need not be unique. More than one record will be accessed,
given a department number as a key. This is permitted if alternate keys are coded
to allow duplicates.

You define the alternate key in your COBOL program with the ALTERNATE RECORD
KEY clause:
ALTERNATE RECORD KEY IS data-name

Here data-name is the name of the key field as you defined it in the record
description entry in the DATA DIVISION. The collation of alternate keys is based on
the binary value of the key, regardless of the class or the category of the key.

Alternate index
To use an alternate index, you need to define a data set (using access method
services) called the alternate index (AIX). The AIX contains one record for each
value of a given alternate key; the records are in sequential order by alternate key
value. Each record contains the corresponding primary keys of all records in the
associated indexed files that contain the alternate key value.

RELATED CONCEPTS
“VSAM files” on page 148

RELATED TASKS
“Creating alternate indexes” on page 167

Specifying relative organization for VSAM files


Identify VSAM RRDS files in your COBOL program with the ORGANIZATION IS
RELATIVE clause.

Use the RELATIVE KEY IS clause to associate each logical record with its relative
record number.

The following example shows a relative-record data set (RRDS) that is accessed
randomly by the value in the relative key ITEM-NO:
SELECT R-FILE
ASSIGN TO RELATIVE-FILE
ORGANIZATION IS RELATIVE
ACCESS IS RANDOM
RELATIVE KEY IS RFILE-RELATIVE-KEY
FILE STATUS IS FSTAT-CODE VSAM-CODE.

Chapter 10. Processing VSAM files 151


You can use a randomizing routine to associate a key value in each record with the
relative record number for that record. Although there are many techniques to
convert a record key to a relative record number, the most commonly used
randomizing algorithm is the division/remainder technique. With this technique,
you divide the key by a value equal to the number of slots in the data set to
produce a quotient and remainder. When you add one to the remainder, the result
will be a valid relative record number.

Alternate indexes are not supported for VSAM RRDS.

Fixed-length and variable-length RRDS


In an RRDS with fixed-length records, each record occupies one slot, and you store
and retrieve records according to the relative record number of that slot. When you
load the file, you have the option of skipping over slots and leaving them empty.

When you load an RRDS with variable-length records, you can skip over relative
record numbers. Unlike fixed-length RRDS, a variable-length RRDS does not have
slots. Instead, the free space that you define allows for more efficient record
insertions.

VSAM variable-length RRDS is supported on OS/390 and z/OS.

Simulating variable-length RRDS


Use VSAM variable-length RRDS when possible. But if you cannot use the VSAM
support, Enterprise COBOL provides another way for you to have relative-record
data sets with variable-length records. This support, called COBOL simulated
variable-length RRDS, is provided by the SIMVRD|NOSIMVRD run-time option. When
you use the SIMVRD option, Enterprise COBOL simulates variable-length RRDS
using a VSAM KSDS.

The coding that you use in your COBOL program to identify and describe VSAM
variable-length RRDS and COBOL simulated variable-length RRDS is similar. How
you use the SIMVRD run-time option and whether you define the VSAM file as a
RRDS or KSDS differs, however.

To use a variable-length RRDS, do the following steps, depending on whether you


want to simulate an RRDS:
Table 25. Steps for using variable-length RRDS
Step VSAM variable-length RRDS COBOL simulated variable-length RRDS
1 Define the file in your COBOL Same
program with the
ORGANIZATION IS RELATIVE
clause.
2 Use FD statements in your Same, but you must also code RECORD IS
COBOL program to describe VARYING on the FD statements of every COBOL
the records with program that accesses the data set.
variable-length sizes.
3 Use the NOSIMVRD run-time Use the SIMVRD run-time option.
option.

152 Programming Guide


Table 25. Steps for using variable-length RRDS (continued)
Step VSAM variable-length RRDS COBOL simulated variable-length RRDS
4 Define the VSAM file through Define the VSAM file through access method
access method services as an services as follows:
RRDS. DEFINE CLUSTER INDEXED
KEYS(4,0)
RECORDSIZE(avg,m)
where:
avg Is the average size of the COBOL
records; strictly less than m.
m Is greater than or equal to the
maximum size COBOL record + 4.

In step 2 for simulated variable-length RRDS, coding other language elements that
imply a variable-length record format does not give you COBOL simulated
variable-length RRDS. For example, these clauses alone do not give you correct file
access:
v Multiple FD records of different lengths
v OCCURS . . . DEPENDING ON in the record definitions
v RECORD CONTAINS integer-1 TO integer-2 CHARACTERS

When you define the cluster in step 4 for simulated variable-length RRDS, observe
these restrictions:
v Do not define an alternate index.
v Do not specify a KEYRANGE.
v Do not specify SPANNED.

Also, use the REUSE parameter when you open for output a file that contains
records.

Errors: When you work with simulated variable-length relative data sets and true
VSAM RRDS data sets, you get an OPEN file status 39 if your COBOL file definition
and the VSAM data set attributes do not match.

RELATED CONCEPTS
“VSAM files” on page 148

RELATED TASKS
“Defining VSAM files” on page 166

Specifying access modes for VSAM files


You can access records in VSAM sequential files only sequentially. You can access
records in VSAM indexed and relative files in three ways: sequentially, randomly,
or dynamically.

For sequential access, code ACCESS IS SEQUENTIAL in the FILE-CONTROL entry.


Records in indexed files are then accessed in the order of the key field selected
(either primary or alternate). Records in relative files are accessed in the order of
the relative record numbers.

Chapter 10. Processing VSAM files 153


For random access, code ACCESS IS RANDOM in the FILE-CONTROL entry. Records in
indexed files are then accessed according to the value you place in a key field.
Records in relative files are accessed according to the value you place in the
relative key.

For dynamic access, code ACCESS IS DYNAMIC in the FILE-CONTROL entry. Dynamic
access is a mixed sequential-random access in the same program. Using dynamic
access, you can write one program to perform both sequential and random
processing, accessing some records in sequential order and others by their keys.

“Example: using dynamic access with VSAM files”

RELATED TASKS
“Reading records from a VSAM file” on page 160

Example: using dynamic access with VSAM files


Suppose that you have an indexed file of employee records and the employee’s
hourly wage forms the record key. Your program is processing those employees
who earn between $10.00 and $12.00 per hour and those who earn $20.00 per hour
and above.

Using dynamic access of VSAM files, the program would do as follows:


1. Retrieve the first record randomly (with a random-retrieval READ) based on the
key of 1000.
2. Read sequentially (using READ NEXT) until the salary field exceeds 1200.
3. Retrieve the next record randomly, this time based on a key of 2000.
4. Read sequentially until the end of the file.

RELATED TASKS
“Reading records from a VSAM file” on page 160

Defining record lengths for VSAM files


VSAM records can be fixed or variable in length. COBOL determines the record
format from the RECORD clause and the record descriptions associated with your FD
entry for the file.

Because the concept of blocking has no meaning for VSAM files, you can omit the
BLOCK CONTAINS clause. The clause is syntax-checked, but it has no effect on how
the program runs.

Defining fixed-length records


To define the records to be fixed length, use one of the following coding options:
Table 26. Definition of VSAM fixed-length records
Clause
RECORD clause format Record length Comments
Code RECORD CONTAINS 1 Fixed in size with a The lengths of the
integer. length of integer-2 level-01 record
description entries
associated with the file
do not matter.

154 Programming Guide


Table 26. Definition of VSAM fixed-length records (continued)
Clause
RECORD clause format Record length Comments
Omit the RECORD clause, The fixed size that you
but code all level-01 coded
records (associated with
the file) as the same size
and none with an OCCURS
DEPENDING ON clause.

Defining variable-length records


To define the records to be variable-length, use one of the following coding
options:
Table 27. Definition of VSAM variable-length records
Clause
RECORD clause format Maximum record length Comments
Code RECORD IS VARYING 3 integer-2 value The lengths of the
FROM integer-1 TO integer-2. level-01 record
description entries
associated with the file
do not matter.
Code RECORD IS VARYING. 3 Size of the largest level-01 The compiler determines
record description entry the maximum record
associated with the file length.
Code RECORD CONTAINS 2 integer-2 value The minimum record
integer-1 TO integer-2. length is the integer-1
value.
Omit the RECORD clause, Size of the largest level-01 The compiler determines
but code multiple level-01 record description entry the maximum record
records (associated with associated with the file length.
the file) that are of
different sizes or that
contain an OCCURS
DEPENDING ON clause.

When you specify a READ INTO statement for a format-V file, the record size read
for that file is used in the MOVE statement generated by the compiler. Consequently,
you might not get the result you expect if the record read in does not correspond
to the level-01 record description. All other rules of the MOVE statement apply. For
example, when you specify a MOVE statement for a format-V record read in by the
READ statement, the size of the record corresponds to its level-01 record description.

RELATED TASKS
Enterprise COBOL Compiler and Run-Time Migration Guide

Coding input and output statements for VSAM files


Use these COBOL statements for processing VSAM files:
OPEN To connect the VSAM data set to your COBOL program for processing.
WRITE To add records to a file or load a file.
START To establish the current location in the cluster for a READ NEXT statement.

Chapter 10. Processing VSAM files 155


START does not retrieve a record; it only sets the current record pointer.
READ and READ NEXT
To retrieve records from a file.
REWRITE
To update records.
DELETE To logically remove records from indexed and relative files only.
CLOSE To disconnect the VSAM data set from your program.

All of the following factors determine which input and output statements you can
use for a given VSAM data set:
v Access mode (sequential, random, or dynamic)
v File organization (ESDS, KSDS, or RRDS)
v Mode of OPEN statement (INPUT, OUTPUT, I-O, or EXTEND)

The following table shows the possible combinations with sequential files (ESDS).
The X indicates that you can use the statement with the open mode at the top of
the column.
Table 28. I/O statements for VSAM sequential files
COBOL OPEN OPEN OPEN OPEN
Access mode statement INPUT OUTPUT I-O EXTEND
Sequential OPEN X X X X
WRITE X X
START
READ X X
REWRITE X
DELETE
CLOSE X X X X

The following table shows the possible combinations you can use with indexed
(KSDS) files and relative (RRDS) files. The X indicates that you can use the
statement with the open mode at the top of the column.
Table 29. I/O statements for VSAM relative and indexed files
COBOL OPEN OPEN OPEN OPEN
Access mode statement INPUT OUTPUT I-O EXTEND
Sequential OPEN X X X X
WRITE X X
START X X
READ X X
REWRITE X
DELETE X
CLOSE X X X X

156 Programming Guide


Table 29. I/O statements for VSAM relative and indexed files (continued)
COBOL OPEN OPEN OPEN OPEN
Access mode statement INPUT OUTPUT I-O EXTEND
Random OPEN X X X
WRITE X X
START
READ X X
REWRITE X
DELETE X
CLOSE X X X
Dynamic OPEN X X X
WRITE X X
START X X
READ X X
REWRITE X
DELETE X
CLOSE X X X

The fields you code in the FILE STATUS clause are updated by VSAM after each
input-output statement to indicate the success or failure of the operation.

RELATED CONCEPTS
“File position indicator”

RELATED TASKS
“Opening a file (ESDS, KSDS, or RRDS)” on page 158
“Reading records from a VSAM file” on page 160
“Updating records in a VSAM file” on page 161
“Adding records to a VSAM file” on page 162
“Replacing records in a VSAM file” on page 162
“Deleting records from a VSAM file” on page 163
“Closing VSAM files” on page 163

RELATED REFERENCES
Status key (Common processing facilities) (Enterprise COBOL Language Reference)

File position indicator


The file position indicator marks the next record to be accessed for sequential
COBOL requests. You do not set the file position indicator anywhere in your
program; it is set by successful OPEN, START, READ, and READ NEXT statements.
Subsequent READ or READ NEXT requests use the established file position indicator
location and update it.

The file position indicator is not used or affected by the output statements WRITE,
REWRITE, or DELETE. The file position indicator has no meaning for random
processing.

RELATED TASKS
“Reading records from a VSAM file” on page 160

Chapter 10. Processing VSAM files 157


Opening a file (ESDS, KSDS, or RRDS)
Before you can use any WRITE, START, READ, REWRITE, or DELETE statements to
process records in a file, you must first open the file with an OPEN statement. File
availability and creation affect OPEN processing, optional files, and file status codes
05 and 35.

For example, if you OPEN EXTEND, OPEN I-O, or OPEN INPUT a file that is neither
optional nor available, you get file status 35 and the OPEN statement fails. If the file
is OPTIONAL, the OPEN EXTEND, OPEN I-O, or OPEN INPUT creates the file and returns
file status 05.

An OPEN operation works successfully only when you set fixed file attributes in the
DD statement or data set label for a file and specify consistent attributes for that file
in the SELECT and FD statements of your COBOL program. Mismatches in the
following items result in a file status code 39, and the OPEN statement fails:
v Attributes for file organization (sequential, relative, or indexed)
v Prime record key
v Alternate record keys
v Maximum record size
v Record type (fixed or variable)

How you code the OPEN statement in your COBOL program for a VSAM file
depends on whether the file is empty (a file that has never contained records) or
loaded. For either type of file, your program should check the file status key after
each OPEN statement.

RELATED TASKS
“Opening an empty file”
“Opening a loaded file (a file with records)” on page 160

RELATED REFERENCES
“Statements to load records into a VSAM file” on page 159

Opening an empty file


To open a file that has never contained records (an empty file), use the following
statements depending on the type of file:
v OPEN OUTPUT for ESDS files.
v OPEN OUTPUT or OPEN EXTEND for KSDS and RRDS files. (Either coding has the
same effect.) If you have coded the file for random or dynamic access and the
file is optional, you can use OPEN I-O.

Optional files are files that are not necessarily present each time the program is
run. You can define files opened in INPUT, I-O, or OUTPUT mode as optional by
defining them with the SELECT OPTIONAL phrase in the FILE-CONTROL section of
your program.

Initially loading records sequentially into a file: Initially loading a file means
writing records into the file for the first time. This is not the same as writing
records into a file from which all previous records have been deleted.

To initially load a VSAM file:


1. Open the file.
2. Use sequential processing (ACCESS IS SEQUENTIAL) because it is faster.

158 Programming Guide


3. Use WRITE to add a record to the file.

Using OPEN OUTPUT to load a VSAM file significantly improves the performance of
your program. Using OPEN I-O or OPEN EXTEND has a negative impact on the
performance of your program.

When you load VSAM indexed files sequentially, you optimize both loading
performance and subsequent processing performance, because sequential
processing maintains user-defined free space. Future insertions will be more
efficient.

With ACCESS IS SEQUENTIAL, you must write the records in ascending RECORD KEY
order.

When you load VSAM relative files sequentially, the records are placed in the file
in the ascending order of relative record numbers.

Initially loading a file randomly or dynamically: You can use random or


dynamic processing to load a file, but they are not as efficient as sequential
processing. Because VSAM does not support random or dynamic processing,
COBOL has to perform some extra processing to enable you to use ACCESS IS
RANDOM or ACCESS IS DYNAMIC with OPEN OUTPUT or OPEN I-O. These steps prepare
the file for use and give it the status of a loaded file, having been used at least
once.

In addition to extra overhead for preparing files for use, random processing does
not consider any user-defined free space. As a result, any future insertions might
be inefficient. Sequential processing maintains user-defined free space.

Loading a VSAM data set with access method services: You can load or update
a VSAM data set with the access method services REPRO command. Use REPRO
whenever possible.

RELATED TASKS
“Opening a loaded file (a file with records)” on page 160

RELATED REFERENCES
“Statements to load records into a VSAM file”
REPRO (z/OS DFSMS: Access Method Services for Catalogs)

Statements to load records into a VSAM file


Table 30. Statements to load records into a VSAM file
Division ESDS KSDS RRDS
ENVIRONMENT SELECT SELECT SELECT
DIVISION ASSIGN ASSIGN ASSIGN
FILE STATUS ORGANIZATION IS INDEXED ORGANIZATION IS
PASSWORD RECORD KEY RELATIVE
ACCESS MODE ALTERNATE RECORD KEY RELATIVE KEY
FILE STATUS FILE STATUS
PASSWORD PASSWORD
ACCESS MODE ACCESS MODE
DATA FD entry FD entry FD entry
DIVISION

Chapter 10. Processing VSAM files 159


Table 30. Statements to load records into a VSAM file (continued)
Division ESDS KSDS RRDS
PROCEDURE OPEN OUTPUT OPEN OUTPUT OPEN OUTPUT
DIVISION OPEN EXTEND OPEN EXTEND OPEN EXTEND
WRITE WRITE WRITE
CLOSE CLOSE CLOSE

RELATED TASKS
“Opening an empty file” on page 158
“Updating records in a VSAM file” on page 161

Opening a loaded file (a file with records)


To open a file that already contains records, use OPEN INPUT, OPEN I-O, or OPEN
EXTEND.

If you open a VSAM entry-sequenced or relative-record file as EXTEND, the added


records are placed after the last existing records in the file.

If you open a VSAM key-sequenced file as EXTEND, each record you add must have
a record key higher than the highest record in the file.

RELATED TASKS
“Opening an empty file” on page 158
“Working with VSAM data sets under z/OS and UNIX” on page 165

RELATED REFERENCES
“Statements to load records into a VSAM file” on page 159
z/OS DFSMS: Access Method Services for Catalogs

Reading records from a VSAM file


Use the READ statement to retrieve (READ) records from a file. To read a record, you
must have opened the file INPUT or I-O. Your program should check the file status
key after each READ.

You can retrieve records in VSAM sequential files only in the sequence in which
they were written.

You can retrieve records in VSAM indexed and relative record files in any of the
following ways:
Sequentially
According to the ascending order of the key you are using, the RECORD KEY
or the ALTERNATE RECORD KEY, beginning at the current position of the file
position indicator for indexed files, or according to ascending relative
record locations for relative files
Randomly
In any order, depending on how you set the RECORD KEY or ALTERNATE
RECORD KEY or the RELATIVE KEY before your READ request
Dynamically
Mixed sequential and random

With dynamic access, you can switch between reading a specific record directly
and reading records sequentially, by using READ NEXT for sequential retrieval and
READ for random retrieval (by key).

160 Programming Guide


When you want to read sequentially, beginning at a specific record, use START
before the READ NEXT statement to set the file position indicator to point to a
particular record. When you code START followed by READ NEXT, the next record is
read and the file position indicator is reset to the next record. You can move the
file position indicator randomly by using START, but all reading is done
sequentially from that point.
START file-name KEY IS EQUAL TO ALTERNATE-RECORD-KEY

When a direct READ is performed for a VSAM indexed file, based on an alternate
index for which duplicates exist, only the first record in the data set (base cluster)
with that alternate key value is retrieved. You need a series of READ NEXT
statements to retrieve each of the data set records with the same alternate key. A
file status code of 02 is returned if there are more records with the same alternate
key value to be read; a code of 00 is returned when the last record with that key
value has been read.

RELATED CONCEPTS
“File position indicator” on page 157

RELATED TASKS
“Specifying access modes for VSAM files” on page 153

Updating records in a VSAM file


To update a VSAM file, use the ENVIRONMENT DIVISION and DATA DIVISION
statements to load records into a VSAM file and the following PROCEDURE DIVISION
statements to update VSAM files.
Table 31. Statements to update records in a VSAM file
Access
method ESDS KSDS RRDS
ACCESS IS OPEN EXTEND OPEN EXTEND OPEN EXTEND
SEQUENTIAL WRITE WRITE WRITE
CLOSE CLOSE CLOSE
or or or
OPEN I-O OPEN I-O OPEN I-O
READ READ READ
REWRITE REWRITE REWRITE
CLOSE DELETE DELETE
CLOSE CLOSE
ACCESS IS Not applicable OPEN I-O OPEN I-O
RANDOM READ READ
WRITE WRITE
REWRITE REWRITE
DELETE DELETE
CLOSE CLOSE
ACCESS IS Not applicable OPEN I-O OPEN I-O
DYNAMIC READ NEXT READ NEXT
(sequential WRITE WRITE
processing) REWRITE REWRITE
START START
DELETE DELETE
CLOSE CLOSE

Chapter 10. Processing VSAM files 161


Table 31. Statements to update records in a VSAM file (continued)
Access
method ESDS KSDS RRDS
ACCESS IS Not applicable OPEN I-O OPEN I-O
DYNAMIC READ READ
(random WRITE WRITE
processing) REWRITE REWRITE
DELETE DELETE
CLOSE CLOSE

RELATED REFERENCES
“Statements to load records into a VSAM file” on page 159

Adding records to a VSAM file


Use the COBOL WRITE statement to add a record to a file without replacing any
existing records. The record to be added must not be larger than the maximum
record size that you set when you defined the file. Your program should check the
file status key after each WRITE statement.

Adding records sequentially


Use ACCESS IS SEQUENTIAL and code the WRITE statement to add records
sequentially to the end of a VSAM file that has been opened with either OUTPUT or
EXTEND.

Sequential files are always written sequentially.

For indexed files, you must write new records in ascending key sequence. If you
open the file EXTEND, the record keys of the records to be added must be higher
than the highest primary record key on the file when you opened the file.

For relative files, the records must be in sequence. If you include a RELATIVE KEY
data item in the SELECT clause, the relative record number of the record to be
written is placed in that data item.

Adding records randomly or dynamically


When you write records to an indexed data set and ACCESS IS RANDOM or ACCESS IS
DYNAMIC, you can write the records in any order.

Replacing records in a VSAM file


To replace records in a VSAM file, use REWRITE on a file that you have opened for
I-O. If you try to use REWRITE on a file that is not opened I-O, the record is not
rewritten and the status key is set to 49. Your program should check the file status
key after each REWRITE statement.
v For sequential files, the length of the record you rewrite must be the same as the
length of the original record.
v For indexed files, you can change the length of the record you rewrite.
v For variable-length relative files, you can change the length of the record you
rewrite.

To replace records randomly or dynamically, your program need not read the
record to be rewritten. Instead, to position the record that you want to update, do
as follows:

162 Programming Guide


v For indexed files, move the record key to the RECORD KEY data item and then
issue the REWRITE.
v For relative files, move the relative record number to the RELATIVE KEY data item
and then issue the REWRITE.

Deleting records from a VSAM file


Open the file I-O and use the DELETE statement to remove an existing record from
an indexed or relative file. You cannot use DELETE on a sequential file.

When you use ACCESS IS SEQUENTIAL or the file contains spanned records, your
program must first read the record to be deleted. The DELETE then removes the
record that was read. If the DELETE is not preceded by a successful READ, the
deletion is not done and the status key value is set to 92.

When you use ACCESS IS RANDOM or ACCESS IS DYNAMIC, your program need not
first read the record to be deleted. To delete a record, move the key of the record to
be deleted to the RECORD KEY data item and then issue the DELETE. Your program
should check the file status key after each DELETE statement.

Closing VSAM files


Use the CLOSE statement to disconnect your program from the VSAM file. If you
try to close a file that is already closed, you will get a logic error. Check the file
status key after each CLOSE statement.

If you do not close a VSAM file, the file is automatically closed for you under the
following conditions, except for files defined in any OS/VS COBOL programs in
the run unit:
v When the run unit ends normally, all open files defined in any COBOL
programs in the run unit are closed.
v When the run unit ends abnormally, if the TRAP(ON) run-time option has been
set, all open files defined in any COBOL programs in the run unit are closed.
v When Language Environment condition handling is completed and the
application resumes in a routine other than where the condition occurred, open
files defined in any COBOL programs in the run unit that might be called again
and reentered are closed.
You can change the location where a program resumes after a condition is
handled. To make this change, you can, for example, move the resume cursor
with the CEEMRCR callable service or use HLL language constructs such as a C
longjmp statement.
v When you issue CANCEL for a COBOL subprogram, any open nonexternal files
defined in that program are closed.
v When a COBOL subprogram with the INITIAL attribute returns control, any
open nonexternal files defined in that program are closed.
v When a thread of a multithreaded application ends, both external and
nonexternal files that were opened from within that same thread are closed.

File status key data items that you define in the WORKING-STORAGE SECTION are set
when these implicit CLOSE operations are performed, but your EXCEPTION/ERROR
and LABEL declaratives are not invoked.

If you open a VSAM file in a multithreaded application, you must close it from the
same thread of execution. Attempting to close the file from a different thread
results in a close failure with file-status condition 90.

Chapter 10. Processing VSAM files 163


Handling errors in VSAM files
When an input statement or output statement operation fails, COBOL does not
perform corrective action for you.

All OPEN and CLOSE errors with a VSAM file, whether logical errors in your
program or input/output errors on the external storage media, return control to
your COBOL program, even when you have coded no DECLARATIVE and no FILE
STATUS clause.

If any other input or output statement operation fails, you choose whether your
program will continue running after a less-than-severe input/output error occurs.

COBOL provides these ways for you to intercept and handle certain VSAM input
and output errors:
v End-of-file phrase (AT END)
v EXCEPTION/ERROR declarative
v FILE STATUS clause (file status key and VSAM return code)
v INVALID KEY phrase

You should define a status key for each VSAM file that you define in your
program. Check the status key value after every input or output request, especially
OPEN and CLOSE.

If you do not code a FILE STATUS key or a declarative, serious VSAM processing
errors will cause a message to be issued and a Language Environment condition to
be signaled, which will cause an abend if you specify the run-time option
ABTERMENC(ABEND).

RELATED TASKS
“Handling errors in input and output operations” on page 203
“Using VSAM return codes (VSAM files only)” on page 209

RELATED REFERENCES
VSAM macro return and reason codes (z/OS DFSMS Macro Instructions for Data
Sets)

Protecting VSAM files with a password


Although the preferred security mechanism on a z/OS system is RACF, Enterprise
COBOL also supports using explicit passwords on VSAM files to prevent
unauthorized access and update.

To use explicit passwords, code the PASSWORD clause in the SELECT statement of
your program. Use this clause only if the catalog entry for the files includes a read
or an update password.
v If the catalog entry includes a read password, you cannot open and access the
file in a COBOL program unless you use the password clause in the
FILE-CONTROL paragraph and describe it in the DATA DIVISION. The data-name
referred to must contain a valid password when the file is opened.
v If the catalog entry includes an update password, you can open and access it,
but not update it, unless you code the password clause in the FILE-CONTROL
paragraph and describe it in the DATA DIVISION.

164 Programming Guide


v If the catalog entry includes both a read password and an update password,
specify the update password to both read and update the file in your program.

If your program only retrieves records and does not update them, you need only
the read password. If your program loads files or updates them, you need to
specify the update password that was cataloged.

For indexed files, the PASSWORD data item for the RECORD KEY must contain the valid
password before the file can be successfully opened.

If you password-protect a VSAM indexed file, you must also password-protect


every alternate index in order to be fully password-protected. Where you place the
PASSWORD clause becomes important because each alternate index has its own
password. The PASSWORD clause must directly follow the key clause to which it
applies.

“Example: password protection for a VSAM indexed file”

Example: password protection for a VSAM indexed file


The following example shows the COBOL code used for a VSAM indexed file with
password protection.
. . .
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT LIBFILE
ASSIGN TO PAYMAST
ORGANIZATION IS INDEXED
RECORD KEY IS EMPL-NUM
PASSWORD IS BASE-PASS
ALTERNATE RECORD KEY IS EMPL-PHONE
PASSWORD IS PATH1-PASS
. . .
WORKING-STORAGE SECTION.
01 BASE-PASS PIC X(8) VALUE “25BSREAD”.
01 PATH1-PASS PIC X(8) VALUE “25ATREAD”.

Working with VSAM data sets under z/OS and UNIX


There are some special considerations for VSAM files under z/OS and UNIX in
terms of coding access method services (IDCAMS) commands, environment
variables, and JCL.

A VSAM file is available if all of the following are true:


v You define it using access method services.
v You define it for your program by providing a DD statement, an environment
variable, or an ALLOCATE command for it.
v It has previously contained a record.

A VSAM file is unavailable if it has never contained a record, even if you have
defined it.

You always get a return code of zero on completion of the OPEN statement for a
VSAM sequential file.

Use the access method services REPRO command to empty a file. Deleting records in
this manner resets the high-use relative byte address (RBA) of the file to zero. The
file is effectively empty and appears to COBOL as if it never contained a record.

Chapter 10. Processing VSAM files 165


RELATED TASKS
“Defining files to the operating system” on page 10
“Defining VSAM files”
“Creating alternate indexes” on page 167
“Allocating VSAM files” on page 169
“Sharing VSAM files through RLS” on page 170

Defining VSAM files


You can process VSAM entry-sequenced, key-sequenced, and relative-record data
sets in Enterprise COBOL only after you define them through access method
services (IDCAMS).

A VSAM cluster is a logical definition for a VSAM data set and has one or two
components:
v The data component of a VSAM cluster contains the data records.
v The index component of a VSAM key-sequenced cluster consists of the index
records.

Use the access method services DEFINE CLUSTER command to define your VSAM
data sets (clusters). This process includes creating an entry in an integrated catalog
without any data transfer.

Define the following information about the cluster:


v Name of the entry
v Name of the catalog to contain this definition and its password (can use default
name.
v Organization (sequential, indexed, or relative)
v Device and volumes that the data set will occupy
v Space required for the data set
v Record size and control interval sizes (CISIZE)
v Passwords (if any) required for future access

Depending on what kind of data set is in the cluster, also define the following
information for each cluster:
v For VSAM indexed data sets (KSDS), specify length and position of the prime
key in the records.
v For VSAM fixed-length relative-record data sets (RRDS), specify the record size
as greater than or equal to the maximum size COBOL record:
DEFINE CLUSTER NUMBERED
RECORDSIZE(n,n)
When you define a data set in this way, all records will be padded to the fixed
slot size n. If you use the RECORD IS VARYING ON data-name form of the RECORD
clause, a WRITE or REWRITE will use the length specified in the DEPENDING ON
data-name as the length of the record to be transferred by VSAM. This data is
then padded to the fixed slot size. READ statements always return the fixed slot
size in the DEPENDING ON data-name.
v For VSAM variable-length relative-record data sets (RRDS), specify the average
size COBOL record expected and the maximum size COBOL record expected:
DEFINE CLUSTER NUMBERED
RECORDSIZE(avg,m)
The average size COBOL record expected must be less than the maximum size
COBOL record expected.

166 Programming Guide


v For COBOL simulated variable-length relative-record data sets, specify the
average size of the COBOL records and a size that is greater than or equal to the
maximum size COBOL record plus 4:
DEFINE CLUSTER INDEXED
KEYS(4,0)
RECORDSIZE(avg,m)
The average size COBOL record expected must be less than the maximum size
COBOL record expected.

RELATED TASKS
“Creating alternate indexes”
“Allocating VSAM files” on page 169
“Specifying relative organization for VSAM files” on page 151

RELATED REFERENCES
z/OS DFSMS: Access Method Services for Catalogs

Creating alternate indexes


An alternate index provides access to the records in a data set using more than one
key. It accesses records in the same way as the prime index key of an indexed data
set (KSDS).

When planning to use an alternate index, you must know:


v The type of data set (base cluster) with which the index will be associated
v Whether the keys will be unique or not unique
v Whether the index is to be password protected
v Some of the performance aspects of using alternate indexes

Because an alternate index is, in practice, a VSAM data set that contains pointers to
the keys of a VSAM data set, you must define the alternate index and the alternate
index path (the entity that establishes the relationship between the alternate index
and the prime index). After you define an alternate index, make a catalog entry to
establish the relationship (or path) between the alternate index and its base cluster.
This path allows you to access the records of the base cluster through the alternate
keys.

To use an alternate index, you need to follow these steps:


1. Define the alternate index by using the DEFINE ALTERNATEINDEX command. In it,
define the following:
v Name of the alternate index
v Name of its related VSAM indexed data set
v Location in the record of any alternate indexes and whether they are unique
or not
v Whether or not alternate indexes are to be updated when the data set is
changed
v Name of the catalog to contain this definition and its password (can use
default name)
In your COBOL program the alternate index is identified solely by the
ALTERNATE RECORD KEY clause of the FILE CONTROL paragraph. The ALTERNATE
RECORD KEY definitions must match the definitions that you have made in the
catalog entry. Any password entries that you have cataloged should be coded
directly after the ALTERNATE RECORD KEY phrase.

Chapter 10. Processing VSAM files 167


2. Relate the alternate index to the base cluster (the data set to which the alternate
index gives you access) by using the DEFINE PATH command. In it, define the
following:
v Name of the path
v Alternate index to which the path is related
v Name of the catalog that contains the alternate index
The base cluster and alternate index are described by entries in the same
catalog.
3. Load the VSAM indexed data set.
4. Build the alternate index by using (typically) the BLDINDEX command. Identify
the input file as the indexed data set (base cluster) and the output file as the
alternate index or its path. This command BLDINDEX reads all the records in
your VSAM indexed data set (or base cluster) and extracts the data needed to
build the alternate index.
Alternatively, you can use the run-time option AIXBLD to build the alternate
index at run time. However, this option might adversely affect run-time
performance.

“Example: entries for alternate indexes”

RELATED REFERENCES
AIXBLD (COBOL only) (Language Environment Programming Reference)

Example: entries for alternate indexes


The following example maps the relationships between the COBOL FILE-CONTROL
entry and the DD statements or environment variables for a VSAM indexed file
with two alternate indexes.

Using JCL:
//MASTERA DD DSNAME=clustername,DISP=OLD (1)
//MASTERA1 DD DSNAME=path1,DISP=OLD (2)
//MASTERA2 DD DSNAME=path2,DISP=OLD (3)

Using environment variables:


export MASTERA=DSN(clustername),OLD (1)
export MASTERA=DSN(path1),OLD (2)
export MASTERA=DSN(path2),OLD (3)
. . .
FILE-CONTROL.
SELECT MASTER-FILE ASSIGN TO MASTERA (4)
RECORD KEY IS EM-NAME
PASSWORD IS PW-BASE (5)
ALTERNATE RECORD KEY IS EM-PHONE (6)
PASSWORD IS PW-PATH1
ALTERNATE RECORD KEY IS EM-CITY (7)
PASSWORD IS PW-PATH2.
(1) The base cluster name is clustername.
(2) The name of the first alternate index path is path1.
(3) The name of the second alternate index path is path2.
(4) The ddname or environment variable name for the base cluster is specified
with the ASSIGN clause.
(5) Passwords immediately follow their indexes.
(6) The key EM-PHONE relates to the first alternate index.

168 Programming Guide


(7) The key EM-CITY relates to the second alternate index.

RELATED TASKS
“Creating alternate indexes” on page 167

Allocating VSAM files


You must predefine and catalog all VSAM data sets through the access method
services DEFINE command. Most of the information about a VSAM data set is in the
catalog. You need to specify only minimal DD or environment variable information
for a VSAM file. When you use an environment variable, the name must be in
uppercase. Usually the input and data buffers are the only variables that you are
concerned about.

Allocation of VSAM files (indexed, relative, and sequential) follows the general
rules for the allocation of COBOL files. If you use an environment variable to
allocate a VSAM file, you must specify these options in the order shown, but no
others:
v DSN(dsname), where dsname is the name of the base cluster
v OLD or SHR

The basic DD statement that you need for your VSAM files is:
//ddname DD DSN=dsname,DISP=SHR,AMP=AMORG

The corresponding export command is:


export evname=“DSN(dsname),SHR”

In either case, dsname must be the same as the name used in the access method
services DEFINE CLUSTER or DEFINE PATH command. DISP must be OLD or SHR
because the data set is already cataloged. If you specify MOD when using JCL, the
data set is treated as OLD.

AMP is a VSAM JCL parameter used to supplement the information that the
program supplies about the data set. AMP takes effect when your program opens
the VSAM file. Any information that you set through the AMP parameter takes
precedence over the information that is in the catalog or that the program supplies.

The AMP parameter is not required except under the following circumstances:
v You use a dummy VSAM data set. For example,
//ddname DD DUMMY,AMP=AMORG
v You request additional index or data buffers. For example,
//ddname DD DSN=VSAM.dsname,DISP=SHR,
// AMP=(’BUFNI=4,BUFND=8’)

You cannot specify AMP if you allocate your VSAM data set with an environment
variable.

For a VSAM base cluster, specify the same system-name (ddname or environment
variable name) that you specify in the ASSIGN clause of the SELECT statement in
your COBOL program.

When you use alternate indexes in your COBOL program, you must specify not
only a system-name (using a DD statement or environment variable) for the base
cluster, but also one for each alternate index path. No language mechanism exists
to explicitly declare system-names for alternate index paths within the program.

Chapter 10. Processing VSAM files 169


Therefore, you must adhere to the following guidelines for forming the
system-name (ddname or environment variable name) for each alternate index
path:
v Concatenate the base cluster name with an integer.
v Begin with 1 for the path associated with the first alternate record defined for
the file in your program (ALTERNATE RECORD KEY clause of the SELECT statement).
v Increment by 1 for the path associated with each successive alternate record
definition for that file.

For example, if the system-name of a base cluster is ABCD, the system name for the
first alternate index path defined for the file in your program is ABCD1, the
system-name for the second alternate index path is ABCD2, and so on.

If the length of the base cluster system-name and sequence number exceeds eight
characters, the base cluster portion of the system-name is truncated on the right to
reduce the concatenated result to eight characters. For example, if the system-name
of a base cluster is ABCDEFGH, the system name of the first alternate index path is
ABCDEFG1, the tenth is ABCDEF10, and so on.

RELATED TASKS
“Allocating files” on page 117

RELATED REFERENCES
MVS JCL Reference

Sharing VSAM files through RLS


By using the VSAM JCL parameter RLS, you can specify the use of record level
sharing with VSAM. Use RLS=CR when consistent read protocols are required, and
RLS=NRI when no read integrity protocols are required. Specifying the RLS
parameter is the only way to request the RLS mode when running COBOL
programs.

You cannot specify RLS if you allocate your VSAM data set with an environment
variable.

Preventing update problems with VSAM files in RLS mode


When a VSAM data set is opened in RLS mode for I-O (updates), the first READ
| causes an exclusive lock of the record regardless of the value of RLS=CR or RLS=NRI
| that you specify. If the COBOL file is defined as ACCESS RANDOM, VSAM releases the
| exclusive lock on the record after a WRITE or REWRITE statement is issued or a READ
| statement is issued for another record. When a WRITE or REWRITE is done, VSAM
| writes the record immediately.

| However, if the COBOL file is defined as ACCESS DYNAMIC, VSAM does not release
| the exclusive lock on the record after a WRITE or REWRITE statement nor after a READ
| statement unless the I-O statement causes VSAM to move to another control
| interval (CI). As a result, if a WRITE or REWRITE was done, VSAM does not write the
| record until processing is moved to another CI and the lock is released. When
| using ACCESS DYNAMIC, one way to cause the record to be written immediately, to
| release the exclusive lock immediately, or both, is to define the VSAM data set to
| allow only one record per CI.

Specifying RLS=CR locks a record and prevents an update to it until another READ is
requested for another record. While a lock on the record being read is in effect,
other users can request a READ for the same record, but they cannot update the

170 Programming Guide


record until the read lock is released. When you specify RLS=NRI, no lock will be in
effect when a READ for input is issued and another user might update the record.

The locking rules for RLS=CR can cause the application to wait for availability of a
record lock, and this wait might slow down the READ for input.

You might need to modify your application logic to use the RLS=CR capability. Do
not use the RLS JCL parameter for batch jobs that update nonrecoverable spheres
until you are sure that the application functions correctly in a multiple updater
environment.

When you open a VSAM data set in RLS mode for INPUT or I-O processing, it is a
good idea to issue an OPEN or START immediately before a READ. If there is a delay
between the OPEN or START and the actual READ, another user might add records
before the record on which the application is positioned after the OPEN or START.
The COBOL run time points explicitly to the beginning of the VSAM data set at
the time when OPEN was requested, but another user might add records that would
alter the true beginning of the VSAM data set if the READ is delayed.

Restrictions when using RLS


The following restrictions apply to RLS mode:
v The VSAM cluster attributes KEYRANGE and IMBED are not supported when you
open a VSAM file in RLS mode.
v The VSAM cluster attribute REPLICATE is not recommended with RLS mode
because the benefits are negated by the system-wide buffer pool and potentially
large CF cache structure in the storage hierarchy.
v The AIXBLD run-time option is not supported when you open a VSAM file in RLS
mode, because VSAM does not allow an empty path to be opened. If you need
the AIXBLD run-time option to build the alternate index data set, open the VSAM
data set in non-RLS mode.
v Temporary data sets are not allowed in RLS mode.
v The SIMVRD run-time option is not supported for VSAM files opened in RLS
mode.

Handling errors in VSAM files in RLS mode


If your application accesses a VSAM data set in RLS mode, be sure to check the file
status and VSAM feedback codes after each request.

If your application encounters “SMSVSAM server not available” while processing


input or output, explicitly close the VSAM file before you try to open it again.
VSAM generates return code 16 for failures like “SMSVSAM server not available,”
and there is no feedback code. You can have your COBOL programs check the first
two bytes of the second file status area for a VSAM return code 16.

The COBOL run time generates message IGZ0205W and automatically closes the
file if the error occurs during OPEN processing.

All other RLS mode errors return a VSAM return code of 4, 8, or 12.

Improving VSAM performance


Most likely, your system programmer is responsible for tuning the performance of
COBOL and VSAM. As an application programmer, you can control the aspects of
VSAM listed in this table.

Chapter 10. Processing VSAM files 171


Table 32. Methods for improving VSAM performance
Aspect of VSAM What you can do Rationale and comments
Invoking access Build your alternate indexes in
methods service advance, using IDCAMS.
Buffering For sequential access, request more The default is one index (BUFNI)
data buffers; for random access, and two data buffers (BUFND).
request more index buffers. Specify
both BUFND and BUFNI when ACCESS
IS DYNAMIC.

Avoid coding additional buffers


unless your application will run
interactively; and then code buffers
only when response-time problems
arise that might be caused by
delays in input and output.
Loading records, Use the access methods service The REPRO command can update an
using access REPRO command when: indexed data set as fast or faster
methods services v The target indexed data set than any COBOL program under
already contains records. these conditions.
v The input sequential data set
contains records to be updated
or inserted into the indexed data
set.

If you use a COBOL program to


load the file, use OPEN OUTPUT and
ACCESS SEQUENTIAL.
File access modes For best performance, access Dynamic access is less efficient
records sequentially. than sequential access, but more
efficient than random access.
Random access results in increased
EXCPs because VSAM must access
the index for each request.
Key design Design the key in the records so This method compresses the key
that the high-order portion is best.
relatively constant and the
low-order portion changes often.
Multiple Avoid using multiple alternate Updates must be applied through
alternate indexes indexes. the primary paths and are reflected
through multiple alternate paths,
perhaps slowing performance,
Relative file Use VSAM fixed-length relative Although not as space efficient,
organization data sets rather than VSAM VSAM fixed-length relative data
variable-length relative data sets. sets are more run-time efficient
than VSAM variable-length relative
data sets, which have performance
characteristics comparable to
COBOL simulated relative data
sets.

172 Programming Guide


Table 32. Methods for improving VSAM performance (continued)
Aspect of VSAM What you can do Rationale and comments
Control interval Provide your system programmer VSAM calculates CISZ to best fit
sizes (CISZ) with information about the data the direct-access storage device
access and future growth of your (DASD) usage algorithm, which
VSAM data sets. From this might not, however, be efficient for
information, your system your application.
programmer can determine the
An average CISZ of 4K is suitable
best control interval size (CISZ) and
FREESPACE size (FSPC). for most applications. A smaller
CISZ means faster retrieval for
Choose proper values for CISZ and random processing at the expense
FSPC to minimize control area (CA) of inserts (that is, more CISZ splits
splits. You can diagnose the and therefore more space in the
current number of CA splits by data set). A larger CISZ results in
issuing the LISTCAT ALL command the transfer of more data across the
on the cluster, and then compress channel for each READ. This is more
(using EXPORT or IMPORT or REPRO) efficient for sequential processing,
the cluster to omit all CA splits similar to a large OS BLKSIZE.
periodically.
Many control area (CA) splits are
unfavorable for VSAM
performance. The FREESPACE
value can affect CA splits,
depending on how the file is used.

RELATED TASKS
“Specifying access modes for VSAM files” on page 153
Deciding how big a virtual resource pool to provide (z/OS DFSMS: Using Data Sets)
Selecting the optimal percentage of free space (z/OS DFSMS: Using Data Sets)

RELATED REFERENCES
z/OS DFSMS: Access Method Services for Catalogs

Chapter 10. Processing VSAM files 173


174 Programming Guide
Chapter 11. Processing line-sequential files
Line-sequential files are files that reside in the hierarchical file system (HFS) and
that contain only printable characters and certain control characters as data. Each
record ends with an EBCDIC new-line character (X’15’), which is not included in
the length of the record. Because these are sequential files, records are placed one
after another according to entry order. Your program can process these files only
sequentially, retrieving (with the READ statement) records in the same order as they
are in the file. A new record is placed after the preceding record.

To process line-sequential files in your program, use COBOL language statements


that:
v Identify and describe the files in the ENVIRONMENT DIVISION and the DATA
DIVISION
v Process the records in the files in the PROCEDURE DIVISION

After you have created a record, you cannot change its length or its position in the
file, and you cannot delete it.

RELATED CONCEPTS
UNIX System Services User’s Guide

RELATED TASKS
“Defining line-sequential files and records in COBOL”
“Describing the structure of a line-sequential file” on page 176
“Coding input-output statements for line-sequential files” on page 177
“Handling errors in line-sequential files” on page 180
“Defining and allocating line-sequential files” on page 177

RELATED REFERENCES
“Allowable control characters” on page 176

Defining line-sequential files and records in COBOL


Use the FILE-CONTROL entry in the ENVIRONMENT DIVISION to:
v Define the files in your COBOL program as line-sequential files.
v Associate them with the external file-names (ddnames or environment variable
names). An external file-name is the name by which a file is known to the
operating system.

In the following example, COMMUTER-FILE is the name that your program uses for
the file; COMMUTR is the external name.
FILE-CONTROL.
SELECT COMMUTER-FILE
ASSIGN TO COMMUTR
ORGANIZATION IS LINE SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS ECODE.

Your ASSIGN assignment-name clause must not include an organization field (S- or
AS-) before the external name. The ACCESS phrase and the FILE STATUS phrase are
optional.

© Copyright IBM Corp. 1991, 2004 175


RELATED TASKS
“Describing the structure of a line-sequential file”
“Coding input-output statements for line-sequential files” on page 177
“Defining and allocating line-sequential files” on page 177

RELATED REFERENCES
“Allowable control characters”

Allowable control characters


The control characters shown in the table below are the only characters other than
printable characters that line-sequential files can contain. The hexadecimal values
are in EBCDIC.

Hexadecimal value Control character


X’05’ Horizontal tab
X’0B’ Vertical tab
X’0C’ Form feed
X’0D’ Carriage return
X’0E’ DBCS shift-out
X’0F’ DBCS shift-in
X’15’ New-line
X’16’ Backspace
X’2F’ Alarm

The new-line character is treated as a record delimiter. The other control characters
are treated as data and are part of the record.

RELATED TASKS
“Defining line-sequential files and records in COBOL” on page 175

Describing the structure of a line-sequential file


In the FILE SECTION of the DATA DIVISION, code a file description (FD) entry for the
file. In the associated record description entry or entries, define the record-name and
record length.

Code the logical size of the records with the RECORD clause. Line-sequential files are
stream files. Because of their character-oriented nature, the physical records are of
variable length.

The following examples show how the FD entry might look for a line-sequential
file:

With fixed-length records:


FILE SECTION.
FD COMMUTER-FILE
RECORD CONTAINS 80 CHARACTERS.
01 COMMUTER-RECORD.
05 COMMUTER-NUMBER PIC X(16).
05 COMMUTER-DESCRIPTION PIC X(64).

With variable-length records:


FILE SECTION.
FD COMMUTER-FILE
RECORD VARYING FROM 16 TO 80 CHARACTERS.

176 Programming Guide


01 COMMUTER-RECORD.
05 COMMUTER-NUMBER PIC X(16).
05 COMMUTER-DESCRIPTION PIC X(64).

If you code the same fixed size and no OCCURS DEPENDING ON clause for any level-01
record description entries associated with the file, that fixed size is the logical
record length. However, because blanks at the end of a record are not written to
the file, the physical records might be of varying lengths.

RELATED TASKS
“Defining line-sequential files and records in COBOL” on page 175
“Coding input-output statements for line-sequential files”
“Defining and allocating line-sequential files”

RELATED REFERENCES
Data Division—file description entries (Enterprise COBOL Language Reference)

Defining and allocating line-sequential files


You can define a line-sequent