home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 44
/
Amiga_Dream_44.iso
/
RiscPc
/
programmation
/
headerg.zi
/
HeaderGen
/
Doc
< prev
next >
Wrap
Text File
|
1996-02-07
|
11KB
|
284 lines
HeaderGen 1.10
Documentation
____________________________________________________________________________________
HeaderGen is a coding tool for use with Acorn ANSI C and ObjAsm.
HeaderGen is (c) Frank F÷hl. This version is PD and may be copied freely, as long as
all files are included and unaltered.
Å Purpose:
Generate header files of C and Assembler source files, and generate C headers from
Assembler sources as well as Assembler headers from C headers.
Å Syntax:
HeaderGen -CtoC [keyword args] <C source> <C header>
HeaderGen -ASMtoASM [keyword args] <ASM source> <ASM header>
HeaderGen -ASMtoC [keyword args] <ASM source> <C header>
HeaderGen -CtoASM [keyword args] <C header> <ASM header>
Keyword options:
-ExtIdent <string> Use <string> to identify external labels (with -ASMtoASM,-ASMtoC)
or to identify external functions/variables (with -CtoC, -CtoASM)
-I <dir>[,<dir>...] Include <dir>s on the include file search path (with -CtoASM)
-via <file> Read extra command line parameters from <file>
Å Limitations and known bugs
Parsing of C source files is not perfect (I haven't bothered to look up the syntax
diagrams), but I think it's now fairly sufficient. If anything goes wrong with
parsing C sources you will get errors or warnings from HeaderGen, as usual.
Bitfields are not supported.
It's possible in C, when declaring variables, to omit a type definition when a
storage class is given, eg. to write "static counter;", where, I suppose, an "int"
is assumed as default. HeaderGen can't cope with this, the type must be given.
(There may be further such obscure abbreviations that aren't handled properly.)
Most preprocessor statements are ignored, only the #include's and #define's are
recognized with the -CtoASM action (see below), the #define's only to a limited
degree.
HeaderGen has no C++ support, but it parses '#ifdef __cplusplus' lines and ignores
the contents of these conditional blocks.
HeaderGen -CtoASM parses all Clib and RISC_OSlib headers fine, with the exceptions
'kernel.h' (because a bitfield is used, urghh)
'signal.h' (hopelessly cryptic function pointer)
'colourpick.h' (silly bracketing)
The length of the words and low level syntax structures scanned in the input files
is limited to 2048 characters, so there might be problems with very long explicit
character strings for example. You'll get a 'word overflow' error if this occurs.
The number of words in a via-file is limited to 2048.
Å How to use HeaderGen
All four actions have in common that the generated code is appended to the target
file immediately after the first occurrence of the sequence '/* Auto */' (in C files)
or '; Auto' (in ASM files), deleting everything following it. If the sequence is not
found in the file, then it will be appended along with the generated code. The header
file is generated if it isn't already there.
As there are a few serious limitations with parsing C sources, a method has been
implemented to prevent critical sections of code from being parsed by HeaderGen.
You can disable parsing by writing
#define __headergen_stop
end re-enable parsing by writing
#define __headergen_start
in a C source file. These statements act simply as markers for HeaderGen's scanner.
Note that you don't have to write '#define __headergen_start' at the beginning, the
entire file will be parsed by default.
The makefile skeleton shows how HeaderGen can be effectively incorporated into
makefiles.
The following sections describe the four actions in detail.
HeaderGen -CtoC
===============
generates prototypes of external functions and variables and appends them to the
named C header. This is similar to Zap's MJE_GENERATEHEADER function, however,
unlike Zap, HeaderGen can also handle external variables.
Functions and global variables are considered to be external if they contain the
'ExtIdent' string (see keyword options). This is to allow for global objects that are
only visible within the program module where they are defined. The default ExtIdent
string is the empty string, which will match any global symbol. If you wish to use
this feature, then I'd recommend using the name of the program module as ExtIdent
string, as shown in the sample makefile. You can then use this string as a prefix of
your external symbols.
Å One little problem with -CtoC
If you declare a (comma-separated) list of global variables of the same type, the
ExtIdent string will only be checked against the first variable name. According to
the result, the whole list is either 'extern'ed or not. If this causes inconvenience,
split the list up into single <type> <var>; declarations.
HeaderGen -ASMtoASM
===================
appends all external labels defined in the ASM source to the ASM header, each preceded
by an IMPORT/EXPORT directive. The directive is implemented as an Asm variable which
is defined at the beginning of the header. This variable expands to 'EXPORT' if the
Asm variable __<file>_s has already been defined, to 'IMPORT' otherwise, where <file>
is the name of the program module. You need to write a 'GBLA __file_s' in every source
file, before it 'GET's its own header, for the header to 'know' whether it is supposed
to IMPORT or to EXPORT the external labels. They are EXPORTed when the header is
included from its own source file, IMPORTed otherwise.
Consequently, you don't need to worry about importing or exporting externals, just
sign your external labels as external, include the ASM header into its own source file
and into any source file where the externals shall be visible, and everything's ok.
Labels found in the source file are considered to be external if they contain the
ExtIdent string.
If additional 'EXPORT <label>' statements are present in the Asm source, then the
corresponding 'IMPORT's will be appended to the header, regardless of the ExtIdent
string, so even if you don't wish to use an external identifier string, you can still
use -ASMtoASM. In this case you should disactivate the externals identification by
using "-ExtIdent @@@" or something, thus no labels will automatically be considered as
external.
$-prefixed symbols and lines with Asm directives are ignored by this operation.
HeaderGen -ASMtoC
=================
appends all external labels to the C header, preceded by 'extern'. A label is
considered to be external, either if it contains the ExtIdent string or if it is
explicitly EXPORTed.
If there's a comment of the form '; (<type>)' following the label, then <type> is
considered to be the type of the object at the label's address. The default type
is 'int'. If a comment of the form '; (<type>) (<arg0>,,,<argN>)' is found, then the
label is converted to a function prototype with the given type and argument list, eg:
this is converted to this
-------------------------------------------|------------------------------------------
counter DCD 0 ; (int) | extern int counter;
|
DotPlot ; (void) (int x,int y) | extern void DotPlot(int x,int y);
|
EXPORT DrawLine ; (void) (void) | extern void DrawLine(void);
|
Note that when 'EXPORT' is used, the (type) and (arg list) comments must follow the
'EXPORT' statement, and NOT be in the label definition line!
Storage areas, data structures and ASM directives are ignored. If you want to declare
constants, or lay out data structures, then do it in a C header (that's the point of
the entire program, BTW ;-)
HeaderGen -CtoASM
=================
This is the most complex action. It is used to convert all 'typedef', 'struct',
'union' and 'enum' definitions and (to a limited degree) macro definitions within a
C header into appropriate ASM code. It also IMPORTs all functions and variables that
are signed as external in the C header.
The program recognizes enum/struct/union templates as well as typedefs. The templates
are referred to in the ASM code with the prefixes 'struct_' or 'union_' or 'enum_'
to avoid ambiguity. All 'typedef'd structures are laid out explicitly in Asm code,
and all non-anonymous 'struct' templates as well, for example the C code
typedef struct { int a,b; } dummy;
will generate the Asm code:
^ 0 ; structure 'dummy'
|dummy.a| # 4
|dummy.b| # 4
dummy * 8
but the C statements
typedef struct dummy0 dummy;
struct dummy0 { int a,b; };
will generate two Asm structures, one for the struct template 'dummy0', and one for
the typedef'd type 'dummy':
^ 0 ; structure 'struct_dummy0'
|struct_dummy0.a| # 4
|struct_dummy0.b| # 4
struct_dummy0 * 8
^ 0 ; structure 'dummy'
|dummy.a| # 4
|dummy.b| # 4
dummy * 8
Structure members are aligned correctly, ie char's are byte-aligned, short int's
are half-word-aligned and all the rest is word-aligned. Alignment gaps are inserted
into the ASM structure code as appropriate. The size of structures is correctly
rounded up to integers.
The members of enumerated data types may optionally have an expression assigned,
which may contain hex and decimal integers and the operators + - * / % << >>.
Union members are not converted (as their offsets are all zero, if I've got it right).
Thus the size of a union is declared as the maximum of its members' sizes.
The program tries to follow any '#include' directive present in the C header. All
secondary headers are parsed, but only the main file's code is converted to Asm code.
The secondary headers are looked for in the root directory, the work directory and in
the directories specified by the '-I' arguments. Every header is included only once.
Å Macro Conversion
Numerical definition macros such as
#define no 100
#define product (10*no/2)
are recognized and converted. The expression may contain hex and decimal integers
and the operators + - * / % << >>. However things like
#define size (10*sizeof(int))
#define BOOL int
won't do. In the latter case, a 'typedef int BOOL;' will do the job, or just replace
the 'BOOL's by 'int's within the type definition header.
The program can also handle string definition macros such as
#define text "some text"
which will be converted into an Asm string variable.
All function and expression macros are ignored.
Macros are recognized as array dimensions (relevant when converting array typedefs,
for example), but ONLY IF THEY EXPAND TO A SINGLE INTEGER. More complex expressions
won't do.
* * *
This piece of code is quite hard to debug, so I would appreciate any bug reports
in particular, of course any suggestions too. To contact me mail to
foehlfk@tick.informatik.uni-stuttgart.de
or snail to
Frank F÷hl
Siemensstr. 7
71636 Ludwigsburg
Germany