PreviousWriting Programs System Limits and Programming RestrictionsNext

Chapter 2: Advanced Language Features

COBOL is a very flexible language. It contains many features that make it easy for you to create successful applications. This chapter introduces some of the more advanced language features that are available with COBOL.

Applying these features to common programming problems enables you to write more efficient, more user-friendly (and in some cases simpler) applications.

Topics that are discussed include:

2.1 Writing Recursive Routines

A recursive routine is a routine that calls itself. Recursion is the most natural method of solving certain problems, such as:

Although you can write any recursive routine as a straight iterative routine, the use of a recursive routine can simplify the program's logic.

2.1.1 Recursion

This section shows you how you can create recursive programs with this COBOL system.

In this COBOL system, a program can be recursive provided it is not nested inside another program and it has a Local-Storage Section. A program can call itself via either its program-id or an entry point. The example below illustrates recursion in COBOL. It reads a table of a person's descendants, and displays the names of those who have no children.

Each call of a recursive routine is called an instance. Each instance needs a different set of the data items used by the routine; so this COBOL system enables you to have a Local-Storage Section. Every time a new instance of the routine starts, a new, initialized copy of this section is created in memory; this is deleted when the instance finishes. You get a run-time error message if you try to use recursion in a program that does not contain a Local-Storage Section.

Example - Recursion:

In the following example, the table in the item family-tree contains an entry for each of Fred Smith's descendants. Assume the data has been put in the table by an earlier program. The first entry is Fred Smith's own. Each entry contains, as well as the person's name, a data item called eldest-pointer containing the position in the table of the entry for that person's eldest child. Someone with no children has 99 in this item. Similarly each entry has a data item sibling-pointer pointing to the entry for the person's next younger sibling. Someone with no younger siblings has 99 in this item.

 identification division.
 program-id. family.
    . . .
 working-storage section.
 01  family-tree.
     03  individual    occurs 50.
         05  ind-name           pic x(30).
         05  eldest-pointer     pic 9(2).
         05  sibling-pointer    pic 9(2).

 local-storage section.
 01  tree-pointer      pic 9(2).

 linkage section.
 01  parent-pointer    pic 9(2).

 procedure division.
     move 1 to tree-pointer
     call "children" using tree-pointer
     stop run.
* If this person has no eldest child, routine "children"
* displays the person's name and does nothing more. Otherwise,
* this routine starts with the person's eldest child and calls
* itself for each sibling in turn.

 entry "children" using parent-pointer
     move eldest-pointer(parent-pointer) to tree-pointer
     if tree-pointer = 99
         display ind-name(parent-pointer)
     else
         perform until tree-pointer = 99
             call "children" using tree-pointer
             move sibling-pointer(tree-pointer)to tree-pointer
         end-perform
     end-if.

2.1.2 Reviewing a Recursive Routine

The following sample code illustrates some of the features of a recursive routine. This routine, identified by the entry point factorl, computes the factorial of a number that you enter.

Example - Illustration of a recursive routine:

The following program that illustrates a recursive routine.

 1 working-storage section.
 2 01 n             pic x(4) comp-x.
 3 01 factorial     pic x(4) comp-x.
 4 01 m             pic x(4) comp-x.
 5
 6 local-storage section.
 7
 8 procedure division.
 9     accept n
10     move 1 to factorial
11     call "factorl" using n
12     display "factorial of " n " is " factorial
13     stop run.
14
15 entry "factorl" using m.
16     if m < 1
17         move 1 to factorial
18     else
19         if m > 1
20             multiply m by factorial
21             subtract 1 from m
22             call "factorl" using m
23         end-if
24     end-if
25
26     exit program.

Line 6:

local-storage section

Since the recursive routine can be called several times, the local data from one call must be protected from another call to the same code. This protection is done using a Local-Storage Section. Each time a new instance of the routine starts, an initialized copy of this section is created in memory. If you try to use recursion in a program that does not contain a Local-Storage Section, you get an RTS error message.

Notice that this routine does not have any local storage data items, but it still requires the local storage declaration.

Line 15:

entry 'factorl' using m.

This is the entry point of the recursive routine factorl. A program can call itself via its Program-ID or an entry point.

Lines 19-23:

if m > 1
    multiply m by factorial
    subtract 1 from m
    call 'factorl' using m
end-if

This loop contains the recursive call.

Line 22:

call 'factorl' using m

The recursive call statement.

2.2 STRING Versus Reference Modification

You can manipulate data items in detail using COBOL. Two features that enable this are the STRING verb and reference modification:

In general, the use of STRING is easier to read and implement. However, it can be resource-intensive, particularly if used many times in a program. You can use STRING in programs that do not incur a lot of overhead for other reasons, such as significant file I/O.

Reference modification is more efficient, but can lead to code that is more difficult to read and maintain. It is a way to improve performance in programs that use STRING heavily and are running slowly or growing too large.

For example, the following two statements are equivalent. In both examples, street-address is 25 bytes long:

    string street-address delimited by size into print-rec
                          with pointer num-char
    move street-address to print-rec (num-char: 25)

For more information on the STRING statement and reference modification, see your Language Reference.

2.3 Coding an Intrinsic Function

An intrinsic function enables you to reference a data item whose value is determined at the time the data item is referenced during the execution of the statement.

As an example of an intrinsic function, consider the following statement:

    compute x = function cos(y)

The intrinsic function cos computes a numeric value that approximates the cosine of an angle (expressed in y radians) and stores that value in x.

This example shows one way of using intrinsic functions, that is assigning the value of the function to a data item. There are many more.

Example - Using Intrinsic Functions:

The following sample program, intrins.cbl, shows some of the ways you can use intrinsic functions in your programs.


Note: There are three types of intrinsic functions: integer, numeric and alpha. The FACTORIAL function used in the sample below is a numeric function. The coding technique shown might not apply for the other function types.


  1$set mf noosvs ans85
  2
  3*************************************************************
  4* Copyright Micro Focus Limited 1991. All Rights Reserved.  *
  5* This demonstration program is provided for use by users   *
  6* of Micro Focus products and may be used, modified and     *
  7* distributed as part of your application provided that you *
  8* properly acknowledge the copyright of Micro Focus in this *
  9* material.                                                 *
 10*************************************************************
 11
 12*************************************************************
 13*                                                           *
 14*                     INTRINS.CBL                           *
 15*                                                           *
 16*    This program demonstrates some of the ways you can     *
 17*    use Intrinsic Functions in your COBOL application.     *
 18*    This program uses the FACTORIAL Intrinsic Function     *
 19*    to illustrate the following capabilities:              *
 20*                                                           *
 21*    1) Data item is assigned the value of a function       *
 22*    2) Function is used as a data item in an EVALUATE      *
 23*           statement                                       *
 24*    3) Function is used as a data item in an IF            *
 25*           statement                                       *
 26*    4) Function uses an array element (fixed index) as     *
 27*           an argument                                     *
 28*    5) Function uses an array element (variable index)     *
 29*           as an argument                                  *
 30*    6) Data item is assigned the value of a function of    *
 31*           a function                                      *
 32*    7) Data item, assigned the value of the function,      *
 33*           is used in a COMPUTE statement                  *
 34*    8) Data item is assigned the value of the sum of       *
 35*           two functions                                   *
 36*    9) Function is used in the UNTIL condition of a        *
 37*           PERFORM ... UNTIL statement                     *
 38*                                                           *
 39*                                                           *
 40*    To familiarize yourself with the Intrinsic function    *
 41*    syntax, try running INTRINS under Animator.            *
 42*                                                           *
 43*    Compile the program using:                             *
 44*                                                           *
 45*           COBOL INTRINS ANIM;                             *
 46*                                                           *
 47*    then animate the program:                              *
 48*                                                           *
 49*           ANIMATE INTRINS                                 *
 50*                                                           *
 51*                                                           *
 52*    For more information see your Language Reference       *
 53*    and PC Programmer's Guide.                             *
 54*                                                           *
 55*************************************************************
 56 working-storage section.
 57 78 fals value 0.
 58 78 tru  value 1.
 59
 60 01 true-or-false               pic 9(1).
 61
 62 01 factor                      pic s9(10).
 63
 64 01 val                         pic s9(10).
 65
 66 01 indx                        pic 9(5) comp-x.
 67
 68 01 arg                         pic 9(2) comp-x  value 5.
 69
 70 01 arr                                         value "40537".
 71     03 elem   occurs 5 times   pic 9.
 72
 73 procedure division.
 74
 75 main-section.
 76
 77************************************************************
 78* Form 1 - Data item is assigned the value of the function *
 79************************************************************
 80
 81     compute factor = function factorial(0)
 82
 83************************************************************
 84* Form 2 - Function is used as a data item in an EVALUATE  *
 85*          statement                                       *
 86************************************************************
 87
 88     evaluate function integer(6.5)
 89      when 6
 90         move tru to true-or-false
 91      when other
 92         move fals to true-or-false
 93     end-evaluate
 94
 95************************************************************
 96* Form 3 - Function is used as a data item in an IF        *
 97*          statement                                       *
 98************************************************************
 99
100     if function integer (function factorial(arg)) = 120 then
101         move tru to true-or-false
102     else
103         move fals to true-or-false
104     end-if
105
106  ************************************************************
107  * Form 4 - Function uses an array element (fixed index) as *
108  *          an argument                                     *
109  ************************************************************
110
111     compute factor = function factorial(elem(4))
112
113  ************************************************************
114  * Form 5 - Function uses an array element (variable index) *
115  *          as an argument                                  *
116  ************************************************************
117
118       move 4 to indx
119       compute factor = function factorial(elem(indx))
120
121  ************************************************************
122  * Form 6 - Data item is assigned the value of a function   *
123  *          of a function                                   *
124  ************************************************************
125
126     compute factor = function factorial(
127                        function factorial(3))
128
129  ************************************************************
130  * Form 7 - Data item, assigned the value of the function,  *
131  *          is used in a COMPUTE statement                  *
132  ************************************************************
133
134     compute val = function factorial(3) + 5
135
136  ************************************************************
137  * Form 8 - Data item is assigned the value of the sum of   *
138  *          two functions                                   *
139  ************************************************************
140
141     compute val = function factorial(3) +
142                   function factorial(5)
143
144  ************************************************************
145  * Form 9 - Function is used in the UNTIL condition of a    *
146  *          PERFORM ... UNTIL statement                     *
147  ************************************************************
148
149     move 1 to indx
150     perform para-1 until function integer (function 
151           factorial(indx))  = 120
152     stop run.
153
154 para-1.
155     compute indx = indx + 1.

Line 81:

 compute factor = function factorial(0)

Data item is assigned the value of the function

Lines 88-93:

 evaluate function integer(6.5)
  when 6
     move tru to true-or-false
  when other
     move fals to true-or-false
 end-evaluate

Function is used as a data item in an EVALUATE statement.

Lines 100-104:

 if function integer (function factorial(arg)) = 120 then
     move tru to true-or-false
 else
     move fals to true-or-false
 end-if

Function is used as a data item in an IF statement

The result of a numeric function is in floating point format, so it cannot be expected to hold an exact integer value. In this example, the integer function is used to obtain an exact integer value for the IF statement.

Line 111:

 compute factor = function factorial(elem(4))

Function uses an array element (fixed index) as an argument

Lines 118-119:

 move 4 to indx
 compute factor = function factorial(elem(indx))

Function uses an array element (variable index) as an argument

Lines 126-127:

 compute factor = function factorial (function factorial(3))

Data item is assigned the value of a function of a function

Line 134:

 compute val = function factorial(3) + 5

Data item, assigned the value of the function, is used in a COMPUTE statement

Lines 141-142:

 compute val = function factorial(3) + function factorial(5)

Data item is assigned the value of the sum of two functions

Lines 149-155:

    move 1 to indx
    perform para-1 until function integer (function
         factorial(indx)) = 120
  stop run.

para-1.
    compute indx = indx + 1.

Function is used in the UNTIL condition of a PERFORM ... UNTIL statement


2.3.1 References for Intrinsic Functions

For more information on intrinsic functions, see your Language Reference.

2.4 Setting Environment Variables

X/Open specifies syntax providing the function-names ENVIRONMENT-NAME and ENVIRONMENT-VALUE. You can DISPLAY UPON ENVIRONMENT-NAME which contains an environment variable name and subsequently ACCEPT FROM or DISPLAY UPON ENVIRONMENT-VALUE which contains an environment variable value.

Specifying these function-names enables you to dynamically alter the environment variable settings at run-time.

Using the X/Open syntax you can read and update the environment space used by your application, thereby changing the logical file associated with a physical file. You then use COBOL I/O syntax to read and write to and from this file in the normal way.

Any environment variables set or changed during an application's run are valid only during that run, and will revert to the original values upon the application's termination. You can have up to a maximum of 64 Kilobytes (or the machine's free space, whichever is smaller) of written environment variables at any one time during the run of an application.

2.5 Using Logic (Boolean) Operators

While programming in a COBOL environment, you deal with data with characters, fields, records, or files. However, there are occasions when you must deal with individual data bits. For example, bit manipulation is an important feature in applications dealing with:

The run-time system has a set of COBOL system library routines that handle bit manipulation operations easily.

The following truth table illustrates the logical operations:

A 0 0 1 1
B 0 1 0 1

CBL_NOT (not A) 1 1 0 0
CBL_AND (A AND B) 0 0 0 0
CBL_OR (A OR B) 0 1 1 1
CBL_EQ (A EQ B) 1 0 0 1
CBL_XOR (A XOR B) 0 1 1 0
CBL_IMP (A IMP B) 1 1 0 1

To see how you use this table, assume you are comparing bits A and B, using the equivalence operation CBL_EQ. From the table you can see the resultant bit is set to 1 if both A and B are 0 or if both A and B are 1. Otherwise the resultant bit is set to 0.

2.5.1 Calling a Bit Manipulation Routine

The following data items are used in the sample syntax below:

Data item
Description
source The sending field; a data item of any format.
target The receiving field; a data item of any format.
length Gives the number of bytes of source and target to be used, starting from the leftmost byte

Except for the CBL_NOT routine, all the routines perform logical operations on the bits of two data items. They combine bits from the two data items and return the result in the second item according to the truth table above. The operation starts at the left-hand end of the items. The length operand determines how many bytes are operated on.

Remaining bytes at the right-hand end of the target item are unchanged.


Warning: If the length is longer than either data item, bytes immediately following the data items are used up to the length specified.


The syntax for the CBL_NOT routine is:

call "CBL_NOT" using target by value length

where:

CBL_NOT Does a logical NOT on the bits of a data item.

The syntax for the remaining bit manipulation routines is:

  call "log_oper" using source target by value length

where log_oper is one of:

CBL_AND Does a logical AND between the bits of two data items.
CBL_OR Does a logical OR between the bits of two data items.
CBL_EQ Does a logical EQuivalence operation between the bits of two data items.
CBL_XOR Does a logical eXclusive OR operation between the bits of two data items.
CBL_IMP Does a logical IMPlies operation on the bits of two data items.

For detailed information on the library routines for logical operations, see the chapter Library Routines.


Copyright © 1999 MERANT International Limited. All rights reserved.
This document and the proprietary marks and names used herein are protected by international law.
PreviousWriting Programs System Limits and Programming RestrictionsNext