PreviousMixed-language Programming 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, such as those for Motif.

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 and 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 statement within a COBOL source file. The preprocessor recognizes these as C headers and uses H2cpy to convert them. This can be very convenient for relatively small header files.

If you regularly use a group of command line options, you can add them all together as a named group of options. See the -G option for more details.

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 description of the -e command line option in the section Command-line Options.

       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.

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 Invoking H2cpy

To invoke H2cpy, enter the command line:

h2cpy { [filename] [option] } ... 

where the parameters are:

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

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

12.2.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.

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 Remove 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 Embed 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 prototypes, 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.

-G name
Use the group of options specified under the section label [name] in the h2cpy.dir file. If name is not specified, the group of options specified under the section label [default] is used. If the -G option appears in a h2cpy.dir file, it can only appear on the line following the section label, and cannot reference a preceding section label.

H2cpy searches for h2cpy.dir files in turn, first in the current directory and then $COBDIR. If there is a file in each location, the entries are concatenated. If no h2cpy.dir file is found, the effect is the same as an empty h2cpy.dir file. If name is found and silent mode is disabled (see the -v option), then H2cpy displays name and its location.

h2cpy.dir is a text file that comprises one or more sections that begin with a section header and end at the next section header or end of file. A section starts with a section header that comprises the group name enclosed between parentheses [], followed by zero or more lines of command-line options. The section header must start in column 1 and contain no spaces.

-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.

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 Specify that name is 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 Disable 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 Disable the IBM C (for OS/2) keywords that are normally recognized:

_Cdecl _Far32 _Optlink _Seg16
_Export _Fastcall _Packed _System
_Far16 _Inline _Pascal
-P Only preprocess the C and 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 Do not generate COBOL variable numbers of parameters.
-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, llong, 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 one of: lp32, ilp32, llp64, lp64, ilp64. If this option is not specified, the default is set to the one most appropriate for the COBOL system in the H2CPY executable environment.

The names comprise the letters i for int, l for long, ll for long-long and p for pointer, together with the size of these types in bytes. By implication, types not referenced in the name have a smaller size. For example, the environment lp32 supports 16-bit ints and 32-bit longs and pointers; the environment llp64 supports 32-bit ints and longs and 64-bit long-longs and pointers. Not all environments support the non-standard type long-long.

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, and are represented by lp32 and ilp32 respectively (in previous products use lp16 and ilp32 respectively, and these are still recognised. UNIX processors are available that support various 64-bit environments, and these are represented by lp64, llp64 and ilp64.

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 floating point literals. By default, if a #define specifies a macro as a floating point literal, 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 point literal is included in a constant expression and H2cpy evaluates that expression, then the floating point literal is treated as zero and a warning given.

-h Convert hexadecimal #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 and 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 on UNIX is silent mode.

12.2.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.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 program 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.4 Translating Directives

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

12.2.4.1 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.

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 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.

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 expands 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.

12.2.4.2 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.

12.2.4.3 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 the 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.

12.2.4.4 Translating Other Directives

The #error directive can 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.5 Translating Statements

H2cpy translates the following statements: definitions and declarations.

H2cpy does not generate COBOL for any other C construct.

12.2.5.1 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 Server Express User's 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.

12.2.5.2 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.

12.2.5.3 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 bit-fields 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.

12.2.5.4 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 
$set                            "XtCreateApplicationContext"
 entry XtCreateApplicationContext default-conv
    returning           data-pinter
    .
$set constant XtInitializeWidgetClass 
$set                               "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".

The entry names are specified using constants rather than by literals, and the call conventions are specified by entries in the Special Names paragraph.

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 
$set                                "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.

12.2.5.5 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.

12.2.5.6 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.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.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. 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 too 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 (or 8) and passed by value cannot be directly accessed from COBOL

Explanation:  On 32-bit systems, 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. On 64-bit systems, the limit is eight bytes rather than four.

12.2.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 LP32, ILP32, LLP64, LP64 or ILP64)

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.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 © 2000 MERANT International Limited. All rights reserved.
This document and the proprietary marks and names used herein are protected by international law.

PreviousMixed-language Programming Application Configuration SystemNext