PreviousThe COBOL Interfacing Environment Header-to-COPY UtilityNext"

Chapter 10: Mixed-language Programming

This chapter describes mixed-language programming; that is, the calling of C programs from COBOL programs, and the calling of COBOL programs and entry points from C functions. All references to C can also be taken to mean any other high-level languages that conform to C calling conventions, such as C++ code contained within the C++ syntax extern "C" { ... }.

10.1 COBOL calling C functions

This section describes how to call and cancel C programs from COBOL programs.

10.1.1 Calling C functions

A COBOL program can call a C function using the COBOL CALL syntax. For example:

CALL "c_func" [USING ...] [RETURNING ...]

where c_func is a C function. Any USING items are passed as arguments to the C function. Any RETURNING item contains the return code from the C function.

Refer to the chapter The COBOL Interfacing Environment for more details.

10.1.2 Cancelling C Functions

Cancelling a COBOL program ensures that the next time it is referenced it is in its initial state. However, this does not necessarily happen when a non-COBOL program is cancelled. Any tidying-up of resources (memory, open files, and so on) used by the non-COBOL program depends on the language used to create the program and the various options associated with its compiler.

When you cancel a dynamically called COBOL or non-COBOL program, the memory used by the program is freed. Cancelling programs that are statically linked into the executable does not free any memory.

10.1.3 Demonstration Program

The demonstration program cobmain1.cbl can be found using Infomgr. For information on using Infomgr, see the chapter Infomgr in your Utilities Handbook. It demonstrates a COBOL program calling C and C++ functions.  It shows how to:

10.2 Calling COBOL from C

A C function can call a COBOL entry point in the same way as it would call another C function.  For example, the following demonstrates C code which calls a COBOL entry point, cobep, using two arguments:

cobep(arg1, arg2);

A C function can call, and cancel, COBOL programs and entry points using the cobcall(), cobcancel() and cobfunc() routines, as described in the sections below.

Before calling a COBOL program, you must call cobinit().

If your application has a C main() and the command line needs to be accessed from COBOL, then cobcommandline() must be called.

Before exiting a thread that has called a COBOL program, but which was not created via COBOL APIs, you must call cobthreadtidy(); also see the section Routines That Enable COBOL to be Called From C.

Before exiting an application that has called a COBOL program, you must call either cobtidy() or cobexit().

If the COBOL program and the C function that calls it are not contained in a callable shared object, nor linked together in a system executable file, then:

10.2.1 Demonstration Programs

The demonstration programs cmain1.c and cxxmain1.C can be found using Infomgr. They demonstrate a C and C++ program calling COBOL. They show how to:

10.3 Interfacing with High-level Languages on UNIX

Server Express provides a number of library routines that enable you to mix C and COBOL programs.

This section details the cob-prefix routines.  These routines should only be called from C; they should not be called from COBOL. The routines are available on all platforms, except where stated otherwise.

The routines are prototyped in C header files, as indicated below, and are located in the $COBDIR/include directory. The routines use portable data types which have a naming convention of cobtype_t. Definitions of these data types can be found in the cobtypes.h header file in $COBDIR/include.

10.3.1 Routines That Enable COBOL to be Called From C

This section describes the routines that enable COBOL programs to be called and cancelled from C functions.  See the sections Calling COBOL from C and Routines that Enable Use of a C main() for more details.

Before calling a COBOL program, you must call cobinit().

Before exiting a thread that has called a COBOL program, but was not created via the COBOL multi-threading syntax or library routines, you must call cobthreadtidy().

Before exiting an application that has called a COBOL program you must call either cobtidy() or cobexit()


cobcall

Call a COBOL program, subprogram or entry point from C.

Syntax:
#include "cobcall.h"

cobrtncode_t cobcall (const cobchar_t *name, int argc, cobchar_t **argv);
Parameters:
name A null-terminated string that specifies the name of the COBOL program to be called
argc The number of arguments passed in argv
argv Arguments to be passed to the COBOL program
Comments:

This routine is used to call the COBOL program of the specified name using the arguments passed in argv.  Parameters are passed BY REFERENCE.

The result of a cobcall() is a COBOL type call as defined in the ANSI '74 standard and behaves in the same way as if the COBOL entry point had been called from COBOL.

This is equivalent to calling a COBOL program directly from C code, using C syntax.

If the specified name is an entry point of an already loaded COBOL program, that program is called. Alternatively, if the specified name is a C function, then that is called. Otherwise, a program with a basename of the specified name is searched for on disk using the standard COBOL search order and paths.  See the program_search_order run-time tunable in the chapter Run-time Configuration in your Server Express User Guide for details on how to change the program search order.

If no program of the specified name can be found a run-time error is produced.  Also see the cobgetfuncaddr() function in this chapter.

If the COBOL entry point does not expect any arguments then argc should be 0 and argv should be NULL.

Equivalent COBOL syntax:
CALL "name" [USING ...] [RETURNING ...]
Example:

To call a COBOL entry point, cobep, with two string arguments from a C function use either:

cobchar_t *argv[2];
argv[0] = arg1;
argv[1] = arg2;
cobcall("cobep", 2, argv);

or:

cobep(arg1, arg2);

If cobep is not already loaded, it is searched for on disk using the standard COBOL search order and paths (that is, cobep.so, cobep.gnt, cobep.int).


cobcancel

Cancel a previously called COBOL program.

Syntax:
#include "cobcall.h"

void cobcancel (const cobchar_t *name);
Parameters:
name A null terminated string that specifies the name of the COBOL program to be cancelled.
Comments:

The COBOL program, specified by name, is cancelled and the data contained in the program is returned to its initial state as defined for the COBOL CANCEL verb (see your Language Reference for details).

If name is a C function then its data will be unchanged.  Also see Cancelling C Functions.

If name does not correspond to any loaded COBOL entry point or C function no action occurs and this routine returns as normal.

Equivalent COBOL syntax:
CANCEL "name"
Example:

To cancel the COBOL entry point cobep:

cobcancel("cobep");

cobfunc

Call a COBOL program, subprogram or entry point and then cancel it

Syntax:
#include "cobcall.h"

cobrtncode_t cobfunc (const cobchar_t *name, int argc, cobchar_t **argv);
Parameters:
name A null-terminated string that specifies the name of the COBOL program to be called
argc The number of arguments passed in argv
argv Arguments to be passed to the COBOL program
Comments:

This routine has the same effect as specifying cobcall() and then cobcancel().  That is, it calls the specified program and then cancels it, leaving the data contained in the program in its initial state

See the descriptions of cobcall() and cobcancel() for more details.

This routine, unlike cobcall(), causes the program to behave as if it had been called using C function rules rather than COBOL call rules. cobfunc() returns the return code of the called program.

Equivalent COBOL syntax:
CALL "name" [USING ...] [RETURNING ...]
CANCEL "name"
Example:

To call and then cancel a COBOL entry point cobep, which takes no arguments, use:

cobfunc("cobep", 0, NULL);

cobgetfuncaddr

Returns a function pointer to a COBOL program, subprogram or entry point.

Syntax:
#include "cobcall.h"

PFR cobgetfuncaddr(int type, const cobchar_t *name);
Parameters:
type Indicates what is returned if the specified program is not found.
Bit Setting Description
0 0
1
A NULL pointer is returned.
The address of an error routine is returned.
1-31 Reserved. Must be set to 0.
name A null terminated string that specifies the name of the COBOL program to be found.
Comments:

This routine returns a function pointer to the COBOL program of the specified name.

If the specified name is an entry point of an already loaded COBOL program, that program is called. Alternatively, if the specified name is a C function, then that is called. Otherwise, a program with a basename of the specified name is searched for on disk using the standard COBOL search order and paths.  See the program_search_order run-time tunable in the chapter Run-time Configuration in your Server Express User Guide for details on how to change the program search order.

If an error routine is returned (bit 0 set to 1) and it is subsequently called then a run-time error is produced, as for cobcall().

This routine only loads the program of the specified name; it does not call it. This enables programs to be preloaded.  This is especially useful if you want to call an entry point within the program, but not the main entry point of the program.

Equivalent COBOL syntax:
SET procedure-pointer TO ENTRY "name"
Example:

The following C code calls a COBOL program cobprog with two arguments, coping with any error condition:

PFR cobprog;

if ((cobprog = cobgetfuncaddr(0, "cobprog")) == NULL)
{
    /* Error case */
}
else
{
    /* Loaded */
    (*cobprog)(arg1, arg2);    /* Call it! */
}

10.3.2 Routines that Enable Use of a C main()

This section describes the routines required when the main entry point of an application is not a COBOL entry point; that is, when the main entry point is a C main() or provided by a third party.


cobexit

Closes down the global COBOL run environment.

Syntax:
#include "cobmain.h"

void cobexit (cobrtncode_t exitstatus);
Parameters:
exitstatus The exit status returned to the calling process (for example, the shell).
Comments:

This routine terminates a running application in the same way as if a COBOL STOP RUN statement had been executed, emptying buffers, closing files and freeing any data areas allocated by the COBOL system.

You must use the cobexit() function to exit from non-COBOL applications rather than just using the C library routine exit().

This routine will ultimately call exit() and so will not return.

The specified exit status is returned to the calling process (for example, the shell). Standard UNIX practice is to use an exit status of 0 on success.

The COBOL run-time system returns values of -1 (255) and -2 (254) if it exits due to an error or signal. See the chapter Handling Protection Violations for details.

Equivalent COBOL syntax:
STOP RUN
Example:

To exit an application that has used COBOL, returning an error value of +123 to the parent process, use:

cobexit(123);

cobinit

Initializes the COBOL environment, so that a COBOL program can be called from a non-COBOL program.

Syntax:
#include "cobmain.h"

int cobinit (void);
Parameters:

None.

Comments:

If your program runs a mixture of non-COBOL and COBOL code, and the main program is not written in COBOL, you must call cobinit() before calling a COBOL program. If you do not, you might receive an initialization error when you enter your COBOL code.

On some platforms, the COBOL environment is initialized when the COBOL run-time system is loaded (for example, at process startup).

If the COBOL environment has already been initialised then cobinit() returns successfully.

This routine returns 0 on success.

Equivalent COBOL syntax:

None.

Example:

The following example shows how to initialize (and close down) the COBOL environment from a C main(), so that a COBOL program can be called:

main(int argv, char *argv)
{
    cobinit();                    /* Initialize COBOL environment */

    cobcall("cobep", 0, NULL);    /* Call a COBOL program */

    cobtidy();                    /* Close down COBOL environment */

    return(0);
}

cobtidy

Tidies up the global COBOL run environment.

Syntax:
#include "cobmain.h"

int cobtidy (void);
Parameters:

None.

Comments:

This routine deinitializes the COBOL environment, emptying buffers, closing files and freeing any data areas allocated by the COBOL system.

Use this routine if you want to close down the COBOL system, but are not yet ready to exit.  It returns 0 on success.

This routine can only be called when all COBOL modules have been exited, and you do not intend to re-enter them.  Do not call cobtidy() directly from a COBOL program.

Once cobtidy() has been called, no COBOL entry points or COBOL routines (such as cobinit()) should be called. Doing so results in undefined behaviour.

Equivalent COBOL syntax:

None.

Example:

The following example shows how to close down (and initialise) the COBOL environment from a C main(), so that a COBOL program can be called:

main(int argv, char *argv)
{
    cobinit();                 /* Initialize COBOL environment */

    cobcall("cobep", 0, NULL); /* Call a COBOL program */

    cobtidy();                 /* Close down COBOL environment */

    return(0);
}

cobcommandline

Set up the COBOL command line.

Syntax:
#include "cobmain.h"

cobchar_t *cobcommandline(int flags, int *argcp, cobchar_t ***argvp, 
      cobchar_t ***envpp,cobchar_t **namep);
Parameters:
flags Reserved for future use. Must be 0.
argcp Address of the argc argument passed to the C main().
argvp Address of the argv argument passed to the C main().
envpp Address of the envp argument passed to the C main().
namep Reserved for future used. Should be NULL.
Comments:

This routine sets up the COBOL run environment with the passed command line.

If your application has a C main() and the command line is accessed from COBOL, then this routine must be called.

Portability:

This routine is only available in this form on UNIX platforms.

Equivalent COBOL syntax:

None.

Example:

The following example shows how to use this routine:

main(int argc, char **argv, char **envp)
{
    cobinit();
    cobcommandline(0, &argc, &argv, &envp, NULL);

    /* Rest of code here */

    cobexit(0);
}

10.3.3 Routines That Enable Use of C Threads

This section describes the routines required when COBOL is called from threads created by non-COBOL APIs; that is, when a thread is created by C library, OS or third party threading APIs.

Before calling a COBOL program, you must call cobinit().  In a threaded environment where you don't know if you're the first thread or not, each thread should call cobinit().

Before exiting an application (and not just the current thread) that has called a COBOL program, you must call either cobtidy() or cobexit().


cobthreadtidy

Tidies up the thread-local COBOL run environment.

Syntax:
#include "cobmain.h"

int cobthreadtidy(void);
Parameters:

None.

Comments:

This routine deinitializes the COBOL environment for the current thread, cleaning up any thread-state information and freeing any data allocated as thread-local.  It returns 0 on success.

This routine can only be used when the current thread was created by non-COBOL APIs;  that is, if the thread was created by C library, OS or third-party threading APIs.  It must not be called if the thread was created by COBOL syntax or the CBL_THREAD_CREATE library routine.  Do not call cobthreadtidy() directly from a COBOL program.

This routine must only be called when all COBOL modules have been exited in this thread and you do not intend to reenter them.

Once cobthreadtidy() has been called, no COBOL entry points or COBOL routines (such as cobinit()) should be called in this thread.  Doing so results in undefined behaviour.

Equivalent COBOL syntax:

None.

Example:

When a C thread is created, you need to specify a C function that is the initial entry point for the thread.  If this entry point is c_thread(), then the following shows how to:

c_thread(void)
{
    cobinit();                  /* Only required if not already
                                 * called in this process  */
    cobcall("cobep", 0, NULL);  /* Call COBOL */
    cobthreadtidy();            /* Tidy up COBOL in this thread */ 

    return 0;                   /* Exit thread */
}

10.3.4 Environment Handling

This section describes the routines required so that the COBOL run-time system knows that the environment has changed.


cobgetenv

Provides the same functionality as the C library call getenv().

Syntax:
#include "cobenv.h"

cobchar_t *cobgetenv(const cobchar_t *name);
Parameters:
name A null-terminated string, specifying the environment variable name to be searched for.
Comments:

The specified environment variable is searched for and returned.  If the environment variable does not exist then NULL is returned.

Equivalent COBOL syntax:
DISPLAY name UPON ENVIRONMENT-NAME
ACCEPT ... FROM ENVIRONMENT-VALUE
Example:

The following code displays the value of $COBDIR:

cobchar_t *cobdir;

if ((cobdir = cobgetenv("COBDIR")) == NULL)
    cobdir = "<unset>";

cobprinf("COBDIR=%s\n", cobdir); 

cobputenv

Allows you to dynamically change the environment at run time.

Syntax:
#include cobenv.h"

int cobputenv (const cobchar_t *envstr);
Parameters:
string The null terminated string to be placed into the environment.
Comments:

The environment string envstr is put into the environment. By convention, environment strings have the format:

NAME=VALUE

but the run-time system does not check that envstr is in this format.

This routine ultimately passes envstr into the C library routine putenv(), which puts envstr into the OS environment.  Hence, the value of envstr cannot be modified or freed (if at all) until the environment variable has been redefined using another cobputenv().

This routine returns a value of zero if the operation was successful; any other value indicates an unsuccessful operation. Illegal environment names lead to undefined results.

Equivalent COBOL syntax:
DISPLAY name UPON ENVIRONMENT-NAME
DISPLAY value UPON ENVIRONMENT-VALUE
Example:

The following code shows how to set $ABC to XYZ:

cobputenv("ABC=XYZ");

cobrescanenv

Causes the run-time system to rescan the environment for COBOL environment strings.

Syntax:
#include "cobenv.h"

int cobrescanenv(void);
Parameters:

None.

Comments:

This routine rescans the environment for COBOL environment strings, such as file-name mapping entries (that is, dd_ entries). This can be useful if the environment has been changed without the knowledge of the run-time system.

A value of zero is returned on success; any other value indicates an unsuccessful call.

Equivalent COBOL syntax:

None.

Example:

The following code shows how to set a dd_ environment variable so that an open of file abc will instead open xyz:

cobputenv("dd_abc=xyz"); 
cobrescanenv();

For information on dd_ file mapping, see the section Filename Mapping in the chapter Filenames in your File Handling book.


10.3.5 Screen Handling from C

Server Express supports a number of screen handling routines that you can use from C programs. These enable the run-time system and run-time support libraries to handle output from both C programs called from COBOL programs and from ACCEPT/DISPLAY operations performed by the calling COBOL programs. Normally if any screen handling is carried out outside the control of COBOL (for example, under the control of C) COBOL is not aware of the output from the screen handling operation when control returns to COBOL. The effect of subsequent screen handling operations could thus be undefined. The routines provided enable you to avoid this problem.

The routines in this section are not portable to non-UNIX environments.

When using these routines you must include the header file cobscreen.h, which is located in the directory $COBDIR/include. This file defines the attributes you can use, the type (cobchtype) and declares any external functions the routine needs. The type cobchtype defines a two-byte pair, with the first byte containing a character and the second the attribute for that character.

The attribute byte of cobchtype, as used in some of these routines, takes the same values as the user attribute byte. By default the UNIX user attribute byte is monochrome with the attributes listed below. These values can change when generic attributes are used (from COBOL). See the chapter Low-level Routines for Character Interfaces in your Programmer's Guide to Creating User Interfaces for details of the COBOL system library routines that can be used to set attributes.

The default monochrome attributes are bit settings and can be combined by ORing them together. The following attribute bit values are defined in cobscreen.h:

Attribute
Description
A_NORMAL
A_BOLD
A_UNDER
Normal, no attribute
Bold or highlight
Underline
A_REVERSE
A_BLINK
A_DIM
Reverse
Blink
Dim or lowlight

These routines use their own "virtual cursor", set using cobmove(). The virtual cursor is thread-local; that is, each thread has its own virtual cursor.


cobaddch

Displays the specified character on the screen at the virtual cursor's current position.

Syntax:
#include "cobscreen.h"

void cobaddch (cobchtype ch);
Parameters:
ch The required character and any attributes.
Comments:

The specified character and attribute ch are displayed on the screen at the current position of the virtual cursor.

A character of \n (new line) is a valid character, and moves the virtual cursor to the beginning of the next line. No other control characters are valid; their use causes undefined results.

Equivalent COBOL syntax:

None.

However, this routine is similar to the COBOL syntax:

CALL "CBL_WRITE_SCR_CHATTRS" USING ... 
Example:

To display the character "X" in reverse-video, use:

cobaddch('X' | A_REVERSE);

cobaddstr

Displays the specified string on the screen starting at the virtual cursor's current position.

Syntax:
#include "cobscreen.h"

int cobaddstr (const cobchtype *str);
Parameters:
str The required string and any attributes.
Comments:

The specified string of characters and attributes str is displayed starting at the current position of the virtual cursor. If the string is longer than the remaining width of the line, it will wrap when it reaches the edge of the screen.

A character of \n (new line) is a valid character, and moves the virtual cursor to the beginning of the next line. The null character \0 terminates the string. No other control characters are valid; their use causes undefined results.

str cannot contain more than 255 characters.

This routine returns 0 on success.

Equivalent COBOL syntax:
CALL "CBL_WRITE_SCR_CHATTRS" USING ... 
Example:

To display the string "HUB" with highlighting, underline and blink attributes, use:

cobchtype s[4] = { 'H' | A_BOLD, 'U' | A_UNDER, 'B' | A_BLINK, 0 };

cobaddstr(s);

cobaddstrc

Displays the specified string on the screen starting at the virtual cursor's current position.

Syntax:
#include "cobscreen.h"

int cobaddstrc (const cobchar_t *cstr);
Parameters:
cstr The required string.
Comments:

The specified string of characters cstr is displayed with the default attribute (A_NORMAL), starting at the current position of the virtual cursor. If the string is longer than the remaining width of the line, it wraps when it reaches the edge of the screen.

A character of \n (new line) is a valid character, and moves the virtual cursor to the beginning of the next line. The null character \0 terminates the string. No other control characters are valid; their use causes undefined results.

cstr cannot contain more than 255 characters.

Equivalent COBOL syntax:
CALL "CBL_WRITE_SCR_CHARS" USING ...

or:

DISPLAY cstr AT yyxx
Example:

To display the string "Hello World" followed by a newline, use:

cobaddstrc("Hello World\n"); 

cobclear

Clears the screen and positions the cursor at line 0, column 0.

Syntax:
#include "cobscreen.h"

void cobclear (void);
Parameters:

None.

Comments:

This routine causes the screen to be cleared. The virtual cursor is reset to the home position, at line 0, column 0

Equivalent COBOL syntax:
CALL "CBL_CLEAR_SCREEN" USING ...

or:

DISPLAY SPACES UPON CRT
Example:

To clear the screen and display a message in the top left hand corner, use:

cobclear();
cobaddstrc("Cursor home occurs on cobclear\n"); 

cobcols

Returns the number of columns on the screen.

Syntax:
#include "cobscreen.h"

int cobcols (void);
Parameters:

None.

Comments:

This routine returns the width, in columns, of the screen.

Equivalent COBOL syntax:
CALL "CBL_GET_SCR_SIZE" USING ...
Example:

To find out and display the width of the screen use:

int width = cobcols();
 
cobprintf("Width of screen = %d\n", width);

cobgetch

Gets a character from the keyboard.

Syntax:
#include "cobscreen.h"

int cobgetch (void);
Parameters:

None.

Comments:

Reads a character from the keyboard and returns it. If no character is pending this routine waits until a key is pressed.

A value of -1 is returned on error (for example, EOF).

Equivalent COBOL syntax:
CALL "CBL_READ_KBD_CHAR" USING ...
Example:

The following code asks for a Yes/No response:

int ch;

cobaddstrc("Continue [y/n]? ");

ch = cobgetch();

if (ch == 'Y' || ch == 'y')
{
    /* Yes */
}

coblines

Returns the number of lines on the screen.

Syntax:
#include "cobscreen.h"

int coblines (void);
Parameters:

None.

Comments:

This routine returns the depth, in lines, of the screen.

Equivalent COBOL syntax:
CALL "CBL_GET_SCR_SIZE" USING ...
Example:

To find out and display the depth of the screen use:

int depth = coblines();

cobprintf("Depth of screen = %d\n", depth);

cobmove

Moves the virtual cursor to the specified line and column on the screen.

Syntax:
#include "cobscreen.h"

void cobmove (int y, int x);
Parameters:
y The line number to move the virtual cursor to
x The column number to move the virtual cursor to
Comments:

The virtual cursor, as used by the routines in this section, is moved to the line and column values, as specified by the y and x parameters.

The virtual cursor home position, of the top left hand corner, is (0,0). That is, a y value of 0 and an x value of 0.

The virtual cursor is thread local. That is, each thread has its own virtual cursor.

Equivalent COBOL syntax:

CALL "CBL_PUT_SCR_POS" USING ...

Example:

The following displays a simple counter:

int secs = 10;
char *message = "Time Left: ";

cobmove(10, 10);
cobprintf("%s%d", message, secs);
while (secs--)
{
    sleep(1);
    cobmove(10, 10 + strlen(message));
    cobprintf("%2d", secs);
}

cobprintf

Displays the specified formatted string on the screen at the virtual cursor's current position.

Syntax:
#include "cobscreen.h"

int cobprinf (const cobchar_t *fmt, ...);
Parameters:
fmt The formatted string to display.
Comments:

The formatted character string fmt is displayed with the default attribute (A_NORMAL), starting at the current position of the virtual cursor. If the string is longer than the remaining width of the line it wraps when it reaches the edge of the screen.

The fmt paramter is formatted as it would be by the C library routine, printf(). For example, any %s in fmt is substituted for the string in the subsequent arguments passed to cobprintf().

The character \n (new line) is a valid character and moves the virtual cursor to the beginning of the next line. The null character \0 terminates the string. No other control characters are valid; their use causes undefined results.

The specified string must not be longer than 255 characters in length when fmt has been fully expanded.

This routine returns either the number of arguments output or -1 for an error condition.

Equivalent COBOL syntax:

None

Example:

The following displays a simple counter:

int secs = 10;

char *message = "Time Left: ";

cobmove(10, 10);
cobprintf("%s%d", message, secs);
while (secs--)
{
    sleep(1);
    cobmove(10, 10 + strlen(message));
    cobprintf("%2d", secs);
} 

cobscroll

Scrolls the screen display, starting and finishing at the specified lines, up one line.

Syntax:
#include "cobscreen.h"

void cobscroll (int top, int bot);
Parameters:
top The first line of the area of screen to be scrolled up one line. This must be two lines less than the physical screen size to prevent the top line from scrolling off the screen.
bot The last line of the area of screen to be scrolled up one line
Equivalent COBOL syntax:

None

Example:

The top line of the screen is 0. The bottom line of the screen can be found using coblines(). Hence, to scroll the entire screen use:

cobscroll(0, coblines() - 1);

10.3.6 Terminal specific routines

This section details the routines to cope with terminal specific functionality. Also see the chapter Terminfo Database and Terminal Devices in your Server Express User Guide.

The functions in this section are only available on UNIX environments.


cobkeypad

Puts the numeric keypad of the terminal keypad into local mode or transmit mode.

Syntax:
#include "cobscreen.h"

void cobkeypad(int mode);
Parameters:
mode The keypad mode; either 0 or 1.
Comments:

This routine puts the numeric keypad of the terminal keypad (if there is one) into local mode or transmit mode. To function correctly, the smkx (transmit mode) and rmkx (local mode) entries must be present in the terminfo database for the terminal type you are using.

The mode parameter should be 0 to put the keypad into local mode or 1 to put the keypad into transmit mode. Any other value is undefined.

By default, the run-time system puts the numeric keypad into transmit mode when smkx is present in your terminfo database.

Equivalent COBOL syntax:

None


cobtermmode

Toggles the terminal screen between standard and wide modes.

Syntax:
#include "cobscreen.h"

int cobtermmode(const cobuns8_t *mode)
Parameters:
mode The terminal mode; the address of a byte that is either 0 or 1.
Comments:

This routine toggles the terminal screen between default and wide modes, if this functionality is present in the terminfo database for the terminal type you are using.

To function correctly, the terminfo database must support a terminal whose name is the current terminal type with a -w suffix, and the terminfo entries must also have appropriate initialization and/or reset capabilities. For example, if the current terminal is vt100 then there also needs to be a vt100-w in the terminfo database and the vt100 and vt100-w need appropriate is1, is2, is3, rs1, rs2 and/or rs3 entries.

The mode parameter should be 0 to put the terminal into standard (default) terminal mode or 1 to put the terminal into wide terminal mode. Any other value is undefined.

When the terminal mode is successfully toggled, the screen handling system is initialised (if it wasn't already), the screen is cleared and the cursor positioned in the home position.

This routine can be safely called from COBOL. See the section Wide Terminal Mode in the chapter Terminfo Database and Terminal Devices of your Server Express User Guide for more details.

When using this routine, you must be aware of the following:

This routine returns 0 on success, non-zero on error. The following error values are currently returned:

1 The terminfo file has not been found, is not readable, is corrupt or there is not enough memory.
2 The terminfo file does not contain one or more of the required capabilities.
3 The environment does not support the requested code.
Equivalent COBOL syntax:
CALL "cobtermmode" using mode 
Example:

The following code switches the terminal into wide mode, displays some text, waits for a keypress and restores the terminal back to normal mode:

cobuns8_t mode_on=1, mode_off=0;

if (cobtermmode(&mode_on) == 0)
{
    /* Display some text over beyond column 80 to demo wide mode */
    cobmove(10, 100);
    cobprintf("Line 10, Column 100");
    cobgetch();
    /* Wait for a key press */
    
    cobtermmode(&mode_off);
    /* Back into standard mode */
}

10.3.7 Interfacing with the UNIX Operating System

The COBOL run-time system sets the terminal to a mode suitable for COBOL. This means that any calls to the C library routine system() might fail because they do not reset the terminal settings before the call, or set them back after the call.

You should replace your calls to system() with calls to SYSTEM() as detailed below.

The function in this section is only available on UNIX environments.


SYSTEM

Run an executable, via a system shell.

Syntax:
#include <sys/wait.h>

int SYSTEM (const unsigned char *cmd);
Parameters:
cmd A null-terminated system command line to be executed.
Comments:

The specified command line is passed to a shell and executed, as for the C library routine system().

The COBOL terminal state is reset to shell mode before the call and restored after the call.

As the COBOL environment is unaware of any output from another process, such as the shell or command executed during SYSTEM(), you must ensure that the screen is either not updated during the SYSTEM() call or is redisplayed after execution of the call.

The return value from this routine is the same format as that returned from the C library routine system(). There are macros in the C library include file <sys/wait.h> to manipulate this value and get the return code of the executed command. See your system documentation for more information.

Equivalent COBOL syntax:
CALL "CBL_EXEC_RUN_UNIT" USING ...
Example:

The example below copies one file to another, redirecting standard output and standard error to an error file (which could be subsequently opened and read to see if any output was generated by running the command) and displays the return code of the command:

int res;

res = SYSTEM("cp f1 f2 > errfile 2>&1");

if (WIFEXITED(res))
    cobprintf("Exit status: %d\n", WEXITSTATUS(res));

10.3.8 Error and Exception Handling

This section describes the cobsetjmp() and coblongjmp() routines that enable you to mix C and COBOL programs. They provide routines similar to the C library routines setjmp() and longjmp(); see your UNIX documentation for details of setjmp() and longjmp().

The purpose of the cobsetjmp() and coblongjmp() routines is to provide the capability of a non-local GO TO, for use in error or exception handling.


cobsetjmp and coblongjmp

Provide the capability of a non-local GO TO, for use in error or exception handling.

Syntax:
#include "cobsetjmp.h"

int cobsetjmp(struct cobjmp_buf *buf);

void coblongjmp(struct cobjmp_buf *buf);
buf A buffer in which the current execution environment is saved.
Comments:

The cobsetjmp() routine saves the environment of the current COBOL program and C function in the buffer pointed to by buf. It calls the C library routine setjmp(), which immediately returns a value of 0.

A subsequent call to coblongjmp() either from elsewhere in the C function that called cobsetjmp(), or from one of its C or COBOL subprograms, causes execution to be resumed at the point immediately after the call to cobsetjmp().

After calling coblongjmp(), cobsetjmp() returns a non-zero value, thus enabling the value to be tested after the cobsetjmp() call.

The following restrictions apply when using these functions:

Equivalent COBOL syntax:

None.

Example:

The following shows how to use these routines:

void
some_c_func(void)
{
    struct cobjmp_buf buf;

    if (cobsetjmp(&buf) != 0)
    {
        cobprintf("Returned from coblongjmp\n");
        return;
    }
  
    /* Valid code here - for example can call COBOL */

    coblongjmp(&cobjmp_buf);
}

10.3.9 Signal Handling

This section describes the calls you need to make if you want to use signal handling in your application, especially if you are mixing COBOL and C in your application.

The run-time system sets up default signal handlers for all signals whose operating system default action is to cause termination. These default handlers make sure that the COBOL system is properly cleaned up before terminating. Hence, any open files are closed (to prevent file corruption), the terminal is reset to a sane state, user posted exit and error procedures are executed, and so on.

The run-time system also uses signal handling to provide various functionality. For example, interrupt key detection, Animator Zoom interrupt key, Job Control, and so on.

This COBOL system provides two routines that you can use to complement or override the signal handling used by the run-time system:

cobpostsighandler()
cobremovesighandler()

These routines allow multiple handlers for each signal and enable you to prioritize use of these handlers. You can use them from inside a C program only, not least because you need the C library include file <signal.h> for the signal values, which vary between platforms.

Use these routines instead of the operating system signal calls, (signal(), sigaction(), and so on) which provide only the ability to post a single signal handler for each call and so often prevent multiple applications being able to work together reliably.

For example, if you use one of the C library signal calls to post a signal handler before invoking a COBOL program, your signal handler might be overridden. Whereas, if you use one of the C library signal calls after invoking a COBOL program, the default run-time system handler, additional COBOL functionality and user posted signal handlers are all overridden, causing unexpected results.


cobpostsighandler

Adds the specified handler to the list of handlers for the specified signal, at the specified priority.

Syntax:
#include "cobsignal.h"

cobsigtype_t cobpostsighandler (int signal, int priority, 
    PFI_SIG handler); 
Parameters:
signal Signal number, as defined in the <signal.h> include file.
priority The priority of handler in the range 1 to 254.
handler Address of your signal handler.
Comments:

This routine posts the specified handler to the list of handles for the specified signal at the specified priority. Also see the section Posting Signal Handlers below.

priority is the priority of the handler in the range 1 to 254, where 254 is the highest priority. Values 127 and 129 through 139 are reserved for use by Micro Focus.

handler is the address of your signal handler. This must be a C function returning an integer value.

This routine returns a pointer that you can use to remove your signal handler later. If the return value is NULL, a signal handler was not posted for this signal. This could be due to lack of memory or the signal being disabled by the tunable signal_regime.

Equivalent COBOL syntax:

None.


cobremovesighandler

Removes a posted handler from the list of handlers for the appropriate signal.

Syntax:
#include "cobsignal.h"

void cobremovesighandler (cobsigtype_t sighandler);
Parameters:
sighandler Pointer returned when posting your signal handler using a previous cobpostsighandler() call.
Comments:

This routine removes a previously posted signal handler.

sighandler must have been previously returned when posting a signal handler with the cobpostsighandler() routine. See the section Posting Signal Handlers below.

There is no return value from this call.

Equivalent COBOL syntax:

None.


10.3.9.1 Posting Signal Handlers

You use the cobpostsighandler() routine to post signal handlers.

The run-time system also uses the cobpostsighandler() routine to post all of its signal handling. Default handlers are posted for all signals whose operating system default action causes termination. The default handlers either make sure that the COBOL system has been cleaned up before terminating, or cause the signal to be ignored. These default handlers assume that the signals were generated by the operating system due to a serious error or that a signal has been unexpectedly raised. Hence, they usually produce a run-time system message, such as 114 or 115.

If the same handler is posted twice, and neither of them is removed using the cobremovesighandler() routine, the handler is executed twice (assuming the handler, and all handlers executed in between, do not return a value of zero).

If two handlers are posted with the same priority, the last one posted is executed first.

Once you have posted a handler, you do not need to repost it. The handler is called each time that signal is received (assuming that the first receipt of the signal does not cause termination). If you want to execute your handler only once, you must remove it, using the cobremovesighandler() routine, in your signal handler.

While processing signal handlers, the signal is blocked. This prevents recursion if the same signal is received in rapid succession.

A signal handler must return normally. That is, you must not use any other function that terminates a signal handler function, such as longjmp() or coblongjmp(), and you must use the C syntax to return a value:

    return(num);

If you do use another function to return, the signal remains blocked, preventing any further signals from being processed.

Setting the Priority

When a signal is received, the handler posted with the highest priority for that signal is called. Your handler should take any appropriate action (such as setting a flag to be acted on later) and then return. If the handler returns a non-zero value, the handler with the next highest priority for that signal is called. If the signal handler returns zero, no further signal handlers are processed.

The run-time system posts its default signal handlers with priority 127. So, to override them, or to process your signal handler before them, post your handler with priority 128. Use a priority of 126 (or less) if you want to make sure that your handler is processed after the default run-time system handler (if the default run-time system handler does not exit).

The run-time system provides various functionality using signal handlers. These handlers are posted with a priority in the range of 129 to 139.

10.3.9.2 Writing Signal Handlers

A signal handler should do very little. A signal can be generated at any time so the routine that was being executed could be in an "unsafe" state (eg. in the middle of modifying global variables) and so trying to execute it in your signal handler could cause problems. The routine being executed could be a C library routine such as malloc().

There are a small subset of C library routines that are safe to call from signal handlers. Do not try to call any other C library routines, or any COBOL routines, from your signal handler. See your system documentation for more information on the safe C library routines.

Some signals are generated by the operating system when a serious error has occurred. Catching these signals can cause unexpected and potentially dangerous results. You should not catch any of the following signals:

SIGBUS
SIGSEGV
SIGEMT
SIGILL
SIGIOT / SIGABRT
SIGSYS
SIGFPE
SIGTRAP

Preventing the run-time system from processing certain signals can break some run-time system functionality. If you catch any of these signals (with a priority of 140 or more), your signal handler must return a non-zero value so that the run-time system's handler is also executed. The signals concerned include:

SIGCHLD
SIGPIPE
SIGUSR1
SIGUSR2
SIGVTALRM
SIGWINCH
SIGCONT
SIGTSTP
SIGTTIN
SIGTTOU


Note: Micro Focus reserves the right to change their default signal handlers or use extra signals in the future.


10.3.9.2.1 Example - setting up a handler for the SIGALRM signal

The following example illustrates setting up a handler for the SIGALRM signal.

#include <stdio.h>
#include <signal.h>
#include "cobsignal.h"
#include "cobmain.h"

int
mysigcatch(int sig)
{
     cobprintf("In new signal handler\n");
     return(0);  /* Do not process any further handlers */
}

void
mysigexit(cobsigtype_t sighand)
{
    cobprintf("Cancelling handler\n");
    cobremovesighandler(sighand);     /* Remove the handler */
}

main(int argc, char *argv[])
{
    cobsigtype_t sighandle;

    cobinit();

    sighandle = cobpostsighandler(SIGALRM, 128, mysigcatch);
    cobfunc("cobolprog", argc, argv); /* call a cobol program
                                      using cobfunc function */
    alarm(1);                         /* raise the signal */
    pause();                          /* wait for the signal */
    sleep(4);
    mysigexit(sighandle);

    cobexit(0);                 /* Cobexit - close down COBOL
                                   run-time environment */
}

10.3.9.3 Coping with More than One Handler for the Same Signal

The cobpostsighandler() routine enables two or more handlers to be posted for the same signal. When that signal is generated by the operating system (such as a SIGINT generated when the interrupt key is pressed), each handler can take appropriate action and then let other handlers be executed (by returning a non-zero value). Alternatively, they can decide to make the signal "ignored" by returning a value of zero to prevent other handlers from being executed. However, so that your handler can work with other handlers for the same signal, a handler of priority 140 (or more) should return non-zero to let other handlers have the opportunity to also be notified. A handler of priority 128 can return zero if you do not want the run-time system default action to be executed (which may cause termination).

When you raise a signal (such as by using alarm() to raise a SIGALRM signal, or when raising a signal to a different run-unit or application), then it is probable that only your signal handler wants to be called and other posted signal handlers are not expecting the signal. Hence, in this case, you should set a global resource before raising the signal and then check that resource in your signal handler. If the resource is set (as expected), then the signal was raised by you, so you can take the appropriate action and return zero to prevent other handlers from being unexpectedly called. If the resource is unset, then someone else (or something else, such as the operating system) raised the signal and so you can take no action and should let other handlers execute by returning a non-zero value.

Examples of global resources are global variables (if in the same run-unit), shared memory, pipes, files, and so on. Hence, in the above example, we could have set a global variable before raising the alarm() signal. We would then need to check the global variable in the signal handler, mysigcatch(). If it was set, we would carry out our action, reset the variable and return zero. However, if the global variable had not been set, then some other code is likely to have raised the signal. Hence, we would not want to carry out our action and would instead need to return a non-zero value immediately. This allows the appropriate action to be taken in some other handler.

10.3.9.4 Converting Signal Handlers Written for the signal() Function

If you have any signal handlers that are posted using a C library signal call, such as signal() or sigaction(), change them to use the cobpostsighandler() routine. This is so that your handler and any default run-time system handler, additional COBOL functionality and user posted signal handlers can all co-exist without one overriding the other, causing unexpected results.

The cobpostsighandler() routine interface is very similar to the signal() interface. The two parameters you pass to signal() are also passed to the cobpostsighandler() routine, plus a priority.

The differences between signal() and the cobpostsighandler() routine are:

10.3.9.5 Coping with Third Party Software that Uses Signals

If you are using third party software that posts a signal handler using a C library signal routine, such as signal() or sigaction(), unexpected results may occur. For example, if the third party software posts its handler before COBOL has been invoked, then when COBOL is invoked the third party's handler might be overridden by a run-time system/COBOL handler. If the the third party subsequently raises a signal, then a 115 error may occur.

To overcome this, you can use the run-time tunable signal_regime. This tunable prevents handlers from being posted for the specified signal if a signal handler is posted before the first COBOL invocation.

If handlers are prevented from being posted for a signal, due to this tunable, the cobpostsighandler() routine returns NULL. Hence, the default run-time system handlers and any additional COBOL functionality achieved using the signal is not available. It also means that you should check the value returned from any cobpostsighandler() routine calls for NULL.

Use of the signal_regime tunable is recommended only for use with third party software. You should always use the cobpostsighandler() routine in your own code. See the chapter Run-time Configuration in your Server Express User Guide for details on how to set signal_regime.

10.3.9.6 Comparing the Signal() and Sigaction() Functions

On some platforms, the C library routine sigaction() is available. It is more robust than signal() when signals are being received in rapid succession or when a machine is heavily loaded. The cobpostsighandler() routine uses sigaction() by default.

You can force the cobpostsighandler() routine to use signal() instead of sigaction() by using the signal_interface tunable. For more information on tunables see the chapter Run-time Configuration in the Server Express User Guide.


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

PreviousThe COBOL Interfacing Environment Header-to-COPY UtilityNext"