HP 3000 Manuals

Translating C Definitions [ Micro Focus COBOL for UNIX COBOL User Guide ] MPE/iX 5.0 Documentation


Micro Focus COBOL for UNIX COBOL User Guide

Translating C Definitions 

The OSF/Motif Programmer's Reference Manual describes all the Motif API
functions in terms of the C programming language.  For those programmers
unfamiliar with C, this section explains how to translate these
descriptions into COBOL.

Your Motif development system includes definitions of many of the Motif
function parameters in C header files that use a file extension of .h.
This COBOL system contains a utility, H2cpy 
, to convert C header files into COBOL COPY-files.  The utility converts
C header files including those supplied with the Motif development kit
into COBOL type definitions and COBOL CALL prototypes.  It is especially
useful if you want to write Motif applications in COBOL using the System
Programming Extensions.  See your COBOL System Reference chapter
Header-to-COPY Utility for details on converting C header files.  See
your Language Reference for details on COBOL TYPEDEFs and CALL
prototypes.

Before you can compile any of the sample programs (or your own Motif
software), you must first run H2cpy to translate the C header files into
COBOL as described below.

Converting C Header Files 

The Motif development system includes a variety of C header files in the
directory Xm in the standard header directory of /usr/include.  Before
you can program to the Motif API you need to translate many of these into
COBOL using H2cpy.  Generally, each Motif function has its own header
file; you can find out which this is from the OSF/Motif Programmer's 
Reference Manual.  For example, XmCreateMainWindow is associated with
/usr/include/Xm/MainW.h and XmMessageBoxGetChild is associated with
/usr/include/Xm/MessageB.h.

H2cpy must convert all C header files during one run to ensure that
declarations are not duplicated.  For this reason, you might find that
the most convenient way to translate the header files is to convert them
indirectly by creating your own header file, which lists together all the
files you are interested in.  For example create a file called motif.h 
and add a line for each file header required:

     #include <Xm/MainW.h>
     #include <Xm/MessageB.h>
     #include <Xm/PushB.h>
       ...

Then run H2cpy to convert them ensuring that the environment variable
INCLUDE is either not set or set to /usr/include:

     h2cpy motif.h -v

Alternatively, where only a few header files are required, you can
specify all the individual files directly on the command line:

     h2cpy /usr/include/Xm/MainW.h /usr/include/Xm/MessageB.h -v

This translates the MainW.h and MessageB.h files and all their included
files into the COBOL copyfile MainW.cpy.  You can use the COPY statement
to include this file in your program.  The compiler then validates any
function calls that you make to ensure that the parameters conform to the
COBOL CALL prototype in MainW.cpy.  H2cpy will automatically generate
useful CALL prototypes from the C function prototypes.  However, it might
be that you find the validation inappropriate in some cases.  You have
the choice of either modifying MainW.cpy or of running H2cpy with the
option to suppress the generation of CALL prototypes.

Translating C Function Declarations 

The C definition of the XmCreateMainWindow API function is taken
from/usr/include/Xm/MainW.h and is shown in the following example; the
rest of this section explains how to translate this C definition into
COBOL.

     extern Widget XmCreateMainWindow
               (Widget   parent,
                char     *name,
                ArgList  args,
                Cardinal argCount);

The following list defines each of the words in the example:

Word                   Meaning

extern                 Declares the function as external and not defined
                       in the current program

Widget                 Function returns data type of Widget

XmCreateMainWindow     Function name

Widget                 Data type of the parameter parent

parent                 Possible name for the parameter (optional in the
                       declaration but required in any use of the
                       function)

char                   Data type of the parameter name; char is
                       equivalent to a COBOL alphanumeric data item.  C
                       generally expects this to be terminated by a null
                       character.

*name                  The asterisk denotes that the routine expects the
                       address of the parameter to be passed rather than
                       the value.  The "name" portion represents a
                       possible name for the parameter.

ArgList                Data type of the parameter args

args                   Possible name for the parameter

Cardinal               Data type of the parameter argCount

argCount               Possible name for the parameter

);                     End of the function declaration

All Motif API function definitions appear in at least one of the Motif
header files.  The names used for the parameters are not significant and
may differ between the documented function definition and the equivalent
definition in the header file.

You now need to find the definitions of the data types and other
constructs and decide how to code them in COBOL. This information is in
the files produced by H2cpy.  Coding is fairly straightforward but
instead of passing fully typed pointer parameters by value, as described
in the C function definition, COBOL can often pass them more conveniently
using the BY REFERENCE clause as may be shown in the COBOL prototype.

The first thing you need to determine is the calling convention required
by the XmCreateMainWindow routine.  Look this routine name up in
MainW.cpy and you will find a CALL prototype definition such as:

          entry "XmCreateMainWindow" using
                  by value      data-pointer
                  by reference  any
                  by value      data-pointer
                  by value      uns-int
              returning         data-pointer

The parameters are specified in terms of COBOL type definitions
data-pointer, uns-int, et cetera which are defined at the beginning of
the MainW.cpy file.  The parameter any signifies that any data type can
be used.  All COBOL CALL statements referencing XmCreateMainWindow must
use parameters that conform with the corresponding data type otherwise
the compiler will give an error.  Wherever possible it is preferable to
use the type definition when defining data items rather than the explicit
COBOL PICTURE so that your program will be more portable between
different Motif API environments.

The calling convention that the routine XmCreateMainWindow requires is
given in the SPECIAL-NAMES paragraph of the program in which it is
defined.  Look in MainW.cpy for the program-id preceding the call
prototype and you will find a declaration such as:

            program-id. "c_typedefs" is external.
            01  XmScrolledWindowWidgetClass        is typedef
           ...

There is no SPECIAL-NAMES paragraph after the PROGRAM-ID paragraph.  This
tells you that the routine XmCreateMainWindow must be called with the
default COBOL calling convention of 0.  This means that you do not need
to define a calling convention for calls to the Motif API routines.  For
purposes of documentation you can add the following line to the
SPECIAL-NAMES paragraph if you wish:

          call-convention 0 is motapi

Returning to the C definition of the XmCreateMainWindow example
above, the first data type you need to translate is Widget.  Since
XmCreateMainWindow returns a value of type Widget, you need to define a
storage location for that value, say WidgetResult.  Looking up Widget in
the file MainW.cpy, you find this definition:

      01  Widget            is typedef       usage data-pointer.

The word TYPEDEF indicates that the data type Widget is a type definition
and so can be used to define the type (i.e., usage) of the variable
WidgetResult.  Widget is defined as having the data type data-pointer,
which is defined at the beginning of the MainW.cpy file as:

     77  data-pointer      pointer is typedef.

The data types Widget and data-pointer are, therefore, both equivalent to
the COBOL type, POINTER and they can all be used interchangeably.  From
the COBOL CALL prototype found earlier we see that the routine returns a
value of type data-pointer and so we can define WidgetResult in terms of
Widget.  However, as a COBOL programmer you may find the definition more
convenient with the equivalent line:

      01  WidgetResult      usage data-pointer.

Next consider the parameters to the function call.  The first parameter
has type Widget, which has already been determined as type data-pointer.
The CALL prototype says that the first parameter must be passed BY VALUE
and have a type data-pointer and so we can write the line:

      01  parent            usage data-pointer.

The CALL prototype says that the second parameter must be passed BY
REFERENCE but can be of any type.  The BY REFERENCE clause is a
convenient COBOL way of avoiding direct use of parameter pointers and of
permitting type checking.  It is otherwise equivalent to passing a
parameter as an untyped pointer BY VALUE.

The C header file declares the parameter name as a char pointer.  In C, a
char pointer references a char datatype which represents both a one-byte
numeric item or the start of a multi-byte text string.  In contrast,
COBOL recognises a one-byte numeric item and a multi-byte alphanumeric
item as distinct data types.  For this reason, when H2cpy translates a C
function prototype parameter that is a char pointer it cannot specify a
specific data type and so generates any.

From the API function description we know that the parameter name is a
pointer to a C string which is a multi-byte text item that is terminated
by a C null character.  The closest COBOL equivalent is either an
alphanumeric data item that includes a C null character within its value
or a concatenation of an alphanumeric data item with an explicit C null
character.  (You can use the DELIMITED clause if you are prepared to
modify your CALL prototype; see your Language Reference for details.)

It is generally convenient to use the COBOL concatenation 
operator.  For example you can define the BY REFERENCE parameter for name 
as:

      01  MainWName         pic x(10) value "My-Window" & x"00".

Where a literal such as x"00" is used many times, it is important that
the correct value is coded each time.  This can be done in a simple way
by declaring the literal as a level 78 item and thereafter using the
level 78 name:

      78  c-null            value x"00".
      01  MainWName         pic x(10) value "My-Window" & c-null.

The third parameter is data type ArgList.  From MainW.cpy you get:

      01  ArgList           is typedef       usage data-pointer.

The CALL prototype says that the third parameter must be passed BY VALUE
and have a type data-pointer and so we can write the line:

      01  MainWArgs         usage data-pointer.

From the C definition we know that this pointer must reference an
argument structure of type Arg.  We can define such a group item as:

      01  MainWArg          usage Arg occurs 100.

and in the procedure you can set the parameter with a statement such as:

          set MainWArgs to address of MainWArg(1)

The next parameter is of data type Cardinal.  From MainW.cpy you get:

      01  Cardinal          is typedef       usage uns-int.

Cardinal is defined as having the data type uns-int, which is defined at
the beginning of the MainW.cpy file as:

      77  uns-int           pic  9(9)  comp-5 is typedef.

The CALL prototype says that the fourth parameter must have a type
uns-int and so, for convenience, we can define the parameter as:

      01  argCount          usage uns-int.

After defining the complete list of parameters, you end up with the
following source lines:

      copy "MainW.cpy".
      program-id. motdemo.
      special-names.
          call-convention 0 is motapi.
      working-storage section.
      78  c-null            value x"00".
      01  WidgetResult      usage data-pointer.
      01  parent            usage data-pointer.
      01  MainWName         pic x(10) value "My-Window" & c-null.
      01  MainWArgs         usage data-pointer.
      01  argCount          usage uns-int.

      01  MainWArg          usage Arg occurs 100.

      procedure division.
          set MainWArgs to address of MainWArg(1).


NOTE The names name and args are already used for a data type so we have to choose other, unique names for these parameters. MainWName and MainWArgs are used in the example above.
After you have performed all these conversions, the COBOL call to the API function XmCreateMainWindow becomes: call "XmCreateMainWindow" using by value parent by reference MainWName by value MainWArgs by value argCount returning WidgetResult If the values you pass to the function are constants, then you can use the phrases: by reference "literal" for alphanumeric literals and: by value literal size n for numeric literals, as long as you use specify the size of the literal. Therefore, you could replace two parameters with literals to give the following call: call "XmCreateMainWindow" using by value parent by reference "My-Window" & c-null by value MainWArgs by value 2 size 4 returning WidgetResult Constants defined at level-78 do not have any size associated with them. When they are used as parameters in a CALL statement, they default to a size of four bytes. The SIZE phrase of the USING clause can be used specifically to set the number of bytes passed as the parameter. For example, the constant XmDIALOG_OK_BUTTON is defined in the C header files as: #define XmDIALOG_OK_BUTTON 4 and translated by H2cpy in motif.cpy as: 78 XmDIALOG-OK-BUTTON value 4.
NOTE C uses the underscore character ( _ ) to split long names or prefixes. The underscore cannot be used in COBOL. Therefore, H2cpy replaces all underscores in names with hyphens (-)
. This constant can be used as a legal value for child parameter in the API function XmMessageBoxGetChild which is defined in C as: extern Widget XmMessageBoxGetChild( Widget widget, unsigned char child ) ; and is translated by H2cpy into: entry "XmMessageBoxGetChild" using by value data-pointer by value uns-char returning data-pointer However, the child parameter must be of type uns-char which is defined in MainW.cpy as: 77 uns-char pic 9(2) comp-5 is typedef. Which is one byte in size. If this is to be passed as a literal then you would have to add a SIZE 1 clause to specify the correct size: call "XmMessageBoxGetChild" using by value parent by value XmDIALOG-OK-BUTTON size 1 returning WidgetResult For further examples of how to use the files created by H2cpy, see your COBOL System Reference. Macros. H2cpy does not convert C macros defined in the header files because COBOL has no equivalent feature. This should not be a problem with the Motif API, but note that the COBOL REDEFINES statement can often be used to achieve the same effect. Compiling Compiling a program for Motif is no different to compiling any other program. For performance reasons you will probably want to produce native code. Linking You can dynamically load a COBOL Motif application as an .int or a .gnt file or you can build your Motif application as an executable file. To dynamically load .int or .gnt files you first need to build a suitable run-time system. Building a Run-time System. To run .int or .gnt files you need to produce an executable run-time that has all the necessary Motif API support routines linked in. We recommend that you specify just those routines that are required, either via the cob -I flag, or by creating a dummy program. The dummy program just needs a CALL literal statement for each routine that is required. For example: procedure division. stop "Error - shouldn't get here in Dummy". call "XtInitialize". call "XmCreateMainWindow". call "XtManageChild". * et cetera ... Compile and link this with the system libraries to produce a run-time system. The exact list of system libraries to be used needs to be taken from your Motif development system documentation. A typical cob command is given below; your Motif system might include additional libraries that need adding to the link list (for example +lPW +lsocket +lintl): cob -xo mrts -e "" dummy.cbl +lXm +lXt +lX11 After compiling your Motif application then you can run it: cob motdemo.cbl ./mrts motdemo.int Building an Executable Application. To build your application as an executable, just use the following cob command (adding any additional libraries your Motif development system might require): cob -xF motdemo.cbl +lXm +lXt +lX11 Then run it by simply entering: ./motdemo Debugging You can use Animator to directly debug Motif applications on an X terminal. You need to compile your application for animation, set COBSW for animation and then run your application as .int code as discussed above. For the Bourne shell use: COBSW=+A export COBSW ./mrts motdemo.int


MPE/iX 5.0 Documentation