100% found this document useful (1 vote)
4K views672 pages

COBOL Programming Guide

This edition applies to Version 2 Release 2 of IBM COBOL for OS / 390 and VM (program number 5648-A25) Make sure you are using the correct edition for the level of the product. A form for readers' comments appears at the back of this publication.

Uploaded by

api-3832180
Copyright
© Attribution Non-Commercial (BY-NC)
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)
4K views672 pages

COBOL Programming Guide

This edition applies to Version 2 Release 2 of IBM COBOL for OS / 390 and VM (program number 5648-A25) Make sure you are using the correct edition for the level of the product. A form for readers' comments appears at the back of this publication.

Uploaded by

api-3832180
Copyright
© Attribution Non-Commercial (BY-NC)
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/ 672

COBOL for OS/390 & VM 

Programming Guide
Version 2 Release 2

SC26-9049-05
COBOL for OS/390 & VM 

Programming Guide
Version 2 Release 2

SC26-9049-05
Note!
Before using this information and the product it supports, be sure to read the general information under “Notices” on
page 609.

Sixth Edition (September 2000)


This edition applies to Version 2 Release 2 of IBM COBOL for OS/390 & VM (program number 5648-A25) and to all
subsequent releases and modifications until otherwise indicated in new editions. Make sure you are using the
correct edition for the level of the product.
Order publications 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.
Publications are not stocked at the address below.
A form for readers’ comments appears at the back of this publication. If the form has been removed, address your
comments to:
IBM Corporation, Department HHX/H3
P.O Box 49023
San Jose, CA 95161-9023
USA
or fax it to this U.S. number: 800-426-7773
or use the form on the Web at:
http://www.ibm.com/software/ad/rcf/
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.
© Copyright International Business Machines Corporation 1991, 2000. All rights reserved.
US Government Users Restricted Rights – Use, duplication or disclosure restricted by GSA ADP Schedule Contract
with IBM Corp.
Contents
About this book . . . . . . . . . . . xi Types of intrinsic functions . . . . . . . . 31
How this book will help you. . . . . . . .
. xi Nesting functions . . . . . . . . . . . 32
Abbreviated terms . . . . . . . . . . .
. xi Using tables (arrays) and pointers . . . . . . . 32
How to read syntax diagrams . . . . . . . . xii
How examples are shown . . . . . . . . . xiii Chapter 3. Working with numbers and
Comparison of commonly-used terms . . . . . xiii arithmetic . . . . . . . . . . . . . 33
Summary of changes . . . . . . . . . . . xiv Defining numeric data. . . . . . . . . . . 33
Major changes . . . . . . . . . . . . xiv Displaying numeric data . . . . . . . . . . 34
Controlling how numeric data is stored . . . . . 35
Part 1. Coding your program . . . . 1 Formats for numeric data. . . . . . . . . . 36
External decimal (DISPLAY) items . . . . . . 36
External floating-point (DISPLAY) items . . . . 36
Chapter 1. Structuring your program . . 5
Binary (COMP) items . . . . . . . . . . 37
Identifying a program . . . . . . . . . . . 5
Native binary (COMP-5) items . . . . . . . 37
Identifying a program as recursive . . . . . . 6
Packed-decimal (COMP-3) items . . . . . . 38
Marking a program as callable by containing
Floating-point (COMP-1 and COMP-2) items . . 38
programs . . . . . . . . . . . . . . 6
Examples: numeric data and internal representation 38
Setting a program to an initial state. . . . . . 6
Data format conversions . . . . . . . . . . 39
Changing the header of a source listing . . . . 6
Conversions and precision . . . . . . . . 40
Describing the computing environment . . . . . 7
Sign representation and processing . . . . . . 41
Example: FILE-CONTROL entries . . . . . . 7
NUMPROC(PFD) . . . . . . . . . . . 41
Specifying the collating sequence . . . . . . 8
NUMPROC(NOPFD) . . . . . . . . . . 41
Defining symbolic characters . . . . . . . . 9
NUMPROC(MIG) . . . . . . . . . . . 41
Defining a user-defined class . . . . . . . . 9
Checking for incompatible data (numeric class test) 42
Defining files to the operating system . . . . 10
Performing arithmetic . . . . . . . . . . . 43
Describing the data . . . . . . . . . . . . 12
COMPUTE and other arithmetic statements . . 43
Using data in input and output operations . . . 13
Arithmetic expressions . . . . . . . . . 43
Comparison of WORKING-STORAGE and
Numeric intrinsic functions . . . . . . . . 44
LOCAL-STORAGE . . . . . . . . . . . 15
Nesting functions and arithmetic expressions . . 45
Using data from another program . . . . . . 16
ALL subscripting and special registers . . . . 45
Processing the data . . . . . . . . . . . . 17
Math and date Language Environment services 45
How logic is divided in the PROCEDURE
Examples: numeric intrinsic functions . . . . . 47
DIVISION . . . . . . . . . . . . . . 17
General number handling . . . . . . . . 47
Declaratives . . . . . . . . . . . . . 21
Date and time . . . . . . . . . . . . 47
Finance . . . . . . . . . . . . . . . 47
Chapter 2. Using data . . . . . . . . 23 Mathematics . . . . . . . . . . . . . 48
Using variables, structures, literals, and constants . 23 Statistics . . . . . . . . . . . . . . 48
Variables . . . . . . . . . . . . . . 23 Fixed-point versus floating-point arithmetic . . . 49
Data structure: data items and group items . . . 23 Floating-point evaluations . . . . . . . . 49
Literals . . . . . . . . . . . . . . . 24 Fixed-point evaluations . . . . . . . . . 49
Constants . . . . . . . . . . . . . . 24 Arithmetic comparisons (relation conditions) . . 50
Figurative constants . . . . . . . . . . 24 Examples: fixed-point and floating-point
Assigning values to data items . . . . . . . . 25 evaluations . . . . . . . . . . . . . 50
Examples: initializing variables . . . . . . . 25 Using currency signs . . . . . . . . . . . 51
Initializing a structure (INITIALIZE) . . . . . 26 Example: multiple currency signs . . . . . . 52
Assigning values to variables or structures
(MOVE) . . . . . . . . . . . . . . 27 Chapter 4. Handling tables . . . . . . 53
Assigning arithmetic results (MOVE or
Defining a table (OCCURS) . . . . . . . . . 53
COMPUTE) . . . . . . . . . . . . . 27
Nesting tables . . . . . . . . . . . . . 54
Assigning input from a screen or file (ACCEPT) 28
Subscripting . . . . . . . . . . . . . 54
Displaying values on a screen or in a file (DISPLAY) 29
Indexing . . . . . . . . . . . . . . 55
Displaying data on the system logical output
Referring to an item in a table . . . . . . . . 55
device . . . . . . . . . . . . . . . 29
Subscripting . . . . . . . . . . . . . 56
Using WITH NO ADVANCING . . . . . . 30
Indexing . . . . . . . . . . . . . . 57
Using intrinsic functions (built-in functions) . . . 31
Putting values into a table . . . . . . . . . 58

© Copyright IBM Corp. 1991, 2000 iii


Loading a table dynamically. . . . . . . . 58 File organization and input-output devices . . . 101
Initializing a table (INITIALIZE) . . . . . . 58 Choosing file organization and access mode . . . 103
Assigning values when you define a table Format for coding input and output . . . . . 103
(VALUE) . . . . . . . . . . . . . . 58 Allocating files . . . . . . . . . . . . . 105
Example: PERFORM and subscripting . . . . 60 Checking for input or output errors . . . . . . 106
Example: PERFORM and indexing. . . . . . 61
Creating variable-length tables (DEPENDING ON) 62 Chapter 8. Processing QSAM files . . 107
Loading a variable-length table . . . . . . . 63 Defining QSAM files and records in COBOL . . . 107
Assigning values to a variable-length table . . . 64 Establishing record formats. . . . . . . . 108
Searching a table . . . . . . . . . . . . 65 Setting block sizes . . . . . . . . . . . 115
Doing a serial search (SEARCH) . . . . . . 65 Coding input and output statements for QSAM
Doing a binary search (SEARCH ALL) . . . . 66 files . . . . . . . . . . . . . . . . 117
Processing table items using intrinsic functions . . 67 Opening QSAM files . . . . . . . . . . 117
Example: intrinsic functions . . . . . . . . 68 Dynamically creating QSAM files with CBLQDA 118
Adding records to QSAM files. . . . . . . 119
Chapter 5. Selecting and repeating Updating QSAM files. . . . . . . . . . 119
program actions . . . . . . . . . . 69 Writing QSAM files to a printer or spooled data
Selecting program actions . . . . . . . . . 69 set . . . . . . . . . . . . . . . . 119
Coding a choice of actions . . . . . . . . 69 Closing QSAM files . . . . . . . . . . 120
Coding conditional expressions . . . . . . . 73 Handling errors in QSAM files . . . . . . . 120
Repeating program actions . . . . . . . . . 76 Working with QSAM files under OS/390 . . . . 121
Choosing inline or out-of-line PERFORM . . . 76 Defining and allocating QSAM files . . . . . 121
Coding a loop . . . . . . . . . . . . 77 Retrieving QSAM files . . . . . . . . . 123
Coding a loop through a table . . . . . . . 78 Ensuring file attributes match your program 124
Executing multiple paragraphs or sections . . . 79 Using striped extended-format QSAM data sets 126
Accessing HFS files using QSAM . . . . . . . 127
Chapter 6. Handling strings . . . . . . 81 Restrictions and usage . . . . . . . . . 127
Identifying QSAM files to CMS . . . . . . . 128
Joining data items (STRING) . . . . . . . . 81
Using FILEDEF. . . . . . . . . . . . 128
Example: STRING statement. . . . . . . . 81
Using LABELDEF . . . . . . . . . . . 129
Splitting data items (UNSTRING) . . . . . . . 83
Labels for QSAM files . . . . . . . . . . 129
Example: UNSTRING statement . . . . . . 83
Using trailer and header labels . . . . . . 130
Manipulating null-terminated strings . . . . . . 85
Format of standard labels . . . . . . . . 131
Example: null-terminated strings . . . . . . 86
Processing QSAM ASCII files on tape . . . . . 132
Referring to substrings of data items . . . . . . 86
Requesting the ASCII alphabet . . . . . . 132
Reference modifiers. . . . . . . . . . . 87
Defining the record formats . . . . . . . 132
Example: arithmetic expressions as reference
Defining the ddname . . . . . . . . . . 132
modifiers . . . . . . . . . . . . . . 88
Processing ASCII file labels . . . . . . . . . 133
Example: intrinsic functions as reference
modifiers . . . . . . . . . . . . . . 88
Tallying and replacing data items (INSPECT) . . . 89 Chapter 9. Processing VSAM files . . 135
Examples: INSPECT statement . . . . . . . 89 VSAM files . . . . . . . . . . . . . . 136
Converting double-byte character set (DBCS) data 90 Defining VSAM file organization and records . . 137
DBCS notation . . . . . . . . . . . . 90 Specifying sequential organization for VSAM
Nonnumeric to DBCS data conversion files . . . . . . . . . . . . . . . 138
(IGZCA2D) . . . . . . . . . . . . . 90 Specifying indexed organization for VSAM files 138
DBCS to nonnumeric data conversion Specifying relative organization for VSAM files 139
(IGZCD2A) . . . . . . . . . . . . . 92 Specifying access modes for VSAM files . . . 141
Converting data items (intrinsic functions) . . . . 94 Defining record lengths for VSAM files. . . . 141
Converting to uppercase or lowercase Coding input and output statements for VSAM
(UPPER-CASE, LOWER-CASE) . . . . . . . 94 files . . . . . . . . . . . . . . . . 143
Converting to reverse order (REVERSE) . . . . 95 File position indicator . . . . . . . . . 144
Converting to numbers (NUMVAL, NUMVAL-C) 95 Opening a file (ESDS, KSDS, or RRDS) . . . . 145
Evaluating data items (intrinsic functions) . . . . 96 Reading records from a VSAM file . . . . . 147
Evaluating single characters for collating Updating records in a VSAM file . . . . . . 148
sequence . . . . . . . . . . . . . . 96 Adding records to a VSAM file . . . . . . 149
Finding the largest or smallest data item . . . 97 Replacing records in a VSAM file. . . . . . 149
Finding the length of data items . . . . . . 98 Deleting records from a VSAM file . . . . . 150
Finding the date of compilation . . . . . . 99 Closing VSAM files . . . . . . . . . . 150
Handling errors in VSAM files . . . . . . . 151
Chapter 7. Processing files . . . . . 101 Protecting VSAM files with a password . . . . 151

iv Programming Guide
Example: password protection for a VSAM Sort special registers . . . . . . . . . . 184
indexed file . . . . . . . . . . . . . 152 Changing DFSORT defaults with control
Working with VSAM data sets under OS/390 and statements . . . . . . . . . . . . . 185
OS/390 UNIX . . . . . . . . . . . . . 152 Allocating storage for sort or merge operations 186
Defining VSAM files under OS/390 . . . . . 153 Using checkpoint/restart with DFSORT under
Creating alternate indexes . . . . . . . . 154 OS/390 . . . . . . . . . . . . . . . 186
Allocating VSAM files . . . . . . . . . 156 Sorting under CICS . . . . . . . . . . . 187
Sharing VSAM files through RLS . . . . . . 157 CICS SORT application restrictions . . . . . 187
Defining VSAM data sets under CMS . . . . . 158
Improving VSAM performance . . . . . . . 159 Chapter 12. Handling errors . . . . . 189
Requesting dumps . . . . . . . . . . . 189
Chapter 10. Processing line-sequential Creating a formatted dump. . . . . . . . 189
files . . . . . . . . . . . . . . . 163 Creating a system dump . . . . . . . . 190
Defining line-sequential files and records in Handling errors in joining and splitting strings . . 190
COBOL . . . . . . . . . . . . . . . 163 Handling errors in arithmetic operations . . . . 191
Allowable control characters . . . . . . . 164 Example: checking for division by zero . . . . 191
Describing the structure of a line-sequential file 164 Handling errors in input and output operations 191
Defining and allocating line-sequential files . . . 165 Using the end-of-file condition (AT END) . . . 193
Coding input-output statements for line-sequential Coding ERROR declaratives . . . . . . . 194
files . . . . . . . . . . . . . . . . 165 Using file status keys . . . . . . . . . . 194
Opening line-sequential files . . . . . . . 166 Example: file status key . . . . . . . . . 195
Reading records from line-sequential files . . . 166 Using VSAM return codes (VSAM files only) 196
Adding records to line-sequential files . . . . 167 Example: checking VSAM status codes . . . . 196
Closing line-sequential files. . . . . . . . 167 Coding INVALID KEY phrases . . . . . . 198
Handling errors in line-sequential files . . . . . 168 Example: FILE STATUS and INVALID KEY . . 198
Handling errors when calling programs . . . . 199
Chapter 11. Sorting and merging files 169 Writing routines for handling errors . . . . . . 199
Sort and merge process . . . . . . . . . . 170
Describing the sort or merge file . . . . . . . 170 Part 2. Compiling and debugging
Describing the input to sorting or merging . . . 171 your program . . . . . . . . . . 201
Example: describing sort and input files for
SORT . . . . . . . . . . . . . . . 171
Coding the input procedure . . . . . . . . 172
Chapter 13. Compiling under OS/390 203
Describing the output from sorting or merging . . 173 Compiling with JCL . . . . . . . . . . . 203
Coding the output procedure . . . . . . . . 173 Using a cataloged procedure . . . . . . . 204
Coding considerations when using DFSORT on Writing JCL to compile programs. . . . . . 213
OS/390 . . . . . . . . . . . . . . 174 Compiling under TSO . . . . . . . . . . 215
Example: coding the output procedure when Example: ALLOCATE and CALL for compiling
using DFSORT . . . . . . . . . . . . 174 under TSO . . . . . . . . . . . . . 215
Restrictions on input and output procedures . . . 175 Example: CLIST for compiling under TSO . . . 216
Defining sort and merge data sets under OS/390 175 Starting the compiler from an assembler program 216
Defining sort and merge files under CMS . . . . 176 Defining compiler input and output . . . . . . 218
Sorting variable-length records . . . . . . . 176 Data sets used by the compiler under OS/390 218
Requesting the sort or merge . . . . . . . . 177 Defining the source code data set (SYSIN) . . . 220
Setting sort or merge criteria . . . . . . . 177 Specifying source libraries (SYSLIB) . . . . . 220
Example: sorting with input and output Defining the output data set (SYSPRINT) . . . 221
procedures . . . . . . . . . . . . . 178 Directing compiler messages to your terminal
Choosing alternate collating sequences . . . . 179 (SYSTERM) . . . . . . . . . . . . . 221
Sorting on windowed date fields . . . . . . 179 Creating object code (SYSLIN or SYSPUNCH) 221
Preserving the original sequence of records with Creating an associated data file (SYSADATA) 222
equal keys . . . . . . . . . . . . . 180 Defining the output IDL data set (SYSIDL) . . 222
Determining whether the sort or merge was Defining the debug data set (SYSDEBUG) . . . 222
successful . . . . . . . . . . . . . . 180 Specifying compiler options under OS/390 . . . 223
Stopping a sort or merge operation prematurely 181 Specifying compiler options with the PROCESS
Improving sort performance with FASTSRT . . . 181 (CBL) statement . . . . . . . . . . . 223
FASTSRT requirements for JCL (OS/390 only) 181 Example: specifying compiler options using JCL 224
FASTSRT requirements for sort input and Example: specifying compiler options under
output files . . . . . . . . . . . . . 181 TSO . . . . . . . . . . . . . . . 224
Checking for sort errors with NOFASTSRT . . . 183 Compiler options and compiler output under
Controlling sort behavior . . . . . . . . . 184 OS/390 . . . . . . . . . . . . . . 224
Compiling multiple programs (batch compilation) 226

Contents v
Example: batch compilation . . . . . . . 226 External data . . . . . . . . . . . . 267
Specifying compiler options in a batch QSAM input/output buffers . . . . . . . 267
compilation . . . . . . . . . . . . . 227 DATEPROC . . . . . . . . . . . . . . 267
Example: precedence of options in a batch DBCS . . . . . . . . . . . . . . . . 269
compilation . . . . . . . . . . . . . 228 DECK . . . . . . . . . . . . . . . . 269
Example: LANGUAGE option in a batch DIAGTRUNC . . . . . . . . . . . . . 269
compilation . . . . . . . . . . . . . 229 DISK/PRINT . . . . . . . . . . . . . 270
Correcting errors in your source program . . . . 230 DLL . . . . . . . . . . . . . . . . 270
Generating a list of compiler error messages . . 230 DUMP . . . . . . . . . . . . . . . 271
Messages and listings for compiler-detected DYNAM . . . . . . . . . . . . . . . 272
errors . . . . . . . . . . . . . . . 231 EXIT . . . . . . . . . . . . . . . . 272
Format of compiler error messages . . . . . 231 EXPORTALL . . . . . . . . . . . . . 272
Severity codes for compiler error messages . . 232 FASTSRT . . . . . . . . . . . . . . . 273
FLAG . . . . . . . . . . . . . . . . 274
Chapter 14. Compiling under OS/390 FLAGMIG . . . . . . . . . . . . . . 275
UNIX . . . . . . . . . . . . . . . 235 FLAGSTD . . . . . . . . . . . . . . 275
IDLGEN . . . . . . . . . . . . . . . 277
Setting environment variables under OS/390 UNIX 235
INTDATE . . . . . . . . . . . . . . 278
Specifying compiler options under OS/390 UNIX 236
LANGUAGE . . . . . . . . . . . . . 279
Compiling and linking with the cob2 command 237
LIB . . . . . . . . . . . . . . . . . 280
Defining input and output . . . . . . . . 237
LINECOUNT . . . . . . . . . . . . . 280
Creating a DLL . . . . . . . . . . . . 238
LIST . . . . . . . . . . . . . . . . 281
Example: using cob2 to compile under OS/390
MAP . . . . . . . . . . . . . . . . 281
UNIX . . . . . . . . . . . . . . . 238
NAME . . . . . . . . . . . . . . . 282
cob2 . . . . . . . . . . . . . . . 239
NUMBER . . . . . . . . . . . . . . 283
cob2 input and output files . . . . . . . . 240
NUMPROC . . . . . . . . . . . . . . 283
Compiling using scripts . . . . . . . . . . 241
OBJECT . . . . . . . . . . . . . . . 284
OFFSET . . . . . . . . . . . . . . . 285
Chapter 15. Compiling under CMS 243 OPTIMIZE . . . . . . . . . . . . . . 285
Accessing the compiler (CP LINK and ACCESS) 243 Unused data items: . . . . . . . . . . 286
Specifying a source program to compile . . . . 244 OUTDD . . . . . . . . . . . . . . . 286
COBOL2 . . . . . . . . . . . . . . 244 PGMNAME . . . . . . . . . . . . . . 287
Using compiler-directing statements . . . . . . 245 PGMNAME(COMPAT) . . . . . . . . . 287
Specifying compiler options under CMS . . . . 246 PGMNAME(LONGUPPER). . . . . . . . 288
Using parentheses in COBOL2 . . . . . . 246 PGMNAME(LONGMIXED) . . . . . . . 288
Abbreviating compiler options . . . . . . 246 PGMNAME usage notes. . . . . . . . . 288
Using logical line-editing characters . . . . . 247 QUOTE/APOST . . . . . . . . . . . . 289
Additional compiler options under CMS . . . 247 RENT . . . . . . . . . . . . . . . . 289
Differences in compiler options under CMS . . 248 RMODE . . . . . . . . . . . . . . . 290
Precedence of compiler options under CMS . . 248 SEQUENCE . . . . . . . . . . . . . . 291
Files used by the compiler under CMS . . . . 248 SIZE . . . . . . . . . . . . . . . . 291
Naming generated files under CMS . . . . . . 251 SOURCE . . . . . . . . . . . . . . . 292
Overriding FILEDEF . . . . . . . . . . 251 SPACE . . . . . . . . . . . . . . . 293
Using system-generated names . . . . . . 251 SQL . . . . . . . . . . . . . . . . 293
Correcting errors . . . . . . . . . . . . 252 SSRANGE . . . . . . . . . . . . . . 294
Error messages from COBOL2 . . . . . . . 252 TERMINAL . . . . . . . . . . . . . . 295
TEST . . . . . . . . . . . . . . . . 295
Chapter 16. Compiler options . . . . 257 TRUNC . . . . . . . . . . . . . . . 297
Option settings for COBOL 85 Standard TRUNC example 1 . . . . . . . . . . 298
conformance. . . . . . . . . . . . . . 259 TRUNC example 2 . . . . . . . . . . 299
Conflicting compiler options . . . . . . . . 259 TYPECHK . . . . . . . . . . . . . . 300
ADATA . . . . . . . . . . . . . . . 261 VBREF . . . . . . . . . . . . . . . 301
ANALYZE . . . . . . . . . . . . . . 261 WORD . . . . . . . . . . . . . . . 301
ADV . . . . . . . . . . . . . . . . 262 XREF . . . . . . . . . . . . . . . . 302
ARITH . . . . . . . . . . . . . . . 262 YEARWINDOW . . . . . . . . . . . . 303
AWO . . . . . . . . . . . . . . . . 263 ZWB . . . . . . . . . . . . . . . . 304
BUFSIZE . . . . . . . . . . . . . . . 263 Compiler-directing statements . . . . . . . . 304
CMPR2 . . . . . . . . . . . . . . . 264
COMPILE . . . . . . . . . . . . . . 265 Chapter 17. Debugging . . . . . . . 309
CURRENCY . . . . . . . . . . . . . . 265 Debugging with source language . . . . . . . 310
DATA . . . . . . . . . . . . . . . . 266 Tracing program logic . . . . . . . . . 310

vi Programming Guide
Finding and handling input-output errors . . . 311 DB2 coprocessor . . . . . . . . . . . 358
Validating data . . . . . . . . . . . . 311
Finding uninitialized data . . . . . . . . 311 Chapter 20. Running COBOL
Generating information about procedures . . . 312 programs under IMS . . . . . . . . 359
Debugging using compiler options . . . . . . 313
Compiling and linking COBOL programs for
Finding coding errors . . . . . . . . . 314
running under IMS . . . . . . . . . . . 359
Finding line sequence problems . . . . . . 315
Checking for valid ranges . . . . . . . . 315
Selecting the level of error to be diagnosed . . 316 Chapter 21. Running COBOL
Finding program entity definitions and programs under OS/390 UNIX . . . . 361
references . . . . . . . . . . . . . 317 Running in OS/390 UNIX environments . . . . 361
Listing data items . . . . . . . . . . . 318 Setting and accessing environment variables . . . 362
Getting listings . . . . . . . . . . . . . 319 Setting environment variables that affect
Example: short listing . . . . . . . . . 320 execution . . . . . . . . . . . . . . 362
Example: SOURCE and NUMBER output . . . 323 Resetting environment variables . . . . . . 363
Example: embedded map summary . . . . . 325 Accessing environment variables . . . . . . 363
Terms used in MAP output. . . . . . . . 326 Example: accessing environment variables . . . 363
Symbols used in LIST and MAP output . . . 326 Calling UNIX/POSIX APIs . . . . . . . . . 364
Example: nested program map . . . . . . 328 fork, exec, and spawn . . . . . . . . . 364
Reading LIST output . . . . . . . . . . 328 Samples . . . . . . . . . . . . . . 365
Example: XREF output - data-name Accessing main program parameters . . . . . 365
cross-references. . . . . . . . . . . . 340 Example: accessing main program parameters 366
Example: XREF output - program-name
cross-references. . . . . . . . . . . . 341 Chapter 22. Running COBOL
Example: embedded cross-reference . . . . . 341 programs under CMS . . . . . . . . 369
Example: OFFSET compiler output . . . . . 342 Run-time restrictions under CMS . . . . . . . 369
Example: VBREF compiler output . . . . . 343 Handling QSAM files under CMS . . . . . . 369
Preparing to use the debugger. . . . . . . . 343 Run-time message IGZ0002S . . . . . . . . 370

Part 3. Targeting COBOL programs Chapter 23. Accessing COBOL


for certain environments . . . . . 345 programs interactively with ISPF . . . 371

Chapter 18. Developing COBOL Part 4. Developing object-oriented


programs for CICS . . . . . . . . . 347 programs . . . . . . . . . . . . 373
Coding COBOL programs to run under CICS . . 347
Coding file input and output . . . . . . . 348
Retrieving the system date and time. . . . . 348
Chapter 24. Writing object-oriented
Displaying the contents of data items . . . . 348 programs . . . . . . . . . . . . . 375
Calling to or from COBOL programs . . . . 348 Example: mail-order catalog . . . . . . . . 375
Coding a COBOL program to run above the Subclasses . . . . . . . . . . . . . 377
16-MB line . . . . . . . . . . . . . 349 Defining a class . . . . . . . . . . . . 378
Determining the success of ECI calls. . . . . 349 CLASS-ID paragraph for defining a class . . . 378
Preparing COBOL programs to run under CICS 350 REPOSITORY paragraph for defining a class 379
Using the CICS translator . . . . . . . . 350 WORKING-STORAGE SECTION for defining a
Compiling your CICS program . . . . . . 350 class . . . . . . . . . . . . . . . 379
CICS reserved-word table . . . . . . . . 351 Example: defining a class . . . . . . . . 380
Handling errors by using CICS HANDLE . . . . 352 Defining a class method . . . . . . . . . . 381
Example: handling errors by using CICS METHOD-ID paragraph for defining a class
HANDLE . . . . . . . . . . . . . 352 method . . . . . . . . . . . . . . 381
Overriding a method . . . . . . . . . . 381
Chapter 19. Programming for a DB2 INPUT-OUTPUT SECTION for defining a
method . . . . . . . . . . . . . . 382
environment . . . . . . . . . . . . 355 DATA DIVISION for defining a method . . . 382
Coding SQL statements . . . . . . . . . . 355 PROCEDURE DIVISION for defining a method 383
Using SQL INCLUDE . . . . . . . . . 355 Coding special methods . . . . . . . . . 383
Using binary items . . . . . . . . . . 355 Example: defining a method . . . . . . . 384
Determining the success of SQL statements . . 356 Defining a client program . . . . . . . . . 389
Compiling with the SQL option . . . . . . . 356 REPOSITORY paragraph for defining a client 389
Compiling in batch . . . . . . . . . . 357 WORKING-STORAGE SECTION for defining a
Separating DB2 suboptions . . . . . . . . 357 client . . . . . . . . . . . . . . . 390

Contents vii
Creating and freeing instances of classes . . . 390 Coordinating procedural code with interface
Manipulating object references . . . . . . 391 actions . . . . . . . . . . . . . . 452
Invoking methods . . . . . . . . . . . 391 Integrating procedural code into OO systems 452
Example: defining a client . . . . . . . . 392 Changing procedural code . . . . . . . . 453
Defining a subclass . . . . . . . . . . . 393 Converting from procedure-oriented to OO
CLASS-ID paragraph for defining a subclass 394 programs . . . . . . . . . . . . . . . 453
REPOSITORY paragraph for defining a subclass 394 Identifying objects . . . . . . . . . . . 454
WORKING-STORAGE SECTION for defining a Analyzing data flow and usage . . . . . . 454
subclass . . . . . . . . . . . . . . 395 Reallocating code to objects . . . . . . . 454
Defining a subclass method . . . . . . . 395 Writing the object-oriented code . . . . . . 455
Example: defining a subclass (with methods) 396
Defining a metaclass . . . . . . . . . . . 405
Part 5. Working with more
CLASS-ID paragraph for defining a metaclass 406
REPOSITORY paragraph for defining a complex applications . . . . . . . 457
metaclass . . . . . . . . . . . . . . 406
WORKING-STORAGE SECTION for defining a Chapter 28. Using subprograms . . . 459
metaclass . . . . . . . . . . . . . . 406 Main programs, subprograms, and calls . . . . 459
Defining a metaclass method . . . . . . . 406 Ending and reentering main programs or
Changing the definition of a class or subclass 407 subprograms . . . . . . . . . . . . . 460
Changing a client program . . . . . . . . 407 Transferring control to another program . . . . 461
Example: defining a metaclass (with methods) 408 Making static calls. . . . . . . . . . . 462
Making dynamic calls . . . . . . . . . 462
Chapter 25. System Object Model. . . 415 Performance considerations of static and
SOM Interface Repository . . . . . . . . . 415 dynamic calls . . . . . . . . . . . . 464
Accessing the SOM Interface Repository . . . 415 Making both static and dynamic calls . . . . 465
Populating the SOM Interface Repository . . . 416 Example: static and dynamic CALL statements 465
SOM environment variables . . . . . . . . 417 NODYNAM restriction (CMS only) . . . . . 467
Example: sample JCL for an object-oriented Calling nested COBOL programs . . . . . . 468
application . . . . . . . . . . . . . 418 Making recursive calls . . . . . . . . . . 472
SOM services . . . . . . . . . . . . . 420 Calling to and from object-oriented programs . . 472
SOM methods and functions . . . . . . . 420 Using procedure pointers . . . . . . . . . 472
Class initialization . . . . . . . . . . . 421 Calling a C function-pointer . . . . . . . 473
Changing SOM class interfaces . . . . . . 422 Calling to alternate entry points . . . . . . 473
Making programs reentrant . . . . . . . . 474
Chapter 26. Using SOM IDL-based
class libraries . . . . . . . . . . . 425 Chapter 29. Sharing data . . . . . . 475
SOM objects . . . . . . . . . . . . . . 425 Passing data . . . . . . . . . . . . . . 475
SOM IDL . . . . . . . . . . . . . . . 426 Describing arguments in the calling program 477
Mapping IDL to COBOL . . . . . . . . . 427 Describing parameters in the called program 477
Using IDL operations. . . . . . . . . . 427 Coding the LINKAGE SECTION . . . . . . . 477
Expressing IDL attributes . . . . . . . . 428 Coding the PROCEDURE DIVISION for passing
Common IDL types . . . . . . . . . . 429 arguments . . . . . . . . . . . . . . 478
Complex IDL types . . . . . . . . . . 432 Grouping data to be passed . . . . . . . 478
Passing COBOL arguments and return values 435 Handling null-terminated strings . . . . . . 478
Example: using a SOM IDL-based class library 440 Using pointers to process a chained list . . . 479
Handling errors and exceptions . . . . . . . 442 Passing return code information . . . . . . . 482
Passing environment variables. . . . . . . 443 Understanding the RETURN-CODE special
Checking the exception type field . . . . . 443 register . . . . . . . . . . . . . . 482
Handling exceptions . . . . . . . . . . 443 Using PROCEDURE DIVISION RETURNING . .
Example: checking SOM exceptions . . . . . 443 .. . . . . . . . . . . . . . . . . 482
Creating and initializing object instances . . . . 445 Specifying CALL . . . RETURNING . . . . . . 483
Looking at the IDL file . . . . . . . . . . 446 Sharing data by using the EXTERNAL clause. . . 483
Avoiding memory leaks . . . . . . . . . . 447 Sharing files between programs (external files) . . 483
Example: COBOL variable-length string class 448 Example: using external files . . . . . . . 484
Source code for helper routines . . . . . . . 450
Chapter 30. Creating a DLL or a DLL
Chapter 27. Wrapping or converting application . . . . . . . . . . . . 489
procedure-oriented programs . . . . 451 Dynamic link libraries (DLLs) . . . . . . . . 489
OO view of COBOL programs. . . . . . . . 451 Compiling programs to create DLLs . . . . . . 490
Wrapping procedure-oriented programs . . . . 452 Linking DLLs . . . . . . . . . . . . . 491

viii Programming Guide


Prelinking certain DLLs . . . . . . . . . . 492 Analyzing and avoiding date-related diagnostic
Example: sample JCL for a procedural DLL messages . . . . . . . . . . . . . . . 528
application . . . . . . . . . . . . . 492 Avoiding problems in processing dates . . . . . 530
Using CALL identifier with DLLs . . . . . . 493 Avoiding problems with packed-decimal fields 530
Search order for DLLs in HFS . . . . . . . 494 Moving from expanded to windowed date fields 530
Using DLL linkage and dynamic calls together . . 494
Using procedure-pointers with DLLs . . . . 495
Part 6. Improving performance and
Calling DLLs from non-DLLs . . . . . . . 496
Example: calling DLLs from non-DLLs . . . . 496 productivity . . . . . . . . . . . 533
Using COBOL DLLs with C/C++ programs . . . 498
Using DLLs in OO COBOL applications . . . . 498 Chapter 33. Tuning your program . . . 535
Using an optimal programming style . . . . . 535
Chapter 31. Interrupts and Using structured programming . . . . . . 536
checkpoint/restart . . . . . . . . . 501 Factoring expressions. . . . . . . . . . 536
Setting checkpoints . . . . . . . . . . . 501 Using symbolic constants . . . . . . . . 536
Designing checkpoints . . . . . . . . . 502 Grouping constant computations . . . . . . 536
Testing for a successful checkpoint . . . . . 502 Grouping duplicate computations . . . . . 537
DD statements for defining checkpoint data sets 503 Choosing efficient data types . . . . . . . . 537
Messages generated during checkpoint . . . . 504 Computational data items . . . . . . . . 537
Restarting programs . . . . . . . . . . . 504 Consistent data types. . . . . . . . . . 538
Requesting automatic restart . . . . . . . 505 Arithmetic expressions . . . . . . . . . 538
Requesting deferred restart . . . . . . . . 505 Exponentiations . . . . . . . . . . . 538
Formats for requesting deferred restart . . . . 506 Handling tables efficiently . . . . . . . . . 539
Resubmitting jobs for restart . . . . . . . 507 Optimization of table references . . . . . . 540
Example: restarting a job at a specific Optimizing your code . . . . . . . . . . 542
checkpoint step. . . . . . . . . . . . 507 Optimization . . . . . . . . . . . . 542
Example: requesting a step restart . . . . . 507 Example: PERFORM procedure integration . . 544
Example: resubmitting a job for a step restart 507 Choosing compiler features to enhance
Example: resubmitting a job for a checkpoint performance . . . . . . . . . . . . . . 544
restart . . . . . . . . . . . . . . . 508 Performance-related compiler options . . . . 545
Evaluating performance . . . . . . . . . 548
Running efficiently with CICS, IMS, or VSAM . . 548
Chapter 32. Processing two-digit-year CICS . . . . . . . . . . . . . . . 548
dates . . . . . . . . . . . . . . . 509 IMS . . . . . . . . . . . . . . . 549
Millennium language extensions (MLE) . . . . 510 VSAM . . . . . . . . . . . . . . . 549
Principles and objectives of these extensions . . 510
Resolving date-related logic problems . . . . . 511 Chapter 34. Simplifying coding . . . . 551
Using a century window . . . . . . . . 512
Eliminating repetitive coding . . . . . . . . 551
Using internal bridging . . . . . . . . . 513
Example: using the COPY statement. . . . . 552
Moving to full field expansion. . . . . . . 514
Using Language Environment callable services . . 553
Using year-first, year-only, and year-last date fields 516
Sample list of Language Environment callable
Compatible dates . . . . . . . . . . . 517
services . . . . . . . . . . . . . . 554
Example: comparing year-first date fields . . . 518
Calling Language Environment services . . . 555
Using other date formats . . . . . . . . 518
Example: Language Environment callable
Example: isolating the year . . . . . . . . 518
services . . . . . . . . . . . . . . 556
Manipulating literals as dates . . . . . . . . 519
Assumed century window . . . . . . . . 520
Treatment of nondates . . . . . . . . . 521 Part 7. Appendixes . . . . . . . . 557
Setting triggers and limits . . . . . . . . . 521
Example: using limits . . . . . . . . . 522 Appendix A. Intermediate results and
Using sign conditions . . . . . . . . . 523 arithmetic precision . . . . . . . . 559
Sorting and merging by date . . . . . . . . 523
Terminology used for intermediate results . . . . 560
Example: sorting by date and time . . . . . 524
Example: calculation of intermediate results . . . 561
Performing arithmetic on date fields. . . . . . 525
Fixed-point data and intermediate results . . . . 561
Allowing for overflow from windowed date
Addition, subtraction, multiplication, and
fields . . . . . . . . . . . . . . . 525
division . . . . . . . . . . . . . . 561
Specifying the order of evaluation . . . . . 526
Exponentiation . . . . . . . . . . . . 562
Controlling date processing explicitly . . . . . 527
Example: exponentiation in fixed-point
Using DATEVAL . . . . . . . . . . . 527
arithmetic . . . . . . . . . . . . . 563
Using UNDATE . . . . . . . . . . . 527
Truncated intermediate results. . . . . . . 564
Binary data and intermediate results . . . . 564

Contents ix
Intrinsic functions evaluated in fixed-point Processing of PRTEXIT . . . . . . . . . . 580
arithmetic . . . . . . . . . . . . . . 565 Parameter list for PRTEXIT . . . . . . . . 581
Integer functions . . . . . . . . . . . 565 Processing of ADEXIT . . . . . . . . . . 582
Mixed functions . . . . . . . . . . . 565 Parameter list for ADEXIT . . . . . . . . 582
Floating-point data and intermediate results . . . 566 Error handling for exit modules . . . . . . . 583
Exponentiations evaluated in floating-point Example: SYSIN user exit . . . . . . . . . 583
arithmetic . . . . . . . . . . . . . 567
Intrinsic functions evaluated in floating-point Appendix D. Sample programs . . . . 587
arithmetic . . . . . . . . . . . . . 567 IGYTCARA: batch application . . . . . . . . 587
ON SIZE ERROR and intermediate results. . . . 567 Input data for IGYTCARA . . . . . . . . 588
Arithmetic expressions in nonarithmetic statements 568 Report produced by IGYTCARA . . . . . . 589
Running IGYTCARA . . . . . . . . . . 590
Appendix B. Complex OCCURS IGYTCARB: interactive program . . . . . . . 592
DEPENDING ON . . . . . . . . . . 569 Running IGYTCARB . . . . . . . . . . 592
Example: complex ODO . . . . . . . . . . 569 IGYTSALE: nested program application . . . . 595
How length is calculated . . . . . . . . 570 Input data for IGYTSALE . . . . . . . . 597
Setting values of ODO objects . . . . . . . 570 Reports produced by IGYTSALE . . . . . . 598
Effects of change in ODO object value . . . . . 570 Running IGYTSALE . . . . . . . . . . 602
Preventing index errors when changing ODO Language elements and concepts that are
object value . . . . . . . . . . . . . 571 illustrated . . . . . . . . . . . . . . 604
Preventing overlay when adding elements to a
variable table . . . . . . . . . . . . 571 Notices . . . . . . . . . . . . . . 609
Trademarks . . . . . . . . . . . . . . 610
Appendix C. EXIT compiler option . . 575
Using the user-exit work area . . . . . . . . 576 Glossary . . . . . . . . . . . . . 611
Calling from exit modules . . . . . . . . . 576
Processing of INEXIT. . . . . . . . . . . 577 List of resources . . . . . . . . . . 633
Parameter list for INEXIT . . . . . . . . 577 COBOL for OS/390 & VM . . . . . . . . . 633
Processing of LIBEXIT . . . . . . . . . . 578 Related publications . . . . . . . . . . . 633
Processing of LIBEXIT with nested COPY
statements . . . . . . . . . . . . . 578
Parameter list for LIBEXIT . . . . . . . . 579
Index . . . . . . . . . . . . . . . 635

x Programming Guide
About this book
Welcome to IBM COBOL for OS/390 & VM, IBM’s latest host COBOL compiler!

This version of IBM COBOL for OS/390 & VM is fully source and object
compatible with COBOL for MVS & VM Version 1, with the exception of programs
containing object-oriented language constructs, which must be recompiled to
enable support for OS/390 SOMobjects.

IBM COBOL for OS/390 & VM is referred to as “COBOL for OS/390 & VM”
throughout this publication.

How this book will help you


This book will help you write and compile COBOL for OS/390 & VM programs. It
will also help you define object-oriented classes and methods, invoke methods, and
refer to objects in your programs. A companion volume, IBM Language Environment
Programming Guide, provides instructions on link-editing and running your
programs.

This book assumes experience in developing application programs and some


knowledge of COBOL. It focuses on using COBOL for OS/390 & VM to meet your
programming objectives and not on the definition of the COBOL language. For
complete information on COBOL syntax, refer to IBM COBOL Language Reference.

For information on migrating OS/VS COBOL and VS COBOL II programs to


COBOL for OS/390 & VM, see IBM COBOL for OS/390 & VM Compiler and
Run-Time Migration Guide.

IBM Language Environment for OS/390 & VM provides the run-time environment
and run-time services required to run your COBOL for OS/390 & VM programs.
You will find information on link-editing and running programs in the IBM
Language Environment Programming Guide and IBM Language Environment
Programming Reference.

For a comparison of commonly used COBOL for OS/390 & VM and IBM
Language Environment for OS/390 & VM terms, see “Comparison of
commonly-used terms” on page xiii.

Abbreviated terms
Certain terms are used in a shortened form in this book. Abbreviations for the
product names used most frequently in this book are listed alphabetically in the
following table. Abbreviations for other terms, if not commonly understood, are
shown in italics the first time they appear, and are listed in the glossary in the back
of this book.

Term used Long form


CICS CICS/ESA
COBOL for OS/390 & VM IBM COBOL for OS/390 & VM
CMS CMS component of VM/ESA

© Copyright IBM Corp. 1991, 2000 xi


Term used Long form
IMS IMS/VS or IMS/ESA
Language Environment IBM Language Environment for OS/390 & VM
MVS MVS/ESA
SOM System Object Model
VM VM/ESA

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


this book to refer to the combination of the following standards:
v ISO 1989:1985, Programming languages - COBOL
v ISO 1989/Amendment 1, Programming Languages - COBOL - Amendment 1:
Intrinsic function module
v X3.23-1985, American National Standard for Information Systems - Programming
Language - COBOL
v X3.23a-1989, American National Standard for Information Systems -
Programming Language - Intrinsic Function Module for COBOL
The two ISO standards are identical to the American National standards.

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 statement.
The symbol indicates that the statement syntax is continued on the next
line.
The symbol indicates that a statement is continued from the previous line.
The symbol indicates the end of a statement.
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).

v Optional items appear below the main path.

If an optional item appears above the main path, that item has no effect on the
execution of the statement and is used only for readability.

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.

xii Programming Guide


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

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

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

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

A repeat arrow above a stack indicates that you can repeat the items in the
stack.
v Keywords appear in uppercase (for example, FROM). They must be spelled exactly
as shown. Variables appear in all lowercase letters (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 book shows numerous examples of sample COBOL statements, program
fragments, and small programs to help illustrate the concepts 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.

Where it helps to more clearly separate the examples from the explanatory text,
they are presented in a different font style.

COBOL keywords and compiler options appearing in text are generally shown in
SMALL UPPER CASE. Other terms such as program variable names or method names
are sometimes shown in a different font style for clarity.

Comparison of commonly-used terms


In order to better understand the various terms used throughout the IBM
Language Environment for OS/390 & VM and IBM COBOL for OS/390 & VM
publications and what terms are meant to be equivalent, see the following table.

Language Environment term COBOL for OS/390 & VM equivalent


Aggregate Group item
Array A table created using the OCCURS clause
Array element Table element

About this book xiii


Language Environment term COBOL for OS/390 & VM equivalent
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

Summary of changes
This section lists the key changes that have been made to IBM COBOL for OS/390
& VM. Those documented in this publication have an associated page reference for
your convenience.

The latest technical changes are marked by a change bar in the left margin. Many
corrections have been made without comment.

Chapters have been extensively reorganized, and artwork improved.


Cross-references (except for those to examples) have been grouped together at the
ends of topics so as not to interrupt the flow of the text.

Major changes
v Enhanced support for decimal data, raising the maximum number of decimal
digits from 18 to 31 and providing an extended-precision mode for arithmetic
calculations (“ARITH” on page 262)
v Enhanced production debugging using overlay hooks rather than compiled-in
hooks, with symbolic debugging information optionally in a separate file
(“TEST” on page 295)
v Support for compiling, linking, and executing in the OS/390 UNIX System
Services environment, with COBOL files able to reside in the HFS (hierarchical
file system) (“Chapter 14. Compiling under OS/390 UNIX” on page 235)
v Toleration of fork(), exec(), and spawn(); and the ability to call UNIX/POSIX
functions (“Calling UNIX/POSIX APIs” on page 364)
v Enhanced input-output function, permitting dynamic file allocation by means of
an environment variable named in SELECT . . . ASSIGN, and the accessing of
sequentially organized HFS files including by means of ACCEPT and DISPLAY
(“Allocating files” on page 105)
v Support for line-sequential file organization for accessing HFS files that contain
text data, with records delimited by the new-line character (“Chapter 10.
Processing line-sequential files” on page 163)
v COMP-5 data type, new to host COBOL, allowing values of magnitude up to the
capacity of the native binary representation (“Formats for numeric data” on
page 36)
v Significant performance improvement in processing binary data with the
TRUNC(BIN) compiler option (“TRUNC” on page 297)

xiv Programming Guide


v Support for linking of COBOL applications using the OS/390 DFSMS binder
alone, with the prelinker required only in exceptional cases under CICS
(“Compiling programs to create DLLs” on page 490)
v Diagnosis of moves (implicit or explicit) that result in numeric truncation
enabled via compiler option (“DIAGTRUNC” on page 269)
v System-determined block size for the listing data set available by specifying
BLKSIZE=0 (“Logical record length and block size” on page 219)
v Limit on block size of QSAM tape files raised to 2 GB (“Setting block sizes” on
page 115)
v Support under CICS for DISPLAY to the system logical output device and ACCEPT
for obtaining date and time (“Coding COBOL programs to run under CICS” on
page 347)
v Support for the DB2 coprocessor enabled through a new compiler option,
eliminating the need for a separate precompile step and permitting SQL
statements in nested programs and copy books (“SQL” on page 293)
v Support for the millennium language extensions now included in the base
COBOL product (“Millennium language extensions (MLE)” on page 510)

Changes in the fifth edition


v New compiler option ANALYZE to check the syntax of embedded SQL and CICS
statements (“ANALYZE” on page 261).
v Extension of the ACCEPT statement to cover the recommendation in the Working
Draft for Proposed Revision of ISO 1989:1985 Programming Language COBOL.
v New intrinsic date functions to convert to dates with a four-digit year.
v The millennium language extensions, enabling compiler-assisted date processing
for dates containing two-digit and four-digit years (“Millennium language
extensions (MLE)” on page 510).
Requires IBM VisualAge millennium language extensions for OS/390 & VM
(program number 5648-MLE) to be installed with your compiler.

Changes in the fourth edition


v Extensions to currency support for displaying financial data, including:
– Support for currency signs of more than one character
– Support for more than one type of currency sign in the same program
– Support for the euro currency sign, as defined by the Economic and Monetary
Union (EMU)

Changes from COBOL for MVS & VM


v Support has been added for dynamic link libraries (DLLs). A DLL is a load
module containing programs and data that can be accessed from other load
modules. The DLL mechanism is the primary means used for packaging SOM
class libraries. With this new support, object-oriented COBOL applications can
be packaged using separate DLL load modules for the client programs and class
definitions. Two new compiler options, DLL|NODLL and EXPORTALL|NOEXPORTALL,
are used to control the creation of DLLs. For details, see “Chapter 30. Creating a
DLL or a DLL application” on page 489.
v Due to changes in the SOMobjects product that is delivered with OS/390 Release
3, changes in the JCL for building object-oriented COBOL applications are
required:
– The SOMobjects kernel and the SOMobjects class libraries must be accessed
from the SOMobjects product DLLs, rather than being linked together with
the COBOL application load module as was required in the prior version.

About this book xv


This requires changes to the JCL to specify appropriate COBOL compiler
options for DLL support; the prelink step must specify (at least) the DLL
definition side decks for the SOM kernel and class libraries, and the SOM
SGOSPLKD data set is no longer used in the SYSLIB concatenation of the
prelink step.
– The format of the SOM profile data set has changed, and the profile is now
specified via the SOMENV DD statement rather than the SOMPROF DD statement.

For further details, see the OS/390 SOMobjects Programmer’s Guide, and
“Chapter 25. System Object Model” on page 415.
v The INTDATE compiler option is no longer an installation option only—it can now
be specified as an option when invoking the compiler. See “INTDATE” on
page 278.

xvi Programming Guide


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

© Copyright IBM Corp. 1991, 2000 1


Loading a table dynamically. . . . . . . . 58 Nonnumeric to DBCS data conversion
Initializing a table (INITIALIZE) . . . . . . 58 (IGZCA2D) . . . . . . . . . . . . . 90
Assigning values when you define a table IGZCA2D syntax . . . . . . . . . . 91
(VALUE) . . . . . . . . . . . . . . 58 IGZCA2D return codes . . . . . . . . 91
Initializing each table item individually . . . 59 Example: IGZCA2D . . . . . . . . . 92
Initializing a table at the 01 level . . . . . 59 DBCS to nonnumeric data conversion
Initializing all occurrences of a table element 59 (IGZCD2A) . . . . . . . . . . . . . 92
Example: PERFORM and subscripting . . . . 60 IGZCD2A syntax . . . . . . . . . . 93
Example: PERFORM and indexing. . . . . . 61 IGZCD2A return codes . . . . . . . . 93
Creating variable-length tables (DEPENDING ON) 62 Example: IGZCD2A . . . . . . . . . 94
Loading a variable-length table . . . . . . . 63 Converting data items (intrinsic functions) . . . . 94
Assigning values to a variable-length table . . . 64 Converting to uppercase or lowercase
Searching a table . . . . . . . . . . . . 65 (UPPER-CASE, LOWER-CASE) . . . . . . . 94
Doing a serial search (SEARCH) . . . . . . 65 Converting to reverse order (REVERSE) . . . . 95
Example: serial search . . . . . . . . . 66 Converting to numbers (NUMVAL, NUMVAL-C) 95
Doing a binary search (SEARCH ALL) . . . . 66 Evaluating data items (intrinsic functions) . . . . 96
Example: binary search . . . . . . . . 67 Evaluating single characters for collating
Processing table items using intrinsic functions . . 67 sequence . . . . . . . . . . . . . . 96
Example: intrinsic functions . . . . . . . . 68 Finding the largest or smallest data item . . . 97
MAX and MIN . . . . . . . . . . . 97
Chapter 5. Selecting and repeating program ORD-MAX and ORD-MIN . . . . . . . 97
actions . . . . . . . . . . . . . . . 69 Returning variable-length results with
Selecting program actions . . . . . . . . . 69 alphanumeric functions . . . . . . . . 97
Coding a choice of actions . . . . . . . . 69 Finding the length of data items . . . . . . 98
Using nested IF statements . . . . . . . 70 Finding the date of compilation . . . . . . 99
Using the EVALUATE statement . . . . . 71
Coding conditional expressions . . . . . . . 73 Chapter 7. Processing files . . . . . . . . 101
Switches and flags . . . . . . . . . . 74 File organization and input-output devices . . . 101
Defining switches and flags . . . . . . . 74 Choosing file organization and access mode . . . 103
Example: switches . . . . . . . . . . 74 Format for coding input and output . . . . . 103
Example: flags . . . . . . . . . . . 75 Allocating files . . . . . . . . . . . . . 105
Resetting switches and flags . . . . . . . 75 Checking for input or output errors . . . . . . 106
Example: set switch on . . . . . . . . 75
Example: set switch off . . . . . . . . 76 Chapter 8. Processing QSAM files . . . . . 107
Repeating program actions . . . . . . . . . 76 Defining QSAM files and records in COBOL . . . 107
Choosing inline or out-of-line PERFORM . . . 76 Establishing record formats. . . . . . . . 108
Example: inline PERFORM statement . . . . 77 Logical records . . . . . . . . . . . 108
Coding a loop . . . . . . . . . . . . 77 Requesting fixed-length format . . . . . 109
Coding a loop through a table . . . . . . . 78 Requesting variable-length format . . . . 110
Executing multiple paragraphs or sections . . . 79 Requesting spanned format. . . . . . . 112
Requesting undefined format . . . . . . 114
Chapter 6. Handling strings . . . . . . . . 81 Setting block sizes . . . . . . . . . . . 115
Joining data items (STRING) . . . . . . . . 81 Letting OS/390 determine block size . . . 115
Example: STRING statement. . . . . . . . 81 Setting block size explicitly . . . . . . . 115
STRING program results . . . . . . . . 82 Taking advantage of LBI. . . . . . . . 116
Splitting data items (UNSTRING) . . . . . . . 83 Block size and the DCB RECFM
Example: UNSTRING statement . . . . . . 83 subparameter . . . . . . . . . . . 116
UNSTRING program results . . . . . . . 84 Coding input and output statements for QSAM
Manipulating null-terminated strings . . . . . . 85 files . . . . . . . . . . . . . . . . 117
Example: null-terminated strings . . . . . . 86 Opening QSAM files . . . . . . . . . . 117
Referring to substrings of data items . . . . . . 86 Dynamically creating QSAM files with CBLQDA 118
Reference modifiers. . . . . . . . . . . 87 Adding records to QSAM files. . . . . . . 119
Example: arithmetic expressions as reference Updating QSAM files. . . . . . . . . . 119
modifiers . . . . . . . . . . . . . . 88 Writing QSAM files to a printer or spooled data
Example: intrinsic functions as reference set . . . . . . . . . . . . . . . . 119
modifiers . . . . . . . . . . . . . . 88 Controlling the page size . . . . . . . 119
Tallying and replacing data items (INSPECT) . . . 89 Controlling the vertical positioning of records 119
Examples: INSPECT statement . . . . . . . 89 Closing QSAM files . . . . . . . . . . 120
Converting double-byte character set (DBCS) data 90 Handling errors in QSAM files . . . . . . . 120
DBCS notation . . . . . . . . . . . . 90 Working with QSAM files under OS/390 . . . . 121
Defining and allocating QSAM files . . . . . 121

2 Programming Guide
Parameters for creating QSAM files . . . . 123 Closing VSAM files . . . . . . . . . . 150
Retrieving QSAM files . . . . . . . . . 123 Handling errors in VSAM files . . . . . . . 151
Parameters for retrieving QSAM files . . . 124 Protecting VSAM files with a password . . . . 151
Ensuring file attributes match your program 124 Example: password protection for a VSAM
Processing existing files . . . . . . . . 125 indexed file . . . . . . . . . . . . . 152
Defining variable-length (format-V) records 125 Working with VSAM data sets under OS/390 and
Defining format-U records . . . . . . . 125 OS/390 UNIX . . . . . . . . . . . . . 152
Defining fixed-length records . . . . . . 125 Defining VSAM files under OS/390 . . . . . 153
Processing new files . . . . . . . . . 125 Creating alternate indexes . . . . . . . . 154
Processing files dynamically created by Example: entries for alternate indexes . . . 155
COBOL . . . . . . . . . . . . . 126 Allocating VSAM files . . . . . . . . . 156
Using striped extended-format QSAM data sets 126 Sharing VSAM files through RLS . . . . . . 157
Allocation of buffers for QSAM files. . . . 127 Preventing update problems with VSAM files
Accessing HFS files using QSAM . . . . . . . 127 in RLS mode . . . . . . . . . . . 157
Restrictions and usage . . . . . . . . . 127 Restrictions when using RLS . . . . . . 158
Identifying QSAM files to CMS . . . . . . . 128 Handling errors in VSAM files in RLS mode 158
Using FILEDEF. . . . . . . . . . . . 128 Defining VSAM data sets under CMS . . . . . 158
Using LABELDEF . . . . . . . . . . . 129 Improving VSAM performance . . . . . . . 159
Labels for QSAM files . . . . . . . . . . 129
Using trailer and header labels . . . . . . 130 Chapter 10. Processing line-sequential files . . 163
Getting a user-label track . . . . . . . 130 Defining line-sequential files and records in
Handling user labels . . . . . . . . . 130 COBOL . . . . . . . . . . . . . . . 163
Format of standard labels . . . . . . . . 131 Allowable control characters . . . . . . . 164
Standard user labels . . . . . . . . . 131 Describing the structure of a line-sequential file 164
Processing QSAM ASCII files on tape . . . . . 132 Defining and allocating line-sequential files . . . 165
Requesting the ASCII alphabet . . . . . . 132 Coding input-output statements for line-sequential
Defining the record formats . . . . . . . 132 files . . . . . . . . . . . . . . . . 165
Defining the ddname . . . . . . . . . . 132 Opening line-sequential files . . . . . . . 166
Processing ASCII file labels . . . . . . . . . 133 Reading records from line-sequential files . . . 166
Adding records to line-sequential files . . . . 167
Chapter 9. Processing VSAM files. . . . . . 135 Closing line-sequential files. . . . . . . . 167
VSAM files . . . . . . . . . . . . . . 136 Handling errors in line-sequential files . . . . . 168
Defining VSAM file organization and records . . 137
Specifying sequential organization for VSAM Chapter 11. Sorting and merging files . . . . 169
files . . . . . . . . . . . . . . . 138 Sort and merge process . . . . . . . . . . 170
Specifying indexed organization for VSAM files 138 Describing the sort or merge file . . . . . . . 170
Alternate keys . . . . . . . . . . . 139 Describing the input to sorting or merging . . . 171
Alternate index . . . . . . . . . . . 139 Example: describing sort and input files for
Specifying relative organization for VSAM files 139 SORT . . . . . . . . . . . . . . . 171
Fixed-length and variable-length RRDS . . . 140 Coding the input procedure . . . . . . . . 172
Simulating variable-length RRDS . . . . . 140 Describing the output from sorting or merging . . 173
Specifying access modes for VSAM files . . . 141 Coding the output procedure . . . . . . . . 173
Example: using dynamic access with VSAM Coding considerations when using DFSORT on
files . . . . . . . . . . . . . . 141 OS/390 . . . . . . . . . . . . . . 174
Defining record lengths for VSAM files. . . . 141 Example: coding the output procedure when
Defining fixed-length records . . . . . . 142 using DFSORT . . . . . . . . . . . . 174
Defining variable-length records . . . . . 142 Restrictions on input and output procedures . . . 175
Coding input and output statements for VSAM Defining sort and merge data sets under OS/390 175
files . . . . . . . . . . . . . . . . 143 Defining sort and merge files under CMS . . . . 176
File position indicator . . . . . . . . . 144 Sorting variable-length records . . . . . . . 176
Opening a file (ESDS, KSDS, or RRDS) . . . . 145 Requesting the sort or merge . . . . . . . . 177
Opening an empty file . . . . . . . . 145 Setting sort or merge criteria . . . . . . . 177
Statements to load records into a VSAM file 147 Example: sorting with input and output
Opening a loaded file (a file with records) 147 procedures . . . . . . . . . . . . . 178
Reading records from a VSAM file . . . . . 147 Choosing alternate collating sequences . . . . 179
Updating records in a VSAM file . . . . . . 148 Sorting on windowed date fields . . . . . . 179
Adding records to a VSAM file . . . . . . 149 Preserving the original sequence of records with
Adding records sequentially . . . . . . 149 equal keys . . . . . . . . . . . . . 180
Adding records randomly or dynamically 149 Determining whether the sort or merge was
Replacing records in a VSAM file. . . . . . 149 successful . . . . . . . . . . . . . . 180
Deleting records from a VSAM file . . . . . 150 Stopping a sort or merge operation prematurely 181

Part 1. Coding your program 3


Improving sort performance with FASTSRT . . . 181
FASTSRT requirements for JCL (OS/390 only) 181
FASTSRT requirements for sort input and
output files . . . . . . . . . . . . . 181
QSAM requirements . . . . . . . . . 182
VSAM requirements . . . . . . . . . 183
Checking for sort errors with NOFASTSRT . . . 183
Controlling sort behavior . . . . . . . . . 184
Sort special registers . . . . . . . . . . 184
Changing DFSORT defaults with control
statements . . . . . . . . . . . . . 185
Default characteristics of the IGZSRTCD data
set . . . . . . . . . . . . . . . 185
Allocating storage for sort or merge operations 186
Using checkpoint/restart with DFSORT under
OS/390 . . . . . . . . . . . . . . . 186
Sorting under CICS . . . . . . . . . . . 187
CICS SORT application restrictions . . . . . 187

Chapter 12. Handling errors . . . . . . . . 189


Requesting dumps . . . . . . . . . . . 189
Creating a formatted dump. . . . . . . . 189
Creating a system dump . . . . . . . . 190
Handling errors in joining and splitting strings . . 190
Handling errors in arithmetic operations . . . . 191
Example: checking for division by zero . . . . 191
Handling errors in input and output operations 191
Using the end-of-file condition (AT END) . . . 193
Coding ERROR declaratives . . . . . . . 194
Using file status keys . . . . . . . . . . 194
Example: file status key . . . . . . . . . 195
Using VSAM return codes (VSAM files only) 196
Example: checking VSAM status codes . . . . 196
Coding INVALID KEY phrases . . . . . . 198
INVALID KEY and ERROR declaratives . . 198
NOT INVALID KEY . . . . . . . . . 198
Example: FILE STATUS and INVALID KEY . . 198
Handling errors when calling programs . . . . 199
Writing routines for handling errors . . . . . . 199

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 would 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 17
“Defining a class” on page 378
“Defining a class method” on page 381

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/18/1997.
Date-Compiled. 03/30/2000.

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 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


IBM IFY IGY IGZ ILB

© Copyright IBM Corp. 1991, 2000 5


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”
“Identifying a program as recursive”
“Marking a program as callable by containing programs”
“Setting a program to an initial state”

RELATED REFERENCES
Compiler limits (IBM COBOL Language Reference)
Conventions for program names (IBM 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 containing nested subprograms can be
recursive.

RELATED TASKS
“Making recursive calls” on page 472

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 469

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.

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 5648-A25 IBM COBOL for OS/390 & VM 2.2.0 Date 03/30/2000 Time 15:05:19 Page 1

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

RELATED REFERENCES
TITLE statement (IBM 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”

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

RELATED REFERENCES
Sections and paragraphs (IBM COBOL Language Reference)

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.

Chapter 1. Structuring your program 7


| QSAM file VSAM file Line-sequential file
| SELECT PRINTFILE 1
SELECT COMMUTER-FILE 1
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 8. Processing QSAM files” on page 107
“Chapter 9. Processing VSAM files” on page 135
“Chapter 10. Processing line-sequential files” on page 163
“Describing the computing environment” on page 7

Specifying the collating sequence


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:
v Nonnumeric comparisons explicitly specified in relation conditions and
condition-name conditions HIGH-VALUE and LOW-VALUE settings
v SEARCH ALL
v SORT and MERGE unless overridden by a COLLATINGSEQUENCE phrase on the SORT or
MERGE statement
“Example: specifying the collating sequence”

The sequence that you use can be based on one of these alphabets:
v EBCDIC (use NATIVE if the native character set is EBCDIC), the default if you
omit the ALPHABET clause
v ASCII (use STANDARD-1)
v ISO 7-bit code, International Reference Version (use STANDARD-2)
v An alteration of the EBCDIC sequence that you define in the SPECIAL-NAMES
paragraph
RELATED TASKS
“Choosing alternate collating sequences” on page 179

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

8 Programming Guide
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

Defining symbolic characters


Use the SYMBOLIC CHARACTER 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’. 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.

Chapter 1. Structuring your program 9


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 OS/390 JCL
v ALLOCATE command under TSO
v FILEDEF command for CMS
| v Environment variable for OS/390 or OS/390 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 FILEDEF command:
(1)
FILEDEF OUTFILE DISK MY OUTPUT A1 (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 FILEDEF command, or the
| environment variable name in the export command, corresponds to the
assignment-name in the ASSIGN clause:
v //OUTFILE DD DSNAME=OUT171 . . ., or
v FILEDEF OUTFILE DISK . . ., or
| v export OUTFILE= . . .

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


| the FILEDEF command, 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

10 Programming Guide
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,
| export command, or FILEDEF 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, the dsname or path-name in your export
| command, or fn, ft, and fm parameters in the FILEDEF 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, the environment
| variable in the export command, or the ddname in the FILEDEF command. You can
| change the actual file by using the DSNAME in the DD statement, the DSNAME or path
| name in the environment variable, or the fn, ft, and fm in the FILEDEF.

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 on OS/390”


“Example: using different input files on VM/CMS” on page 12

Example: using different input files on OS/390: 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

Under OS/390, assume the three possible input files are MASTER1, MASTER2, and
MASTER3. Then 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, . . .
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.

Chapter 1. Structuring your program 11


Example: using different input files on VM/CMS: 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

Under VM, assume the three possible input files on your A-disk are MASTER1
INPUT, MASTER2 INPUT, and MASTER3 INPUT. Then you need to issue one of the
following FILEDEF commands before running the program:
FILEDEF MASTERA DISK MASTER1 INPUT A1 . . .

FILEDEF MASTERA DISK MASTER2 INPUT A1 . . .

FILEDEF MASTERA DISK MASTER3 INPUT A1 . . .

Any reference in the program to MASTERA will therefore be a reference to the file
named in the FILEDEF command.

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 263

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 called and deallocated
when the program ends (LOCAL-STORAGE SECTION).
v Describe data from another program (LINKAGE SECTION).

The IBM COBOL for OS/390 & VM compiler limits the maximum size of DATA
DIVISION elements.

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

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

RELATED REFERENCES
Compiler limits (IBM 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 OS/390 data management
facilities (including a DD file job control statement) or with CMS file services
under VM.
| – 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.

Chapter 1. Structuring your program 13


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 469

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

RELATED REFERENCES
“FILE SECTION entries”

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 See reference below. 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.

14 Programming Guide
Clause To define Notes
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 or
COBOL for OS/390 & VM.
RECORDING MODE Physical record description QSAM only.

RELATED CONCEPTS
“Labels for QSAM files” on page 129

Comparison of WORKING-STORAGE and LOCAL-STORAGE


WORKING-STORAGE 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 on the PROGRAM-ID
In this case, WORKING-STORAGE data items are reinitialized each time 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.

LOCAL-STORAGE is allocated each time a program is called, and is deallocated when


the program returns by means of an EXIT PROGRAM, GOBACK, or STOP RUN. Note
however that for nested programs, LOCAL-STORAGE is allocated upon entry to, and
deallocated upon exit from, the containing outermost program. Any LOCAL-STORAGE
data items with VALUE clauses in a nested program are initialized to the appropriate
value each time the nested program is called.

RELATED CONCEPTS
“Example: storage sections”

RELATED TASKS
“Ending and reentering main programs or subprograms” on page 460

RELATED REFERENCES
Working-Storage section (IBM COBOL Language Reference)
Local-Storage section (IBM COBOL Language Reference)

Example: storage sections


The following is an example of a recursive program that uses both
WORKING-STORAGE and LOCAL-STORAGE.
CBL nocmpr2,pgmn(lu)
*********************************
* Recursive Program - Factorials
*********************************
IDENTIFICATION DIVISION.
Program-Id. factorial recursive.
ENVIRONMENT DIVISION.

Chapter 1. Structuring your program 15


DATA DIVISION.
Working-Storage Section.
01 numb pic 9(4) value 5.
01 fact pic 9(8) value 0.
Local-Storage Section.
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 following tables show the changing values of the data items in LOCAL-STORAGE
(L-S) and WORKING-STORAGE (W-S) 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).
Recursive
CALLs: Main 1 2 3 4 5
___________________________________
L-S num 5 4 3 2 1 0
___________________________________
W-S numb 5 4 3 2 1 0
fact 0 0 0 0 0 0
___________________________________
Recursive
GOBACKs: 5 4 3 2 1 Main
____________________________________
L-S num 0 1 2 3 4 5
____________________________________
W-S numb 0 0 0 0 0 0
fact 1 1 2 6 24 120
____________________________________

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

Using data from another program


How you share data depends on whether the programs are separately compiled or
are nested, as discussed in the topics referenced below.

RELATED TASKS
“Sharing data in separately compiled programs”
“Sharing data in nested programs” on page 17

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 475

16 Programming Guide
Sharing data in nested programs
Some applications consist of nested programs—programs that are contained in
other programs. Level-01 LINKAGE SECTION data items can include the GLOBAL
attribute. This attribute allows any nested program that includes the declarations
to access these LINKAGE SECTION 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 469

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 the 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 551

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:

Chapter 1. Structuring your program 17


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.
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.
Many structured programs do not have separate sentences. Each paragraph
can contain one sentence.
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 20
“Imperative statements”
“Conditional statements” on page 19
“Declaratives” on page 21

RELATED REFERENCES
PROCEDURE DIVISION structure (IBM 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” on page 19
“Scope terminators” on page 20

18 Programming Guide
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
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 18
“Scope terminators” on page 20

Chapter 1. Structuring your program 19


RELATED TASKS
“Selecting program actions” on page 69

RELATED REFERENCES
Conditional statements (IBM 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
“Compiler-directing statements” on page 304
Compiler-directing statements (IBM COBOL Language Reference)

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.

20 Programming Guide
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

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 18

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 311

RELATED REFERENCES
Declaratives (IBM COBOL Language Reference)

Chapter 1. Structuring your program 21


22 Programming Guide
Chapter 2. Using data
This section is intended to help the non-COBOL programmer 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 TASKS
Using variables, structures, literals, and constants
“Assigning values to data items” on page 25
“Using intrinsic functions (built-in functions)” on page 31
“Using tables (arrays) and pointers” on page 32

Using variables, structures, literals, and constants


Most high-level programming languages share the concept of data being
represented as variables, structures, literals, and constants. You place all data
definitions in the DATA DIVISION of your program. The data in a COBOL program
can be alphabetic, alphanumeric, or numeric.

Variables
A variable is a data item whose value can change during a program. The values
are restricted, however, to the data type that you define when you give the
variable a name and a length. For example, if a customer name is a variable 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.

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.

© Copyright IBM Corp. 1991, 2000 23


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 a nonnumeric 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 variable 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.

Figurative constants
A variable is a data item whose value can change during a program. 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
PICTURE clause (IBM COBOL Language Reference)
Literals (IBM COBOL Language Reference)
Figurative constants (IBM COBOL Language Reference)

24 Programming Guide
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.

What you want to do How to do it


To establish a constant Use the VALUE clause in the definition of the data
item.
Note: Not a language feature; for
optimized code only: the optimizer
recognizes an invariant VALUE item and
treats it as a constant.
Assign values to a data item or large Use one of these ways:
data area 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)
Assign the results of arithmetic Use the COMPUTE statement.
Replace characters or groups of Use the INSPECT statement.
characters in a data item
Receive values from a file Use the READ (or READ INTO) statement.
Receive values from a screen or a file Use the ACCEPT statement.
Display values on a screen or in a file Use the DISPLAY statement.

“Examples: initializing variables”

RELATED TASKS
“Initializing a structure (INITIALIZE)” on page 26
“Assigning values to variables or structures (MOVE)” on page 27
“Assigning arithmetic results (MOVE or COMPUTE)” on page 27
“Assigning input from a screen or file (ACCEPT)” on page 28
“Displaying values on a screen or in a file (DISPLAY)” on page 29

Examples: initializing variables


Initializing a variable to blanks or zeros:
INITIALIZE identifier-1

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


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

1. The symbol º represents a blank space.

Chapter 2. Using data 25


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


ABCD ºººººººº 1
ººººABCD1

1. The symbol º represents a blank space.

Initializing an alphanumeric variable:


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 variable:


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

NUM-INT-CMPT-3 NUMERIC-1 before NUMERIC-1 after


1234567 98765432 01234567

Initializing an edited alphanumeric variable:


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

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


M/ºº1
ABºC/DEF 1
M/ºº/ººº1

1. The symbol º represents a blank space.

RELATED TASKS
“Initializing a structure (INITIALIZE)”

Initializing a structure (INITIALIZE)


You can reset the values of all subordinate items in a group 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.

26 Programming Guide
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 º0000000000000000000000000001
2 R001390000480000000000000000 º0000000000000000000000000001
3 S001410000120000000000000000 º0000000000000000000000000001
4 C001383000000000425000000000 º0000000000000000000000000001
5 C002010000000000000100000000 º0000000000000000000000000001

1. The symbol º represents a blank space.

Assigning values to variables or structures (MOVE)


Use the MOVE statement to assign values to variables or structures.

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

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 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 variables containing 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.

Assigning arithmetic results (MOVE or COMPUTE)


When assigning a number to a variable, 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

Chapter 2. Using data 27


| 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.

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 variable. 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 via 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 variable with the statement:
Call 'CEESIABS' Using Arg, Feedback-code, Result.

As a result of this call, the variable Result is assigned to be the absolute value of
the value that is in the variable Arg; the variable Feedback-code contains the return
code indicating whether the service completed successfully. You have to define all
the variables 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 variables 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 269
Intrinsic functions (IBM 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 variable 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 variable.

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:

28 Programming Guide
v Change Console to device, where device is any valid system device (for example,
SYSIN). For example:
SYSIN is Names-Inpu

| 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 an OS/390 UNIX
| environment, stdin is the input source. If this DD is not defined and your
| program is not running in an OS/390 UNIX environment, the ACCEPT statement
| fails.
RELATED REFERENCES
SPECIAL-NAMES paragraph (IBM COBOL Language Reference)

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


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

If the content of the variable 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.

| Note that 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:


Display “Hello” UPON CONSOLE.

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. Note that 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 an OS/390 UNIX
| environment, a default DD of SYSOUT=* is allocated.

| If the OUTDD ddname is not allocated and you are running in an OS/390 UNIX
| environment, the _IGZ_SYSOUT environment variable is used as follows:
| Undefined or set to stdout
| Output is routed to stdout (file descriptor 1).

Chapter 2. Using data 29


| 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”

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 TASKS
“Setting and accessing environment variables” on page 362
“Coding COBOL programs to run under CICS” on page 347

RELATED REFERENCES
DISPLAY statement (IBM COBOL Language Reference)
“OUTDD” on page 286

30 Programming Guide
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 having defined attributes and a
predetermined value. In COBOL, these 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 variable.
For example, you could use Sqrt to invoke an intrinsic function and to name a
variable in your program:
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 either a character string
(alphanumeric data class) or a number (numeric data class) depending on the type
of function. You can include a substring specification (reference modifier) in a
function-identifier for alphanumeric 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.

Chapter 2. Using data 31


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 67
“Converting data items (intrinsic functions)” on page 94
“Evaluating data items (intrinsic functions)” on page 96

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:
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.
A procedure pointer is a pointer to an entry point of a procedure. Define the entry
address for a procedure with the USAGE IS PROCEDURE-POINTER clause in the DATA
DIVISION.

RELATED TASKS
“Defining a table (OCCURS)” on page 53

32 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 34
“Controlling how numeric data is stored” on page 35
“Checking for incompatible data (numeric class test)” on page 42
“Performing arithmetic” on page 43
“Using currency signs” on page 51

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”.

| When you compile using the default compiler option ARITH(COMPAT) (referred to as
| compatibility mode), you can code up to 18 digits in the PICTURE clause. 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, 2000 33


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 38

RELATED CONCEPTS
“Appendix A. Intermediate results and arithmetic precision” on page 559

RELATED TASKS
“Displaying numeric data”
“Controlling how numeric data is stored” on page 35
“Performing arithmetic” on page 43

RELATED REFERENCES
“Sign representation and processing” on page 41
“ARITH” on page 262
“NUMPROC” on page 283

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.)

34 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 38

RELATED TASKS
“Controlling how numeric data is stored”
“Defining numeric data” on page 33
“Performing arithmetic” on page 43

RELATED REFERENCES
MOVE statement (IBM 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 35


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 38

RELATED CONCEPTS
“Formats for numeric data”
“Data format conversions” on page 39
“Appendix A. Intermediate results and arithmetic precision” on page 559

RELATED TASKS
“Defining numeric data” on page 33
“Displaying numeric data” on page 34
“Performing arithmetic” on page 43

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

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.

36 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 on all platforms.

Binary format numbers occupy 2, 4, or 8 bytes of storage. If the picture clause


specifies that the 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


| COMP-5 is a USAGE type based on the X/OPEN COBOL specification.

| 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.

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)

Chapter 3. Working with numbers and arithmetic 37


| 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
| 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.

| 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 on all platforms.

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.

On OS/390 & VM, COMP-1 and COMP-2 data items are stored in System/390
hexadecimal format.

RELATED CONCEPTS
“Appendix A. Intermediate results and arithmetic precision” on page 559

RELATED REFERENCE
“TRUNC” on page 297

Examples: numeric data and internal representation


This table shows the 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

38 Programming Guide
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.

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.

Chapter 3. Working with numbers and arithmetic 39


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 41

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.

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.

40 Programming Guide
RELATED CONCEPTS
“Appendix A. Intermediate results and arithmetic precision” on page 559

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)).

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 COBOL for OS/390 & VM.

RELATED REFERENCES
“NUMPROC” on page 283

Chapter 3. Working with numbers and arithmetic 41


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.

NUMPROC(NOPFD) NUMPROC(PFD) NUMPROC(MIG)


Signed C, D, F C, D, +0 (positive zero) C, D, F
Unsigned F F F
Separate sign +, - +, -, +0 (positive zero) +, -

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.

NUMPROC(NOPFD) NUMPROC(PFD) NUMPROC(MIG)


Signed A to F C, D, +0 (positive zero) A to F
Unsigned F F F
Separate sign +, - +, -, +0 (positive zero) +, -

RELATED REFERENCES
“NUMPROC” on page 283

42 Programming Guide
Performing arithmetic
You can use any of several COBOL language features to perform arithmetic:
v COMPUTE, ADD, SUBTRACT, MULTIPLY, and DIVIDE statements
v Arithmetic expressions
v Intrinsic functions
v Language Environment callable services

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.

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:

Operator Meaning Order of evaluation


Unary + or - Algebraic sign First
** Exponentiation Second

Chapter 3. Working with numbers and arithmetic 43


Operator Meaning Order of evaluation
/ 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.

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

You can use intrinsic functions to perform several different arithmetic operations,
as outlined in the following table.

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 47

44 Programming Guide
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.

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.

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.

Corresponding Language Environment


Results same for
callable services
COBOL intrinsic intrinsic function
function Long precision Extended precision and callable 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
| RANDOM 1
CEERAN0 none No
| REM CEESDMOD CEESQMOD Yes
| SIN CEESDSIN CEESQSIN Yes
| SQRT CEESDSQT CEESQSQT Yes

Chapter 3. Working with numbers and arithmetic 45


| 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.

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.

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.

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

46 Programming Guide
RELATED CONCEPTS
“Fixed-point versus floating-point arithmetic” on page 49
“Appendix A. Intermediate results and arithmetic precision” on page 559

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

RELATED REFERENCES
“ARITH” on page 262

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
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.

Chapter 3. Working with numbers and arithmetic 47


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
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.
. . .

48 Programming Guide
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 your 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 your program (whether an arithmetic statement, an
intrinsic function, an expression, or some combination of these nested within each
other) determines whether the evaluation is in floating-point or fixed-point
arithmetic.

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.
A data item is floating point if you code it as a floating-point literal or if you
define it 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
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 will cause 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.

Chapter 3. Working with numbers and arithmetic 49


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.

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 568

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:

50 Programming Guide
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, DEM, 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:
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 hex 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.

Modified
Code page Applicable countries from Euro sign
IBM-1140 USA, Canada, Netherlands, Portugal, IBM-037 X’9F’
Australia, New Zealand
IBM-1141 Austria, Germany IBM-273 X’9F’
IBM-1142 Denmark, Norway IBM-277 X’5A’

Chapter 3. Working with numbers and arithmetic 51


Modified
Code page Applicable countries from Euro sign
IBM-1143 Finland, Sweden IBM-278 X’5A’
IBM-1144 Italy IBM-280 X’9F’
IBM-1145 Spain, Latin America - Spanish IBM-284 X’9F’
IBM-1146 UK IBM-285 X’9F’
IBM-1147 France IBM-297 X’9F’
IBM-1148 Belgium, Canada, Switzerland IBM-500 X’9F’
IBM-1149 Iceland IBM-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 French francs (as FRF):
IDENTIFICATION DIVISION.
PROGRAM-ID. EuroExample.
Environment Division.
Configuration Section.
Special-Names.
Currency Sign is “FRF ” with Picture Symbol “F”
Currency Sign is “EUR ” with Picture Symbol “U”.
Data Division.
WORKING-STORAGE Section.
01 Deposit-in-Euro Pic S9999V99 Value 8000.00.
01 Deposit-in-FRF Pic S99999V99.
01 Deposit-Report.
02 Report-in-Franc Pic -FFFFF9.99.
02 Report-in-Euro Pic -UUUUU9.99.
. . .
01 EUR-to-FRF-Conv-Rate Pic 9V99999 Value 6.78901.
. . .
PROCEDURE DIVISION.
Report-Deposit-in-FRF-and-EUR.
Move Deposit-in-Euro to Report-in-Euro
. . .
Compute Deposit-in-FRF Rounded
= Deposit-in-Euro * EUR-to-FRF-Conv-Rate
On Size Error
Perform Conversion-Error
Not On Size Error
Move Deposit-in-FRF 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 FRF”
Display “Euro value: ” Report-in-Euro.

The above example produces the following display output:


Deposit in Euro = EUR 8000.00
Deposit in Franc = FRF 54312.08

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

52 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 55
“Putting values into a table” on page 58
“Nesting tables” on page 54
“Creating variable-length tables (DEPENDING ON)” on page 62
“Searching a table” on page 65
“Processing table items using intrinsic functions” on page 67
“Handling tables efficiently” on page 539

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.

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

© Copyright IBM Corp. 1991, 2000 53


RELATED TASKS
“Creating variable-length tables (DEPENDING ON)” on page 62
“Nesting tables”
“Putting values into a table” on page 58
“Referring to an item in a table” on page 55
“Searching a table” on page 65

RELATED REFERENCES
OCCURS clause (IBM 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.

The following valid references to SAMPLE-TABLE-THREE use literal subscripts. The


spaces are required in the second example.

54 Programming Guide
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 53
“Referring to an item in a table”
“Putting values into a table” on page 58
“Creating variable-length tables (DEPENDING ON)” on page 62
“Searching a table” on page 65
“Processing table items using intrinsic functions” on page 67
“Handling tables efficiently” on page 539

RELATED REFERENCES
OCCURS clause (IBM 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 55


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
indenames.
v Use both subscripts and indexes together.
RELATED TASKS
“Indexing” on page 57
“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 57

56 Programming Guide
“Putting values into a table” on page 58
“Searching a table” on page 65
“Handling tables efficiently” on page 539

Indexing
You can create an index either with a particular table (using OCCURS INDEXED BY) or
separately (using USAGE IS INDEX).

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.
. . .
PERFORM VARYING INX-B FROM 1 BY 1 UNTIL INX-B > 10
DISPLAY TABLE-ITEM (INX-B)
. . .
END-PERFORM.

INX-B is used to traverse table TABLE-ITEM above, but could be used to traverse
other tables also.

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 56
“Putting values into a table” on page 58

Chapter 4. Handling tables 57


“Searching a table” on page 65
“Processing table items using intrinsic functions” on page 67
“Handling tables efficiently” on page 539

RELATED REFERENCES
INDEXED BY phrase (IBM COBOL Language Reference)
INDEX phrase (IBM 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 63
“Initializing a table (INITIALIZE)”
“Assigning values when you define a table (VALUE)”
“Assigning values to a variable-length table” on page 64

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 60


“Example: PERFORM and indexing” on page 61

RELATED REFERENCES
PERFORM with VARYING phrase (IBM 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 (IBM COBOL Language Reference)

Assigning values when you define a table (VALUE)


If your table contains stable values (such as days and months), set the specific
values your table holds when you define it.

58 Programming Guide
Define static values in WORKING-STORAGE 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 your table is small, you can use this technique:
1. Declare a record that contains the same items as are in your 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 was 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”.

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.

Chapter 4. Handling tables 59


RELATED REFERENCES
REDEFINES clause (IBM COBOL Language Reference)
PERFORM statement (IBM COBOL Language Reference)
INITIALIZE statement (IBM COBOL Language Reference)
OCCURS clause (IBM 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)
Move Error-Message (Sub) To Print-Message
Perform 260-Print-Report
End-If
End-Perform
. . .

60 Programming Guide
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 61


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 records lengths.
The length of the variable portions of a group item is the product of the object
of the DEPENDING ON option 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.

This behavior is different if the CMPR2 compiler option is in effect.

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:

62 Programming Guide
01 MAIN-AREA
03 REC-1.
05 FIELD-1 PIC 9.
05 FIELD-3 PIC 9.
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 569

RELATED TASKS
“Assigning values to a variable-length table” on page 64
“Loading a variable-length table”
COBOL for OS/390 & VM Compiler and Run-Time Migration Guide

RELATED REFERENCES
OCCURS DEPENDING ON clause (IBM COBOL Language Reference)
“CMPR2” on page 264

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.

Chapter 4. Handling tables 63


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 “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 option. Each subordinate structure that contains the DEPENDING ON
option is initialized using the maximum number of occurrences. If you define the
entire table with the DEPENDING ON option, 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).

This behavior is different if the CMPR2 compiler option is in effect.

RELATED TASKS
COBOL for OS/390 & VM Compiler and Run-Time Migration Guide

64 Programming Guide
RELATED REFERENCES
OCCURS DEPENDING ON clause (IBM COBOL Language Reference)
“CMPR2” on page 264

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 66

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” on page 66

RELATED REFERENCES
SEARCH statement (IBM COBOL Language Reference)

Chapter 4. Handling tables 65


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.
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” on page 67

RELATED REFERENCES
SEARCH statement (IBM COBOL Language Reference)

66 Programming Guide
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
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” on page 68

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

RELATED REFERENCES
Intrinsic functions (IBM COBOL Language Reference)

Chapter 4. Handling tables 67


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

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))

68 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 76

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 73

RELATED REFERENCES
IF statement (IBM COBOL Language Reference)
EVALUATE statement (IBM 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, 2000 69


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 72


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

RELATED TASKS
“Coding conditional expressions” on page 73
“Using the EVALUATE statement” on page 71
“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.

70 Programming Guide
RELATED TASKS
“Coding a choice of actions” on page 69

RELATED REFERENCES
Explicit scope terminators (IBM 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 69

Chapter 5. Selecting and repeating program actions 71


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.

72 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. COBOL lets
you specify any of these conditions:
v Numeric condition
v Nonnumeric condition
v Class of a field
v Switches and flags that you define
v Sign condition
v Status of UPSI switch
RELATED CONCEPTS
“Switches and flags” on page 74

RELATED TASKS
“Defining switches and flags” on page 74
“Resetting switches and flags” on page 75
“Checking for incompatible data (numeric class test)” on page 42

Chapter 5. Selecting and repeating program actions 73


RELATED REFERENCES
Rules for condition-name values (IBM COBOL Language Reference)
Switch-status condition (IBM COBOL Language Reference)
Sign condition (IBM COBOL Language Reference)
Comparing numeric and nonnumeric operands (IBM COBOL Language Reference)
Combined conditions (IBM COBOL Language Reference)
Class condition (IBM 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 75

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.

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” on page 75

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”:

74 Programming Guide
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”

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” on page 76

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.

Chapter 5. Selecting and repeating program actions 75


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.

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 77
“Coding a loop through a table” on page 78
“Executing multiple paragraphs or sections” on page 79

RELATED REFERENCES
PERFORM statement (IBM 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.

76 Programming Guide
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”

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 . . .

Chapter 5. Selecting and repeating program actions 77


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
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:

78 Programming Guide
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.

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

Chapter 5. Selecting and repeating program actions 79


80 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 83
“Manipulating null-terminated strings” on page 85
“Referring to substrings of data items” on page 86
“Tallying and replacing data items (INSPECT)” on page 89
“Converting double-byte character set (DBCS) data” on page 90
“Converting data items (intrinsic functions)” on page 94
“Evaluating data items (intrinsic functions)” on page 96

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 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)
“Example: STRING statement”

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

RELATED REFERENCES
STRING statement (IBM COBOL Language Reference)

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).

© Copyright IBM Corp. 1991, 2000 81


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 º indicates a
blank space):
J.B.ºSMITHººººº
444ºSPRINGºST.,ºCHICAGO,ºILL.ºººººº
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
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.

82 Programming Guide
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
CMPR2 consideration: The UNSTRING statement works differently when the CMPR2
compiler option is in effect. For VS COBOL II Release 2 compatibility and
migration details, see the references indicated below.

“Example: UNSTRING statement”

RELATED TASKS
“Handling errors in joining and splitting strings” on page 190
COBOL for OS/390 & VM Compiler and Run-Time Migration Guide

RELATED REFERENCES
“CMPR2” on page 264
UNSTRING statement (IBM 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:


* 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).

Chapter 6. Handling strings 83


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.

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.

84 Programming Guide
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:
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

Chapter 6. Handling strings 85


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
Nonnumeric literals (IBM 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.

Referring to substrings of data items


Refer to a substring of a character-string data item (including EBCDIC data items)
with reference modifiers. Intrinsic functions that return character-string values are
also considered alphanumeric data items, and 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, in parentheses immediately following the data item you
code two values separated by a colon:
v Ordinal position (from the left) of the character you want the substring to start
with
v Length of the desired substring

86 Programming Guide
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 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.

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
RELATED CONCEPTS
“Reference modifiers”

RELATED TASKS
“Referring to an item in a table” on page 55

RELATED REFERENCES
“SSRANGE” on page 294
Reference modification (IBM COBOL Language Reference)
Function definitions (IBM 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:

Chapter 6. Handling strings 87


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”

RELATED TASKS
“Referring to substrings of data items” on page 86

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:


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 variable 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

88 Programming Guide
RELATED REFERENCES
INTEGER-PART (IBM COBOL Language Reference)
INTEGER (IBM COBOL Language Reference)

Tallying and replacing data items (INSPECT)


Use the INSPECT statement to do the following:
v Fill selective portions of a data item with a value
v Replace portions of a data item with a corresponding portion of another data
item
v Count the number of times a specific character (zero, space, or asterisk, for
example) occurs in a data item
“Examples: INSPECT statement”

RELATED REFERENCES
INSPECT statement (IBM COBOL Language Reference)

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 following 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 preceding the first
instance of a quote (“) 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

Chapter 6. Handling strings 89


characters in the data item following the first instance of the character / but
preceding 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

Converting double-byte character set (DBCS) data


If you use byte-oriented nonnumeric operations (for example, STRING and
UNSTRING) on nonnumeric data items containing double-byte characters, results are