Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I prevent internal table overflow in COBOL?

This is probably a rookie question, but I still have a hard time working out how to use tables in COBOL.

Currently I'm writing a simple module that can be called by other programs. My program has to search an internal table for data and if not found, add to it.

I have this table:

01 TB-1 OCCURS 10 INDEXED X1.
   03 CLIENT-NAME    PIC N(30).
   03 ORDER-NUMBER   PIC 9(06).

Of course I can increase the amount of OCCURS so the likelihood of table overflow decreases. However, when testing the module, I have to deal with the scenario that there's one more record to add that doesn't fit in the table.

What is the best way of dealing with this? I was thinking of preventing an ABEND by giving back an error message.

To do this, I thought I'd define a new field and using it as a counter. So basically, every time my module adds a record, it adds +1 to the counter as well. Kind of like this:

IF COUNTER < 10 
     PERFORM ADD-RECORD
ELSE DISPLAY 'INPUT HAS EXCEEDED MAX OF 10 OCCURRENCES'
     GOBACK 
END-IF
.

ADD-RECORD.
    MOVE INPUT-CLIENT-NAME  TO CLIENT-NAME(X1)  IN TB-1.
    MOVE INPUT-ORDER-NUMBER TO ORDER-NUMBER(X1) IN TB-1.
    ADD +1 TO COUNTER
    .

Is this a good way to do this? Do you have any other ideas? Thanks in advance for your help.

like image 374
Lena Avatar asked Jul 18 '16 09:07

Lena


2 Answers

The question misses the information what compiler you actually use, therefore you have to check which part of the answer works for you.

The best option is: no maximum (COBOL 2014 feature, not very likely that your compiler supports this)

01 TB-1 OCCURS DYNAMIC DEPENDING ON COUNTER
                     INDEXED X1.
   03 CLIENT-NAME    PIC N(30).
   03 ORDER-NUMBER   PIC 9(06).

As you already use a counter check if you use the INDEXED clause (for example for SEARCH), otherwise drop it and only use the counter.

In any case I personally prefer to use the counter for the bounds checking, even in your range (slightly less performant but safer as your program will abend if something is wrong):

    01 BOUND-ERR.
       03 FILLER         PIC X(26) VALUE 
          'INPUT HAS EXCEEDED MAX OF '.
       03 BOUND-MAX      PIC 9(03).
       03 FILLER         PIC X(11) VALUE 
          'OCCURENCES.'.
    01 TB-1-COUNT        PIC 9(03) VALUE 0.
   *> may not work on your compiler...
    01 TB-1-MAX          AS CONSTANT 10.
   *> ... then try the level 78 extension:
    78 TB-1-MAX          VALUE 10.       
   *> if this doesn't work, too, then use REPLACE for the actual bound:
    REPLACE TB-1-MAX BY 10.
    01 TB-1 OCCURS       1 TO TB-1-MAX DEPENDING ON TB-1-COUNT
                         INDEXED BY X1.
       03 CLIENT-NAME    PIC N(30).
       03 ORDER-NUMBER   PIC 9(06).


        IF TB-1-COUNT = TB-1-MAX
           MOVE TB-1-MAX TO BOUND-MAX
           DISPLAY BOUND-ERR
           MOVE 1 TO RETURN-CODE
           GOBACK 
        END-IF
        ADD +1 TO TB-1-COUNT
        SET X1 UP BY 1
        MOVE INPUT-CLIENT-NAME  TO CLIENT-NAME  (X1) IN TB-1.
        MOVE INPUT-ORDER-NUMBER TO ORDER-NUMBER (X1) IN TB-1.
like image 103
Simon Sobisch Avatar answered Nov 21 '22 22:11

Simon Sobisch


The best way to deal with this is subject to interpretation. Eventually you will hit a limit and be unable to add a new entry in the table.

My experience has been that most programmers pick an upper bound for the table size that is both reasonable and bigger than they expect to need. E.g. when they are told there will never be more than 100 entries they make the table 200 entries in size.

If you are using IBM Enterprise COBOL v5.2 or later, you can specify...

01 TB-1 OCCURS 1 TO UNBOUNDED 
   DEPENDING NB-ITEMS INDEXED X1.
   03 CLIENT-NAME    PIC N(30).
   03 ORDER-NUMBER   PIC 9(06).

77  NB-ITEMS PIC 9(009) COMP VALUE 10.

...and you are fine until you hit 15,151,516 entries. This presumes the size of one occurrence is 66 bytes. The limit for an UNBOUNDED table is 999,999,998 bytes; 999999998 / 66 = 15151515 (and change).

If you are using an earlier version of IBM Enterprise COBOL you can either pick a reasonable upper limit for your table size or you can venture into the land of dynamically allocating storage (via LE Callable Services), which is useful under certain circumstances but often is overkill.

like image 38
cschneid Avatar answered Nov 21 '22 22:11

cschneid