Mixed-language Programming | Application Configuration System |
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.
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.
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__
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.
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:
These names match C keywords, possibly with one or more leading
underscore characters, except for |
||||||||||||||||||||||||||||||||||||||||||||
-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:
|
||||||||||||||||||||||||||||||||||||||||||||
-O | Disable the IBM C (for OS/2) keywords that are
normally recognized:
|
||||||||||||||||||||||||||||||||||||||||||||
-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 |
||||||||||||||||||||||||||||||||||||||||||||
-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 |
||||||||||||||||||||||||||||||||||||||||||||
-f | Pass #define floating point literals to
COBOL
The COBOL Compiler validates the size and format of floating point
literals. By default, if a 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 |
||||||||||||||||||||||||||||||||||||||||||||
-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 Silent mode displays only error messages. The default on UNIX is silent mode. |
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.
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
H2cpy translates the following types of directive: preprocessor, macro,
conditional, #error
, and #pragma.
H2cpy handles both #include
and #define
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.
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.
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.
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.
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.
H2cpy translates the following statements: definitions and declarations.
H2cpy does not generate COBOL for any other C construct.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Explanation: A floating point literal has been encountered within a numeric expression. In evaluating the expression it has been replaced with the value zero.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Explanation: You forgot to name the input header file.
Explanation:
You have specified too many filenames on the command line. Create a
C header and use #include
for each filename.
Explanation: You have given the same name in two -D options.
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.
Explanation: You have given an incorrect parameter in a -a or -s option.
Explanation: You have given an incorrect parameter in a -a option.
Explanation: You have given an incorrect parameter in a -s option.
Explanation: You have given an incorrect parameter in the -F option.
Explanation: You have given an incorrect parameter in a -e option.
Explanation: You have specified an incorrect flag letter.
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 .
Copyright © 2000 MERANT International Limited. All rights reserved.
This document and the proprietary marks and names
used herein are protected by international law.
Mixed-language Programming | Application Configuration System |