Calling Programs | System Limits and Programming Restrictions |
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 (and in some cases simpler) applications.
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.
In this COBOL system, a program can be recursive if it is not nested inside another program and if it has a Local-Storage Section. A program can call itself using either its program-ID or an entry point.
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.
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.
In this 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. 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.
If a person has no eldest child, the routine children
displays the person's name and does nothing more. Otherwise, children
starts with the person's eldest child and calls itself for each sibling in
turn.
In this example, the routine, identified by the entry point factorl
,
computes the factorial of a number that you enter.
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 a run-time system 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.
You can manipulate the contents of COBOL data items. Two features that enable this are the STRING verb and reference modification:
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 than using STRING, 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.
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.
Consider the following example intrinsic function:
compute x = function cos(y)
This intrinsic functions assigns the value of the function to a data
item. 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
.
For more information on intrinsic functions, see your Language Reference.
This example, intrins.cbl, shows you 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 MERANT 1991. All rights reserved. * 5* This demonstration program is provided for use by * 6* users of MERANT products and may be used, modified * 7* and distributed as part of your application provided * 8* that you properly acknowledge the copyright of MERANT * 9* in this 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 * 31* of 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 * 41* function syntax, try running INTRINS under * 42* Animator. * 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 * 79* function * 80******************************************************** 81 82 compute factor = function factorial(0) 83 84******************************************************** 85* Form 2 - Function is used as a data item in an * 86* EVALUATE statement * 87******************************************************** 88 89 evaluate function integer(6.5) 90 when 6 91 move tru to true-or-false 922 when other 93 move fals to true-or-false 94 end-evaluate 95 96******************************************************** 97* Form 3 - Function is used as a data item in an IF * 98* statement * 99******************************************************** 100 101 if function integer (function factorial(arg)) = 120 102 then move tru to true-or-false 103 else 104 move fals to true-or-false 105 end-if 106 107******************************************************** 108* Form 4 - Function uses an array element (fixed * 109* index) as an argument * 110******************************************************** 111 112 compute factor = function factorial(elem(4)) 113 114******************************************************** 115* Form 5 - Function uses an array element (variable * 116* index) as an argument * 117******************************************************** 118 119 move 4 to indx 120 compute factor = function factorial(elem(indx)) 121 122******************************************************** 123* Form 6 - Data item is assigned the value * 124* of a function * 125******************************************************** 126 127 compute factor = function factorial( 128 function factorial(3)) 129 130******************************************************** 131* Form 7 - Data item, assigned the value of the * 132* function, is used in a COMPUTE statement * 133******************************************************** 134 135 compute val = function factorial(3) + 5 136 137******************************************************** 138* Form 8 - Data item is assigned the value of the sum * 139* of two functions * 140******************************************************** 141 142 compute val = function factorial(3) + 143 function factorial(5) 144 145******************************************************** 146* Form 9 - Function is used in the UNTIL condition of * 147* a PERFORM ... UNTIL statement * 148******************************************************** 149 150 move 1 to indx 151 perform para-1 until function integer (function 152 factorial(indx)) = 120 153 stop run. 154 155 para-1. 156 compute indx = indx + 1.
Line 82:
compute factor = function factorial(0)
Data item is assigned the value of the intrinsic function
Lines 89-94:
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 101-105:
if function integer (function factorial(arg)) = 120 then move tru to true-or-false else move fals to true-or-false end-if
The intrinsic 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 112:
compute factor = function factorial(elem(4))
The intrinsic function uses an array element (fixed index) as an argument
Lines 119-120:
move 4 to indx compute factor = function factorial(elem(indx))
The intrinsic function uses an array element (variable index) as an argument
Lines 127-128:
compute factor = function factorial (function factorial(3))
Data item is assigned the value of a function of a function
Line 135:
compute val = function factorial(3) + 5
Data item, assigned the value of the intrinsic function, is used in a COMPUTE statement
Lines 142-143:
compute val = function factorial(3) + function factorial(5)
Data item is assigned the value of the sum of two intrinsic functions
Lines 150-156:
move 1 to indx perform para-1 until function integer (function factorial(indx)) = 120 stop run. para-1. compute indx = indx + 1.
The intrinsic function is used in the UNTIL condition of a PERFORM ... UNTIL statement
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.
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.
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 |
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:
For all the routines:
length
operand determines how many bytes are
operated on. 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:
For detailed information on the library routines for logical operations, see the chapter Library Routines.
Copyright © 2000 MERANT International Limited. All rights reserved.
This document and the proprietary marks and names
used herein are protected by international law.
Calling Programs | System Limits and Programming Restrictions |