Frank Heckenbach wrote:
GPC currently uses a stand-alone preprocessor (gpcpp) that is derived from the C preprocessor and shares many of its features.
I plan to integrate it into the compiler which would follow gcc's example (not so important, though), maybe make it a little faster (not very much, I guess, since preprocessing in general doesn't take very long), solve some problems (e.g., the `--needed-option' ugliness, mostly on MIPS) and allow for further improvements.
In the same process, I'd like to change some of the more obscure aspects, thereby hopefully making the code much simpler and even more powerful. This will not affect the BPish features of the preprocessor (`{$ifdef}', `{$ifopt}' and `{$i ...}' (include)), and the Pascal standards don't have a preprocessor, anyway, so I think there are no compatibility concerns (except for backward-compatibility to existing GPC versions). I think most the features discussed below are known to few people at all and not used much.
Well, as much as I welcome Frank's suggestions for the preprocessor, there really are compatibilty-concerns. CodeWarrior Pascal has integrated preprocessor support, similar to what Frank suggests. I have included relevant parts of the CodeWarrior Pascal Compilers Reference in the text below.
Regards,
Adriaan van Os
---------------
Using Compiler Directives
<taken from the CodeWarrior® Pascal Compilers Reference>
Every compiler directive must be enclosed within comment delimit- ers ({ and }, or (* and *)) and begins with a dollar sign ($). Only one directive may be within each pair of comment delimiters.
CodeWarrior Pascal lets you compile sections of your source text conditionally by means of the $IFC, $ELSEC, and $ENDC and associ- ated directives. The $IFC directive is controlled by the value of a compile-time expression. You set such an expression using $SETC. Sections of source code controlled by these directives may be nested. The rules covering such nesting are the same as the rules for IF statements. See the Pascal Language Reference for more informa- tion about IF statements.
You can form compile-time expressions out of compile-time variables or constants of type INTEGER or BOOLEAN. The final value of the ex- pression that controls a $IFC directive must be BOOLEAN. You can use all the Pascal operators in compile-time expressions except IN and @. If you use the operator /, the compiler will automatically change it to DIV.
$DEFINE {$DEFINE id }
Defines an identifier that may be tested and undefined with other directives.
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
See also $IFDEF, $ELSE, $ENDIF.
$DEFINEC {$DEFINEC id} {$DEFINEC id definition} {$DEFINEC id ( parameters )definition
Defines an item, id. The $DEFINEC directive substitutes every occur- rence of id in the source code with its definition, definition. The iden- tifier, id, is not substituted when it appears in between comment de- limiters or a string literal.
The definition part of a $DEFINEC directive can be any keyword, constant value, or statement that is legal in CodeWarrior Pascal. Multiple statements in the definition must be separated by semi-co- lons (;).
The item id may have the same name of an already-declared proce- dure or function if id and the routine don't have the same number of parameters.
If id is defined with parameters, every occurrence of a parameter is replace with the corresponding items in id's definition before id is substituted. Parameters must be enclosed in parentheses in the $DEFINE directive.
Items defined in the INTERFACE part of a unit are accessible by the units or the program that use the unit. Items defined in the IMPLEMENTATION part of a unit are only accessible within the unit.
An item defined without a definition and without parameters is still defined but has an empty definition. To remove the definition of an item defined with $DEFINEC, use the $UNDEFC directive.
Listing 4.2 lists examples of using the $DEFINEC directive. Listing 4.2 $DEFINEC examples
PROGRAM DefineExamples; {$DEFINEC EraseMe} {$DEFINEC two 2} {$DEFINEC PRINT(a) WriteLn(a);} begin WriteLn(two); EraseMe; PRINT('Hello, world!'); end.
$ELIF {$ELIF comp-expr}
This directive is equivalent to the $ELIFC directive.
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
$ELIFC {$ELIFC comp-expr}
Marks the beginning of source text that is compiled only if the value of the comp-expr controlling its corresponding $IFC or $IFNOTC di- rective is false and its own comp-expr expression is true.
This is a CodeWarrior Pascal-compatible directive. It may not be used in the same source code file as other Turbo-compatible direc- tives.
See also $IFC, $ENDC, $SETC.
$ELSE {$ELSE}
This directive is equivalent to the $ELSEC directive.
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
$ELSEC {$ELSEC}
Marks the beginning of source text that is compiled only if the value of the comp-expr controlling its corresponding $IFC or $IFNOTC di- rective is false.
This is a CodeWarrior Pascal-compatible directive. It may not be used in the same source code file as other Turbo-compatible direc- tives.
See also $IFC, $ELIFC, $ENDC, $SETC.
$ENDIF {$ENDIF}
This directive is equivalent to the $ENDC directive.
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
$ENDC {$ENDC}
The $ENDC directive marks the end of a section of conditionally compiled source text, matching a $IFC or $IFNOTC directive.
This is a CodeWarrior Pascal-compatible directive. It may not be used in the same source code file as other Turbo-compatible direc- tives.
See also: $IFC, $IFNOTC, $ELSEC, $SETC.
$ERROR {$ERROR comment}
This directive is equivalent to the $ERRORC directive.
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
$ERRORC {$ERRORC comment}
Forces a compiler error. A comment, comment, may optionally fol- low this directive.
This is a CodeWarrior Pascal-compatible directive. It may not be used in the same source code file as other Turbo-compatible direc- tives.
$IF {$IF comp-expr} {$IF OPTION(option-name) } {$IF OPTION option-name }
This directive is equivalent to the {$IFC comp-expr} form of the $IFC directive.
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
See also $IFDEF, $ELSE, $ELIF, $ENDIF.
$IFC {$IFC comp-expr} {$IFC DEFINED name} {$IFC OPTION(option-name) } {$IFC OPTION option-name }
Compiles subsequent source code until the next $ELSEC or $ENDC directive, only if the boolean value of comp-expr is true.
You may also write this directive in the form {$IFC DEFINED name}. This will act like {$IFC false} if name has not yet been de- clared with a $SETC directive; otherwise, it will act like {$IFC true}.
You can also write this directive {$IFC OPTION( option-name} to test the current setting of compiler directives. For example, {$IFC OPTION (PROF)} acts like {$IFC true} if {$PROF+} had been specified prior to the $IFC.
This is a CodeWarrior Pascal-compatible directive. It may not be used in the same source code file as other Turbo-compatible direc- tives.
See also $IFNOTC, $ELIFC, $ELSEC, $ENDC, $SETC, $DEFINEC,
$IFDEF {$IFDEF id} This directive is equivalent to the {$IFC DEFINED id} form of the $IFC directive.
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
See also $DEFINE, $UNDEF, $IFNDEF, $IF.
$IFOPT {$IFOPT option-name}
This directive is equivalent to the $IF OPTION(option-name) form of the $IF directive.
See also $IF, $ELSE, $ELIF, $ENDIF, Checking Options on page 98 .
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
$IFNDEF {$IFDEF id }
This directive is equivalent to the {$IFNOTC DEFINED id} form of the $IFNOTC directive.
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
See also $IFDEF.
$IFNOTC {$IFNOTC DEFINED name}
Compiles subsequent source code until the next $ELSEC or $ENDC directive, only if the boolean value of comp-expr is true.
This directive will act like {$IFC true} if name has not yet been declared with a $SETC directive; otherwise, it will act like {$IFC false}.
This is a CodeWarrior Pascal-compatible directive. It may not be used in the same source code file as other Turbo-compatible direc- tives.
See also: $ELSEC, $ENDC, $IFC, $SETC, $DEFINEC.
$MACRO {$MACRO id} {$MACRO id definition} {$MACRO id ( parameters )definition
This directive is equivalent to the $DEFINEC directive.
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
$PRAGMA {$PRAGMA pragma state}
This directive is equivalent to the $PRAGMAC directive.
This is a Turbo Pascal-compatible directive. It may not be used in the same source code file as other CodeWarrior-compatible direc- tives.
$PRAGMAC {$PRAGMA pragma state}
Sets the state of a pragma. See Pragmas on page 60 for more infor- mation on using pragmas to control how source code is translated into object code.
This is a CodeWarrior Pascal-compatible directive. It may not be used in the same source code file as other Turbo-compatible direc- tives.
$SETC {$SETC id := comp-expr}
Declares a compile-time variable named id and assigns it the value comp-expr.
This directive may not be used with Turbo Pascal-compatible direc- tives.
See also: $IFC, $ELSEC, $ENDC.
$UNDEFC {$UNDEFC id}
Undefines an identifier that was defined with the $DEFINEC direc- tive. Undefining a previously defined item tells the compiler not to substitute subsequent occurrences of id with its definition.
Use this directive with the $IFC and $IFNOTC directives to control the compilation of source code.
This is a CodeWarrior Pascal-compatible directive. It may not be used in the same source code file as other Turbo-compatible direc- tives.
See also $DEFINEC, $IFC, $IFNOTC.
---------------
Adriaan van Os wrote:
Well, as much as I welcome Frank's suggestions for the preprocessor, there really are compatibilty-concerns. CodeWarrior Pascal has integrated preprocessor support, similar to what Frank suggests. I have included relevant parts of the CodeWarrior Pascal Compilers Reference in the text below.
Well, the descriptions don't always seem to be very accurate. Besides some smaller mistakes, it lists some "Turbo Pascal compatible directives" (e.g., elif, error, if, macro, pragma) that at least BP 7.0 doesn't know (so I'd be surprised if previous TP/BP versions had them). Or this:
$IFNOTC {$IFNOTC DEFINED name}
Compiles subsequent source code until the next $ELSEC or $ENDC directive, only if the boolean value of comp-expr is true.
comp-expr is not even mentioned in the heading, and I suppose it must read "false" instead of "true".
So I'm discarding the exact wording in favour of reading the text in a "reasonable" (IMHO) way ... ;-)
You can form compile-time expressions out of compile-time variables or constants of type INTEGER or BOOLEAN.
That would be a reason for integrating the preprocessor into the compiler since a stand-alone preprocessor would have no knowledge of constants.
However, I actually don't like this very much. I prefer the preprocessor output to be a function of the source code and the initial settings.
Otherwise, it would also depend on imported modules (used units) which may define constants ...
$DEFINEC Items defined in the INTERFACE part of a unit are accessible by the units or the program that use the unit.
For the same reason I don't like this, either. (And it would also require an integrated preprocessor.)
BTW, these things would also make the task of external programs such as `gp' much more difficult (since, e.g., `uses'/`import' could be within a conditional).
Apart from this, most seems to boil down to aliases of existing directives:
definec define elifc elif endc endif errorc error ifc if macro define undefc undef
Of course, this would be easy to do, but I don't see the big point in it. Especially since "CodeWarrior Pascal-compatible directive[s] ... may not be used in the same source code file as Turbo-compatible directives". It seems they're just creating artifical incompatibilities by just calling the same directives differently. :-(
{$IF OPTION(option-name) } {$IF OPTION option-name }
Another syntax for `ifopt'.
{$IFC DEFINED name} You may also write this directive in the form {$IFC DEFINED name}. This will act like {$IFC false} if name has not yet been de- clared with a $SETC directive; otherwise, it will act like {$IFC true}.
GPC currently has `defined (name)'. The parentheses seem more "Pascalish" to me (cf. `sizeof foo' in C vs. `SizeOf (foo)' in BP which I actually consider more Pascalish here). Though it shouldn't be a big problem to implement it without the parentheses, too ...
$IFNOTC {$IFNOTC DEFINED name}
Compiles subsequent source code until the next $ELSEC or $ENDC directive, only if the boolean value of comp-expr is true.
Same as `if not (...)'. (Since `not' is apparently allowed already in conditionals, this seems rather redundant ...)
$PRAGMAC {$PRAGMA pragma state}
Sets the state of a pragma. See Pragmas on page 60 for more infor- mation on using pragmas to control how source code is translated into object code.
I don't know what pragmas are, I guess they're the same as (some) compiler directives in GPC (and possibly BP), and could possibly be mappend to them ...
$SETC {$SETC id := comp-expr}
Declares a compile-time variable named id and assigns it the value comp-expr.
So there's another mechanism besides defines (and usual Pascal constants etc., of course)? I'm not convinced this is very useful. (Even C, which makes heavy use of the preprocessor and uses defines for constants, seems to be quite happy with only one preprocessor "name space".) So if anything, I think it might be reasonable to make this equivalent to `{$define id comp-expr}'.
All in all, these features don't seem to add new capabilities (with the exception above, working across units, that I don't like), just more syntax alternatives. I think about it mostly the same as about some Delphi features ... :-(
I.e., we might choose to implement them for compatibility's sake. Then again, how far is GPC compatible to CW in other respects? Is it reasonable to claim (or strive for) compatibility at all?
Frank
Frank Heckenbach wrote:
... snip ...
I.e., we might choose to implement them for compatibility's sake. Then again, how far is GPC compatible to CW in other respects? Is it reasonable to claim (or strive for) compatibility at all?
No no no no no. If CW wants compatibility it should implement an ISO standard. One tool, one job. Please don't waste valuable time and effort on this.
Frank Heckenbach wrote:
I.e., we might choose to implement them for compatibility's sake. Then again, how far is GPC compatible to CW in other respects? Is it reasonable to claim (or strive for) compatibility at all?
Well, I don't mind writing different code, where compilers and platforms are different. I am striving for the possibility to do so within one conditionalized source code. One might call this the lowest level of compatibility, the possibilty to write a conditional compiler expression IFxx ELSExx ENDxx in a way that both compilers understand.
In CodeWarrior Pascal, you have the choice between "Apple style" and "BP style" conditional expressions (the latter not strictly BP, but enhanced with Apple-like features) You can use either, but you can't mix them in the same project, e.g.
{$ifc condition} ... {$elsec} ... {$endc}
or either
{$if condition} ... {$else} ... {$endif}
in all sources.
Most Macintosh programmers traditionally will use "Apple style" conditional expressions, since they are used in Apple's Pascal Interfaces to MacOS. I, for one, am lucky to maintain my own Pascal Interfaces to MacOS, so for me the choice is free. Also, I am free to make any changes to those Interfaces, needed for GPC.
To put it in a nutshell, I will be very grateful if GPC supports
{$if condition} ... {$else} ... {$endif}
and it would be nice if
{$ifc condition} ... {$elsec} ... {$endc}
is supported also. The other items from the CodeWarrior Reference are non-essential.
Best regards,
Adriaan van Os
Adriaan van Os wrote:
[...]
To put it in a nutshell, I will be very grateful if GPC supports
{$if condition} ... {$else} ... {$endif}
It does (since a very long time, actually).
and it would be nice if
{$ifc condition} ... {$elsec} ... {$endc}
is supported also. The other items from the CodeWarrior Reference are non-essential.
It would be trivial to add those (though I guess without the restriction that only one form may be used in a source file). My main question (see below) is how useful this would be on the whole.
CBFalconer wrote:
Frank Heckenbach wrote:
I.e., we might choose to implement them for compatibility's sake. Then again, how far is GPC compatible to CW in other respects? Is it reasonable to claim (or strive for) compatibility at all?
No no no no no. If CW wants compatibility it should implement an ISO standard. One tool, one job. Please don't waste valuable time and effort on this.
I don't plan to. I asked this question in order to find out about CW's language. If it's compatible to (a subset of the union of) Standard Pascal and Borland Pascal, we might not have to add much at all to be compatible (maybe a few warnings and errors, but they're not so important I guess).
If, however, it's substantially different, I won't strive for compatibility (of course, if someone else volunteers, they can still do it).
Frank
Frank Heckenbach wrote:
CBFalconer wrote:
Frank Heckenbach wrote:
I.e., we might choose to implement them for compatibility's sake. Then again, how far is GPC compatible to CW in other respects? Is it reasonable to claim (or strive for) compatibility at all?
No no no no no. If CW wants compatibility it should implement an ISO standard. One tool, one job. Please don't waste valuable time and effort on this.
I don't plan to. I asked this question in order to find out about CW's language. If it's compatible to (a subset of the union of) Standard Pascal and Borland Pascal, we might not have to add much at all to be compatible (maybe a few warnings and errors, but they're not so important I guess).
If, however, it's substantially different, I won't strive for compatibility (of course, if someone else volunteers, they can still do it).
Even then I maintain don't do it. If someone needs to port such code THAT is the place for a macro pre-processor, which can convert such things as $IFC to %IF, etc.
CBFalconer wrote:
Frank Heckenbach wrote:
CBFalconer wrote:
Frank Heckenbach wrote:
I.e., we might choose to implement them for compatibility's sake. Then again, how far is GPC compatible to CW in other respects? Is it reasonable to claim (or strive for) compatibility at all?
No no no no no. If CW wants compatibility it should implement an ISO standard. One tool, one job. Please don't waste valuable time and effort on this.
I don't plan to. I asked this question in order to find out about CW's language. If it's compatible to (a subset of the union of) Standard Pascal and Borland Pascal, we might not have to add much at all to be compatible (maybe a few warnings and errors, but they're not so important I guess).
If, however, it's substantially different, I won't strive for compatibility (of course, if someone else volunteers, they can still do it).
Even then I maintain don't do it. If someone needs to port such code THAT is the place for a macro pre-processor, which can convert such things as $IFC to %IF, etc.
I don't agree. As I said before, some (including myself) need a macro-preprocessor sometimes, not only for compatibility reasons. So there's no question (as far as I'm concerned) that GPC's preprocessor will remain, the question is only how to change it (in the details). And, of course, it will be (remain) non-intrusive, i.e. any program that does not use its features will not notice them.
Frank