COBOL Programming Course 2 Advanced Topics
COBOL Programming Course 2 Advanced Topics
Advanced Topics
Version 2.3.0
1
Copyright
COBOL Programming Course is licensed under Creative Commons Attribution 4.0 International. To view a
copy of this license, visit https://creativecommons.org/licenses/by/4.0.
2
Contents
1 Resources 5
1.1 Professional manuals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2 Learn more about recent COBOL advancements . . . . . . . . . . . . . . . . . . . . . . . . . 5
3 Dynamic-Length Item 17
3.1 Dynamic-Length Elementary Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2 Dynamic-Length Group Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.3 DYNAMIC LENGTH Clause . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3
7 Multithreading and COBOL 30
7.1 Multithreading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
7.2 THREAD to support multithreading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
7.3 Transferring control to multithreaded programs . . . . . . . . . . . . . . . . . . . . . . . . . . 30
7.4 Ending multithreaded environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.5 Processing files with multithreading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.5.1 File-definition storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.5.2 Serializing file access with multithreading . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.6 Limitation of COBOL with multithreading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
9 COBOL Challenges 37
9.1 COBOL Challenge - Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
9.2 COBOL Challenge - The COVID-19 Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
9.2.1 Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
9.2.2 Advanced Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
9.2.3 Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
9.3 COBOL Challenge - The Unemployment Claims . . . . . . . . . . . . . . . . . . . . . . . . . 43
9.3.1 Our Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
9.3.2 Use Case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
9.3.3 Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
9.3.4 Craving more programming challenges? . . . . . . . . . . . . . . . . . . . . . . . . . . 47
9.4 Hacker News Rankings for Mainframe/COBOL Posts . . . . . . . . . . . . . . . . . . . . . . . 48
9.4.1 A Little Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
9.4.2 Our Goal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
9.4.3 The Plan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4
1 Resources
This section provides useful resources in the form of manuals and videos to assist in learning more about the
basics of COBOL.
5
2 Numerical Data Representation
In the first COBOL Programming Course, various types of data representation were discussed. This chapter
seeks to expand upon the binary and hexadecimal numbering systems as well as the various numeric
representations in COBOL.
• Numbering Systems
– Binary System
– Hexadecimal System
– EBCDIC Encoding
– COBOL Picture Clause
• Numeric Representations in COBOL
– Zoned Decimal Format
– Packed Decimal Format
– Binary Format
– Single Precision Floating Point
– Double Precision Floating Point
On the IBM Mainframe system, the two’s complement form is used for the representation of binary integers.
In this form, the leftmost bit is used to represent the sign of the number: 0 for positive and 1 for negative.
For a positive number, the two’s complement form is simply the binary form of the number with leading
zero(s). For a negative number, the two’s complement is obtained by writing out the positive value of the
number in binary, then complementing each bit and finally adding 1 to the result. Assuming one byte of
storage and b0b1b2b3b4b5b6b7 are the bits, let us look at some examples.
As we can see, the sign bit b0 is 0 for a positive integer and 1 for a negative integer. This bit will participate
in all arithmetic operations as though it represented the value (-b0 * 2k-1) for a k bit number. In the above
6
binary representation of -28:
The number of bits will clearly dictate the range of values that can be stored. With k bits, the maximum
positive value that can be stored correctly is 2k-1 - 1 and the minimum (negative) value will be -2k-1. The
number Zero is always represented with sign bit zero. With k=4:
7
A423 is the hexadecimal equivalent of the decimal value 42019:
Although data is encoded in binary on computers, it is rather cumbersome to work with binary. The
hexadecimal numerals provide a human friendly representation of the binary coded values. An understanding
of this system is invaluable to the COBOL programmer as he designs, develops and tests code. Often, hex
dumps of the data in memory are used to debug a program and understand what is going on. The conversion
between binary and hexadecimal system is easy as 24 = 16. Each hexadecimal digit represents 4 binary digits,
also known as a nibble, which is half a byte.
• To convert from hexadecimal to binary, replace each hexadecimal digit with its equivalent 4-bit binary
representation
• To convert from binary to hexadecimal, replace every four consecutive binary digits by their equivalent
hexadecimal digits, starting from the rightmost digit and adding zeros, on the left if necessary
8
The usual convention is to use X’ ‘ to denote a hexadecimal value, B’ ‘ to denote a binary value.
9
8-bit EBCDIC Encoding
For numerical representations, the last column is of particular interest here; the character representations of
numerical digits 0-9 in the EBCDIC encoding. C’5’ is encoded, for example, as X’F5’ and C’9’ as encoded as
X’F9’.
10
Since the number of decimal places is determined and fixed in place by the V, this representation is called
fixed point . Let us illustrate with an example to show how the V determines the value stored.
The zone portion is the ‘upper half byte’ and numeric portion is the ‘lower half byte’. This format is the
default numeric encoding in COBOL. The coding syntax of USAGE IS DISPLAY can also be used. Let us
look at a few valid zoned decimal declarations.
11
As discussed earlier, the first two declarations above are unsigned, indicated by the absence of a S. Such
numbers are ‘implied positive’. The next two declarations are explicitly signed by the symbol S and are
capable of representing positive and negative numbers. The sign is represented by the rightmost zone bits (in
the above example the F above the 5) and is determined as follows:
• F indicates the number is unsigned
• C indicates the number is positive
• D indicates the number is negative
It is clear some adjusting (or editing) needs to be done before printing a signed number. The V in the
declarations above has no storage allocated for it and will also need to be edited for printing purposes. To
illustrate the way it works, consider an input file with a number 12345 and the input PIC clause is 999V99.
This means that there is a decimal point assumed between 3 and 4. When the number is later aligned with
an edited field, say ‘999.99’, the result is printed as 123.45.
When we code arithmetic statements involving zoned decimal fields, under the covers, COBOL converts the
data to packed decimal and/or binary representations in order to do the math and the result is converted
back to zoned decimal, all seamlessly. This extra step and hence a loss in efficiency is the price to pay for the
easy readability that this format provides.
12
As we can observe, when the number is packed into a field that is larger than necessary to hold that number,
it is padded with zeroes on the left.
• Number 1 will be stored as X’1F’ in 1 byte
• Number +12 will be stored as X’012C’ in 2 bytes
• Number -123 will be stored as X’123D’ in 2 bytes
• Number 1234 (unsigned) will be stored as X’01234F’ in 3 bytes
• Number +12345 will be stored as X’12345C’ in 3 bytes
The COBOL syntax for this format is USAGE IS COMP-3 or just COMP-3.
As the packed decimal representation stores two digits in one byte, it is a variable length format. Also, as
we can see, the digits are stored in decimal notation, and each digit is binary coded. So, COMP-3 exactly
represents values with decimal places. A COMP-3 value can have up to 31 decimal digits. This format
is somewhat unique and native to mainframe computers such as the IBM z architecture. The zOS has
specialized hardware for packed decimal arithmetic and so the system can perform mathematical calculations
without having to convert the format. This is, by far, the most utilized numerical value representation in
COBOL programs. Storing information in this format may save a significant amount of storage space.
It is usually the best choice for arithmetic involving decimal points/fractions. After numerical processing, a
packed decimal field is (moved) unpacked into a zoned decimal format which can then be edited for printing
purposes.
13
2.2.3 Binary Format
On the IBM Mainframe systems, the other main arithmetic type besides the packed decimal is the binary
format which is built for efficiency in integer arithmetic operations. This encoding finds many uses in Legacy
applications. Many datasets are created with binary fields. Variable length records and table processing
in COBOL use this representation. The binary format is largely implementation dependent and has many
variations. On the zOS and IBM Mainframes, the twos complement encoding is used.
The COBOL clauses for this format are COMP, COMP-4, COMPUTATIONAL or BINARY which can be
used interchangeably. COMP-5 clause also falls in this category. Let us look at some valid declarations.
14
Those numbers are more than sufficient for most business applications! To give a quick comparison, a two
byte packed decimal field can range in value from -999 to +999 only. When faced with larger than capacity
values, COMP truncates to the decimal value of the PIC clause and COMP-5 truncates to the size of the
field.
Although very much suited for integer processing, the binary format is not a good choice for non-integer
arithmetic. Many banking and insurance applications rely on accuracy for their business processing logic and
packed decimal format is preferred in such cases. Let’s see why. In decimal systems, fractions are represented
in terms of negative powers of 10:
There is a possible loss of accuracy when converting a decimal fraction to a binary fraction as there is not a
one-to-one correspondence between the set of numbers expressible in a finite number of binary digits and the
set of numbers expressible in a finite number of decimal digits. Let’s take the example of the fraction 1/10.
In the decimal system:
So, we get different values when, for example, we multiply 1/10 by 10 in the decimal and in the binary
systems. In the decimal system, 10 X 0.1 = 1.0. In the binary system, we get
i.e. not quite 1.0 !! In scenarios involving a large number of calculations, this type of discrepancy may lead to
cumulative rounding errors that may not be acceptable in many business applications. The use of packed
decimal works very well in such cases.
15
2.2.4 COMP-1: Single Precision Floating Point
Due to the floating-point nature, a COMP-1 value can be very small and close to zero, or it can be very large
(about 10 to the power of 38). However, a COMP-1 value has limited precision. This means that even though
a COMP-1 value can be up to 10 to the power of 38, it can only maintain about seven significant decimal
digits. Any value that has more than seven significant digits are rounded. This means that a COMP-1 value
cannot exactly represent a bank balance like $1,234,567.89 because this value has nine significant digits.
Instead, the amount is rounded. The main application of COMP-1 is for scientific numerical value storage as
well as computation.
16
3 Dynamic-Length Item
So far during this course, we have only explored data items that have a fixed length. In other words, you need
to define the length you need for each data type. But in this section, we will explore a fairly new concept in
Enterprise COBOL - dynamic-length items.
Enterprise COBOL v6.3 supports dynamic-length items, which are items whose logical length might change
at runtime.
17
Let us observe a few things from the examples above. Firstly, we note that the LENGTH keyword is optional.
Next, we also have a LIMIT phrase that specifies the maximum length of the data item. If a sender’s length
is longer than the receiver’s LIMIT value, the data will be truncated on the right. This LIMIT value defaults
to 999999999 if not specified. Lastly, note that we use PIC X. To use dynamic-length clause, you can only
use PIC X or PIC U (which is for UTF-8 data item).
18
4 UTF-8 Data Type
With Enterprise COBOL v6.3, we also have a new USAGE, which is UTF-8. This is indicated by the picture
symbol ‘U’. Unlike NATIONAL or DBCS characters, the byte length of each UTF-8 character varies between
1 and 4 bytes. Enterprise COBOL treats a single UTF-8 character as equivalent to a single Unicode code
point.
In this case, we define a fixed character-length UTF-8 data item that holds 10 UTF-8 characters that occupy
between 10 (n) and 40 (4 * n) bytes. Since UTF-8 character’s byte length varies, 4 * n bytes are always
reserved for UTF-8 item. If there are unused bytes, those will be padded with the UTF-8 blank statement
(x’20’). When truncation is performed, it is done on a character boundary.
In this case, we define a fixed byte-length UTF-8 data item that holds 10 bytes of UTF-8 data, this translates
to up to 10 characters. When these are used to receive characters with byte length smaller than indicated,
the unused bytes are padded by the UTF-8 blank statement (x’20’).
With dynamic-length UTF-8 data item, there is no restriction on the number of bytes besides the one
indicated on the LIMIT phrase of the DYNAMIC LENGTH clause. Unlike the other two definitions, no
padding is involved with the dynamic-length UTF-8 data item. Truncation will only occur on the character
boundaries if it exceeds the specified limit.
Note that UTF-8 edited, numeric-edited, decimal and external float are not supported.
19
When we define basic UTF-8 literals, the character-data is converted from EBCDIC to UTF-8. If we have
double-byte EBCDIC characters, those must be delimited by shift-out and shift-in characters. The amount of
Unicode code points which we can represent here varies depending on the size of the UTF-8 characters, but a
maximum of 160 bytes (after conversion) is allowed before truncation.
In this case, the hexadecimal-digits are converted to bytes sequences which are used verbatim as the UTF-8
literal values. There is a minimum of 2 hexadecimal digits and a maximum of 320.
20
5 COBOL Application Programming Interface (API)
API is the acronym for Application Programming Interface. An API allows two applications to communicate.
We use API’s everyday from our phones, personal computers, using a credit card to make a payment at a
point of sale, etc.
Today’s digital infrastructure is instrumented and interconnected. It is the API’s that enable the “instrumented”
network to be “interconnected”. As a result, API has become a highly used acronym in the technology
arena. The phrase “API Economy” became strategic term since Forbes declared 2017 “The Year of the API
Economy”.
Business application solutions were architected decades ago using programming language API’s. Long before
API became a strategic technology category, mainframe application developers understood the acronym
as a way to enable a programming language to communicate with other software. The value of being a
programmer in any specific programming language increased by understanding and using API’s.
• Enterprise COBOL APIs
– z/OS Middleware
– COBOL API Communication with Middleware
– COBOL EXEC SQL
– COBOL Data Items
• SQL Capability within Enterprise COBOL
– Enterprise COBOL Application Programming and SQL Guide
– Db2 Data Base Administration (DBA) vs Application Programming
• Lab
– Using VSCode and Zowe Explorer
21
COBOL programmer. The COBOL programmer uses an API to accomplish a task within the logic and the
middleware expanded code follows through with accomplishing the task.
PROCEDURE DIVISION .
*------------------
LIST - ALL .
EXEC SQL OPEN CUR1 END - EXEC .
EXEC SQL FETCH CUR1 INTO : CUSTOMER - RECORD END - EXEC .
PERFORM PRINT - AND - GET1
UNTIL SQLCODE IS NOT EQUAL TO ZERO .
EXEC SQL CLOSE CUR1 END - EXEC .
22
Observe “:CUSTOMER-RECORD” in the EXEC SQL FETCH statement. A colon (:) precedes COBOL
program defined variables that are used in SQL statements so that Db2 can distinguish a variable name from
a column name. Example 3. shows the COBOL program data items describing the COBOL program variable
names.
*****************************************************
* STRUCTURE FOR CUSTOMER RECORD *
*****************************************************
01 CUSTOMER - RECORD .
02 ACCT - NO PIC X (8) .
02 ACCT - LIMIT PIC S9 (7) V99 COMP -3.
02 ACCT - BALANCE PIC S9 (7) V99 COMP -3.
02 ACCT - LASTN PIC X (20) .
02 ACCT - FIRSTN PIC X (15) .
02 ACCT - ADDR1 PIC X (25) .
02 ACCT - ADDR2 PIC X (20) .
02 ACCT - ADDR3 PIC X (15) .
02 ACCT - RSRVD PIC X (7) .
02 ACCT - COMMENT PIC X (50) .
Example 3. COBOL Data Item for storing variables where Db2 is the data source
23
manual number. Db2 V12 for z/OS SQL Reference is also necessary to advance programming API capability
(SC27-8859).
5.3 Lab
The lab contains data used in previous labs from “COBOL Programming Course #1 - Getting Started” where
the data source was sequential data set, then a VSAM data set. The lab provides JCL to create a personal
Db2 table in a DBA-created database name using a DBA-created storage group. The DBA-created storage
group directs the create tablespace and table to specific disk storage volumes.
The lab contains Enterprise COBOL source code with Db2 APIs along with the JCL to compile and execute
the COBOL programs.
24
6 COBOL Program Compilation
In the previous course, we briefly mentioned how a COBOL program is compiled. In this chapter, we will
deep dive into the Enterprise COBOL compiler and how you have interacted with it.
To restate what we have learned, the compiler will translate the COBOL program we wrote into language
that the system can process. It will also list errors in our source statements and provide information on how
to debug them. After compilation, we can review the results and correct any detected errors.
As part of the compilation, we need to define the necessary data sets and specify any compiler options
necessary for our program.
• Compilation via JCL
– Catalogued JCL Procedure
– Writing JCL to compile programs
• Specifying compiler options
– Specifying options in the PROCESS statement
– Specifying options in JCL
• Batch compilation
– Compiler options in a batch compilation
In the example above, the COBOL program we are trying to compile is sourced directly from within the JCL
file. If we store our source code in a data set, we can replace the SYSIN DD statement with the appropriate
parameters.
We can also override any compiler options which are not explicitly set by using an EXEC statement that
includes the required options. Take for example:
// STEPA EXEC IGYWC ,
// PARM . COBOL = ' LIST , MAP , RENT '
25
The content of the PARM statement defines the Enterprise COBOL compiler options we are setting for the
program that we wrote. We will discuss more details regarding compiler options in a later section.
Compile procedure (IGYWC)
The first of the supplied catalogued procedures is the single-step IGYWC. It is a procedure for compiling a
program, and it will produce an object module. The step which compiled the program is called COBOL. We
are required to supply the SYSIN DD statement for the step to indicate the location of the source program:
// COBOL . SYSIN DD * ( or appropriate parameters )
If we use copybooks in the program we are compiling, we must also supply a SYSLIB DD statement to
indicate the location of our copybooks:
// COBOL . SYSLIB DD DISP = SHR , DSN = Z99998 . COBLIB
26
// SYSUT10 DD UNIT = SYSALLDA , SPACE =( subparms )
// SYSUT11 DD UNIT = SYSALLDA , SPACE =( subparms )
// SYSUT12 DD UNIT = SYSALLDA , SPACE =( subparms )
// SYSUT13 DD UNIT = SYSALLDA , SPACE =( subparms )
// SYSUT14 DD UNIT = SYSALLDA , SPACE =( subparms )
// SYSUT15 DD UNIT = SYSALLDA , SPACE =( subparms )
// SYSMDECK DD UNIT = SYSALLDA , SPACE =( subparms )
// SYSPRINT DD SYSOUT = A (5)
// SYSLIN DD DSNAME = MYPROG , UNIT = SYSALLDA , (6)
// DISP =( MOD , PASS ) , SPACE =( subparms )
// SYSIN DD DSNAME = dsname , UNIT = device , (7)
VOLUME =( subparms ) , DISP = SHR
27
6.2.1 Specifying options in the PROCESS statement
Within a COBOL program, you can modify most compiler options in the PROCESS statements. We will
need to code the statements before the IDENTIFICATION DIVISION header and before any comment lines
or compiler-directing statements.
We can also use CBL as a synonym of PROCESS. One or more blanks will be needed to separate a PROCESS
or CBL statement from the first option in the list of options. The options themselves must be separated by a
comma or a blank, while no spaces should be inserted between individual options and their suboptions.
Furthermore, we can code more than one PROCESS or CBL statement. If we do so, they must follow one
another. Note that your organization can inhibit the use of PROCESS statements by fixing up certain
compiler settings. If the PROCESS or CBL statement contains an option that is not allowed, the COBOL
compiler will generate an error diagnostic.
Take a look at the following example:
PROCESS LIST , MAP .
*-----------------------
IDENTIFICATION DIVISION .
*-----------------------
PROGRAM - ID . CBL0001
AUTHOR . Otto B . Fun .
*--------------------
...
28
// jobname JOB acctno , name , MSGLEVEL =1
// stepname EXEC IGYWCL
// COBOL . SYSIN DD *
010100 IDENTIFICATION DIVISION .
010200 PROGRAM - ID PROG1 .
. . .
019000 END PROGRAM PROG1 .
020100 IDENTIFICATION DIVISION .
020200 PROGRAM - ID PROG2 .
. . .
029000 END PROGRAM PROG2 .
CBL NAME
030100 IDENTIFICATION DIVISION .
030200 PROGRAM - ID PROG3 .
. . .
039000 END PROGRAM PROG3 .
/*
// LKED . SYSLMOD DD DSN =&& GOSET
/*
// P2 EXEC PGM = PROG2
// STEPLIB DD DSN =&& GOSET , DISP =( SHR , PASS )
. . .
/*
// P3 EXEC PGM = PROG3
// STEPLIB DD DSN =&& GOSET , DISP =( SHR , PASS )
. . .
/*
//
In the JCL, PROG1 and PROG2 are link-edited together to form one program object with the name PROG2.
Despite the name, the entry point of this program object will default to the first program in the program
object, PROG1. On the other hand, PROG3 is link-edited by itself into a program object with the name
PROG3.
29
7 Multithreading and COBOL
We can run COBOL programs in multiple threads. To do so, we compile using the THREAD compiler option.
Note that COBOL does not directly support the management of the program threads. But we can run the
programs that we compile in a multithreaded application server. So, other programs can call the COBOL
program we wrote in a way that enables it to run in multiple threads.
Choosing LOCAL-STORAGE or WORKING-STORAGE
• Data items in the LOCAL-STORAGE SECTION are allocated for each instance of a program invocation.
So in this case, each copy of the program will have its copy of the LOCAL-STORAGE data.
• Data items in the WORKING-STORAGE SECTION are only allocated once for each program, so they
will be available in their last-used state to all programs invocation.
So, if we want to isolate data to an individual invocation, we need to define the data in the LOCAL-STORAGE
SECTION. If we decided to define them in the WORKING-STORAGE SECTION, we need to make sure
that the data will not be accessed simultaneously from multiple threads, or if we do, write the appropriate
serialization code for it.
7.1 Multithreading
Let us first understand how multithreading works.
The operating system and multithreaded applications handle execution flow within a process, which is the
course of events when the program runs. Programs within a process can share resources, and the processes
themselves can be manipulated.
Within a process, an application can initiate one or more threads, basically a stream of computer instruction
that controls it. A multithreaded process begins with one thread and can create more to perform tasks.
These threads can run concurrently.
In a multithreaded environment, a COBOL run unit is the portion of the process that includes threads that
have actively executing COBOL programs. The run unit will continue until no COBOL program is active in
any of the threads. Within the run unit, COBOL programs can call non-COBOL programs and vice versa.
Within a thread, control is transferred between separate COBOL and non-COBOL programs. Each separately
called program is a program invocation instance. Program invocation instances of a particular program can
exist in multiple threads within a given process.
30
7.4 Ending multithreaded environment
We can end a multithread program by using GOBACK, EXIT PROGRAM or STOP RUN.
GO BACK will return control to the caller of the program. If the caller is the first program in a thread, the
thread will be terminated. If the thread is the initial one in a process, the process will be terminated.
EXIT PROGRAM runs the same way as GO BACK, except from the main program where it has no effect.
STOP RUN will terminate the entire Language Environment process and return control to the caller of the
main program (which might be the operating system). All threads in the process will also be terminated.
31
With other usage patterns, you must ensure that two instances of the program are never simultaneously
active on different threads or that serialization logic is coded explicitly by using calls to POSIX services.
To avoid serialization problems, we can define the data items that are associated with the file in the
LOCAL-STORAGE SECTION.
32
8 Program tuning and simplification
In the previous chapters, we have seen how you could code COBOL applications. But now, let us explore
how to improve them.
When a program is comprehensible, we can assess its performance. However, if the opposite is true, it can
make your application difficult to understand and maintain, thus hindering optimization.
To improve performance, we should take note of the following things:
• The underlying algorithm of your business logic
• Data structure
Having a robust algorithm with the appropriate data structure is essential to improve performance.
We can also write programs that result in more efficient use of the available services. We can also use coding
techniques to improve our productivity.
If you are interested in learning more about performance tuning with COBOL, check out the Enterprise
COBOL for z/OS Performance Tuning Guide.
• Optimal programming style
– Using structured programming
– Factoring expressions
– Using symbolic constants
• Choosing efficient data types
– Efficient computational data types
– Consistent data types
– Efficient arithmetic expressions
– Efficient exponentiations
• Handling tables efficiently
• Choosing compiler features to enhance performance
33
PERFORM 010 - INITIALIZE
PERFORM UNTIL END - OF - FILE
READ FILE - DATA INTO WS - DATA
AT END
SET END - OF - FILE TO TRUE
NOT AT END
PERFORM 020 - UPDATE - TRANSACTION
END - READ
END - PERFORM
In the example above, we have two out-of-line PERFORM and one inline PERFORM. An inline PERFORM
is executed in the normal flow of a program, while an out-of-line PERFORM will branch to the named
paragraph.
It is also suggested to avoid the use of the following constructs:
• ALTER statements
• Explicit GO TO statements
• PERFORM procedures that involve irregular control flow
34
precision of eight or fewer digits. Anything above 18 digits will always be computed using decimal arithmetics,
and those in-between can use either form.
Therefore, to produce the most efficient code for a BINARY data item, we need to ensure that it has a sign
(indicated with an S in the PICTURE clause) and eight or fewer digits.
But for a data item that is larger than eight digits or is used with DISPLAY or NATIONAL data items,
we can use PACKED-DECIMAL. The code generated can be as fast as BINARY data items in some cases,
especially if the statement is complicated or involves rounding.
To produce the most efficient code for a PACKED-DECIMAL data item, we need to ensure it has a sign
(indicated with an S in the PICTURE clause), an odd number of digits, and 15 or fewer digits in the PICTURE
clause (since the instructions the compiler use are faster with 15 or fewer digits).
By using floating-point exponent, the compiler will use floating-point arithmetics to compute the exponentia-
tions.
35
• Avoid errors in reference by coding index and subscript checks into your program.
We can also improve the efficiency of tables by:
• Using binary data items for all subscripts
• Using binary data items for variable-length table items
• Using fixed-length data items whenever possible
• Organize tables according to the type of search method used
36
9 COBOL Challenges
As you have now handled some basic exercises, we have prepared a new section containing more advanced
exercises that test your ability to resolve bugs and other issues in COBOL programs. Each exercise will have
a short description and a goal to be accomplished.
Happy Coding!
• COBOL Challenge - Debugging
• COBOL Challenge - The COVID-19 Reports
• COBOL Challenge - The Unemployment Claims
• Hacker News Rankings for Mainframe/COBOL Posts
37
9.1 COBOL Challenge - Debugging
It is 2020 in Washington, D.C. John Doe runs a program which provides financial reports on US Presidents
and tallies the number of reports from the state of Virginia. Everything seems OK. (see below)
John is satisfied, as he can see that everything is working as it should be. He calls it a day and goes home.
The next day, when he comes back to the office, his colleague Mari tells him “I’ve made some changes to one
of your programs so that it also tallies the number of presidents who spent more than their allowed limit.
Check it out.”
He runs his usual reports and sees the following:
38
Clearly, Mari’s changes to the program that generates the reports have broken something.
Can you fix the code to get the correct result? The new source code is named CBL0106 and the JCL is
CBL0106J. In case you get stuck, the solution is in the file CBL0106C.
You can find them in the github repository for the COBOL course, in the subfolder /COBOL Programming
Course #2 - Advanced Topics/Challenges/Debugging.
39
9.2 COBOL Challenge - The COVID-19 Reports
Today, you are tasked to create a COVID-19 Summary Report of all the countries around the world, using
information from the COVID19API website.
9.2.1 Instructions
1. Extract the response from this API: https://api.covid19api.com/summary. You will receive a JSON file
that is similar to the image below:
2. Convert that file to CSV format. It should look like this. In my example, I only chose the “Countries”
part.
40
3. Using Zowe, upload the CSV file to the mainframe.
Hint: You can use the command zowe files ul ftds "file location" "dataset name" to upload the
CSV file to the mainframe.
4. Create a new member in your *.CBL data set to write your COBOL program.
Hint: You can create a member using Zowe Explorer or Zowe CLI.
5. Write a COBOL program that reads the uploaded CSV file and reformats it to display the contents like
this:
********************************************************************
DATE : 2020 -04 -22
TIME : T16 :54:5
COUNTRY : " Antigua and Barbuda "
COUNTRY CODE : " AG "
SLUG : " antigua - and - barbuda "
NEW CONFIRMED CASES : 00000
TOTAL CONFIRMED CASES : 00023
NEW DEATHS : 00000
TOTAL DEATHS : 00003
NEW RECOVERIES : 00004
TOTAL RECOVERIES : 00007
********************************************************************
41
9.2.2 Advanced Tasks
If you want a more challenging approach, try the optional tasks below:
• Reformat the data into a Report Form like this:
• Automate. Using NPM and Zowe CLI, run all these steps and create a “one click” COBOL build similar
to this:
9.2.3 Solution
To check the solution, refer to the blog post here.
Happy Coding!
Disclaimer: This challenge is also posted in Medium.com.
42
9.3 COBOL Challenge - The Unemployment Claims
Now let’s try a more advanced challenge! Your task is to create an end-to-end solution. Our end goal is to
build an application that will fire Zowe APIs to the mainframe and display the result in the application. This
is how the flow would look:
Of course, you do not have to complete the whole challenge if you do not want to. But it would be great if you
do
9.3.3 Instructions
1. Create a database. This can be done in various ways but the easiest one the I could think of is a VSAM
file. First, create a COBOL program that will consume your data. Then, using the RECORD-ID as
the key (which is more visible when reading the CSV file), create a KSDS VSAM file and store all the
information there.
What this means is that one record will have the RECORD-ID as the key and all the information from
The Monthly Unemployment Claims (Fields from Age, Ethnicity, Industry, Race and Gender) will be
added or connected to the RECORD-ID.
The flow would look like this:
43
2. Create a COBOL sub-routine. This program will allow other programs to read the data from the
VSAM file. This sub-routine should be able to perform the following tasks:
• accept requests to get information about a specific record ID.
• (Optional) accept requests to get information about all the records inside the database. What
does this mean? It means that instead of providing a record ID, I could provide an indicator that
I want to create a report of all the records inside the database.
The purpose of the COBOL sub-routine is to allow other COBOL programs or other application to
access the information inside the VSAM file.
3. Create a Main COBOL Program. This program will create a report based on the records inside the
newly created database. The process is as follows:
• The program calls the COBOL sub-routine passing the Record ID or, optionally, an indicator that
you want to print all records in the database.
• It receives the response from the sub-routine.
• It processes the response and generates a report. This report can be a formal report or just a
display in the SYSOUT. It’s up to you.
The flow should look like this:
44
4. Create your JCLs.
By this point, if you choose to do the exercise using COBOL programs only, you should be able to
read the data from your VSAM file, process it and generate a report. The generated report could be an
information of a specific record or multiple records.
5. (Optional) Create an application. It can be any type of application; a Mobile App, a Web App or an
Electron App. It is up to you. In this application you should be able to view a record by providing a
RECORD-ID. The flow would be similar to Step #3.
This is an example of a possible application design:
45
Hint: How can I accomplish this? By using the Zowe CLI NPM package, you can fire Zowe APIs that
submit your JCLs and get the results. From there, you can view the output and display it in your
application. This article can provide a good example.
Hint: What APIs am I going to use? You will use the Jobs Submit API and View Jobs Spool or View
Dataset API. For more information, please visit this site.
6. (Optional) Create a CI/CD process that will create a nightly build of your application. This article can
help explain that process.
Sample CI/CD Build using CircleCI:
46
9.3.4 Craving more programming challenges?
Add more functionality to your COBOL Sub-routine like:
• Insert a new record
• Update an existing record
• Delete an existing record
I hope that by taking this challenge, you will be able to learn something new!
Happy Coding!
Disclaimer: This challenge is also posted in Medium.com.
47
9.4 Hacker News Rankings for Mainframe/COBOL Posts
We will explore the popular Hacker News website for this challenge. Hacker News is an online community
started by Paul Graham for sharing “Anything that good hackers would find interesting. That includes more
than hacking and startups”.
48
2. Create your COBOL program in <userid>.CBL using VS Code with the Code4z extension installed
and enabled – This program will :
1. Read in each record in the input CSV file
2. Select only the records that have mention of the words Mainframe or COBOL (ignore case) in
the Title field
3. Calculate the ranking score for each record based on the number of votes it received and the time
it was posted (Ignore date as we assume all posts were created on the same date)
4. Write the record to an output file along with the ranking score
49
3. Copy/Modify/Create a JCL in <userid>.JCL for compiling/linking and running the program against
input/output datasets.
4. Submit the job (via Zowe Explorer or Zowe CLI), debug and test to create the output dataset.
5. Next add a new step in the JCL member to run the DFSORT utility on the output dataset from the
previous step. The sort should be done on the ranking score field, from highest to lowest. Use DFSORT
to also print headers for our front page. As this is a new utility not covered in the course, please check
out these links to explore this very powerful and versatile tool:
Getting started with DFSORT
Example with DFSORT
6. Run and debug until the front page looks ready! Which posts ranked among the highest? Here’s a look
at the generated report:
50
Hope you have fun working on this Challenge. Happy COBOL coding!
51