Joined: 20 Oct 2006 Posts: 1411 Topics: 26 Location: germany
Posted: Sat Jul 07, 2007 11:43 am Post subject:
you can't.
What you can do, is GETMAIN (or use whatever LE -Language Environment service is available on your OPSYS and acquire additional runtime memory) and assign a table definition to the new area, but a COBOL Table defined in working storage has only one size, the max occurs.
A COBOL Table defined with ODO (occurs depending on) will be assigned the size of the max occurs; though for purposes of Statements such a SEARCH, using the ODO will cause the Search to only look at the number of items declared by the value contained in the ODO object - the counter. _________________ Dick Brenholtz
American living in Varel, Germany
Joined: 20 Oct 2006 Posts: 1411 Topics: 26 Location: germany
Posted: Mon Jul 09, 2007 2:17 am Post subject:
As a follow-up to Blitz's excellent post:
Unlike C, VB, JAVA & REXX, where you can just keep on dynamically adding 'occurs', COBOL Tables are based on contiguous memory - it is required by the code to address each item.
In the C, VB & JAVA languages and REXX Scripts, the table items are not required to be in contiguous memory - the concept of contiguous memory does not belong to those languages - which is why you can, continuously, dynamically allocate 'occurs' during runtime.
In COBOL, once you have dynamically allocated additional memory (GETMAIN in CICS, LE memory acquisition in Batch), that memory is one (1) table definition. If you then acquire more memory, the second and subsequent memory allocations have to be addressed as separate tables. i.e. you can not 'extend' a COBOL Table with a second dynamic memory allocation. _________________ Dick Brenholtz
American living in Varel, Germany
Actually, this is possible to do, with caveats. I did something similar in CICS program via GETMAIN, and I'm sure could be done in batch using CEEGTST.
Here is what I did:
1) COBOL OCCURS has to be 1 and counld reside in the LINKAGE or WS
2) Compile ALWAYS with NOSSRANGE
3) Allocate Max memory by calculating number of bytes = <occurs element length> * <Max number of elements>
4) Assign address of newly allocated memory to array in linkage
5) Redefine the Pointer as follows:
05 LINK-ADDRSS USAGE IS POINTER.
05 LINK-ADDRSS-RE REDEFINES LINK-ADDRSS PIC S9(08) COMP.
5) Walk the array (up to <Max number of elements>) by increasing the address in LINK-ADDRSS-RE by simple addition of the <occurs element length>. Reset the address of COBOL array to point to LINK-ADDRSS
6) ALWAYS use index of 1 when referencing array element
7) Good idea to save your original address, for FREEMAIN (or CEEFRST) purposes
Joined: 02 Dec 2002 Posts: 151 Topics: 3 Location: Perth, Western Australia
Posted: Thu Jul 12, 2007 2:16 am Post subject:
dbzTHEdinosauer wrote:
In the C, VB & JAVA languages and REXX Scripts, the table items are not required to be in contiguous memory - the concept of contiguous memory does not belong to those languages - which is why you can, continuously, dynamically allocate 'occurs' during runtime.
.
In C an array is contiguous, same for Java. C++ and Java have vector containers, which are also contiguous. Almost all random access containers are contiguous, otherwise they cannot guarantee a constant time complexity, O(1). Of course, REXX compound variables are hash tables, so you're right there... _________________ Dave Crayford
Joined: 08 Aug 2007 Posts: 291 Topics: 2 Location: Chicago
Posted: Wed Aug 08, 2007 2:21 pm Post subject:
I'll go one step further on dz's excellent recommendation to aquire storage using LE service CEEGTST. I use CEEGTST in COBOL to create linked lists. I'd recommend using the linked list rather than bothering with tables and increasing displacements. It's fairly straightforward.
Code:
WORKING STORAGE SECTION.
01 IN-REC.
03 FLD1 PIC X(10).
03 FLD2 PIC X(02).
01 CEEGTST-PARM-AREA.
05 CEEGTST-HEAP-ID PIC S9(09) COMP VALUE +0.
05 CEEGTST-BYTES-QTY PIC S9(09) COMP.
05 CEEGTST-STORAGE-ADDR USAGE IS POINTER.
PROCEDURE DIVISION USING LS-ELEMENT.
.
.
.
*** CREATE LINKED LIST
READ IN-FLE INTO IN-REC
PERFORM GET-STORAGE
SET LINKED-LIST-ANCHOR TO CEEGTST-STORAGE-ADDR
PERFORM UNTIL <IN-FLE end of file>
SET ADDRESS OF LS-ELEMENT TO CEEGTST-STORAGE-ADDR
MOVE FLD1 TO LS-VAL1
MOVE FLD2 TO LS-VAL2
PERFORM GET-STORAGE
SET LS-NEXT-ITEM TO CEEGTST-STORAGE-ADDR
READ IN-FLE INTO IN-REC
END-PERFORM
SET LS-NEXT-ITEM TO NULL
*** RETRIEVE ELEMENTS FROM LINKED LIST
SET ADDRESS OF LS-ELEMENT TO LINKED-LIST-ANCHOR
PERFORM UNTIL LS-NEXT-ITEM = NULL
DISPLAY 'LS-VAL1: ' LS-VAL1
DISPLAY 'LS-VAL2: ' LS-VAL2
SET ADDRESS OF LS-ELEMENT TO LS-NEXT-ITEM
END-PERFORM
GET-STORAGE.
MOVE LENGTH OF LS-ELEMENT TO CEEGTST-BYTES-QTY
SET CEEGTST-STORAGE-ADDR TO NULL
CALL 'CEEGTST' USING CEEGTST-HEAP-ID
CEEGTST-BYTES-QTY
CEEGTST-STORAGE-ADDR
OMITTED
.
GET-STORAGE-EXIT. EXIT.
This is obviously a contrived example and the syntax is most likely flawed, but the overall idea is accurate. I used this on multiple occasions when the occurences varies widely from one run to the next. It can also be used when the size of the individual elements varies. To vary the length of the individual elements, just define a very large area in the linkage section, LS-VAL PIC X(2000), but only request the amount you need from CEEGTST. You'd need to store the length of each element too and only reference data within that length. COBOL will allow you to access the full length defined and as IBM likes to say, the results are unpredictable.
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum