tags:

views:

216

answers:

2

Say I have the following variable-length table defined in WORKING-STORAGE...

01  SOAP-RECORD.                                           
    05  SOAP-INPUT        PIC X(8)          VALUE SPACES.
    05  SOAP-STATUS       PIC 9             VALUE ZERO.                         
    05  SOAP-MESSAGE      PIC X(50)         VALUE SPACES.
    05  SOAP-ITEMS        OCCURS 0 TO 500 TIMES   
                          DEPENDING ON ITEM-COUNT
                          INDEXED BY ITEM-X.     
        10 SI-SUB-ITEMS   OCCURS 0 TO 100 TIMES
                          DEPENDING ON SUB-COUNT
                          INDEXED BY SUB-X.     
           15 SS-KEY      PIC X(8)          VALUE SPACES.
           15 SS-AMOUNT   PIC -9(7).99      VALUE ZEROS.
           15 SS-DESCR    PIC x(100)        VALUE SPACES.

When this program runs, will it initially allocate as much space as this table could possibly need, or is it more dynamic about allocating memory? I would guess that the DEPENDING ON clause would make it more dynamic in the sense that it would allocate more memory as the ITEM-COUNT variable is incremented. A co-worker tells me otherwise, but he is not 100% sure. So I would really like to know how this works in order to structure my program as efficiently as possible.

PS: Yes, I am writing a new COBOL program! It's actually a CICS web service. I don't think this language will ever die :(

+3  A: 

You don't mention which compiler you're using, but, at least up through the current, 2002, COBOL standard, the space allocated for an OCCURS...DEPENDING ON (ODO) data item is not required to be dynamic. (It's really only the number of occurrences, not the length, of the data item that varies.) Although your compiler vendor may've implemented an extension to the standard, I'm not aware of any vendor that has done so in this area.

The next, but not yet approved, revision of the standard includes support for dynamic-capacity tables with a new OCCURS DYNAMIC format.

Bruce Hobbs
Good Answer... Enough memory is allocated to accomodate the maximum array size. The DEPENDING ON variable only defines the currnent number of elements used. ODO's are useful when using SEARCH/SEARCH ALL on variable sized tables and some other COBOL features. A full discussion as to when/why to use ODO's would be lengthy. But - there is nothing "dynamic" about memory allocation here.
NealB
Thanks for the comment, NealB. Well I guess that `DEPENDING ON` is not a very useful phrase in COBOL. I am accepting this answer, thank you Bruce!
Josh Stodola
A: 

In the CICS world, OCCURS DEPENDING ON (ODO) can be used to create a table that is dynamically sized at run time. However, the way you are declaring SOAP-RECORD will allocate enough memory to hold a record of maximum size.

Try the following:

First, move the SOAP-RECORD into LINKAGE SECTION. Items declared in the linkage section do not have any memory allocated for them. At this point you only have a record layout. Leave the declaration of ITEM-COUNT and SUB-COUNT in WORKING-STORAGE.

Next, declare a pointer and a length in WORKING-STORAGE something like:

77 SOAP-PTR       USAGE POINTER.
77 SOAP-LENGTH    PIC S9(8) BINARY.

Finally in the PROCEDURE DIVISION: Set the size of the array dimensions to some real values; allocate the appropriate amount of memory and then connect the two. For example:

MOVE 200 TO ITEM-COUNT
MOVE 15 TO SUB-COUNT
MOVE LENGTH OF SOAP-RECORD TO SOAP-LENGTH
EXEC CICS GETMAIN
     BELOW
     USERDATAKEY
     SET(SOAP-PTR)
     FLENGTH(SOAP-LENGTH)
END-EXEC
SET ADDRESS OF SOAP-RECORD TO SOAP-PTR

This will allocate only enough memory to store a SOAP-RECORD with 200 SOAP-ITEMS each of which contain 15 SI-SUB-ITEMS.

Note that the LENGTH OF register gives you the size of SOAP-RECORD based on the ODO object values (ITEM-COUNT, SUB-COUNT) as opposed to the maximum number of OCCURS.

Very important... Don't forget to deallocate the memory when your done!

NealB
Please show how to deallocate
John Saunders
@NealB Wow, awesome idea! Never even thought about the linkage section. I might just give this a try, although I already ended up using a completely different solution using TS queues. Correct me if I am wrong, but to deallocate the memory I would simply call the `FREEMAIN`, passing the address of my pointer.
Josh Stodola
@Josh Stodola. Correct use FREEMAIN. BTW. You can do something similar in a non-CICS program using LE routines to allocate/deallocate memory.
NealB