Browse Source

* merged r15735 through r15751 from trunk

git-svn-id: branches/llvm@15752 -
Jonas Maebe 15 years ago
parent
commit
876e0d78da

+ 2 - 0
.gitattributes

@@ -9238,6 +9238,8 @@ tests/test/tinterface4.pp svneol=native#text/plain
 tests/test/tinterface5.pp svneol=native#text/plain
 tests/test/tinterface5.pp svneol=native#text/plain
 tests/test/tinterface6.pp svneol=native#text/plain
 tests/test/tinterface6.pp svneol=native#text/plain
 tests/test/tinterrupt.pp svneol=native#text/plain
 tests/test/tinterrupt.pp svneol=native#text/plain
+tests/test/tintfcdecl1.pp svneol=native#text/plain
+tests/test/tintfcdecl2.pp svneol=native#text/plain
 tests/test/tintfdef.pp svneol=native#text/plain
 tests/test/tintfdef.pp svneol=native#text/plain
 tests/test/tintuint.pp svneol=native#text/plain
 tests/test/tintuint.pp svneol=native#text/plain
 tests/test/tisogoto1.pp svneol=native#text/pascal
 tests/test/tisogoto1.pp svneol=native#text/pascal

+ 0 - 3
compiler/aasmdata.pas

@@ -332,9 +332,6 @@ implementation
         for hal:=low(TAsmListType) to high(TAsmListType) do
         for hal:=low(TAsmListType) to high(TAsmListType) do
           AsmLists[hal]:=TAsmList.create;
           AsmLists[hal]:=TAsmList.create;
         WideInits :=TLinkedList.create;
         WideInits :=TLinkedList.create;
-        { PIC data }
-        if (target_info.system in [system_powerpc_darwin,system_powerpc64_darwin,system_i386_darwin,system_arm_darwin]) then
-          new_section(AsmLists[al_picdata],sec_data_nonlazy,'',sizeof(pint));
         { CFI }
         { CFI }
         FAsmCFI:=CAsmCFI.Create;
         FAsmCFI:=CAsmCFI.Create;
       end;
       end;

+ 6 - 2
compiler/cgobj.pas

@@ -1115,6 +1115,7 @@ implementation
            end;
            end;
       end;
       end;
 
 
+
     procedure tcg.a_load_cgparaloc_ref(list : TAsmList;const paraloc : TCGParaLocation;const ref : treference;sizeleft : aint;align : longint);
     procedure tcg.a_load_cgparaloc_ref(list : TAsmList;const paraloc : TCGParaLocation;const ref : treference;sizeleft : aint;align : longint);
       var
       var
         href : treference;
         href : treference;
@@ -4169,6 +4170,7 @@ implementation
       var
       var
         l: tasmsymbol;
         l: tasmsymbol;
         ref: treference;
         ref: treference;
+        nlsymname: string;
       begin
       begin
         result := NR_NO;
         result := NR_NO;
         case target_info.system of
         case target_info.system of
@@ -4177,10 +4179,12 @@ implementation
           system_powerpc64_darwin,
           system_powerpc64_darwin,
           system_arm_darwin:
           system_arm_darwin:
             begin
             begin
-              l:=current_asmdata.getasmsymbol('L'+symname+'$non_lazy_ptr');
+              nlsymname:='L'+symname+'$non_lazy_ptr';
+              l:=current_asmdata.getasmsymbol(nlsymname);
               if not(assigned(l)) then
               if not(assigned(l)) then
                 begin
                 begin
-                  l:=current_asmdata.DefineAsmSymbol('L'+symname+'$non_lazy_ptr',AB_LOCAL,AT_DATA);
+                  new_section(current_asmdata.asmlists[al_picdata],sec_data_nonlazy,'',sizeof(pint));
+                  l:=current_asmdata.DefineAsmSymbol(nlsymname,AB_LOCAL,AT_DATA);
                   current_asmdata.asmlists[al_picdata].concat(tai_symbol.create(l,0));
                   current_asmdata.asmlists[al_picdata].concat(tai_symbol.create(l,0));
                   if not(weak) then
                   if not(weak) then
                     current_asmdata.asmlists[al_picdata].concat(tai_directive.Create(asd_indirect_symbol,current_asmdata.RefAsmSymbol(symname).Name))
                     current_asmdata.asmlists[al_picdata].concat(tai_directive.Create(asd_indirect_symbol,current_asmdata.RefAsmSymbol(symname).Name))

+ 1 - 1
compiler/defutil.pas

@@ -997,7 +997,7 @@ implementation
             end;
             end;
           stringdef :
           stringdef :
             begin
             begin
-              if is_ansistring(def) or is_widestring(def) then
+              if is_ansistring(def) or is_wide_or_unicode_string(def) then
                 result := OS_ADDR
                 result := OS_ADDR
               else
               else
                 result:=int_cgsize(def.size);
                 result:=int_cgsize(def.size);

+ 7 - 44
compiler/i386/cgcpu.pas

@@ -552,38 +552,20 @@ unit cgcpu;
       {
       {
       possible calling conventions:
       possible calling conventions:
                     default stdcall cdecl pascal register
                     default stdcall cdecl pascal register
-      default(0):      OK     OK    OK(1)  OK       OK
-      virtual(2):      OK     OK    OK(3)  OK       OK
+      default(0):      OK     OK    OK     OK       OK
+      virtual(1):      OK     OK    OK     OK       OK(2)
 
 
       (0):
       (0):
           set self parameter to correct value
           set self parameter to correct value
           jmp mangledname
           jmp mangledname
 
 
-      (1): The code is the following
-           set self parameter to correct value
-           call mangledname
-           set self parameter to interface value
-           ret
-
-           This is different to case (0) because in theory, the caller
-           could reuse the data pushed on the stack so we've to return
-           it unmodified because self is const.
-
-      (2): The wrapper code use %eax to reach the virtual method address
+      (1): The wrapper code use %eax to reach the virtual method address
            set self to correct value
            set self to correct value
            move self,%eax
            move self,%eax
            mov  0(%eax),%eax ; load vmt
            mov  0(%eax),%eax ; load vmt
            jmp  vmtoffs(%eax) ; method offs
            jmp  vmtoffs(%eax) ; method offs
 
 
-      (3): The wrapper code use %eax to reach the virtual method address
-           set self to correct value
-           move self,%eax
-           mov  0(%eax),%eax ; load vmt
-           jmp  vmtoffs(%eax) ; method offs
-           set self parameter to interface value
-
-
-      (4): Virtual use values pushed on stack to reach the method address
+      (2): Virtual use values pushed on stack to reach the method address
            so the following code be generated:
            so the following code be generated:
            set self to correct value
            set self to correct value
            push %ebx ; allocate space for function address
            push %ebx ; allocate space for function address
@@ -676,30 +658,11 @@ unit cgcpu;
         { set param1 interface to self  }
         { set param1 interface to self  }
         g_adjust_self_value(list,procdef,ioffset);
         g_adjust_self_value(list,procdef,ioffset);
 
 
-        { case 1 or 2 }
-        if (procdef.proccalloption in clearstack_pocalls) then
-          begin
-            if po_virtualmethod in procdef.procoptions then
-              begin
-                { case 2 }
-                getselftoeax(0);
-                loadvmttoeax;
-                op_oneaxmethodaddr(A_CALL);
-              end
-            else
-              begin
-                { case 1 }
-                cg.a_call_name(list,procdef.mangledname,false);
-              end;
-            { restore param1 value self to interface }
-            g_adjust_self_value(list,procdef,-ioffset);
-            list.concat(taicpu.op_none(A_RET,S_L));
-          end
-        else if po_virtualmethod in procdef.procoptions then
+        if po_virtualmethod in procdef.procoptions then
           begin
           begin
             if (procdef.proccalloption=pocall_register) then
             if (procdef.proccalloption=pocall_register) then
               begin
               begin
-                { case 4 }
+                { case 2 }
                 list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EBX)); { allocate space for address}
                 list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EBX)); { allocate space for address}
                 list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EAX));
                 list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EAX));
                 getselftoeax(8);
                 getselftoeax(8);
@@ -715,7 +678,7 @@ unit cgcpu;
               end
               end
             else
             else
               begin
               begin
-                { case 3 }
+                { case 1 }
                 getselftoeax(0);
                 getselftoeax(0);
                 loadvmttoeax;
                 loadvmttoeax;
                 op_oneaxmethodaddr(A_JMP);
                 op_oneaxmethodaddr(A_JMP);

+ 8 - 1
compiler/nadd.pas

@@ -889,7 +889,14 @@ implementation
         { is one a real float, then both need to be floats, this
         { is one a real float, then both need to be floats, this
           need to be done before the constant folding so constant
           need to be done before the constant folding so constant
           operation on a float and int are also handled }
           operation on a float and int are also handled }
-        resultrealdef:=pbestrealtype^;
+{$ifdef x86}
+        { use extended as default real type only when the x87 fpu is used }
+        if not(current_settings.fputype=fpu_x87) then
+          resultrealdef:=s64floattype
+        else
+{$endif x86}
+          resultrealdef:=pbestrealtype^;
+
         if (right.resultdef.typ=floatdef) or (left.resultdef.typ=floatdef) then
         if (right.resultdef.typ=floatdef) or (left.resultdef.typ=floatdef) then
          begin
          begin
            { when both floattypes are already equal then use that
            { when both floattypes are already equal then use that

+ 191 - 86
packages/fcl-passrc/src/pastree.pp

@@ -67,6 +67,58 @@ resourcestring
   SPasTreeDestructorImpl = 'destructor implementation';
   SPasTreeDestructorImpl = 'destructor implementation';
 
 
 type
 type
+
+
+  // Visitor pattern.
+  TPassTreeVisitor = class;
+
+  TPasElementBase = class
+    procedure Accept(Visitor: TPassTreeVisitor); virtual; abstract;
+  end;
+
+
+  TPasModule = class;
+
+  TPasMemberVisibility = (visDefault, visPrivate, visProtected, visPublic,
+    visPublished, visAutomated,
+    visStrictPrivate, visStrictProtected);
+
+  TCallingConvention = (ccDefault,ccRegister,ccPascal,ccCDecl,ccStdCall,ccOldFPCCall,ccSafeCall);
+
+  TPasMemberVisibilities = set of TPasMemberVisibility;
+  TPasMemberHint = (hDeprecated,hLibrary,hPlatform,hExperimental,hUnimplemented);
+  TPasMemberHints = set of TPasMemberHint; 
+
+  TPTreeElement = class of TPasElement;
+
+  { TPasElement }
+
+  TPasElement = class(TPasElementBase)
+  private
+    FRefCount: LongWord;
+    FName: string;
+    FParent: TPasElement;
+    FHints : TPasMemberHints;
+  public
+    SourceFilename: string;
+    SourceLinenumber: Integer;
+    Visibility: TPasMemberVisibility;
+  public
+    constructor Create(const AName: string; AParent: TPasElement); virtual;
+    procedure AddRef;
+    procedure Release;
+    function FullName: string;          // Name including parent's names
+    function PathName: string;          // = Module.Name + FullName
+    function GetModule: TPasModule;
+    function ElementTypeName: string; virtual;
+    function GetDeclaration(full : Boolean) : string; virtual;
+    procedure Accept(Visitor: TPassTreeVisitor); override;
+    property RefCount: LongWord read FRefCount;
+    property Name: string read FName write FName;
+    property Parent: TPasElement read FParent;
+    Property Hints : TPasMemberHints Read FHints Write FHints;
+  end;
+
   TPasExprKind = (pekIdent, pekNumber, pekString, pekSet, pekNil, pekBoolConst, pekRange,
   TPasExprKind = (pekIdent, pekNumber, pekString, pekSet, pekNil, pekBoolConst, pekRange,
      pekUnary, pekBinary, pekFuncParams, pekArrayParams, pekListOfExp);
      pekUnary, pekBinary, pekFuncParams, pekArrayParams, pekListOfExp);
 
 
@@ -82,15 +134,16 @@ type
   
   
   { TPasExpr }
   { TPasExpr }
 
 
-  TPasExpr = class
+  TPasExpr = class(TPasElement)
     Kind      : TPasExprKind;
     Kind      : TPasExprKind;
     OpCode    : TexprOpcode;
     OpCode    : TexprOpcode;
-    constructor Create(AKind: TPasExprKind; AOpCode: TexprOpcode);
+    constructor Create(AParent : TPasElement; AKind: TPasExprKind; AOpCode: TexprOpcode);
   end;
   end;
 
 
   TUnaryExpr = class(TPasExpr)
   TUnaryExpr = class(TPasExpr)
     Operand   : TPasExpr;
     Operand   : TPasExpr;
-    constructor Create(AOperand: TPasExpr; AOpCode: TExprOpCode);
+    constructor Create(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode);
+    function GetDeclaration(full : Boolean) : string; override;
     destructor Destroy; override;
     destructor Destroy; override;
   end;
   end;
 
 
@@ -99,26 +152,29 @@ type
   TBinaryExpr = class(TPasExpr)
   TBinaryExpr = class(TPasExpr)
     left      : TPasExpr;
     left      : TPasExpr;
     right     : TPasExpr;
     right     : TPasExpr;
-    constructor Create(xleft, xright: TPasExpr; AOpCode: TExprOpCode);
-    constructor CreateRange(xleft, xright: TPasExpr);
+    constructor Create(AParent : TPasElement; xleft, xright: TPasExpr; AOpCode: TExprOpCode);
+    constructor CreateRange(AParent : TPasElement; xleft, xright: TPasExpr);
+    function GetDeclaration(full : Boolean) : string; override;
     destructor Destroy; override;
     destructor Destroy; override;
   end;
   end;
 
 
   TPrimitiveExpr = class(TPasExpr)
   TPrimitiveExpr = class(TPasExpr)
     Value     : AnsiString;
     Value     : AnsiString;
-    constructor Create(AKind: TPasExprKind; const AValue : Ansistring);
+    constructor Create(AParent : TPasElement; AKind: TPasExprKind; const AValue : Ansistring);
+    function GetDeclaration(full : Boolean) : string; override;
   end;
   end;
   
   
   TBoolConstExpr = class(TPasExpr)
   TBoolConstExpr = class(TPasExpr)
     Value     : Boolean;
     Value     : Boolean;
-    constructor Create(AKind: TPasExprKind; const ABoolValue : Boolean);
+    constructor Create(AParent : TPasElement; AKind: TPasExprKind; const ABoolValue : Boolean);
+    function GetDeclaration(full : Boolean) : string; override;
   end;
   end;
 
 
   { TNilExpr }
   { TNilExpr }
 
 
   TNilExpr = class(TPasExpr)
   TNilExpr = class(TPasExpr)
-    Value     : Boolean;
-    constructor Create;
+    constructor Create(AParent : TPasElement);
+    function GetDeclaration(full : Boolean) : string; override;
   end;
   end;
 
 
   { TParamsExpr }
   { TParamsExpr }
@@ -127,7 +183,8 @@ type
     Value     : TPasExpr;
     Value     : TPasExpr;
     Params    : array of TPasExpr;
     Params    : array of TPasExpr;
     {pekArray, pekFuncCall, pekSet}
     {pekArray, pekFuncCall, pekSet}
-    constructor Create(AKind: TPasExprKind);
+    constructor Create(AParent : TPasElement; AKind: TPasExprKind);
+    function GetDeclaration(full : Boolean) : string; override;
     destructor Destroy; override;
     destructor Destroy; override;
     procedure AddParam(xp: TPasExpr);
     procedure AddParam(xp: TPasExpr);
   end;
   end;
@@ -141,69 +198,20 @@ type
 
 
   TRecordValues = class(TPasExpr)
   TRecordValues = class(TPasExpr)
     Fields    : array of TRecordValuesItem;
     Fields    : array of TRecordValuesItem;
-    constructor Create;
+    constructor Create(AParent : TPasElement);
     destructor Destroy; override;
     destructor Destroy; override;
-    procedure AddField(const Name: AnsiString; Value: TPasExpr);
+    procedure AddField(const AName: AnsiString; Value: TPasExpr);
+    function GetDeclaration(full : Boolean) : string; override;
   end;
   end;
 
 
   { TArrayValues }
   { TArrayValues }
 
 
   TArrayValues = class(TPasExpr)
   TArrayValues = class(TPasExpr)
     Values    : array of TPasExpr;
     Values    : array of TPasExpr;
-    constructor Create;
+    constructor Create(AParent : TPasElement);
     destructor Destroy; override;
     destructor Destroy; override;
     procedure AddValues(AValue: TPasExpr);
     procedure AddValues(AValue: TPasExpr);
-  end;
-
-
-  // Visitor pattern.
-  TPassTreeVisitor = class;
-
-  TPasElementBase = class
-    procedure Accept(Visitor: TPassTreeVisitor); virtual; abstract;
-  end;
-
-
-  TPasModule = class;
-
-  TPasMemberVisibility = (visDefault, visPrivate, visProtected, visPublic,
-    visPublished, visAutomated,
-    visStrictPrivate, visStrictProtected);
-
-  TCallingConvention = (ccDefault,ccRegister,ccPascal,ccCDecl,ccStdCall,ccOldFPCCall,ccSafeCall);
-
-  TPasMemberVisibilities = set of TPasMemberVisibility;
-  TPasMemberHint = (hDeprecated,hLibrary,hPlatform,hExperimental,hUnimplemented);
-  TPasMemberHints = set of TPasMemberHint; 
-
-  TPTreeElement = class of TPasElement;
-
-  { TPasElement }
-
-  TPasElement = class(TPasElementBase)
-  private
-    FRefCount: LongWord;
-    FName: string;
-    FParent: TPasElement;
-    FHints : TPasMemberHints;
-  public
-    SourceFilename: string;
-    SourceLinenumber: Integer;
-    Visibility: TPasMemberVisibility;
-  public
-    constructor Create(const AName: string; AParent: TPasElement); virtual;
-    procedure AddRef;
-    procedure Release;
-    function FullName: string;          // Name including parent's names
-    function PathName: string;          // = Module.Name + FullName
-    function GetModule: TPasModule;
-    function ElementTypeName: string; virtual;
-    function GetDeclaration(full : Boolean) : string; virtual;
-    procedure Accept(Visitor: TPassTreeVisitor); override;
-    property RefCount: LongWord read FRefCount;
-    property Name: string read FName write FName;
-    property Parent: TPasElement read FParent;
-    Property Hints : TPasMemberHints Read FHints Write FHints;
+    function GetDeclaration(full : Boolean) : string; override;
   end;
   end;
 
 
   { TPasDeclarations }
   { TPasDeclarations }
@@ -255,6 +263,7 @@ type
     InitializationSection: TInitializationSection;
     InitializationSection: TInitializationSection;
     FinalizationSection: TFinalizationSection;
     FinalizationSection: TFinalizationSection;
     PackageName: string;
     PackageName: string;
+    Filename   : String;  // the IN filename, only written when not empty.
   end;
   end;
 
 
   { TPasPackage }
   { TPasPackage }
@@ -942,7 +951,16 @@ const
 
 
   ObjKindNames: array[TPasObjKind] of string = (
   ObjKindNames: array[TPasObjKind] of string = (
     'object', 'class', 'interface');
     'object', 'class', 'interface');
-
+  
+  OpcodeStrings : Array[TExprOpCode] of string = 
+       ('','+','-','*','/','div','mod','**',
+        'shr','shl',
+        'not','and','or','xor',
+        '=','<>',
+        '<','>','<=','>=',
+        'in','is','as','><',
+        '@','^',
+        '.');
 
 
 implementation
 implementation
 
 
@@ -2375,7 +2393,7 @@ end;
 
 
 { TPasExpr }
 { TPasExpr }
 
 
-constructor TPasExpr.Create(AKind: TPasExprKind; AOpCode: TexprOpcode);
+constructor TPasExpr.Create(AParent : TPasElement; AKind: TPasExprKind; AOpCode: TexprOpcode);
 begin
 begin
   Kind:=AKind;
   Kind:=AKind;
   OpCode:=AOpCode;
   OpCode:=AOpCode;
@@ -2383,26 +2401,49 @@ end;
 
 
 { TPrimitiveExpr }
 { TPrimitiveExpr }
 
 
-constructor TPrimitiveExpr.Create(AKind: TPasExprKind; const AValue : Ansistring);
+function TPrimitiveExpr.GetDeclaration(Full : Boolean):AnsiString;
 begin
 begin
-  inherited Create(AKind, eopNone);
+  Result:=Value;
+end;
+
+constructor TPrimitiveExpr.Create(AParent : TPasElement; AKind: TPasExprKind; const AValue : Ansistring);
+begin
+  inherited Create(AParent,AKind, eopNone);
   Value:=AValue;
   Value:=AValue;
 end;
 end;
 
 
 { TBoolConstExpr }
 { TBoolConstExpr }
 
 
-constructor TBoolConstExpr.Create(AKind: TPasExprKind; const ABoolValue : Boolean);
+constructor TBoolConstExpr.Create(AParent : TPasElement; AKind: TPasExprKind; const ABoolValue : Boolean);
 begin
 begin
-  inherited Create(AKind, eopNone);
+  inherited Create(AParent,AKind, eopNone);
   Value:=ABoolValue;
   Value:=ABoolValue;
 end;
 end;
 
 
+Function TBoolConstExpr.GetDeclaration(Full: Boolean):AnsiString;
+
+begin
+  If Value then
+    Result:='True'
+  else
+    Result:='False';  
+end;
+
+
 
 
 { TUnaryExpr }
 { TUnaryExpr }
 
 
-constructor TUnaryExpr.Create(AOperand: TPasExpr; AOpCode: TExprOpCode);
+Function TUnaryExpr.GetDeclaration(Full : Boolean):AnsiString;
+
 begin
 begin
-  inherited Create(pekUnary, AOpCode);
+  Result:=OpCodeStrings[Opcode];
+  If Assigned(Operand) then
+    Result:=Result+Operand.GetDeclaration(Full);
+end;
+
+constructor TUnaryExpr.Create(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode);
+begin
+  inherited Create(AParent,pekUnary, AOpCode);
   Operand:=AOperand;
   Operand:=AOperand;
 end;
 end;
 
 
@@ -2413,16 +2454,30 @@ end;
 
 
 { TBinaryExpr }
 { TBinaryExpr }
 
 
-constructor TBinaryExpr.Create(xleft,xright:TPasExpr; AOpCode:TExprOpCode);
+function TBinaryExpr.GetDeclaration(Full : Boolean):AnsiString;
+
+begin
+  If Kind=pekRange then
+    Result:='..'
+  else
+    Result:=' '+OpcodeStrings[Opcode]+' ';
+  If Assigned(Left) then
+    Result:=Left.GetDeclaration(Full)+Result;
+  If Assigned(Right) then
+    Result:=Result +Right.GetDeclaration(Full);
+end;
+
+
+constructor TBinaryExpr.Create(AParent : TPasElement; xleft,xright:TPasExpr; AOpCode:TExprOpCode);
 begin
 begin
-  inherited Create(pekBinary, AOpCode);
+  inherited Create(AParent,pekBinary, AOpCode);
   left:=xleft;
   left:=xleft;
   right:=xright;
   right:=xright;
 end;
 end;
 
 
-constructor TBinaryExpr.CreateRange(xleft,xright:TPasExpr);
+constructor TBinaryExpr.CreateRange(AParent : TPasElement; xleft,xright:TPasExpr);
 begin
 begin
-  inherited Create(pekRange, eopNone);
+  inherited Create(AParent,pekRange, eopNone);
   left:=xleft;
   left:=xleft;
   right:=xright;
   right:=xright;
 end;
 end;
@@ -2436,6 +2491,21 @@ end;
 
 
 { TParamsExpr }
 { TParamsExpr }
 
 
+Function TParamsExpr.GetDeclaration(Full: Boolean) : Ansistring;
+
+Var
+  I : Integer;
+
+begin
+  For I:=0 to Length(Params) do
+    begin
+    If (Result<>'')  then
+      Result:=Result+', ';
+    Result:=Result+Params[I].GetDeclaration(Full);  
+    end;  
+  Result:='('+Result+')';
+end;
+
 procedure TParamsExpr.AddParam(xp:TPasExpr);
 procedure TParamsExpr.AddParam(xp:TPasExpr);
 var
 var
   i : Integer;
   i : Integer;
@@ -2445,9 +2515,9 @@ begin
   Params[i]:=xp;
   Params[i]:=xp;
 end;
 end;
 
 
-constructor TParamsExpr.Create(AKind: TPasExprKind);
+constructor TParamsExpr.Create(AParent : TPasElement; AKind: TPasExprKind);
 begin
 begin
-  inherited Create(AKind, eopNone)
+  inherited Create(AParent,AKind, eopNone)
 end;
 end;
 
 
 destructor TParamsExpr.Destroy;
 destructor TParamsExpr.Destroy;
@@ -2460,9 +2530,24 @@ end;
 
 
 { TRecordValues }
 { TRecordValues }
 
 
-constructor TRecordValues.Create;
+Function TRecordValues.GetDeclaration(Full : Boolean):AnsiString;
+
+Var
+  I : Integer;
+
+begin
+  For I:=0 to Length(Fields) do
+    begin
+    If Result='' then
+      Result:=Result+'; ';
+    Result:=Result+Fields[I].Name+': '+Fields[i].ValueExp.getDeclaration(Full);
+    end;
+  Result:='('+Result+')'  
+end;
+
+constructor TRecordValues.Create(AParent : TPasElement);
 begin
 begin
-  inherited Create(pekListOfExp, eopNone);
+  inherited Create(AParent,pekListOfExp, eopNone);
 end;
 end;
 
 
 destructor TRecordValues.Destroy;
 destructor TRecordValues.Destroy;
@@ -2473,21 +2558,41 @@ begin
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
-procedure TRecordValues.AddField(const Name:AnsiString;Value:TPasExpr);
+procedure TRecordValues.AddField(const AName:AnsiString;Value:TPasExpr);
 var
 var
   i : Integer;
   i : Integer;
 begin
 begin
   i:=length(Fields);
   i:=length(Fields);
   SetLength(Fields, i+1);
   SetLength(Fields, i+1);
-  Fields[i].Name:=Name;
+  Fields[i].Name:=AName;
   Fields[i].ValueExp:=Value;
   Fields[i].ValueExp:=Value;
 end;
 end;
 
 
 { TArrayValues }
 { TArrayValues }
 
 
-constructor TArrayValues.Create;
+Function TNilExpr.GetDeclaration(Full :Boolean):AnsiString;
+begin
+  Result:='Nil';
+end;
+
+Function TArrayValues.GetDeclaration(Full: Boolean):AnsiString;
+
+Var
+  I : Integer;
+
+begin
+  For I:=0 to Length(Values) do
+    begin
+    If Result='' then
+      Result:=Result+', ';
+    Result:=Result+Values[i].getDeclaration(Full);
+    end;
+  Result:='('+Result+')';
+end;
+
+constructor TArrayValues.Create(AParent : TPasElement);
 begin
 begin
-  inherited Create(pekListOfExp, eopNone)
+  inherited Create(AParent,pekListOfExp, eopNone)
 end;
 end;
 
 
 destructor TArrayValues.Destroy;
 destructor TArrayValues.Destroy;
@@ -2509,9 +2614,9 @@ end;
 
 
 { TNilExpr }
 { TNilExpr }
 
 
-constructor TNilExpr.Create;
+constructor TNilExpr.Create(AParent : TPasElement);
 begin
 begin
-  inherited Create(pekNil, eopNone);
+  inherited Create(AParent,pekNil, eopNone);
 end;
 end;
 
 
 end.
 end.

+ 122 - 128
packages/fcl-passrc/src/pparser.pp

@@ -99,6 +99,9 @@ type
   TProcType = (ptProcedure, ptFunction, ptOperator, ptConstructor, ptDestructor,
   TProcType = (ptProcedure, ptFunction, ptOperator, ptConstructor, ptDestructor,
                ptClassProcedure, ptClassFunction);
                ptClassProcedure, ptClassFunction);
 
 
+               
+  TExprKind = (ek_Normal, ek_PropertyIndex);               
+               
   { TPasParser }
   { TPasParser }
 
 
   TPasParser = class
   TPasParser = class
@@ -125,8 +128,8 @@ type
     Function IsCurTokenHint: Boolean; overload;
     Function IsCurTokenHint: Boolean; overload;
     Function CheckHint(Element : TPasElement; ExpectSemiColon : Boolean) : TPasMemberHints;
     Function CheckHint(Element : TPasElement; ExpectSemiColon : Boolean) : TPasMemberHints;
 
 
-    function ParseParams(paramskind: TPasExprKind): TParamsExpr;
-    function ParseExpIdent: TPasExpr;
+    function ParseParams(AParent : TPasElement;paramskind: TPasExprKind): TParamsExpr;
+    function ParseExpIdent(AParent : TPasElement): TPasExpr;
   public
   public
     Options : set of TPOptions;
     Options : set of TPOptions;
     CurModule: TPasModule;
     CurModule: TPasModule;
@@ -145,9 +148,9 @@ type
     procedure ParseArrayType(Element: TPasArrayType);
     procedure ParseArrayType(Element: TPasArrayType);
     procedure ParseFileType(Element: TPasFileType);
     procedure ParseFileType(Element: TPasFileType);
     function isEndOfExp: Boolean;
     function isEndOfExp: Boolean;
-    function DoParseExpression(InitExpr: TPasExpr=nil): TPasExpr;
-    function DoParseConstValueExpression: TPasExpr;
-    function ParseExpression: String;
+    function DoParseExpression(Aparent : TPaselement;InitExpr: TPasExpr=nil): TPasExpr;
+    function DoParseConstValueExpression(AParent : TPasElement): TPasExpr;
+    function ParseExpression(AParent : TPaselement; Kind: TExprKind=ek_Normal): String;
     function ParseCommand: String; // single, not compound command like begin..end
     function ParseCommand: String; // single, not compound command like begin..end
     procedure AddProcOrFunction(Declarations: TPasDeclarations; AProc: TPasProcedure);
     procedure AddProcOrFunction(Declarations: TPasDeclarations; AProc: TPasProcedure);
     function CheckIfOverloaded(AOwner: TPasClassType;
     function CheckIfOverloaded(AOwner: TPasClassType;
@@ -400,9 +403,9 @@ function TPasParser.ParseType(Parent: TPasElement; Prefix : String): TPasType;
   begin
   begin
     Result := TPasRangeType(CreateElement(TPasRangeType, '', Parent));
     Result := TPasRangeType(CreateElement(TPasRangeType, '', Parent));
     try
     try
-      TPasRangeType(Result).RangeStart := ParseExpression;
+      TPasRangeType(Result).RangeStart := ParseExpression(Result);
       ExpectToken(tkDotDot);
       ExpectToken(tkDotDot);
-      TPasRangeType(Result).RangeEnd := ParseExpression;
+      TPasRangeType(Result).RangeEnd := ParseExpression(Result);
     except
     except
       Result.Free;
       Result.Free;
       raise;
       raise;
@@ -510,7 +513,7 @@ begin
             break
             break
           else if CurToken in [tkEqual,tkAssign] then
           else if CurToken in [tkEqual,tkAssign] then
             begin
             begin
-            EnumValue.AssignedValue:=ParseExpression;
+            EnumValue.AssignedValue:=ParseExpression(Result);
             NextToken;
             NextToken;
             if CurToken = tkBraceClose then
             if CurToken = tkBraceClose then
               Break
               Break
@@ -648,7 +651,9 @@ procedure TPasParser.ParseFileType(Element: TPasFileType);
 begin
 begin
   NextToken;
   NextToken;
   If CurToken=tkOf then
   If CurToken=tkOf then
-    Element.ElType := ParseType(nil);
+    Element.ElType := ParseType(nil)
+  else 
+   ungettoken;
 end;
 end;
 
 
 function TPasParser.isEndOfExp:Boolean;
 function TPasParser.isEndOfExp:Boolean;
@@ -661,7 +666,7 @@ begin
   Result:=(CurToken in EndExprToken) or IsCurTokenHint;
   Result:=(CurToken in EndExprToken) or IsCurTokenHint;
 end;
 end;
 
 
-function TPasParser.ParseParams(paramskind: TPasExprKind): TParamsExpr;
+function TPasParser.ParseParams(AParent: TPasElement;paramskind: TPasExprKind): TParamsExpr;
 var
 var
   params  : TParamsExpr;
   params  : TParamsExpr;
   p       : TPasExpr;
   p       : TPasExpr;
@@ -676,12 +681,12 @@ begin
     PClose:=tkBraceClose;
     PClose:=tkBraceClose;
   end;
   end;
 
 
-  params:=TParamsExpr.Create(paramskind);
+  params:=TParamsExpr.Create(AParent,paramskind);
   try
   try
     NextToken;
     NextToken;
     if not isEndOfExp then begin
     if not isEndOfExp then begin
       repeat
       repeat
-        p:=DoParseExpression;
+        p:=DoParseExpression(AParent);
         if not Assigned(p) then Exit; // bad param syntax
         if not Assigned(p) then Exit; // bad param syntax
         params.AddParam(p);
         params.AddParam(p);
 
 
@@ -740,7 +745,7 @@ begin
   end;
   end;
 end;
 end;
  
  
-function TPasParser.ParseExpIdent:TPasExpr;
+function TPasParser.ParseExpIdent(AParent : TPasElement):TPasExpr;
 var
 var
   x       : TPasExpr;
   x       : TPasExpr;
   prm     : TParamsExpr;
   prm     : TParamsExpr;
@@ -750,13 +755,13 @@ var
 begin
 begin
   Result:=nil;
   Result:=nil;
   case CurToken of
   case CurToken of
-    tkString:           x:=TPrimitiveExpr.Create(pekString, CurTokenString);
-    tkChar:             x:=TPrimitiveExpr.Create(pekString, CurTokenText);
-    tkNumber:           x:=TPrimitiveExpr.Create(pekNumber, CurTokenString);
-    tkIdentifier:       x:=TPrimitiveExpr.Create(pekIdent, CurTokenText);
-    tkfalse, tktrue:    x:=TBoolConstExpr.Create(pekBoolConst, CurToken=tktrue);
-    tknil:              x:=TNilExpr.Create;
-    tkSquaredBraceOpen: x:=ParseParams(pekSet);
+    tkString:           x:=TPrimitiveExpr.Create(AParent,pekString, CurTokenString);
+    tkChar:             x:=TPrimitiveExpr.Create(AParent,pekString, CurTokenText);
+    tkNumber:           x:=TPrimitiveExpr.Create(AParent,pekNumber, CurTokenString);
+    tkIdentifier:       x:=TPrimitiveExpr.Create(AParent,pekIdent, CurTokenText);
+    tkfalse, tktrue:    x:=TBoolConstExpr.Create(Aparent,pekBoolConst, CurToken=tktrue);
+    tknil:              x:=TNilExpr.Create(Aparent);
+    tkSquaredBraceOpen: x:=ParseParams(AParent,pekSet);
     tkCaret: begin
     tkCaret: begin
       // ^A..^_ characters. See #16341
       // ^A..^_ characters. See #16341
       NextToken;
       NextToken;
@@ -764,7 +769,7 @@ begin
         UngetToken;
         UngetToken;
         ParseExc(SParserExpectedIdentifier);
         ParseExc(SParserExpectedIdentifier);
       end;
       end;
-      x:=TPrimitiveExpr.Create(pekString, '^'+CurTokenText);
+      x:=TPrimitiveExpr.Create(AParent,pekString, '^'+CurTokenText);
     end;
     end;
   else
   else
     ParseExc(SParserExpectedIdentifier);
     ParseExc(SParserExpectedIdentifier);
@@ -777,19 +782,19 @@ begin
       while CurToken in [tkBraceOpen, tkSquaredBraceOpen, tkCaret] do
       while CurToken in [tkBraceOpen, tkSquaredBraceOpen, tkCaret] do
         case CurToken of
         case CurToken of
           tkBraceOpen: begin
           tkBraceOpen: begin
-            prm:=ParseParams(pekFuncParams);
+            prm:=ParseParams(AParent,pekFuncParams);
             if not Assigned(prm) then Exit;
             if not Assigned(prm) then Exit;
             prm.Value:=x;
             prm.Value:=x;
             x:=prm;
             x:=prm;
           end;
           end;
           tkSquaredBraceOpen: begin
           tkSquaredBraceOpen: begin
-            prm:=ParseParams(pekArrayParams);
+            prm:=ParseParams(AParent,pekArrayParams);
             if not Assigned(prm) then Exit;
             if not Assigned(prm) then Exit;
             prm.Value:=x;
             prm.Value:=x;
             x:=prm;
             x:=prm;
           end;
           end;
           tkCaret: begin
           tkCaret: begin
-            u:=TUnaryExpr.Create(x, TokenToExprOp(CurToken));
+            u:=TUnaryExpr.Create(AParent,x, TokenToExprOp(CurToken));
             x:=u;
             x:=u;
             NextToken;
             NextToken;
           end;
           end;
@@ -798,7 +803,7 @@ begin
       if CurToken in [tkDot, tkas] then begin
       if CurToken in [tkDot, tkas] then begin
         optk:=CurToken;
         optk:=CurToken;
         NextToken;
         NextToken;
-        b:=TBinaryExpr.Create(x, ParseExpIdent(), TokenToExprOp(optk));
+        b:=TBinaryExpr.Create(AParent,x, ParseExpIdent(AParent), TokenToExprOp(optk));
         if not Assigned(b.right) then Exit; // error
         if not Assigned(b.right) then Exit; // error
         x:=b;
         x:=b;
       end;
       end;
@@ -806,7 +811,7 @@ begin
 
 
     if CurToken = tkDotDot then begin
     if CurToken = tkDotDot then begin
       NextToken;
       NextToken;
-      b:=TBinaryExpr.CreateRange(x, DoParseExpression);
+      b:=TBinaryExpr.CreateRange(AParent,x, DoParseExpression(AParent));
       if not Assigned(b.right) then Exit; // error
       if not Assigned(b.right) then Exit; // error
       x:=b;
       x:=b;
     end;
     end;
@@ -833,7 +838,7 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TPasParser.DoParseExpression(InitExpr: TPasExpr): TPasExpr;
+function TPasParser.DoParseExpression(Aparent : TPaselement;InitExpr: TPasExpr): TPasExpr;
 var
 var
   expstack  : TList;
   expstack  : TList;
   opstack   : TList;
   opstack   : TList;
@@ -886,7 +891,7 @@ const
     t:=PopOper;
     t:=PopOper;
     xright:=PopExp;
     xright:=PopExp;
     xleft:=PopExp;
     xleft:=PopExp;
-    expstack.Add(TBinaryExpr.Create(xleft, xright, TokenToExprOp(t)));
+    expstack.Add(TBinaryExpr.Create(AParent,xleft, xright, TokenToExprOp(t)));
   end;
   end;
 
 
 begin
 begin
@@ -921,18 +926,18 @@ begin
 
 
         if CurToken = tkBraceOpen then begin
         if CurToken = tkBraceOpen then begin
           NextToken;
           NextToken;
-          x:=DoParseExpression();
+          x:=DoParseExpression(AParent);
           if CurToken<>tkBraceClose then Exit;
           if CurToken<>tkBraceClose then Exit;
           NextToken;
           NextToken;
         end else begin
         end else begin
-          x:=ParseExpIdent;
+          x:=ParseExpIdent(AParent);
         end;
         end;
 
 
         if not Assigned(x) then Exit;
         if not Assigned(x) then Exit;
         expstack.Add(x);
         expstack.Add(x);
         for i:=1 to pcount do begin
         for i:=1 to pcount do begin
           tempop:=PopOper;
           tempop:=PopOper;
-          expstack.Add( TUnaryExpr.Create( PopExp, TokenToExprOp(tempop) ));
+          expstack.Add( TUnaryExpr.Create(AParent, PopExp, TokenToExprOp(tempop) ));
         end;
         end;
 
 
       end else
       end else
@@ -973,10 +978,11 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TPasParser.ParseExpression: String;
+function TPasParser.ParseExpression(Aparent : TPaselement;Kind: TExprKind): String;
 var
 var
   BracketLevel: Integer;
   BracketLevel: Integer;
   LastTokenWasWord: Boolean;
   LastTokenWasWord: Boolean;
+  ls: String;
 begin
 begin
   SetLength(Result, 0);
   SetLength(Result, 0);
   BracketLevel := 0;
   BracketLevel := 0;
@@ -993,11 +999,21 @@ begin
       if BracketLevel = 0 then
       if BracketLevel = 0 then
         break;
         break;
       Dec(BracketLevel);
       Dec(BracketLevel);
-    end else if (BracketLevel = 0) and (CurToken in [tkComma, tkSemicolon,
-      tkColon, tkDotDot, tkthen, tkend, tkelse, tkuntil, tkfinally, tkexcept,
-      tkof, tkbegin, tkdo, tkto, tkdownto, tkinitialization, tkfinalization])
-    then
-      break;
+    end else if (BracketLevel = 0) then 
+    begin
+      if (CurToken in [tkComma, tkSemicolon,
+        tkColon, tkDotDot, tkthen, tkend, tkelse, tkuntil, tkfinally, tkexcept,
+        tkof, tkbegin, tkdo, tkto, tkdownto, tkinitialization, tkfinalization])
+      then
+        break;
+        
+      if (Kind=ek_PropertyIndex) and (CurToken=tkIdentifier) then begin
+        ls:=LowerCase(CurTokenText);
+        if (ls='read') or (ls ='write') or (ls='default') or (ls='nodefault') or (ls='implements') then
+          Break;
+      end;
+        
+    end;
 
 
     if (CurTokenString<>'') and IsIdentStart[CurTokenString[1]] then
     if (CurTokenString<>'') and IsIdentStart[CurTokenString[1]] then
       begin
       begin
@@ -1029,7 +1045,7 @@ begin
     Result:='';
     Result:='';
 end;
 end;
 
 
-function TPasParser.DoParseConstValueExpression: TPasExpr;
+function TPasParser.DoParseConstValueExpression(Aparent : TPaselement): TPasExpr;
 var
 var
   x : TPasExpr;
   x : TPasExpr;
   n : AnsiString;
   n : AnsiString;
@@ -1052,18 +1068,18 @@ end;
 
 
 begin
 begin
   if CurToken <> tkBraceOpen then
   if CurToken <> tkBraceOpen then
-    Result:=DoParseExpression
+    Result:=DoParseExpression(AParent)
   else begin
   else begin
     NextToken;
     NextToken;
-    x:=DoParseConstValueExpression();
+    x:=DoParseConstValueExpression(Aparent);
     case CurToken of
     case CurToken of
       tkComma: // array of values (a,b,c);
       tkComma: // array of values (a,b,c);
         begin
         begin
-          a:=TArrayValues.Create;
+          a:=TArrayValues.Create(AParent);
           a.AddValues(x);
           a.AddValues(x);
           repeat
           repeat
             NextToken;
             NextToken;
-            x:=DoParseConstValueExpression();
+            x:=DoParseConstValueExpression(AParent);
             a.AddValues(x);
             a.AddValues(x);
           until CurToken<>tkComma;
           until CurToken<>tkComma;
           Result:=a;
           Result:=a;
@@ -1073,23 +1089,23 @@ begin
         begin
         begin
           n:=GetExprIdent(x);
           n:=GetExprIdent(x);
           x.Free;
           x.Free;
-          r:=TRecordValues.Create;
+          r:=TRecordValues.Create(AParent);
           NextToken;
           NextToken;
-          x:=DoParseConstValueExpression();
+          x:=DoParseConstValueExpression(AParent);
           r.AddField(n, x);
           r.AddField(n, x);
           if not lastfield then
           if not lastfield then
             repeat
             repeat
               n:=ExpectIdentifier;
               n:=ExpectIdentifier;
               ExpectToken(tkColon);
               ExpectToken(tkColon);
               NextToken;
               NextToken;
-              x:=DoParseConstValueExpression();
+              x:=DoParseConstValueExpression(AParent);
               r.AddField(n, x)
               r.AddField(n, x)
             until lastfield; // CurToken<>tkSemicolon;
             until lastfield; // CurToken<>tkSemicolon;
           Result:=r;
           Result:=r;
         end;
         end;
     else
     else
       // Binary expression!  ((128 div sizeof(longint)) - 3);       ;
       // Binary expression!  ((128 div sizeof(longint)) - 3);       ;
-      Result:=DoParseExpression(x);
+      Result:=DoParseExpression(AParent,x);
     end;
     end;
     if CurToken<>tkBraceClose then ParseExc(SParserExpectedCommaRBracket);
     if CurToken<>tkBraceClose then ParseExc(SParserExpectedCommaRBracket);
     NextToken;
     NextToken;
@@ -1536,7 +1552,7 @@ begin
   begin
   begin
     AUnitName := ExpectIdentifier;
     AUnitName := ExpectIdentifier;
 
 
-    Element := Engine.FindModule(AUnitName);
+    Element := Engine.FindModule(AUnitName); // should we resolve module here when "IN" filename is not known yet?
     if Assigned(Element) then
     if Assigned(Element) then
       Element.AddRef
       Element.AddRef
     else
     else
@@ -1550,6 +1566,8 @@ begin
       // todo: store unit's file name somewhere
       // todo: store unit's file name somewhere
       NextToken; // skip in
       NextToken; // skip in
       ExpectToken(tkString); // skip unit's real file name
       ExpectToken(tkString); // skip unit's real file name
+      if (Element is TPasModule) and (TPasmodule(Element).filename<>'')  then
+        TPasModule(Element).FileName:=curtokenstring;
     end;
     end;
 
 
     if CurToken = tkSemicolon then
     if CurToken = tkSemicolon then
@@ -1577,7 +1595,7 @@ begin
 
 
     // using new expression parser!
     // using new expression parser!
     NextToken; // skip tkEqual
     NextToken; // skip tkEqual
-    Result.Expr:=DoParseConstValueExpression;
+    Result.Expr:=DoParseConstValueExpression(Result);
 
 
     // must unget for the check to be peformed fine!
     // must unget for the check to be peformed fine!
     UngetToken;
     UngetToken;
@@ -1595,7 +1613,7 @@ begin
   Result := TPasResString(CreateElement(TPasResString, CurTokenString, Parent));
   Result := TPasResString(CreateElement(TPasResString, CurTokenString, Parent));
   try
   try
     ExpectToken(tkEqual);
     ExpectToken(tkEqual);
-    Result.Value := ParseExpression;
+    Result.Value := ParseExpression(Result);
     CheckHint(Result,True);
     CheckHint(Result,True);
   except
   except
     Result.Free;
     Result.Free;
@@ -1612,9 +1630,9 @@ var
   begin
   begin
     Result := TPasRangeType(CreateElement(TPasRangeType, TypeName, Parent));
     Result := TPasRangeType(CreateElement(TPasRangeType, TypeName, Parent));
     try
     try
-      TPasRangeType(Result).RangeStart := ParseExpression;
+      TPasRangeType(Result).RangeStart := ParseExpression(Result);
       ExpectToken(tkDotDot);
       ExpectToken(tkDotDot);
-      TPasRangeType(Result).RangeEnd := ParseExpression;
+      TPasRangeType(Result).RangeEnd := ParseExpression(Result);
       CheckHint(Result,True);
       CheckHint(Result,True);
     except
     except
       Result.Free;
       Result.Free;
@@ -1716,7 +1734,7 @@ begin
           try
           try
             TPasAliasType(Result).DestType :=
             TPasAliasType(Result).DestType :=
               TPasUnresolvedTypeRef.Create(CurTokenString, Parent);
               TPasUnresolvedTypeRef.Create(CurTokenString, Parent);
-            ParseExpression;
+            ParseExpression(Parent);
             ExpectToken(tkSquaredBraceClose);
             ExpectToken(tkSquaredBraceClose);
             CheckHint(Result,True);
             CheckHint(Result,True);
           except
           except
@@ -1781,7 +1799,7 @@ begin
               break
               break
             else if CurToken in [tkEqual,tkAssign] then
             else if CurToken in [tkEqual,tkAssign] then
               begin
               begin
-              EnumValue.AssignedValue:=ParseExpression;
+              EnumValue.AssignedValue:=ParseExpression(result);
               NextToken;
               NextToken;
               if CurToken = tkBraceClose then
               if CurToken = tkBraceClose then
                 Break
                 Break
@@ -1929,7 +1947,7 @@ begin
   // Writeln(LastVar,': Parsed complex type, next: ',CurtokenText);
   // Writeln(LastVar,': Parsed complex type, next: ',CurtokenText);
   If CurToken=tkEqual then
   If CurToken=tkEqual then
     begin
     begin
-    Value := ParseExpression;
+    Value := ParseExpression(Parent);
     for i := 0 to List.Count - 1 do
     for i := 0 to List.Count - 1 do
       TPasVariable(List[i]).Value := Value;
       TPasVariable(List[i]).Value := Value;
     NextToken;
     NextToken;
@@ -2076,7 +2094,7 @@ begin
       NextToken;
       NextToken;
       if CurToken = tkEqual then
       if CurToken = tkEqual then
       begin
       begin
-        Value := ParseExpression;
+        Value := ParseExpression(Parent);
       end else
       end else
         UngetToken;
         UngetToken;
     end;
     end;
@@ -2378,6 +2396,9 @@ end;
 
 
 procedure TPasParser.ParseProperty(Element:TPasElement);
 procedure TPasParser.ParseProperty(Element:TPasElement);
 
 
+var
+  isArray : Boolean;
+
   procedure MaybeReadFullyQualifiedIdentifier(Var r : String);
   procedure MaybeReadFullyQualifiedIdentifier(Var r : String);
 
 
   begin
   begin
@@ -2413,11 +2434,16 @@ procedure TPasParser.ParseProperty(Element:TPasElement);
     //writeln(Result);
     //writeln(Result);
   end;
   end;
 
 
+var
+  us  : String; 
+  h   : TPasMemberHint;
 begin
 begin
-
+  isArray:=False;
   NextToken;
   NextToken;
 // if array prop then parse [ arg1:type1;... ]
 // if array prop then parse [ arg1:type1;... ]
+
   if CurToken = tkSquaredBraceOpen then begin
   if CurToken = tkSquaredBraceOpen then begin
+    isArray:=True;
   // !!!: Parse array properties correctly
   // !!!: Parse array properties correctly
     ParseArgList(Element, TPasProperty(Element).Args, tkSquaredBraceClose);
     ParseArgList(Element, TPasProperty(Element).Args, tkSquaredBraceClose);
     NextToken;
     NextToken;
@@ -2432,10 +2458,10 @@ begin
 
 
   if CurToken <> tkSemicolon then begin
   if CurToken <> tkSemicolon then begin
 //  if indexed prop then read the index value
 //  if indexed prop then read the index value
-    if (CurToken = tkIdentifier) and (UpperCase(CurTokenText) = 'INDEX') then
+    if (CurToken = tkIdentifier) and (UpperCase(CurTokenText) = 'INDEX') then begin
 //    read 'index' access modifier
 //    read 'index' access modifier
-      TPasProperty(Element).IndexValue := ParseExpression
-    else
+      TPasProperty(Element).IndexValue := ParseExpression(Element,ek_PropertyIndex);
+    end else
 //    not indexed prop will be recheck for another token
 //    not indexed prop will be recheck for another token
       UngetToken;
       UngetToken;
 
 
@@ -2490,24 +2516,19 @@ begin
   end;
   end;
 
 
 // if the specifiers list is not finished
 // if the specifiers list is not finished
-  if CurToken <> tkSemicolon then begin
-    if (CurToken = tkIdentifier) and (UpperCase(CurTokenText) = 'DEFAULT') then
+  if (CurToken <> tkSemicolon) and (CurToken = tkIdentifier) then begin
+    us:=UpperCase(CurTokenText);
+    if (us = 'DEFAULT') then begin
+      if isArray then ParseExc('Array properties cannot have default value');
 //    read 'default' value modifier -> ParseExpression(DEFAULT <value>)
 //    read 'default' value modifier -> ParseExpression(DEFAULT <value>)
-      TPasProperty(Element).DefaultValue := ParseExpression
-    else
-//    not "default <value>" prop will be recheck for another token
-      UngetToken;
-
-    NextToken;
-  end;
-
-// if the specifiers list is not finished
-  if CurToken <> tkSemicolon then begin
-    if (CurToken = tkIdentifier) and (UpperCase(CurTokenText) = 'NODEFAULT') then begin
+      TPasProperty(Element).DefaultValue := ParseExpression(Element);
+      NextToken;
+    end else if (us = 'NODEFAULT') then begin
 //    read 'nodefault' modifier
 //    read 'nodefault' modifier
       TPasProperty(Element).IsNodefault:=true;
       TPasProperty(Element).IsNodefault:=true;
-    end;
-//  stop recheck for specifiers - start from next token
+    end else
+//    not "default <value>" prop will be recheck for another token
+      UngetToken;
     NextToken;
     NextToken;
   end;
   end;
 
 
@@ -2518,55 +2539,28 @@ begin
   end;
   end;
 
 
   if (CurToken = tkIdentifier) and (UpperCase(CurTokenText) = 'DEFAULT') then begin
   if (CurToken = tkIdentifier) and (UpperCase(CurTokenText) = 'DEFAULT') then begin
+    if not isArray then ParseExc('The default property must be an array property');
 //  what is after DEFAULT token at the end
 //  what is after DEFAULT token at the end
     NextToken;
     NextToken;
     if CurToken = tkSemicolon then begin
     if CurToken = tkSemicolon then begin
 //    ";" then DEFAULT=prop
 //    ";" then DEFAULT=prop
       TPasProperty(Element).IsDefault := True;
       TPasProperty(Element).IsDefault := True;
-      UngetToken;
-    end else begin
-//    "!;" then a step back to get phrase "DEFAULT <value>"
-      UngetToken;
-//    DefaultValue  -> ParseExpression(DEFAULT <value>)  and stay on the <value>
-      TPasProperty(Element).DefaultValue := ParseExpression;
-    end;
-
-//!!  there may be DEPRECATED token
-    CheckHint(Element,False);
-    NextToken;
-
+      NextToken;
+    end
   end;
   end;
-
-// after DEFAULT may be a ";"
-  if CurToken = tkSemicolon then begin
-    // read semicolon
+  
+  while IsCurTokenHint(h) do begin
+    Element.Hints:=Element.Hints+[h];
     NextToken;
     NextToken;
-  end;
-
-  if (CurToken = tkIdentifier) and (UpperCase(CurTokenText) = 'DEPRECATED') then begin
-//  nothing to do on DEPRECATED - just to accept
-//    NextToken;
-  end else
-    UngetToken;;
-
-//!!   else
-//  not DEFAULT prop accessor will be recheck for another token
-//!!    UngetToken;
+    // there can be multiple hints, separated by the, i.e.:
+    // property Prop: integer read FMyProp write FMyProp; platform; library deprecated;
+    if CurToken=tkSemicolon then 
+      NextToken;
+  end;    
 
 
-{
-  if CurToken = tkSemicolon then begin
-    // read semicolon
-    NextToken;
-  end;
-  if (CurToken = tkIdentifier) and (UpperCase(CurTokenText) = 'DEPRECATED') then begin
-//  nothing to do - just to process
-    NextToken;
-  end;
-  if CurToken = tkSemicolon then begin
-    // read semicolon
-    NextToken;
-  end;
-}
+  // property parsing must finish at the LAST Semicolon of the property
+  // since we're parsing "one-step" ahead of the semicolon. we must return one-step
+  UngetToken; 
 end;
 end;
 
 
 // Starts after the "begin" token
 // Starts after the "begin" token
@@ -2661,7 +2655,7 @@ begin
       CreateBlock(CurBlock.AddRepeatUntil);
       CreateBlock(CurBlock.AddRepeatUntil);
     tkIf:
     tkIf:
       begin
       begin
-        Condition:=ParseExpression;
+        Condition:=ParseExpression(Parent);
         //WriteLn(i,'IF Condition="',Condition,'" Token=',CurTokenText);
         //WriteLn(i,'IF Condition="',Condition,'" Token=',CurTokenText);
         CreateBlock(CurBlock.AddIfElse(Condition));
         CreateBlock(CurBlock.AddIfElse(Condition));
         ExpectToken(tkthen);
         ExpectToken(tkthen);
@@ -2683,7 +2677,7 @@ begin
     tkwhile:
     tkwhile:
       begin
       begin
         // while Condition do
         // while Condition do
-        Condition:=ParseExpression;
+        Condition:=ParseExpression(Parent);
         //WriteLn(i,'WHILE Condition="',Condition,'" Token=',CurTokenText);
         //WriteLn(i,'WHILE Condition="',Condition,'" Token=',CurTokenText);
         CreateBlock(CurBlock.AddWhileDo(Condition));
         CreateBlock(CurBlock.AddWhileDo(Condition));
         ExpectToken(tkdo);
         ExpectToken(tkdo);
@@ -2694,7 +2688,7 @@ begin
         ExpectIdentifier;
         ExpectIdentifier;
         VarName:=CurTokenString;
         VarName:=CurTokenString;
         ExpectToken(tkAssign);
         ExpectToken(tkAssign);
-        StartValue:=ParseExpression;
+        StartValue:=ParseExpression(Parent);
         //writeln(i,'FOR Start=',StartValue);
         //writeln(i,'FOR Start=',StartValue);
         NextToken;
         NextToken;
         if CurToken=tkTo then
         if CurToken=tkTo then
@@ -2703,7 +2697,7 @@ begin
           ForDownTo:=true
           ForDownTo:=true
         else
         else
           ParseExc(Format(SParserExpectTokenError, [TokenInfos[tkTo]]));
           ParseExc(Format(SParserExpectTokenError, [TokenInfos[tkTo]]));
-        EndValue:=ParseExpression;
+        EndValue:=ParseExpression(Parent);
         CreateBlock(CurBlock.AddForLoop(VarName,StartValue,EndValue,ForDownTo));
         CreateBlock(CurBlock.AddForLoop(VarName,StartValue,EndValue,ForDownTo));
         //WriteLn(i,'FOR "',VarName,'" := ',StartValue,' to ',EndValue,' Token=',CurTokenText);
         //WriteLn(i,'FOR "',VarName,'" := ',StartValue,' to ',EndValue,' Token=',CurTokenText);
         ExpectToken(tkdo);
         ExpectToken(tkdo);
@@ -2712,7 +2706,7 @@ begin
       begin
       begin
         // with Expr do
         // with Expr do
         // with Expr, Expr do
         // with Expr, Expr do
-        Expr:=ParseExpression;
+        Expr:=ParseExpression(Parent);
         //writeln(i,'WITH Expr="',Expr,'" Token=',CurTokenText);
         //writeln(i,'WITH Expr="',Expr,'" Token=',CurTokenText);
         CreateBlock(CurBlock.AddWithDo(Expr));
         CreateBlock(CurBlock.AddWithDo(Expr));
         repeat
         repeat
@@ -2720,14 +2714,14 @@ begin
           if CurToken=tkdo then break;
           if CurToken=tkdo then break;
           if CurToken<>tkComma then
           if CurToken<>tkComma then
             ParseExc(Format(SParserExpectTokenError, [TokenInfos[tkdo]]));
             ParseExc(Format(SParserExpectTokenError, [TokenInfos[tkdo]]));
-          Expr:=ParseExpression;
+          Expr:=ParseExpression(Parent);
           //writeln(i,'WITH ...,Expr="',Expr,'" Token=',CurTokenText);
           //writeln(i,'WITH ...,Expr="',Expr,'" Token=',CurTokenText);
           TPasImplWithDo(CurBlock).AddExpression(Expr);
           TPasImplWithDo(CurBlock).AddExpression(Expr);
         until false;
         until false;
       end;
       end;
     tkcase:
     tkcase:
       begin
       begin
-        Expr:=ParseExpression;
+        Expr:=ParseExpression(Parent);
         //writeln(i,'CASE OF Expr="',Expr,'" Token=',CurTokenText);
         //writeln(i,'CASE OF Expr="',Expr,'" Token=',CurTokenText);
         ExpectToken(tkof);
         ExpectToken(tkof);
         CreateBlock(CurBlock.AddCaseOf(Expr));
         CreateBlock(CurBlock.AddCaseOf(Expr));
@@ -2747,7 +2741,7 @@ begin
             UngetToken;
             UngetToken;
             // read case values
             // read case values
             repeat
             repeat
-              Expr:=ParseExpression;
+              Expr:=ParseExpression(Parent);
               //writeln(i,'CASE value="',Expr,'" Token=',CurTokenText);
               //writeln(i,'CASE value="',Expr,'" Token=',CurTokenText);
               if CurBlock is TPasImplCaseStatement then
               if CurBlock is TPasImplCaseStatement then
                 TPasImplCaseStatement(CurBlock).Expressions.Add(Expr)
                 TPasImplCaseStatement(CurBlock).Expressions.Add(Expr)
@@ -2756,7 +2750,7 @@ begin
               NextToken;
               NextToken;
               if CurToken=tkDotDot then
               if CurToken=tkDotDot then
               begin
               begin
-                Expr:=Expr+'..'+ParseExpression;
+                Expr:=Expr+'..'+ParseExpression(Parent);
                 NextToken;
                 NextToken;
               end;
               end;
               //writeln(i,'CASE after value Token=',CurTokenText);
               //writeln(i,'CASE after value Token=',CurTokenText);
@@ -2820,13 +2814,13 @@ begin
         if CurBlock is TPasImplTryExcept then
         if CurBlock is TPasImplTryExcept then
         begin
         begin
           VarName:='';
           VarName:='';
-          TypeName:=ParseExpression;
+          TypeName:=ParseExpression(Parent);
           //writeln(i,'ON t=',TypeName,' Token=',CurTokenText);
           //writeln(i,'ON t=',TypeName,' Token=',CurTokenText);
           NextToken;
           NextToken;
           if CurToken=tkColon then
           if CurToken=tkColon then
           begin
           begin
             VarName:=TypeName;
             VarName:=TypeName;
-            TypeName:=ParseExpression;
+            TypeName:=ParseExpression(Parent);
             //writeln(i,'ON v=',VarName,' t=',TypeName,' Token=',CurTokenText);
             //writeln(i,'ON v=',VarName,' t=',TypeName,' Token=',CurTokenText);
           end else
           end else
             UngetToken;
             UngetToken;
@@ -2872,7 +2866,7 @@ begin
         end;
         end;
         if CurBlock is TPasImplRepeatUntil then
         if CurBlock is TPasImplRepeatUntil then
         begin
         begin
-          Condition:=ParseExpression;
+          Condition:=ParseExpression(Parent);
           TPasImplRepeatUntil(CurBlock).Condition:=Condition;
           TPasImplRepeatUntil(CurBlock).Condition:=Condition;
           //WriteLn(i,'UNTIL Condition="',Condition,'" Token=',CurTokenString);
           //WriteLn(i,'UNTIL Condition="',Condition,'" Token=',CurTokenString);
           if CloseBlock then break;
           if CloseBlock then break;
@@ -3020,7 +3014,7 @@ begin
         Variant.Values := TStringList.Create;
         Variant.Values := TStringList.Create;
         while True do
         while True do
         begin
         begin
-      Variant.Values.Add(ParseExpression);
+      Variant.Values.Add(ParseExpression(Parent));
       NextToken;
       NextToken;
       if CurToken = tkColon then
       if CurToken = tkColon then
         break
         break

+ 79 - 72
packages/fcl-xml/src/sax_xml.pp

@@ -40,6 +40,7 @@ type
     FEndOfStream: Boolean;
     FEndOfStream: Boolean;
     FScannerContext: TXMLScannerContext;
     FScannerContext: TXMLScannerContext;
     FTokenText: SAXString;
     FTokenText: SAXString;
+    FRawTokenText: string;
     FCurStringValueDelimiter: Char;
     FCurStringValueDelimiter: Char;
     FAttrNameRead: Boolean;
     FAttrNameRead: Boolean;
   protected
   protected
@@ -103,7 +104,9 @@ procedure ReadXMLFragment(AParentNode: TDOMNode; var f: TStream);
 
 
 implementation
 implementation
 
 
-uses htmldefs; // for entities...
+uses
+  xmlutils,
+  htmldefs; // for entities...
 
 
 const
 const
   WhitespaceChars = [#9, #10, #13, ' '];
   WhitespaceChars = [#9, #10, #13, ' '];
@@ -154,6 +157,7 @@ begin
 
 
     BufferPos := 0;
     BufferPos := 0;
     while (BufferPos < BufferSize) and not FStopFlag do
     while (BufferPos < BufferSize) and not FStopFlag do
+    begin
       case ScannerContext of
       case ScannerContext of
         scUnknown:
         scUnknown:
           case Buffer[BufferPos] of
           case Buffer[BufferPos] of
@@ -176,7 +180,7 @@ begin
           case Buffer[BufferPos] of
           case Buffer[BufferPos] of
             #9, #10, #13, ' ':
             #9, #10, #13, ' ':
               begin
               begin
-                FTokenText := FTokenText + Buffer[BufferPos];
+                FRawTokenText := FRawTokenText + Buffer[BufferPos];
                 Inc(BufferPos);
                 Inc(BufferPos);
               end;
               end;
             '&':
             '&':
@@ -190,7 +194,7 @@ begin
                 EnterNewScannerContext(scTag);
                 EnterNewScannerContext(scTag);
               end;
               end;
             else
             else
-              FScannerContext := scText
+              FScannerContext := scText;
           end;
           end;
         scText:
         scText:
           case Buffer[BufferPos] of
           case Buffer[BufferPos] of
@@ -206,7 +210,7 @@ begin
               end;
               end;
             else
             else
             begin
             begin
-              FTokenText := FTokenText + Buffer[BufferPos];
+              FRawTokenText := FRawTokenText + Buffer[BufferPos];
               Inc(BufferPos);
               Inc(BufferPos);
             end;
             end;
           end;
           end;
@@ -220,7 +224,7 @@ begin
             EnterNewScannerContext(scUnknown)
             EnterNewScannerContext(scUnknown)
           else
           else
           begin
           begin
-            FTokenText := FTokenText + Buffer[BufferPos];
+            FRawTokenText := FRawTokenText + Buffer[BufferPos];
             Inc(BufferPos);
             Inc(BufferPos);
           end;
           end;
         scTag:
         scTag:
@@ -237,13 +241,13 @@ begin
                     FAttrNameRead := False;
                     FAttrNameRead := False;
                   end;
                   end;
                 end;
                 end;
-                FTokenText := FTokenText + Buffer[BufferPos];
+                FRawTokenText := FRawTokenText + Buffer[BufferPos];
                 Inc(BufferPos);
                 Inc(BufferPos);
               end;
               end;
             '=':
             '=':
               begin
               begin
                 FAttrNameRead := True;
                 FAttrNameRead := True;
-                FTokenText := FTokenText + Buffer[BufferPos];
+                FRawTokenText := FRawTokenText + Buffer[BufferPos];
                 Inc(BufferPos);
                 Inc(BufferPos);
               end;
               end;
             '>':
             '>':
@@ -254,99 +258,101 @@ begin
               end;
               end;
             else
             else
             begin
             begin
-              FTokenText := FTokenText + Buffer[BufferPos];
+              FRawTokenText := FRawTokenText + Buffer[BufferPos];
               Inc(BufferPos);
               Inc(BufferPos);
             end;
             end;
           end;
           end;
-      end;
+        end;    // case ScannerContext of
+    end;        // while not endOfBuffer
   end;
   end;
 end;
 end;
 
 
-procedure TSAXXMLReader.EnterNewScannerContext(NewContext: TXMLScannerContext);
-
-  function SplitTagString(const s: String; var Attr: TSAXAttributes): String;
-  var
-    i, j: Integer;
-    AttrName: String;
-    ValueDelimiter: Char;
-    DoIncJ: Boolean;
+function SplitTagString(const s: SAXString; var Attr: TSAXAttributes): SAXString;
+var
+  i, j: Integer;
+  AttrName: SAXString;
+  ValueDelimiter: WideChar;
+  DoIncJ: Boolean;
+begin
+  Attr := nil;
+  i := 0;
+  repeat
+    Inc(i)
+  until (i > Length(s)) or IsXMLWhitespace(s[i]);
+
+  if i > Length(s) then
+    Result := s
+  else
   begin
   begin
-    Attr := nil;
-    i := 0;
-    repeat
-      Inc(i)
-    until (i > Length(s)) or (s[i] in WhitespaceChars);
-
-    if i > Length(s) then
-      Result := LowerCase(s)
-    else
-    begin
-      Result := LowerCase(Copy(s, 1, i - 1));
-      Attr := TSAXAttributes.Create;
+    Result := Copy(s, 1, i - 1);
+    Attr := TSAXAttributes.Create;
+    Inc(i);
 
 
+    while (i <= Length(s)) and IsXMLWhitespace(s[i]) do
       Inc(i);
       Inc(i);
 
 
-      while (i <= Length(s)) and (s[i] in WhitespaceChars) do
-        Inc(i);
-
-      SetLength(AttrName, 0);
-      j := i;
+    SetLength(AttrName, 0);
+    j := i;
 
 
-      while j <= Length(s) do
-        if s[j] = '=' then
+    while j <= Length(s) do
+      if s[j] = '=' then
+      begin
+        AttrName := Copy(s, i, j - i);
+        Inc(j);
+        if (j < Length(s)) and ((s[j] = '''') or (s[j] = '"')) then
         begin
         begin
-          AttrName := LowerCase(Copy(s, i, j - i));
+          ValueDelimiter := s[j];
           Inc(j);
           Inc(j);
-          if (j < Length(s)) and ((s[j] = '''') or (s[j] = '"')) then
+        end else
+          ValueDelimiter := #0;
+        i := j;
+        DoIncJ := False;
+        while j <= Length(s) do
+          if ValueDelimiter = #0 then
+            if IsXMLWhitespace(s[j]) then
+              break
+            else
+              Inc(j)
+          else if s[j] = ValueDelimiter then
           begin
           begin
-            ValueDelimiter := s[j];
-            Inc(j);
+            DoIncJ := True;
+            break
           end else
           end else
-            ValueDelimiter := #0;
-          i := j;
-          DoIncJ := False;
-          while j <= Length(s) do
-            if ValueDelimiter = #0 then
-              if s[j] in WhitespaceChars then
-                break
-              else
-                Inc(j)
-            else if s[j] = ValueDelimiter then
-            begin
-              DoIncJ := True;
-              break
-            end else
-              Inc(j);
+            Inc(j);
 
 
+        if IsXMLName(AttrName) then
           Attr.AddAttribute('', AttrName, '', '', Copy(s, i, j - i));
           Attr.AddAttribute('', AttrName, '', '', Copy(s, i, j - i));
 
 
-          if DoIncJ then
-            Inc(j);
+        if DoIncJ then
+          Inc(j);
 
 
-          while (j <= Length(s)) and (s[j] in WhitespaceChars) do
-            Inc(j);
-          i := j;
-        end
-        else if s[j] in WhitespaceChars then
-        begin
-          Attr.AddAttribute('', Copy(s, i, j - i), '', '', '');
+        while (j <= Length(s)) and IsXMLWhitespace(s[j]) do
           Inc(j);
           Inc(j);
-          while (j <= Length(s)) and (s[j] in WhitespaceChars) do
-            Inc(j);
-          i := j;
-        end else
+        i := j;
+      end
+      else if IsXMLWhitespace(s[j]) then
+      begin
+        if IsXMLName(@s[i], j-i) then
+          Attr.AddAttribute('', Copy(s, i, j - i), '', '', '');
+        Inc(j);
+        while (j <= Length(s)) and IsXMLWhitespace(s[j]) do
           Inc(j);
           Inc(j);
-    end;
+        i := j;
+      end else
+        Inc(j);
   end;
   end;
+end;
 
 
+procedure TSAXXMLReader.EnterNewScannerContext(NewContext: TXMLScannerContext);
 var
 var
   Attr: TSAXAttributes;
   Attr: TSAXAttributes;
-  TagName: String;
+  TagName: SAXString;
   Ent: SAXChar;
   Ent: SAXChar;
 begin
 begin
+  FTokenText := FRawTokenText;  // this is where conversion takes place
   case ScannerContext of
   case ScannerContext of
     scWhitespace:
     scWhitespace:
-      DoIgnorableWhitespace(PSAXChar(TokenText), 1, Length(TokenText));
+      DoIgnorableWhitespace(PSAXChar(TokenText), 0, Length(TokenText));
     scText:
     scText:
       DoCharacters(PSAXChar(TokenText), 0, Length(TokenText));
       DoCharacters(PSAXChar(TokenText), 0, Length(TokenText));
     scEntityReference:
     scEntityReference:
@@ -397,7 +403,8 @@ begin
       end;
       end;
   end;
   end;
   FScannerContext := NewContext;
   FScannerContext := NewContext;
-  SetLength(FTokenText, 0);
+  FTokenText := '';
+  FRawTokenText := '';
   FCurStringValueDelimiter := #0;
   FCurStringValueDelimiter := #0;
   FAttrNameRead := False;
   FAttrNameRead := False;
 end;
 end;

+ 3 - 138
packages/fcl-xml/src/xmlread.pp

@@ -321,7 +321,6 @@ type
     FRecognizePE: Boolean;
     FRecognizePE: Boolean;
     FHavePERefs: Boolean;
     FHavePERefs: Boolean;
     FInsideDecl: Boolean;
     FInsideDecl: Boolean;
-    FDocNotValid: Boolean;
     FValue: TWideCharBuf;
     FValue: TWideCharBuf;
     FEntityValue: TWideCharBuf;
     FEntityValue: TWideCharBuf;
     FName: TWideCharBuf;
     FName: TWideCharBuf;
@@ -497,137 +496,6 @@ begin
     end;
     end;
 end;
 end;
 
 
-function Decode_UCS2(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
-var
-  cnt: Cardinal;
-begin
-  cnt := OutCnt;         // num of widechars
-  if cnt > InCnt div sizeof(WideChar) then
-    cnt := InCnt div sizeof(WideChar);
-  Move(InBuf^, OutBuf^, cnt * sizeof(WideChar));
-  Dec(InCnt, cnt*sizeof(WideChar));
-  Dec(OutCnt, cnt);
-  Result := cnt;
-end;
-
-function Decode_UCS2_Swapped(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
-var
-  I: Integer;
-  cnt: Cardinal;
-  InPtr: PChar;
-begin
-  cnt := OutCnt;         // num of widechars
-  if cnt > InCnt div sizeof(WideChar) then
-    cnt := InCnt div sizeof(WideChar);
-  InPtr := InBuf;
-  for I := 0 to cnt-1 do
-  begin
-    OutBuf[I] := WideChar((ord(InPtr^) shl 8) or ord(InPtr[1]));
-    Inc(InPtr, 2);
-  end;
-  Dec(InCnt, cnt*sizeof(WideChar));
-  Dec(OutCnt, cnt);
-  Result := cnt;
-end;
-
-function Decode_88591(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
-var
-  I: Integer;
-  cnt: Cardinal;
-begin
-  cnt := OutCnt;         // num of widechars
-  if cnt > InCnt then
-    cnt := InCnt;
-  for I := 0 to cnt-1 do
-    OutBuf[I] := WideChar(ord(InBuf[I]));
-  Dec(InCnt, cnt);
-  Dec(OutCnt, cnt);
-  Result := cnt;
-end;
-
-function Decode_UTF8(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
-const
-  MaxCode: array[1..4] of Cardinal = ($7F, $7FF, $FFFF, $1FFFFF);
-var
-  i, j, bc: Cardinal;
-  Value: Cardinal;
-begin
-  result := 0;
-  i := OutCnt;
-  while (i > 0) and (InCnt > 0) do
-  begin
-    bc := 1;
-    Value := ord(InBuf^);
-    if Value < $80 then
-      OutBuf^ := WideChar(Value)
-    else
-    begin
-      if Value < $C2 then
-      begin
-        Result := -1;
-        Break;
-      end;
-      Inc(bc);
-      if Value > $DF then
-      begin
-        Inc(bc);
-        if Value > $EF then
-        begin
-          Inc(bc);
-          if Value > $F7 then  // never encountered in the tests.
-          begin
-            Result := -1;
-            Break;
-          end;
-        end;
-      end;
-      if InCnt < bc then
-        Break;
-      j := 1;
-      while j < bc do
-      begin
-        if InBuf[j] in [#$80..#$BF] then
-          Value := (Value shl 6) or (Cardinal(InBuf[j]) and $3F)
-        else
-        begin
-          Result := -1;
-          Break;
-        end;
-        Inc(j);
-      end;
-      Value := Value and MaxCode[bc];
-      // RFC2279 check
-      if Value <= MaxCode[bc-1] then
-      begin
-        Result := -1;
-        Break;
-      end;
-      case Value of
-        0..$D7FF, $E000..$FFFF: OutBuf^ := WideChar(Value);
-        $10000..$10FFFF:
-        begin
-          if i < 2 then Break;
-          OutBuf^ := WideChar($D7C0 + (Value shr 10));
-          OutBuf[1] := WideChar($DC00 xor (Value and $3FF));
-          Inc(OutBuf); // once here
-          Dec(i);
-        end
-        else
-        begin
-          Result := -1;
-          Break;
-        end;
-      end;
-    end;
-    Inc(OutBuf);
-    Inc(InBuf, bc);
-    Dec(InCnt, bc);
-    Dec(i);
-  end;
-  if Result >= 0 then
-    Result := OutCnt-i;
-  OutCnt := i;
-end;
 
 
 function Is_8859_1(const AEncoding: string): Boolean;
 function Is_8859_1(const AEncoding: string): Boolean;
 begin
 begin
@@ -1003,7 +871,7 @@ begin
 // see rmt-e2e-61, it now fails but for a completely different reason.
 // see rmt-e2e-61, it now fails but for a completely different reason.
   FillChar(NewDecoder, sizeof(TDecoder), 0);
   FillChar(NewDecoder, sizeof(TDecoder), 0);
   if Is_8859_1(AEncoding) then
   if Is_8859_1(AEncoding) then
-    FDecoder.Decode := @Decode_88591
+    FDecoder.Decode := @Decode_8859_1
   else if FindDecoder(AEncoding, NewDecoder) then
   else if FindDecoder(AEncoding, NewDecoder) then
     FDecoder := NewDecoder
     FDecoder := NewDecoder
   else
   else
@@ -1212,7 +1080,6 @@ end;
 
 
 procedure TXMLReader.ValidationError(const Msg: string; const Args: array of const; LineOffs: Integer);
 procedure TXMLReader.ValidationError(const Msg: string; const Args: array of const; LineOffs: Integer);
 begin
 begin
-  FDocNotValid := True;
   if FValidate then
   if FValidate then
     DoError(esError, Format(Msg, Args), LineOffs);
     DoError(esError, Format(Msg, Args), LineOffs);
 end;
 end;
@@ -3099,7 +2966,6 @@ end;
 
 
 procedure TXMLReader.ParseEndTag;     // [42]
 procedure TXMLReader.ParseEndTag;     // [42]
 var
 var
-  ErrOffset: Integer;
   ElName: PHashItem;
   ElName: PHashItem;
 begin
 begin
   ElName := FValidator[FNesting].FElement.NSI.QName;
   ElName := FValidator[FNesting].FElement.NSI.QName;
@@ -3109,18 +2975,17 @@ begin
     FatalError('Unmatching element end tag (expected "</%s>")', [ElName^.Key], FName.Length);
     FatalError('Unmatching element end tag (expected "</%s>")', [ElName^.Key], FName.Length);
   if FSource.FBuf^ = '>' then    // this handles majority of cases
   if FSource.FBuf^ = '>' then    // this handles majority of cases
   begin
   begin
-    ErrOffset := FName.Length+1;
     FSource.NextChar;
     FSource.NextChar;
+    DoEndElement(FName.Length+1);
   end
   end
   else    // but if closing '>' is preceded by whitespace,
   else    // but if closing '>' is preceded by whitespace,
   begin   // skipping it is likely to lose position info.
   begin   // skipping it is likely to lose position info.
     StoreLocation(FTokenStart);
     StoreLocation(FTokenStart);
     Dec(FTokenStart.LinePos, FName.Length);
     Dec(FTokenStart.LinePos, FName.Length);
-    ErrOffset := -1;
     SkipS;
     SkipS;
     ExpectChar('>');
     ExpectChar('>');
+    DoEndElement(-1);
   end;
   end;
-  DoEndElement(ErrOffset);
 end;
 end;
 
 
 procedure TXMLReader.ParseAttribute(Elem: TDOMElement; ElDef: TDOMElementDef);
 procedure TXMLReader.ParseAttribute(Elem: TDOMElement; ElDef: TDOMElementDef);

+ 141 - 0
packages/fcl-xml/src/xmlutils.pp

@@ -160,6 +160,13 @@ procedure BufAppend(var ABuffer: TWideCharBuf; wc: WideChar);
 procedure BufAppendChunk(var ABuf: TWideCharBuf; pstart, pend: PWideChar);
 procedure BufAppendChunk(var ABuf: TWideCharBuf; pstart, pend: PWideChar);
 function BufEquals(const ABuf: TWideCharBuf; const Arg: WideString): Boolean;
 function BufEquals(const ABuf: TWideCharBuf; const Arg: WideString): Boolean;
 
 
+{ Built-in decoder functions for UTF-8, UTF-16 and ISO-8859-1 }
+
+function Decode_UCS2(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
+function Decode_UCS2_Swapped(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
+function Decode_UTF8(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
+function Decode_8859_1(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
+
 {$i names.inc}
 {$i names.inc}
 
 
 implementation
 implementation
@@ -905,6 +912,140 @@ begin
     CompareMem(ABuf.Buffer, Pointer(Arg), ABuf.Length*sizeof(WideChar));
     CompareMem(ABuf.Buffer, Pointer(Arg), ABuf.Length*sizeof(WideChar));
 end;
 end;
 
 
+{ standard decoders }
+
+function Decode_UCS2(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
+var
+  cnt: Cardinal;
+begin
+  cnt := OutCnt;         // num of widechars
+  if cnt > InCnt div sizeof(WideChar) then
+    cnt := InCnt div sizeof(WideChar);
+  Move(InBuf^, OutBuf^, cnt * sizeof(WideChar));
+  Dec(InCnt, cnt*sizeof(WideChar));
+  Dec(OutCnt, cnt);
+  Result := cnt;
+end;
+
+function Decode_UCS2_Swapped(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
+var
+  I: Integer;
+  cnt: Cardinal;
+  InPtr: PChar;
+begin
+  cnt := OutCnt;         // num of widechars
+  if cnt > InCnt div sizeof(WideChar) then
+    cnt := InCnt div sizeof(WideChar);
+  InPtr := InBuf;
+  for I := 0 to cnt-1 do
+  begin
+    OutBuf[I] := WideChar((ord(InPtr^) shl 8) or ord(InPtr[1]));
+    Inc(InPtr, 2);
+  end;
+  Dec(InCnt, cnt*sizeof(WideChar));
+  Dec(OutCnt, cnt);
+  Result := cnt;
+end;
+
+function Decode_8859_1(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
+var
+  I: Integer;
+  cnt: Cardinal;
+begin
+  cnt := OutCnt;         // num of widechars
+  if cnt > InCnt then
+    cnt := InCnt;
+  for I := 0 to cnt-1 do
+    OutBuf[I] := WideChar(ord(InBuf[I]));
+  Dec(InCnt, cnt);
+  Dec(OutCnt, cnt);
+  Result := cnt;
+end;
+
+function Decode_UTF8(Context: Pointer; InBuf: PChar; var InCnt: Cardinal; OutBuf: PWideChar; var OutCnt: Cardinal): Integer; stdcall;
+const
+  MaxCode: array[1..4] of Cardinal = ($7F, $7FF, $FFFF, $1FFFFF);
+var
+  i, j, bc: Cardinal;
+  Value: Cardinal;
+begin
+  result := 0;
+  i := OutCnt;
+  while (i > 0) and (InCnt > 0) do
+  begin
+    bc := 1;
+    Value := ord(InBuf^);
+    if Value < $80 then
+      OutBuf^ := WideChar(Value)
+    else
+    begin
+      if Value < $C2 then
+      begin
+        Result := -1;
+        Break;
+      end;
+      Inc(bc);
+      if Value > $DF then
+      begin
+        Inc(bc);
+        if Value > $EF then
+        begin
+          Inc(bc);
+          if Value > $F7 then  // never encountered in the tests.
+          begin
+            Result := -1;
+            Break;
+          end;
+        end;
+      end;
+      if InCnt < bc then
+        Break;
+      j := 1;
+      while j < bc do
+      begin
+        if InBuf[j] in [#$80..#$BF] then
+          Value := (Value shl 6) or (Cardinal(InBuf[j]) and $3F)
+        else
+        begin
+          Result := -1;
+          Break;
+        end;
+        Inc(j);
+      end;
+      Value := Value and MaxCode[bc];
+      // RFC2279 check
+      if Value <= MaxCode[bc-1] then
+      begin
+        Result := -1;
+        Break;
+      end;
+      case Value of
+        0..$D7FF, $E000..$FFFF: OutBuf^ := WideChar(Value);
+        $10000..$10FFFF:
+        begin
+          if i < 2 then Break;
+          OutBuf^ := WideChar($D7C0 + (Value shr 10));
+          OutBuf[1] := WideChar($DC00 xor (Value and $3FF));
+          Inc(OutBuf); // once here
+          Dec(i);
+        end
+        else
+        begin
+          Result := -1;
+          Break;
+        end;
+      end;
+    end;
+    Inc(OutBuf);
+    Inc(InBuf, bc);
+    Dec(InCnt, bc);
+    Dec(i);
+  end;
+  if Result >= 0 then
+    Result := OutCnt-i;
+  OutCnt := i;
+end;
+
 
 
 initialization
 initialization
 
 

+ 10 - 10
packages/graph/src/go32v2/vesa.inc

@@ -515,7 +515,7 @@ end;
           {$endif logging}
           {$endif logging}
           For l := 0 to (Bankrest div 4)-1 Do
           For l := 0 to (Bankrest div 4)-1 Do
             begin
             begin
-              pixels := MemL[WinWriteSeg:word(offs)+l*4];
+              pixels := MemL[WinReadSeg:word(offs)+l*4];
               WordArray(Data)[index+l*4] := pixels and $ff;
               WordArray(Data)[index+l*4] := pixels and $ff;
               pixels := pixels shr 8;
               pixels := pixels shr 8;
               WordArray(Data)[index+l*4+1] := pixels and $ff;
               WordArray(Data)[index+l*4+1] := pixels and $ff;
@@ -798,7 +798,7 @@ end;
                          setreadbank(offs shr 16);
                          setreadbank(offs shr 16);
                          setwritebank(offs shr 16);
                          setwritebank(offs shr 16);
                          Mem[WinWriteSeg:word(offs)] :=
                          Mem[WinWriteSeg:word(offs)] :=
-                           Mem[WinReadSeg:word(offs)] And byte(currentColor);
+                           Mem[WinReadSeg:word(offs)] Or byte(currentColor);
                          inc(offs);
                          inc(offs);
                        end;
                        end;
                      HLength := 0
                      HLength := 0
@@ -925,10 +925,10 @@ end;
                  {$ifdef logging2}
                  {$ifdef logging2}
                  LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
                  LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
                  {$endif logging}
                  {$endif logging}
-                 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
+                 If (VLength-1)*bytesperline <= ($ffff-(Offs and $ffff)) Then
                    bankrest := VLength
                    bankrest := VLength
                  else {the rest won't fit anymore in the current window }
                  else {the rest won't fit anymore in the current window }
-                   bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
+                   bankrest := (($ffff - (Offs and $ffff)) div bytesperline)+1;
                  {$ifdef logging2}
                  {$ifdef logging2}
                  LogLn('Rest to be drawn in this window: '+strf(bankrest));
                  LogLn('Rest to be drawn in this window: '+strf(bankrest));
                  {$endif logging}
                  {$endif logging}
@@ -953,10 +953,10 @@ end;
                  {$ifdef logging2}
                  {$ifdef logging2}
                  LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
                  LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
                  {$endif logging}
                  {$endif logging}
-                 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
+                 If (VLength-1)*bytesperline <= ($ffff-(Offs and $ffff)) Then
                    bankrest := VLength
                    bankrest := VLength
                  else {the rest won't fit anymore in the current window }
                  else {the rest won't fit anymore in the current window }
-                   bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
+                   bankrest := (($ffff - (Offs and $ffff)) div bytesperline)+1;
                  {$ifdef logging2}
                  {$ifdef logging2}
                  LogLn('Rest to be drawn in this window: '+strf(bankrest));
                  LogLn('Rest to be drawn in this window: '+strf(bankrest));
                  {$endif logging}
                  {$endif logging}
@@ -981,10 +981,10 @@ end;
                  {$ifdef logging2}
                  {$ifdef logging2}
                  LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
                  LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
                  {$endif logging}
                  {$endif logging}
-                 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
+                 If (VLength-1)*bytesperline <= ($ffff-(Offs and $ffff)) Then
                    bankrest := VLength
                    bankrest := VLength
                  else {the rest won't fit anymore in the current window }
                  else {the rest won't fit anymore in the current window }
-                   bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
+                   bankrest := (($ffff - (Offs and $ffff)) div bytesperline)+1;
                  {$ifdef logging2}
                  {$ifdef logging2}
                  LogLn('Rest to be drawn in this window: '+strf(bankrest));
                  LogLn('Rest to be drawn in this window: '+strf(bankrest));
                  {$endif logging}
                  {$endif logging}
@@ -1010,10 +1010,10 @@ end;
                  {$ifdef logging2}
                  {$ifdef logging2}
                  LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
                  LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8));
                  {$endif logging}
                  {$endif logging}
-                 If (VLength-1)*bytesperline <= ($10000-(Offs and $ffff)) Then
+                 If (VLength-1)*bytesperline <= ($ffff-(Offs and $ffff)) Then
                    bankrest := VLength
                    bankrest := VLength
                  else {the rest won't fit anymore in the current window }
                  else {the rest won't fit anymore in the current window }
-                   bankrest := (($10000 - (Offs and $ffff)) div bytesperline)+1;
+                   bankrest := (($ffff - (Offs and $ffff)) div bytesperline)+1;
                  {$ifdef logging2}
                  {$ifdef logging2}
                  LogLn('Rest to be drawn in this window: '+strf(bankrest));
                  LogLn('Rest to be drawn in this window: '+strf(bankrest));
                  {$endif logging}
                  {$endif logging}

+ 2 - 1
rtl/darwin/Makefile

@@ -1,5 +1,5 @@
 #
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/08/06]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/08/03]
 #
 #
 default: all
 default: all
 MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
 MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
@@ -2505,6 +2505,7 @@ $(SYSTEMUNIT)$(PPUEXT) : $(BSDINC)/$(SYSTEMUNIT).pp $(SYSDEPS)
 clocale$(PPUEXT): initc$(PPUEXT) sysutils$(PPUEXT) unixtype$(PPUEXT)
 clocale$(PPUEXT): initc$(PPUEXT) sysutils$(PPUEXT) unixtype$(PPUEXT)
 fpintres$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT)
 fpintres$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT)
 fpextres$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT) baseunix$(PPUEXT)
 fpextres$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT) baseunix$(PPUEXT)
+iso7185$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT)
 objpas$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT) $(OBJPASDIR)/objpas.pp $(INC)/except.inc $(SYSTEMUNIT)$(PPUEXT)
 objpas$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT) $(OBJPASDIR)/objpas.pp $(INC)/except.inc $(SYSTEMUNIT)$(PPUEXT)
 	$(COMPILER) -I$(OBJPASDIR) $(OBJPASDIR)/objpas.pp
 	$(COMPILER) -I$(OBJPASDIR) $(OBJPASDIR)/objpas.pp
 dateutils$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT) objpas$(PPUEXT) sysutils$(PPUEXT) math$(PPUEXT) types$(PPUEXT) sysconst$(PPUEXT) $(OBJPASDIR)/dateutils.pp baseunix$(PPUEXT) $(SYSTEMUNIT)$(PPUEXT)
 dateutils$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT) objpas$(PPUEXT) sysutils$(PPUEXT) math$(PPUEXT) types$(PPUEXT) sysconst$(PPUEXT) $(OBJPASDIR)/dateutils.pp baseunix$(PPUEXT) $(SYSTEMUNIT)$(PPUEXT)

+ 2 - 0
rtl/darwin/Makefile.fpc

@@ -125,6 +125,8 @@ fpintres$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT)
 
 
 fpextres$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT) baseunix$(PPUEXT)
 fpextres$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT) baseunix$(PPUEXT)
 
 
+iso7185$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT)
+
 objpas$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT) $(OBJPASDIR)/objpas.pp $(INC)/except.inc $(SYSTEMUNIT)$(PPUEXT)
 objpas$(PPUEXT): $(SYSTEMUNIT)$(PPUEXT) $(OBJPASDIR)/objpas.pp $(INC)/except.inc $(SYSTEMUNIT)$(PPUEXT)
         $(COMPILER) -I$(OBJPASDIR) $(OBJPASDIR)/objpas.pp
         $(COMPILER) -I$(OBJPASDIR) $(OBJPASDIR)/objpas.pp
 
 

+ 46 - 0
rtl/linux/linux.pp

@@ -101,6 +101,13 @@ const
    if (oldval CMP CMPARG)
    if (oldval CMP CMPARG)
      wake UADDR2; }
      wake UADDR2; }
 
 
+function futex(uaddr:Pcint;op,val:cint;timeout:Ptimespec;addr2:Pcint;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+function futex(var uaddr;op,val:cint;timeout:Ptimespec;var addr2;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+function futex(var uaddr;op,val:cint;var timeout:Ttimespec;var addr2;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+function futex(uaddr:Pcint;op,val:cint;timeout:Ptimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+function futex(var uaddr;op,val:cint;timeout:Ptimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+function futex(var uaddr;op,val:cint;var timeout:Ttimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+
 {$ifndef FPC_USE_LIBC}
 {$ifndef FPC_USE_LIBC}
 function futex_op(op, oparg, cmp, cmparg: cint): cint; {$ifdef SYSTEMINLINE}inline;{$endif}
 function futex_op(op, oparg, cmp, cmparg: cint): cint; {$ifdef SYSTEMINLINE}inline;{$endif}
 {$endif}
 {$endif}
@@ -480,6 +487,45 @@ begin
   fdatasync:=do_SysCall(syscall_nr_fdatasync, fd);
   fdatasync:=do_SysCall(syscall_nr_fdatasync, fd);
 end;
 end;
 
 
+function futex(uaddr:Pcint;op,val:cint;timeout:Ptimespec;addr2:Pcint;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+
+begin
+  futex:=do_syscall(syscall_nr_futex,Tsysparam(uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(timeout),
+                    Tsysparam(addr2),Tsysparam(val3));
+end;
+
+function futex(var uaddr;op,val:cint;timeout:Ptimespec;var addr2;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+
+begin
+  futex:=do_syscall(syscall_nr_futex,Tsysparam(@uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(timeout),
+                    Tsysparam(@addr2),Tsysparam(val3));
+end;
+
+function futex(var uaddr;op,val:cint;var timeout:Ttimespec;var addr2;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+
+begin
+  futex:=do_syscall(syscall_nr_futex,Tsysparam(@uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(@timeout),
+                    Tsysparam(@addr2),Tsysparam(val3));
+end;
+
+function futex(uaddr:Pcint;op,val:cint;timeout:Ptimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+
+begin
+  futex:=do_syscall(syscall_nr_futex,Tsysparam(uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(timeout));
+end;
+
+function futex(var uaddr;op,val:cint;timeout:Ptimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+
+begin
+  futex:=do_syscall(syscall_nr_futex,Tsysparam(@uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(timeout));
+end;
+
+function futex(var uaddr;op,val:cint;var timeout:Ttimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
+
+begin
+  futex:=do_syscall(syscall_nr_futex,Tsysparam(@uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(@timeout));
+end;
+
 {$endif} // non-libc
 {$endif} // non-libc
 
 
 { FUTEX_OP is a macro, doesn't exist in libC as function}
 { FUTEX_OP is a macro, doesn't exist in libC as function}

+ 42 - 0
tests/test/tintfcdecl1.pp

@@ -0,0 +1,42 @@
+program tinfcdecl1;
+
+{$mode objfpc}{$H+}
+
+type
+  IcdeclIntf = interface
+  ['{3C409C8B-3A15-44B2-B22D-6BAA2071CAAD}']
+    function DoSomething : longint; cdecl;
+  end;
+
+  { TcdeclClass }
+
+  TcdeclClass = class(TInterfacedObject,IcdeclIntf)
+  private
+    FCounter: integer;
+  public
+    function DoSomething : longint; cdecl;
+  end;
+
+{ TcdeclClass }
+
+function TcdeclClass.DoSomething: longint; cdecl;
+begin
+  inc(FCounter);
+  result := FCounter;
+end;
+
+var
+  js: TcdeclClass;
+  ji: IcdeclIntf;
+  i: longint;
+begin
+  js := TcdeclClass.Create;
+
+  i := js.DoSomething;
+
+  ji := IcdeclIntf(js);
+  i := ji.DoSomething;
+
+  if i <> 2 then halt(1);
+end.
+

+ 42 - 0
tests/test/tintfcdecl2.pp

@@ -0,0 +1,42 @@
+program tintfcdecl2;
+
+{$mode objfpc}{$H+}
+
+type
+  IcdeclIntf = interface
+  ['{3C409C8B-3A15-44B2-B22D-6BAA2071CAAD}']
+    function DoSomething : longint; cdecl;
+  end;
+
+  { TcdeclClass }
+
+  TcdeclClass = class(TInterfacedObject,IcdeclIntf)
+  private
+    FCounter: integer;
+  public
+    function DoSomething : longint; cdecl; virtual;
+  end;
+
+{ TcdeclClass }
+
+function TcdeclClass.DoSomething: longint; cdecl;
+begin
+  inc(FCounter);
+  result := FCounter;
+end;
+
+var
+  js: TcdeclClass;
+  ji: IcdeclIntf;
+  i: longint;
+begin
+  js := TcdeclClass.Create;
+
+  i := js.DoSomething;
+
+  ji := IcdeclIntf(js);
+  i := ji.DoSomething;
+
+  if i <> 2 then halt(1);
+end.
+