The H2SDL utility makes it possible to access C code declarations and definitions in SDL. A C code header file is translated into SDL-PR thus making the C code constructs available as if they were declared in SDL.
H2SDL is fully integrated in SDT. It can also be started from a command shell as a stand-alone utility to create SDL-PR packages.
This chapter is the reference manual for the H2SDL utility. The reader is assumed to be familiar with C and SDL/SDT.
The purpose of H2SDL is to provide a means of making external C functions, typedefs, etc. available inside SDL. H2SDL translates C header files and generates SDL packages.
H2SDL is fully integrated in SDT; the Analyzer starts the tool automatically when it finds a C header file in the Organizer.
H2SDL can also be run in stand-alone mode, i.e. started from a shell command line.
When translating from C to SDL, H2SDL follows a set of translation rules. These rules are described in detail in C to SDL Translation Rules. Although H2SDL supports translation of a major part of the C language, not everything is supported. The limitations of H2SDL are listed in H2SDL.
Figure 177 shows the input to and output from H2SDL.
Figure 177 : H2SDL input and output.
|
As can be seen in the figure, the input header file is first sent to a C preprocessor. The output from that is one single file, where all preprocessor directives such as #include
and #define
have been resolved and removed. This file is then translated by H2SDL to an SDL package.
H2SDL can be instructed to use any C preprocessor for preprocessing the header file. If no particular preprocessor is specified, H2SDL assumes a default preprocessor (cpp on UNIX and cl (Microsoft Visual C++) in Windows). It is then required that this default preprocessor is in the path or that there is a link to it in the directory from which H2SDL was started. Here are two examples of directories where cpp might be found:
/usr/ccs/lib/cpp /opt/lib/gcc-lib/sparc-sun-solaris2.5/2.7.2/cpp
(You might have another version of gcc, but the above gives you a clue where to look.)
From a shell command line H2SDL is invoked with:
sdth2sdl [options] <file>
In stand-alone mode all text output, such as error messages, version information etc., is directed to stderr
.
If nothing else is specified by options, H2SDL will save the generated SDL package in a file called headername_SDL.pr
, where headername is the name of the C header file. The output file will be placed in the same directory as the input file. The name of the SDL package will be untitled if nothing else is specified.
The H2SDL command-line options must be set for each input file. Only the -post
option differs from this, as described below. H2SDL has the following options:
-C <path>
Use the preprocessor specified by <path>
. Default is cpp on UNIX and cl in Windows.-O <options>
Pass the option string <options>
to the preprocessor. Note that option strings containing white spaces must be delimited with quotation marks ("). -a
-s
option described below, an arbitrary name can be set.-c
-C++
-e
Tell H2SDL to translate enum declarations to syntypes of integer. This was the translation rule used in Telelogic Tau version 3.3 and earlier, and this option exists for backward compatibility reasons only. Read more about how enums are translated in Enum Declarations.-h
-l
Do not use full path for the filename in the #C code generator directive (see Introduction for more information about the #C directive). This option could be useful if generated files are to be moved to another location later on.-n <packagename>
-p
-post
-post
at start-up. H2SDL will live until the PostMaster tells it to shut down.-r
-s <filename>
Set the output file name to <filename>
(may contain a path).
-v
or -version
Print version information. The version number is on the form "x.y.z". Note that the input file is preprocessed with three macros defined that, for example, can be used for #ifdef
directives: __H2SDL__=x
, __H2SDL_MINOR__=y
and __H2SDL_MINOR_MINOR=z
.-w
Show all warnings. H2SDL will warn about prefixing and suffixing of identifiers (see Modifying C Identifiers to Conform to SDL) only if this option is used.sdth2sdl -s Curses.pr -n CursePack -O "-I/include/h -D__STDC__" /usr/include/curses.h
This will generate the file Curses.pr
from the file /usr/include/curses.h
. The resulting SDL package will be named CursePack
and the options -I/include/h -D__STDC__
will be sent to the default C preprocessor.
When H2SDL is started automatically by the SDT Analyzer, the input are the C headers that are present in the Organizer view. For information on how to include C headers in your SDL system, see Organizing C Headers in SDT.
Each C header in the Organizer is translated to an SDL package according to the procedure depicted in Figure 177. The packages are then included in the finally generated SDL-PR file that is the input to the Analyzer.
Error messages and warnings produced by H2SDL during the translation are output to the Organizer Log.
Figure 178 shows the H2SDL Options dialog which is reached from the Organizer's Analyzer dialog. The dialog is used to set options for the preprocessor and for H2SDL.
Options to be passed to the preprocessor are entered in the field labelled Preprocessor options. This makes it for example possible to set include directories and defines for the included files.
Figure 178 : The H2SDL Options dialog
|
Assume we have the following files and libraries:
<some dir>/const.h /home/poh/my_incs/theincfile.h
The contents of const.h
which we want to include in our SDL system is:
#include "theincfile.h" #ifdef USE_Z typedef int zType; #endif
To make this work the preprocessor needs the full path to the directory containing theincfile.h
. Since we want to use the special type zType
we must set the define USE_Z
. We open the H2SDL Options dialog, turn on Preprocessor options (see Figure 178), and enter the following:
-I/home/poh/my_incs -DUSE_Z
Consult the manual for your preprocessor to find out how to set include directories and defines.
The other fields and toggle buttons of the H2SDL Options dialog are more or less self-explaining and correspond directly to the command-line options described in Command-Line Options:
-C
command-line option. If it is left empty, H2SDL will attempt to use the default preprocessor, which is cpp on UNIX and cl (Microsoft Visual C++) in Windows. -l
command-line option.-e
command-line option.-w
command-line option.References to declarations in the source files are on the form: /*#SDTREF(TEXT,relative_path_and_filename,lineno)*/
Where:
relative_path_and_filename
is the path and filename as input to H2SDL.lineno
is the starting line of this declaration.In stand-alone mode H2SDL generates source code references if the -r
option is used. When the Analyzer starts H2SDL, source code references are always generated.
Error references have the same form as source code references but with a column position added after the line number. H2SDL prints error references when errors (or warnings) are found during translation. They are output to stderr
or to the Organizer Log depending upon whether H2SDL is run in stand-alone mode or started automatically by the Analyzer.
A source code reference is shown in Example 40 below.
/*#SDTREF(TEXT,/usr/include/math.h,113) procedure acos; fpar fpar_0 Real; returns Real; external;
Problems with error references may arise because of the preprocessor. Among other things, the preprocessor expands macros, and a typical problem is illustrated in Example 41 below.
File def.h
, and using H2SDL as a stand-alone tool:
#define init init32 void init(undefdType *, int); % sdth2sdl -r def.h
This results in the following error message:
#SDTREF(TEXT,def.h,3,25) ERROR 3000 Syntax error in declaration void init32(undefdType *,?
Here the column position (25) is two characters off the target in the original file. When using the Organizer Log's Show Error function (see Show Error) to view the source of this error message, the cursor (?
) will be placed at int
instead of at the `,
'. H2SDL calculates its references from the preprocessed source code where init
is expanded to init32
. This leads to reference errors like the one described and can make macros a grievance for the H2SDL user in the same way as for many users of C debuggers.
H2SDL will translate a C header to SDL for use as a package in SDT. Example 42 below shows such a package. As can be seen, a /*#C `<filename>'*/
directive is inserted directly after the package name. Thereby the Analyzer is told that this is a special package with definitions imported from a C header file. This information is passed on to the C Code Generator to tell it not to generate code for the package. Instead the original header file is included in the generated C code, so in the final executable application it is actually the original C header that is used.
A C header file often includes other header files, and by means of the preprocessor H2SDL will generate code for the entire include tree. This is shown in Example 42 where the file test1.h
, which includes test2.h
, is translated with H2SDL.
File test1.h
:
#include "test2.h" /* This function returns myType which is defined in test2.h */ extern myType theFunction(void);
File test2.h
:
typedef int myType;
Let us now run H2SDL stand-alone on test1.h
:
% sdth2sdl -r test1.h
The resulting package untitled
includes the definitions from test2.h
and is saved to a file called test1_SDL.pr
:
/*#SDTREF(TEXT,test1.h)*/ use ctypes; package untitled; /*#C `test1.h' */ /*#SDTREF(TEXT,test2.h,1) syntype myType = Integer endsyntype; /*#SDTREF(TEXT,test1.h,5) procedure theFunction; returns myType; external; endpackage untitled;
In order to handle arrays declared in C, two new SDT specific generators have been defined in the package ctypes
:
/*------------------- CArray --------------------*/ /* Corresponds to C arrays */ /*-----------------------------------------------*/ GENERATOR CArray (CONSTANT Length, TYPE Itemsort) OPERATORS Modify! : CArray, Integer, Itemsort -> CArray; Extract! : CArray, Integer -> Itemsort; ENDGENERATOR CArray; /*-------------------- Ref ----------------------*/ /* Corresponds to C pointers */ /*-----------------------------------------------*/ GENERATOR Ref (TYPE Itemsort) LITERALS Null /*#OP(S)*/, Alloc /*#OP(H)*/; OPERATORS "*>" : Ref, ItemSort -> Ref; "*>" : Ref -> ItemSort; "&" : ItemSort -> Ref; /*#OP(SI)*/ make! : ItemSort -> Ref; "+" : Ref, Integer -> Ref; /*#OP(SI)*/ "-" : Ref, Integer -> Ref; /*#OP(SI)*/ Ref2VStar : Ref -> VoidStar; /*#OP(HP)*/ VStar2Ref : VoidStar -> Ref; /*#OP(HP)*/ Ref2VStarStar : Ref /*#REF*/ -> VoidStarStar;/*#OP(HP)*/ DEFAULT Null; /*#ADT() #INSTTYPE typedef #1 *#0; #INSTHEADING #define #(Null)() 0 #define #(Alloc)() yAll_#0() #define yAll_#0() (#0)XMALLOC(sizeof(##1),ySrtN_#0) #define #(Ref2VStar)(P) ((#(VoidStar))P) #define #(Ref2VStarStar)(P) ((#(VoidStarStar))P) #define #(VStar2Ref)(P) ((#0)P) */ ENDGENERATOR Ref; procedure Free /*#NAME `XXFREE'*/; fpar p VoidStarStar; external;
More information about ctypes
can be found in Integration with C Data Types.
The table below describes how basic C types map to SDL sorts. Many types in C have a natural counterpart in SDL, but for some special C types, such as void *
, dedicated SDL newtypes have been defined. These definitions can be found in the ctypes
package (see Integration with C Data Types.)
If the C header has been written exclusively for being combined with SDL, it is sometimes useful to be able to refer to SDL sorts directly from the C code. This can be done by preceding the SDL sort name with "SDL_
". For example, the "C type" SDL_PId
translates to the SDL sort PId
. All predefined SDL types can be accessed this way. See Predefined Sorts for a description of the predefined sorts in SDL.
The C type void
is a very special type that has no corresponding sort in SDL. The way H2SDL translates void
depends on the context, as shown in Example 43 below .
void
C header file:
void func1(int); /* No return value. */ char func2(void); /* No parameters. */ typedef void myvoid; myvoid func3(myvoid); /* No return value and no parameters.*/
procedure func1; fpar fpar_0 Integer; external; procedure func2; returns Character; external; procedure func3; external;
The following C operators are handled in expressions: *
, /
, %
, +
, -
, =
A constant expression can be any valid arithmetic expression consisting of the operators mentioned above, enumerators and integer expressions. Parenthesis, (
and )
, are allowed. Only hexadecimal and decimal constants are supported.
Due to the differences between the C language and SDL it is sometimes not possible to let an identifier in C keep its name when mapped to SDL. There are three reasons behind naming conflicts:
The first case may occur since C is a case sensitive language while SDL is not. These naming conflicts are resolved by adding a unique suffix to names that would be illegal in the SDL namespace. The rule is simple; the first version of a C identifier can keep its name in SDL, the second version is suffixed "_1", the third version is suffixed "_2" and so on. See Example 44.
The second and third case are handled by adding a prefix to the identifier's name in SDL. The rules are:
zz_CCod_
keyword. See Example 44._a__b
is prefixed and will be named zz_UScr_13_a_b
. "13" in the prefix means that the original identifier had an illegal underscore in the first and third position of the name. The numbers are calculated with charPos mod 10
. See Example 44.
If a C name that gets modified by H2SDL is to be accessed from SDL, the modified name must be used. The original name is included in the SDL declaration by means of a /*#NAME*/
directive. This directive tells the C Code Generator what name the identifier shall have in the generated C code.
typedef int INT; typedef int Int; INT ___signal(char *); Int signal(char *);
translates to:
syntype INT = Integer endsyntype; syntype Int_1 /*#NAME 'Int' */ = Integer endsyntype; procedure zz_UScr_123_signal /*#NAME '___signal' */; fpar fpar_0 CharStar; returns INT; external; procedure zz_CCod_signal /*#NAME 'signal' */; fpar fpar_0 CharStar; returns Int_1 /*#NAME 'Int' */; external;
If possible, try to avoid using names in the C header that will need to be modified by H2SDL. Names that need to be suffixed because of their capitalization are a particular problem since their names in SDL will depend upon the order in which they first appear in the C header file.
In stand-alone mode H2SDL can be run with the -w
option to get warnings for each name modification made by H2SDL. From SDT the same thing is accomplished by opening the H2SDL Options dialog and setting the option Display all warnings on (see Setting Options for the Preprocessor and H2SDL).
The table below shows how type declarations in C are translated to SDL. <type>
can be substituted for any C type except for void
. It can also be a typedef name. <SDLtype>
is the translation of <type>
as listed in the type translation table in Basic Type Mapping.
Note that the SDT generator CArray
takes two arguments; an integer for the number of array elements followed by an SDL type.
In the example typedef <type> *T[20];
the array consists of pointers to <type>
. In C this kind of compound declarations can be written in a very compact way on one single line. However, the declaration is in fact two declarations in one; a declaration of type T1 that is a pointer to <type>
, and a declaration of type T2 that is an array of elements of type T1. The type T1 is called an in-line type. SDL has no in-line types, so for such C declarations H2SDL actually must generate SDL declarations for the in-line types. These declarations are marked with a /*#SYNT*/
directive which informs the C Code Generator that this type has been synthesized by H2SDL.
Synthesized types are named by H2SDL as follows:
Ref_<filename>_<SDLType>
<filename>
is the name of the header file, and is included to guarantee that the type gets a name that will be unique when several packages are used simultaneously.
CA_<filename>_<numElements>_X_<SDLtype>
Indicates that the type corresponds to a C array type. Note that the number of array elements (<numElements>
) is included in the name.
MA_<filename>_<number>
If multiple arrays were to be named according to the rule above, it would be easy to get extremely long type names. Therefore, if the type name has more than 41 characters, a syntype with this name is generated. <number>
is a suffix to make the entire type name unique.
Enum_<tag>
enum <tag>.
These are translated to a syntype with this name.
Struct_<tag>
A syntype name corresponding to the C type struct <tag>
.
Union_<tag>
A syntype name corresponding to the C type union <tag>
.
DE_<filename>_<number>
Syntypes for in-line declared enums get this name. <number>
is a suffix to make the entire type name unique. (DE = Dummy Enum).
DS_<filename>_<number>
Syntypes for in-line declared structs get this name. <number>
is a suffix to make the entire type name unique. (DS = Dummy Struct).
DU_<filename>_<number>
Syntypes for in-line declared unions get this name. <number>
is a suffix to make the entire type name unique. (DU = Dummy Union). Example 45 below is an example of a common situation where H2SDL must create a dummy struct for the in-line declared struct variable aStructVar
. The in-line declared struct translated to SDL is named DS_test_0
, where test
is the name of the file and 0
is a number to make the entire type name unique.
C header test.h
:
typedef struct PId_Type { struct { int a,b; } aStructVar; } PId_Type;
translates to:
/*#SDTREF(TEXT,test)*/ use ctypes; package test; /*#C 'test' */ /* Global #defines */ /*#CODE #TYPE #define #(PId_Type)_s PId_Type */ newtype DS_test_0 /*#SYNTNN*/ struct a Integer; b Integer; endnewtype DS_test_0; newtype PId_Type struct aStructVar DS_test_0; endnewtype PId_Type; syntype Struct_PId_Type /*#SYNT*/ = PId_Type endsyntype; endpackage test;
As can be seen in the example, a special synthesize directive called /*#SYNTNN*/
is used for the in-line declared struct type. This directive is used instead of /*#SYNT*/
when the in-line declared type has no complete name (NN = No Name).
The following storage class specifiers are supported for variables:
typedef
extern
static
Variables without explicit storage class, e.g. int a;
, are also handled.
Except for typedef
, all declarations with the supported storage classes will be translated according to the same rule:
<SDLtype>
is the translation of <type>
as listed in the type translation table in Basic Type Mapping. If <type>
is an in-line type, synthesized types will be created as needed. H2SDL automatically creates C #define
s to provide a method of accessing the variable. When variable declarations appear in the following sections, the C code part is skipped and only the Get_
and Set_
procedure declarations are shown in order to save space.
H2SDL supports two different translation rules for enum declarations. If the -e
option is used (see Setting Options for the Preprocessor and H2SDL and Command-Line Options to see how this is done), enum literals will be translated to integer synonyms, and enum types will become syntypes of integer. See Example 46.
-e
option typedef enum tag{a, b} Etype;
translates to:
syntype Etype = Integer endsyntype; syntype Enum_tag /*#SYNT*/ = Etype endsyntype; synonym a Etype = 0; synonym b Etype = 1;
This translation rule is present for backward compatibility reasons only. It should normally be avoided, since some target compilers give errors due to implicit type conversions from integer to enum that arise when compiling the resulting C code.
Use the default translation rule instead that maps enum declarations to newtypes with literals, as described in the table below.
Note that enum tags are prefixed with Enum_
when translated to SDL since SDL has no tag concept like C does.
An enum literal can be set to the value of any constant expression. Currently only hexadecimal and decimal constants are supported.
Struct declarations are translated to SDL structs according to the table below. <SDLtype>
is the translation of <type>
as listed in the type translation table in Basic Type Mapping.
Note that struct tags are prefixed with Struct_
when translated to SDL since SDL has no tag concept like C does.
Union declarations are translated according to the same translation rules as for structs. The only difference is that a /*#UNIONC*/
directive is inserted after the newtype name. This directive informs the C Code Generator that the type corresponds to a proper C union. <SDLtype>
is the translation of <type>
as listed in the type translation table in Basic Type Mapping.
Note that union tags are prefixed with Union_
when translated to SDL since SDL has no tag concept like C does.
H2SDL will translate all unions to SDL, but unions containing pointers or bitfields will not be accepted by the C Code Generator. See UnionC for more information.
A bitfield is a struct or union member consisting of a specified number of bits. The size of a bitfield is set by a constant expression. An example is given in Example 47 below.
typedef struct{ int a:4; unsigned int b:7; } B;
translates to:
newtype B struct a Integer:4; b UnsignedInt:7; endnewtype B;
The bitfields in the generated SDL code are SDT specific and are described in detail in Struct.
Once again note that although H2SDL will generate code for bitfields in unions, the C Code Generator does not support this feature.
In C two different kinds of function declarations can be used; old-style function declarations and function declarations with prototypes. An old-style function declaration (also known as a Kernighan & Ritchie declaration) is on the form resulttype functionname ();
and does not give any information at all about the function's parameters. H2SDL therefore only supports function declarations with prototypes.
Function translation to SDL is not affected by the linkage type of the function. Functions are translated in the same way whether they are declared with external linkage or not. In the table below, <type>
can be substituted for any C type, in-line type or typedef type. <SDLtype>
is the translation of <type>
as listed in the type translation table in Basic Type Mapping.
Note that function parameters without name will be named fpar_x
, where x
is a number starting on 0 and increasing.
A C function declaration with a varying number of parameters, i.e. its parameter list ends with an ellipsis notation (...)
, will be translated as shown below.
C | SDL |
---|---|
<type> func(<type> a, ...); |
procedure func; fpar a <SDLtype>; /*#C_ELLIPSIS*/ returns <SDLtype>; external; |
The directive /*#C_ELLIPSIS*/
is a place-holder for the ellipsis notation since SDL has no ellipsis concept. Example 48 below suggests how C functions with a varying number of parameters can be used from SDT.
printf()
, which is included in stdio.h
, is a typical example of a function which can be called with a varying number of arguments of different types. A wrapper file can be used to tailor special versions of printf()
to be called from SDT.
File wrap.h
:
#ifdef __H2SDL__ /* __H2SDL__ is defined when the file is preprocessed*/ extern int printf1(const char *, int); extern int printf2(const char *, int, int); #else #define printf1 printf #define printf2 printf #include <stdio.h> #endif
The resulting SDL file is:
/*#SDTREF(TEXT,wrap.h)*/ use ctypes; package wrap; /*#C `wrap.h' */ procedure printf1; fpar fpar_0 CharStar, fpar_1 Integer; returns Integer; external; procedure printf2; fpar fpar_0 CharStar, fpar_1 Integer, fpar_2 Integer; returns Integer; external; endpackage wrap;
The procedures printf1
and printf2
are now available in SDL. When compiled and linked the calls will be to printf()
with one or two integer arguments.
Constants are translated to external SDL synonyms. <SDLtype>
is the translation of <type>
as listed in the type translation table in Basic Type Mapping.
C | SDL |
---|---|
const <type> a = <expression>; |
synonym a <SDLtype> = external; |
Note that constants specified with macros (e.g. #define MIL 1000
) will not be translated by H2SDL since they are expanded and removed by the preprocessor before H2SDL sees them. Nevertheless it is possible to access such macro values from SDL by means of the implicit #CODE operator (see Including C Code in SDL Expressions -- Operator #CODE for more information about the #CODE operator). Example 49 below demonstrates how to do this.
File macrotest.h
:
#define MIL 1000
The macro MIL
may be accessed from SDL using the #CODE operator:
DCL m Integer; TASK m := #CODE(`MIL');
Naturally, this SDL assignment will be accepted by the Analyzer no matter how MIL actually is defined. Any type problems will not be detected until the generated C code is compiled.
Other techniques for dealing with macros are described in the section When the Built-in Translation Rules Fail.
When H2SDL finds an error it will issue an error message which is sent to the Organizer Log, or to stderr
(in stand-alone mode).
Please note that H2SDL will cascade error messages and continue until it finds the end of the file. This can lead to strange results; an error in a struct declaration will probably lead to struct members being declared in an erroneous scope in the translation file.
The listing below explains all errors and warnings that may be issued by H2SDL:
ERROR 3000 Syntax error in declaration
The C code in the header file contains a syntax error.
ERROR 3101 Typedef functions not supported!
An attempt to declare a typedef function was made. Typedef functions are not supported by H2SDL since there is no translation rule for them.
ERROR 3102 Symbol redefined: <name>
A symbol called <name>
was redefined. The symbol could be for example an enum literal or a variable.
WARNING 3103 Operator sizeof does not know size of this type
The sizeof()
operator is not fully supported by H2SDL; it currently only works for predefined C types. This warning informs that H2SDL has made the assumption that the size of the type is 1.
WARNING 3104 Operator sizeof cannot calculate size of this expression
The sizeof()
operator is not fully supported by H2SDL; it currently only works for predefined C types. This warning informs that H2SDL has made the assumption that the size of the expression is 1.
ERROR 3107 Typedef name redefined: <typename>
A typedef name called <typename>
was redefined. This means that the C code contains two declarations on the form typedef <typeX> <typename>;
where the second of these makes an illegal redefinition of <typename>
.
ERROR 3108 Typedef declaration with only one identifier
H2SDL found a declaration on the form typedef
<typename>;
. The base type is missing.
ERROR 3109 Declaration with keyword struct/union missing
An attempt to declare an aggregate type was made, but the keyword struct
or union
is missing.
ERROR 3110 Kernighan & Ritchie function declarations not supported
H2SDL does not support old-style function declarations (Kernighan & Ritchie function declarations). Rewrite it using function prototypes.
WARNING 3113 Function pointer will be replaced by VoidStar
H2SDL has found a function pointer type that will be mapped to the SDL type VoidStar
. This warning is issued for variables of function pointer type, typedef declarations of a function pointer type, and struct/union declarations with fields of function pointer type. The reason for warning is that the mapping requires that the target compiler is able to do certain implicit type conversions, e.g. from a function pointer to a pointer to void.
WARNING 3114 Symbol <name> is not legal in SDL namespace. Will be named: <SDLname>
This warning informs that H2SDL had to modify <name>
to be legal according to SDL naming rules. <name>
either was not unique by spelling, was an SDL reserved word, or contained an illegal combination of underscores. The symbol will be renamed to <SDLname>
.
WARNING 3115 Possibly illegal redeclaration of identifier: <name>. Declaration ignored.
H2SDL has found a variable or function called <name>
that was already declared. This is legal in C if the declarations have exactly the same types. H2SDL does not perform any type checks, but assumes that the redeclaration is legal and simply ignores it. However, a warning is issued to inform that the header file might contain an error.
After finding an error H2SDL is reset and tries to continue the translation. This will in most cases result in a cascade of translation errors and error messages since the proper scope was lost, typedef names were never declared and so on.
A few of the most common errors are discussed in the examples below.
typedef unknownType (*fnPtr)(struct sTag *, void *args); struct sTag { fnPtr *aPtr; int aVar; };
The code segment above results in the following error messages:
#SDTREF(TEXT,try.h,10,24) ERROR 3000 Syntax error in declaration typedef unknownType (*fnPtr)(? #SDTREF(TEXT,try.h,13,8) ERROR 3000 Syntax error in declaration fnPtr *? #SDTREF(TEXT,try.h,15,1) ERROR 3000 Syntax error in declaration }?
The first error message is caused by unknownType
which for some reason is undeclared. The second error message is caused by fnPtr
never being defined because of the error in the fnPtr
typedef declaration. The third error message is caused by the fact that after the second error H2SDL resets its scope level. The `};
' is thus considered to be a declaration on its own, and not the end of the struct declaration.
The following is written to the SDL-PR output file:
/*#SDTREF(TEXT,try.h,14) procedure Set_aVar; fpar setVal Integer; external; procedure Get_aVar; returns Integer; external; /*#CODE #HEADING #define Set_aVar(i) (aVar = (i)) #define Get_aVar() (aVar) */
aVar
is translated as if it was a global variable because the struct scope was lost in the second error.
Example 51 below is basically the same problem as Example 50 above.
typedef struct A_Tag { unknownType Class; } A_StructType;
H2SDL will print the following error messages:
#SDTREF(TEXT,function1.h,55,24) ERROR 3000 Syntax error in declaration unknownType Class? #SDTREF(TEXT,function1.h,56,1) ERROR 3000 Syntax error in declaration }?
Here unknownType
gives rise to error messages which may be hard to understand. The first message is the result of the H2SDL parser treating the unknownType
as an identifier. Thus H2SDL thinks it sees two identifiers on line 2, which would not be a valid C statement. In this case it would be easy to interpret the error as if it was caused by the identifier Class
.
The second message is issued because the parser is reset after the first error is found. When it continues, a `}'
is found which, of course, is not a valid C statement either.
Errors like these will occur when unknownType
is undeclared. This, in turn, happens when the declaration of unknownType
contains constructs not supported by H2SDL, for example a typedef function. Worth noting is that translation errors inside structs will result in one syntax error for every right curly brace, `}'
, belonging to the erroneous struct.