Browse Source

+ compile time expression type checking
* fixed bug in $DEFINE under macpas

git-svn-id: trunk@919 -

olle 20 years ago
parent
commit
e40c2fd8b0
4 changed files with 596 additions and 387 deletions
  1. 4 2
      compiler/msg/errore.msg
  2. 3 2
      compiler/msgidx.inc
  3. 306 306
      compiler/msgtxt.inc
  4. 283 77
      compiler/scanner.pas

+ 4 - 2
compiler/msg/errore.msg

@@ -309,8 +309,8 @@ scan_e_wrong_switch_toggle_default=02066_E_Wrong switch toggle, use ON/OFF/DEFAU
 scan_e_mode_switch_not_allowed=02067_E_Mode switch "$1" not allowed here
 scan_e_mode_switch_not_allowed=02067_E_Mode switch "$1" not allowed here
 % A mode switch has already been encountered, or, in case of option -Mmacpas,
 % A mode switch has already been encountered, or, in case of option -Mmacpas,
 % a mode switch occur after UNIT.
 % a mode switch occur after UNIT.
-scan_e_error_macro_undefined=02068_E_Compile time variable "$1" is not defined.
-% Thus the conditional compile time expression cannot be evaluated.
+scan_e_error_macro_undefined=02068_E_Compile time variable or macro "$1" is not defined.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
 scan_e_utf8_bigger_than_65535=02069_E_UTF-8 code greater than 65535 found
 scan_e_utf8_bigger_than_65535=02069_E_UTF-8 code greater than 65535 found
 % \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
 % \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
 scan_e_utf8_malformed=02070_E_Malformed UTF-8 string
 scan_e_utf8_malformed=02070_E_Malformed UTF-8 string
@@ -318,6 +318,8 @@ scan_e_utf8_malformed=02070_E_Malformed UTF-8 string
 scan_c_switching_to_utf8=02071_C_UTF-8 signature found, using UTF-8 encoding
 scan_c_switching_to_utf8=02071_C_UTF-8 signature found, using UTF-8 encoding
 % The compiler found an UTF-8 encoding signature ($ef, $bb, $bf) at the beginning of a file,
 % The compiler found an UTF-8 encoding signature ($ef, $bb, $bf) at the beginning of a file,
 % so it interprets it as an UTF-8 file
 % so it interprets it as an UTF-8 file
+scan_e_compile_time_typeerror=02072_E_Compile time expression: Wanted $1 but got $2 at $3
+% Type check of a compile time expression failed.
 % \end{description}
 % \end{description}
 #
 #
 # Parser
 # Parser

+ 3 - 2
compiler/msgidx.inc

@@ -87,6 +87,7 @@ const
   scan_e_utf8_bigger_than_65535=02069;
   scan_e_utf8_bigger_than_65535=02069;
   scan_e_utf8_malformed=02070;
   scan_e_utf8_malformed=02070;
   scan_c_switching_to_utf8=02071;
   scan_c_switching_to_utf8=02071;
+  scan_e_compile_time_typeerror=02072;
   parser_e_syntax_error=03000;
   parser_e_syntax_error=03000;
   parser_e_dont_nest_interrupt=03004;
   parser_e_dont_nest_interrupt=03004;
   parser_w_proc_directive_ignored=03005;
   parser_w_proc_directive_ignored=03005;
@@ -658,9 +659,9 @@ const
   option_info=11024;
   option_info=11024;
   option_help_pages=11025;
   option_help_pages=11025;
 
 
-  MsgTxtSize = 38879;
+  MsgTxtSize = 38948;
 
 
   MsgIdxMax : array[1..20] of longint=(
   MsgIdxMax : array[1..20] of longint=(
-    19,72,215,59,59,46,100,20,135,60,
+    19,73,215,59,59,46,100,20,135,60,
     40,1,1,1,1,1,1,1,1,1
     40,1,1,1,1,1,1,1,1,1
   );
   );

File diff suppressed because it is too large
+ 306 - 306
compiler/msgtxt.inc


+ 283 - 77
compiler/scanner.pas

@@ -387,9 +387,77 @@ implementation
           setfilename(paramfn^, paramallowoutput);
           setfilename(paramfn^, paramallowoutput);
       end;
       end;
 
 
-    function parse_compiler_expr:string;
+{
+Compile time expression type check
+----------------------------------
+Each subexpression returns its type to the caller, which then can
+do type check.  Since data types of compile time expressions is
+not well defined, the type system does a best effort. The drawback is
+that some errors might not be detected.
+
+Instead of returning a particular data type, a set of possible data types
+are returned. This way ambigouos types can be handled.  For instance a
+value of 1 can be both a boolean and and integer.
+
+Booleans
+--------
+
+The following forms of boolean values are supported:
+* C coded, that is 0 is false, non-zero is true.
+* TRUE/FALSE for mac style compile time variables
+
+Thus boolean mac compile time variables are always stored as TRUE/FALSE.
+When a compile time expression is evaluated, they are then translated
+to C coded booleans (0/1), to simplify for the expression evaluator.
 
 
-        function read_expr : string; forward;
+Note that this scheme then also of support mac compile time variables which
+are 0/1 but with a boolean meaning.
+
+The TRUE/FALSE format is new from 22 august 2005, but the above scheme
+means that units which is not recompiled, and thus stores 
+compile time variables as the old format (0/1), continue to work.
+
+}
+
+    type
+      {Compile time expression types}
+      TCTEType = (ctetBoolean, ctetInteger, ctetString, ctetSet);
+      TCTETypeSet = set of TCTEType;
+
+    const
+      cteTypeNames : array[TCTEType] of string[10] = (
+        'BOOLEAN','INTEGER','STRING','SET');
+
+      {Subset of types which can be elements in sets.}
+      setElementTypes = [ctetBoolean, ctetInteger, ctetString];
+
+
+    function GetCTETypeName(t: TCTETypeSet): String;
+      var
+        i: TCTEType;
+      begin
+        result:= '';
+        for i:= Low(TCTEType) to High(TCTEType) do
+          if i in t then
+            if result = '' then
+              result:= cteTypeNames[i]
+            else
+              result:= result + ' or ' + cteTypeNames[i];
+      end;
+
+    procedure CTEError(actType, desiredExprType: TCTETypeSet; place: String);
+
+    begin
+      Message3(scan_e_compile_time_typeerror,
+               GetCTETypeName(desiredExprType),
+               GetCTETypeName(actType),
+               place
+              );
+    end;
+
+    function parse_compiler_expr(var compileExprType: TCTETypeSet):string;
+
+        function read_expr(var exprType: TCTETypeSet) : string; forward;
 
 
         procedure preproc_consume(t : ttoken);
         procedure preproc_consume(t : ttoken);
         begin
         begin
@@ -398,14 +466,23 @@ implementation
           current_scanner.preproc_token:=current_scanner.readpreproc;
           current_scanner.preproc_token:=current_scanner.readpreproc;
         end;
         end;
 
 
-        function preproc_substitutedtoken: string;
+        function preproc_substitutedtoken(var macroType: TCTETypeSet): string;
+				{ Currently this parses identifiers as well as numbers. 
+          The result from this procedure can either be that the token
+          itself is a value, or that it is a compile time variable/macro,
+          which then is substituted for another value (for macros
+          recursivelly substituted).}
+
         var
         var
           hs: string;
           hs: string;
           mac : tmacro;
           mac : tmacro;
           macrocount,
           macrocount,
           len : integer;
           len : integer;
+          numres : longint;
+          w: word;
         begin
         begin
           result := current_scanner.preproc_pattern;
           result := current_scanner.preproc_pattern;
+          mac:= nil;
           { Substitue macros and compiler variables with their content/value.
           { Substitue macros and compiler variables with their content/value.
             For real macros also do recursive substitution. }
             For real macros also do recursive substitution. }
           macrocount:=0;
           macrocount:=0;
@@ -441,21 +518,47 @@ implementation
                 end
                 end
             else
             else
               begin
               begin
-                (*
-                // To make this work, there must be some kind of type checking here...
-                if m_mac in aktmodeswitches then
-                  Message1(scan_e_error_macro_undefined, result)
-                else
-                *)
                   break;
                   break;
               end;
               end;
 
 
             if mac.is_compiler_var then
             if mac.is_compiler_var then
               break;
               break;
           until false;
           until false;
+
+          {At this point, result do contain the value. Do some decoding and
+					 determine the type.}
+  				val(result,numres,w);
+  				if (w=0) then {It is an integer}
+  				  begin
+  				    if (numres = 0) or (numres = 1) then
+  		    		  macroType := [ctetInteger, ctetBoolean]
+  		    		else
+  		    		  macroType := [ctetInteger];  		    	
+		    		end
+          else if assigned(mac) and (m_mac in aktmodeswitches) and (result='FALSE') then
+					  begin
+						  result:= '0';
+     					macroType:= [ctetBoolean];
+						end
+          else if assigned(mac) and (m_mac in aktmodeswitches) and (result='TRUE') then
+					  begin
+						  result:= '1';
+     					macroType:= [ctetBoolean];
+						end
+          else if (m_mac in aktmodeswitches) and
+                  (not assigned(mac) or not mac.defined) and
+                  (macrocount = 1) then
+            begin
+              {Errors in mode mac is issued here. For non macpas modes there is
+               more liberty, but the error will eventually be caught at a later stage.}
+              Message1(scan_e_error_macro_undefined, result);
+              macroType:= [ctetString]; {Just to have something}
+            end
+          else
+            macroType:= [ctetString];
         end;
         end;
 
 
-        function read_factor : string;
+        function read_factor(var factorType: TCTETypeSet) : string;
         var
         var
            hs : string;
            hs : string;
            mac: tmacro;
            mac: tmacro;
@@ -464,12 +567,14 @@ implementation
            l : longint;
            l : longint;
            w : integer;
            w : integer;
            hasKlammer: Boolean;
            hasKlammer: Boolean;
+           setElemType : TCTETypeSet;
 
 
         begin
         begin
            if current_scanner.preproc_token=_ID then
            if current_scanner.preproc_token=_ID then
              begin
              begin
                 if current_scanner.preproc_pattern='DEFINED' then
                 if current_scanner.preproc_pattern='DEFINED' then
                   begin
                   begin
+                    factorType:= [ctetBoolean];
                     preproc_consume(_ID);
                     preproc_consume(_ID);
                     current_scanner.skipspace;
                     current_scanner.skipspace;
                     if current_scanner.preproc_token =_LKLAMMER then
                     if current_scanner.preproc_token =_LKLAMMER then
@@ -510,6 +615,7 @@ implementation
                 else
                 else
                 if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='UNDEFINED') then
                 if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='UNDEFINED') then
                   begin
                   begin
+                    factorType:= [ctetBoolean];
                     preproc_consume(_ID);
                     preproc_consume(_ID);
                     current_scanner.skipspace;
                     current_scanner.skipspace;
                     if current_scanner.preproc_token =_ID then
                     if current_scanner.preproc_token =_ID then
@@ -533,6 +639,7 @@ implementation
                 else
                 else
                 if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='OPTION') then
                 if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='OPTION') then
                   begin
                   begin
+                    factorType:= [ctetBoolean];
                     preproc_consume(_ID);
                     preproc_consume(_ID);
                     current_scanner.skipspace;
                     current_scanner.skipspace;
                     if current_scanner.preproc_token =_LKLAMMER then
                     if current_scanner.preproc_token =_LKLAMMER then
@@ -568,6 +675,7 @@ implementation
                 else
                 else
                 if current_scanner.preproc_pattern='SIZEOF' then
                 if current_scanner.preproc_pattern='SIZEOF' then
                   begin
                   begin
+                    factorType:= [ctetInteger];
                     preproc_consume(_ID);
                     preproc_consume(_ID);
                     current_scanner.skipspace;
                     current_scanner.skipspace;
                     if current_scanner.preproc_token =_LKLAMMER then
                     if current_scanner.preproc_token =_LKLAMMER then
@@ -607,6 +715,7 @@ implementation
                 else
                 else
                 if current_scanner.preproc_pattern='DECLARED' then
                 if current_scanner.preproc_pattern='DECLARED' then
                   begin
                   begin
+                    factorType:= [ctetBoolean];
                     preproc_consume(_ID);
                     preproc_consume(_ID);
                     current_scanner.skipspace;
                     current_scanner.skipspace;
                     if current_scanner.preproc_token =_LKLAMMER then
                     if current_scanner.preproc_token =_LKLAMMER then
@@ -637,8 +746,11 @@ implementation
                 else
                 else
                 if current_scanner.preproc_pattern='NOT' then
                 if current_scanner.preproc_pattern='NOT' then
                   begin
                   begin
+                    factorType:= [ctetBoolean];
                     preproc_consume(_ID);
                     preproc_consume(_ID);
-                    hs:=read_factor();
+                    hs:=read_factor(factorType);
+                    if not (ctetBoolean in factorType) then
+                      CTEError(factorType, [ctetBoolean], 'NOT');
                     val(hs,l,w);
                     val(hs,l,w);
                     if l<>0 then
                     if l<>0 then
                       read_factor:='0'
                       read_factor:='0'
@@ -648,21 +760,24 @@ implementation
                 else
                 else
                 if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='TRUE') then
                 if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='TRUE') then
                   begin
                   begin
+                    factorType:= [ctetBoolean];
                     preproc_consume(_ID);
                     preproc_consume(_ID);
                     read_factor:='1';
                     read_factor:='1';
                   end
                   end
                 else
                 else
                 if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='FALSE') then
                 if (m_mac in aktmodeswitches) and (current_scanner.preproc_pattern='FALSE') then
                   begin
                   begin
+                    factorType:= [ctetBoolean];
                     preproc_consume(_ID);
                     preproc_consume(_ID);
                     read_factor:='0';
                     read_factor:='0';
                   end
                   end
                 else
                 else
                   begin
                   begin
-                    hs:=preproc_substitutedtoken;
+                    hs:=preproc_substitutedtoken(factorType);
+
                     { Default is to return the original symbol }
                     { Default is to return the original symbol }
                     read_factor:=hs;
                     read_factor:=hs;
-                    if (m_delphi in aktmodeswitches) then
+                    if (m_delphi in aktmodeswitches) and (ctetString in factorType) then
                       if searchsym(current_scanner.preproc_pattern,srsym,srsymtable) then
                       if searchsym(current_scanner.preproc_pattern,srsym,srsymtable) then
                         begin
                         begin
                           case srsym.typ of
                           case srsym.typ of
@@ -676,18 +791,34 @@ implementation
                                           case consttype.def.deftype of
                                           case consttype.def.deftype of
                                             orddef:
                                             orddef:
                                               begin
                                               begin
-                                                if is_integer(consttype.def) or is_boolean(consttype.def) then
-                                                  read_factor:=tostr(value.valueord)
-                                                else
-                                                  if is_char(consttype.def) then
+                                                if is_integer(consttype.def) then
+                                                  begin
+                                                    read_factor:=tostr(value.valueord);
+                                                    factorType:= [ctetInteger];
+                                                  end
+                                                else if is_boolean(consttype.def) then
+                                                  begin
+                                                    read_factor:=tostr(value.valueord);
+                                                    factorType:= [ctetBoolean];
+                                                  end
+                                                else if is_char(consttype.def) then
+                                                  begin
                                                     read_factor:=chr(value.valueord);
                                                     read_factor:=chr(value.valueord);
+                                                    factorType:= [ctetString];
+                                                  end
                                               end;
                                               end;
                                             enumdef:
                                             enumdef:
-                                              read_factor:=tostr(value.valueord)
+                                              begin
+                                                read_factor:=tostr(value.valueord);
+                                                factorType:= [ctetInteger];
+                                              end;
                                           end;
                                           end;
                                         end;
                                         end;
                                       conststring :
                                       conststring :
-                                        read_factor := upper(pchar(value.valueptr));
+                                        begin
+                                          read_factor := upper(pchar(value.valueptr));
+                                          factorType:= [ctetString];
+                                        end;
                                       constset :
                                       constset :
                                         begin
                                         begin
                                           hs:=',';
                                           hs:=',';
@@ -695,15 +826,18 @@ implementation
                                             if l in pconstset(tconstsym(srsym).value.valueptr)^ then
                                             if l in pconstset(tconstsym(srsym).value.valueptr)^ then
                                               hs:=hs+tostr(l)+',';
                                               hs:=hs+tostr(l)+',';
                                           read_factor := hs;
                                           read_factor := hs;
+                                          factorType:= [ctetSet];
                                         end;
                                         end;
                                     end;
                                     end;
                                   end;
                                   end;
                               end;
                               end;
                             enumsym :
                             enumsym :
-                              read_factor:=tostr(tenumsym(srsym).value);
+                              begin
+																read_factor:=tostr(tenumsym(srsym).value);
+																factorType:= [ctetInteger];
+														  end;
                           end;
                           end;
                         end;
                         end;
-
                     preproc_consume(_ID);
                     preproc_consume(_ID);
                     current_scanner.skipspace;
                     current_scanner.skipspace;
                   end
                   end
@@ -711,7 +845,7 @@ implementation
            else if current_scanner.preproc_token =_LKLAMMER then
            else if current_scanner.preproc_token =_LKLAMMER then
              begin
              begin
                 preproc_consume(_LKLAMMER);
                 preproc_consume(_LKLAMMER);
-                read_factor:=read_expr;
+                read_factor:=read_expr(factorType);
                 preproc_consume(_RKLAMMER);
                 preproc_consume(_RKLAMMER);
              end
              end
            else if current_scanner.preproc_token = _LECKKLAMMER then
            else if current_scanner.preproc_token = _LECKKLAMMER then
@@ -720,30 +854,44 @@ implementation
                read_factor := ',';
                read_factor := ',';
                while current_scanner.preproc_token = _ID do
                while current_scanner.preproc_token = _ID do
                begin
                begin
-                 read_factor := read_factor+read_factor()+',';
+                 read_factor := read_factor+read_factor(setElemType)+',';
                  if current_scanner.preproc_token = _COMMA then
                  if current_scanner.preproc_token = _COMMA then
                    preproc_consume(_COMMA);
                    preproc_consume(_COMMA);
                end;
                end;
+               // TODO Add check of setElemType
                preproc_consume(_RECKKLAMMER);
                preproc_consume(_RECKKLAMMER);
+               factorType:= [ctetSet];
              end
              end
            else
            else
              Message(scan_e_error_in_preproc_expr);
              Message(scan_e_error_in_preproc_expr);
         end;
         end;
 
 
-        function read_term : string;
+        function read_term(var termType: TCTETypeSet) : string;
         var
         var
            hs1,hs2 : string;
            hs1,hs2 : string;
            l1,l2 : longint;
            l1,l2 : longint;
            w : integer;
            w : integer;
+           termType2: TCTETypeSet;
         begin
         begin
-          hs1:=read_factor;
+          hs1:=read_factor(termType);
           repeat
           repeat
             if (current_scanner.preproc_token<>_ID) then
             if (current_scanner.preproc_token<>_ID) then
               break;
               break;
             if current_scanner.preproc_pattern<>'AND' then
             if current_scanner.preproc_pattern<>'AND' then
               break;
               break;
+
+            {Check if first expr is boolean. Must be done here, after we know 
+             it is an AND expression.}
+            if not (ctetBoolean in termType) then
+              CTEError(termType, [ctetBoolean], 'AND');
+            termType:= [ctetBoolean];
+
             preproc_consume(_ID);
             preproc_consume(_ID);
-            hs2:=read_factor;
+            hs2:=read_factor(termType2);
+
+            if not (ctetBoolean in termType2) then
+              CTEError(termType2, [ctetBoolean], 'AND');
+
             val(hs1,l1,w);
             val(hs1,l1,w);
             val(hs2,l2,w);
             val(hs2,l2,w);
             if (l1<>0) and (l2<>0) then
             if (l1<>0) and (l2<>0) then
@@ -755,20 +903,32 @@ implementation
         end;
         end;
 
 
 
 
-        function read_simple_expr : string;
+        function read_simple_expr(var simpleExprType: TCTETypeSet) : string;
         var
         var
            hs1,hs2 : string;
            hs1,hs2 : string;
            l1,l2 : longint;
            l1,l2 : longint;
            w : integer;
            w : integer;
+           simpleExprType2: TCTETypeSet;
         begin
         begin
-          hs1:=read_term;
+          hs1:=read_term(simpleExprType);
           repeat
           repeat
             if (current_scanner.preproc_token<>_ID) then
             if (current_scanner.preproc_token<>_ID) then
               break;
               break;
             if current_scanner.preproc_pattern<>'OR' then
             if current_scanner.preproc_pattern<>'OR' then
               break;
               break;
+
+            {Check if first expr is boolean. Must be done here, after we know 
+             it is an OR expression.}
+            if not (ctetBoolean in simpleExprType) then
+              CTEError(simpleExprType, [ctetBoolean], 'OR');
+            simpleExprType:= [ctetBoolean];
+
             preproc_consume(_ID);
             preproc_consume(_ID);
-            hs2:=read_term;
+            hs2:=read_term(simpleExprType2);
+
+            if not (ctetBoolean in simpleExprType2) then
+              CTEError(simpleExprType2, [ctetBoolean], 'OR');
+
             val(hs1,l1,w);
             val(hs1,l1,w);
             val(hs2,l2,w);
             val(hs2,l2,w);
             if (l1<>0) or (l2<>0) then
             if (l1<>0) or (l2<>0) then
@@ -779,75 +939,97 @@ implementation
           read_simple_expr:=hs1;
           read_simple_expr:=hs1;
         end;
         end;
 
 
-        function read_expr : string;
+        function read_expr(var exprType: TCTETypeSet) : string;
         var
         var
            hs1,hs2 : string;
            hs1,hs2 : string;
            b : boolean;
            b : boolean;
-           t : ttoken;
+           op : ttoken;
            w : integer;
            w : integer;
            l1,l2 : longint;
            l1,l2 : longint;
+           exprType2: TCTETypeSet;
         begin
         begin
-           hs1:=read_simple_expr;
-           t:=current_scanner.preproc_token;
-           if (t = _ID) and (current_scanner.preproc_pattern = 'IN') then
-             t := _IN;
-           if not (t in [_IN,_EQUAL,_UNEQUAL,_LT,_GT,_LTE,_GTE]) then
+           hs1:=read_simple_expr(exprType);
+           op:=current_scanner.preproc_token;
+           if (op = _ID) and (current_scanner.preproc_pattern = 'IN') then
+             op := _IN;
+           if not (op in [_IN,_EQUAL,_UNEQUAL,_LT,_GT,_LTE,_GTE]) then
              begin
              begin
                 read_expr:=hs1;
                 read_expr:=hs1;
                 exit;
                 exit;
              end;
              end;
-           if (t = _IN) then
+             
+           if (op = _IN) then
              preproc_consume(_ID)
              preproc_consume(_ID)
            else
            else
-             preproc_consume(t);
-           hs2:=read_simple_expr;
-           if is_number(hs1) and is_number(hs2) then
+             preproc_consume(op);
+           hs2:=read_simple_expr(exprType2);
+
+           if op = _IN then
              begin
              begin
-                val(hs1,l1,w);
-                val(hs2,l2,w);
-                case t of
-                      _IN : Message(scan_e_preproc_syntax_error);
-                   _EQUAL : b:=l1=l2;
-                 _UNEQUAL : b:=l1<>l2;
-                      _LT : b:=l1<l2;
-                      _GT : b:=l1>l2;
-                     _GTE : b:=l1>=l2;
-                     _LTE : b:=l1<=l2;
-                end;
+               if exprType2 <> [ctetSet] then
+                 CTEError(exprType2, [ctetSet], 'IN');
+               if exprType = [ctetSet] then
+                 CTEError(exprType, setElementTypes, 'IN');
+
+              if is_number(hs1) and is_number(hs2) then
+                Message(scan_e_preproc_syntax_error)
+              else if hs2[1] = ',' then
+                b:=pos(','+hs1+',', hs2) > 0   { TODO For integer sets, perhaps check for numeric equivalence so that 0 = 00 }
+              else
+                Message(scan_e_preproc_syntax_error);
              end
              end
            else
            else
-             begin
-                case t of
-                      _IN : if hs2[1] = ',' then
-                              b:=pos(','+hs1+',', hs2) > 0
-                            else
-                              Message(scan_e_preproc_syntax_error);
-                   _EQUAL : b:=hs1=hs2;
-                 _UNEQUAL : b:=hs1<>hs2;
-                      _LT : b:=hs1<hs2;
-                      _GT : b:=hs1>hs2;
-                     _GTE : b:=hs1>=hs2;
-                     _LTE : b:=hs1<=hs2;
-                end;
-             end;
+						 begin
+							 if (exprType * exprType2) = [] then
+									CTEError(exprType2, exprType, tokeninfo^[op].str);
+	
+							 if is_number(hs1) and is_number(hs2) then
+								 begin
+										val(hs1,l1,w);
+										val(hs2,l2,w);
+										case op of
+											 _EQUAL : b:=l1=l2;
+										 _UNEQUAL : b:=l1<>l2;
+													_LT : b:=l1<l2;
+													_GT : b:=l1>l2;
+												 _GTE : b:=l1>=l2;
+												 _LTE : b:=l1<=l2;
+										end;
+								 end
+							 else
+								 begin
+										case op of
+											 _EQUAL : b:=hs1=hs2;
+										 _UNEQUAL : b:=hs1<>hs2;
+													_LT : b:=hs1<hs2;
+													_GT : b:=hs1>hs2;
+												 _GTE : b:=hs1>=hs2;
+												 _LTE : b:=hs1<=hs2;
+										end;
+								 end;
+						 end;
+
            if b then
            if b then
              read_expr:='1'
              read_expr:='1'
            else
            else
              read_expr:='0';
              read_expr:='0';
+           exprType:= [ctetBoolean];
         end;
         end;
-
      begin
      begin
         current_scanner.skipspace;
         current_scanner.skipspace;
         { start preproc expression scanner }
         { start preproc expression scanner }
         current_scanner.preproc_token:=current_scanner.readpreproc;
         current_scanner.preproc_token:=current_scanner.readpreproc;
-        parse_compiler_expr:=read_expr;
-      end;
+        parse_compiler_expr:=read_expr(compileExprType);
+     end;
 
 
     function boolean_compile_time_expr(var valuedescr: String): Boolean;
     function boolean_compile_time_expr(var valuedescr: String): Boolean;
       var
       var
         hs : string;
         hs : string;
+        exprType: TCTETypeSet;
       begin
       begin
-        hs:=parse_compiler_expr;
+        hs:=parse_compiler_expr(exprType);
+        if (exprType * [ctetBoolean]) = [] then
+          CTEError(exprType, [ctetBoolean], 'IF or ELSEIF');
         boolean_compile_time_expr:= hs <> '0';
         boolean_compile_time_expr:= hs <> '0';
         valuedescr:= hs;
         valuedescr:= hs;
       end;
       end;
@@ -862,7 +1044,7 @@ implementation
         current_scanner.elseifpreprocstack(@boolean_compile_time_expr);
         current_scanner.elseifpreprocstack(@boolean_compile_time_expr);
       end;
       end;
 
 
-    procedure dir_define;
+    procedure dir_define_impl(macstyle: boolean);
       var
       var
         hs  : string;
         hs  : string;
         bracketcount : longint;
         bracketcount : longint;
@@ -898,7 +1080,7 @@ implementation
              { !!!!!! handle macro params, need we this? }
              { !!!!!! handle macro params, need we this? }
              current_scanner.skipspace;
              current_scanner.skipspace;
 
 
-             if not (m_mac in aktmodeswitches) then
+             if not macstyle then
                begin
                begin
                  { may be a macro? }
                  { may be a macro? }
                  if c <> ':' then
                  if c <> ':' then
@@ -964,10 +1146,23 @@ implementation
           end;
           end;
       end;
       end;
 
 
+    procedure dir_define;
+      begin
+			  dir_define_impl(false);
+			end;
+
+    procedure dir_definec;
+      begin
+				dir_define_impl(true);
+			end;
+
     procedure dir_setc;
     procedure dir_setc;
       var
       var
         hs  : string;
         hs  : string;
         mac : tmacro;
         mac : tmacro;
+        exprType: TCTETypeSet;
+        l : longint;
+			  w : integer;
       begin
       begin
         current_scanner.skipspace;
         current_scanner.skipspace;
         hs:=current_scanner.readid;
         hs:=current_scanner.readid;
@@ -1008,9 +1203,22 @@ implementation
         if c='=' then
         if c='=' then
           begin
           begin
              current_scanner.readchar;
              current_scanner.readchar;
-             hs:= parse_compiler_expr;
+             hs:= parse_compiler_expr(exprType);
+             if (exprType * [ctetBoolean, ctetInteger]) = [] then
+               CTEError(exprType, [ctetBoolean, ctetInteger], 'SETC');
+
              if length(hs) <> 0 then
              if length(hs) <> 0 then
                begin
                begin
+							   {If we are absolutely shure it is boolean, translate
+								  to TRUE/FALSE to increase possibility to do future type check}
+							   if exprType = [ctetBoolean] then
+								   begin
+							       val(hs,l,w);
+                     if l<>0 then
+                       hs:='TRUE'
+                     else
+                       hs:='FALSE';
+                   end;
                  Message2(parser_c_macro_set_to,mac.name,hs);
                  Message2(parser_c_macro_set_to,mac.name,hs);
                  { free buffer of macro ?}
                  { free buffer of macro ?}
                  if assigned(mac.buftext) then
                  if assigned(mac.buftext) then
@@ -1067,13 +1275,13 @@ implementation
           hpath  : string;
           hpath  : string;
 
 
         begin
         begin
-         { look for the include file
+         (* look for the include file
 	   If path was specified as part of {$I } then
 	   If path was specified as part of {$I } then
 	    1. specified path (expanded with path of inputfile if relative)
 	    1. specified path (expanded with path of inputfile if relative)
            else
            else
             1. path of current inputfile,current dir
             1. path of current inputfile,current dir
             2. local includepath
             2. local includepath
-            3. global includepath }
+            3. global includepath *)
            found:=false;
            found:=false;
            foundfile:='';
            foundfile:='';
            hpath:='';
            hpath:='';
@@ -1695,8 +1903,6 @@ implementation
       end;
       end;
 
 
     procedure tscannerfile.elsepreprocstack;
     procedure tscannerfile.elsepreprocstack;
-      var
-        valuedescr: String;
       begin
       begin
         if assigned(preprocstack) and
         if assigned(preprocstack) and
            (preprocstack.typ<>pp_else) then
            (preprocstack.typ<>pp_else) then
@@ -3436,7 +3642,7 @@ exit_label:
 
 
         { Directives and conditionals for mode macpas: }
         { Directives and conditionals for mode macpas: }
         AddDirective('SETC',directive_mac, @dir_setc);
         AddDirective('SETC',directive_mac, @dir_setc);
-        AddDirective('DEFINEC',directive_mac, @dir_define);
+        AddDirective('DEFINEC',directive_mac, @dir_definec);
         AddDirective('UNDEFC',directive_mac, @dir_undef);
         AddDirective('UNDEFC',directive_mac, @dir_undef);
 
 
         AddConditional('IFC',directive_mac, @dir_if);
         AddConditional('IFC',directive_mac, @dir_if);

Some files were not shown because too many files changed in this diff