Recent

Author Topic: Conditional Defines  (Read 770 times)

Mark20

  • Newbie
  • Posts: 4
Conditional Defines
« on: June 02, 2020, 09:59:30 am »
Hello,
I am trying to use the simple structure

{$IF XXX} 
  // XXX Code here 
{$ELSEIF YYY} 
  // YYY code here 
{$ELSE} 
  // And default code here 
{$ENDIF}

but I get compiler error on ELSEIF line:
"unit1.pas(43,14) Error: ENDIF without IF(N)DEF"

Is it a bug or there is any option to enable to make elseif recognized ?

Regards

PascalDragon

  • Hero Member
  • *****
  • Posts: 1922
  • Compiler Developer
Re: Conditional Defines
« Reply #1 on: June 02, 2020, 10:03:03 am »
Please show a full example, because there is a subtle difference between $IF and $IFDEF.

TRon

  • Sr. Member
  • ****
  • Posts: 362
Re: Conditional Defines
« Reply #2 on: June 02, 2020, 10:19:33 am »
but I get compiler error on ELSEIF line:
"unit1.pas(43,14) Error: ENDIF without IF(N)DEF"

try:
Code: Pascal  [Select][+][-]
  1. {$IF DEFINED(XXX)}  
  2.   // XXX Code here  
  3. {$ELSEIF DEFINED(YYY)}  
  4.   // YYY code here  
  5. {$ELSE}  
  6.   // And default code here  
  7. {$ENDIF}
  8.  
The elseif only works that way, there is no "elseifdef"

Mark20

  • Newbie
  • Posts: 4
Re: Conditional Defines
« Reply #3 on: June 02, 2020, 10:30:21 am »
Thanks for your precisation, infact I wrote:
Code: Pascal  [Select][+][-]
  1. function BitTestAndSet(var Target: Integer; BitOffset: Shortint): Boolean;
  2. {$IFDEF CPUX86_64}
  3. begin
  4.     asm
  5.       AND  EDX,31
  6.       LOCK BTS   [RCX].Integer,EDX
  7.       SETNC  AL
  8.     end;
  9. end;
  10. {$ELSEIF CPUI386}
  11. begin
  12.     asm
  13.       AND   EDX,31
  14.       LOCK BTS   [EAX],EDX
  15.       SETNC  AL
  16.     end;
  17. end;
  18. {$ELSE}
  19. var
  20.   OldValue: Integer;
  21. begin
  22.   OldValue := Target and not (1 shl (BitOffset and 31));
  23.   AtomicCmpExchange(Target, OldValue or (1 shl (BitOffset and 31)), OldValue, Result);
  24. end;
  25. {$ENDIF}    
  26.  
which gave me the error.
Instead is correct using $IF only:
Code: Pascal  [Select][+][-]
  1. function BitTestAndSet(var Target: Integer; BitOffset: Shortint): Boolean;
  2. {$IF Defined(CPUX86_64)} // Free Pascal target is a AMD64 or Intel 64-bit processor.
  3. begin
  4.     asm
  5.       AND  EDX,31
  6.       LOCK BTS   [RCX].Integer,EDX
  7.       SETNC  AL
  8.     end;
  9. end;
  10. {$ELSEIF Defined(CPUI386)}
  11. begin
  12.     asm
  13.       AND   EDX,31
  14.       LOCK BTS   [EAX],EDX
  15.       SETNC  AL
  16.     end;
  17. end;
  18. {$ELSE}
  19. var
  20.   OldValue: Integer;
  21. begin
  22.   OldValue := Target and not (1 shl (BitOffset and 31));
  23.   AtomicCmpExchange(Target, OldValue or (1 shl (BitOffset and 31)), OldValue, Result);
  24. end;
  25. {$ENDIF}  
  26.  

Regards.

TRon

  • Sr. Member
  • ****
  • Posts: 362
Re: Conditional Defines
« Reply #4 on: June 02, 2020, 10:36:16 am »
To further clarify: the page (https://www.freepascal.org/docs-html/prog/progsu14.html#x21-200001.2.14) that you quote has some additional statement (that you forgot to quote   ;D ):
Quote
The directive is followed by an expression like the ones recognized by the {$IF } directive.

Therefor you should really have a look at https://www.freepascal.org/docs-html/prog/progsu29.html#x36-350001.2.29 , which states:
Quote
The directive {$IF expr} will continue the compilation if the boolean expression expr evaluates to True.
... and that same page redirects to https://www.freepascal.org/docs-html/prog/progsu127.html#x140-1410002.4.1

There you are able to find all possible valid expressions for using the IF condition.


Thaddy

  • Hero Member
  • *****
  • Posts: 10271
Re: Conditional Defines
« Reply #5 on: June 02, 2020, 11:53:18 am »
side note:
The intention was to have {$ifdef} end with {$endif} and {$If} end with {$ifend}
This got confused at one point, but I highly recommend using {$if}/{$ifend}
This makes the difference between the two notations - with different options - also easier to follow.
The parser is imho not strict enough here regarding the closing statement...That includes the examples in the manual...

If this requires a bug report? I leave that to the forum...

It has been allowed for so many years that it can cause mayhem all over the place...
E.g. the manual examples...

(one little "feature' where we fell into a C trap: interpretation relies on the programmer..not the compiler...)
« Last Edit: June 02, 2020, 12:03:44 pm by Thaddy »
I am more like donkey than shrek

PascalDragon

  • Hero Member
  • *****
  • Posts: 1922
  • Compiler Developer
Re: Conditional Defines
« Reply #6 on: June 02, 2020, 01:16:43 pm »
The parser is imho not strict enough here regarding the closing statement...That includes the examples in the manual...

It's intentional that the compiler doesn't care whether $IFEND or $ENDIF is used.

Thaddy

  • Hero Member
  • *****
  • Posts: 10271
Re: Conditional Defines
« Reply #7 on: June 02, 2020, 01:49:54 pm »
Then explain the intention?... As far as I am concerned it leads to clashes between the two forms.... It leads to logically completely different paths.. Erratic at best.
When the compiler parses {$endif} and {$ifend) the same that is a huge bug, intentional or not, that is wrong and you know it.

There is simply not a predictable match....
Since {$ifdef} and {$if} are distinct...

It is a feature, not a bug?
( a humble sigh added... :P )
« Last Edit: June 02, 2020, 02:36:44 pm by Thaddy »
I am more like donkey than shrek

Kays

  • Full Member
  • ***
  • Posts: 204
  • Whasup!?
    • KaiBurghardt.de
Re: Conditional Defines
« Reply #8 on: June 02, 2020, 04:09:21 pm »
Then explain the intention? […]

Isn’t it always compatibility?
Yours Sincerely
Kai Burghardt

Thaddy

  • Hero Member
  • *****
  • Posts: 10271
Re: Conditional Defines
« Reply #9 on: June 02, 2020, 04:19:35 pm »
Well, I wonder if Delphi still makes the same mistake  :-X
I am more like donkey than shrek

PascalDragon

  • Hero Member
  • *****
  • Posts: 1922
  • Compiler Developer
Re: Conditional Defines
« Reply #10 on: June 03, 2020, 09:35:12 am »
Then explain the intention?... As far as I am concerned it leads to clashes between the two forms.... It leads to logically completely different paths.. Erratic at best.
When the compiler parses {$endif} and {$ifend) the same that is a huge bug, intentional or not, that is wrong and you know it.

There is simply not a predictable match....
Since {$ifdef} and {$if} are distinct...

It is a feature, not a bug?
( a humble sigh added... :P )

It is a feature, because it allows the user not having to care whether they need to use $IfEnd or $EndIf. It's already confusing enough whether they can simply use a define or have to use an expression (as this thread shows).

Well, I wonder if Delphi still makes the same mistake  :-X

Delphi enforced the use of $IfEnd for $If until XE3, but they relaxed that with XE4.

Thaddy

  • Hero Member
  • *****
  • Posts: 10271
Re: Conditional Defines
« Reply #11 on: June 03, 2020, 11:09:24 am »
Ok, but that is silly imho.
I am more like donkey than shrek

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 799
    • Lebeau Software
Re: Conditional Defines
« Reply #12 on: June 03, 2020, 08:15:03 pm »
Delphi enforced the use of $IfEnd for $If until XE3, but they relaxed that with XE4.

However, in XE4+, you can use the {$LEGACYIFEND ON} directive to go back to the old behavior, so that {$IF} is closed only by {$IFEND} and not by {$ENDIF} (for instance, Indy uses this directive internally).
« Last Edit: June 03, 2020, 08:19:59 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

 

TinyPortal © 2005-2018