Wednesday, February 01, 2006

Pointers in COBOL

In the MVS world, COBOL II introduced pointers to COBOL. However, few programs use pointers. For one thing, pointers are more characteristic of C, Pascal, and other languages; they are somewhat alien to the traditional COBOL culture. For another thing, pointers are most useful when you allocate memory dynamically -- another concept alien to the COBOL culture.
Still, pointers are useful, and deserve more attention from programmers. Since newer versions of COBOL provide a way to dynamically allocate memory (without resorting to Assembler), pointers may become more common in the COBOL world.
Warning: the following discussion is based on VS COBOL II. For other dialects the syntax may differ. For example:
• I have read that VAX COBOL does not support SET ADDRESS.
• I've looked briefly at Fujitsu COBOL. Its syntax is closer to that of C, and less cumbersome than COBOL II's syntax.
• AS/400 COBOL uses MOVE instead of SET to assign a value to a pointer.
How Do I Make a Pointer?
Declare a pointer as an elementary data item bearing the USAGE IS POINTER clause, with no PICTURE. E.g:
05 EXAMPLE-P USAGE IS POINTER.
EXAMPLE-P is a four-byte field which can store the address of any data item. Unless you're interfacing COBOL to Assembler or something, you really don't care what the pointer looks like internally. It's just a piece of magic which enables you to access the thing it's pointing to.
Where Does the Address Come From?
Sometimes it comes from another program as a parameter, or part of a parameter. Still, that program had to get it from somewhere. In COBOL, you can obtain an address by using the SET verb:
SET EXAMPLE-P TO ADDRESS OF LINKAGE-THING.
LINKAGE-THING is some data item in the LINKAGE SECTION. It can be a group item or an elementary item; it can be a 01-level or not; but it has to be in the LINKAGE SECTION.
How Can I Get the Address of Something in WORKING-STORAGE?
You have to cheat. Write a mindless subprogram that takes the address of one parameter and passes the address back, in the form of a pointer, in another parameter.
Why does the compiler make you go to so much trouble to do something so trivial? Who knows? That's just the way it is. And that's a pity, because pointers would be more useful if you could easily point them at WORKING-STORAGE.
So I've Got an Address. Now What?
You have a pointer EXAMPLE-P which points to an object of some known type. Set up an instance of such an object in the LINKAGE SECTION:
LINKAGE SECTION.

01 NAME-STRUCTURE.
05 FIRST-NAME PIC X(18).
05 LAST-NAME PIC X(26).
Now use the SET verb:
SET ADDRESS OF NAME-STRUCTURE TO EXAMPLE-P.
The variable whose address you are setting (NAME-STRUCTURE in this case) must be a 01-level or 77-level item in the LINKAGE SECTION.
Note that NAME-STRUCTURE was probably never passed as a parameter. It's just an empty shell until you attach it to a specific address by using the SET verb. This operation is sometimes called dereferencing the pointer.
Having done so, you can do whatever you like with NAME-STRUCTURE, FIRST-NAME, or LAST-NAME.
That's the essence. That's what pointers are good for. If you have a pointer to a thing, you can dereference the pointer and get the thing itself. That thing might contain pointers to other things, enabling you to build data structures of arbitrary complexity.
What Else Can I Do With a Pointer?
Pass or receive it as a parameter:
PROCEDURE DIVISION USING LINK-P.
...
CALL 'CX779J32' USING EXAMPLE-P.
Assign NULL to it, either with a VALUE clause or with the SET verb:
05 ANOTHER-P USAGE IS POINTER VALUE NULL.
...
SET ANOTHER-P TO NULL.
Assign it to another pointer, using the SET verb:
SET EXAMPLE-P TO ANOTHER-P.
Compare it for equality to NULL or another pointer:
IF EXAMPLE-P NOT = NULL
AND EXAMPLE-P NOT = ANOTHER-P
PERFORM 2730-SOMETHING.
It would not be meaningful to test for inequality. That is, it doesn't mean anything for EXAMPLE-P to be greater than ANOTHER-P, or less. Also, you can't perform arithmetic on pointers. For instance, you can't subtract 4 from EXAMPLE-P (unless you REDEFINE it as a numeric type, making a correct but non-portable assumption about the physical representation of a pointer).
What's NULL?
NULL is a special pointer value. A pointer equal to NULL is guaranteed not to point to anything. If you try to dereference a null pointer your program will abend.
When Should I Use Pointers?
Pointers are mainly useful for stitching together various data objects to form a data structure. Typically, data structures are built from dynamically allocated memory.
Pointers can sometimes simplify the interface to a subprogram, especially in an IMS program. One entry point, called once at the beginning of the main program, receives one or more PCBs and stores pointers to them in WORKING-STORAGE. Other entry points dereference the appropriate pointers whenever they need to call IMS. This approach avoids the need to pass PCBs all the way up and down the calling chain.
Recommendations
1. Use pointers sparingly in COBOL. Try to use a more conventional approach if it is not too cumbersome.
2. So far as possible, isolate your pointer operations in a subprogram. Write it once and debug it thoroughly. Maybe no one will ever have to look at it again.
3. When designing your pointer operations, use a more appropriate notation than COBOL. For example, draw boxes and arrows to represent your data structures. If you are familiar with C, use a C-like pseudocode. When you are satisfied that your design is correct, translate it mechanically into COBOL, concentrating on syntax rather than design.

0 Comments:

Post a Comment

<< Home