Compaq COBOL
User Manual


Previous Contents Index

4.1.4 Storage Allocation for Tables

The compiler maps the table elements into memory, following mapping rules that depend on the use of COMP, COMP-1, COMP-2, POINTER, and INDEX data items in the table element, the presence or absence of the SYNCHRONIZED (SYNC) clause with those data items, and the -align flag (on the Tru64 UNIX operating system) or the /ALIGNMENT qualifier (on the OpenVMS Alpha operating system).

The Compaq COBOL compiler allocates storage for data items within records according to the rules of the Major-Minor Equivalence technique. This technique ensures that identically defined group items have the same structure, even when their subordinate items are aligned. Therefore, group moves always produce predictable results. For more information, refer to the description of record allocation in the Compaq COBOL Reference Manual.

Note

To determine exactly how much space your tables use, specify the -map flag (on Tru64 UNIX), or the /MAP qualifier (on OpenVMS Alpha). This gives you an offset map of both the Data Division and the Procedure Division.

Figure 4-6 shows how the table defined in Example 4-7 is mapped into memory.

Example 4-7 Sample Record Description Defining a Table

01 TABLE-A. 
    03 GROUP-G PIC X(5) OCCURS 5 TIMES. 

Figure 4-6 Memory Map for Sample Record Description Example


Alphanumeric data items require 1 byte of storage per character. Therefore, each occurrence of GROUP-G occupies 5 bytes. The first byte of the first element is automatically aligned at the left record boundary and the first 5 bytes occupy all of word 1 and part of 2. A memory longword is composed of 4 bytes. Succeeding occurrences of GROUP-G are assigned to the next 5 adjacent bytes so that TABLE-A is composed of five 5-byte elements for a total of 25 bytes. Each table element, after the first, is allowed to start in any byte of a word with no regard for word boundaries.

4.1.4.1 Using the SYNCHRONIZED Clause

By default, the Compaq COBOL compiler tries to allocate a data item at the next unassigned byte location. However, you can align some data items on a 2-, 4-, or 8-byte boundary by using the SYNCHRONIZED clause. The compiler may then have to skip one or more bytes before assigning a location to the next data item. The skipped bytes, called fill bytes, are gaps between one data item and the next.

The SYNCHRONIZED clause explicitly aligns COMP, COMP-1, COMP-2, POINTER, and INDEX data items on their natural boundaries: one-word COMP items on 2-byte boundaries, longword items on 4-byte boundaries, and quadword items on 8-byte boundaries. Thus the use of SYNC can have a significant effect on the amount of memory required to store tables containing COMP and COMP SYNC data items.

Note

The examples in this section assume compilation without the -align flag (on Tru64 UNIX systems) or the /ALIGNMENT qualifier (on OpenVMS Alpha systems).

Example 4-8 describes a table containing a COMP SYNC data item. Figure 4-7 illustrates how it is mapped into memory.

Example 4-8 Record Description Containing a COMP SYNC Item

01 A-TABLE. 
   03 GROUP-G OCCURS 4 TIMES. 
      05 ITEM1 PIC X. 
      05 ITEM2 PIC S9(5) COMP SYNC. 

Figure 4-7 Memory Map for Record Description Containing a COMP SYNC Item


Because a 5-digit COMP SYNC item requires one longword (or 4 bytes) of storage, ITEM2 must start on a longword boundary. This requires the addition of 3 fill bytes after ITEM1, and each GROUP-G occupies 8 bytes. In Example 4-8, A-TABLE requires 32 bytes to store four elements of 8 bytes each.

If, in the previous example, you define ITEM2 as a COMP data item of the same size without the SYNC clause, the storage required will be considerably less. Although ITEM2 will still require one longword of storage, it will be aligned on a byte boundary. No fill bytes will be needed between ITEM1 and ITEM2, and A-TABLE will require a total of 20 bytes.

If you now add a 3-byte alphanumeric item (ITEM3) to Example 4-8 and locate it between ITEM1 and ITEM2 (see Example 4-9), the new item occupies the space formerly occupied by the 3 fill bytes. This adds 3 data bytes without changing the table size, as Figure 4-8 illustrates.

Example 4-9 Adding an Item Without Changing the Table Size

01 A-TABLE. 
   03 GROUP-G OCCURS 4 TIMES. 
      05 ITEM1 PIC X. 
      05 ITEM3 PIC XXX. 
      05 ITEM2 PIC 9(5) COMP SYNC. 

Figure 4-8 Memory Map for Example on Adding an Item Without Changing the Table Size


If, however, you place ITEM3 after ITEM2, the additional 3 bytes add their own length plus another fill byte. The additional fill byte is added after the third ITEM3 character to ensure that all occurrences of the table element are mapped in an identical manner. Now, each element requires 12 bytes, and the complete table occupies 48 bytes. This is illustrated by Example 4-10 and Figure 4-9.

Example 4-10 How Adding 3 Bytes Adds 4 Bytes to the Element Length

01 A-TABLE. 
   03 GROUP-G OCCURS 4 TIMES. 
      05 ITEM1 PIC X. 
      05 ITEM2 PIC 9(5) COMP SYNC. 
      05 ITEM3 PIC XXX. 

Note that GROUP-G begins on a 4-byte boundary because of the way Compaq COBOL allocates memory.

Figure 4-9 Memory Map for Example on How Adding 3 Bytes Adds 4 Bytes to the Element Length


4.2 Initializing Values of Table Elements

You can initialize a table that contains only DISPLAY items to any desired value in either of the following ways:

Example 4-11 and Figure 4-10 provide an example and memory map of a table initialized using the VALUE clause.

Example 4-11 Initializing Tables with the VALUE Clause

01 A-TABLE VALUE IS "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC". 
    03 MONTH-GROUP PIC XXX USAGE DISPLAY 
               OCCURS 12 TIMES. 

Figure 4-10 Memory Map for Example on Initializing Tables with the VALUE Clause


If each entry in the table has the same value, you can initialize the table as shown in Example 4-12.

Example 4-12 Initializing a Table with the OCCURS Clause

01 A-TABLE. 
   03 TABLE-LEG OCCURS 5 TIMES. 
      05 FIRST-LEG   PIC X VALUE "A". 
      05 SECOND-LEG  PIC S9(9) COMP VALUE 5. 

In this example, there are five occurrences of each table element. Each element is initialized to the same value as follows:

Often a table is too long to initialize using a single literal, or it contains numeric, alphanumeric, COMP, COMP-1, COMP-2, or COMP SYNC items that cannot be initialized. In these situations, you can initialize individual items by redefining the group level that precedes the level containing the OCCURS clause. Consider the sample table descriptions illustrated in Example 4-13 and Example 4-14. Each fill byte between ITEM1 and ITEM2 in Example 4-13 is initialized to X. Figure 4-11 shows how this is mapped into memory.

Example 4-13 Initializing Mixed Usage Items

01 A-RECORD-ALT. 
   05 FILLER PIC XX VALUE "AX". 
   05 FILLER PIC S99 COMP VALUE 1. 
   05 FILLER PIC XX VALUE "BX". 
   05 FILLER PIC S99 COMP VALUE 2. 
   . 
   . 
   . 
01 A-RECORD REDEFINES A-RECORD-ALT. 
   03 A-GROUP OCCURS 26 TIMES. 
      05 ITEM1 PIC X. 
      05 ITEM2 PIC S99 COMP SYNC. 

Figure 4-11 Memory Map for Example on Initializing Mixed Usage Items


As shown in Example 4-14 and in Figure 4-12, each FILLER item initializes three 10-byte table elements.

Example 4-14 Initializing Alphanumeric Items

01 A-RECORD-ALT. 
    03 FILLER PIC X(30) VALUE IS 
       "AAAAAAAAAABBBBBBBBBBCCCCCCCCCC". 
    03 FILLER PIC X(30) VALUE IS 
       "DDDDDDDDDDEEEEEEEEEEFFFFFFFFFF". 
    . 
    . 
    . 
01 A-RECORD REDEFINES A-RECORD-ALT. 
    03 ITEM1 PIC X(10) OCCURS 26 TIMES. 

Figure 4-12 Memory Map for Example on Initializing Alphanumeric Items


When redefining or initializing table elements, allow space for any fill bytes that may be added due to synchronization. You do not have to initialize fill bytes, but you can do so. If you initialize fill bytes to an uncommon value, you can use them as a debugging aid in situations where a Procedure Division statement refers to the record level preceding the OCCURS clause, or to another record redefining that level.

You can also initialize tables at run time. To initialize tables at run time, use the INITIALIZE statement. This statement allows you to initialize all occurrences of a table element to the same value. For more information about the INITIALIZE statement, refer to the Compaq COBOL Reference Manual.

Sometimes the length and format of table items are such that they are best initialized using Procedure Division statements such as a MOVE statement to send a value to the table.

4.3 Accessing Table Elements

Once tables have been created using the OCCURS clause, the program must have a method of accessing the individual elements of those tables. Subscripting and indexing are the two methods Compaq COBOL provides for accessing individual table elements. To refer to a particular element within a table, follow the name of that element with a subscript or index enclosed in parentheses. The following sections describe how to identify and access table elements using subscripts and indexes.

4.3.1 Subscripting

A subscript can be an integer literal, an arithmetic expression, a data name, or a subscripted data name that has an integer value. The integer value represents the desired element of the table. An integer value of 3, for example, refers to the third element of a table.

4.3.2 Subscripting with Literals

A literal subscript is an integer value, enclosed in parentheses, that represents the desired table element. In Example 4-15, the literal subscript (2) in the MOVE instruction moves the contents of the second element of A-TABLE to I-RECORD.

Example 4-15 Using a Literal Subscript to Access a Table

Table Description:
 
      01 A-TABLE. 
         03 A-GROUP PIC X(5) 
            OCCURS 10 TIMES. 
 
Instruction:
 
         MOVE A-GROUP(2) TO I-RECORD. 

If the table is multidimensional, follow the data name of the desired data item with a list of subscripts, one for each OCCURS clause to which the item is subordinate. The first subscript in the list applies to the first OCCURS clause to which that item is subordinate. This is the most inclusive level, and is represented by A-GROUP in Example 4-16. The second subscript applies to the next most inclusive level and is represented by ITEM3 in the example. Finally, the third subscript applies to the least inclusive level, represented by ITEM5. (Note that Compaq COBOL can have 48 subscripts that follow the pattern in Example 4-15.)

In Example 4-16, the subscripts (2,11,3) in the MOVE statements move the third occurrence of ITEM5 in the eleventh repetition of ITEM3 in the second repetition of A-GROUP to I-FIELD5. ITEM5(1,1,1) refers to the first occurrence of ITEM5 in the table, and ITEM5(5,20,4) refers to the last occurrence of ITEM5.

Example 4-16 Subscripting a Multidimensional Table

Table Description:
 
      01 A-TABLE. 
         03 A-GROUP OCCURS 5 TIMES. 
            05 ITEM1           PIC X. 
            05 ITEM2           PIC 99 COMP OCCURS 20 TIMES. 
            05 ITEM3 OCCURS 20 TIMES. 
               07 ITEM4        PIC X. 
               07 ITEM5        PIC XX OCCURS 4 TIMES. 
      01 I-FIELD5              PIC XX. 
 
Procedural Instruction:
 
            MOVE ITEM5(2, 11, 3) TO I-FIELD5. 

Note

Because ITEM5 is not subordinate to ITEM2, an occurrence number for ITEM2 is not permitted in the subscript list (when referencing ITEM3, ITEM4, or ITEM5). The ninth occurrence of ITEM2 in the fifth occurrence of A-GROUP will be selected by ITEM2(5,9).

Table 4-1 shows the subscripting rules that apply to Example 4-16.

Table 4-1 Subscripting Rules for a Multidimensional Table
Name of Item Number of Subscripts
Required to Refer to
the Name Item
Size of Item in Bytes
(Each Occurrence)
A-TABLE NONE 1105
A-GROUP ONE 221
ITEM1 ONE 1
ITEM2 TWO 2
ITEM3 TWO 9
ITEM4 TWO 1
ITEM5 THREE 2

4.3.3 Subscripting with Data Names

You can also use data names to specify subscripts. To use a data name as a subscript, define it with COMP, COMP-1, COMP-2, COMP-3, or DISPLAY usage and with a numeric integer value. If the data name is signed, the sign must be positive at the time the data name is used as a subscript.

A data name that is a subscript can also be subscripted; for example, A(B(C)). Note that for efficiency your subscripts should be S9(5) to S9(9) COMP.

The sample subscripts and data names used in Table 4-2 refer to the table defined in Example 4-16.

Table 4-2 Subscripting with Data Names
Data Descriptions of Subscript Data Names Procedural Instructions
01 SUB1 PIC 99 USAGE DISPLAY. MOVE 2 TO SUB1.
01 SUB2 PIC S9(9) USAGE COMP. MOVE 11 TO SUB2.
01 SUB3 PIC S99. MOVE 3 TO SUB3.
  MOVE ITEM5(SUB1,SUB2,SUB3) TO I-FIELD5.

4.3.4 Subscripting with Indexes

The same rules apply for specifying indexes as for subscripts, except that the index must be named in the INDEXED BY phrase of the OCCURS clause.

You cannot access index items as normal data items; that is, you cannot use them, redefine them, or write them to a file. However, the SET statement can change their values, and relation tests can examine their values. The index integer you specify in the SET statement must be in the range of one to the integer value in the OCCURS clause. The sample MOVE statement shown in Example 4-17 moves the contents of the third element of A-GROUP to I-FIELD.

Example 4-17 Subscripting with Index Name Items

Table Description:
 
      01 A-TABLE. 
         03 A-GROUP OCCURS 5 TIMES 
            INDEXED BY IND-NAME. 
            05   ITEMC   PIC X  VALUE "C". 
            05   ITEMD   PIC X  VALUE "D". 
      01 I-FIELD     PIC X(5). 
 
Procedural Instructions:
 
      SET IND-NAME TO 3. 
      MOVE A-GROUP(IND-NAME) TO I-FIELD. 

Note

Compaq COBOL initializes the value of all indexes to 1. Initializing indexes is an extension to the ANSI COBOL standard. Users who write COBOL programs that must adhere to standard COBOL should not rely on this feature.

4.3.5 Relative Indexing

To perform relative indexing when referring to a table element, you follow the index name with a plus or minus sign and an integer literal. Although it is easy to use, relative indexing generates additional overhead each time a table element is referenced in this way. The run-time overhead for relative indexing of variable-length tables is significantly greater than that required for fixed-length tables. If any of the range checks reveals an out-of-range index value, program execution terminates, and an error message is issued. You can use the -check flag (on Tru64 UNIX systems) or the /CHECK qualifier (on OpenVMS Alpha systems) to check the range when you compile the program.

On Tru64 UNIX, see Chapter 1 or the cobol man page for more information about the -check flag. <>

On OpenVMS, invoke the online HELP facility for Compaq COBOL at the OpenVMS Alpha system prompt for more information about the /CHECK qualifier. <>

The following sample MOVE statement moves the fourth repetition of A-GROUP to I-FIELD:


SET IND-NAME TO 1. 
MOVE A-GROUP(IND-NAME + 3) TO I-FIELD. 

4.3.6 Index Data Items

Often a program requires that the value of an index be stored outside of that item. Compaq COBOL provides the index data item to fulfill this requirement.

Index data items are stored as longword COMP items and must be declared with a USAGE IS INDEX phrase in the item description. Index data items can be explicitly modified only with the SET statement.

4.3.7 Assigning Index Values Using the SET Statement

You can use the SET statement to assign values to indexes associated with tables to reference particular table elements. The following sections discuss the two relevant SET statement formats. (All six SET statement formats are shown in the Compaq COBOL Reference Manual.)

4.3.7.1 Assigning an Integer Index Value with a SET Statement

When you use the SET statement, the index is set to the value you specify. The most straightforward use of the SET statement is to set an index name to an integer literal value. This example assigns a value of 5 to IND-5:


SET IND-5 TO 5. 

You can also set an index name to an integer data item. For example:


SET INDEX-A TO COUNT-1. 

More than one index can be set with a single SET statement. For example:


SET TAB1-IND TAB2-IND TO 15. 

Table indexes specified in INDEXED BY phrases can be displayed by using the WITH CONVERSION option with the DISPLAY statement. Also, you can display, move, and manipulate the value of the table index with an index data item. You do this by setting an index data item to the present value of an index. You can, for example, set an index data item and then display its value as shown in the following example:


SET INDEX-ITEM TO TAB-IND. 
         . 
         . 
         . 
DISPLAY INDEX-ITEM WITH CONVERSION. 


Previous Next Contents Index