فهرست منبع

Merged revisions 2310,2312,2317,2320,2325,2331,2333,2340,2347,2358-2359,2373,2380-2381,2390,2402-2403,2405-2406,2436-2437 via svnmerge from
http://[email protected]/svn/fpc/trunk

........
r2310 | peter | 2006-01-17 09:44:57 +0100 (Tue, 17 Jan 2006) | 2 lines

* fix compare with null

........
r2312 | hajny | 2006-01-18 23:48:19 +0100 (Wed, 18 Jan 2006) | 1 line

* fix for web bug #4518 by Salvatore Licciardi
........
r2317 | jonas | 2006-01-21 21:19:19 +0100 (Sat, 21 Jan 2006) | 5 lines

* use vfork instead of fork for popen and one variant of executeprocess
if USE_VFORK is defined (currently only if both BSD and FPC_USE_LIBC
are defined). Speeds up the compilation of the compiler under Darwin
by 20-25% (the larger the project, the bigger the speedup).

........
r2320 | daniel | 2006-01-22 12:06:10 +0100 (Sun, 22 Jan 2006) | 3 lines

* Add --64 or --32 to as call to allow i386 make cycle using -Aas on
x64_64 systems.

........
r2325 | daniel | 2006-01-22 15:29:07 +0100 (Sun, 22 Jan 2006) | 2 lines

* Add --32 or --64 to to ensure functionality of i386 compiler on x64_64 OSes.

........
r2331 | olle | 2006-01-23 22:34:24 +0100 (Mon, 23 Jan 2006) | 1 line

Added short circuit evaluation of compile time expressions
........
r2333 | michael | 2006-01-24 21:04:46 +0100 (Tue, 24 Jan 2006) | 1 line

+ Enabled use of embedded firebird library.
........
r2340 | peter | 2006-01-25 23:05:31 +0100 (Wed, 25 Jan 2006) | 2 lines

* added missing varString,varOlestr to ordinals

........
r2347 | marco | 2006-01-26 22:11:37 +0100 (Thu, 26 Jan 2006) | 2 lines

* fdset is now array of unsigned.

........
r2358 | michael | 2006-01-28 19:07:23 +0100 (Sat, 28 Jan 2006) | 1 line

+ Patch from Graeme Geldenhuys to add delphi compatibility function
........
r2359 | michael | 2006-01-28 19:10:07 +0100 (Sat, 28 Jan 2006) | 1 line

+ Patch from Graeme Geldenhuys to fix ExtractFileDrive
........
r2373 | michael | 2006-01-29 11:28:37 +0100 (Sun, 29 Jan 2006) | 1 line

+ Patch from Michalis Kamburelis to fix hex2dec behaviour in case of error
........
r2380 | peter | 2006-01-29 20:46:14 +0100 (Sun, 29 Jan 2006) | 2 lines

* added sumInt

........
r2381 | jonas | 2006-01-29 23:46:46 +0100 (Sun, 29 Jan 2006) | 2 lines

+ added (not yet fixed)

........
r2390 | jonas | 2006-02-01 11:22:52 +0100 (Wed, 01 Feb 2006) | 4 lines

* fixed some FloatToStrF and FloatToStr precision problems. Still fails
for some corner cases (e.g. 8.502 as double), but that problem is in
str_real

........
r2402 | peter | 2006-02-02 10:03:02 +0100 (Thu, 02 Feb 2006) | 2 lines

* range check errors

........
r2403 | jonas | 2006-02-02 11:33:12 +0100 (Thu, 02 Feb 2006) | 2 lines

+ comp and int64 overloads for floattostr(f)

........
r2405 | peter | 2006-02-02 14:17:05 +0100 (Thu, 02 Feb 2006) | 2 lines

* test for enums in record

........
r2406 | peter | 2006-02-02 14:41:17 +0100 (Thu, 02 Feb 2006) | 2 lines

* more tests for symtable insert/search

........
r2436 | peter | 2006-02-05 02:55:44 +0100 (Sun, 05 Feb 2006) | 2 lines

* duplicate names fixed

........
r2437 | peter | 2006-02-05 02:57:23 +0100 (Sun, 05 Feb 2006) | 2 lines

* duplicate names fixed

........

git-svn-id: branches/fixes_2_0@2457 -

peter 19 سال پیش
والد
کامیت
8471e03e6e

+ 7 - 0
.gitattributes

@@ -4559,6 +4559,7 @@ tests/tbf/tb0174c.pp svneol=native#text/plain
 tests/tbf/tb0174d.pp svneol=native#text/plain
 tests/tbf/tb0174d.pp svneol=native#text/plain
 tests/tbf/tb0175.pp svneol=native#text/plain
 tests/tbf/tb0175.pp svneol=native#text/plain
 tests/tbf/tb0176.pp svneol=native#text/plain
 tests/tbf/tb0176.pp svneol=native#text/plain
+tests/tbf/tb0177.pp svneol=native#text/plain
 tests/tbf/ub0115.pp svneol=native#text/plain
 tests/tbf/ub0115.pp svneol=native#text/plain
 tests/tbf/ub0149.pp svneol=native#text/plain
 tests/tbf/ub0149.pp svneol=native#text/plain
 tests/tbf/ub0158a.pp svneol=native#text/plain
 tests/tbf/ub0158a.pp svneol=native#text/plain
@@ -5053,6 +5054,8 @@ tests/tbs/tb0496.pp svneol=native#text/plain
 tests/tbs/tb0497a.pp -text
 tests/tbs/tb0497a.pp -text
 tests/tbs/tb0497b.pp -text
 tests/tbs/tb0497b.pp -text
 tests/tbs/tb0497c.pp -text
 tests/tbs/tb0497c.pp -text
+tests/tbs/tb0498.pp svneol=native#text/plain
+tests/tbs/tb0499.pp svneol=native#text/plain
 tests/tbs/ub0060.pp svneol=native#text/plain
 tests/tbs/ub0060.pp svneol=native#text/plain
 tests/tbs/ub0069.pp svneol=native#text/plain
 tests/tbs/ub0069.pp svneol=native#text/plain
 tests/tbs/ub0119.pp svneol=native#text/plain
 tests/tbs/ub0119.pp svneol=native#text/plain
@@ -5403,6 +5406,7 @@ tests/test/tstring7.pp svneol=native#text/plain
 tests/test/tstring8.pp svneol=native#text/plain
 tests/test/tstring8.pp svneol=native#text/plain
 tests/test/tstrreal1.pp svneol=native#text/plain
 tests/test/tstrreal1.pp svneol=native#text/plain
 tests/test/tstrreal2.pp svneol=native#text/plain
 tests/test/tstrreal2.pp svneol=native#text/plain
+tests/test/tstrreal3.pp -text
 tests/test/tsubdecl.pp svneol=native#text/plain
 tests/test/tsubdecl.pp svneol=native#text/plain
 tests/test/tunit1.pp svneol=native#text/plain
 tests/test/tunit1.pp svneol=native#text/plain
 tests/test/tunit2.pp svneol=native#text/plain
 tests/test/tunit2.pp svneol=native#text/plain
@@ -6389,6 +6393,7 @@ tests/webtbs/tw4533.pp svneol=native#text/plain
 tests/webtbs/tw4534.pp svneol=native#text/plain
 tests/webtbs/tw4534.pp svneol=native#text/plain
 tests/webtbs/tw4537.pp svneol=native#text/plain
 tests/webtbs/tw4537.pp svneol=native#text/plain
 tests/webtbs/tw4540.pp -text svneol=unset#text/plain
 tests/webtbs/tw4540.pp -text svneol=unset#text/plain
+tests/webtbs/tw4541.pp svneol=native#text/plain
 tests/webtbs/tw4557.pp svneol=native#text/plain
 tests/webtbs/tw4557.pp svneol=native#text/plain
 tests/webtbs/tw4566.pp -text svneol=unset#text/plain
 tests/webtbs/tw4566.pp -text svneol=unset#text/plain
 tests/webtbs/tw4574.pp svneol=native#text/plain
 tests/webtbs/tw4574.pp svneol=native#text/plain
@@ -6402,6 +6407,7 @@ tests/webtbs/tw4635.pp svneol=native#text/plain
 tests/webtbs/tw4640.pp svneol=native#text/plain
 tests/webtbs/tw4640.pp svneol=native#text/plain
 tests/webtbs/tw4669.pp svneol=native#text/plain
 tests/webtbs/tw4669.pp svneol=native#text/plain
 tests/webtbs/tw4675.pp svneol=native#text/plain
 tests/webtbs/tw4675.pp svneol=native#text/plain
+tests/webtbs/tw4700.pp svneol=native#text/plain
 tests/webtbs/ub1873.pp svneol=native#text/plain
 tests/webtbs/ub1873.pp svneol=native#text/plain
 tests/webtbs/ub1883.pp svneol=native#text/plain
 tests/webtbs/ub1883.pp svneol=native#text/plain
 tests/webtbs/uw0555.pp svneol=native#text/plain
 tests/webtbs/uw0555.pp svneol=native#text/plain
@@ -6446,6 +6452,7 @@ tests/webtbs/uw4352b.pp svneol=native#text/plain
 tests/webtbs/uw4352c.pp svneol=native#text/plain
 tests/webtbs/uw4352c.pp svneol=native#text/plain
 tests/webtbs/uw4352d.pp svneol=native#text/plain
 tests/webtbs/uw4352d.pp svneol=native#text/plain
 tests/webtbs/uw4352e.pp svneol=native#text/plain
 tests/webtbs/uw4352e.pp svneol=native#text/plain
+tests/webtbs/uw4541.pp svneol=native#text/plain
 utils/Makefile svneol=native#text/plain
 utils/Makefile svneol=native#text/plain
 utils/Makefile.fpc svneol=native#text/plain
 utils/Makefile.fpc svneol=native#text/plain
 utils/README -text
 utils/README -text

+ 165 - 124
compiler/scanner.pas

@@ -510,6 +510,12 @@ The TRUE/FALSE format is new from 22 august 2005, but the above scheme
 means that units which is not recompiled, and thus stores
 means that units which is not recompiled, and thus stores
 compile time variables as the old format (0/1), continue to work.
 compile time variables as the old format (0/1), continue to work.
 
 
+Short circuit evaluation
+------------------------
+For this to work, the part of a compile time expression which is short
+circuited, should not be evaluated, while it still should be parsed.
+Therefor there is a parameter eval, telling whether evaluation is needed.
+In case not, the value returned can be arbitrary.
 }
 }
 
 
     type
     type
@@ -550,16 +556,16 @@ compile time variables as the old format (0/1), continue to work.
 
 
     function parse_compiler_expr(var compileExprType: TCTETypeSet):string;
     function parse_compiler_expr(var compileExprType: TCTETypeSet):string;
 
 
-        function read_expr(var exprType: TCTETypeSet) : string; forward;
+        function read_expr(var exprType: TCTETypeSet; eval : Boolean) : string; forward;
 
 
         procedure preproc_consume(t : ttoken);
         procedure preproc_consume(t : ttoken);
         begin
         begin
           if t<>current_scanner.preproc_token then
           if t<>current_scanner.preproc_token then
-           Message(scan_e_preproc_syntax_error);
+            Message(scan_e_preproc_syntax_error);
           current_scanner.preproc_token:=current_scanner.readpreproc;
           current_scanner.preproc_token:=current_scanner.readpreproc;
         end;
         end;
 
 
-        function preproc_substitutedtoken(var macroType: TCTETypeSet): string;
+        function preproc_substitutedtoken(var macroType: TCTETypeSet; eval : Boolean): string;
                                 { Currently this parses identifiers as well as numbers.
                                 { Currently this parses identifiers as well as numbers.
           The result from this procedure can either be that the token
           The result from this procedure can either be that the token
           itself is a value, or that it is a compile time variable/macro,
           itself is a value, or that it is a compile time variable/macro,
@@ -575,6 +581,9 @@ compile time variables as the old format (0/1), continue to work.
           w: word;
           w: word;
         begin
         begin
           result := current_scanner.preproc_pattern;
           result := current_scanner.preproc_pattern;
+          if not eval then
+            exit;
+
           mac:= nil;
           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. }
@@ -651,7 +660,7 @@ compile time variables as the old format (0/1), continue to work.
             macroType:= [ctetString];
             macroType:= [ctetString];
         end;
         end;
 
 
-        function read_factor(var factorType: TCTETypeSet) : string;
+        function read_factor(var factorType: TCTETypeSet; eval : Boolean) : string;
         var
         var
            hs : string;
            hs : string;
            mac: tmacro;
            mac: tmacro;
@@ -777,33 +786,36 @@ compile time variables as the old format (0/1), continue to work.
                         current_scanner.skipspace;
                         current_scanner.skipspace;
                       end
                       end
                     else
                     else
-                      Message(scan_e_error_in_preproc_expr);
-                    if searchsym(current_scanner.preproc_pattern,srsym,srsymtable) then
-                      begin
-                        l:=0;
-                        case srsym.typ of
-                          globalvarsym,
-                          localvarsym,
-                          paravarsym :
-                            l:=tabstractvarsym(srsym).getsize;
-                          typedconstsym :
-                            l:=ttypedconstsym(srsym).getsize;
-                          typesym:
-                            l:=ttypesym(srsym).restype.def.size;
-                          else
-                            Message(scan_e_error_in_preproc_expr);
-                        end;
-                        str(l,read_factor);
-                        preproc_consume(_ID);
-                        current_scanner.skipspace;
-                      end
-                    else
-                      Message1(sym_e_id_not_found,current_scanner.preproc_pattern);
+                      Message(scan_e_preproc_syntax_error);
+
+                    if eval then
+                      if searchsym(current_scanner.preproc_pattern,srsym,srsymtable) then
+                        begin
+                          l:=0;
+                          case srsym.typ of
+                            globalvarsym,
+                            localvarsym,
+                            paravarsym :
+                              l:=tabstractvarsym(srsym).getsize;
+                            typedconstsym :
+                              l:=ttypedconstsym(srsym).getsize;
+                            typesym:
+                              l:=ttypesym(srsym).restype.def.size;
+                            else
+                              Message(scan_e_error_in_preproc_expr);
+                          end;
+                          str(l,read_factor);
+                        end
+                      else
+                        Message1(sym_e_id_not_found,current_scanner.preproc_pattern);
+
+                    preproc_consume(_ID);
+                    current_scanner.skipspace;
 
 
                     if current_scanner.preproc_token =_RKLAMMER then
                     if current_scanner.preproc_token =_RKLAMMER then
                       preproc_consume(_RKLAMMER)
                       preproc_consume(_RKLAMMER)
                     else
                     else
-                      Message(scan_e_error_in_preproc_expr);
+                      Message(scan_e_preproc_syntax_error);
                   end
                   end
                 else
                 else
                 if current_scanner.preproc_pattern='DECLARED' then
                 if current_scanner.preproc_pattern='DECLARED' then
@@ -841,14 +853,19 @@ compile time variables as the old format (0/1), continue to work.
                   begin
                   begin
                     factorType:= [ctetBoolean];
                     factorType:= [ctetBoolean];
                     preproc_consume(_ID);
                     preproc_consume(_ID);
-                    hs:=read_factor(factorType);
-                    if not (ctetBoolean in factorType) then
-                      CTEError(factorType, [ctetBoolean], 'NOT');
-                    val(hs,l,w);
-                    if l<>0 then
-                      read_factor:='0'
+                    hs:=read_factor(factorType, eval);
+                    if eval then
+                      begin
+                        if not (ctetBoolean in factorType) then
+                          CTEError(factorType, [ctetBoolean], 'NOT');
+                        val(hs,l,w);
+                        if l<>0 then
+                          read_factor:='0'
+                        else
+                          read_factor:='1';
+                      end
                     else
                     else
-                      read_factor:='1';
+                      read_factor:='0'; {Just to have something}
                   end
                   end
                 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
@@ -866,11 +883,11 @@ compile time variables as the old format (0/1), continue to work.
                   end
                   end
                 else
                 else
                   begin
                   begin
-                    hs:=preproc_substitutedtoken(factorType);
+                    hs:=preproc_substitutedtoken(factorType, eval);
 
 
                     { 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) and (ctetString in factorType) then
+                    if eval and (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
@@ -938,7 +955,7 @@ compile time variables as the old format (0/1), continue to work.
            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(factorType);
+                read_factor:=read_expr(factorType, eval);
                 preproc_consume(_RKLAMMER);
                 preproc_consume(_RKLAMMER);
              end
              end
            else if current_scanner.preproc_token = _LECKKLAMMER then
            else if current_scanner.preproc_token = _LECKKLAMMER then
@@ -947,7 +964,7 @@ compile time variables as the old format (0/1), continue to work.
                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(setElemType)+',';
+                 read_factor := read_factor+read_factor(setElemType, eval)+',';
                  if current_scanner.preproc_token = _COMMA then
                  if current_scanner.preproc_token = _COMMA then
                    preproc_consume(_COMMA);
                    preproc_consume(_COMMA);
                end;
                end;
@@ -959,80 +976,98 @@ compile time variables as the old format (0/1), continue to work.
              Message(scan_e_error_in_preproc_expr);
              Message(scan_e_error_in_preproc_expr);
         end;
         end;
 
 
-        function read_term(var termType: TCTETypeSet) : string;
+        function read_term(var termType: TCTETypeSet; eval : Boolean) : string;
         var
         var
            hs1,hs2 : string;
            hs1,hs2 : string;
            l1,l2 : longint;
            l1,l2 : longint;
            w : integer;
            w : integer;
            termType2: TCTETypeSet;
            termType2: TCTETypeSet;
         begin
         begin
-          hs1:=read_factor(termType);
+          hs1:=read_factor(termType, eval);
           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];
+            val(hs1,l1,w);
+            if l1=0 then
+              eval:= false; {Short circuit evaluation of OR}
+
+            if eval then
+               begin
+                {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];
+              end;
 
 
             preproc_consume(_ID);
             preproc_consume(_ID);
-            hs2:=read_factor(termType2);
+            hs2:=read_factor(termType2, eval);
 
 
-            if not (ctetBoolean in termType2) then
-              CTEError(termType2, [ctetBoolean], 'AND');
+            if eval then
+              begin
+                if not (ctetBoolean in termType2) then
+                  CTEError(termType2, [ctetBoolean], 'AND');
 
 
-            val(hs1,l1,w);
-            val(hs2,l2,w);
-            if (l1<>0) and (l2<>0) then
-              hs1:='1'
-            else
-              hs1:='0';
+                val(hs2,l2,w);
+                if (l1<>0) and (l2<>0) then
+                  hs1:='1'
+                else
+                  hs1:='0';
+              end;
            until false;
            until false;
            read_term:=hs1;
            read_term:=hs1;
         end;
         end;
 
 
 
 
-        function read_simple_expr(var simpleExprType: TCTETypeSet) : string;
+        function read_simple_expr(var simpleExprType: TCTETypeSet; eval : Boolean) : string;
         var
         var
            hs1,hs2 : string;
            hs1,hs2 : string;
            l1,l2 : longint;
            l1,l2 : longint;
            w : integer;
            w : integer;
            simpleExprType2: TCTETypeSet;
            simpleExprType2: TCTETypeSet;
         begin
         begin
-          hs1:=read_term(simpleExprType);
+          hs1:=read_term(simpleExprType, eval);
           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];
+            val(hs1,l1,w);
+            if l1<>0 then
+              eval:= false; {Short circuit evaluation of OR}
+
+            if eval then
+              begin
+                {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];
+              end;
 
 
             preproc_consume(_ID);
             preproc_consume(_ID);
-            hs2:=read_term(simpleExprType2);
+            hs2:=read_term(simpleExprType2, eval);
 
 
-            if not (ctetBoolean in simpleExprType2) then
-              CTEError(simpleExprType2, [ctetBoolean], 'OR');
+            if eval then
+              begin
+                if not (ctetBoolean in simpleExprType2) then
+                  CTEError(simpleExprType2, [ctetBoolean], 'OR');
 
 
-            val(hs1,l1,w);
-            val(hs2,l2,w);
-            if (l1<>0) or (l2<>0) then
-              hs1:='1'
-            else
-              hs1:='0';
+                val(hs2,l2,w);
+                if (l1<>0) or (l2<>0) then
+                  hs1:='1'
+                else
+                  hs1:='0';
+              end;
           until false;
           until false;
           read_simple_expr:=hs1;
           read_simple_expr:=hs1;
         end;
         end;
 
 
-        function read_expr(var exprType: TCTETypeSet) : string;
+        function read_expr(var exprType: TCTETypeSet; eval : Boolean) : string;
         var
         var
            hs1,hs2 : string;
            hs1,hs2 : string;
            b : boolean;
            b : boolean;
@@ -1041,7 +1076,7 @@ compile time variables as the old format (0/1), continue to work.
            l1,l2 : longint;
            l1,l2 : longint;
            exprType2: TCTETypeSet;
            exprType2: TCTETypeSet;
         begin
         begin
-           hs1:=read_simple_expr(exprType);
+           hs1:=read_simple_expr(exprType, eval);
            op:=current_scanner.preproc_token;
            op:=current_scanner.preproc_token;
            if (op = _ID) and (current_scanner.preproc_pattern = 'IN') then
            if (op = _ID) and (current_scanner.preproc_pattern = 'IN') then
              op := _IN;
              op := _IN;
@@ -1055,64 +1090,69 @@ compile time variables as the old format (0/1), continue to work.
              preproc_consume(_ID)
              preproc_consume(_ID)
            else
            else
              preproc_consume(op);
              preproc_consume(op);
-           hs2:=read_simple_expr(exprType2);
+           hs2:=read_simple_expr(exprType2, eval);
 
 
-           if op = _IN then
-             begin
-               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
-           else
+           if eval then
              begin
              begin
-               if (exprType * exprType2) = [] then
-                 CTEError(exprType2, exprType, tokeninfo^[op].str);
-
-               if is_number(hs1) and is_number(hs2) then
+               if op = _IN then
                  begin
                  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;
+                   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
                  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;
+                   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;
                  end;
-             end;
+              end
+           else
+             b:= false; {Just to have something}
 
 
            if b then
            if b then
              read_expr:='1'
              read_expr:='1'
@@ -1120,11 +1160,12 @@ compile time variables as the old format (0/1), continue to work.
              read_expr:='0';
              read_expr:='0';
            exprType:= [ctetBoolean];
            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(compileExprType);
+        parse_compiler_expr:=read_expr(compileExprType, true);
      end;
      end;
 
 
     function boolean_compile_time_expr(var valuedescr: String): Boolean;
     function boolean_compile_time_expr(var valuedescr: String): Boolean;

+ 2 - 2
fv/dialogs.pas

@@ -1335,11 +1335,11 @@ END;
 {---------------------------------------------------------------------------}
 {---------------------------------------------------------------------------}
 FUNCTION TInputLine.Valid (Command: Word): Boolean;
 FUNCTION TInputLine.Valid (Command: Word): Boolean;
 
 
-   FUNCTION AppendError (Validator: PValidator): Boolean;
+   FUNCTION AppendError (AValidator: PValidator): Boolean;
    BEGIN
    BEGIN
      AppendError := False;                            { Preset false }
      AppendError := False;                            { Preset false }
      If (Data <> Nil) Then
      If (Data <> Nil) Then
-       With Validator^ Do
+       With AValidator^ Do
          If (Options AND voOnAppend <> 0) AND         { Check options }
          If (Options AND voOnAppend <> 0) AND         { Check options }
          (CurPos <> Length(Data^)) AND                { Exceeds max length }
          (CurPos <> Length(Data^)) AND                { Exceeds max length }
          NOT IsValidInput(Data^, True) Then Begin     { Check data valid }
          NOT IsValidInput(Data^, True) Then Begin     { Check data valid }

+ 9 - 9
fv/menus.pas

@@ -430,10 +430,10 @@ END;
 CONSTRUCTOR TMenuView.Load (Var S: TStream);
 CONSTRUCTOR TMenuView.Load (Var S: TStream);
 
 
    FUNCTION DoLoadMenu: PMenu;
    FUNCTION DoLoadMenu: PMenu;
-   VAR Tok: Byte; Item: PMenuItem; Last: ^PMenuItem; Menu: PMenu;
+   VAR Tok: Byte; Item: PMenuItem; Last: ^PMenuItem; HMenu: PMenu;
    BEGIN
    BEGIN
-     New(Menu);                                       { Create new menu }
-     Last := @Menu^.Items;                            { Start on first item }
+     New(HMenu);                                       { Create new menu }
+     Last := @HMenu^.Items;                            { Start on first item }
      Item := Nil;                                     { Clear pointer }
      Item := Nil;                                     { Clear pointer }
      S.Read(Tok, SizeOf(Tok));                        { Read token }
      S.Read(Tok, SizeOf(Tok));                        { Read token }
      While (Tok <> 0) Do Begin
      While (Tok <> 0) Do Begin
@@ -460,8 +460,8 @@ CONSTRUCTOR TMenuView.Load (Var S: TStream);
        S.Read(Tok, SizeOf(Tok));                      { Read token }
        S.Read(Tok, SizeOf(Tok));                      { Read token }
      End;
      End;
      Last^ := Nil;                                    { List complete }
      Last^ := Nil;                                    { List complete }
-     Menu^.Default := Menu^.Items;                    { Set menu default }
-     DoLoadMenu := Menu;                              { Return menu }
+     HMenu^.Default := HMenu^.Items;                    { Set menu default }
+     DoLoadMenu := HMenu;                              { Return menu }
    End;
    End;
 
 
 BEGIN
 BEGIN
@@ -772,11 +772,11 @@ END;
 {---------------------------------------------------------------------------}
 {---------------------------------------------------------------------------}
 PROCEDURE TMenuView.Store (Var S: TStream);
 PROCEDURE TMenuView.Store (Var S: TStream);
 
 
-   PROCEDURE DoStoreMenu (Menu: PMenu);
+   PROCEDURE DoStoreMenu (AMenu: PMenu);
    VAR Item: PMenuItem; Tok: Byte;
    VAR Item: PMenuItem; Tok: Byte;
    BEGIN
    BEGIN
      Tok := $FF;                                      { Preset max count }
      Tok := $FF;                                      { Preset max count }
-     Item := Menu^.Items;                             { Start first item }
+     Item := AMenu^.Items;                             { Start first item }
      While (Item <> Nil) Do Begin
      While (Item <> Nil) Do Begin
        With Item^ Do Begin
        With Item^ Do Begin
          S.Write(Tok, SizeOf(Tok));                      { Write tok value }
          S.Write(Tok, SizeOf(Tok));                      { Write tok value }
@@ -806,10 +806,10 @@ END;
 PROCEDURE TMenuView.HandleEvent (Var Event: TEvent);
 PROCEDURE TMenuView.HandleEvent (Var Event: TEvent);
 VAR CallDraw: Boolean; P: PMenuItem;
 VAR CallDraw: Boolean; P: PMenuItem;
 
 
-   PROCEDURE UpdateMenu (Menu: PMenu);
+   PROCEDURE UpdateMenu (AMenu: PMenu);
    VAR P: PMenuItem; CommandState: Boolean;
    VAR P: PMenuItem; CommandState: Boolean;
    BEGIN
    BEGIN
-     P := Menu^.Items;                                { Start on first item }
+     P := AMenu^.Items;                                { Start on first item }
      While (P <> Nil) Do Begin
      While (P <> Nil) Do Begin
        If (P^.Name <> Nil) Then                       { Valid name }
        If (P^.Name <> Nil) Then                       { Valid name }
        If (P^.Command = 0) Then UpdateMenu(P^.SubMenu){ Update menu }
        If (P^.Command = 0) Then UpdateMenu(P^.SubMenu){ Update menu }

+ 1 - 1
ide/fpcalc.pas

@@ -371,7 +371,7 @@ begin
                   '*', '/': R := R / 100;
                   '*', '/': R := R / 100;
                 end;
                 end;
               case _Operator of
               case _Operator of
-                '^': SetDisplay(Power(Operand,R),false);
+                '^': if (Operand = 0)and(R <= 0) then Error else SetDisplay(Power(Operand,R),false);
                 '+': SetDisplay(Operand + R,false);
                 '+': SetDisplay(Operand + R,false);
                 '-': SetDisplay(Operand - R,false);
                 '-': SetDisplay(Operand - R,false);
                 '*': SetDisplay(Operand * R,false);
                 '*': SetDisplay(Operand * R,false);

+ 23 - 8
packages/base/ibase/ibase60.inc

@@ -8,6 +8,10 @@ interface
 
 
 {$IFDEF LinkDynamically}
 {$IFDEF LinkDynamically}
 uses Dynlibs, sysutils;
 uses Dynlibs, sysutils;
+
+Var
+  UseEmbeddedFirebird : Boolean = False;
+
 {$ENDIF}
 {$ENDIF}
 
 
 {$IFDEF Unix}
 {$IFDEF Unix}
@@ -15,18 +19,21 @@ uses Dynlibs, sysutils;
   const
   const
     gdslib = 'libgds.so';
     gdslib = 'libgds.so';
     fbclib = 'libfbclient.so';
     fbclib = 'libfbclient.so';
+    fbembedlib = 'libfbembed.so';
 {$ENDIF}
 {$ENDIF}
 {$IFDEF Win32}
 {$IFDEF Win32}
   {$DEFINE extdecl:=stdcall}
   {$DEFINE extdecl:=stdcall}
   const
   const
     gdslib = 'gds32.dll';
     gdslib = 'gds32.dll';
     fbclib = 'fbclient.dll';
     fbclib = 'fbclient.dll';
+    fbembedlib = 'fbembed.dll';
 {$ENDIF}
 {$ENDIF}
 {$IFDEF Wince}
 {$IFDEF Wince}
   {$DEFINE extdecl:=stdcall}
   {$DEFINE extdecl:=stdcall}
   const
   const
     gdslib = 'gds32.dll';
     gdslib = 'gds32.dll';
     fbclib = 'fbclient.dll';
     fbclib = 'fbclient.dll';
+    fbembedlib = 'fbembed.dll';
 {$ENDIF}
 {$ENDIF}
 
 
 type
 type
@@ -2456,17 +2463,25 @@ begin
   inc(RefCount);
   inc(RefCount);
   if RefCount = 1 then
   if RefCount = 1 then
     begin
     begin
-    IBaseLibraryHandle := loadlibrary(fbclib);
-    if IBaseLibraryHandle = nilhandle then
+    If UseEmbeddedFirebird then
       begin
       begin
-      IBaseLibraryHandle := loadlibrary(gdslib);
-      if loadlibrary(gdslib) = nilhandle then
+      IBaseLibraryHandle:=loadlibrary(fbembedlib);
+      if (IBaseLibraryHandle=nilhandle) then
+        Raise EInOutError.Create('Can not load Firebird Embedded client. Is it installed? ('+fbembedlib+')');
+      end
+    else 
+      begin
+      IBaseLibraryHandle:=loadlibrary(fbclib);
+      if (IBaseLibraryHandle=nilhandle) then
         begin
         begin
-        RefCount := 0;
-        Raise EInOutError.Create('Can not load Firebird or Interbase client. Is it installed? ('+gdslib+' or '+fbclib+')');
+        IBaseLibraryHandle:=loadlibrary(gdslib);
+        if (IBaseLibraryHandle=nilhandle) then
+          begin
+          RefCount := 0;
+          Raise EInOutError.Create('Can not load Firebird or Interbase client. Is it installed? ('+gdslib+' or '+fbclib+')');
+          end;
         end;
         end;
-      end;
-
+      end;  
     pointer(isc_attach_database) := GetProcedureAddress(IBaseLibraryHandle,'isc_attach_database');
     pointer(isc_attach_database) := GetProcedureAddress(IBaseLibraryHandle,'isc_attach_database');
     pointer(isc_array_gen_sdl) := GetProcedureAddress(IBaseLibraryHandle,'isc_array_gen_sdl');
     pointer(isc_array_gen_sdl) := GetProcedureAddress(IBaseLibraryHandle,'isc_array_gen_sdl');
     pointer(isc_array_get_slice) := GetProcedureAddress(IBaseLibraryHandle,'isc_array_get_slice');
     pointer(isc_array_get_slice) := GetProcedureAddress(IBaseLibraryHandle,'isc_array_get_slice');

+ 2 - 1
rtl/linux/ostypes.inc

@@ -1,3 +1,4 @@
+
 {
 {
     This file is part of the Free Pascal run time library.
     This file is part of the Free Pascal run time library.
     Copyright (c) 2001 by Free Pascal development team
     Copyright (c) 2001 by Free Pascal development team
@@ -207,7 +208,7 @@ type
    TTms      = tms;
    TTms      = tms;
    PTms      = ^tms;
    PTms      = ^tms;
 
 
- TFDSet    = ARRAY[0..(FD_MAXFDSET div BITSINWORD)-1] of cLong;
+ TFDSet    = ARRAY[0..(FD_MAXFDSET div BITSINWORD)-1] of cuLong;
  pFDSet    = ^TFDSet;
  pFDSet    = ^TFDSet;
 
 
   timezone = packed record
   timezone = packed record

+ 67 - 10
rtl/objpas/cvarutil.inc

@@ -56,7 +56,8 @@ end;
   ---------------------------------------------------------------------}
   ---------------------------------------------------------------------}
 
 
 Function VariantToSmallInt(Const VargSrc : TVarData) : SmallInt;
 Function VariantToSmallInt(Const VargSrc : TVarData) : SmallInt;
-
+var
+  l : longint;
 begin
 begin
   With VargSrc do
   With VargSrc do
     Case (VType and VarTypeMask) of
     Case (VType and VarTypeMask) of
@@ -67,20 +68,32 @@ begin
       VarDouble  : Result:=Round(VDouble);
       VarDouble  : Result:=Round(VDouble);
       VarCurrency: Result:=Round(VCurrency);
       VarCurrency: Result:=Round(VCurrency);
       VarDate    : Result:=Round(VDate);
       VarDate    : Result:=Round(VDate);
-      VarOleStr  : Result:=StrToInt(WideCharToString(vOleStr));
       VarBoolean : Result:=SmallInt(VBoolean);
       VarBoolean : Result:=SmallInt(VBoolean);
       VarByte    : Result:=VByte;
       VarByte    : Result:=VByte;
       VarWord    : Result:=VWord;
       VarWord    : Result:=VWord;
       VarLongWord   : Result:=VLongWord;
       VarLongWord   : Result:=VLongWord;
       VarInt64   : Result:=VInt64;
       VarInt64   : Result:=VInt64;
       VarQword   : Result:=VQWord;
       VarQword   : Result:=VQWord;
+      VarOleStr  :
+        begin
+          if not(TryStrToInt(WideCharToString(vOleStr),l)) then
+            VariantTypeMismatch;
+          result:=l;
+        end;
+      VarString  :
+        begin
+          if not(TryStrToInt(ansistring(vString),l)) then
+            VariantTypeMismatch;
+          result:=l;
+        end;
   else
   else
     VariantTypeMismatch;
     VariantTypeMismatch;
   end;
   end;
 end;
 end;
 
 
 Function VariantToShortInt(Const VargSrc : TVarData) : ShortInt;
 Function VariantToShortInt(Const VargSrc : TVarData) : ShortInt;
-
+var
+  l : longint;
 begin
 begin
   With VargSrc do
   With VargSrc do
     Case (VType and VarTypeMask) of
     Case (VType and VarTypeMask) of
@@ -91,13 +104,24 @@ begin
       VarDouble  : Result:=Round(VDouble);
       VarDouble  : Result:=Round(VDouble);
       VarCurrency: Result:=Round(VCurrency);
       VarCurrency: Result:=Round(VCurrency);
       VarDate    : Result:=Round(VDate);
       VarDate    : Result:=Round(VDate);
-      VarOleStr  : Result:=StrToInt(WideCharToString(vOleStr));
       VarBoolean : Result:=SmallInt(VBoolean);
       VarBoolean : Result:=SmallInt(VBoolean);
       VarByte    : Result:=VByte;
       VarByte    : Result:=VByte;
       VarWord    : Result:=VWord;
       VarWord    : Result:=VWord;
       VarLongWord   : Result:=VLongWord;
       VarLongWord   : Result:=VLongWord;
       VarInt64   : Result:=VInt64;
       VarInt64   : Result:=VInt64;
       VarQword   : Result:=VQWord;
       VarQword   : Result:=VQWord;
+      VarOleStr  :
+        begin
+          if not(TryStrToInt(WideCharToString(vOleStr),l)) then
+            VariantTypeMismatch;
+          result:=l;
+        end;
+      VarString  :
+        begin
+          if not(TryStrToInt(ansistring(vString),l)) then
+            VariantTypeMismatch;
+          result:=l;
+        end;
   else
   else
     VariantTypeMismatch;
     VariantTypeMismatch;
   end;
   end;
@@ -191,7 +215,6 @@ Function VariantToSingle(Const VargSrc : TVarData) : Single;
             if not(TryStrToFloat(ansistring(vString),Result)) then
             if not(TryStrToFloat(ansistring(vString),Result)) then
               VariantTypeMismatch;
               VariantTypeMismatch;
           end;
           end;
-
         VarBoolean : Result:=Longint(VBoolean);
         VarBoolean : Result:=Longint(VBoolean);
         VarByte    : Result:=VByte;
         VarByte    : Result:=VByte;
         VarWord    : Result:=VWord;
         VarWord    : Result:=VWord;
@@ -220,6 +243,11 @@ Function VariantToDouble(Const VargSrc : TVarData) : Double;
             if not(TryStrToFloat(WideCharToString(vOleStr),Result)) then
             if not(TryStrToFloat(WideCharToString(vOleStr),Result)) then
               VariantTypeMismatch;
               VariantTypeMismatch;
           end;
           end;
+        VarString  :
+          begin
+            if not(TryStrToFloat(ansistring(vString),Result)) then
+              VariantTypeMismatch;
+          end;
         VarBoolean : Result:=Longint(VBoolean);
         VarBoolean : Result:=Longint(VBoolean);
         VarByte    : Result:=VByte;
         VarByte    : Result:=VByte;
         VarWord    : Result:=VWord;
         VarWord    : Result:=VWord;
@@ -324,7 +352,8 @@ begin
 end;
 end;
 
 
 Function VariantToByte(Const VargSrc : TVarData) : Byte;
 Function VariantToByte(Const VargSrc : TVarData) : Byte;
-
+var
+  l : longint;
 begin
 begin
   Try
   Try
     With VargSrc do
     With VargSrc do
@@ -336,13 +365,24 @@ begin
         VarDouble  : Result:=Round(VDouble);
         VarDouble  : Result:=Round(VDouble);
         VarCurrency: Result:=Round(VCurrency);
         VarCurrency: Result:=Round(VCurrency);
         VarDate    : Result:=Round(VDate);
         VarDate    : Result:=Round(VDate);
-        VarOleStr  : NoWideStrings;
         VarBoolean : Result:=Longint(VBoolean);
         VarBoolean : Result:=Longint(VBoolean);
         VarByte    : Result:=VByte;
         VarByte    : Result:=VByte;
         VarWord    : Result:=VWord;
         VarWord    : Result:=VWord;
         VarLongWord   : Result:=VLongWord;
         VarLongWord   : Result:=VLongWord;
         VarInt64   : Result:=Vint64;
         VarInt64   : Result:=Vint64;
         VarQword   : Result:=VQWord;
         VarQword   : Result:=VQWord;
+      VarOleStr  :
+        begin
+          if not(TryStrToInt(WideCharToString(vOleStr),l)) then
+            VariantTypeMismatch;
+          result:=l;
+        end;
+      VarString  :
+        begin
+          if not(TryStrToInt(ansistring(vString),l)) then
+            VariantTypeMismatch;
+          result:=l;
+        end;
     else
     else
       VariantTypeMismatch;
       VariantTypeMismatch;
     end;
     end;
@@ -367,13 +407,18 @@ begin
         VarDouble  : Result:=Trunc(VDouble);
         VarDouble  : Result:=Trunc(VDouble);
         VarCurrency: Result:=Trunc(VCurrency);
         VarCurrency: Result:=Trunc(VCurrency);
         VarDate    : Result:=Trunc(VDate);
         VarDate    : Result:=Trunc(VDate);
-        VarOleStr  : NoWideStrings;
         VarBoolean : Result:=Longint(VBoolean);
         VarBoolean : Result:=Longint(VBoolean);
         VarByte    : Result:=VByte;
         VarByte    : Result:=VByte;
         VarWord    : Result:=VWord;
         VarWord    : Result:=VWord;
         VarLongWord   : Result:=VLongWord;
         VarLongWord   : Result:=VLongWord;
         VarInt64   : Result:=VInt64;
         VarInt64   : Result:=VInt64;
         VarQword   : Result:=VQWord;
         VarQword   : Result:=VQWord;
+        VarOleStr  :
+          if not(TryStrToInt64(WideCharToString(vOleStr),Result)) then
+            VariantTypeMismatch;
+        VarString  :
+          if not(TryStrToInt64(ansistring(vString),Result)) then
+            VariantTypeMismatch;
     else
     else
       VariantTypeMismatch;
       VariantTypeMismatch;
     end;
     end;
@@ -386,7 +431,8 @@ begin
 end;
 end;
 
 
 Function VariantToQWord(Const VargSrc : TVarData) : QWord;
 Function VariantToQWord(Const VargSrc : TVarData) : QWord;
-
+var
+  l : int64;
 begin
 begin
   Try
   Try
     With VargSrc do
     With VargSrc do
@@ -398,13 +444,24 @@ begin
         VarDouble  : Result:=Trunc(VDouble);
         VarDouble  : Result:=Trunc(VDouble);
         VarCurrency: Result:=Trunc(VCurrency);
         VarCurrency: Result:=Trunc(VCurrency);
         VarDate    : Result:=Trunc(VDate);
         VarDate    : Result:=Trunc(VDate);
-        VarOleStr  : NoWideStrings;
         VarBoolean : Result:=Longint(VBoolean);
         VarBoolean : Result:=Longint(VBoolean);
         VarByte    : Result:=VByte;
         VarByte    : Result:=VByte;
         VarWord    : Result:=VWord;
         VarWord    : Result:=VWord;
         VarLongWord   : Result:=VLongWord;
         VarLongWord   : Result:=VLongWord;
         VarInt64   : Result:=VInt64;
         VarInt64   : Result:=VInt64;
         VarQword   : Result:=VQWord;
         VarQword   : Result:=VQWord;
+        VarOleStr  :
+          begin
+            if not(TryStrToInt64(WideCharToString(vOleStr),l)) then
+              VariantTypeMismatch;
+            result:=l;
+          end;
+        VarString  :
+          begin
+            if not(TryStrToInt64(ansistring(vString),l)) then
+              VariantTypeMismatch;
+            result:=l;
+          end;
     else
     else
       VariantTypeMismatch;
       VariantTypeMismatch;
     end;
     end;

+ 19 - 0
rtl/objpas/math.pp

@@ -304,6 +304,8 @@ function mean(const data : array of float) : float;
 function sum(const data : array of float) : float;
 function sum(const data : array of float) : float;
 function mean(const data : PFloat; Const N : longint) : float;
 function mean(const data : PFloat; Const N : longint) : float;
 function sum(const data : PFloat; Const N : Longint) : float;
 function sum(const data : PFloat; Const N : Longint) : float;
+function sumInt(const data : PInt64;Const N : longint) : Int64;
+function sumInt(const data : array of Int64) : Int64;
 function sumofsquares(const data : array of float) : float;
 function sumofsquares(const data : array of float) : float;
 function sumofsquares(const data : PFloat; Const N : Integer) : float;
 function sumofsquares(const data : PFloat; Const N : Integer) : float;
 { calculates the sum and the sum of squares of data }
 { calculates the sum and the sum of squares of data }
@@ -752,6 +754,23 @@ function sum(const data : PFloat;Const N : longint) : float;
        sum:=sum+data[i];
        sum:=sum+data[i];
   end;
   end;
 
 
+function sumInt(const data : PInt64;Const N : longint) : Int64;
+
+  var
+     i : longint;
+
+  begin
+     sumInt:=0;
+     for i:=0 to N-1 do
+       sumInt:=sumInt+data[i];
+  end;
+
+function sumInt(const data : array of Int64) : Int64;
+
+  begin
+     Result:=SumInt(@Data[0],High(Data)+1);
+  end;
+
  function sumofsquares(const data : array of float) : float;
  function sumofsquares(const data : array of float) : float;
 
 
  begin
  begin

+ 1 - 1
rtl/objpas/strutils.pp

@@ -1156,7 +1156,7 @@ begin
     HexStr:='$'+ S
     HexStr:='$'+ S
   else
   else
     HexStr:=S;
     HexStr:=S;
-  Result:=StrTointDef(HexStr,0);
+  Result:=StrToInt(HexStr);
 end;
 end;
 
 
 function Dec2Numb(N: Longint; Len, Base: Byte): string;
 function Dec2Numb(N: Longint; Len, Base: Byte): string;

+ 1 - 1
rtl/objpas/sysutils/fina.inc

@@ -55,7 +55,7 @@ end;
 function ExtractFileDrive(const FileName: string): string;
 function ExtractFileDrive(const FileName: string): string;
 var i: longint;
 var i: longint;
 begin
 begin
-if (Length(FileName) >= 3) and (FileName[2] = ':') then
+if (Length(FileName) >= 2) and (FileName[2] = ':') then
    result := Copy(FileName, 1, 2)
    result := Copy(FileName, 1, 2)
 else if (Length(FileName) >= 2) and (FileName[1] in ['/', '\']) and
 else if (Length(FileName) >= 2) and (FileName[1] in ['/', '\']) and
    (FileName[2] in ['/', '\']) then begin
    (FileName[2] in ['/', '\']) then begin

+ 122 - 21
rtl/objpas/sysutils/sysstr.inc

@@ -1012,33 +1012,19 @@ Begin
 End;
 End;
 {$endif FPC_HAS_TYPE_EXTENDED}
 {$endif FPC_HAS_TYPE_EXTENDED}
 
 
-Function FloatToStr(Value: Extended): String;
-Begin
-  Result := FloatToStrF(Value, ffGeneral, 15, 0);
-End;
-
-Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
-Var
-  Tmp: String[40];
-Begin
-  Tmp := FloatToStrF(Value, format, Precision, Digits);
-  Result := Length(Tmp);
-  Move(Tmp[1], Buffer[0], Result);
-End;
 
 
 const
 const
-{$if sizeof(extended) > sizeof(double)}
+{$ifdef FPC_HAS_TYPE_EXTENDED}
   maxdigits = 15;
   maxdigits = 15;
 {$else}
 {$else}
   maxdigits = 14;
   maxdigits = 14;
 {$endif}
 {$endif}
 
 
-Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
+Function FloatToStrFIntl(Value: Extended; format: TFloatFormat; Precision, Digits: Integer; ValueType: TFloatValue): String;
 Var
 Var
   P: Integer;
   P: Integer;
   Negative, TooSmall, TooLarge: Boolean;
   Negative, TooSmall, TooLarge: Boolean;
 
 
-
 Begin
 Begin
   Case format Of
   Case format Of
 
 
@@ -1049,7 +1035,14 @@ Begin
         TooSmall := (Abs(Value) < 0.00001) and (Value>0.0);
         TooSmall := (Abs(Value) < 0.00001) and (Value>0.0);
         If Not TooSmall Then
         If Not TooSmall Then
         Begin
         Begin
-          Str(Value:digits:precision, Result);
+          case ValueType of
+            fvDouble:
+              Str(Double(Value):digits:precision, Result);
+            fvSingle:
+              Str(Single(Value):digits:precision, Result);
+            else
+              Str(Extended(Value):digits:precision, Result);
+          end;
           P := Pos('.', Result);
           P := Pos('.', Result);
           if P<>0 then
           if P<>0 then
             Result[P] := DecimalSeparator;
             Result[P] := DecimalSeparator;
@@ -1093,7 +1086,14 @@ Begin
 
 
       Begin
       Begin
         If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
         If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
-        Str(Value:Precision + 8, Result);
+        case ValueType of
+          fvDouble:
+            Str(Double(Value):Precision+8, Result);
+          fvSingle:
+            Str(Single(Value):Precision+8, Result);
+          else
+            Str(Extended(Value):Precision+8, Result);
+        end;
         Result[3] := DecimalSeparator;
         Result[3] := DecimalSeparator;
         P:=4;
         P:=4;
         While (P>0) and (Digits < P) And (Result[Precision + 5] = '0') do
         While (P>0) and (Digits < P) And (Result[Precision + 5] = '0') do
@@ -1113,7 +1113,14 @@ Begin
       Begin
       Begin
         If Digits = -1 Then Digits := 2
         If Digits = -1 Then Digits := 2
         Else If Digits > 18 Then Digits := 18;
         Else If Digits > 18 Then Digits := 18;
-        Str(Value:0:Digits, Result);
+        case ValueType of
+          fvDouble:
+            Str(Double(Value):0:Digits, Result);
+          fvSingle:
+            Str(Single(Value):0:Digits, Result);
+          else
+            Str(Extended(Value):0:Digits, Result);
+        end;
         If Result[1] = ' ' Then
         If Result[1] = ' ' Then
           System.Delete(Result, 1, 1);
           System.Delete(Result, 1, 1);
         P := Pos('.', Result);
         P := Pos('.', Result);
@@ -1125,7 +1132,14 @@ Begin
       Begin
       Begin
         If Digits = -1 Then Digits := 2
         If Digits = -1 Then Digits := 2
         Else If Digits > maxdigits Then Digits := maxdigits;
         Else If Digits > maxdigits Then Digits := maxdigits;
-        Str(Value:0:Digits, Result);
+        case ValueType of
+          fvDouble:
+            Str(Double(Value):0:Digits, Result);
+          fvSingle:
+            Str(Single(Value):0:Digits, Result);
+          else
+            Str(Extended(Value):0:Digits, Result);
+        end;
         If Result[1] = ' ' Then System.Delete(Result, 1, 1);
         If Result[1] = ' ' Then System.Delete(Result, 1, 1);
         P := Pos('.', Result);
         P := Pos('.', Result);
         If P <> 0 Then
         If P <> 0 Then
@@ -1152,7 +1166,14 @@ Begin
 
 
         If Digits = -1 Then Digits := CurrencyDecimals
         If Digits = -1 Then Digits := CurrencyDecimals
         Else If Digits > 18 Then Digits := 18;
         Else If Digits > 18 Then Digits := 18;
-        Str(Value:0:Digits, Result);
+        case ValueType of
+          fvDouble:
+            Str(Double(Value):0:Digits, Result);
+          fvSingle:
+            Str(Single(Value):0:Digits, Result);
+          else
+            Str(Extended(Value):0:Digits, Result);
+        end;
         If Result[1] = ' ' Then System.Delete(Result, 1, 1);
         If Result[1] = ' ' Then System.Delete(Result, 1, 1);
         P := Pos('.', Result);
         P := Pos('.', Result);
         If P <> 0 Then Result[P] := DecimalSeparator;
         If P <> 0 Then Result[P] := DecimalSeparator;
@@ -1192,11 +1213,91 @@ Begin
   End;
   End;
 End;
 End;
 
 
+{$ifdef FPC_HAS_TYPE_EXTENDED}
+Function FloatToStr(Value: Extended): String;
+Begin
+  Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvExtended);
+End;
+{$endif FPC_HAS_TYPE_EXTENDED}
+
+Function FloatToStr(Value: Currency): String;
+Begin
+  Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvCurrency);
+End;
+
+Function FloatToStr(Value: Double): String;
+Begin
+  Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvDouble);
+End;
+
+Function FloatToStr(Value: Single): String;
+Begin
+  Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvSingle);
+End;
+
+Function FloatToStr(Value: Comp): String;
+Begin
+  Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvComp);
+End;
+
+{$ifndef FPC_COMP_IS_INT64}
+Function FloatToStr(Value: Int64): String;
+Begin
+  Result := FloatToStrFIntl(Comp(Value), ffGeneral, 15, 0, fvComp);
+End;
+{$endif FPC_COMP_IS_INT64}
+
+
+Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
+Var
+  Tmp: String[40];
+Begin
+  Tmp := FloatToStrF(Value, format, Precision, Digits);
+  Result := Length(Tmp);
+  Move(Tmp[1], Buffer[0], Result);
+End;
+
+{$ifdef FPC_HAS_TYPE_EXTENDED}
+Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
+begin
+  result := FloatToStrFIntl(value,format,precision,digits,fvExtended);
+end;
+{$endif}
+
+Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer): String;
+begin
+  result := FloatToStrFIntl(value,format,precision,digits,fvCurrency);
+end;
+
+Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer): String;
+begin
+  result := FloatToStrFIntl(value,format,precision,digits,fvDouble);
+end;
+
+Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer): String;
+begin
+  result := FloatToStrFIntl(value,format,precision,digits,fvSingle);
+end;
+
+Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer): String;
+begin
+  result := FloatToStrFIntl(value,format,precision,digits,fvComp);
+end;
+
+{$ifndef FPC_COMP_IS_INT64}
+Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer): String;
+begin
+  result := FloatToStrFIntl(Comp(value),format,precision,digits,fvComp);
+end;
+{$endif FPC_COMP_IS_INT64}
+
+
 Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string;
 Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string;
   begin
   begin
     result:=FloatToStrF(Value,Format,19,Digits);
     result:=FloatToStrF(Value,Format,19,Digits);
   end;
   end;
 
 
+
 Function FloatToDateTime (Const Value : Extended) : TDateTime;
 Function FloatToDateTime (Const Value : Extended) : TDateTime;
 begin
 begin
   If (Value<MinDateTime) or (Value>MaxDateTime) then
   If (Value<MinDateTime) or (Value>MaxDateTime) then

+ 18 - 0
rtl/objpas/sysutils/sysstrh.inc

@@ -119,9 +119,27 @@ Function FormatBuf (Var Buffer; BufLen : Cardinal; Const Fmt; fmtLen : Cardinal;
 Function StrFmt(Buffer,Fmt : PChar; Const args: Array of const) : Pchar;
 Function StrFmt(Buffer,Fmt : PChar; Const args: Array of const) : Pchar;
 Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const) : Pchar;
 Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const) : Pchar;
 Procedure FmtStr(Var Res: String; Const Fmt : String; Const args: Array of const);
 Procedure FmtStr(Var Res: String; Const Fmt : String; Const args: Array of const);
+{$ifdef FPC_HAS_TYPE_EXTENDED}
 Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
 Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
+{$endif FPC_HAS_TYPE_EXTENDED}
+Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer): String;
+Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer): String;
+Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer): String;
+Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer): String;
+{$ifndef FPC_COMP_IS_INT64}
+Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer): String;
+{$endif FPC_COMP_IS_INT64}
 Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string;
 Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string;
+{$ifdef FPC_HAS_TYPE_EXTENDED}
 Function FloatToStr(Value: Extended): String;
 Function FloatToStr(Value: Extended): String;
+{$endif FPC_HAS_TYPE_EXTENDED}
+Function FloatToStr(Value: Double): String;
+Function FloatToStr(Value: Single): String;
+Function FloatToStr(Value: Currency): String;
+Function FloatToStr(Value: Comp): String;
+{$ifndef FPC_COMP_IS_INT64}
+Function FloatToStr(Value: Int64): String;
+{$endif FPC_COMP_IS_INT64}
 Function StrToFloat(Const S : String) : Extended;
 Function StrToFloat(Const S : String) : Extended;
 Function StrToFloatDef(Const S: String; Const Default: Extended): Extended;
 Function StrToFloatDef(Const S: String; Const Default: Extended): Extended;
 Function TryStrToFloat(Const S : String; Var Value: Single): Boolean;
 Function TryStrToFloat(Const S : String; Var Value: Single): Boolean;

+ 16 - 9
rtl/objpas/typinfo.pp

@@ -195,8 +195,10 @@ Function GetPropInfo(AClass: TClass; const PropName: string): PPropInfo;
 Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
 Function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo;
 Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
 Function FindPropInfo(AClass:TClass;const PropName: string): PPropInfo;
 Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
 Procedure GetPropInfos(TypeInfo : PTypeInfo;PropList : PPropList);
-Function  GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
+Function GetPropList(TypeInfo : PTypeInfo;TypeKinds : TTypeKinds; PropList : PPropList;Sorted : boolean = true):longint;
 Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
 Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
+function GetPropList(AObject: TObject; out PropList: PPropList): Integer;
+
 
 
 
 
 // Property information routines.
 // Property information routines.
@@ -690,16 +692,21 @@ end;
 
 
 
 
 Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
 Function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): SizeInt;
-  begin
-    result:=GetTypeData(TypeInfo)^.Propcount;
-    if result>0 then
-      begin
-        getmem(PropList,result*sizeof(pointer));
-        GetPropInfos(TypeInfo,PropList);
-      end;
-  end;
+begin
+  result:=GetTypeData(TypeInfo)^.Propcount;
+  if result>0 then
+    begin
+      getmem(PropList,result*sizeof(pointer));
+      GetPropInfos(TypeInfo,PropList);
+    end;
+end;
 
 
 
 
+function GetPropList(AObject: TObject; out PropList: PPropList): Integer;
+begin
+  Result := GetPropList(PTypeInfo(AObject.ClassInfo), PropList);
+end;
+
 { ---------------------------------------------------------------------
 { ---------------------------------------------------------------------
   Property access functions
   Property access functions
   ---------------------------------------------------------------------}
   ---------------------------------------------------------------------}

+ 1 - 0
rtl/unix/oscdeclh.inc

@@ -33,6 +33,7 @@ Type TGrpArr = Array [0..0] of TGid;            { C style array workarounds}
     function  FpDup2    (oldd:cint;newd:cint):cint; cdecl; external clib name 'dup2';
     function  FpDup2    (oldd:cint;newd:cint):cint; cdecl; external clib name 'dup2';
     function  FpExecve  (path : pchar; argv : ppchar; envp: ppchar): cint; cdecl; external clib name 'execve';
     function  FpExecve  (path : pchar; argv : ppchar; envp: ppchar): cint; cdecl; external clib name 'execve';
     function  FpFork  : TPid; cdecl; external clib name 'fork';
     function  FpFork  : TPid; cdecl; external clib name 'fork';
+    function  FpvFork  : TPid; cdecl; external clib name 'vfork';
     function  FpFtruncate(fd : cint; flength : TOff): cint; cdecl; external clib name 'ftruncate';
     function  FpFtruncate(fd : cint; flength : TOff): cint; cdecl; external clib name 'ftruncate';
     function  FpLseek   (fd : cint; offset : TOff; whence : cint): TOff; cdecl; external clib name 'lseek';
     function  FpLseek   (fd : cint; offset : TOff; whence : cint): TOff; cdecl; external clib name 'lseek';
     function  FpMkdir   (path : pchar; mode: TMode):cint; cdecl; external clib name 'mkdir';
     function  FpMkdir   (path : pchar; mode: TMode):cint; cdecl; external clib name 'mkdir';

+ 8 - 0
rtl/unix/sysutils.pp

@@ -20,6 +20,10 @@ interface
 { force ansistrings }
 { force ansistrings }
 {$H+}
 {$H+}
 
 
+{$if defined(BSD) and defined(FPC_USE_LIBC)}
+{$define USE_VFORK}
+{$endif}
+
 {$DEFINE OS_FILESETDATEBYNAME}
 {$DEFINE OS_FILESETDATEBYNAME}
 {$DEFINE HAS_SLEEP}
 {$DEFINE HAS_SLEEP}
 {$DEFINE HAS_OSERROR}
 {$DEFINE HAS_OSERROR}
@@ -984,7 +988,11 @@ Begin
   if ComLine <> '' then
   if ComLine <> '' then
     CommandLine := Commandline + ' ' + ComLine;
     CommandLine := Commandline + ' ' + ComLine;
   {$endif}
   {$endif}
+  {$ifdef USE_VFORK}
+  pid:=fpvFork;
+  {$else USE_VFORK}
   pid:=fpFork;
   pid:=fpFork;
+  {$endif USE_VFORK}
   if pid=0 then
   if pid=0 then
    begin
    begin
    {The child does the actual exec, and then exits}
    {The child does the actual exec, and then exits}

+ 111 - 51
rtl/unix/unix.pp

@@ -17,6 +17,10 @@ Interface
 
 
 Uses BaseUnix,UnixType;
 Uses BaseUnix,UnixType;
 
 
+{$if defined(BSD) and defined(FPC_USE_LIBC)}
+{$define USE_VFORK}
+{$endif}
+
 {$i aliasptp.inc}
 {$i aliasptp.inc}
 
 
 { Get Types and Constants only exported in this unit }
 { Get Types and Constants only exported in this unit }
@@ -128,8 +132,8 @@ Function AssignPipe  (var pipe_in,pipe_out:text):cint;
 Function AssignPipe  (var pipe_in,pipe_out:file):cint;
 Function AssignPipe  (var pipe_in,pipe_out:file):cint;
 //Function PClose      (Var F:text) : cint;
 //Function PClose      (Var F:text) : cint;
 //Function PClose      (Var F:file) : cint;
 //Function PClose      (Var F:file) : cint;
-Function POpen       (var F:text;const Prog:String;rw:char):cint;
-Function POpen       (var F:file;const Prog:String;rw:char):cint;
+Function POpen       (var F:text;const Prog:Ansistring;rw:char):cint;
+Function POpen       (var F:file;const Prog:Ansistring;rw:char):cint;
 Function AssignStream(Var StreamIn,Streamout:text;Const Prog:ansiString;const args : array of ansistring) : cint;
 Function AssignStream(Var StreamIn,Streamout:text;Const Prog:ansiString;const args : array of ansistring) : cint;
 Function AssignStream(Var StreamIn,Streamout,streamerr:text;Const Prog:ansiString;const args : array of ansistring) : cint;
 Function AssignStream(Var StreamIn,Streamout,streamerr:text;Const Prog:ansiString;const args : array of ansistring) : cint;
 
 
@@ -736,7 +740,7 @@ begin
 end;
 end;
 
 
 
 
-function POpen(var F:text;const Prog:String;rw:char):cint;
+Function POpen(var F:text;const Prog:Ansistring;rw:char):cint;
 {
 {
   Starts the program in 'Prog' and makes it's input or out put the
   Starts the program in 'Prog' and makes it's input or out put the
   other end of a pipe. If rw is 'w' or 'W', then whatever is written to
   other end of a pipe. If rw is 'w' or 'W', then whatever is written to
@@ -747,11 +751,12 @@ function POpen(var F:text;const Prog:String;rw:char):cint;
 var
 var
   pipi,
   pipi,
   pipo : text;
   pipo : text;
-  pid  : pid_t;
+  pid  : cint;
   pl   : ^cint;
   pl   : ^cint;
-{$ifndef FPC_USE_FPEXEC}
-  pp   : ppchar;
-{$endif not FPC_USE_FPEXEC}
+{$if not defined(FPC_USE_FPEXEC) or defined(USE_VFORK)}
+  pp : array[0..3] of pchar;
+  temp : string[255];
+{$endif not FPC_USE_FPEXEC or USE_VFORK}
   ret  : cint;
   ret  : cint;
 begin
 begin
   rw:=upcase(rw);
   rw:=upcase(rw);
@@ -760,9 +765,14 @@ begin
      FpSetErrno(ESysEnoent);
      FpSetErrno(ESysEnoent);
      exit(-1);
      exit(-1);
    end;
    end;
-  if AssignPipe(pipi,pipo)=-1 Then
-    Exit(-1);
-  pid:=fpfork;          // vfork in FreeBSD.
+  ret:=AssignPipe(pipi,pipo);
+  if ret=-1 then
+   exit(-1);
+{$ifdef USE_VFORK}
+  pid:=fpvfork;
+{$else USE_VFORK}
+  pid:=fpfork;
+{$endif USE_VFORK}
   if pid=-1 then
   if pid=-1 then
    begin
    begin
      close(pipi);
      close(pipi);
@@ -774,27 +784,53 @@ begin
    { We're in the child }
    { We're in the child }
      if rw='W' then
      if rw='W' then
       begin
       begin
+        if (textrec(pipi).handle <> stdinputhandle) then
+          begin
+            ret:=fpdup2(pipi,input);
+{$ifdef USE_VFORK}
+            fpclose(textrec(pipi).handle);
+{$else USE_VFORK}
+            close(pipi);
+{$endif USE_VFORK}
+          end;
+{$ifdef USE_VFORK}
+        fpclose(textrec(pipo).handle);
+{$else USE_VFORK}
         close(pipo);
         close(pipo);
-        ret:=fpdup2(pipi,input);
-        close(pipi);
+{$endif USE_VFORK}
         if ret=-1 then
         if ret=-1 then
-         halt(127);
+         fpexit(127);
       end
       end
      else
      else
       begin
       begin
+{$ifdef USE_VFORK}
+        fpclose(textrec(pipi).handle);
+{$else USE_VFORK}
         close(pipi);
         close(pipi);
-        ret:=fpdup2(pipo,output);
-        close(pipo);
-        if ret=-1 then
-         halt(127);
+{$endif USE_VFORK}
+        if (textrec(pipo).handle <> stdoutputhandle) then
+          begin
+            ret:=fpdup2(pipo,output);
+{$ifdef USE_VFORK}
+            fpclose(textrec(pipo).handle);
+{$else USE_VFORK}
+            close(pipo);
+{$endif USE_VFORK}
+          end;
+        if ret=1 then
+         fpexit(127);
       end;
       end;
-     {$ifdef FPC_USE_FPEXEC}
-     fpexecl('/bin/sh',['-c',Prog]);
+     {$if defined(FPC_USE_FPEXEC) and not defined(USE_VFORK)}
+     fpexecl(pchar('/bin/sh'),['-c',Prog]);
      {$else}
      {$else}
-     pp:=createshellargv(prog);
-     fpExecve(pp^,pp,envp);
+     temp:='/bin/sh'#0'-c'#0;
+     pp[0]:=@temp[1];
+     pp[1]:=@temp[9];
+     pp[2]:=@prog[1];
+     pp[3]:=Nil;
+     fpExecve('/bin/sh',@pp,envp);
      {$endif}
      {$endif}
-     halt(127);
+     fpexit(127);
    end
    end
   else
   else
    begin
    begin
@@ -803,23 +839,22 @@ begin
       begin
       begin
         close(pipi);
         close(pipi);
         f:=pipo;
         f:=pipo;
-        textrec(f).bufptr:=@textrec(f).buffer;
       end
       end
      else
      else
       begin
       begin
         close(pipo);
         close(pipo);
         f:=pipi;
         f:=pipi;
-        textrec(f).bufptr:=@textrec(f).buffer;
       end;
       end;
+     textrec(f).bufptr:=@textrec(f).buffer;
    {Save the process ID - needed when closing }
    {Save the process ID - needed when closing }
      pl:=@(textrec(f).userdata[2]);
      pl:=@(textrec(f).userdata[2]);
      pl^:=pid;
      pl^:=pid;
      textrec(f).closefunc:=@PCloseText;
      textrec(f).closefunc:=@PCloseText;
    end;
    end;
- ret:=0;
+ POpen:=0;
 end;
 end;
 
 
-Function POpen(var F:file;const Prog:String;rw:char):cint;
+Function POpen(var F:file;const Prog:Ansistring;rw:char):cint;
 {
 {
   Starts the program in 'Prog' and makes it's input or out put the
   Starts the program in 'Prog' and makes it's input or out put the
   other end of a pipe. If rw is 'w' or 'W', then whatever is written to
   other end of a pipe. If rw is 'w' or 'W', then whatever is written to
@@ -832,10 +867,10 @@ var
   pipo : file;
   pipo : file;
   pid  : cint;
   pid  : cint;
   pl   : ^cint;
   pl   : ^cint;
-{$ifndef FPC_USE_FPEXEC}
-  p,pp : ppchar;
+{$if not defined(FPC_USE_FPEXEC) or defined(USE_VFORK)}
+  pp : array[0..3] of pchar;
   temp : string[255];
   temp : string[255];
-{$endif not FPC_USE_FPEXEC}
+{$endif not FPC_USE_FPEXEC or USE_VFORK}
   ret  : cint;
   ret  : cint;
 begin
 begin
   rw:=upcase(rw);
   rw:=upcase(rw);
@@ -847,7 +882,11 @@ begin
   ret:=AssignPipe(pipi,pipo);
   ret:=AssignPipe(pipi,pipo);
   if ret=-1 then
   if ret=-1 then
    exit(-1);
    exit(-1);
+{$ifdef USE_VFORK}
+  pid:=fpvfork;
+{$else USE_VFORK}
   pid:=fpfork;
   pid:=fpfork;
+{$endif USE_VFORK}
   if pid=-1 then
   if pid=-1 then
    begin
    begin
      close(pipi);
      close(pipi);
@@ -859,36 +898,53 @@ begin
    { We're in the child }
    { We're in the child }
      if rw='W' then
      if rw='W' then
       begin
       begin
+        if (filerec(pipi).handle <> stdinputhandle) then
+          begin
+            ret:=fpdup2(filerec(pipi).handle,stdinputhandle);
+{$ifdef USE_VFORK}
+            fpclose(filerec(pipi).handle);
+{$else USE_VFORK}
+            close(pipi);
+{$endif USE_VFORK}
+          end;
+{$ifdef USE_VFORK}
+        fpclose(filerec(pipo).handle);
+{$else USE_VFORK}
         close(pipo);
         close(pipo);
-        ret:=fpdup2(filerec(pipi).handle,stdinputhandle);
-        close(pipi);
+{$endif USE_VFORK}
         if ret=-1 then
         if ret=-1 then
-         halt(127);
+         fpexit(127);
       end
       end
      else
      else
       begin
       begin
+{$ifdef USE_VFORK}
+        fpclose(filerec(pipi).handle);
+{$else USE_VFORK}
         close(pipi);
         close(pipi);
-        ret:=fpdup2(filerec(pipo).handle,stdoutputhandle);
-        close(pipo);
+{$endif USE_VFORK}
+        if (filerec(pipo).handle <> stdoutputhandle) then
+          begin
+            ret:=fpdup2(filerec(pipo).handle,stdoutputhandle);
+{$ifdef USE_VFORK}
+            fpclose(filerec(pipo).handle);
+{$else USE_VFORK}
+            close(pipo);
+{$endif USE_VFORK}
+          end;
         if ret=1 then
         if ret=1 then
-         halt(127);
+         fpexit(127);
       end;
       end;
-     {$ifdef FPC_USE_FPEXEC}
-     fpexecl('/bin/sh',['-c',Prog]);
+     {$if defined(FPC_USE_FPEXEC) and not defined(USE_VFORK)}
+     fpexecl(pchar('/bin/sh'),['-c',Prog]);
      {$else}
      {$else}
-     getmem(pp,sizeof(pchar)*4);
-     temp:='/bin/sh'#0'-c'#0+prog+#0;
-     p:=pp;
-     p^:=@temp[1];
-     inc(p);
-     p^:=@temp[9];
-     inc(p);
-     p^:=@temp[12];
-     inc(p);
-     p^:=Nil;
-     fpExecve(ansistring('/bin/sh'),pp,envp);
+     temp:='/bin/sh'#0'-c'#0;
+     pp[0]:=@temp[1];
+     pp[1]:=@temp[9];
+     pp[2]:=@prog[1];
+     pp[3]:=Nil;
+     fpExecve('/bin/sh',@pp,envp);
      {$endif}
      {$endif}
-     halt(127);
+     fpexit(127);
    end
    end
   else
   else
    begin
    begin
@@ -931,8 +987,12 @@ begin
   AssignStream:=-1;
   AssignStream:=-1;
   if AssignPipe(streamin,pipo)=-1 Then
   if AssignPipe(streamin,pipo)=-1 Then
    exit(-1);
    exit(-1);
-  if AssignPipe(pipi,streamout)=-1 Then // shouldn't this close streamin and pipo?
-   exit(-1);
+  if AssignPipe(pipi,streamout)=-1 Then
+    begin
+      close(streamin);
+      close(pipo);
+      exit(-1);
+    end;
   pid:=fpfork;
   pid:=fpfork;
   if pid=-1 then
   if pid=-1 then
    begin
    begin

+ 16 - 0
tests/tbf/tb0177.pp

@@ -0,0 +1,16 @@
+{ %fail }
+
+procedure p;
+var
+  e1     : byte;
+  r : record
+    e : (e1,e2);
+  end;
+
+begin
+  r.e:=e1;
+end;
+
+begin
+end.
+

+ 15 - 0
tests/tbs/tb0498.pp

@@ -0,0 +1,15 @@
+type
+  t1 = longint;
+
+procedure p(t3:word);
+var
+  t2 : record
+    t1 : t1;
+end;
+begin
+  writeln(t3);
+end;
+
+begin
+  p(10);
+end.

+ 16 - 0
tests/tbs/tb0499.pp

@@ -0,0 +1,16 @@
+var
+  e1     : byte;
+
+procedure p;
+var
+  r : record
+    e : (e1,e2);
+  end;
+
+begin
+  r.e:=e1;
+end;
+
+begin
+end.
+

+ 51 - 0
tests/test/tstrreal3.pp

@@ -0,0 +1,51 @@
+{ test by Graeme Geldenhuys }
+
+{$mode delphi}
+uses sysutils;
+
+
+procedure test;
+var
+ Result: string;
+ e: extended;
+ r: double;
+begin
+ e := 234.502;
+ Result := FloatToStrF(e, ffGeneral, 15, 0);
+// Memo1.Lines.Add(Result);      { prints 234.502  }
+ writeln(result);
+ if (result <> '234.502') then
+   halt(1);
+
+ r := 234.502;
+ Result := FloatToStrF(r, ffGeneral, 15, 0);
+// Memo1.Lines.Add(Result);  { prints 234.50200000000001 }
+ writeln(result);
+ if (result <> '234.502') then
+   halt(1);
+
+ r := 234.501;
+ Result := FloatToStrF(r, ffGeneral, 15, 0);
+// Memo1.Lines.Add(Result);  { prints 234.501  Why does this work? }
+ writeln(result);
+ if (result <> '234.501') then
+   halt(1);
+
+ r := 7.502;
+ Result := FloatToStrF(r, ffGeneral, 15, 0);
+// Memo1.Lines.Add(Result);  { prints 7.502 }
+ writeln(result);
+ if (result <> '7.502') then
+   halt(1);
+
+ r := 8.502;
+ Result := FloatToStrF(r, ffGeneral, 15, 0);
+// Memo1.Lines.Add(Result);  { prints 8.502000000000001 }
+ writeln(result);
+ if (result <> '8.502') then
+   halt(1);
+end;
+
+begin
+  test;
+end.

+ 12 - 0
tests/webtbs/tw4541.pp

@@ -0,0 +1,12 @@
+{ Source provided for Free Pascal Bug Report 4541 }
+{ Submitted by "Vincent Snijders" on  2005-11-23 }
+{ e-mail: [email protected] }
+program tw4541;
+
+{$mode objfpc}{$H+}
+
+uses
+  uw4541;
+
+begin
+end.

+ 12 - 0
tests/webtbs/tw4700.pp

@@ -0,0 +1,12 @@
+var
+  a: Boolean;
+  b,c,d : Variant;
+  e : Integer;
+begin
+  b := 'abc';
+  c := null;
+  a := b = c;
+  a := b <> c;
+  d := e - c;
+  d := e + c;
+end.

+ 26 - 0
tests/webtbs/uw4541.pp

@@ -0,0 +1,26 @@
+unit uw4541;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes;
+
+type
+
+  TA = class(TComponent)
+    D: TComponent;
+  end;
+
+  TB= class(TComponent)
+  private
+    FA: TA;
+  public
+    property C: TComponent read FA.D;
+  end;
+
+implementation
+
+end.
+

+ 11 - 11
utils/fpdoc/dglobals.pp

@@ -595,24 +595,24 @@ var
     var
     var
       DotPos, DotPos2, i: Integer;
       DotPos, DotPos2, i: Integer;
       s: String;
       s: String;
-      Package: TPasPackage;
+      HPackage: TPasPackage;
       Module: TPasModule;
       Module: TPasModule;
     begin
     begin
       // Find or create package
       // Find or create package
       DotPos := Pos('.', AName);
       DotPos := Pos('.', AName);
       s := Copy(AName, 1, DotPos - 1);
       s := Copy(AName, 1, DotPos - 1);
-      Package := nil;
+      HPackage := nil;
       for i := 0 to FPackages.Count - 1 do
       for i := 0 to FPackages.Count - 1 do
         if CompareText(TPasPackage(FPackages[i]).Name, s) = 0 then
         if CompareText(TPasPackage(FPackages[i]).Name, s) = 0 then
         begin
         begin
-          Package := TPasPackage(FPackages[i]);
+          HPackage := TPasPackage(FPackages[i]);
           break;
           break;
         end;
         end;
-      if not Assigned(Package) then
+      if not Assigned(HPackage) then
       begin
       begin
-        Package := TPasPackage(inherited CreateElement(TPasPackage, s, nil,
+        HPackage := TPasPackage(inherited CreateElement(TPasPackage, s, nil,
           '', 0));
           '', 0));
-        FPackages.Add(Package);
+        FPackages.Add(HPackage);
       end;
       end;
 
 
       // Find or create module
       // Find or create module
@@ -622,17 +622,17 @@ var
       until AName[DotPos2] = '.';
       until AName[DotPos2] = '.';
       s := Copy(AName, DotPos + 1, DotPos2 - DotPos - 1);
       s := Copy(AName, DotPos + 1, DotPos2 - DotPos - 1);
       Module := nil;
       Module := nil;
-      for i := 0 to Package.Modules.Count - 1 do
-        if CompareText(TPasModule(Package.Modules[i]).Name, s) = 0 then
+      for i := 0 to HPackage.Modules.Count - 1 do
+        if CompareText(TPasModule(HPackage.Modules[i]).Name, s) = 0 then
         begin
         begin
-          Module := TPasModule(Package.Modules[i]);
+          Module := TPasModule(HPackage.Modules[i]);
           break;
           break;
         end;
         end;
       if not Assigned(Module) then
       if not Assigned(Module) then
       begin
       begin
-        Module := TPasModule.Create(s, Package);
+        Module := TPasModule.Create(s, HPackage);
         Module.InterfaceSection := TPasSection.Create('', Module);
         Module.InterfaceSection := TPasSection.Create('', Module);
-        Package.Modules.Add(Module);
+        HPackage.Modules.Add(Module);
       end;
       end;
 
 
       // Create node for class
       // Create node for class