mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 15:31:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			438 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			438 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| {
 | |
|     $Id$
 | |
|     This file is part of the Free Pascal run time library.
 | |
|     Copyright (c) 1998,99 by the Free Pascal development team
 | |
| 
 | |
|     This unit makes Free Pascal as much as possible Delphi compatible
 | |
| 
 | |
|     See the file COPYING.FPC, included in this distribution,
 | |
|     for details about the copyright.
 | |
| 
 | |
|     This program is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | |
| 
 | |
|  **********************************************************************}
 | |
| 
 | |
| {****************************************************************************
 | |
|                   Internal Routines called from the Compiler
 | |
| ****************************************************************************}
 | |
| 
 | |
|     { the reverse order of the parameters make code generation easier }
 | |
|     function int_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS'];
 | |
|       begin
 | |
|          int_do_is:=aobject.inheritsfrom(aclass);
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     { the reverse order of the parameters make code generation easier }
 | |
|     procedure int_do_as(aclass : tclass;aobject : tobject);[public,alias: 'FPC_DO_AS'];
 | |
|       begin
 | |
|          if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
 | |
|            handleerror(219);
 | |
|       end;
 | |
| 
 | |
| 
 | |
| {****************************************************************************
 | |
|                                TOBJECT
 | |
| ****************************************************************************}
 | |
| 
 | |
|       constructor TObject.Create;
 | |
| 
 | |
|         begin
 | |
|         end;
 | |
| 
 | |
|       destructor TObject.Destroy;
 | |
| 
 | |
|         begin
 | |
|         end;
 | |
| 
 | |
|       procedure TObject.Free;
 | |
| 
 | |
|         begin
 | |
|            // the call via self avoids a warning
 | |
|            if self<>nil then
 | |
|              self.destroy;
 | |
|         end;
 | |
| 
 | |
|       class function TObject.InstanceSize : LongInt;
 | |
| 
 | |
|         type
 | |
|            plongint = ^longint;
 | |
| 
 | |
|         begin
 | |
|            { type of self is class of tobject => it points to the vmt }
 | |
|            { the size is saved at offset 0                            }
 | |
|            InstanceSize:=plongint(self)^;
 | |
|         end;
 | |
| 
 | |
|       class function TObject.InitInstance(instance : pointer) : tobject;
 | |
| 
 | |
|         begin
 | |
|            fillchar(instance^,self.instancesize,0);
 | |
|            { insert VMT pointer into the new created memory area }
 | |
|            { (in class methods self contains the VMT!)           }
 | |
|            ppointer(instance)^:=pointer(self);
 | |
|            InitInstance:=TObject(Instance);
 | |
|         end;
 | |
| 
 | |
|       class function TObject.ClassParent : tclass;
 | |
| 
 | |
|         begin
 | |
|            { type of self is class of tobject => it points to the vmt }
 | |
|            { the parent vmt is saved at offset vmtParent              }
 | |
|            classparent:=pclass(pointer(self)+vmtParent)^;
 | |
|         end;
 | |
| 
 | |
|       class function TObject.NewInstance : tobject;
 | |
| 
 | |
|         var
 | |
|            p : pointer;
 | |
| 
 | |
|         begin
 | |
|            getmem(p,instancesize);
 | |
|            InitInstance(p);
 | |
|            NewInstance:=TObject(p);
 | |
|         end;
 | |
| 
 | |
|       procedure TObject.FreeInstance;
 | |
| 
 | |
|         var
 | |
|            p : Pointer;
 | |
| 
 | |
|         begin
 | |
|            CleanupInstance;
 | |
| 
 | |
|            { self is a register, so we can't pass it call by reference }
 | |
|            p:=Pointer(Self);
 | |
|            FreeMem(p,InstanceSize);
 | |
|         end;
 | |
| 
 | |
|       function TObject.ClassType : TClass;
 | |
| 
 | |
|         begin
 | |
|            ClassType:=TClass(Pointer(Self)^)
 | |
|         end;
 | |
| 
 | |
|       type
 | |
|          tmethodnamerec = packed record
 | |
|             name : pshortstring;
 | |
|             addr : pointer;
 | |
|          end;
 | |
| 
 | |
|          tmethodnametable = packed record
 | |
|            count : dword;
 | |
|            entries : packed array[0..0] of tmethodnamerec;
 | |
|          end;
 | |
| 
 | |
|          pmethodnametable =  ^tmethodnametable;
 | |
| 
 | |
|       class function TObject.MethodAddress(const name : shortstring) : pointer;
 | |
| 
 | |
|         var
 | |
|            methodtable : pmethodnametable;
 | |
|            i : dword;
 | |
|            c : tclass;
 | |
| 
 | |
|         begin
 | |
|            c:=self;
 | |
|            while assigned(c) do
 | |
|              begin
 | |
|                 methodtable:=pmethodnametable((Pointer(c)+vmtMethodTable)^);
 | |
|                 if assigned(methodtable) then
 | |
|                   begin
 | |
|                      for i:=0 to methodtable^.count-1 do
 | |
|                        if methodtable^.entries[i].name^=name then
 | |
|                          begin
 | |
|                             MethodAddress:=methodtable^.entries[i].addr;
 | |
|                             exit;
 | |
|                          end;
 | |
|                   end;
 | |
|                 c:=c.ClassParent;
 | |
|              end;                                                                                                                                                                                                                                              
 | |
|            MethodAddress:=nil;
 | |
|         end;
 | |
| 
 | |
|       class function TObject.MethodName(address : pointer) : shortstring;
 | |
| 
 | |
|         var
 | |
|            methodtable : pmethodnametable;
 | |
|            i : dword;
 | |
|            c : tclass;
 | |
| 
 | |
|         begin
 | |
|            c:=self;
 | |
|            while assigned(c) do
 | |
|              begin
 | |
|                 methodtable:=pmethodnametable((Pointer(c)+vmtMethodTable)^);
 | |
|                 if assigned(methodtable) then
 | |
|                   begin
 | |
|                      for i:=0 to methodtable^.count-1 do
 | |
|                        if methodtable^.entries[i].addr=address then
 | |
|                          begin
 | |
|                             MethodName:=methodtable^.entries[i].name^;
 | |
|                             exit;
 | |
|                          end;
 | |
|                   end;
 | |
|                 c:=c.ClassParent;
 | |
|              end;
 | |
|            MethodName:='';
 | |
|         end;
 | |
| 
 | |
|       function TObject.FieldAddress(const name : shortstring) : pointer;
 | |
| 
 | |
|         begin
 | |
|            fieldaddress:=nil;
 | |
|         end;
 | |
| 
 | |
|       function TObject.SafeCallException(exceptobject : tobject;
 | |
|         exceptaddr : pointer) : longint;
 | |
| 
 | |
|         begin
 | |
|            safecallexception:=0;
 | |
|         end;
 | |
| 
 | |
|       class function TObject.ClassInfo : pointer;
 | |
| 
 | |
|         begin
 | |
|            ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
 | |
|         end;
 | |
| 
 | |
|       class function TObject.ClassName : ShortString;
 | |
| 
 | |
|         begin
 | |
|            ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
 | |
|         end;
 | |
| 
 | |
|       class function TObject.ClassNameIs(const name : string) : boolean;
 | |
| 
 | |
|         begin
 | |
|            ClassNameIs:=ClassName=name;
 | |
|         end;
 | |
| 
 | |
|       class function TObject.InheritsFrom(aclass : TClass) : Boolean;
 | |
| 
 | |
|         var
 | |
|            c : tclass;
 | |
| 
 | |
|         begin
 | |
|            c:=self;
 | |
|            while assigned(c) do
 | |
|              begin
 | |
|                 if c=aclass then
 | |
|                   begin
 | |
|                      InheritsFrom:=true;
 | |
|                      exit;
 | |
|                   end;
 | |
|                 c:=c.ClassParent;
 | |
|              end;
 | |
|            InheritsFrom:=false;
 | |
|         end;
 | |
| 
 | |
|       class function TObject.stringmessagetable : pstringmessagetable;
 | |
| 
 | |
|         type
 | |
|            pdword = ^dword;
 | |
| 
 | |
|         begin
 | |
|            stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
 | |
|         end;
 | |
| 
 | |
|       type
 | |
|          tmessagehandler = procedure(var msg) of object;
 | |
|          tmessagehandlerrec = packed record
 | |
|             proc : pointer;
 | |
|             obj : pointer;
 | |
|          end;
 | |
| 
 | |
| 
 | |
|       procedure TObject.Dispatch(var message);
 | |
| 
 | |
|         type
 | |
|            tmsgtable = record
 | |
|               index : dword;
 | |
|               method : pointer;
 | |
|            end;
 | |
| 
 | |
|            pmsgtable = ^tmsgtable;
 | |
| 
 | |
|            pdword = ^dword;
 | |
| 
 | |
|         var
 | |
|            index : dword;
 | |
|            count,i : longint;
 | |
|            msgtable : pmsgtable;
 | |
|            p : pointer;
 | |
|            vmt : tclass;
 | |
|            msghandler : tmessagehandler;
 | |
| 
 | |
|         begin
 | |
|            index:=dword(message);
 | |
|            vmt:=ClassType;
 | |
|            while assigned(vmt) do
 | |
|              begin
 | |
|                 // See if we have messages at all in this class.
 | |
|                 p:=pointer(vmt)+vmtDynamicTable;
 | |
|                 If Assigned(p) and (Pdword(p)^<>0) then
 | |
|                   begin
 | |
|                   msgtable:=pmsgtable(pdword(P)^+4);
 | |
|                   count:=pdword(pdword(P)^)^;
 | |
|                   end
 | |
|                 else
 | |
|                   Count:=0;
 | |
|                 { later, we can implement a binary search here }
 | |
|                 for i:=0 to count-1 do
 | |
|                   begin
 | |
|                      if index=msgtable[i].index then
 | |
|                        begin
 | |
|                           p:=msgtable[i].method;
 | |
|                           tmessagehandlerrec(msghandler).proc:=p;
 | |
|                           tmessagehandlerrec(msghandler).obj:=self;
 | |
|                           msghandler(message);
 | |
|                           { we don't need any longer the assembler
 | |
|                             solution                              
 | |
|                           asm
 | |
|                              pushl message
 | |
|                              pushl %esi
 | |
|                              movl p,%edi
 | |
|                              call *%edi
 | |
|                           end;
 | |
|                           }
 | |
|                           exit;
 | |
|                        end;
 | |
|                   end;
 | |
|                 vmt:=vmt.ClassParent;
 | |
|              end;
 | |
|            DefaultHandler(message);
 | |
|         end;
 | |
| 
 | |
|       procedure TObject.DispatchStr(var message);
 | |
| 
 | |
|         type
 | |
|            pdword = ^dword;
 | |
| 
 | |
|         var
 | |
|            name : shortstring;
 | |
|            count,i : longint;
 | |
|            msgstrtable : pmsgstrtable;
 | |
|            p : pointer;
 | |
|            vmt : tclass;
 | |
|            msghandler : tmessagehandler;
 | |
| 
 | |
|         begin
 | |
|            name:=pshortstring(@message)^;
 | |
|            vmt:=ClassType;
 | |
|            while assigned(vmt) do
 | |
|              begin
 | |
|                 p:=(pointer(vmt)+vmtMsgStrPtr);
 | |
|                 If (P<>Nil) and (PDWord(P)^<>0) then
 | |
|                   begin
 | |
|                   count:=pdword(pdword(p)^)^;
 | |
|                   msgstrtable:=pmsgstrtable(pdword(P)^+4);
 | |
|                   end
 | |
|                 else
 | |
|                   Count:=0;
 | |
|                 { later, we can implement a binary search here }
 | |
|                 for i:=0 to count-1 do
 | |
|                   begin
 | |
|                      if name=msgstrtable[i].name^ then
 | |
|                        begin
 | |
|                           p:=msgstrtable[i].method;
 | |
|                           tmessagehandlerrec(msghandler).proc:=p;
 | |
|                           tmessagehandlerrec(msghandler).obj:=self;
 | |
|                           msghandler(message);
 | |
|                           { we don't need any longer the assembler
 | |
|                             solution                              
 | |
|                           asm
 | |
|                              pushl message
 | |
|                              pushl %esi
 | |
|                              movl p,%edi
 | |
|                              call *%edi
 | |
|                           end;
 | |
|                           }
 | |
|                           exit;
 | |
|                        end;
 | |
|                   end;
 | |
|                 vmt:=vmt.ClassParent;
 | |
|              end;
 | |
|            DefaultHandlerStr(message);
 | |
|         end;
 | |
| 
 | |
|       procedure TObject.DefaultHandler(var message);
 | |
| 
 | |
|         begin
 | |
|         end;
 | |
| 
 | |
|       procedure TObject.DefaultHandlerStr(var message);
 | |
| 
 | |
|         begin
 | |
|         end;
 | |
| 
 | |
|       procedure TObject.CleanupInstance;
 | |
| 
 | |
|         var
 | |
|            vmt : tclass;
 | |
| 
 | |
|         begin
 | |
|            vmt:=ClassType;
 | |
|            while vmt<>nil do
 | |
|              begin
 | |
|                 if Assigned(Pointer((Pointer(vmt)+vmtInitTable)^)) then
 | |
|                   Finalize(Pointer(Self),Pointer((Pointer(vmt)+vmtInitTable)^));
 | |
|                 vmt:=vmt.ClassParent;
 | |
|              end;
 | |
|         end;
 | |
| 
 | |
|       procedure TObject.AfterConstruction;
 | |
| 
 | |
|         begin
 | |
|         end;
 | |
| 
 | |
|       procedure TObject.BeforeDestruction;
 | |
| 
 | |
|         begin
 | |
|         end;
 | |
| 
 | |
| {****************************************************************************
 | |
|                              Exception Support
 | |
| ****************************************************************************}
 | |
| 
 | |
| {$i except.inc}
 | |
| 
 | |
| {****************************************************************************
 | |
|                                 Initialize
 | |
| ****************************************************************************}
 | |
| 
 | |
| {
 | |
|   $Log$
 | |
|   Revision 1.11  1999-09-15 20:28:35  florian
 | |
|     * fixed methodname/address: the loops must go from 0 to ...^.count-1
 | |
| 
 | |
|   Revision 1.10  1999/09/12 14:53:26  florian
 | |
|     + tobject.methodaddress und tobject.methodname durchsucht nun auch
 | |
|       die Elternklassen
 | |
| 
 | |
|   Revision 1.9  1999/09/12 08:01:00  florian
 | |
|     + implementation of TObject.MethodName and TObject.MethodAddress (not
 | |
|       in the compiler yet)
 | |
| 
 | |
|   Revision 1.8  1999/09/08 16:14:41  peter
 | |
|     * pointer fixes
 | |
| 
 | |
|   Revision 1.7  1999/07/11 14:10:48  michael
 | |
|   + Adaptes Dispatch(STr) to cope with empty/non-existent message tables
 | |
| 
 | |
|   Revision 1.6  1999/07/11 14:05:50  michael
 | |
|   + Added
 | |
| 
 | |
|   Revision 1.5  1999/07/05 20:04:24  peter
 | |
|     * removed temp defines
 | |
| 
 | |
|   Revision 1.4  1999/05/19 13:20:09  peter
 | |
|     * fixed dispatchstr
 | |
| 
 | |
|   Revision 1.3  1999/05/17 21:52:37  florian
 | |
|     * most of the Object Pascal stuff moved to the system unit
 | |
| 
 | |
| }
 | 
