PreviousWriting Efficient Programs Advanced Language FeaturesNext

Chapter 2: Calling Programs

This chapter describes how to call programs. It provides information on writing subprograms and passing parameters between them.

2.1 Inter-program Communication (CALL)

The COBOL system enables you to design applications as separate programs at source level. Each program can then be called dynamically from the main application program without first having to be linked dynamically with the other programs. Figure 2-1 shows an example of an application divided up in this way.

Figure 2-1: Application Divided Using CALL

The main program A, which is permanently resident in memory, calls B, C, or H, which are programs within the same application. These programs call other specific functions as follows:

B calls D, E and F
C calls X, Y, Z, L and K
H calls K
K calls M, N and O.

Because the functions B, C and H are standalone they do not need to be permanently resident in memory together. You can call them as they are needed, using the same physical memory when they are called. The same applies to the lower functions at their level in the tree structure.

In the figure, you would have to plan the use of CALL and CANCEL operations so that a frequently called subprogram such as K would be kept in memory to avoid load time. On the other hand, because it is called by C or H, it cannot be initially called without C or H in memory; that is, the largest of C or H should call K initially so as to allow space. It is important also to avoid overflow of programs. At the level of X, Y and Z, the order in which they are loaded does not matter because they do not make calls at a lower level.

It is advantageous to leave called programs in memory if they open files, to avoid having to reopen them on every call. The EXIT statement leaves files open in memory. The CANCEL statement closes the files and releases the memory that the canceled program occupies, provided all other programs in the executable file have been cancelled or never called.

If you use a tree structure of called, independent programs as shown earlier, each program can call the next dynamically by using the technique shown in the following sample coding:

 working-storage section.
 01 next-prog      pic x(20) value spaces.
 01 current-prog     pic x(20) value "rstprg".

 procedure division.
     call current-prog using next-prog
     cancel current-prog
     if next-prog = spaces
         stop run
     move next-prog to current-prog
     move spaces to next-prog
     go to loop.

The programs to be run can then specify their successors as follows:

      . . .
      . . .
 01 next-prog pic x(20).
      . . .
      . . .
 procedure division using next-prog.
      . . .
      . . .
     move "follow" to next-prog.
     exit program.

In this way, each independent segment or subprogram cancels itself and changes the name in the CALL statement to call the next one with the USING phrase.

2.1.1 Call Requirements

The total number of programs which can be loaded in memory as the result of a call is not constant. The number depends on the amount of available memory in your computer and the size of the program being called.

Dynamically called programs have an advantage over programs that have been linked into a single executable file, in that dynamically called programs have their memory freed when they are cancelled while the latter do not. Public Symbols and Your Program-Id

If a program is called and the program is dynamically loaded, the filename is used to identify it. If the program is statically linked then the Program-Id paragraph can be used. See the section Calling COBOL Subprograms for more details.

You can avoid many "program not found" errors by always using the filename without extensions as the program-name in the Program-Id paragraph. This enables flexibility in constructing your executable programs with statically or dynamically called programs.

For details on the Program-ID paragraph, see your Language Reference.

2.2 Calling Subprograms

You can write subprograms or your main programs in the COBOL language or in some other language, such as C. You can mix these subprograms freely in an application. However, before you call a non-COBOL subprogram from a COBOL program, you must link it to either the dynamic loader run-time support module or to your statically or dynamically linked COBOL application.

2.2.1 Calling COBOL Subprograms

A COBOL subprogram can be linked, or it can also be dynamically loaded at run time.

A linked program is an executable object module, while a dynamically loadable module is a COBOL intermediate code file (.int file), COBOL generated code file (.gnt file), or a COBOL callable shared object.

A COBOL program can call a COBOL subprogram by using one of the following formats of the CALL statement:

CALL "literal" USING ...


CALL data-name USING ...

For any COBOL programs, the literal string or the contents of the alphanumeric data item must represent the Program-ID, the entry point name, or the basename of the source file (that is, the filename without any extension). The path and filename for a module can also be specified when referencing a COBOL program, but we do not recommend you do this, as unexpected results can occur where the referenced module exists in more than one file, or type of format, or if the application is ported to other environments. For statically linked modules, the native code generator converts calls with literal strings to subroutine calls which refer to external symbols. Server Express automatically creates a routine to define the symbol and to load the associated file if it is entered at run time.

Note: Programs that are called at link time must have names that the system assembler and linker can accept; that is, they must not contain characters other than 0-9, A-Z, a-z, underscore (_), or hyphen (-). You must correct any entry point names that use characters other than these so that they are acceptable to the system assembler and linker. Calling Linked Programs

Use a CALL literal statement to call a linked program directly. If the program is not found a run-time system error is displayed unless the dynamic loader is present, in which case it will attempt to find a dynamically loadable version of the program. Calling Dynamically Loadable Programs

Use either a CALL literal statement, or a CALL data-name statement, to call a dynamically loadable program, and make the dynamic loader run-time support module search for the called program.

You might need to load the dynamic loader using the Cob utility.See the chapter COBOL System Interface (Cob) in your Server Express User's Guide for more details of this directive.

The dynamic loader run-time support module follows this search order to find the named file:

  1. The entry points of all loaded programs

  2. The disk in order to find a suitable file from which the program could be loaded

If the dynamic loader run-time support module has to search for a file on disk and no path-name has been specified on the call, the search order followed is:

  1. The directory from which the calling program was loaded

  2. The directories specified by the COBDIR environment variable. You can set COBDIR to a value of the form:
    [:] path-name [:path-name] ...

    For example:

    set COBDIR=d:/cobol/lbr;d:/cobol/exedll

    If you include the optional colon (:) at the beginning of the string, the dynamic loader run-time support module assumes the current directory is the first one to be searched

If you specify a directory path on the call, the dynamic loader support module searches for the file only in the named directory.

If you specify a file extension, the dynamic loader run-time support module searches only for a file with a matching extension. However, we recommend that you do not include an explicit extension in the filenames you specify to the CALL statement. If you specify a file without an extension, the dynamic loader run-time support module adds the extension .so to the basename of the file, and searches the disk for the corresponding callable shared object file. If it cannot find the callable shared object the dynamic loader run-time support module adds the extension .int to the basename of the file, and searches the disk for the corresponding intermediate code file. If it cannot find the .int file, the dynamic loader run-time support module adds the extension .gnt to the basename of the file, and searches for the corresponding .gnt file.

The dynamic loader run-time support module always assumes that the first matching program name which it finds is the program you require to CALL.

If no matching program is found a run-time error occurs.

Note that if the first character of a filename which is to be dynamically loaded at run time is the dollar sign ($), the first element of the filename is checked for filename mapping. The first element of the filename consists of all the characters before the first slash character (/).

See your File Handling for details. For example, if the statement:


is found in the source program, the file A is loaded from the path as defined by the MYLIB environment variable at run time.

2.2.2 Calling Non-COBOL Subprograms

You can access non-COBOL subprograms using the standard COBOL CALL ... USING statement. The address of each USING BY REFERENCE or USING BY CONTENT parameter is passed to the argument in the non-COBOL subprogram which has the same ordinal position in the formal parameter declarations. You must thus ensure all formal parameter declarations are pointers.

Note that if you use the CALL...USING BY VALUE form of the CALL...USING statement, the USING parameter is not passed BY VALUE if it is larger than four bytes long. If it is larger than this, it can be passed BY REFERENCE, but no warning is output to inform you of this. If you specify a numeric literal with a CALL...USING BY VALUE statement, it is passed BY VALUE as though it were a four-byte COMP-5 item; that is, it appears in machine-order as a data item and not as a pointer to that data item. If you specify a data item with a CALL...USING BY VALUE statement it must be defined as COMP-5.

You might need to specify a particular calling convention when interfacing to non-COBOL programs - see the chapter The COBOL Interfacing Environment for more information.

The following example shows how C functions can be accessed from a COBOL program

Example - Accessing C functions from a COBOL program:
$set rtncode-size"4"

 working-storage section.
 01 str.
   03 str-text  pic x(10).
   03 filler   pic x value x"00". 

* Null terminate string for C function
 01 counter pic 9(8) comp-5 value zero.

 procedure division.
 call-c section.

   call "cfunc" using str, counter
   if return-code not = zero
* RETURN-CODE set from return () in C
         display "ERROR"
         display "OK"
     stop run.

cfunc  (st, c)
char  *st;
int   *c;

When you use the CALL statement from within a COBOL program to access a non-COBOL module as described above, you must ensure that the COBOL run environment is not accidentally damaged. This means you must ensure that:

The CANCEL statement has no effect when it references a non-COBOL program . RTS Errors 114 and 115

The Server Express system traps unexpected signals and returns run-time system errors:

114 Attempt to access item beyond bounds of memory
115 Unexpected signal

Where C and COBOL modules are linked, these error messages are usually due to an error in the C code which causes a hardware interrupt for such conditions as segmentation violation. If you do receive these run-time system errors, carefully check the C source routines using the system debugger, paying particular attention to the format and byte ordering of parameters passed between the COBOL and C modules.

2.3 Program Entry Points

COBOL programs can contain ENTRY statements. An ENTRY statement identifies a place where execution can begin as an alternative to the Procedure Division if a calling program so specifies.

COBOL fully supports entry points, but the dynamic call loader presents a potential problem. Because the run-time system typically defaults to looking for called programs dynamically, there is no way for the run-time system to locate a particular entry point embedded in a program on disk. When you execute a call statement like:

call "abc" using ...

the run-time system first looks for a program or entry point called abc in all of the programs and libraries that have already been loaded. If it does not find the program, the run-time system then looks for a file called abc.ext where .ext is an executable file formats. For details of executable file types see the section Executable File Types in the chapter Packaging Applications in your Server Express User's Guide.

If abc represents the name of an entry point contained in another program, the run-time system cannot locate the file on disk, and a "program not found" message is issued. The run-time system does not scan through every individual executable file on disk to locate an entry point.

Therefore, you must load the program containing the called entry point into the run-time system.

One technique that you can use to do this is to create a .lbr file that contains any programs containing entry points that need to be preloaded. You can create the .lbr file (library file), using the Library facility. Once the .lbr file is created, you can issue a call to the .lbr file.

Note: When you call an .lbr file, the run-time system does not load every program in the .lbr into the run-time system. Instead, the run-time system registers the existence of all programs and entry points contained in the called .lbr file, for future reference. Later when one of these programs contained in the .lbr is called, the run-time system notes that it is contained in the .lbr and loads it at that point.

Once a program that contains the entry points is loaded into the run-time system, all entry points contained in the program are identified to the run-time system and are available to be called by any program loaded later. This means that if you need to call entry points in a particular program from another program, you must ensure that the program is loaded first, so the run-time system can register these entry points.

2.4 Passing the Command Line

This section describes how you call a program and pass the command line to the main program as a parameter. The main program in a run unit is the first program within it; that is, the program which is called directly by the COBOL system.

As the maximum size, form and contents of the command line vary between operating systems, these issues need to be considered if you want to port your application between environments. For example, to ensure portability, a maximum command line size of 128 characters might be appropriate rather than the system limit. Similarly, only alphabetic and numeric characters with the equals sign (=) and space characters should be used for entering the command line for a program if you want to guarantee portability.

The command line can be accessed from:

2.5 Program Calling Conventions

The standard COBOL calling convention is:

call progname using ...


call "progname" using ...

where progname (without quotation marks) is a data item that contains a valid program-name, and "progname" (with quotation marks) is the actual name of a valid program.

2.5.1 Program Names

A program-name is a character string representing the program or subprogram to be called. In the run-time system, this name is treated as an implicit program-name; that is, there is no filename extension in the program-name.

This means the actual executable file being called might be in any of the following supported executable formats:

When progname.lbr is found, the run-time system opens the .lbr file and locates and loads an executable file with the same program-name, for example progname.gnt,, or progname (no extension) from the .lbr file.

An explicit program-name can be specified in the call statement as well:

call "progname.gnt" using ....

This forces the run-time system to look for the exact filename specified, in this case progname.gnt. If the exact program-name is not located a "program not found" error message is issued.

2.6 Program Management

Once started, the run-time system loads and manages all called subprograms. When the run-time system locates and loads a a called program, it assigns a unique run-time system identifier to the program. (This identifier is used internally in the run-time system.) The run-time system allocates memory (both real and virtual) for the program, and can swap portions of it out to disk as needed.

The run-time system records the pathname of a program as well. Once loaded into the run-time system, the run-time system uses the same copy of the program unless it is physically canceled. See the description of the l run-time switch in the chapter Descriptions of Run-time Switches in your Server Express User's Guide for details of how to specify that programs should be physically canceled.

2.7 Search Conventions for Called Programs

Whenever a COBOL program running under the run-time system issues a call to a subprogram, the run-time system goes through the following steps:

  1. Locate and open the program file.

  2. Load the program file into the run-time system.

  3. Close the program file.

As described above, the run-time system can search for multiple executable files, and can search for these program files in more than one directory.

Note: The search sequences described below apply to executable files (programs). It does not apply to other file types, for example data files and COBOL source files.

You do not need to be concerned about search conventions if you only have one executable version of your program on disk. This discussion only applies if you have multiple executable files available.

Whenever a COBOL program issues an explicit call to a subprogram, for example:

call "myprog.gnt" using ...

the run-time system searches for a file with the specified extension.

In this case, the run-time system searches for myprog.gnt. It does not search for other valid executable formats with the same program-name but different extensions.

When a program issues an implicit call, that is, a call to a program-name without specifying a file extension, the run-time system searches for the called program in the order listed below.

When a program issues a call like:

call "proga" using ...

the run-time system searches through the following sequence looking for proga:

2 proga.gnt
4 proga.lbr The run-time system opens this .lbr file and searches it for an executable name
5 proga No extension

If none of the above are found, the run-time system issues the message, "program not found".

You can change the order in which the run-time system searches for files by setting the I1 run-time switch. This causes the run-time system to search for files in the order :

3 proga.gnt
4. proga.lbr

This is useful for testing when you are typically compiling only to intermediate (.int) code.

When the run-time system finds and loads a program, it records the location (drive and path) where the program was first found. If the program issues a later call to another program, the run-time system does not look in the current directory for the new program being called. Instead, it defaults back to the same directory where the calling program was first found.

If the run-time system cannot find the called program in the same directory that the calling program is in, the run-time system begins its standard search sequence to try to locate the called program. This technique, known as inheritance, is the default behavior for the run-time system.

2.7.1 Searching Through Multiple Directories

It is also important to understand the way the run-time system searches for various executable files through the multiple directories that can be set in the COBDIR environment variable. For example, if your program issues a call to a program like:

call "myprog" using ...

the run-time system initially searches its active directory to see if myprog has already been loaded (and not subsequently canceled).

If it has been loaded, the run-time system passes control to myprog. It does not refresh the program's Data Division unless:

Note: You should be aware of the impact of inheritance on the run-time system search sequence. If you have the same program-name in more than one directory, you can access the wrong version.

2.8 CALL Prototypes

CALL prototypes are a relatively new feature of the COBOL language. Prototypes enable each CALL statement to be checked for correctness when the program is compiled. Prototypes can help you write multi-program applications that function as you expect. For information on the CALL syntax see your Language Reference.

When a COBOL program calls another program there is no validation of the type or the number of parameters provided in the CALL statement. If there is a mismatch between the parameter types provided on the CALL statement's USING clause and those of the called program's Linkage Section as referenced in the USING clause of the Procedure Division, then it is likely that either an application error or a run-time system error will occur.

For example, suppose you had the following program Mymain:

 program-id. MYMAIN.
 working-storage section.
  01  .
     05 myhandle         pic x(4).
     05 othervalue       pic x(4) value "6x3b".
 procedure division.
     call 'MYROUTINE'   using myhandle
     display "Othervalue is " othervalue.

and the subprogram Myroutine:

 program-id. MYROUTINE.
  linkage section.
  01  myhandle            usage pointer.
  procedure division using myhandle.
      set myhandle        to null
      exit program.

The program and its subprogram would work as you expected if compiled and run on a 32-bit system (where pointers are 4 bytes long), but would corrupt the value othervalue on a 64-bit system (where pointers are 8 bytes long):

You could be informed about this kind of problem when you compiled the programs, if the compiler had access to the data-types expected by the called program Myroutine when it compiled the program Mymain. CALL prototypes provide this information about called programs, and enable the compiler to check for semantic consistency between the parameters in both the calling program, and in the called subprogram.

A CALL prototype can be regarded as a cut-down version or model of the code of the called program. The prototype contains:

No code is required in the Procedure Division.

A CALL prototype is identified by the use of the IS EXTERNAL clause in the PROGRAM-ID paragraph.

If you were to code the calling program above (Mymain) as follows:

  program-id. MYROUTINE is EXTERNAL.      
  linkage section.                       
  01  myhandle            usage pointer.
  procedure division using myhandle.     
  end program MYROUTINE.
  * Prototypes are usually defined in a copyfile, but  *
  * here it is placed in-line                          *
  program-id. MYMAIN.
  working-storage section.
  01  .
      05 myhandle         pic x(4).
      05 othervalue       pic x(4) value "6x3b".
  procedure division.
      call 'MYROUTINE'   using myhandle
      display "Othervalue is " othervalue.
  end program MYMAIN.

when you compiled the program you would receive this warning message:

    14      call 'MYROUTINE'   using myhandle
**    Parameter is not consistent with that defined
      in prototype

Coding your programs in this way enables you to recognise programming errors without having to do run-time tests.

Ideally, all programs called from COBOL should be prototyped; however, this is not practical, as there is already a substantial body of COBOL code, and COBOL programmers are not used to type-checking programs. Even if the effort was expended to prototype all calls a program makes, it is likely that strict type-checking would cause a large number of Compiler errors on valid COBOL calls. For this reason, Server Express enables you to prototype called programs using a relaxed form of type-checking, and/or the keyword ANY with a USING statement.

For an extended example of using CALL prototypes, see the section CALL Prototypes in the chapter Examples in your Language Reference - Additional Topics.

2.8.1 The ANY Keyword

You can use the keyword ANY as a USING parameter. This enables any parameter to fill the corresponding parameter position on any CALL statement to the prototyped routine. For example, you can avoid producing the error shown in the example above by using this prototype:

 program-id. MYROUTINE is EXTERNAL.
 procedure division using any.
 end program MYROUTINE.

For information on the ANY keyword, see your Language Reference.

2.8.2 Relaxed Type-checking

By default, Server Express performs relaxed type-checking on BY VALUE binary data items. That is, even if binary data items have been defined with different sizes in the calling and called programs, the programs will compile with errors. If you specified a CALL statement that had a data-item defined as PIC X(2) COMP in its USING list, that date-item can correspond to a PIC X(n) COMP data-item in a CALL prototype, where n on a 32-bit system can be from 1 through 4, and on a 64-bit system can be 1 through 8.

For example, the following program will compile successfully:

 program-id. MYROUTINE is EXTERNAL.
 linkage section.
 01  callee-value             pic x(2) comp-5.
 procedure division using by value callee-value.
 end program MYROUTINE.

 program-id. MYMAIN.
 working-storage section.
 01  .
     05 caller-value          pic x(4) value 123.
 procedure division.
     call 'MYROUTINE' using by value caller-value
 end program MYMAIN.

In this example, if the actual value of caller-value was too big to fit a data-item defined as PIC X(2) COMP-5, binary truncation would occur. Such truncations might cause problems with the logic of your program, so you might want to specify that type-checking is more strict so that you can identify such potential problems. You can do this by setting the Compiler directive PROTOTYPE"STRICT". If you were to set PROTOTYPE"STRICT" when you compiled the above program, the Compiler would produce a message warning you of the type mismatch. For information on the PROTOTYPE directive, see the chapter Directives for Compiler in your Server Express User's Guide.

2.8.3 Using TYPEDEF

The COBOL TYPEDEF facility enables you to use common data description entries for USING parameters in calling and called programs and their prototypes. For detailed information on TYPEDEF, see your Language Reference.

As you saw in the section CALL Prototypes, when program prototypes are used an error occurs if there is a mismatch between data-types. To avoid this error, and to code the CALL statement and USING parameters correctly, the data description entry of the USING parameter in the CALL prototype must be duplicated in the program calling that prototype. If you were to do this manually, such duplication could lead to code maintenance problems, and perhaps lead to inconsistencies when you were creating programs.

To enable easy duplication of data description entries, the CALL prototype can use a TYPEDEF name to describe the parameter expected. For example:

 program-id. MYROUTINE is EXTERNAL.
 linkage section.
 01  callee-value-t           pic x(2) comp-5 is typedef.
 01  callee-value             usage callee-value-t.
 procedure division using callee-value.
 end program MYROUTINE.

 program-id. MYMAIN.
 working-storage section.
 01  .
     05 caller-value          usage callee-value-t.
 procedure division.
     call 'MYROUTINE' using caller-value
 end program MYMAIN.

TYPEDEF can be used not only for simple data description; it can represent an entire record structure. For example:

 program-id. MYROUTINE is EXTERNAL.
 linkage section.
 01  callee-value-t is typedef.
     05  callee-value-item-1  pic x(2) comp-5.
     05  callee-value-item-2  pic x(4).
 01  callee-value             usage callee-value-t.
 procedure division using callee-value.
 end program MYROUTINE.

 program-id. MYMAIN.
 working-storage section.
 01  .
     05 caller-value          usage callee-value-t.
 procedure division.
     move 123      to callee-value-item-1 of caller-value
     move 'abcdef' to callee-value-item-2 of caller-value
     call 'MYROUTINE' using caller-value
 end program MYMAIN.

All data-items defined as TYPEDEFs in a CALL prototype are available to any programs using that prototype.

2.8.4 COBOL System Library Routines

In Server Express 2.0 the COBOL system library routines are now prototyped, enabling you to ensure that data-items defined in your programs match those expected by the library routines. This is particularly useful if you are porting 32-bit applications to 64-bit systems, and want to ensure that data-items are typed correctly.

For information on the prototypes used by the library routines, see the chapter Library Routines.

Copyright © 2000 MERANT International Limited. All rights reserved.
This document and the proprietary marks and names used herein are protected by international law.

PreviousWriting Efficient Programs Advanced Language FeaturesNext