PreviousInstallf Facility Application Configuration SystemNext"

Chapter 12: Header-to-COPY Utility

The Header-to-COPY (H2cpy) utility is a self-contained application run from the command line or automatically invoked by the Headers preprocessor. It translates C-language header files into their COBOL-equivalent copyfiles. It can handle any valid ANSI or ISO C-language file.

12.1 Overview

H2cpy translates C-language header files into the equivalent COBOL copyfiles, using the COBOL type definition and CALL prototype syntax. The COBOL system then uses this syntax to verify that the parameters used in a COBOL program conform to the definition in the original C-language header file. H2cpy simplifies COBOL programming where you use libraries of routines whose interface definitions are provided as C-language header files. Examples of this include the libraries for Motif, Windows and OS/2 Presentation Manager.

H2cpy produces two COBOL files which you can include in your COBOL program using the COPY statement. The main .cpy file contains type definitions and literals, the subsidiary .ext file contains any external data declarations. As well as being essential when using C interfaces, you may also find H2cpy helpful when rewriting C programs in COBOL.

Input to H2cpy is any valid ANSI or ISO standard C source file. H2cpy may fail or may generate incorrect COBOL code if it encounters invalid C.

H2cpy may be run directly from the command line or may be invoked indirectly via the PREPROCESS(headers) Compiler directive. The Headers preprocessor allows C header files, with an extension of .h to be specified within a COPY statment within a COBOL source file. The preprocessor will recognize these as C headers and will use H2cpy to convert them. This can be very convenient for relatively small header files.

12.1.1 Examples

The examples in this chapter are code fragments, and not the complete code generated by H2cpy.

The examples in this chapter generate extra COBOL data items in addition to those specified in the code fragments. These extra data items are included in the output COBOL copy file because they are general COBOL typedefs that correspond to equivalent C data types. The size of these data items depends on the environment you are using. See the -e command line option.

32-bit:
For 32-bit environments:

       77 char                pic s9(2)   comp-5 is typedef.
       77 uns-char            pic  9(2)   comp-5 is typedef.
       77 short               pic s9(4)   comp-5 is typedef.
       77 uns-short           pic  9(4)   comp-5 is typedef.
       77 int                 pic s9(9)   comp-5 is typedef.
       77 uns-int             pic  9(9)   comp-5 is typedef.
       77 long                pic s9(9)   comp-5 is typedef.
       77 uns-long            pic  9(9)   comp-5 is typedef.
       77 d-l-float                       comp-2 is typedef.
       77 d-float                         comp-2 is typedef.
       77 float                           comp-1 is typedef.
       77 proc-pointer        procedure-pointer is typedef.
       77 data-pointer                    pointer is typedef.
       77 void                pic  9(2)   comp-5 is typedef.

16-bit:
For 16-bit environments, the following data items are different sizes:

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

Note: C header files that require other header files that have been previously processed in the same run cannot be processed on their own by the C compiler. Similarly, H2cpy can only translate a standalone header file, or a complete set of header files. Any macro-names that need specifying in the C compiler command line, and any macros predefined by a particular compiler, may need specifying on the H2cpy command line. For example, Microsoft specific predefined macros include:

_CHAR_UNSIGNED
_CPPUNWIND
_DLL
_M_IX86

_MSC_VER
_MT
_WIN32

ANSI C predefined macros that may need to be specified on the command line using the -D option, include:

__DATE__
__FILE__
__LINE__
__STDC__
__TIME__

12.2 Operation

This section describes how to use H2cpy, starting with the command line syntax.

12.2.1 Invoking H2cpy

To invoke H2cpy, enter the command line:

component { [filename] [option] } ... 

where the parameters are:

component The program-name for the system component to be invoked, in this case H2cpy:

DOS
OS/2 and Windows
UNIX
xm h2cpy h2cpy h2cpy

option One of the H2cpy options listed in the section Command Line Options below.
filename A C language header file that is to be converted to COBOL.

If you do not specify option or filename, a list of the available options is displayed.

12.2.1.1 Command-line Options

An option begins with a hyphen (-) and is case sensitive. Single letter options that take no parameters can be grouped behind one hyphen. For example, the three options "-v -C -h" can also be written as "-vCh". Options can be entered in any order.

DOS , Windows and OS/2:
The forward slash (/) can be used in place of the hyphen on DOS, Windows and OS/2. Options that begin with a hyphen must not be used before specifying the first filename.

The following list describes each option in detail. Options are listed in alphabetical order, with upper-case letters preceding lower-case letters. Spaces between the option letter and any parameter are optional.

Option
Description
-A Removes strict ANSI interpretation of C-language.

There are some obscure areas in which the current ANSI/ISO C standard differs from earlier C language implementations. If you have problems and suspect it is due to old fashioned C, try using this option.

-C Embeds C code within generated COBOL.

The embedded C source lines start with an asterisk (*) and space and are ignored by the COBOL Compiler. The embedded code has been through the C preprocessor.

-D name[=val] Declare a macro name, optionally giving a value. The value can be a numeric or a string literal.
-E Expand all occurrences of structures and unions.

The COBOL for a structure or union is only given in full when it is first declared. Later references are by name.

-F name=val Equate a C function calling convention name to a COBOL CALL-CONVENTION value val for CALL protoypes, where name can be one of the following:
Name Default Value
cdecl 0
default 0
fastcall 2
optlink 16
pascal 11
stdcall 74
system 16

These names match C keywords, possibly with one or more leading underscore characters, except for default which represents the default C calling convention when a convention is not explicitly specified.

See the section Calling Conventions for more details.

-I path Insert the path at the beginning of the include search path list. This option can be used to add entries until the search path list is full. The list can hold up to fourteen entries.

DOS:
On the COBOL systems for DOS, Windows and OS/2, the search list is initially empty unless the INCLUDE environment variable is used.

UNIX:
On the COBOL system for UNIX, the search list initially has one entry for the standard C header directory /usr/include.

-J Change default for character type to unsigned
-K name Specifies that name should be recognized (and ignored) as a keyword. This option is useful for header files tailored for C compilers that are not covered by the -M and -O options.
-M Disables the Microsoft keywords that are normally recognized:

cdecl pascal _far _near
far _asm _fastcall _pascal
fortran _based _fortran _saveregs
huge _cdecl _huge _segment
interrupt _emit _interrupt _segname
near _export _loadds _self
__asm __far __loadds __segname
__based __fastcall __near __self
__cdecl __fortran __pascal __stdcall
__declspec __huge __saveregs
__export __inline __segment
-O Disables the IBM C (for OS/2) keywords that are normally recognized:

_Cdecl _Far32 _Optlink _Seg16
_Export _Fastcall _Packed _System
_Far16 _Inline _Pascal
-P Just preprocess the C, do not generate the COBOL copyfile.

This option is equivalent to the -C option but additionally suppresses COBOL generation. It is useful if you suspect that H2cpy preprocesses the C source differently to your C compiler.

-R name Add a COBOL reserved word to the dictionary

All current known reserved words are already built into H2cpy. This option enables you to add new ones.

-S Generate COBOL for #define macro definitions into a separate file. The filename will be based on the output filename but with any extension replaced by .78.
-V Generate COBOL variable numbers of parameters

The C language ellipsis (...) has no standard COBOL equivalent at present, so H2cpy ignores it. This option enables you to generate a provisional COBOL equivalent.

-X Extend the COBOL equivalence of string pointers from just char* to both char* and unsigned char*

An unsigned char* parameter to a function prototype will generate, by default, a BY REFERENCE uns-char. The type uns-char is numeric which is generally suitable except for header files, such as os2.h, that use the type unsigned char* to define string pointers. Use the -X option when converting such files so that H2cpy generates BY REFERENCE ANY and you can pass string parameters as PIC X(n) items.

-a type=n Set the alignment for C type, where type is one of: int, char, short, long, pointer, float, dfloat or dlfloat.

There are default alignments for all these C types (see the -e option). This option allows them to be varied individually.

-c Generate all names in COBOL in lower case

H2cpy generates the first occurrence of COBOL names to be as close to the original C names as possible. The case of each letter in the name is as in the original C.

-e n Target environment where n is 16 or 32 representing the two most common 16-bit and 32-bit environments. If this option is not specified, the default is 16 or 32 depending on the environment in which H2cpy is running.

The size and alignment of C types is dependent on the environment in which the code is to run. There are two common environments representing the PC (DOS, Windows or OS/2 V1.x) and larger (UNIX, OS/2 V2.x or Windows NT) machines. They are referred to as 16-bit and 32-bit environments, after the size of the C type int.

16-bit:
The 16-bit environment size and alignment for C types are:

char 1:1, short 2:2, int 2:2, long 4:2, pointer 4:2,
float 4:2, double float 8:2 or double long float 8:2.

32-bit:
The 32-bit environment size and alignment for C types are:

char 1:1, short 2:2, int 4:4, long 4:4, pointer 4:4,
float 4:4, double float 8:8 or double long float 8:8.

You can modify the default values using the #pragma pack directive in the C header file. See the section Translating Directives later in this chapter for details.

-f Pass #define floating point literals to COBOL

The COBOL Compiler validates the size and format of float literals. By default, if a #define specifies a macro as a floating constant, no COBOL is generated. Setting this option causes a COBOL equivalent to be generated; however, the COBOL Compiler may object to the size of the number.

If a floating constant is included in a constant expression and H2cpy evaluates that expression, then the floating constant is treated as zero and a warning given.

-h Convert hex #define value to decimal

By default, if a #define specifies a macro as a hexadecimal constant, H2cpy generates a COBOL hexadecimal constant. Setting this option causes H2cpy to generate the equivalent decimal value in the generated COBOL.

-o name Name the generated COBOL output file

By default, the names of the output files containing the generated COBOL are constructed from the basename of the first C header file, with extension .cpy for the main copyfile and .ext for the external declarations file. This option enables you to use an alternative name for the main file. The file containing generated external declarations always has the same basename as the main file.

-p Do not generate CALL prototypes

By default, H2cpy converts C function prototypes into COBOL CALL prototypes. The COBOL Compiler then ensures that any CALLs conform to the CALL prototypes. The checking for conformance is not always very flexible.

Set this option if you do not want H2cpy to generate CALL prototypes.

Beware of calls that pass a numeric literal (or level-78 item) as a parameter. The Compiler converts the item to COMP-5 format with the size being provided by the COBOL CALL prototype. If there is no CALL prototype present, then the default size of two bytes may be incorrect and the call may fail at run time. You must specify the correct size in bytes using the SIZE clause to the BY VALUE phrase in such cases.

-r Remove COBOL reserved word list

Use this option to reduce start-up time if you are not going to compile the generated COBOL.

-s type=n Set the size for C type where type is as for -a option
-v Toggle informational messages to screen on/off

This option switches the display of messages on the screen. Verbose mode displays the program banner and other messages, including a trace of nested #include files.

Silent mode displays only error messages. The default depends on your system:

UNIX:
The default on UNIX is silent mode.

DOS, Windows and OS/2:
The default on DOS, Windows and OS/2 is verbose mode.

12.2.1.2 Translating Names

H2cpy generally uses the same data and procedure names in the copyfile as in the original C header file. However, there are different standards in the way C and COBOL use names. H2cpy generates a new name if the following occur in the C file:

Some of these can be changed by setting the options available.

The new name generated by H2cpy is the old name with a number added to the front. The number is the number of synonyms encountered so far since the original name declaration.

12.2.1.3 Using the Headers Preprocessor

Running H2cpy from the command line is often most convenient when converting large C header files, when you wish to modify the generated copyfile or when you wish to use a variety of command line flags.

For simple header files it can be more convenient to reference the C header file directly from within your COBOL program and allow the Headers preprocessor to invoke H2cpy automatically each time the progam is compiled.

To use H2cpy in this way, simply include COPY statements that reference .h files within your COBOL program. There is no restriction on where the COPY statements can appear. In addition, ensure you use the directive PREPROCESS(headers). This can be done most conveniently in a $SET statement as in the following example:

$set preprocess(headers)
 working-storage section.
 01 data-item pic x(9).
     copy "cheader.h".
 01 cobol-b usage btype.
 procedure division.
     copy "cheader2.h".
     move 6 to c-long        of cobol-b
     move 7 to c-int         of cobol-b
     move "Show" to c-char   of cobol-b
     display "C struct= " c-long " " c-int " " c-char  level-78.

where cheader.h contains:

#define b B
int a;
typedef struct btype {
   long c_long;
   char c_char[5];
   int  c_int;
   } b;

where cheader2.h contains:

#ifdef b
#define level_78 "C literal"
#else
typedef struct btype {
   signed char c_uchar;
   float  c_float[5];
   } b;
#endif

and when run, the program displays:

C struct= +0000000006 +00007 Show C literal

12.2.1.4 Translating Directives

H2cpy translates the following types of directive: preprocessor, macro, conditional, #error, and #pragma.

Preprocessor Directives

H2cpy handles both #include and #define directives.

Translating #include Directives

H2cpy handles #include directives of the form:

#include <name>   where name can be a simple filename with extension, or a filename that includes a relative path.
#include "name"   where name can be a simple filename with extension, a filename that includes a relative path or a filename that includes an absolute path.
#include macro where macro expands to give one of the other two forms.

H2cpy looks for the named file, and reads the C source from that. When it reaches the end of the file, it resumes reading the original file.

You do not need to enter the absolute path for a file when you use the #include directive. If you enter a non-absolute filename in quotation marks (" "), H2cpy searches for the file in the current directory first, followed by each directory in the include search path list.

If you enter the filename within angle brackets (<>), the filename is assumed to be a system header file and only the include search path list is searched. The current directory is not searched.

The search path list contains from zero to fourteen absolute directory names. The file is searched for in each of the directories in turn until it is found or the search list is exhausted. If H2cpy still cannot find the file, you receive an error message.

You can add additional directories to the front of the search path list using the -I option described in the section Command-line Options.

DOS, Windows and OS/2:
On DOS, Windows and OS/2, the include search path list is initially empty. You can replace it by setting the INCLUDE environment variable to a list of up to fourteen search directories, separated by semicolons.

H2cpy assumes that the character that delimits directory-names in a path is the backslash (\). Any forward slashes (/) in the filename are converted to backslashes before the file is searched for.

For example, if you set the INCLUDE environment variable as follows:

include=d:\include;e:\sys\include

the directive:

#include <Xm/Xm.h>

causes H2cpy to look for d:\include\Xm\Xm.h. It then searches for e:\sys\include\Xm\Xm.h.

UNIX:
On UNIX, the include search path list initially has the one entry /usr/include. H2cpy assumes that the character that delimits directory-names in a path is the forward slash (/). Any backslash characters (\) in the filename are converted to forward slashes before the file is searched for.

For example, using the default path of /usr/include, the directive:

#include <Xm/Xm.h>

causes H2cpy to search for /usr/include/Xm/Xm.h only.

Translating #define Directives

H2cpy handles macros with parameters as well as those without parameters. It stores them and will expand them if the macro-name is encountered in the C source. A macro can contain any number of C tokens and in general will not be directly translatable to COBOL.

H2cpy translates the following macro definitions to COBOL level-78 items:

If H2cpy encounters a macro that has been defined before in both cases with identical C tokens, H2cpy ignores it. If the definitions are different, you receive an error message.

The #undef directive can be used to undefine a macro-name that may previously have been defined.

Example

C source:

#define _H_STDLIB 
#define XmNborderColor "borderColor"
#define CHAR_BIT 8
#define GMEM_MOVEABLE 0x2
#define GMEM_ZEROINIT 0x0040
#define GHND (GMEM_MOVEABLE | GMEM_ZEROINIT)
#define VisualAllMask 0x1ff
#define INT_MAX (2147483647)
#define INT_MIN (-(INT_MAX + 1))
#define Button5Mask (1<<12)
#define HFILE int
#define HFILE_ERROR ((HFILE)-1)
#define NULL ((void *)0)
#define brdev(x) (x&0x7fffffff)
#define XT_CONVERT_FAIL (Atom)0x80000001
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define FLT_MAX 3.402823466385288e+38f
#define NBPW sizeof(int)

COBOL output:

 78  XmNborderColor   value   "borderColor".
 78  CHAR-BIT         value   8.
 78  GMEM-MOVEABLE    value   h"02".
 78  GMEM-ZEROINIT    value   h"0040".
 78  GHND                             value   66.
 78  VisualAllMask    value   h"01ff".
 78  INT-MAX          value   2147483647.
 78  INT-MIN          value   -2147483648. 
 78  Button5Mask      value   4096.
 78  FLT-MAX          value   3.402823466385288e+38. 
 78  NBPW             value   4.

The COBOL code generated varies depending on the setting of options such as -f and -h.

Expanding Macros and Creating String Literals

H2cpy expands macros with parameters, using the string and concatenation operators # and ##. For example, the following #define directive:

#define DECLARE_HANDLE32(name) struct name##__ { int unused; }; \
     typedef const struct name##__ _far* name

produces no level-78 item, but if the C header then invokes the macro later, using:

DECLARE_HANDLE32(HHOOK);

it is expanded according to the rules for C and translated into the equivalent COBOL. COBOL does not provide typed pointers except for distinguishing between data and procedure pointers.

 01 HHOOK--         is typedef.
     02  unused                     usage int.
 01 HHOOK           is typedef      usage data-pointer.
Translating Conditional Directives

H2cpy interprets the following conditional directives, which can be nested:

#if     #else       #endif
#elif   #ifdef      #ifndef

The #if directive must be followed by a constant expression. Macros in the expression are expanded, the defined operator evaluated, unknown names replaced by zero and the resulting numeric expression evaluated to give a numeric value. If the result of evaluation of the expression is zero, then the condition is false; otherwise, it is true. If the condition is false, then the following lines are ignored; otherwise, they are translated.

The #else and #endif directives switch the sense and terminate the effect of the preceding #if, #ifdef or #ifndef directive.

The #elif directive is treated as equivalent to a #else directive followed by a #if directive, except that the nesting level is not increased and any following #endif directive applies to the preceding #if directive.

The #ifdef directive must be followed by a name. If the name has previously been defined, either in the header file or as a result of the -D option, then the condition is true; otherwise, it is false. If the condition is false, then following lines are ignored; otherwise, they are translated. The #ifndef directive is treated in the same way as the #ifdef directive except the sense of the condition is reversed.

Translating Other Directives

The #error directive may be followed by any comment on the directive line. If you have specified the -C option, H2cpy displays the entire line on the screen and lists it in the output file.

The #pragma directives are ignored, except for the Microsoft and IBM C pragma for packing structure or union members, which modifies the default alignments of C types. A directive of the form:

#pragma pack(n)

where the value of n is 1, 2 or 4, aligns any following structure or union members to 1,2 or 4-byte boundaries. The default alignments can be reinstated by a directive of the form:

#pragma pack()

The default alignments may be modified by the -e or -a options of the H2cpy command; see the section Command-line Options for details.

The pack pragma is ignored if both the -M and -O options of the H2cpy command are specified.

H2cpy ignores any other line which has a hash (#) character in the first character position.

12.2.1.5 Translating Statements

H2cpy translates the following statements: definitions and declarations.

H2cpy does not generate COBOL for any other C construct.

External Data Declarations

H2cpy ignores any data declaration it encounters unless it is defined as being external. If a C data declaration is defined as extern then H2cpy generates a COBOL declaration using the IS EXTERNAL phrase. If such an item is declared within a C module and the COBOL application can be linked to it (see your Object COBOL User Guide for details of linking), then the declaration allows the COBOL application to reference this C data item.

H2cpy generates all output into the .cpy file except for external data declarations which are output to a separate .ext file.

Example

C source:

typedef struct _WidgetClassRec *WidgetClass;
extern WidgetClass widgetClass;

COBOL output (to .cpy file):

 01  WidgetClass       is typedef       usage data-pointer.

COBOL output (to .ext file):

 01  1widgetClass      is external by "widgetClass"
                       usage data-pointer.

The names of the type definition and the external data item must be unique for COBOL which is why H2cpy has added a 1 to the front of the data-name. The symbolic name widgetClass is the name to be used by the Linker to resolve the reference to the external data item declared in C.

Type Definitions

H2cpy treats a character as a numeric item if it is explicitly declared as signed or unsigned. If declared as an array, H2cpy treats it as a COBOL alphanumeric item. Otherwise, H2cpy treats it as a numeric item. Two-dimensional arrays generate a COBOL OCCURS clause.

Arrays which have no array size are translated as if they were a pointer to the given type.

Pointers to any C data type are mapped to COBOL data pointers via a type definition. Pointers to a C function type are similarly mapped to COBOL procedure pointers.

Example

C source:

typedef char t_slab[12], cnt, c_list[], c_table[12][5];
typedef unsigned char BYTE, *BYTE_ptr;
typedef t_slab *t_slab_ptr;
typedef void _near _cdecl _export _dmsEVENT(short ent_type);
typedef _dmsEVENT *fptr;
typedef void (*XtActionProc)(
#if NeedFunctionPrototypes
    Widget      /* widget */,
    XEvent*     /* event */,
    String*     /* params */,
    Cardinal*       /* num_params */
#endif
);
typedef XtActionProc* XtBoundActions;

COBOL output:

 01  t-slab             is typedef  pic x(12).
 01  cnt                is typedef  usage char.
 01  c-list             is typedef  usage data-pointer.
 01  c-table            is typedef.
     02  filler occurs 12           pic x(5).
 01  BYTE               is typedef  usage uns-char.
 01  BYTE-ptr           is typedef  usage data-pointer.
 01  t-slab-ptr         is typedef  usage data-pointer.
 01  fptr               is typedef  usage proc-pointer.
 01  XtActionProc       is typedef  usage proc-pointer.
 01  XtBoundActions     is typedef  usage data-pointer.

Other type definitions generate similar COBOL type definitions. For example:

typedef signed int I, AI[12], *PI, I_Table[12] [5];

produces the following COBOL code:

 01  I              is typedef  usage int.
 01  AI             is typedef.
     02  filler occurs 12       usage int.
 01  PI             is typedef  usage data-pointer.
 01  I-Table        is typedef.
     02  filler occurs 5.
         03  filler occurs 12   usage int.
Declarations

Structure, union and enumerator declarations can be either named or unnamed. They can appear on their own or within type definitions or within structure or union declarations.

When a declaration is named, COBOL is generated in full for the item.

Example

C source:

typedef struct fsid { long val[2]; } fsid_t;
typedef unsigned long ino_t;  /* inode number (filesystem) */
typedef unsigned int  uint_t;
#define FHSIZE      32
#define MAXFIDSZ    (FHSIZE - sizeof(fsid_t) - sizeof(uint_t))
struct fileid {  /* this is for servers only! */
     uint_t  fid_len;
     ino_tfid_ino;
     uint_t  fid_gen;
     char fid_x[MAXFIDSZ - (sizeof(ino_t) + 2) -
                            sizeof(uint_t)];  };

COBOL output:

 01  fsid               is typedef.
     02  val occurs 2               usage long.
 01  fsid-t             is typedef  usage fsid.
 01  ino-t              is typedef  usage uns-long.
 01  uint-t             is typedef  usage uns-int.
 78  FHSIZE             value 32.
 78  MAXFIDSZ           value 28.
 01  fileid             is typedef.
     02  fid-len                    usage uns-int.
     02  filler                     pic x(2).
     02  fid-ino                    usage uns-long.
     02  fid-gen                    usage uns-int.
     02  fid-x                      pic x(14).

H2cpy ensures the correct alignment of the field fid-ino (which is a long, alignment 4) by inserting a two-byte FILLER item after the two-byte fid-len field.

The correct alignment is subject to the -e and -a options as well as the #pragma pack directive. The IBM C structure and union type _Packed is ignored.

When a declaration is unnamed, COBOL is generated in full only for the items that use it.

Example

C source:

typedef struct {
int type;
union {
    char b[20];
    short s[10];
    long l[5];
} data;
} XClientMessageEvent;

COBOL output:

 01  XClientMessageEventis typedef.
     02  type                           usage int.
     02  filler                         pic x(2).
     02  data.
         03  data.
             04  1b                     pic x(20).
         03  filler redefines data.
             04  s occurs 10            usage short.
         03  filler redefines data.
             04  l occurs 5             usage long.

H2cpy generates level-78 items for the named values for an enumeration type. Enumeration items can be named within structures; bit fields can also be specified within structures.

Example

C source:

enum input_type { GPICK = 0x0001, GANK= 0x0002, GPFK = 0x0004,
                FP_NOINBUF = 0x10000, FP_WTMAX = 0x20000 };
typedef struct qqel {           /* queue element*/
    enum input_type type;       /* enum input_type value */
    int time;               /* timestamp */
    struct {
        unsigned bad_data :1;       /* extra data io failed  */
        unsigned no_data  :1;       /* queue empty (for K_POLL) */
        unsigned reserved :6;       /* reserved  */
        char rsvd[3];               /* reserved  */
    } flags;
    int data_len;               /* length of appended data */
} q_qel;

COBOL output:

 01  input-type     is typedef      usage uns-int.
 78  gpick                          value   1.
 78  gank                           value   2.
 78  gpfk                           value   4.
 78  fp-noinbuf                     value   65536.
 78  fp-wtmax                       value   131072.
 01  qqel           is typedef.
     02  type                       usage input-type.
     02  time                       usage int.
     02  flags.
         03  bad-data.
             04  bad-data           usage uns-int.  *> 1 Bit
         03  filler redefines       bad-data.
             04  no-data            usage uns-int.  *> 1 Bit
         03  filler redefines       bad-data.
             04  reserved           usage uns-int.  *> 6 Bits
         03  rsvd                   pic x(3).
         03  filler                 pic x(1).
     02  data-len                   usage int.
 01  q-qel          is typedef      usage qqel.

The field rsvd is three bytes long. An assumption has been made that the preceding eight bits allocate one byte of storage. In fact, the ANSI C standard says that bitfields are within an int and so a 16-bit area will be allocated, requiring H2cpy to add a one-byte padding item on the end.

Function Prototype Declarations

C function prototypes must always return a type of item and must always pass at least one parameter. If no parameters are shown, then the function declaration is not a function prototype and H2cpy does not generate any COBOL CALL prototype. If no return type is shown, then the return type is assumed to be of type int.

If a function is not to return anything, then a function prototype uses a return type of void. H2cpy translates this, omitting any RETURNING clause. If a function is not to have any parameters, the function prototype will have one parameter of type void. H2cpy translates this by omitting the USING clause, together with any BY VALUE or BY REFERENCE clause.

Example

C source:

extern XFontStruct *XLoadQueryFont(
);
extern void XrmInitialize(
);
extern char *XFetchBytes(
);
extern int (*XSetAfterFunction(
))();
extern XtAppContext XtCreateApplicationContext(
void
);
extern void XtInitializeWidgetClass(
WidgetClass
);
XmColorProc XmGetColorCalculation(void);

COBOL output:

program-id. "c_typefefs" is external.
special-names.
    call-convention default-convention-val is defaultconv.
$set constant XtCreateApplicationContext "XtCreateApplicationContext"
 entry XtCreateApplicationContext default-conv
    returning           data-pinter
    .
$set constant XtInitializeWidgetClass "XtInitializeWidgetClass"
 entry XtInitializeWidgetClass default-conv using
    by value            data-pointer
    .
$set constant XmGetColorCalculation "XmGetColorCalculation"
 entry XmGetColorCalculation default-conv
    returning           proc-pointer
    .
end program "c_typedefs".

This output is slightly different to previous phases. The entry names are specified using constants rather than by literals, and the call conventions are specified by entries in the Special Names paragraph.

Calling Conventions

DOS, Windows and OS/2:
This section applies only to DOS, Windows and OS/2.

There may be more than one calling convention, distinguished in C by the keywords:

_cdecl
_Cdecl
_Fastcall
_Optlink
_pascal
_Pascal
_stdcall
_System

COBOL supports different calling conventions in the Special-Names paragraph which comes before the Procedure Division (see the chapter The COBOL Interfacing Environment for valid settings for CALL-CONVENTION). Where the calling convention for a CALL prototype changes from the previously used calling convention or where a type definition needs to be generated after CALL prototype has been generated, a new program needs to be declared. H2cpy generates an end-program record followed by a program-id record. If none of these keywords is specified for a function, COBOL is generated with the default C calling convention. The default COBOL values for the various C calling conventions can be modified using the -F command line option, or by manually editing the appropriate level-78 item in the translated copyfile.

Example

C source:

typedef HINSTANCE HMODULE;
DWORD _far _pascal GetVersion(void);
UINT _far _pascal GetFreeSystemResources(UINT);
#define GFSR_SYSTEMRESOURCES 0x0000
BOOL _far _pascal SetWinDebugInfo(const WINDEBUGINFO _far*
  lpwdi);
void _far _cdecl DebugOutput(UINT flags, LPCSTR lpsz, ...);
#define WDI_OPTIONS 0x0001

COBOL output:

 01  HMODULE              is typedef  usage uns-int.
 end program "c-typedefs".
 program-id. "c-typedefs" is external.
 special-names.
    call-convention pascal-convention-val is pascal-conv.
$set constant GetVersion "GetVersion"
 entry GetVersion pascal-conv
    returning           uns-long
    .
$set constant GetFreeSystemResources "GetFreeSystemResources"
 entry GetFreeSystemResources pascal-conv using
        by value        uns-int
    returning           uns-int
    .
 end program "c-typedefs".
 program-id. "c-typedefs" is external.
 special-names.
    call-convention pascal-convention-val is pascal-conv.
 78  GFSR-SYSTEMRESOURCES               value h"0000".
 end program "c-typedefs".
 program-id. "c-typedefs" is external.
 special-names.
    call-convention pascal-convention-val is pascal-conv.
$set constant SetWinDebugInfo "SetWinDebugInfo"
 entry SetWinDebugInfo pascal-conv using
        by reference    windebuginfo
    returning           int
    .
 end program "c-typedefs".
 program-id. "c-typedefs" is external.
 special-names.
    call-convention cdecl-convention-val is cdecl-conv.
$set constant DebugOutput "DebugOutput"
 entry DebugOutput cdecl-conv using
        by value        uns-int
        by reference    any
        by value        any
    .
 end program "c-typedefs".
 program-id. "c-typedefs" is external.
 special-names.
    call-convention cdecl-convention-val is cdecl-conv.
 78  WDI-OPTIONS                value h"0001".
 end program "c-typedefs".

H2cpy starts generating COBOL within the default external program c_typedefs which uses the default calling convention. The routine GetVersion uses the Pascal convention which is different, so H2cpy generates a header for a new external program containing a Procedure Division ENTRY statement. The routine GetFreeSystemResources uses the same calling convention so a second entry statement is generated with no need for a new program header. H2cpy then needs to generate a level-78 item in the Data Division, so it generates another program header. The routine DebugOutput uses the cdecl calling convention, so another program header is needed.

Call Parameters

C passes parameters, conceptually, via the stack. Parameters can be passed directly or indirectly via pointers. COBOL does not currently allow items greater than four bytes to be passed directly via the stack. It is considered bad C programming practice to pass structs or unions via the stack. If such items are greater than the size of a pointer (four bytes) it is also less efficient. The COBOL restriction will not normally cause any problem. If H2cpy encounters such code it adds additional parameters to ensure that the stack retains its integrity.

The simple C types such as int, char, pointer are easily mapped to COBOL. When passed directly as parameters on the stack, H2cpy generates a BY VALUE clause. But C also allows pointers to be typed as a means for indirectly passing parameters. COBOL also allows indirection, but only to one level. Where H2cpy encounters a typed pointer, it generates a BY REFERENCE clause.

Example

C source:

typedef unsigned char BYTE;
typedef char _far* LPSTR;
typedef int HFILE;
typedef Boolean (*XtFilePredicate)( /* String filename */ );
BYTE _far _pascal GetTempDrive(char);
long _far _pascal _llseek(HFILE, long, int);
long _far _pascal _hwrite(HFILE, const void _huge*, long);
LPSTR _far _pascal AnsiLower(LPSTR);
void _far _pascal Throw(const int _far*, int);
extern_pascal String XtFindFile(
    CONST String            /* path */,
    Substitution            /* substitutions */,
    Cardinal                /* num_substitutions */,
    XtFilePredicate     /* predicate */
);

COBOL output:

 01  BYTE               is typedef  usage uns-char.
 01  LPSTR              is typedef  usage data-pointer.
 01  HFILE              is typedef  usage int.
 01  XtFilePredicate    is typedef  usage proc-pointer.
 end program "c-typedefs".
 program-id. "c-typedefs" is external.
 special-names.
    call-convention pascal-convention-val is pascal-conv.
$set constant GetTempDrive "GetTempDrive"
 entry GetTempDrive pascal-conv using
        by value        char
    returning           uns-char
    .
$set constant 1-llseek "_llseek"
 entry 1-llseek pascal-conv using
        by value        int
        by value        long
        by value        int
    returning           long
    .
$set constant 1-hwrite "_hwrite"
 entry 1-hwrite pascal-conv using
        by value        int
        by value        data-pointer
        by value        long
    returning           long
    .
$set constant AnsiLower "AnsiLower"
 entry AnsiLower pascal-conv using
        by reference    any
    returning           data-pointer
    .
$set constant Throw "Throw"
 entry Throw pascal-conv using
        by reference    int
        by value        int
    .
 end program "c-typedefs".
 program-id. "c-typedefs" is external.
 special-names.
    call-convention default-convention-val is default-conv.
 end program "c-typedefs".
 program-id. "c-typedefs" is external.
 special-names.
    call-convention default-convention-val is default-conv.
$set constant XtFindFile "XtFindFile"
 entry XtFindFile default-conv using
        by reference    any
        by value        data-pointer
        by value        uns-int
        by value        proc-pointer
    returning           data-pointer.
    .
 end program "c-typedefs".

Notice in the routine _hwrite that a pointer to a void generates a data pointer passed by value. However, in the routine AnsiLower the type LPSTR which is a pointer to a character generates a BY REFERENCE clause with any parameter being allowed. A char would be too restrictive as normally any COBOL alphabetic item would be suitable. For this reason H2cpy generates any.

In the routine Throw, we have an int passed both BY VALUE and BY REFERENCE. In the routine XtFindFile, we pass a procedure pointer BY VALUE.

Example

C source:

typedef int (_far _pascal* FARPROC)();
typedef struct tagSEGINFO
{
    UINT offSegment;
    UINT cbSegment;
    UINT flags;
    UINT cbAlloc;
    HGLOBAL h;
    UINT alignShift;
    UINT reserved[2];
} SEGINFO;
typedef SEGINFO _far* LPSEGINFO;
typedef struct tagPOINT
{
    int x;
    int y;
} POINT;
void _far _pascal GetCodeInfo(FARPROC lpProc, SEGINFO _far*
                          lpSegInfo);
BOOL _far _pascal PtInRect(const RECT _far*, POINT);
void _far _pascal ClientToScreen(HWND, POINT _far*);

COBOL output:

 01  FARPROC            is typedef  usage proc-pointer.
 01  tagSEGINFO         is typedef.
     02  offsegment                 usage uns-int.
     02  cbsegment                  usage uns-int.
     02  flags                      usage uns-int.
     02  cballoc                    usage uns-int.
     02  h                          usage uns-int.
     02  alignshift                 usage uns-int.
     02  reserved occurs 2          usage uns-int.
 01  SEGINFO            is typedef  usage tagseginfo.
 01  LPSEGINFO          is typedef  usage data-pointer.
 01  tagPOINT           is typedef.
     02  x                          usage int.
     02  y                          usage int.
 01  POINT              is typedef  usage tagpoint.
 end program "c-typedefs".
 program-id. "c-typedefs" is external.
 special-names.
    call-convention pascal-convention-val is pascal-conv.
$set constant GetCodeInfo "GetCodeInfo"
 entry GetCodeInfo pascal-conv using
        by value        proc-pointer
        by reference    seginfo
    .
$set constant PtInRect "PtInRect"
 entry PtInRect pascal-conv using
        by reference    rect
        by value        point
    returning           int
    .
$set constant ClientToScreen "ClientToScreen"
 entry ClientToScreen pascal-conv using
        by value        uns-int
        by reference    point
    .
 end program "c-typedefs".

A parameter of data type POINT is passed both BY VALUE and BY REFERENCE.

Limitations

H2cpy stores macros with parameters for possible expansion later. If H2cpy encounters a macro with parameters and the macro definition extends over more than two or three physical lines, it may not have enough space to store all the macro details. This has no effect until H2cpy is called upon to expand that macro. If this happens, you get an error message.

If any problems occur with H2cpy not preprocessing a header file in the same way as the C compiler, this can be overcome by using the C compiler to just preprocess the header file and then use the preprocessed file as input to H2cpy.

Unlike COBOL, the C-language data types are not readily portable between environments. For this reason, H2cpy may need to be run more than once if you need to interface to the same library on different machines or operating systems.

H2cpy ignores the IBM C type _Packed rather than generating one-byte alignment for that structure or union. You will have to remove any filler items manually as necessary.

12.2.1.6 H2cpy Messages

H2cpy generates three types of message: information, warning and error. Information messages tell you what is happening. Warning messages mean that the translated code won't cause an error when compiled, but it may not produce the results you expect. Error messages mean there is something wrong, and the code will not compile correctly.


Note: H2cpy also produces several internal error messages. These are flagged as internal messages. You should not see these in normal operation. If you do receive one, please check that your C header file only contains valid ANSI C source code. If it is correct then contact your Technical Support representative.


12.2.1.6.1 Warning Messages

Warning messages are always preceded by an asterisk (*). They indicate that H2cpy has found some unusual C source which it cannot process for some reason and therefore ignores it. The ignored C source does not directly affect the generation or use of the COBOL copyfile but might possibly affect it indirectly or indicate that the C header is incorrect. H2cpy can generate the following messages.

* Warning, other return already defined for: name

Explanation:  A declaration for function name has been encountered in which the returned data type does not agree with a previous function prototype. The new declaration is ignored.

* Warning, float has been evaluated as zero

Explanation: A floating point literal has been encountered within a numeric expression. In evaluating the expression it has been replaced with the value zero.

* Warning, expression buffer overflow - ignored

Explanation:  A numeric expression has been encountered that is too large and complex for H2cpy to handle. It is ignored. You should check the C source to ensure the expression is not used within a C definition that requires translation into COBOL.

* Warning, macro too long, ignored: name

Explanation:  A definition for the macro name has been encountered that extends over several lines and is too large for H2cpy to handle. It is ignored. Generally it will not be referenced again within the header file and so will not affect the translation to COBOL.

* Warning, macro has too many parameters

Explanation:  A macro definition has been encountered that specifies many parameters. It is ignored. Generally it will not be referenced again within the header file and so will not affect the translation to COBOL.

* Warning, macro parameters too long - ignored

Explanation:  A macro definition has been encountered that specifies a very large parameter. The macro is ignored. Generally it will not be referenced again within the header file and so will not affect the translation to COBOL.

* Warning, neither whitespace nor ( after #define. Ignoring the line.

Explanation:  The C header file does not conform to the ANSI C specification as shown by an illegal use of #define. The offending line is ignored. Correct the C header file so that it conforms to ANSI C before using any translated COBOL code.

* Warning, redefinition ignored for #define

Explanation:  The C header file does not conform to the ANSI C specification as shown by an illegal use of #define to define a macro a second time in a non-identical way. The offending line is ignored. Correct the C header file so that it conforms to ANSI C before using any translated COBOL code.

* Warning, struct/union 4 bytes and passed by value cannot be directly accessed from COBOL

Explanation:  C allows data items greater than four bytes to be passed by value but the effects at run time are implementor dependent and so the items cannot be directly accessed from COBOL. This is considered by C programmers to be bad programming practice and indicates that the C header file should be modified.

12.2.1.6.2 Error Messages - Command Line Errors

Each of these messages mean that the command line given to H2cpy is invalid and translation has not taken place. The error must be corrected and H2cpy run again.

Error, command line too long

Explanation:  You have specified too much on the command line. Specify header filenames and macro declarations in a small C header file using #include "filename" and #define declaredname instead of putting filename or the -D declaredname option on the command line.

Error, no input C header file given

Explanation:  You forgot to name the input header file.

Error, too many input filenames

Explanation:  You have specified too many filenames on the command line. Create a C header and use #include for each filename.

Error, macro name already defined

Explanation:  You have given the same name in two -D options.

Error, exceeded max number of include directories, max=14

Explanation:  You have specified a -I option that causes the include search list to overflow. Reduce the number of -I options specified or the number of directories specified in the INCLUDE environment variable.

Error, unknown C type:name

Explanation:  You have given an incorrect parameter in a -a or -s option.

Error, no C type alignment value

Explanation:  You have given an incorrect parameter in a -a option.

Error, no C type size value

Explanation:  You have given an incorrect parameter in a -s option.

Error, no call convention value provided

Explanation:  You have given an incorrect parameter in the -F option.

Error, unknown environment (not 16 or 32)

Explanation:  You have given an incorrect parameter in a -e option.

Error, unknown option - flag

Explanation:  You have specified an incorrect flag letter.

12.2.1.6.3 Error Messages - Invalid C Source

Each of these messages mean that the C header file given as input to H2cpy is invalid and contains C source that does not conform to the ANSI specification. Translation has not taken place. You must modify the header file so that it contains only valid ANSI C before attempting to use H2cpy to translate it to COBOL. You must use C development tools with the correct C dialect checking enabled to determine the exact nature of the error .

Error, type expected, found name: name
Error, type expected
Error, typedef found at inner level; check brackets
Unexpected token token
Error, type expected
Error, type expected, found name
Error, no unique typedef name!
Error, already declared this name
Error, undeclared enum name
Error, already defined name: name
Error, already defined struct/union as: name
Error, other params already defined for : name
Error, declaration buffer overflow
Error, no unique declarator name!
Error, no unique parameter name!
Error, invalid C code (missing token)
Error, too many digits for 4 bytes in name
Error - ## not followed by correct token type
Error, mismatched brackets in #if line


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

PreviousInstallf Facility Application Configuration SystemNext"