home *** CD-ROM | disk | FTP | other *** search
- {
- The execute part of the script engine
- }
- unit ifps3;
- {$I ifps3_def.inc}
- {
-
- Innerfuse Pascal Script III
- Copyright (C) 2000-2002 by Carlo Kok (ck@carlo-kok.com)
-
- }
- interface
- uses
- SysUtils, ifps3utl, ifps3common;
-
- type
- TIFPSExec = class;
- { TIFError contains all possible errors }
- TIFError = (ErNoError, erCannotImport, erInvalidType, ErInternalError,
- erInvalidHeader, erInvalidOpcode, erInvalidOpcodeParameter, erNoMainProc,
- erOutOfGlobalVarsRange, erOutOfProcRange, ErOutOfRange, erOutOfStackRange,
- ErTypeMismatch, erUnexpectedEof, erVersionError, ErDivideByZero, ErMathError,
- erCouldNotCallProc, erOutofRecordRange, erOutOfMemory, erException,
- erNullPointerException, erNullVariantError, erCustomError);
- { The current status of the script }
- TIFStatus = (isNotLoaded, isLoaded, isRunning, isPaused);
- {Pointer to array of bytes}
- PByteArray = ^TByteArray;
- {Array of bytes}
- TByteArray = array[0..1023] of Byte;
- {Pointer to array of words}
- PDWordArray = ^TDWordArray;
- {Array of dwords}
- TDWordArray = array[0..1023] of Cardinal;
- { Pointer to @link(TIFTypeRec)}
- PIFTypeRec = ^TIFTypeRec;
- {TIFTypeRec is used to store all types inside the script}
- TIFTypeRec = record
- {Ext is used in a typecopy or array to store more information}
- Ext: Pointer;
- BaseType: TIFPSBaseType;
- ExportName: string;
- ExportNameHash: Longint;
- end;
- {TIFArrayType is a pointer to an other type}
- TIFArrayType = PIFTypeRec;
- {PIFRecordType is a pointer to record information}
- PIFRecordType = ^TIFRecordType;
- {TIFRecordType is used to store information about records}
- TIFRecordType = record
- Data: string;
- end;
- {@link(TProcRec)
- PProcRec is pointer to a TProcRec record}
- PProcRec = ^TProcRec;
- {@link(TIFProcRec)
- PIFProcRec is a pointer to a TIProcRec record}
- PIFProcRec = ^TIFProcRec;
- {
- @link(TIFPSExec)
- @link(PIFProcRec)
- @link(TIfList)
- TIFProc is is the procedure definition of all external functions
- }
- TIFProc = function(Caller: TIFPSExec; p: PIFProcRec; Global, Stack: TIfList): Boolean;
- {
- @link(PProcRec)
- FreeProc is called when a PProcRec is freed}
- TIFFreeProc = procedure (Caller: TIFPSExec; p: PProcRec);
- {TIFProcRec contains a currently used internal or external function}
- TIFProcRec = record
- {True means the procedure is external}
- ExternalProc: Boolean;
- {The exportname/decl used to identify the procedure}
- ExportName, ExportDecl: string;
- {ExportNameHash is used to quickly find an ExportName}
- ExportNameHash: Longint;
- case Boolean of
- False: (Data: PByteArray; Length: Cardinal);
- True: (ProcPtr: TIFProc; Name: ShortString; Ext1, Ext2: Pointer);
- // ExportDecl will contain Params in case of importing with Flags := 3;
- end;
- {TProcrec is used to store an external function that could be used by the script executer}
- TProcRec = record
- Name: ShortString;
- Hash: Longint;
- ProcPtr: TIFProc;
- FreeProc: TIFFreeProc;
- Ext1, Ext2: Pointer;
- end;
- {@link(TBTReturnAddress)
- PBTReturnAddress is a pointer to an TBTReturnAddress record}
- PBTReturnAddress = ^TBTReturnAddress;
- {TBTReturnAddress is a record used to store return information}
- TBTReturnAddress = record
- ProcNo: PIFProcRec;
- Position, StackBase: Cardinal;
- end;
- {@link(PIFVariant)
- PPIFVariant is a pointer to a PIFVariant}
- PPIFVariant = ^PIfVariant;
- {@link(TIFVariant)
- PIFVariant is a pointer to a TIFVariant}
- PIFVariant = ^TIfVariant;
- {@link(TVariantResourceFreeProc)
- TVRMode is used to when the scriptengine needs to free or duplicate a resourcepointer}
- TVRFMode = (vrfFree, vrfDuplicate);
- {@link(TVRMode)
- TVariantResourceFreeProc is used when the scriptengine needs to free or duplicate a resourcepointer}
- TVariantResourceFreeProc = function (FMode: TVRFMode; P, IntoP: PIFVariant): Boolean;
- {PBTRecord is a pointer to a @link(TbtRecord) record}
- pbtrecord = ^TbtRecord;
- {TIFvariant is variant used for storing all variables used by the script}
- TIFVariant = packed record
- {The type of the variant}
- FType: PIFTypeRec;
- {The number of pointers referencing this variant}
- RefCount: Cardinal; // 0 = Freeable
- case Byte of
- 1: (tu8: TbtU8);
- 2: (tS8: TbtS8);
- 3: (tu16: TbtU16);
- 4: (ts16: TbtS16);
- 5: (tu32: TbtU32);
- 6: (ts32: TbtS32);
- 7: (tsingle: TbtSingle);
- 8: (tdouble: TbtDouble);
- 9: (textended: TbtExtended);
- 10: (tstring: Pointer);
- 11: (treturnaddress: TBTReturnAddress);
- 12: (trecord: pbtrecord);
- 13: (tArray: pbtrecord);
- 14: (tPointer: PIfVariant);
- 15: (tResourceP1, tResourceP2: Pointer; tResourceFreeProc: TVariantResourceFreeProc);
- 16: (tvariant: PIFVariant);
- {$IFNDEF NOINT64}
- 17: (ts64: Tbts64);
- {$ENDIF}
- end;
- {TbtRecord is used to store the fields in a record or array}
- TbtRecord = packed record
- FieldCount: Cardinal;
- Fields: array[0..10000] of PIfVariant;
- end;
- {TIFPSResourceFreeProc is called when a resource needs to be freed}
- TIFPSResourceFreeProc = procedure (Sender: TIFPSExec; P: Pointer);
- {@link(TIFPSResource)
- PIFPSResource is a pointer to a TIFPSResource record
- }
- PIFPSResource = ^TIFPSResource;
- { A resource in IFPS3 is stored as a pointer to the proc and a tag (p) }
- TIFPSResource = record
- Proc: Pointer;
- P: Pointer;
- end;
- {@link(pbtrecord)
- PBTRecord}
- PBTArray = pbtrecord;
- {@link(TbtRecord)
- tbtrecord}
- TBTArray = TbtRecord;
- {See TIFPSExec.OnRunLine}
- TIFPSOnLineEvent = procedure(Sender: TIFPSExec);
- {See TIFPSExec.AddSpecialProcImport}
- TIFPSOnSpecialProcImport = function (Sender: TIFPSExec; p: PIFProcRec; Tag: Pointer): Boolean;
- {TIFPSExec is the core of the script engine executer}
- TIFPSExec = class(TObject)
- Private
- FId: Pointer;
- FJumpFlag: Boolean;
- FCallCleanup: Boolean;
- function ReadData(var Data; Len: Cardinal): Boolean;
- function ReadByte(var b: Cardinal): Boolean;
- function ReadLong(var b: Cardinal): Boolean;
- function DoCalc(var1, Var2: PIfVariant; CalcType: Cardinal): Boolean;
- function DoBooleanCalc(var1, Var2: PIfVariant; Into: PIfVariant; Cmd: Cardinal): Boolean;
- function SetVariantValue(dest, Src: PIfVariant): Boolean;
- function ReadVariable(var NeedToFree: LongBool; UsePointer: LongBool): PIfVariant;
- procedure DoBooleanNot(Vd: PIfVariant);
- procedure DoMinus(Vd: PIfVariant);
- function BuildArray(Dest, Src: PIFVariant): boolean;
- Protected
- {MM is the memory manager used internally. It's needed to create and destroy variants}
- {$IFNDEF NOSMARTMM}MM: Pointer;
- {$ENDIF}
- {The exception stack}
- FExceptionStack: TIFList;
- {The list of resources}
- FResources: TIFList;
- {The list of exported variables}
- FExportedVars: TIfList;
- {FTypes contains all types used by the script}
- FTypes: TIfList;
- {FProcs contains all script procedures}
- FProcs: TIfList;
- {FGlobalVars contains the global variables of the current script}
- FGlobalVars: TIfList;
- {The current stack}
- FStack: TIfList;
- {The main proc no or -1 (no main proc)}
- FMainProc: Cardinal;
- {The current status of the script engine}
- FStatus: TIFStatus;
- {The current proc}
- FCurrProc: PIFProcRec;
- {The current position in the current proc}
- FCurrentPosition: Cardinal;
- {Current stack base}
- FCurrStackBase: Cardinal;
- {FOnRunLine event}
- FOnRunLine: TIFPSOnLineEvent;
- {List of SpecialProcs; See TIFPSExec.AddSpecialProc}
- FSpecialProcList: TIfList;
- {List of all registered external functions}
- FRegProcs: TIfList;
- {The proc where the last error occured}
- ExProc: Cardinal;
- {The position of the last error}
- ExPos: Cardinal;
- {The error code}
- ExEx: TIFError;
- {The optional parameter for the error}
- ExParam: string;
- {RunLine function}
- procedure RunLine; virtual;
- {ImportProc is called when the script needs to import an external function}
- function ImportProc(const Name: ShortString; var proc: TIFProcRec): Boolean; Virtual;
- {ExceptionProc is called when an error occurs}
- procedure ExceptionProc(proc, Position: Cardinal; Ex: TIFError; const s: string); Virtual;
- Public
- {Call CMD_Err to cause an error and stop the script}
- procedure CMD_Err(EC: TIFError);
- {Call CMD_Err2 to cause an error and stop the script}
- procedure CMD_Err2(EC: TIFError; const Param: string);
- {Optional tag of the script engine}
- property Id: Pointer read FID write FID;
- {The MemoryManager used when calling CreateVariant/DestroyVariant}
- {$IFNDEF NOSMARTMM}property MemoryManager: Pointer Read MM;{$ENDIF}
- {This function will return about information}
- class function About: string;
- {Use RunProc to call a script function. The Params will not be freed after the call}
- function RunProc(Params: TIfList; ProcNo: Cardinal): Boolean;
- {Search for a type (l is the starting position)}
- function FindType(StartAt: Cardinal; BaseType: TIFPSBaseType; var l: Cardinal): PIFTypeRec;
- {Search for a type}
- function FindType2(BaseType: TIFPSBaseType): PIFTypeRec;
- {Return type no L}
- function GetTypeNo(l: Cardinal): PIFTypeRec;
- {Create an integer variant}
- function CreateIntegerVariant(FType: PIFTypeRec; Value: Longint): PIfVariant;
- {create a string variant}
- function CreateStringVariant(FType: PIFTypeRec; const Value: string): PIfVariant;
- {Create a float variant}
- function CreateFloatVariant(FType: PIFTypeRec; Value: Extended): PIfVariant;
-
- {Get Type that has been compiled with a name}
- function GetType(const Name: string): Cardinal;
- {Get function that has been compiled with a name}
- function GetProc(const Name: string): Cardinal;
- {Get variable that has been compiled with a name}
- function GetVar(const Name: string): Cardinal;
- {Get variable compiled with a name as a variant}
- function GetVar2(const Name: string): PIFVariant;
- {Get variable no (C)}
- function GetVarNo(C: Cardinal): PIFVariant;
- {Get Proc no (C)}
- function GetProcNo(C: Cardinal): PIFProcRec;
-
- {Create an instance of the executer}
- constructor Create;
- {Destroy this instance of the executer}
- destructor Destroy; Override;
-
- {Run the current script}
- function RunScript: Boolean;
-
- {Load data into the script engine}
- function LoadData(const s: string): Boolean; virtual;
- {Clear the currently loaded script}
- procedure Clear; Virtual;
- {Reset all variables in the script to zero}
- procedure Cleanup; Virtual;
- {Stop the script engine}
- procedure Stop; Virtual;
- {Pause the script engine}
- procedure Pause; Virtual;
- {Set CallCleanup to false when you don't want the script engine to cleanup all variables after RunScript}
- property CallCleanup: Boolean read FCallCleanup write FCallCleanup;
- {Status contains the current status of the scriptengine}
- property Status: TIFStatus Read FStatus;
- {The OnRunLine event is called after each executed script line}
- property OnRunLine: TIFPSOnLineEvent Read FOnRunLine Write FOnRunLine;
- {Add a special proc import; this is used for the dll and class library}
- procedure AddSpecialProcImport(const FName: string; P: TIFPSOnSpecialProcImport; Tag: Pointer);
- {Register a function by name}
- function RegisterFunctionName(const Name: ShortString; ProcPtr: TIFProc;
- Ext1, Ext2: Pointer): PProcRec;
- {Clear the function list}
- procedure ClearFunctionList;
- {Contains the last error proc}
- property ExceptionProcNo: Cardinal Read ExProc;
- {Contains the last error position}
- property ExceptionPos: Cardinal Read ExPos;
- {Contains the last error code}
- property ExceptionCode: TIFError Read ExEx;
- {Contains the last error string}
- property ExceptionString: string read ExParam;
-
- {Add a resource}
- procedure AddResource(Proc, P: Pointer);
- {Check if P is a valid resource for Proc}
- function IsValidResource(Proc, P: Pointer): Boolean;
- {Delete a resource}
- procedure DeleteResource(P: Pointer);
- {Find a resource}
- function FindProcResource(Proc: Pointer): Pointer;
- {Find a resource}
- function FindProcResource2(Proc: Pointer; var StartAt: Longint): Pointer;
- end;
- {Decrease the variant's refcount and free it if it's 0}
- procedure DisposeVariant({$IFNDEF NOSMARTMM}MM: Pointer; {$ENDIF}p: PIfVariant);
- {Create a variant}
- function CreateVariant({$IFNDEF NOSMARTMM}MM: Pointer; {$ENDIF}n: PIFTypeRec): PIfVariant;
- {Convert an error to a string}
- function TIFErrorToString(x: TIFError; const Param: string): string;
- {Get the value of a variant (as Cardinal/Longword)}
- function GetUInt(Src: PIfVariant; var s: Boolean): Cardinal;
- {Get the value of a variant (as Longint)}
- function GetInt(Src: PIfVariant; var s: Boolean): Longint;
- {Get the value of a variant (as Extended)}
- function GetReal(Src: PIfVariant; var s: Boolean): Extended;
- {Get the value of a variant (as String)}
- function GetString(Src: PIfVariant; var s: Boolean): string;
- {Set the value of an Integer variant in a list}
- procedure LSetInt(List: TIfList; Pos: Cardinal; Val: Longint);
- {Set the value of an unsigned integer variant in a list}
- procedure LSetUInt(List: TIfList; Pos: Cardinal; Val: Cardinal);
- {Get the value of an Integer variant in a list}
- function LGetInt(List: TIfList; Pos: Cardinal): Longint;
- {Get the value of an unsigned integer variant in a list}
- function LGetUInt(List: TIfList; Pos: Cardinal): Cardinal;
- {Set the value of a string variant in a list}
- procedure LSetStr(List: TIfList; Pos: Cardinal; const s: string);
- {Get the value of a string variant in a list}
- function LGetStr(List: TIfList; Pos: Cardinal): string;
- {Set the value of a real variant in a list}
- procedure LSetReal(List: TIfList; Pos: Cardinal; const Val: Extended);
- {Get the value of a real variant in a list}
- function LGetReal(List: TIfList; Pos: Cardinal): Extended;
- {Get the length of a variant array}
- function GetIFPSArrayLength(SE: TIFPSExec; p: PIfVariant): Cardinal;
- {Set the length of a variant array}
- procedure SetIFPSArrayLength(SE: TIFPSExec; p: PIfVariant; NewLength: Cardinal);
-
- {Convert a variant to a string}
- function IFPSVariantToString(p: PIfVariant): string;
- {Free a list of variants and also the list}
- procedure FreePIFVariantList({$IFNDEF NOSMARTMM}MM: Pointer; {$ENDIF}List: TIfList);
-
- function VGetString(P: PIFVariant): string;
- function VGetFloat(P: PIFVariant): Extended;
- function VGetInt(P: PIFVariant): Longint;
- {$IFNDEF NOINT64}
- function VGetInt64(P: PIFVariant): Int64;
- {$ENDIF}
-
- procedure VSetString(P: PIFVariant; const d: string);
- procedure VSetFloat(P: PIFVariant; const d: Extended);
- procedure VSetInt(P: PIFVariant; const d: Longint);
- {$IFNDEF NOINT64}
- procedure VSetInt64(P: PIFVariant; const d: Int64);
- {$ENDIF}
-
- const
- ENoError = ERNoError;
- ecCustomError = erCustomError;
-
-
- procedure ChangeVariantType({$IFNDEF NOSMARTMM}MM: Pointer; {$ENDIF}p: PIFVariant; n: PIFTypeRec);
-
- implementation
-
- function VGetString(P: PIFVariant): string;
- begin
- if p = nil then begin Result := ''; exit; end;
- case p^.FType^.BaseType of
- btu8: Result := chr(p^.tu8);
- btString: Result := TbtString(p^.tstring);
- else Result := '';
- end;
- end;
-
- function VGetFloat(P: PIFVariant): Extended;
- begin
- if p = nil then begin Result := 0; exit; end;
- case p^.FType^.BaseType of
- btSingle: Result := p^.tsingle;
- btDouble: Result := p^.tdouble;
- btExtended: Result := p^.textended;
- else Result := 0;
- end;
- end;
- function VGetInt(P: PIFVariant): Longint;
- begin
- if p = nil then begin Result := 0; exit; end;
- case p^.FType^.BaseType of
- btu8: Result := p^.tu8;
- bts8: Result := p^.ts8;
- btu16: Result := p^.tu16;
- bts16: Result := p^.ts16;
- btu32: Result := p^.tu32;
- bts32: Result := p^.ts32;
- else Result := 0;
- end;
- end;
- {$IFNDEF NOINT64}
-
- function VGetInt64(P: PIFVariant): Int64;
- begin
- if p = nil then begin Result := 0; exit; end;
- case p^.FType^.BaseType of
- btu8: Result := p^.tu8;
- bts8: Result := p^.ts8;
- btu16: Result := p^.tu16;
- bts16: Result := p^.ts16;
- btu32: Result := p^.tu32;
- bts32: Result := p^.ts32;
- btS64: Result := p^.ts64;
- else Result := 0;
- end;
- end;
- {$ENDIF}
- procedure VSetString(P: PIFVariant; const d: string);
- begin
- if p = nil then begin exit; end;
- case p^.FType^.BaseType of
- btString: TbtString(p^.tstring) := d;
- end;
- end;
- procedure VSetFloat(P: PIFVariant; const d: Extended);
- begin
- if p = nil then begin exit; end;
- case p^.FType^.BaseType of
- btSingle: p^.tsingle := d;
- btDouble: p^.tdouble := d;
- btExtended: p^.textended := d;
- end;
- end;
- procedure VSetInt(P: PIFVariant; const d: Longint);
- begin
- if p = nil then begin exit; end;
- case p^.FType^.BaseType of
- btu8: p^.tu8 := d;
- bts8: p^.ts8 := d;
- btu16: p^.tu16 := d;
- bts16: p^.ts16 := d;
- btu32: p^.tu32 := d;
- bts32: p^.ts32 := d;
- end;
- end;
- {$IFNDEF NOINT64}
- procedure VSetInt64(P: PIFVariant; const d: Int64);
- begin
- if p = nil then begin exit; end;
- case p^.FType^.BaseType of
- btu8: p^.tu8 := d;
- bts8: p^.ts8 := d;
- btu16: p^.tu16 := d;
- bts16: p^.ts16 := d;
- btu32: p^.tu32 := d;
- bts32: p^.ts32 := d;
- btS64: p^.ts64 := d;
- end;
- end;
- {$ENDIF}
- function MakeString(const s: string): string;
- var
- i: Longint;
- e: string;
- b: boolean;
- begin
- Result := s;
- i := 1;
- b := false;
- while i <= length(result) do
- begin
- if Result[i] = '''' then
- begin
- if not b then
- begin
- b := true;
- Insert('''', Result, i);
- inc(i);
- end;
- Insert('''', Result, i);
- inc(i, 2);
- end else if (Result[i] < #32) then
- begin
- e := '#'+inttostr(ord(Result[i]));
- Delete(Result, i, 1);
- if b then
- begin
- b := false;
- Insert('''', Result, i);
- inc(i);
- end;
- Insert(e, Result, i);
- inc(i, length(e));
- end else begin
- if not b then
- begin
- b := true;
- Insert('''', Result, i);
- inc(i, 2);
- end else
- inc(i);
- end;
- end;
- if b then
- begin
- Result := Result + '''';
- end;
- if Result = '' then
- Result := '''''';
- end;
-
- function IFPSVariantToString(p: PIfVariant): string;
- var
- I: Longint;
- begin
- while p^.FType^.BaseType = btPointer do
- begin
- if p^.tPointer <> nil then p := p^.tPointer else break;
- end;
- if p^.FType^.BaseType = btVariant then P := p^.tvariant;
- case p^.FType^.BaseType of
- btU8: str(p^.tu8, Result);
- btS8: str(p^.ts8, Result);
- btU16: str(p^.tu16, Result);
- btS16: str(p^.ts16, Result);
- btU32: str(p^.tu32, Result);
- btS32: str(p^.ts32, Result);
- btSingle: str(p^.tsingle, Result);
- btDouble: str(p^.tdouble, Result);
- btExtended: str(p^.textended, Result);
- btString, btPChar: Result := makestring(string(p^.tString));
- {$IFNDEF NOINT64}btS64: str(p^.ts64, Result);{$ENDIF}
- btRecord, btArray:
- begin
- Result := '[';
- if p^.tArray <>nil then
- begin
- for i := 0 to pbtRecord(p^.tarray)^.FieldCount -1 do
- begin
- if i <> 0 then
- Result := Result + ', ';
- Result := Result + IFPSVariantToString(pbtRecord(p^.tarray)^.Fields[i]);
- end;
- end;
- Result := Result + ']';
- end;
- btPointer: Result := 'Nil';
- btResourcePointer: Result := '[ResourcePointer]';
- else
- Result := '[Invalid]';
- end;
- end;
-
-
- function GetIFPSArrayLength(SE: TIFPSExec; p: PIfVariant): Cardinal;
- begin
- if p^.FType^.BaseType <> btArray then begin
- Result := 0;
- exit;
- end;
- if p^.tArray = nil then
- Result := 0
- else
- Result := pbtrecord(p^.tArray)^.FieldCount;
- end;
-
- function Min(const x, Y: Integer): Integer;
- begin
- if x < Y then Result := x else Result := Y;
- end;
-
- procedure SetIFPSArrayLength(SE: TIFPSExec; p: PIfVariant; NewLength: Cardinal);
- var
- I, oldl: Integer;
- r: pbtrecord;
- begin
- if p^.FType^.BaseType <> btArray then exit;
- if p^.tArray = nil then begin
- I := NewLength;
- if I > 0 then begin
- try
- GetMem(r, 4 + I * 4);
- except
- exit;
- end;
- r^.FieldCount := I;
- Dec(I);
- while I >= 0 do begin
- r^.Fields[I] := CreateVariant({$IFNDEF NOSMARTMM}SE.MemoryManager, {$ENDIF}SE.GetTypeNo(Cardinal(p^.FType^.Ext)));
- if r^.Fields[I] = nil then begin
- while I < Longint(NewLength) do begin
- DisposeVariant({$IFNDEF NOSMARTMM}SE.MemoryManager, {$ENDIF}r.Fields[I]);
- Inc(I);
- end;
- exit;
- end;
- Dec(I);
- end;
- p^.tArray := r;
- end;
- end else begin
- r := p^.tArray;
- oldl := NewLength;
- for I := oldl to r^.FieldCount - 1 do begin
- DisposeVariant({$IFNDEF NOSMARTMM}SE.MemoryManager, {$ENDIF}r^.Fields[I]);
- end;
- if oldl = 0 then begin
- FreeMem(r, 4 + 4 * r^.FieldCount);
- p^.tArray := nil;
- end else begin
- I := oldl;
- oldl := r^.FieldCount;
- try
- ReallocMem(r, 4 + 4 * I);
- except
- for I := 0 to Min(NewLength, oldl) - 1 do begin
- DisposeVariant({$IFNDEF NOSMARTMM}SE.MemoryManager, {$ENDIF}r^.Fields[I]);
- end;
- FreeMem(r, 4 + 4 * NewLength);
- p^.tArray := nil;
- exit;
- end;
- r^.FieldCount := I;
- for I := r^.FieldCount - 1 downto oldl do begin
- r^.Fields[I] := CreateVariant({$IFNDEF NOSMARTMM}SE.MemoryManager, {$ENDIF}SE.GetTypeNo(Cardinal(p^.FType^.Ext)));
- if r^.Fields[I] = nil then begin
- oldl := I;
- while oldl < Longint(NewLength) do begin
- DisposeVariant({$IFNDEF NOSMARTMM}SE.MemoryManager, {$ENDIF}r.Fields[oldl]);
- Inc(oldl);
- end;
- exit;
- end;
- end;
- p^.tArray := r;
- end;
- end;
- end;
-
- function SafeStr(const s: string): string;
- var
- i : Longint;
- begin
- Result := s;
- for i := 1 to length(s) do
- begin
- if s[i] in [#0..#31] then
- begin
- Result := Copy(s, 1, i-1);
- exit;
- end;
- end;
-
- end;
-
- function TIFErrorToString(x: TIFError; const Param: string): string;
- begin
- case x of
- ErNoError: Result := 'No Error';
- erCannotImport: Result := 'Cannot Import '+Safestr(Param);
- erInvalidType: Result := 'Invalid Type';
- ErInternalError: Result := 'Internal error';
- erInvalidHeader: Result := 'Invalid Header';
- erInvalidOpcode: Result := 'Invalid Opcode';
- erInvalidOpcodeParameter: Result := 'Invalid Opcode Parameter';
- erNoMainProc: Result := 'no Main Proc';
- erOutOfGlobalVarsRange: Result := 'Out of Global Vars range';
- erOutOfProcRange: Result := 'Out of Proc Range';
- ErOutOfRange: Result := 'Out Of Range';
- erOutOfStackRange: Result := 'Out Of Stack Range';
- ErTypeMismatch: Result := 'Type Mismatch';
- erUnexpectedEof: Result := 'Unexpected End Of File';
- erVersionError: Result := 'Version error';
- ErDivideByZero: Result := 'divide by Zero';
- erMathError: Result := 'Math error';
- erCouldNotCallProc: Result := 'Could not call proc';
- erOutofRecordRange: Result := 'Out of Record Fields Range';
- erNullPointerException: Result := 'Null Pointer Exception';
- erNullVariantError: Result := 'Null variant error';
- erOutOfMemory: Result := 'Out Of Memory';
- erException: Result := 'Exception: '+ Param;
- erCustomError: Result := Param;
- else
- Result := 'Unknown error';
- end;
- //
- end;
-
- {$IFNDEF NOSMARTMM}
- const
- Count = 50;
-
- type
- TFreeIFVariant = packed record
- NextFreeItem: Longint;
- DummyData: array[0..SizeOf(TIfVariant) - SizeOf(Longint) - 1 +
- SizeOf(Pointer)] of Byte;
- end;
- PPageData = ^TPageData;
- TMyIFVariant = packed record
- Page: PPageData;
- p: TIfVariant;
- end;
- TPageData = packed record
- ItemCount, FirstFreeItem: Longint;
- PrevPage, NextPage,
- PrevFreeItemsPage, NextFreeItemsPage: PPageData;
- case Byte of
- 0: (BLOCK: array[0..Count - 1] of TMyIFVariant);
- 1: (FREELIST: array[0..Count - 1] of TFreeIFVariant);
- end;
-
- type
- TIFVariantMemoryManager = class
- Private
- FFirstFreeItemsPage, FFirstPage: PPageData;
- procedure CleanItem(Page: PPageData);
- function AllocItem: Boolean;
- Public
- constructor Create;
- destructor Destroy; Override;
- procedure Clear;
-
- function Alloc: PIfVariant;
- procedure DisposeItem(p: PIfVariant);
- end;
- type
- TPointingInteger = Longint; // same size as Pointer
-
- function TIFVariantMemoryManager.Alloc: PIfVariant;
- var
- CB: PPageData;
- I: Integer;
- begin
- if FFirstFreeItemsPage = nil then begin
- if not AllocItem then begin
- Result := nil;
- exit;
- end;
- end;
- CB := FFirstFreeItemsPage;
- Inc(CB^.ItemCount);
- I := CB^.FirstFreeItem;
- CB^.FirstFreeItem := CB^.FREELIST[I].NextFreeItem;
- Result := @CB^.BLOCK[I].p;
- CB^.BLOCK[I].Page := CB;
- if CB^.FirstFreeItem = -1 then begin // remove from freeitemspage list
- if CB^.PrevFreeItemsPage <> nil then
- CB^.PrevFreeItemsPage^.NextFreeItemsPage := CB^.NextFreeItemsPage;
- if CB^.NextFreeItemsPage <> nil then
- CB^.NextFreeItemsPage^.PrevFreeItemsPage := CB^.PrevFreeItemsPage;
- if FFirstFreeItemsPage = CB then
- FFirstFreeItemsPage := CB^.NextFreeItemsPage;
- end;
- end;
-
- function TIFVariantMemoryManager.AllocItem: Boolean;
- var
- NewItem: PPageData;
- I: Longint;
-
- begin
- try
- New(NewItem);
- except
- Result := False;
- exit;
- end;
-
- NewItem^.ItemCount := 0;
- NewItem^.FirstFreeItem := Count - 1;
- NewItem^.PrevPage := nil;
- NewItem^.NextPage := FFirstPage;
- NewItem^.PrevFreeItemsPage := nil;
- NewItem^.NextFreeItemsPage := FFirstFreeItemsPage;
-
- for I := Count - 1 downto 0 do begin
- NewItem^.FREELIST[I].NextFreeItem := I - 1;
- end;
-
- if FFirstPage <> nil then
- FFirstPage^.PrevPage := NewItem;
- if FFirstFreeItemsPage <> nil then
- FFirstFreeItemsPage^.PrevPage := NewItem;
-
- FFirstPage := NewItem;
- FFirstFreeItemsPage := NewItem;
- Result := True;
- end;
-
- procedure TIFVariantMemoryManager.CleanItem(Page: PPageData);
- begin
- if Page^.PrevPage <> nil then
- Page^.PrevPage^.NextPage := Page^.NextPage;
- if Page^.NextPage <> nil then
- Page^.NextPage^.PrevPage := Page^.PrevPage;
-
- if Page^.PrevFreeItemsPage <> nil then
- Page^.PrevFreeItemsPage^.NextFreeItemsPage := Page^.NextFreeItemsPage;
- if Page^.NextFreeItemsPage <> nil then
- Page^.NextFreeItemsPage^.PrevFreeItemsPage := Page^.PrevFreeItemsPage;
- if FFirstPage = Page then
- FFirstPage := Page^.NextPage;
- if FFirstFreeItemsPage = Page then
- FFirstFreeItemsPage := Page^.NextFreeItemsPage;
- Dispose(Page);
- end;
-
- procedure TIFVariantMemoryManager.Clear;
- var
- CB, NB: PPageData;
- begin
- CB := FFirstPage;
- while CB <> nil do begin
- NB := CB^.NextPage;
- Dispose(CB);
- CB := NB;
- end;
- FFirstPage := nil;
- FFirstFreeItemsPage := nil;
- end;
-
- constructor TIFVariantMemoryManager.Create;
- begin
- inherited Create;
- FFirstFreeItemsPage := nil;
- FFirstPage := nil;
- end;
-
- destructor TIFVariantMemoryManager.Destroy;
- begin
- Clear;
- inherited Destroy;
- end;
-
- procedure TIFVariantMemoryManager.DisposeItem(p: PIfVariant);
- var
- Page: PPageData;
- I: Longint;
- begin
- Page := PPageData(Pointer(TPointingInteger(p) - SizeOf(Pointer))^);
- I := (TPointingInteger(p) - TPointingInteger(@Page^.BLOCK) - SizeOf(Pointer)) div SizeOf(TMyIFVariant);
- Dec(Page^.ItemCount);
- Page^.FREELIST[I].NextFreeItem := Page^.FirstFreeItem;
- Page^.FirstFreeItem := I;
- if Page^.ItemCount = 0 then begin
- CleanItem(Page);
- end
- else if Page^.ItemCount = Count - 1 then begin // insert into list
- if FFirstFreeItemsPage <> nil then
- FFirstFreeItemsPage^.PrevFreeItemsPage := Page;
- Page^.PrevFreeItemsPage := nil;
- Page^.NextFreeItemsPage := FFirstFreeItemsPage;
- FFirstFreeItemsPage := Page;
- end;
- end;
-
- {$ENDIF}
-
- const
- ReturnAddressType: TIFTypeRec = (Ext: nil; BaseType: btReturnAddress);
-
- type
- PIFPSExceptionHandler =^TIFPSExceptionHandler;
- TIFPSExceptionHandler = packed record
- BasePtr, StackSize: Cardinal;
- FinallyOffset, ExceptOffset, Finally2Offset, EndOfBlock: Cardinal;
- end;
- TIFPSHeader = packed record
- HDR: Cardinal;
- IFPSBuildNo: Cardinal;
- TypeCount: Cardinal;
- ProcCount: Cardinal;
- VarCount: Cardinal;
- MainProcNo: Cardinal;
- ImportTableSize: Cardinal;
- end;
-
- TIFPSExportItem = packed record
- ProcNo: Cardinal;
- NameLength: Cardinal;
- DeclLength: Cardinal;
- end;
-
- TIFPSType = packed record
- BaseType: TIFPSBaseType;
- end;
- TIFPSProc = packed record
- Flags: Byte;
- end;
-
- TIFPSVar = packed record
- TypeNo: Cardinal;
- Flags: Byte;
- end;
- PSpecialProc = ^TSpecialProc;
- TSpecialProc = record
- P: TIFPSOnSpecialProcImport;
- namehash: Longint;
- Name: string;
- tag: pointer;
- end;
-
- procedure DisposeType(p: PIFTypeRec);
- var
- x: PIFRecordType;
- begin
- if p^.BaseType = btRecord then begin
- x := p^.Ext;
- x^.Data := '';
- Dispose(x);
- end;
- Dispose(p);
- end;
-
- procedure DisposeProc(SE: TIFPSExec; p: PIFProcRec);
- begin
- if not p^.ExternalProc then
- FreeMem(p^.Data, p^.Length);
-
- Dispose(p);
- end;
-
- function Initrecord({$IFNDEF NOSMARTMM}MM: Pointer; {$ENDIF}FType:
- PIFRecordType; var Rec: pbtrecord): Boolean;
- var
- I, J: Longint;
- begin
- I := (Length(FType^.Data) shr 2);
- try
- GetMem(Rec, 4 + 4 * I);
- except
- Result := False;
- exit;
- end;
- Rec.FieldCount := I;
- for I := 0 to Rec.FieldCount - 1 do begin
- Rec.Fields[I] := CreateVariant({$IFNDEF NOSMARTMM}MM,
- {$ENDIF}PIFTypeRec((@FType^.Data[I shl 2 + 1])^));
- if Rec.Fields[I] = nil then begin
- for J := I - 1 downto 0 do begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Rec.Fields[J]);
- FreeMem(Rec, 4 * 4 * (Length(FType^.Data) shr 2));
- Result := False;
- exit;
- end;
- end;
- end;
- Result := True;
- end;
-
- procedure FreeRecord({$IFNDEF NOSMARTMM}MM: Pointer; {$ENDIF}Rec: pbtrecord);
- var
- I: Longint;
- begin
- if Rec <> nil then begin
- for I := Rec.FieldCount - 1 downto 0 do
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Rec.Fields[I]);
- FreeMem(Rec, Rec.FieldCount * 4 + 4);
- end;
- end;
-
- procedure DisposeVariant({$IFNDEF NOSMARTMM}MM: Pointer; {$ENDIF}p: PIfVariant);
- begin
- if p <> nil then
- if p^.RefCount = 0 then begin
- if p^.FType <> nil then
- begin
- if (p^.FType^.BaseType = btRecord) or (p^.FType^.BaseType = btArray) then
- FreeRecord({$IFNDEF NOSMARTMM}MM, {$ENDIF}p^.trecord)
- else if p^.FType^.BaseType = btString then
- Finalize(TbtString((@p^.tstring)^))
- else if p^.FType^.BaseType = btResourcePointer then
- begin
- if (@p^.tResourceFreeProc <> nil) then
- begin
- p^.tResourceFreeProc(vrfFree, p, nil);
- end;
- end else if p^.FType^.BaseType = btvariant then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}p^.tvariant);
- end;
- {$IFNDEF NOSMARTMM}
- TIFVariantMemoryManager(MM).DisposeItem(p);
- {$ELSE}
- Dispose(p);
- {$ENDIF}
- end
- else
- Dec(p^.RefCount);
- end;
-
- procedure ChangeVariantType({$IFNDEF NOSMARTMM}MM: Pointer; {$ENDIF}p: PIFVariant; n: PIFTypeRec);
- begin
- if p^.FType <> nil then
- begin
- if (p^.FType^.BaseType = btRecord) or (p^.FType^.BaseType = btArray) then
- FreeRecord({$IFNDEF NOSMARTMM}MM, {$ENDIF}p^.trecord)
- else if p^.FType^.BaseType = btString then
- Finalize(TbtString((@p^.tstring)^))
- else if p^.FType^.BaseType = btResourcePointer then
- begin
- if (@p^.tResourceFreeProc <> nil) then
- begin
- p^.tResourceFreeProc(vrfFree, p, nil);
- end;
- end else if p^.FType^.BaseType = btvariant then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}p^.tvariant);
- end;
- p^.FType := n;
- if n <> nil then
- begin
- if n^.BaseType = btVariant then
- begin
- {$IFDEF NOSMARTMM}
- try
- New(p^.tvariant);
- except
- p^.tvariant := nil;
- exit;
- end;
- {$ELSE}
- p^.TVariant := TIFVariantMemoryManager(MM).Alloc;
- {$ENDIF}
- p^.tVariant^.FType := nil;
- p^.tvariant^.refcount := 0;
- end else if (n^.BaseType = btRecord) then begin
- p^.RefCount := 0;
- if not Initrecord({$IFNDEF NOSMARTMM}MM, {$ENDIF}n^.Ext, pbtrecord(p^.trecord)) then begin
- p^.trecord := nil;
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}p);
- end;
- end
- else begin
- FillChar(p^.RefCount, SizeOf(TIfVariant) - SizeOf(Pointer), 0);
- end;
- end;
- end;
-
- function CreateVariant({$IFNDEF NOSMARTMM}MM: Pointer; {$ENDIF}n: PIFTypeRec): PIfVariant;
- var
- p: PIfVariant;
- begin
- if n = nil then begin
- Result := nil;
- exit;
- end;
- {$IFNDEF NOSMARTMM}
- p := TIFVariantMemoryManager(MM).Alloc;
- if p = nil then begin
- Result := nil;
- exit;
- end;
- {$ELSE}
- try
- New(p);
- except
- Result := nil;
- exit;
- end;
- {$ENDIF}
-
- p^.FType := n;
- if n^.BaseType = btVariant then
- begin
- {$IFDEF NOSMARTMM}
- try
- New(p^.tvariant);
- except
- p^.tvariant := nil;
- exit;
- end;
- {$ELSE}
- p^.TVariant := TIFVariantMemoryManager(MM).Alloc;
- {$ENDIF}
- p^.tVariant^.FType := nil;
- p^.tvariant^.RefCount := 0;
- end else if (n^.BaseType = btRecord) then begin
- p^.RefCount := 0;
- if not Initrecord({$IFNDEF NOSMARTMM}MM, {$ENDIF}n^.Ext, pbtrecord(p^.trecord)) then begin
- p^.trecord := nil;
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}p);
- end;
- end
- else begin
- FillChar(p^.RefCount, SizeOf(TIfVariant) - SizeOf(Pointer), 0);
- end;
- CreateVariant := p;
- end;
- procedure LSetReal(List: TIfList; Pos: Cardinal; const Val: Extended);
- var
- p: PIfVariant;
- begin
- p := List.GetItem(Pos);
- if p = nil then exit;
- case p^.FType^.BaseType of
- btSingle: p^.tsingle := Val;
- btDouble: p^.tdouble := Val;
- btExtended: p^.textended := Val;
- end;
- end;
-
- function LGetReal(List: TIfList; Pos: Cardinal): Extended;
- var
- p: PIfVariant;
- begin
- p := List.GetItem(Pos);
- if p = nil then begin result := 0; exit; end;
- case p^.FType^.BaseType of
- btSingle: Result := p^.tsingle;
- btDouble: Result := p^.tdouble;
- btExtended: Result := p^.textended;
- else
- Result := 0;
- end;
- end;
-
- function LGetStr(List: TIfList; Pos: Cardinal): string;
- var
- p: PIfVariant;
- begin
- p := List.GetItem(Pos);
- if p = nil then begin result := ''; exit; end;
- case p^.FType^.BaseType of
- btstring: Result := TbtString(p^.tstring);
- end;
- end;
-
- procedure LSetStr(List: TIfList; Pos: Cardinal; const s: string);
- var
- p: PIfVariant;
- begin
- p := List.GetItem(Pos);
- if p = nil then exit;
- case p^.FType^.BaseType of
- btstring: TbtString(p^.tstring) := s;
- end;
- end;
-
- function LGetUInt(List: TIfList; Pos: Cardinal): Cardinal;
- var
- p: PIfVariant;
- begin
- p := List.GetItem(Pos);
- if p = nil then begin result := 0; exit; end;
- case p^.FType^.BaseType of
- btU8: Result := p^.tu8;
- btS8: Result := p^.tS8;
- btU16: Result := p^.tu16;
- btS16: Result := p^.ts16;
- btU32: Result := p^.tu32;
- btS32: Result := p^.ts32;
- {$IFNDEF NOINT64}btS64: Result := p^.ts64;{$ENDIF}
- btString: begin
- if Length(tbtstring(p^.tstring)) =1 then
- begin
- Result := ord(tbtstring(p^.tstring)[1]);
- end else Result := 0;
- end;
- else
- Result := 0;
- end;
- end;
-
- function LGetInt(List: TIfList; Pos: Cardinal): Longint;
- var
- p: PIfVariant;
- begin
- p := List.GetItem(Pos);
- if p = nil then begin result := 0; exit; end;
- case p^.FType^.BaseType of
- btU8: Result := p^.tu8;
- btS8: Result := p^.tS8;
- btU16: Result := p^.tu16;
- btS16: Result := p^.ts16;
- btU32: Result := p^.tu32;
- btS32: Result := p^.ts32;
- {$IFNDEF NOINT64}btS64: Result := p^.ts64;{$ENDIF}
- btString: begin
- if Length(tbtstring(p^.tstring)) =1 then
- begin
- Result := ord(tbtstring(p^.tstring)[1]);
- end else Result := 0;
- end;
- else
- Result := 0;
- end;
- end;
-
- procedure LSetUInt(List: TIfList; Pos: Cardinal; Val: Cardinal);
- var
- Src: PIfVariant;
- begin
- Src := List.GetItem(Pos);
- if Src = nil then exit;
- case Src^.FType^.BaseType of
- btU8: Src^.tu8 := Val;
- btS8: Src^.tS8 := Val;
- btU16: Src^.tu16 := Val;
- btS16: Src^.ts16 := Val;
- btU32: Src^.tu32 := Val;
- btS32: Src^.ts32 := Val;
- {$IFNDEF NOINT64}btS64: src^.ts64 := Val;{$ENDIF}
- btString: tbtstring(src^.tstring) := Chr(Val);
- end;
- end;
-
- procedure LSetInt(List: TIfList; Pos: Cardinal; Val: Longint);
- var
- Src: PIfVariant;
- begin
- Src := List.GetItem(Pos);
- if Src = nil then exit;
- case Src^.FType^.BaseType of
- btU8: Src^.tu8 := Val;
- btS8: Src^.tS8 := Val;
- btU16: Src^.tu16 := Val;
- btS16: Src^.ts16 := Val;
- btU32: Src^.tu32 := Val;
- btS32: Src^.ts32 := Val;
- {$IFNDEF NOINT64}btS64: src^.ts64 := Val;{$ENDIF}
- btString: tbtstring(src^.tstring) := chr(Val);
- end;
- end;
- {$IFNDEF NOINT64}
- function GetInt64(Src: PIfVariant; var s: Boolean): Int64;
- begin
- case Src^.FType^.BaseType of
- btVariant:
- begin
- if src^.TVariant^.FType <> nil then
- Result := GetInt64(Src^.TVariant, s)
- else
- Result := 0;
- end;
- btU8: Result := Src^.tu8;
- btS8: Result := Src^.tS8;
- btU16: Result := Src^.tu16;
- btS16: Result := Src^.ts16;
- btU32: Result := Src^.tu32;
- btS32: Result := Src^.ts32;
- btS64: Result := src^.ts64;
- btString: begin
- if Length(tbtstring(src^.tstring)) =1 then
- begin
- Result := ord(tbtstring(src^.tstring)[1]);
- end else begin Result := 0; s := False; end;
- end;
- else begin
- s := False;
- Result := 0;
- end;
- end;
- end;
- {$ENDIF}
-
- function GetUInt(Src: PIfVariant; var s: Boolean): Cardinal;
- begin
- case Src^.FType^.BaseType of
- btVariant:
- begin
- if src^.TVariant^.FType <> nil then
- Result := GetUINT(Src^.TVariant, s)
- else
- Result := 0;
- end;
- btU8: Result := Src^.tu8;
- btS8: Result := Src^.tS8;
- btU16: Result := Src^.tu16;
- btS16: Result := Src^.ts16;
- btU32: Result := Src^.tu32;
- btS32: Result := Src^.ts32;
- {$IFNDEF NOINT64}btS64: Result := src^.ts64;{$ENDIF}
- btString: begin
- if Length(tbtstring(src^.tstring)) =1 then
- begin
- Result := ord(tbtstring(src^.tstring)[1]);
- end else begin Result := 0; s := False; end;
- end;
- else begin
- s := False;
- Result := 0;
- end;
- end;
- end;
-
- function GetInt(Src: PIfVariant; var s: Boolean): Longint;
- begin
- case Src^.FType^.BaseType of
- btVariant:
- begin
- if src^.TVariant^.FType <> nil then
- Result := GetInt(Src^.TVariant, s)
- else
- Result := 0;
- end;
- btU8: Result := Src^.tu8;
- btS8: Result := Src^.tS8;
- btU16: Result := Src^.tu16;
- btS16: Result := Src^.ts16;
- btU32: Result := Src^.tu32;
- btS32: Result := Src^.ts32;
- {$IFNDEF NOINT64}btS64: Result := src^.ts64;{$ENDIF}
- btString: begin
- if Length(tbtstring(src^.tstring)) =1 then
- begin
- Result := ord(tbtstring(src^.tstring)[1]);
- end else begin Result := 0; s := False; end;
- end;
- else begin
- s := False;
- Result := 0;
- end;
- end;
- end;
-
- function GetReal(Src: PIfVariant; var s: Boolean): Extended;
- begin
- case Src^.FType^.BaseType of
- btVariant:
- begin
- if src^.TVariant^.FType <> nil then
- Result := GetReal(Src^.TVariant, s)
- else
- Result := 0;
- end;
- btU8: Result := Src^.tu8;
- btS8: Result := Src^.tS8;
- btU16: Result := Src^.tu16;
- btS16: Result := Src^.ts16;
- btU32: Result := Src^.tu32;
- btS32: Result := Src^.ts32;
- btSingle: Result := Src^.tsingle;
- btDouble: Result := Src^.tdouble;
- btExtended: Result := Src^.textended;
- else begin
- s := False;
- Result := 0;
- end;
- end;
- end;
-
- function GetString(Src: PIfVariant; var s: Boolean): string;
- begin
- case Src^.FType^.BaseType of
- btVariant:
- begin
- if src^.TVariant^.FType <> nil then
- Result := GetString(Src^.TVariant, s)
- else
- Result := '';
- end;
- btU8, btS8: Result := Char(Src^.tu8);
- btPChar, btString: Result := TbtString((@Src^.tstring)^);
- else begin
- s := False;
- Result := '';
- end;
- end;
- end;
-
- function LookupProc(List: TIfList; const Name: ShortString): PProcRec;
- var
- h, l: Longint;
- begin
- h := MakeHash(Name);
- for l := 0 to List.Count - 1 do begin
- if (PProcRec(List.GetItem(l))^.Hash = h) and (PProcRec(List.GetItem(l))^.Name
- = Name) then begin
- Result := List.GetItem(l);
- exit;
- end;
- end;
- Result := nil;
- end;
-
- { TIFPSExec }
-
- procedure TIFPSExec.ClearFunctionList;
- var
- x: PProcRec;
- l: Longint;
- begin
- for l := 0 to FRegProcs.Count - 1 do begin
- x := FRegProcs.GetItem(l);
- if @x^.FreeProc <> nil then x^.FreeProc(Self, x);
- Dispose(x);
- end;
- FRegProcs.Clear;
- end;
-
- class function TIFPSExec.About: string;
- begin
- Result := 'Innerfuse Pascal Script III ' + IFPSCurrentversion + '. Copyright (c) 2001-2002 by Carlo Kok';
- end;
-
- procedure TIFPSExec.Cleanup;
- var
- I: Longint;
- p: PIfVariant;
- begin
- if FStatus <> isLoaded then
- exit;
- for I := 0 to Longint(FGlobalVars.Count) - 1 do begin
- p := FGlobalVars.GetItem(I);
- FGlobalVars.SetItem(I, CreateVariant({$IFNDEF NOSMARTMM}MM,
- {$ENDIF}p^.FType));
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}p);
- end;
- end;
- type
- PIFPSExportedVar = ^TIFPSExportedVar;
- TIFPSExportedVar = record
- FName: string;
- FNameHash: Longint;
- FVarNo: Cardinal;
- end;
-
- procedure TIFPSExec.Clear;
- var
- I: Longint;
- temp: PIFPSResource;
- Proc: TIFPSResourceFreeProc;
- pp: PIFPSExceptionHandler;
- begin
- for i := Longint(FExceptionStack.Count) -1 downto 0 do
- begin
- pp := FExceptionStack.GetItem(i);
- Dispose(pp);
- end;
- for i := Longint(FResources.Count) -1 downto 0 do
- begin
- Temp := FResources.GetItem(i);
- Proc := Temp^.Proc;
- Proc(Self, Temp^.P);
- Dispose(Temp);
- end;
- for i := Longint(FExportedVars.Count) -1 downto 0 do
- begin
- Dispose(PIFPSExportedVar(FExportedVars.GetItem(I)));
- end;
- for I := 0 to Longint(FStack.Count) - 1 do begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}FStack.GetItem(I));
- end;
- for I := 0 to Longint(FProcs.Count) - 1 do begin
- DisposeProc(Self, FProcs.GetItem(I));
- end;
- for I := 0 to Longint(FGlobalVars.Count) - 1 do begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}FGlobalVars.GetItem(I));
- end;
- for I := 0 to Longint(FTypes.Count) - 1 do begin
- DisposeType(FTypes.GetItem(I));
- end;
- FStack.Clear;
- FProcs.Clear;
- FGlobalVars.Clear;
- FTypes.Clear;
- FStatus := isNotLoaded;
- FResources.Clear;
- FExportedVars.Clear;
- FExceptionStack.Clear;
- end;
-
- constructor TIFPSExec.Create;
- begin
- inherited Create;
- {$IFNDEF NOSMARTMM}MM := TIFVariantMemoryManager.Create;
- {$ENDIF}
- FExceptionStack := TIfList.Create;
- FCallCleanup := False;
- FResources := TIfList.Create;
- FTypes := TIfList.Create;
- FProcs := TIfList.Create;
- FGlobalVars := TIfList.Create;
- FStack := TIfList.Create;
- FMainProc := 0;
- FStatus := isNotLoaded;
- FRegProcs := TIfList.Create;
- FExportedVars := TIfList.create;
- FSpecialProcList := TIfList.Create;
- end;
-
- destructor TIFPSExec.Destroy;
- var
- I: Longint;
- P: PSpecialProc;
- begin
- Clear;
- for I := FSpecialProcList.Count -1 downto 0 do
- begin
- P := FSpecialProcList.GetItem(I);
- Dispose(p);
- end;
- FStack.Free;
- FResources.Free;
- FExportedVars.Free;
- FGlobalVars.Free;
- FProcs.Free;
- FTypes.Free;
- FSpecialProcList.Free;
- ClearFunctionList;
-
- FRegProcs.Free;
- FExceptionStack.Free;
- {$IFNDEF NOSMARTMM}TIFVariantMemoryManager(MM).Free;
- {$ENDIF}
- inherited Destroy;
- end;
-
- procedure TIFPSExec.ExceptionProc(proc, Position: Cardinal; Ex: TIFError; const s: string);
- var
- d, l: Longint;
- pp: PIFPSExceptionHandler;
- begin
- ExProc := proc;
- ExPos := Position;
- ExEx := Ex;
- ExParam := s;
- if Ex = eNoError then Exit;
- for d := FExceptionStack.Count -1 downto 0 do
- begin
- pp := FExceptionStack.GetItem(d);
- if FStack.Count > pp^.StackSize then
- begin
- for l := Longint(FStack.count) -1 downto Longint(pp^.StackSize) do
- begin
- DisposeVariant({$IFNDEF SMARTMM}mm, {$ENDIF}FStack.GetItem(l));
- FStack.Delete(l);
- end;
- end;
- FCurrStackBase := pp^.BasePtr;
- if pp^.FinallyOffset <> cardinal(-1) then
- begin
- FCurrentPosition := pp^.FinallyOffset;
- pp^.FinallyOffset := cardinal(-1);
- Exit;
- end else if pp^.ExceptOffset <> cardinal(-1) then
- begin
- FCurrentPosition := pp^.ExceptOffset;
- pp^.ExceptOffset := cardinal(-1);
- Exit;
- end else if pp^.Finally2Offset <> Cardinal(-1) then
- begin
- FCurrentPosition := pp^.FinallyOffset;
- pp^.FinallyOffset := cardinal(-1);
- Exit;
- end;
- Dispose(pp);
- FExceptionStack.Delete(FExceptionStack.Count -1);
- end;
- FStatus := isPaused;
- end;
-
- function TIFPSExec.ImportProc(const Name: ShortString; var proc: TIFProcRec): Boolean;
- var
- u: PProcRec;
- fname: string;
- I, fnh: Longint;
- P: PSpecialProc;
-
- begin
- if name = '' then
- begin
- fname := proc.ExportDecl;
- fname := copy(fname, 1, pos(':', fname)-1);
- fnh := MakeHash(fname);
- for I := FSpecialProcList.Count -1 downto 0 do
- begin
- p := FSpecialProcList.GetItem(I);
- IF (p^.name = '') or ((p^.namehash = fnh) and (p^.name = fname)) then
- begin
- if p^.P(Self, @Proc, p^.tag) then
- begin
- Result := True;
- exit;
- end;
- end;
- end;
- Result := FAlse;
- exit;
- end;
- u := LookupProc(FRegProcs, Name);
- if u = nil then begin
- Result := False;
- exit;
- end;
- proc.ProcPtr := u^.ProcPtr;
- proc.Ext1 := u^.Ext1;
- proc.Ext2 := u^.Ext2;
- Result := True;
- end;
-
- function TIFPSExec.RegisterFunctionName(const Name: ShortString; ProcPtr: TIFProc; Ext1, Ext2: Pointer): PProcRec;
- var
- p: PProcRec;
- begin
- if LookupProc(FRegProcs, Name) <> nil then begin
- Result := nil;
- exit;
- end;
- New(p);
- p^.Name := Name;
- p^.Hash := MakeHash(Name);
- p^.ProcPtr := ProcPtr;
- p^.FreeProc := nil;
- p^.Ext1 := Ext1;
- p^.Ext2 := Ext2;
- FRegProcs.Add(p);
- Result := P;
- end;
-
- function TIFPSExec.LoadData(const s: string): Boolean;
- var
- HDR: TIFPSHeader;
- Pos: Cardinal;
-
- function read(var Data; Len: Cardinal): Boolean;
- begin
- if Longint(Pos + Len) <= Length(s) then begin
- Move(s[Pos + 1], Data, Len);
- Pos := Pos + Len;
- read := True;
- end
- else
- read := False;
- end;
- {$WARNINGS OFF}
-
- function LoadTypes: Boolean;
- var
- currf: TIFPSType;
- Curr: PIFTypeRec;
- currr: PIFRecordType;
- fe: Boolean;
- l: Longint;
- d: Cardinal;
-
- function resolve(var s: string): Boolean;
- var
- l: Longint;
- p: PIFTypeRec;
- begin
- l := 1;
- while l < Length(s) do begin
- p := FTypes.GetItem(Cardinal(s[l]));
- if p = nil then begin
- Result := False;
- exit;
- end;
- PIFTypeRec((@s[l])^) := p;
- if p^.BaseType = btRecord then begin
- Delete(s, l, 4);
- insert(PIFRecordType(p^.Ext)^.Data, s, l);
- end;
- l := l + 4;
- end;
- Result := True;
- end;
- begin
- LoadTypes := True;
- for l := 0 to HDR.TypeCount - 1 do begin
- if not read(currf, SizeOf(currf)) then begin
- cmd_err(erUnexpectedEof);
- LoadTypes := False;
- exit;
- end;
- if (currf.BaseType and 128) <> 0 then begin
- fe := True;
- currf.BaseType := currf.BaseType - 128;
- end else
- fe := False;
- try
- New(Curr);
- except
- CMD_Err(erOutOfMemory);
- LoadTypes := False;
- exit;
- end;
- case currf.BaseType of
- {$IFNDEF NOINT64}bts64, {$ENDIF}
- btU8, btS8, btU16, btS16, btU32, btS32, btSingle, btDouble, btExtended, btString, btPointer, btPChar, btResourcePointer, btVariant: begin
- Curr^.BaseType := currf.BaseType;
- Curr^.Ext := nil;
- FTypes.Add(Curr);
- end;
- btArray: begin
- if not read(d, 4) then begin // Read type
- cmd_err(erUnexpectedEof);
- LoadTypes := False;
- exit;
- end;
- if (d >= FTypes.Count) then begin
- cmd_err(erTypeMismatch);
- LoadTypes := False;
- exit;
- end;
- Curr^.BaseType := currf.BaseType;
- Curr^.Ext := Pointer(d);
- FTypes.Add(Curr);
- end;
- btRecord: begin
- if not read(d, 4) or (d = 0) then begin
- cmd_err(erUnexpectedEof);
- LoadTypes := false;
- exit;
- end;
- try
- New(currr);
- except
- cmd_err(erOutOfMemory);
- LoadTypes := False;
- exit;
- end;
- SetLength(currr^.Data, d * 4);
- if not read(currr^.Data[1], d * 4) then begin
- currr^.Data := '';
- Dispose(currr);
- cmd_err(erUnexpectedEof);
- LoadTypes := False;
- exit;
- end;
- if not resolve(currr^.Data) then begin
- currr^.Data := '';
- Dispose(currr);
- cmd_err(erInvalidType);
- LoadTypes := False;
- exit;
- end;
- Curr^.BaseType := currf.BaseType;
- Curr^.Ext := currr;
- FTypes.Add(Curr);
- end;
- else begin
- LoadTypes := False;
- CMD_Err(erInvalidType);
- Dispose(Curr);
- exit;
- end;
- end;
- if fe then begin
- if not read(d, 4) then begin
- cmd_err(erUnexpectedEof);
- LoadTypes := False;
- exit;
- end;
- if d > IFPSAddrNegativeStackStart then begin
- cmd_err(erInvalidType);
- LoadTypes := False;
- exit;
- end;
- SetLength(Curr^.ExportName, d);
- if not read(Curr^.ExportName[1], d) then begin
- cmd_err(erUnexpectedEof);
- LoadTypes := False;
- exit;
- end;
- Curr^.ExportNameHash := MakeHash(Curr^.ExportName);
- end;
- end;
- end;
-
- function LoadProcs: Boolean;
- var
- Rec: TIFPSProc;
- n: string;
- b: Byte;
- l, L2, L3: Longint;
- Curr: PIFProcRec;
- begin
- LoadProcs := True;
- for l := 0 to HDR.ProcCount - 1 do begin
- if not read(Rec, SizeOf(Rec)) then begin
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- try
- New(Curr);
- except
- cmd_err(erOutOfMemory);
- LoadProcs := False;
- exit;
- end;
- Curr^.ExternalProc := (Rec.Flags and 1) <> 0;
- if Curr^.ExternalProc then begin
- if not read(b, 1) then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- SetLength(n, b);
- if not read(n[1], b) then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- Curr^.Name := n;
- if (Rec.Flags and 3 = 3) then
- begin
- if (not Read(L2, 4)) or (L2 > Length(s) - Pos) then
- begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- SetLength(n, L2);
- Read(n[1], L2); // no check is needed
- Curr^.ExportDecl := n;
- end;
- if not ImportProc(Curr^.Name, Curr^) then begin
- if Curr^.Name <> '' then
- CMD_Err2(erCannotImport, Curr^.Name)
- else if Curr^.ExportDecl <> '' then
- CMD_Err2(erCannotImport, curr^.ExportDecl)
- else
- CMD_Err2(erCannotImport, curr^.ExportName);
- Dispose(Curr);
- LoadProcs := False;
- exit;
- end;
- end
- else begin
- if not read(L2, 4) then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- if not read(L3, 4) then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- if (L2 < 0) or (L2 >= Length(s)) or (L2 + L3 > Length(s)) then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- GetMem(Curr^.Data, L3);
- Move(s[L2 + 1], Curr^.Data^, L3);
- Curr^.Length := L3;
- if (Rec.Flags and 2) <> 0 then begin // exported
- if not read(L3, 4) then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- if L3 > IFPSAddrNegativeStackStart then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- SetLength(Curr^.ExportName, L3);
- if not read(Curr^.ExportName[1], L3) then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- if not read(L3, 4) then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- if L3 > IFPSAddrNegativeStackStart then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- SetLength(Curr^.ExportDecl, L3);
- if not read(Curr^.ExportDecl[1], L3) then begin
- Dispose(Curr);
- cmd_err(erUnexpectedEof);
- LoadProcs := False;
- exit;
- end;
- Curr^.ExportNameHash := MakeHash(Curr^.ExportName);
- end;
- end;
- FProcs.Add(Curr);
- end;
- end;
- {$WARNINGS ON}
-
- function LoadVars: Boolean;
- var
- l, n: Longint;
- e: PIFPSExportedVar;
- Rec: TIFPSVar;
- Curr: PIfVariant;
- begin
- LoadVars := True;
- for l := 0 to HDR.VarCount - 1 do begin
- if not read(Rec, SizeOf(Rec)) then begin
- cmd_err(erUnexpectedEof);
- LoadVars := False;
- exit;
- end;
- if Rec.TypeNo >= HDR.TypeCount then begin
- cmd_err(erInvalidType);
- LoadVars := False;
- exit;
- end;
- Curr := CreateVariant({$IFNDEF NOSMARTMM}MM,
- {$ENDIF}FTypes.GetItem(Rec.TypeNo));
- if Curr = nil then begin
- cmd_err(erInvalidType);
- LoadVars := False;
- exit;
- end;
- if (Rec.Flags and 1) <> 0then
- begin
- if not read(n, 4) then begin
- cmd_err(erUnexpectedEof);
- LoadVars := False;
- exit;
- end;
- new(e);
- try
- SetLength(e^.FName, n);
- if not Read(e^.FName[1], n) then
- begin
- dispose(e);
- cmd_err(erUnexpectedEof);
- LoadVars := False;
- exit;
- end;
- e^.FNameHash := MakeHash(e^.FName);
- e^.FVarNo := FGlobalVars.Count;
- FExportedVars.Add(E);
- except
- dispose(e);
- cmd_err(erInvalidType);
- LoadVars := False;
- exit;
- end;
- end;
- FGlobalVars.Add(Curr);
- end;
- end;
-
- begin
- Clear;
- Pos := 0;
- LoadData := False;
- if not read(HDR, SizeOf(HDR)) then
- begin
- CMD_Err(erInvalidHeader);
- exit;
- end;
- if HDR.HDR <> IFPSValidHeader then
- begin
- CMD_Err(erInvalidHeader);
- exit;
- end;
- if (HDR.IFPSBuildNo > IFPSCurrentBuildNo) or (HDR.IFPSBuildNo < IFPSLowBuildSupport) then begin
- CMD_Err(erInvalidHeader);
- exit;
- end;
- if not LoadTypes then
- begin
- Clear;
- exit;
- end;
- if not LoadProcs then
- begin
- Clear;
- exit;
- end;
- if not LoadVars then
- begin
- Clear;
- exit;
- end;
- if (HDR.MainProcNo >= FProcs.Count) and (HDR.MainProcNo <> Cardinal(-1))then begin
- CMD_Err(erNoMainProc);
- Clear;
- exit;
- end;
- // Load Import Table
- FMainProc := HDR.MainProcNo;
- FStatus := isLoaded;
- Result := True;
- end;
-
- procedure TIFPSExec.Pause;
- begin
- if FStatus = isRunning then
- FStatus := isPaused;
- end;
-
- function TIFPSExec.ReadData(var Data; Len: Cardinal): Boolean;
- begin
- if FCurrentPosition + Len <= FCurrProc.Length then begin
- Move(FCurrProc.Data^[FCurrentPosition], Data, Len);
- FCurrentPosition := FCurrentPosition + Len;
- Result := True;
- end
- else
- Result := False;
- end;
-
- procedure TIFPSExec.CMD_Err(EC: TIFError); // Error
- begin
- CMD_Err2(ec, '');
- end;
-
- function TIFPSExec.BuildArray(Dest, Src: PIFVariant): boolean;
- var
- i, j: Longint;
- t: pbtrecord;
- begin
- if (Src^.FType^.BaseType = btVariant) and (Src^.TVariant^.FType <> nil) and (Src^.TVariant^.FType^.BaseType = btArray) then
- Src := Src^.TVariant;
- if (Src^.FType^.BaseType <> btArray) and (Src^.FType^.BaseType <> btRecord) then
- begin
- Result := False;
- exit;
- end;
- if Dest^.TArray <> nil then
- begin
- for i := 0 to pbtrecord(Dest^.Tarray)^.FieldCount -1 do
- begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM ,{$ENDIF}pbtrecord(Dest^.Tarray)^.fields[i]);
- end;
- FreeMem(pbtrecord(Dest^.Tarray), pbtrecord(Dest^.Tarray)^.FieldCount * 4 + 4);
- end;
- if src^.TArray = nil then
- begin
- Dest^.TArray := nil;
- Result := true;
- exit;
- end;
- try
- getmem(t, pbtRecord(src^.Tarray)^.FieldCount * 4 +4);
- t.FieldCount := pbtRecord(src^.Tarray)^.FieldCount;
- except
- Dest^.TArray := nil;
- Result := False;
- exit;
- end;
- for i := pbtRecord(src^.Tarray)^.FieldCount -1 downto 0 do
- begin
- t^.Fields[i] := CreateVariant({$IFNDEF NOSMARTMM}mm, {$ENDIF} pbtRecord(src^.Tarray)^.Fields[i]^.FType);
- if t^.Fields[i] = nil then
- begin
- Freemem(t, t^.FieldCount * 4 + 4);
- for j := 0 to i -1 do
- begin
- DisposeVariant({$IFNDEF NOSMARTMM}mm, {$ENDIF} t^.Fields[j]);
- end;
- Dest^.TArray := nil;
- Result := False;
- exit;
- end;
- if not SetVariantValue(t^.Fields[i], pbtRecord(src^.Tarray)^.Fields[i]) then
- begin
- for j := pbtRecord(src^.Tarray)^.FieldCount -1 downto i do
- begin
- DisposeVariant({$IFNDEF NOSMARTMM}mm, {$ENDIF} t^.Fields[j]);
- end;
- Freemem(t, t^.FieldCount * 4 + 4);
- Dest^.TArray := nil;
- Result := False;
- exit;
- end;
- end;
- dest^.TArray := t;
-
- Result := True;
- end;
-
- function TIFPSExec.SetVariantValue(dest, Src: PIfVariant): Boolean;
- begin
- Result := True;
- case dest^.FType^.BaseType of
- btU8: dest^.tu8 := GetUInt(Src, Result);
- btS8: dest^.tS8 := GetInt(Src, Result);
- btU16: dest^.tu16 := GetUInt(Src, Result);
- btS16: dest^.ts16 := GetInt(Src, Result);
- btU32: dest^.tu32 := GetUInt(Src, Result);
- btS32: dest^.ts32 := GetInt(Src, Result);
- {$IFNDEF NOINT64}
- btS64: dest^.ts64 := GetInt64(Src, Result);
- {$ENDIF}
- btSingle: dest^.tsingle := GetReal(Src, Result);
- btDouble: dest^.tdouble := GetReal(Src, Result);
- btExtended: dest^.textended := GetReal(Src, Result);
- btPChar,btString: TbtString((@dest^.tstring)^) := GetString(Src, Result);
- btArray, btRecord: Result := BuildArray(Dest, Src);
- btVariant:
- begin
- if Src^.FType^.BaseType = btVariant then
- ChangeVariantType({$IFNDEF NOSMARTMM}mm, {$ENDIF}Dest^.tVariant, src^.TVariant^.FType)
- else
- ChangeVariantType({$IFNDEF NOSMARTMM}mm, {$ENDIF}Dest^.tVariant, src^.FType);
- if Dest^.tvariant = nil then
- begin
- Result := False;
- end else begin
- if Dest^.TVariant^.FType <> nil then
- begin
- if Src^.FType^.BaseType = btVariant then
- Result := SetVariantValue(Dest^.TVariant, Src^.tvariant)
- else
- Result := SetVariantValue(Dest^.TVariant, Src);
- end;
- end;
- end;
- btResourcePointer:
- begin
- if src^.Ftype^.BaseType = btvariant then
- begin
- Src := src^.tvariant;
- if src^.FType = nil then
- begin
- Result := False;
- exit;
- end;
- end;
- if Src^.FType^.BaseType <> btResourcePointer then
- begin
- Result := False;
- exit;
- end;
- if @Src^.tResourceFreeProc <> nil then
- begin
- Result := Src^.tResourceFreeProc(vrfDuplicate, Src, Dest);
- end else begin
- Dest^.TResourceFreeProc := nil;
- Dest^.TResourceP1 := nil;
- Dest^.TResourceP2 := nil;
- end;
- end;
- else begin
- Result := False;
- end;
- end;
- if Result = False then
- CMD_Err(ErTypeMismatch);
- end;
-
- function TIFPSExec.DoBooleanCalc(var1, Var2: PIfVariant; Into: PIfVariant; Cmd:
- Cardinal): Boolean;
- var
- b: Boolean;
-
- procedure SetBoolean(b: Boolean; var Ok: Boolean);
- begin
- Ok := True;
- case Into^.FType^.BaseType of
- btU8: Into^.tu8 := Cardinal(b);
- btS8: Into^.tS8 := Longint(b);
- btU16: Into^.tu16 := Cardinal(b);
- btS16: Into^.ts16 := Longint(b);
- btU32: Into^.tu32 := Cardinal(b);
- btS32: Into^.ts32 := Longint(b);
- else begin
- CMD_Err(ErTypeMismatch);
- Ok := False;
- end;
- end;
- end;
- begin
- Result := True;
- if (var1^.FType = nil) and (var1^.FType = nil) then {variants}
- begin
- case Cmd of
- 0,1,2,3: Result := False;
- 4: SetBoolean(False, Result); { <> }
- 5: SetBoolean(True, Result); { = }
- else begin
- Result := False;
- CMD_Err(erInvalidOpcodeParameter);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end else
- if (var1^.FType = nil) xor (var2^.FType = nil) then {variants}
- begin
- case Cmd of
- 0,1,2,3: Result := False;
- 4: SetBoolean(True, Result); { <> }
- 5: SetBoolean(False, Result); { = }
- else begin
- Result := False;
- CMD_Err(erInvalidOpcodeParameter);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end else
- case Cmd of
- 0: begin { >= }
- case var1^.FType^.BaseType of
- btU8:
- if (var2^.FType^.BaseType = btString) or (Var2^.Ftype^.BaseType = btPChar) then
- b := char(var1^.tu8) >= GetString(Var2, Result)
- else
- b := var1^.tu8 >= GetUInt(Var2, Result);
- btS8: b := var1^.tS8 >= GetInt(Var2, Result);
- btU16: b := var1^.tu16 >= GetUInt(Var2, Result);
- btS16: b := var1^.ts16 >= GetInt(Var2, Result);
- btU32: b := var1^.tu32 >= GetUInt(Var2, Result);
- btS32: b := var1^.ts32 >= GetInt(Var2, Result);
- btSingle: b := var1^.tsingle >= GetReal(Var2, Result);
- btDouble: b := var1^.tdouble >= GetReal(Var2, Result);
- btExtended: b := var1^.textended >= GetReal(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: b := var1^.ts64 >= GetInt64(Var2, Result);
- {$ENDIF}
- btPChar,btString: b := tbtstring(var1^.tstring) >= GetString(Var2, Result);
- else begin
- CMD_Err(ErTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(ErTypeMismatch);
- exit;
- end;
- SetBoolean(b, Result);
- end;
- 1: begin { <= }
- case var1^.FType^.BaseType of
- btU8:
- if (var2^.FType^.BaseType = btString) or (Var2^.Ftype^.BaseType = btPChar) then
- b := char(var1^.tu8) <= GetString(Var2, Result)
- else
- b := var1^.tu8 <= GetUInt(Var2, Result);
- btS8: b := var1^.tS8 <= GetInt(Var2, Result);
- btU16: b := var1^.tu16 <= GetUInt(Var2, Result);
- btS16: b := var1^.ts16 <= GetInt(Var2, Result);
- btU32: b := var1^.tu32 <= GetUInt(Var2, Result);
- btS32: b := var1^.ts32 <= GetInt(Var2, Result);
- btSingle: b := var1^.tsingle <= GetReal(Var2, Result);
- btDouble: b := var1^.tdouble <= GetReal(Var2, Result);
- btExtended: b := var1^.textended <= GetReal(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: b := var1^.ts64 <= GetInt64(Var2, Result);
- {$ENDIF}
- btPChar,btString: b := tbtstring(var1^.tstring) <= GetString(Var2, Result);
- else begin
- CMD_Err(ErTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- SetBoolean(b, Result);
- end;
- 2: begin { > }
- case var1^.FType^.BaseType of
- btU8:
- if (var2^.FType^.BaseType = btString) or (Var2^.Ftype^.BaseType = btPChar) then
- b := char(var1^.tu8) > GetString(Var2, Result)
- else
- b := var1^.tu8 > GetUInt(Var2, Result);
- btS8: b := var1^.tS8 > GetInt(Var2, Result);
- btU16: b := var1^.tu16 > GetUInt(Var2, Result);
- btS16: b := var1^.ts16 > GetInt(Var2, Result);
- btU32: b := var1^.tu32 > GetUInt(Var2, Result);
- btS32: b := var1^.ts32 > GetInt(Var2, Result);
- btSingle: b := var1^.tsingle > GetReal(Var2, Result);
- btDouble: b := var1^.tdouble > GetReal(Var2, Result);
- btExtended: b := var1^.textended > GetReal(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: b := var1^.ts64 > GetInt64(Var2, Result);
- {$ENDIF}
- btPChar,btString: b := tbtstring(var1^.tstring) > GetString(Var2, Result);
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- SetBoolean(b, Result);
- end;
- 3: begin { < }
- case var1^.FType^.BaseType of
- btU8:
- if (var2^.FType^.BaseType = btString) or (Var2^.Ftype^.BaseType = btPChar) then
- b := char(var1^.tu8) < GetString(Var2, Result)
- else
- b := var1^.tu8 < GetUInt(Var2, Result);
- btS8: b := var1^.tS8 < GetInt(Var2, Result);
- btU16: b := var1^.tu16 < GetUInt(Var2, Result);
- btS16: b := var1^.ts16 < GetInt(Var2, Result);
- btU32: b := var1^.tu32 < GetUInt(Var2, Result);
- btS32: b := var1^.ts32 < GetInt(Var2, Result);
- btSingle: b := var1^.tsingle < GetReal(Var2, Result);
- btDouble: b := var1^.tdouble < GetReal(Var2, Result);
- btExtended: b := var1^.textended < GetReal(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: b := var1^.ts64 < GetInt64(Var2, Result);
- {$ENDIF}
- btPChar,btString: b := tbtstring(var1^.tstring) < GetString(Var2, Result);
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- SetBoolean(b, Result);
- end;
- 4: begin { <> }
- case var1^.FType^.BaseType of
- btU8:
- if (var2^.FType^.BaseType = btString) or (Var2^.Ftype^.BaseType = btPChar) then
- b := char(var1^.tu8) <> GetString(Var2, Result)
- else
- b := var1^.tu8 <> GetUInt(Var2, Result);
- btS8: b := var1^.tS8 <> GetInt(Var2, Result);
- btU16: b := var1^.tu16 <> GetUInt(Var2, Result);
- btS16: b := var1^.ts16 <> GetInt(Var2, Result);
- btU32: b := var1^.tu32 <> GetUInt(Var2, Result);
- btS32: b := var1^.ts32 <> GetInt(Var2, Result);
- btSingle: b := var1^.tsingle <> GetReal(Var2, Result);
- btDouble: b := var1^.tdouble <> GetReal(Var2, Result);
- btExtended: b := var1^.textended <> GetReal(Var2, Result);
- btPChar,btString: b := TbtString(var1^.tstring) <> GetString(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: b := var1^.ts64 <> GetInt64(Var2, Result);
- {$ENDIF}
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- SetBoolean(b, Result);
- end;
- 5: begin { = }
- case var1^.FType^.BaseType of
- btU8:
- if (var2^.FType^.BaseType = btString) or (Var2^.Ftype^.BaseType = btPChar) then
- b := char(var1^.tu8) = GetString(Var2, Result)
- else
- b := var1^.tu8 = GetUInt(Var2, Result);
- btS8: b := var1^.tS8 = GetInt(Var2, Result);
- btU16: b := var1^.tu16 = GetUInt(Var2, Result);
- btS16: b := var1^.ts16 = GetInt(Var2, Result);
- btU32: b := var1^.tu32 = GetUInt(Var2, Result);
- btS32: b := var1^.ts32 = GetInt(Var2, Result);
- btSingle: b := var1^.tsingle = GetReal(Var2, Result);
- btDouble: b := var1^.tdouble = GetReal(Var2, Result);
- btExtended: b := var1^.textended = GetReal(Var2, Result);
- btPchar, btString: b := TbtString(var1^.tstring) = GetString(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: b := var1^.ts64 = GetInt64(Var2, Result);
- {$ENDIF}
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- SetBoolean(b, Result);
- end;
- else begin
- Result := False;
- CMD_Err(erInvalidOpcodeParameter);
- exit;
- end;
- end;
- end;
-
- function TIFPSExec.DoCalc(var1, Var2: PIfVariant; CalcType: Cardinal): Boolean;
- { var1=dest, var2=src }
- begin
- try
- Result := True;
- case CalcType of
- 0: begin { + }
- case var1^.FType^.BaseType of
- btU8: var1^.tu8 := var1^.tu8 + GetUInt(Var2, Result);
- btS8: var1^.tS8 := var1^.tS8 + GetInt(Var2, Result);
- btU16: var1^.tu16 := var1^.tu16 + GetUInt(Var2, Result);
- btS16: var1^.ts16 := var1^.ts16 + GetInt(Var2, Result);
- btU32: var1^.tu32 := var1^.tu32 + GetUInt(Var2, Result);
- btS32: var1^.ts32 := var1^.ts32 + GetInt(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: var1^.ts64 := var1^.ts64 + GetInt64(var2, Result);
- {$ENDIF}
- btSingle: var1^.tsingle := var1^.tsingle + GetReal(Var2, Result);
- btDouble: var1^.tdouble := var1^.tdouble + GetReal(Var2, Result);
- btExtended: var1^.textended := var1^.textended + GetReal(Var2,
- Result);
- btPchar, btString: TbtString((@var1^.tstring)^) :=
- TbtString((@var1^.tstring)^) + GetString(Var2, Result);
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- 1: begin { - }
- case var1^.FType^.BaseType of
- btU8: var1^.tu8 := var1^.tu8 - GetUInt(Var2, Result);
- btS8: var1^.tS8 := var1^.tS8 - GetInt(Var2, Result);
- btU16: var1^.tu16 := var1^.tu16 - GetUInt(Var2, Result);
- btS16: var1^.ts16 := var1^.ts16 - GetInt(Var2, Result);
- btU32: var1^.tu32 := var1^.tu32 - GetUInt(Var2, Result);
- btS32: var1^.ts32 := var1^.ts32 - GetInt(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: var1^.ts64 := var1^.ts64 - GetInt64(var2, Result);
- {$ENDIF}
- btSingle: var1^.tsingle := var1^.tsingle - GetReal(Var2, Result);
- btDouble: var1^.tdouble := var1^.tdouble - GetReal(Var2, Result);
- btExtended: var1^.textended := var1^.textended - GetReal(Var2,
- Result);
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- 2: begin { * }
- case var1^.FType^.BaseType of
- btU8: var1^.tu8 := var1^.tu8 * GetUInt(Var2, Result);
- btS8: var1^.tS8 := var1^.tS8 * GetInt(Var2, Result);
- btU16: var1^.tu16 := var1^.tu16 * GetUInt(Var2, Result);
- btS16: var1^.ts16 := var1^.ts16 * GetInt(Var2, Result);
- btU32: var1^.tu32 := var1^.tu32 * GetUInt(Var2, Result);
- btS32: var1^.ts32 := var1^.ts32 * GetInt(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: var1^.ts64 := var1^.ts64 * GetInt64(var2, Result);
- {$ENDIF}
- btSingle: var1^.tsingle := var1^.tsingle * GetReal(Var2, Result);
- btDouble: var1^.tdouble := var1^.tdouble * GetReal(Var2, Result);
- btExtended: var1^.textended := var1^.textended * GetReal(Var2,
- Result);
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- 3: begin { / }
- case var1^.FType^.BaseType of
- btU8: var1^.tu8 := var1^.tu8 div GetUInt(Var2, Result);
- btS8: var1^.tS8 := var1^.tS8 div GetInt(Var2, Result);
- btU16: var1^.tu16 := var1^.tu16 div GetUInt(Var2, Result);
- btS16: var1^.ts16 := var1^.ts16 div GetInt(Var2, Result);
- btU32: var1^.tu32 := var1^.tu32 div GetUInt(Var2, Result);
- btS32: var1^.ts32 := var1^.ts32 div GetInt(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: var1^.ts64 := var1^.ts64 div GetInt64(var2, Result);
- {$ENDIF}
- btSingle: var1^.tsingle := var1^.tsingle / GetReal(Var2, Result);
- btDouble: var1^.tdouble := var1^.tdouble / GetReal(Var2, Result);
- btExtended: var1^.textended := var1^.textended / GetReal(Var2, Result);
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- 4: begin { MOD }
- case var1^.FType^.BaseType of
- btU8: var1^.tu8 := var1^.tu8 mod GetUInt(Var2, Result);
- btS8: var1^.tS8 := var1^.tS8 mod GetInt(Var2, Result);
- btU16: var1^.tu16 := var1^.tu16 mod GetUInt(Var2, Result);
- btS16: var1^.ts16 := var1^.ts16 mod GetInt(Var2, Result);
- btU32: var1^.tu32 := var1^.tu32 mod GetUInt(Var2, Result);
- btS32: var1^.ts32 := var1^.ts32 mod GetInt(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: var1^.ts64 := var1^.ts64 mod GetInt64(var2, Result);
- {$ENDIF}
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- 5: begin { SHL }
- case var1^.FType^.BaseType of
- btU8: var1^.tu8 := var1^.tu8 shl GetUInt(Var2, Result);
- btS8: var1^.tS8 := var1^.tS8 shl GetInt(Var2, Result);
- btU16: var1^.tu16 := var1^.tu16 shl GetUInt(Var2, Result);
- btS16: var1^.ts16 := var1^.ts16 shl GetInt(Var2, Result);
- btU32: var1^.tu32 := var1^.tu32 shl GetUInt(Var2, Result);
- btS32: var1^.ts32 := var1^.ts32 shl GetInt(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: var1^.ts64 := var1^.ts64 shl GetInt64(var2, Result);
- {$ENDIF}
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- 6: begin { SHR }
- case var1^.FType^.BaseType of
- btU8: var1^.tu8 := var1^.tu8 shr GetUInt(Var2, Result);
- btS8: var1^.tS8 := var1^.tS8 shr GetInt(Var2, Result);
- btU16: var1^.tu16 := var1^.tu16 shr GetUInt(Var2, Result);
- btS16: var1^.ts16 := var1^.ts16 shr GetInt(Var2, Result);
- btU32: var1^.tu32 := var1^.tu32 shr GetUInt(Var2, Result);
- btS32: var1^.ts32 := var1^.ts32 shr GetInt(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: var1^.ts64 := var1^.ts64 shr GetInt64(var2, Result);
- {$ENDIF}
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- 7: begin { AND }
- case var1^.FType^.BaseType of
- btU8: var1^.tu8 := var1^.tu8 and GetUInt(Var2, Result);
- btS8: var1^.tS8 := var1^.tS8 and GetInt(Var2, Result);
- btU16: var1^.tu16 := var1^.tu16 and GetUInt(Var2, Result);
- btS16: var1^.ts16 := var1^.ts16 and GetInt(Var2, Result);
- btU32: var1^.tu32 := var1^.tu32 and GetUInt(Var2, Result);
- btS32: var1^.ts32 := var1^.ts32 and GetInt(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: var1^.ts64 := var1^.ts64 and GetInt64(var2, Result);
- {$ENDIF}
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- 8: begin { OR }
- case var1^.FType^.BaseType of
- btU8: var1^.tu8 := var1^.tu8 or GetUInt(Var2, Result);
- btS8: var1^.tS8 := var1^.tS8 or GetInt(Var2, Result);
- btU16: var1^.tu16 := var1^.tu16 or GetUInt(Var2, Result);
- btS16: var1^.ts16 := var1^.ts16 or GetInt(Var2, Result);
- btU32: var1^.tu32 := var1^.tu32 or GetUInt(Var2, Result);
- btS32: var1^.ts32 := var1^.ts32 or GetInt(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: var1^.ts64 := var1^.ts64 or GetInt64(var2, Result);
- {$ENDIF}
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- 9: begin { XOR }
- case var1^.FType^.BaseType of
- btU8: var1^.tu8 := var1^.tu8 xor GetUInt(Var2, Result);
- btS8: var1^.tS8 := var1^.tS8 xor GetInt(Var2, Result);
- btU16: var1^.tu16 := var1^.tu16 xor GetUInt(Var2, Result);
- btS16: var1^.ts16 := var1^.ts16 xor GetInt(Var2, Result);
- btU32: var1^.tu32 := var1^.tu32 xor GetUInt(Var2, Result);
- btS32: var1^.ts32 := var1^.ts32 xor GetInt(Var2, Result);
- {$IFNDEF NOINT64}
- btS64: var1^.ts64 := var1^.ts64 xor GetInt64(var2, Result);
- {$ENDIF}
- else begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- if not Result then begin
- CMD_Err(erTypeMismatch);
- exit;
- end;
- end;
- else begin
- Result := False;
- CMD_Err(erInvalidOpcodeParameter);
- exit;
- end;
- end;
- except
- on E: EDivByZero do
- begin
- Result := False;
- CMD_Err(erDivideByZero);
- Exit;
- end;
- on E: EZeroDivide do
- begin
- Result := False;
- CMD_Err(erDivideByZero);
- Exit;
- end;
- on E: EMathError do
- begin
- Result := False;
- CMD_Err(erMathError);
- Exit;
- end;
- on E: Exception do
- begin
- Result := False;
- CMD_Err2(erException, e.Message);
- exit;
- end;
- end;
- end;
-
- function TIFPSExec.ReadVariable(var NeedToFree: LongBool; UsePointer: LongBool): PIfVariant;
- var
- VarType: Cardinal;
- Param: Cardinal;
- Tmp: PIfVariant;
-
- begin
- if not (ReadByte(VarType) and ReadLong(Param)) then begin
- CMD_Err(erOutOfRange);
- Result := nil;
- exit;
- end;
- case VarType of
- 0: begin
- NeedToFree := False;
- if Param < IFPSAddrNegativeStackStart then begin
- Result := FGlobalVars.GetItem(Param);
- if Result = nil then begin
- CMD_Err(erOutOfGlobalVarsRange);
- exit;
- end;
- end
- else begin
- Result := FStack.GetItem(Cardinal(Longint(-IFPSAddrStackStart) +
- Longint(FCurrStackBase) + Longint(Param)));
- if Result = nil then begin
- CMD_Err(erOutOfStackRange);
- exit;
- end;
- end;
- if UsePointer then
- begin
- if Result^.FType^.BaseType = btPointer then begin
- Result := Result^.tPointer;
- if Result = nil then begin
- CMD_Err(erNullPointerException);
- exit;
- end;
- end;
- if Result^.FType^.BaseType = btVariant then begin
- Result := Result^.tvariant;
- if Result = nil then begin
- CMD_Err(erNullPointerException);
- exit;
- end;
- if Result^.FType = nil then
- begin
- Result := nil;
- CMD_Err(erNullVariantError);
- Exit;
- end;
- end;
- end;
- end;
- 1: begin
- NeedToFree := True;
- Result := CreateVariant({$IFNDEF NOSMARTMM}MM,
- {$ENDIF}FTypes.GetItem(Param));
- if Result = nil then begin
- CMD_Err(erInvalidType);
- exit;
- end;
- case Result^.FType^.BaseType of
- btU8: if not ReadData(Result^.tu8, 1) then begin
- CMD_Err(erOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- btS8: if not ReadData(Result^.tS8, 1) then begin
- CMD_Err(erOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- btU16: if not ReadData((@Result^.tu16)^, SizeOf(TbtU16)) then begin
- CMD_Err(ErOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- btS16: if not ReadData((@Result^.ts16)^, SizeOf(TbtS16)) then begin
- CMD_Err(ErOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- btU32: if not ReadLong(Result^.tu32) then begin
- CMD_Err(erOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- btS32: if not ReadLong(Cardinal(Result^.ts32)) then begin
- CMD_Err(erOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- {$IFNDEF NOINT64}
- bts64: if not ReadData(Result^.ts64, sizeof(tbts64)) then
- begin
- CMD_Err(erOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- {$ENDIF}
- btSingle: if not ReadData((@Result^.tsingle)^, SizeOf(TbtSingle))
- then begin
- CMD_Err(erOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- btDouble: if not ReadData((@Result^.tdouble)^, SizeOf(TbtDouble))
- then begin
- CMD_Err(erOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- btExtended: if not ReadData((@Result^.textended)^,
- SizeOf(TbtExtended)) then begin
- CMD_Err(erOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- btPchar, btString: begin
- if not ReadLong(Param) then begin
- CMD_Err(erOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- SetLength(TbtString((@Result^.tstring)^), Param);
- if not ReadData(TbtString((@Result^.tstring)^)[1], Param) then begin
- CMD_Err(erOutOfRange);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- end;
- else begin
- CMD_Err(erInvalidType);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Result);
- Result := nil;
- exit;
- end;
- end;
- end;
- 2: begin
- NeedToFree := False;
- if Param < IFPSAddrNegativeStackStart then begin
- Result := FGlobalVars.GetItem(Param);
- if Result = nil then begin
- CMD_Err(erOutOfGlobalVarsRange);
- exit;
- end;
- end
- else begin
- Result := FStack.GetItem(Cardinal(Longint(-IFPSAddrStackStart) +
- Longint(FCurrStackBase) + Longint(Param)));
- if Result = nil then begin
- CMD_Err(erOutOfStackRange);
- exit;
-
- end;
- end;
- if (Result^.FType^.BaseType = btPointer) then begin
- Result := Result^.tPointer;
- if Result = nil then begin
- CMD_Err(erNullPointerException);
- exit;
- end;
- end;
- if Result^.FType^.BaseType = btVariant then begin
- Result := Result^.tvariant;
- if Result = nil then begin
- CMD_Err(erNullPointerException);
- exit;
- end;
- if Result^.FType = nil then
- begin
- Result := nil;
- CMD_Err(erNullVariantError);
- Exit;
- end;
- end;
- if (Result^.FType^.BaseType <> btRecord) and (Result^.FType^.BaseType <> btArray) then begin
- CMD_Err(erInvalidType);
- Result := nil;
- exit;
- end;
- if not ReadLong(Param) then begin
- CMD_Err(erOutOfRange);
- Result := nil;
- exit;
- end;
- if (Result^.trecord = nil) or (Param >= pbtrecord(Result^.trecord)^.FieldCount) then begin
- CMD_Err(erOutofRecordRange);
- Result := nil;
- exit;
- end;
- Result := pbtrecord(Result^.trecord)^.Fields[Param];
- if UsePointer then
- begin
- if Result^.FType^.BaseType = btPointer then begin
- Result := Result^.tPointer;
- if Result = nil then begin
- CMD_Err(erNullPointerException);
- exit;
- end;
- end;
- if Result^.FType^.BaseType = btVariant then begin
- Result := Result^.tvariant;
- if Result = nil then begin
- CMD_Err(erNullPointerException);
- exit;
- end;
- if Result^.FType = nil then
- begin
- Result := nil;
- CMD_Err(erNullVariantError);
- Exit;
- end;
- end;
- end;
- end;
- 3: begin
- NeedToFree := False;
- if Param < IFPSAddrNegativeStackStart then begin
- Result := FGlobalVars.GetItem(Param);
- if Result = nil then begin
- CMD_Err(erOutOfGlobalVarsRange);
- exit;
- end;
- end
- else begin
- Result := FStack.GetItem(Cardinal(Longint(-IFPSAddrStackStart) +
- Longint(FCurrStackBase) + Longint(Param)));
- if Result = nil then begin
- CMD_Err(erOutOfStackRange);
- exit;
- end;
- end;
- if (Result^.FType^.BaseType = btPointer) then begin
- Result := Result^.tPointer;
- if Result = nil then begin
- CMD_Err(erNullPointerException);
- exit;
- end;
- end;
- if Result^.FType^.BaseType = btVariant then begin
- Result := Result^.tvariant;
- if Result = nil then begin
- CMD_Err(erNullPointerException);
- exit;
- end;
- if Result^.FType = nil then
- begin
- Result := nil;
- CMD_Err(erNullVariantError);
- Exit;
- end;
- end;
- if (Result^.FType^.BaseType <> btRecord) and (Result^.FType^.BaseType <> btArray) then begin
- CMD_Err(erInvalidType);
- Result := nil;
- exit;
- end;
- if not ReadLong(Param) then begin
- CMD_Err(erOutOfRange);
- Result := nil;
- exit;
- end;
- if Param < IFPSAddrNegativeStackStart then begin
- Tmp := FGlobalVars.GetItem(Param);
- if Tmp = nil then begin
- CMD_Err(erOutOfGlobalVarsRange);
- exit;
- end;
- end
- else begin
- Tmp := FStack.GetItem(Cardinal(Longint(-IFPSAddrStackStart) + Longint(FCurrStackBase) + Longint(Param)));
- if Tmp = nil then begin
- CMD_Err(erOutOfStackRange);
- exit;
- end;
- end;
- case Tmp^.FType^.BaseType of
- btu8: Param := Tmp^.tu8;
- bts8: Param := Tmp^.ts8;
- btu16: Param := Tmp^.tu16;
- bts16: Param := Tmp^.ts16;
- btu32: Param := Tmp^.tu32;
- bts32: Param := Tmp^.ts32;
- else
- CMD_Err(ErTypeMismatch);
- exit;
- end;
-
- if (Result^.trecord = nil) or (Param >= pbtrecord(Result^.trecord)^.FieldCount) then begin
- CMD_Err(erOutofRecordRange);
- Result := nil;
- exit;
- end;
- Result := pbtrecord(Result^.trecord)^.Fields[Param];
- if UsePointer then
- begin
- if Result^.FType^.BaseType = btPointer then begin
- Result := Result^.tPointer;
- if Result = nil then begin
- CMD_Err(erNullPointerException);
- exit;
- end;
- end;
- if Result^.FType^.BaseType = btVariant then begin
- if Result = nil then begin
- CMD_Err(erNullPointerException);
- exit;
- end;
- if Result^.FType = nil then
- begin
- Result := nil;
- CMD_Err(erNullVariantError);
- Exit;
- end;
- end;
- end;
- end;
- else
- Result := nil;
- end;
- end;
-
- procedure TIFPSExec.DoMinus(Vd: PIfVariant);
- begin
- case Vd^.FType^.BaseType of
- btU8: Vd^.tu8 := -Vd^.tu8;
- btU16: Vd^.tu8 := -Vd^.tu16;
- btU32: Vd^.tu8 := -Vd^.tu32;
- btS8: Vd^.tS8 := -Vd^.tS8;
- btS16: Vd^.ts16 := -Vd^.ts16;
- btS32: Vd^.ts32 := -Vd^.ts32;
- btSingle: Vd^.tsingle := - vd^.tsingle;
- btDouble: Vd^.tdouble := -vd^.tdouble;
- btExtended: Vd^.textended := -vd^.textended;
- else
- CMD_Err(erTypeMismatch);
- end;
- end;
-
- procedure TIFPSExec.DoBooleanNot(Vd: PIfVariant);
- begin
- case Vd^.FType^.BaseType of
- btU8: Vd^.tu8 := TbtU8(Vd^.tu8 = 0);
- btS8: Vd^.tS8 := TbtS8(Vd^.tS8 = 0);
- btU16: Vd^.tu16 := TbtU16(Vd^.tu16 = 0);
- btS16: Vd^.ts16 := TbtS16(Vd^.ts16 = 0);
- btU32: Vd^.tu32 := TbtU32(Vd^.tu32 = 0);
- btS32: Vd^.ts32 := TbtS32(Vd^.ts32 = 0);
- else
- CMD_Err(erTypeMismatch);
- end;
- end;
-
- function TIFPSExec.RunScript: Boolean;
- var
- CalcType: Cardinal;
- Vd, Vs, v3: PIfVariant;
- vdFree, vsFree: LongBool;
- p: Cardinal;
- P2: Longint;
- u: PIFProcRec;
- Cmd: Cardinal;
- I: Longint;
- pp: PIFPSExceptionHandler;
- FExitPoint: Cardinal;
-
- begin
- FExitPoint := Cardinal(-1);
- for i := FExceptionStack.Count -1 downto 0 do
- begin
- pp := FExceptionStack.GetItem(i);
- Dispose(pp);
- end;
- FExceptionStack.Clear;
- ExceptionProc(Cardinal(-1), Cardinal(-1), erNoError, '');
- RunScript := True;
- case FStatus of
- isLoaded: begin
- if FMainProc = Cardinal(-1) then
- begin
- RunScript := False;
- exit;
- end;
- FStatus := isRunning;
- FCurrProc := FProcs.GetItem(FMainProc);
- if FCurrProc^.ExternalProc then begin
- CMD_Err(erNoMainProc);
- FStatus := isLoaded;
- exit;
- end;
- FCurrStackBase := Cardinal(-1);
- FCurrentPosition := 0;
- end;
- isPaused: begin
- FStatus := isRunning;
- end;
- else begin
- RunScript := False;
- exit;
- end;
- end;
- RunLine;
- repeat
- FStatus := isRunning;
- while FStatus = isRunning do begin
- if not ReadByte(Cmd) then
- CMD_Err(erOutOfRange) // Error
- else begin
- if Cmd = CM_CA then begin // Calc and assigning are needed most and have priority
- if not ReadByte(CalcType) then begin
- CMD_Err(erOutOfRange);
- break;
- end;
- Vd := ReadVariable(vdFree, True);
- if Vd = nil then
- break;
- if vdFree then begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vd);
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end;
- Vs := ReadVariable(vsFree, True);
- if Vs = nil then
- break;
- if not DoCalc(Vd, Vs, CalcType) then Break;
- if vsFree then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- end
- else if Cmd = CM_A then begin // Calc and assigning are needed most and have priority
- Vd := ReadVariable(vdFree, False);
- if Vd = nil then
- break;
- if vdFree then begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vd);
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end;
- if vd^.FType^.BaseType = btPointer then
- begin
- vd := vd^.tPointer;
- if vd = nil then
- begin
- CMD_Err(erNullPointerException);
- Break;
- end;
- end;
- Vs := ReadVariable(vsFree, False);
- if Vs = nil then
- break;
- if vs^.FType^.BaseType = btPointer then begin
- v3 := vs^.tPointer;
- if v3 = nil then begin
- if vsFree then
- begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- end;
- CMD_Err(erNullPointerException);
- Break;
- end;
- vs := v3;
- end;
- if not SetVariantValue(Vd, Vs) then
- begin
- if vsFree then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- cmd_err(erTypeMismatch);
- Break;
- end;
- if vsFree then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- end
- else
- case Cmd of
- CM_P: begin
- Vs := ReadVariable(vsFree, True);
- if Vs = nil then
- break;
- if vsFree then begin
- FStack.Add(Vs);
- end
- else begin
- Vd := CreateVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs^.FType);
- SetVariantValue(Vd, Vs);
- FStack.Add(Vd);
- end;
- end;
- CM_PV: begin
- Vs := ReadVariable(vsFree, False);
- if vs^.FType^.BaseType = btPointer then
- begin
- vs := vs^.tPointer;
- if vs = nil then
- begin
- CMD_Err(erNullPointerException);
- break;
- end;
- end;
-
- if Vs = nil then
- break;
- if vsFree then begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end
- else begin
- Inc(Vs^.RefCount);
- FStack.Add(Vs);
- end;
- end;
- CM_PO: begin
- if FStack.Count = 0 then begin
- CMD_Err(erOutOfStackRange);
- break;
- end;
- Vs := FStack.GetItem(FStack.Count - 1);
- FStack.Delete(FStack.Count - 1);
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- end;
- Cm_C: begin
- if not ReadLong(p) then begin
- CMD_Err(erOutOfRange);
- break;
- end;
- if p >= FProcs.Count then begin
- CMD_Err(erOutOfProcRange);
- break;
- end;
- u := FProcs.GetItem(p);
- if u^.ExternalProc then begin
- if not u^.ProcPtr(Self, u, FGlobalVars, FStack) then
- CMD_Err(erCouldNotCallProc);
- end
- else begin
- Vd := CreateVariant({$IFNDEF NOSMARTMM}MM,
- {$ENDIF}@ReturnAddressType);
- Vd^.treturnaddress.ProcNo := FCurrProc;
- Vd^.treturnaddress.Position := FCurrentPosition;
- Vd^.treturnaddress.StackBase := FCurrStackBase;
- FStack.Add(Vd);
-
- FCurrStackBase := FStack.Count - 1;
- FCurrProc := u;
- FCurrentPosition := 0;
- end;
- end;
- Cm_G: begin
- if not ReadLong(p) then begin
- CMD_Err(erOutOfRange);
- break;
- end;
- FCurrentPosition := FCurrentPosition + p;
- end;
- Cm_CG: begin
- if not ReadLong(p) then begin
- CMD_Err(erOutOfRange);
- break;
- end;
- Vs := ReadVariable(vsFree, True);
- if Vs = nil then
- break;
- if vsFree then begin
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end;
- case Vs^.FType^.BaseType of
- btU8: vdFree := Vs^.tu8 <> 0;
- btS8: vdFree := Vs^.tS8 <> 0;
- btU16: vdFree := Vs^.tu16 <> 0;
- btS16: vdFree := Vs^.ts16 <> 0;
- btU32: vdFree := Vs^.tu32 <> 0;
- btS32: vdFree := Vs^.ts32 <> 0;
- else begin
- CMD_Err(erInvalidType);
- break;
- end;
- end;
- if vdFree then
- FCurrentPosition := FCurrentPosition + p;
- end;
- Cm_CNG: begin
- if not ReadLong(p) then begin
- CMD_Err(erOutOfRange);
- break;
- end;
- Vs := ReadVariable(vsFree, True);
- if Vs = nil then
- break;
- if vsFree then begin
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end;
- case Vs^.FType^.BaseType of
- btU8: vdFree := Vs^.tu8 = 0;
- btS8: vdFree := Vs^.tS8 = 0;
- btU16: vdFree := Vs^.tu16 = 0;
- btS16: vdFree := Vs^.ts16 = 0;
- btU32: vdFree := Vs^.tu32 = 0;
- btS32: vdFree := Vs^.ts32 = 0;
- else begin
- CMD_Err(erInvalidType);
- break;
- end;
- end;
- if vdFree then
- FCurrentPosition := FCurrentPosition + p;
- end;
- Cm_R: begin
- FExitPoint := FCurrentPosition -1;
- P2 := 0;
- if FExceptionStack.Count > 0 then
- begin
- pp := FExceptionStack.GetItem(FExceptionStack.Count -1);
- if pp^.BasePtr >= FCurrStackBase then
- begin
- if pp^.StackSize < FStack.Count then
- begin
- for p := Longint(FStack.count) -1 downto Longint(pp^.StackSize) do
- begin
- DisposeVariant({$IFNDEF SMARTMM}mm, {$ENDIF}FStack.GetItem(p));
- FStack.Delete(p);
- end;
- end;
- FCurrStackBase := pp^.BasePtr;
- if pp^.FinallyOffset <> Cardinal(-1) then
- begin
- FCurrentPosition := pp^.FinallyOffset;
- pp^.FinallyOffset := cardinal(-1);
- p2 := 1;
- end else if pp^.Finally2Offset <> Cardinal(-1) then
- begin
- FCurrentPosition := pp^.Finally2Offset;
- pp^.Finally2Offset := cardinal(-1);
- p2 := 1;
- end;
- end;
- end;
- if p2 = 0 then
- begin
- FExitPoint := Cardinal(-1);
- Vs := FStack.GetItem(FCurrStackBase);
- if Vs = nil then begin
- FStatus := isLoaded;
- break;
- end;
- for P2 := FStack.Count - 1 downto FCurrStackBase + 1 do begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM,
- {$ENDIF}FStack.GetItem(P2));
- FStack.Delete(P2);
- end;
- FStack.Delete(FCurrStackBase);
- FCurrProc := Vs^.treturnaddress.ProcNo;
- FCurrentPosition := Vs^.treturnaddress.Position;
- FCurrStackBase := Vs^.treturnaddress.StackBase;
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- if FCurrProc = nil then begin
- FStatus := isPaused;
- break;
- end;
- end;
- end;
- Cm_ST: begin
- if not ReadLong(p) or not ReadLong(Cardinal(P2)) then begin
- CMD_Err(erOutOfRange);
- break;
- end;
- Cardinal(P2) := FCurrStackBase + Cardinal(P2);
- if p >= FTypes.Count then begin
- CMD_Err(erInvalidType);
- break;
- end;
- if Cardinal(P2) >= FStack.Count then begin
- CMD_Err(erOutOfStackRange);
- break;
- end;
- Vs := FStack.GetItem(Cardinal(P2));
- if Vs^.FType = @ReturnAddressType then begin
- CMD_Err(erInvalidType);
- break;
- end;
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- Vs := CreateVariant({$IFNDEF NOSMARTMM}MM,
- {$ENDIF}FTypes.GetItem(p));
- FStack.SetItem(Cardinal(P2), Vs);
- end;
- Cm_Pt: begin
- if not ReadLong(p) then begin
- CMD_Err(erInvalidType);
- break;
- end;
- Vs := CreateVariant({$IFNDEF NOSMARTMM}MM,
- {$ENDIF}FTypes.GetItem(p));
- if Vs = nil then begin
- CMD_Err(erInvalidType);
- break;
- end;
- FStack.Add(Vs);
- end;
- CM_CO: begin
- if not ReadByte(CalcType) then begin
- CMD_Err(erOutOfRange);
- break;
- end;
- v3 := ReadVariable(vsFree, True);
- if v3 = nil then
- break;
- if vsFree then begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}v3);
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end;
- Vs := ReadVariable(vsFree, False);
- if Vs = nil then
- break;
- if vs^.FType^.BaseType = btPointer then begin
- vs := vs^.tPointer;
- if vs = nil then begin
- CMD_Err(erNullPointerException);
- break;
- end;
- end;
- if vs^.FType^.BaseType = btVariant then begin
- vs := vs^.tvariant;
- end;
- Vd := ReadVariable(vdFree, False);
- if vd^.FType^.BaseType = btPointer then begin
- vd := vs^.tPointer;
- if vd = nil then begin
- CMD_Err(erNullPointerException);
- break;
- end;
- end;
- if vd^.FType^.BaseType = btVariant then begin
- vd := vd^.tvariant;
- end;
- if Vd = nil then begin
- if vsFree then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- break;
- end;
- DoBooleanCalc(Vs, Vd, v3, CalcType);
- if vsFree then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- if vdFree then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vd);
- end;
- Cm_cv: begin
- Vd := ReadVariable(vdFree, True);
- if Vd = nil then
- break;
- if (Vd^.FType^.BaseType <> btU32) and (Vd^.FType^.BaseType <>
- btS32) then begin
- if vdFree then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vd);
- CMD_Err(ErTypeMismatch);
- break;
- end;
- p := Vd^.tu32;
- if vdFree then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vd);
- if (p >= FProcs.Count) or (p = FMainProc) then begin
- CMD_Err(erOutOfProcRange);
- break;
- end;
- u := FProcs.GetItem(p);
- if u^.ExternalProc then begin
- if not u^.ProcPtr(Self, u, FGlobalVars, FStack) then
- CMD_Err(erCouldNotCallProc);
- end
- else begin
- Vs := CreateVariant({$IFNDEF NOSMARTMM}MM,
- {$ENDIF}@ReturnAddressType);
- Vs^.treturnaddress.ProcNo := FCurrProc;
- Vs^.treturnaddress.Position := FCurrentPosition;
- Vs^.treturnaddress.StackBase := FCurrStackBase;
- FStack.Add(Vs);
- FCurrStackBase := FStack.Count - 1;
- FCurrProc := u;
- FCurrentPosition := 0;
- end;
- end;
- cm_sp: begin
- Vd := ReadVariable(vdFree, False);
- if Vd = nil then
- break;
- if vdFree then begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vd);
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end;
- if Vd^.FType^.BaseType <> btPointer then begin
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end;
- if (Vd^.tPointer <> nil) then
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vd^.tPointer);
- Vs := ReadVariable(vsFree, False);
- if Vs = nil then begin
- Vd^.tPointer := nil;
- end else if vsFree then begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vs);
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end else begin
- Inc(Vs^.RefCount);
- Vd^.tPointer := Vs;
- end;
- end;
- cm_bn: begin
- Vd := ReadVariable(vdFree, False);
- if Vd = nil then
- break;
- if vdFree then begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vd);
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end;
- DoBooleanNot(Vd);
- end;
- cm_vm: begin
- Vd := ReadVariable(vdFree, False);
- if Vd = nil then
- break;
- if vdFree then begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vd);
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end;
- DoMinus(Vd);
- end;
- cm_sf:
- begin
- vd := ReadVariable(vdFree, True);
- if vd = nil then
- break;
- if vdFree then
- begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}vd);
- CMD_Err(erInvalidOpcodeParameter);
- break;
- end;
- if not ReadByte(p) then
- begin
- CMD_Err(erOutOfRange);
- Break;
- end;
- case Vd^.FType^.BaseType of
- btU8: vdFree := Vd^.tu8 <> 0;
- btS8: vdFree := Vd^.tS8 <> 0;
- btU16: vdFree := Vd^.tu16 <> 0;
- btS16: vdFree := Vd^.ts16 <> 0;
- btU32: vdFree := Vd^.tu32 <> 0;
- btS32: vdFree := Vd^.ts32 <> 0;
- else begin
- CMD_Err(erInvalidType);
- break;
- end;
- end;
- if p <> 0 then
- FJumpFlag := not vdFree
- else
- FJumpFlag := vdFree;
- end;
- cm_fg:
- begin
- if not ReadLong(p) then begin
- CMD_Err(erOutOfRange);
- break;
- end;
- if FJumpFlag then
- FCurrentPosition := FCurrentPosition + p;
- end;
- cm_puexh:
- begin
- New(pp);
- pp^.BasePtr :=FCurrStackBase;
- pp^.StackSize := FStack.Count;
- if not ReadLong(pp^.FinallyOffset) then begin
- CMD_Err(erOutOfRange);
- Dispose(pp);
- Break;
- end;
- if not ReadLong(pp^.ExceptOffset) then begin
- CMD_Err(erOutOfRange);
- Dispose(pp);
- Break;
- end;
- if not ReadLong(pp^.Finally2Offset) then begin
- CMD_Err(erOutOfRange);
- Dispose(pp);
- Break;
- end;
- if not ReadLong(pp^.EndOfBlock) then begin
- CMD_Err(erOutOfRange);
- Dispose(pp);
- Break;
- end;
- if pp^.FinallyOffset <> Cardinal(-1) then
- pp^.FinallyOffset := pp^.FinallyOffset + FCurrentPosition;
- if pp^.ExceptOffset <> Cardinal(-1) then
- pp^.ExceptOffset := pp^.ExceptOffset + FCurrentPosition;
- if pp^.Finally2Offset <> Cardinal(-1) then
- pp^.Finally2Offset := pp^.Finally2Offset + FCurrentPosition;
- if pp^.EndOfBlock <> Cardinal(-1) then
- pp^.EndOfBlock := pp^.EndOfBlock + FCurrentPosition;
- if ((pp^.FinallyOffset <> cardinal(-1)) and (pp^.FinallyOffset >= FCurrProc^.Length)) or
- ((pp^.ExceptOffset <> cardinal(-1)) and (pp^.ExceptOffset >= FCurrProc^.Length)) or
- ((pp^.Finally2Offset <> cardinal(-1)) and (pp^.Finally2Offset >= FCurrProc^.Length)) or
- ((pp^.EndOfBlock <> cardinal(-1)) and (pp^.EndOfBlock >= FCurrProc^.Length)) then
- begin
- CMD_Err(ErOutOfRange);
- Dispose(pp);
- Break;
- end;
- FExceptionStack.Add(pp);
- end;
- cmd_poexh:
- begin
- if not ReadByte(p) then
- begin
- CMD_Err(ErOutOfRange);
- Break;
- end;
- case p of
- 2:
- begin
- ExceptionProc(Cardinal(-1), Cardinal(-1), erNoError, '');
- pp := FExceptionStack.GetItem(FExceptionStack.Count -1);
- if pp = nil then begin
- cmd_err(ErOutOfRange);
- Break;
- end;
- if pp^.Finally2Offset <> cardinal(-1) then
- begin
- FCurrentPosition := pp^.Finally2Offset;
- pp^.Finally2Offset := cardinal(-1);
- end else begin
- p := pp^.EndOfBlock;
- Dispose(pp);
- FExceptionStack.Delete(FExceptionStack.Count -1);
- if FExitPoint <> Cardinal(-1) then
- begin
- FCurrentPosition := FExitPoint;
- end else begin
- FCurrentPosition := p;
- end;
- end;
- end;
- 0:
- begin
- pp := FExceptionStack.GetItem(FExceptionStack.Count -1);
- if pp = nil then begin
- cmd_err(ErOutOfRange);
- Break;
- end;
- if pp^.FinallyOffset <> cardinal(-1) then
- begin
- FCurrentPosition := pp^.FinallyOffset;
- pp^.FinallyOffset := cardinal(-1);
- end else if pp^.Finally2Offset <> cardinal(-1) then
- begin
- FCurrentPosition := pp^.Finally2Offset;
- pp^.ExceptOffset := cardinal(-1);
- end else begin
- p := pp^.EndOfBlock;
- Dispose(pp);
- FExceptionStack.Delete(FExceptionStack.Count -1);
- if ExEx <> eNoError then
- begin
- ExceptionProc(ExProc, ExPos, ExEx, ExParam);
- end else
- if FExitPoint <> Cardinal(-1) then
- begin
- FCurrentPosition := FExitPoint;
- end else begin
- FCurrentPosition := p;
- end;
- end;
- end;
- 1:
- begin
- pp := FExceptionStack.GetItem(FExceptionStack.Count -1);
- if pp = nil then begin
- cmd_err(ErOutOfRange);
- Break;
- end;
- if (ExEx <> ENoError) and (pp^.ExceptOffset <> cardinal(-1)) then
- begin
- FCurrentPosition := pp^.ExceptOffset;
- pp^.ExceptOffset := cardinal(-1);
- end else if (pp^.Finally2Offset <> cardinal(-1)) then
- begin
- FCurrentPosition := pp^.Finally2Offset;
- pp^.Finally2Offset := cardinal(-1);
- end else begin
- p := pp^.EndOfBlock;
- Dispose(pp);
- FExceptionStack.Delete(FExceptionStack.Count -1);
- if ExEx <> eNoError then
- begin
- ExceptionProc(ExProc, ExPos, ExEx, ExParam);
- end else
- if FExitPoint <> Cardinal(-1) then
- begin
- FCurrentPosition := FExitPoint;
- end else begin
- FCurrentPosition := p;
- end;
- end;
- end;
- 3:
- begin
- pp := FExceptionStack.GetItem(FExceptionStack.Count -1);
- if pp = nil then begin
- cmd_err(ErOutOfRange);
- Break;
- end;
- p := pp^.EndOfBlock;
- Dispose(pp);
- FExceptionStack.Delete(FExceptionStack.Count -1);
- if ExEx <> eNoError then
- begin
- ExceptionProc(ExProc, ExPos, ExEx, ExParam);
- end else
- if FExitPoint <> Cardinal(-1) then
- begin
- FCurrentPosition := FExitPoint;
- end else begin
- FCurrentPosition := p;
- end;
- end;
- end;
- end;
- else
- CMD_Err(erInvalidOpcode); // Error
- end;
- RunLine;
- end;
- end;
- until (FExceptionStack.Count = 0) or (Fstatus <> IsRunning);
- if FStatus = isLoaded then begin
- for I := 0 to Longint(FStack.Count) - 1 do begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}FStack.GetItem(I));
- end;
- FStack.Clear;
- if FCallCleanup then Cleanup;
- end;
- end;
-
- procedure TIFPSExec.Stop;
- var
- I: Longint;
- begin
- if FStatus = isRunning then
- FStatus := isLoaded
- else if FStatus = isPaused then begin
- FStatus := isLoaded;
- for I := 0 to Longint(FStack.Count) - 1 do begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}FStack.GetItem(I));
- end;
- FStack.Clear;
- end;
- end;
-
- function TIFPSExec.ReadByte(var b: Cardinal): Boolean;
- begin
- if FCurrentPosition < FCurrProc.Length then begin
- b := FCurrProc.Data^[FCurrentPosition];
- Inc(FCurrentPosition);
- Result := True;
- end
- else
- Result := False;
- end;
-
- function TIFPSExec.ReadLong(var b: Cardinal): Boolean;
- begin
- if FCurrentPosition + 3 < FCurrProc.Length then begin
- b := Cardinal((@FCurrProc.Data^[FCurrentPosition])^);
- Inc(FCurrentPosition, 4);
- Result := True;
- end
- else
- Result := False;
- end;
-
- function TIFPSExec.RunProc(Params: TIfList; ProcNo: Cardinal): Boolean;
- var
- I, I2: Integer;
- Vd: PIfVariant;
- Cp: PIFProcRec;
- oldStatus: TIFStatus;
- begin
- if FStatus <> isNotLoaded then begin
- if ProcNo >= FProcs.Count then begin
- Result := False;
- exit;
- end;
- if PIFProcRec(FProcs.GetItem(ProcNo))^.ExternalProc then begin
- Result := False;
- exit;
- end;
- for I := 0 to Params.Count - 1 do begin
- vd := Params.GetItem(I);
- if vd = nil then
- begin
- Result := False;
- exit;
- end;
- FStack.Add(Params.GetItem(I));
- end;
- Vd := CreateVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}@ReturnAddressType);
- Cp := FCurrProc;
- Vd^.treturnaddress.ProcNo := nil;
- Vd^.treturnaddress.Position := FCurrentPosition;
- Vd^.treturnaddress.StackBase := FCurrStackBase;
- I := FStack.Count;
- FStack.Add(Vd);
- FCurrStackBase := FStack.Count - 1;
- FCurrProc := FProcs.GetItem(ProcNo);
- FCurrentPosition := 0;
- oldStatus := FStatus;
- FStatus := isPaused;
- Result := RunScript;
- if FStack.Count > Cardinal(I) then
- begin
- vd := FStack.GetItem(I);
- if (vd <> nil) and (vd^.FType = @ReturnAddressType) then begin
- for i2 := FStack.Count - 1 downto I + 1 do begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}FStack.GetItem(i2));
- FStack.Delete(i2);
- end;
- FStack.Delete(I);
- FCurrentPosition := Vd^.treturnaddress.Position;
- FCurrStackBase := Vd^.treturnaddress.StackBase;
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}Vd);
- end;
- end;
- for I := Params.Count - 1 downto 0 do begin
- FStack.Delete(FStack.Count - 1);
- end;
- FStatus := oldStatus;
- FCurrProc := Cp;
- end else begin
- Result := False;
- end;
- end;
-
- function TIFPSExec.CreateIntegerVariant(FType: PIFTypeRec; Value: Longint): PIfVariant;
- begin
- Result := CreateVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}FType);
- if Result <> nil then begin
- case FType^.BaseType of
- btU8: Result^.tu8 := Value;
- btS8: Result^.tS8 := Value;
- btU16: Result^.tu16 := Value;
- btS16: Result^.ts16 := Value;
- btU32: Result^.tu32 := Value;
- btS32: Result^.ts32 := Value;
- end;
- end;
- end;
-
- function TIFPSExec.CreateStringVariant(FType: PIFTypeRec; const Value: string): PIfVariant;
- begin
- Result := CreateVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}FType);
- if Result <> nil then begin
- case FType^.BaseType of
- btPChar, btString: begin
- TbtString(Result^.tstring) := Value;
- end;
- end;
- end;
- end;
-
- function TIFPSExec.CreateFloatVariant(FType: PIFTypeRec; Value: Extended): PIfVariant;
- begin
- Result := CreateVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}FType);
- if Result <> nil then begin
- case FType^.BaseType of
- btSingle: Result^.tsingle := Value;
- btDouble: Result^.tdouble := Value;
- btExtended: Result^.textended := Value;
- end;
- end;
- end;
-
- function TIFPSExec.FindType2(BaseType: TIFPSBaseType): PIFTypeRec;
- var
- l: Cardinal;
- begin
- FindType2 := FindType(0, BaseType, l);
-
- end;
-
- function TIFPSExec.FindType(StartAt: Cardinal; BaseType: TIFPSBaseType; var l: Cardinal): PIFTypeRec;
- var
- I: Integer;
- n: PIFTypeRec;
- begin
- for I := StartAt to FTypes.Count - 1 do begin
- n := FTypes.GetItem(I);
- if n^.BaseType = BaseType then begin
- l := I;
- Result := n;
- exit;
- end;
- end;
- Result := nil;
- end;
-
- function TIFPSExec.GetTypeNo(l: Cardinal): PIFTypeRec;
- begin
- Result := FTypes.GetItem(l);
- end;
-
- function TIFPSExec.GetProc(const Name: string): Cardinal;
- var
- MM,
- I: Longint;
- n: PIFProcRec;
- begin
- MM := MakeHash(Name);
- for I := 0 to FProcs.Count - 1 do begin
- n := FProcs.GetItem(I);
- if (not n^.ExternalProc) and (Length(n^.ExportName) <> 0) and (n^.ExportNameHash = MM) and (n^.ExportName = Name) then begin
- Result := I;
- exit;
- end;
- end;
- Result := Cardinal(-1);
- end;
-
- function TIFPSExec.GetType(const Name: string): Cardinal;
- var
- MM,
- I: Longint;
- n: PIFTypeRec;
- begin
- MM := MakeHash(Name);
- for I := 0 to FTypes.Count - 1 do begin
- n := FTypes.GetItem(I);
- if (Length(n^.ExportName) <> 0) and (n^.ExportNameHash = MM) and (n^.ExportName = Name) then begin
- Result := I;
- exit;
- end;
- end;
- Result := Cardinal(-1);
- end;
-
-
- procedure TIFPSExec.AddResource(Proc, P: Pointer);
- var
- Temp: PIFPSResource;
- begin
- New(Temp);
- Temp^.Proc := Proc;
- Temp^.P := p;
- FResources.Add(temp);
- end;
-
- procedure TIFPSExec.DeleteResource(P: Pointer);
- var
- i: Longint;
- begin
- for i := Longint(FResources.Count) -1 downto 0 do
- begin
- if PIFPSResource(FResources.GetItem(I))^.P = P then
- begin
- FResources.Delete(I);
- exit;
- end;
- end;
- end;
-
- function TIFPSExec.FindProcResource(Proc: Pointer): Pointer;
- var
- I: Longint;
- temp: PIFPSResource;
- begin
- for i := Longint(FResources.Count) -1 downto 0 do
- begin
- temp := FResources.GetItem(I);
- if temp^.Proc = proc then
- begin
- Result := Temp^.P;
- exit;
- end;
- end;
- Result := nil;
- end;
-
- function TIFPSExec.IsValidResource(Proc, P: Pointer): Boolean;
- var
- i: Longint;
- temp: PIFPSResource;
- begin
- for i := 0 to Longint(FResources.Count) -1 do
- begin
- temp := FResources.GetItem(i);
- if temp^.p = p then begin
- result := temp^.Proc = Proc;
- exit;
- end;
- end;
- result := false;
- end;
-
- function TIFPSExec.FindProcResource2(Proc: Pointer;
- var StartAt: Longint): Pointer;
- var
- I: Longint;
- temp: PIFPSResource;
- begin
- if StartAt > longint(FResources.Count) -1 then
- StartAt := longint(FResources.Count) -1;
- for i := StartAt downto 0 do
- begin
- temp := FResources.GetItem(I);
- if temp^.Proc = proc then
- begin
- Result := Temp^.P;
- StartAt := i -1;
- exit;
- end;
- end;
- StartAt := -1;
- Result := nil;
- end;
-
- procedure TIFPSExec.RunLine;
- begin
- if @FOnRunLine <> nil then
- FOnRunLine(Self);
- end;
-
- procedure TIFPSExec.CMD_Err2(EC: TIFError; const Param: string);
- var
- l: Longint;
- C: Cardinal;
- begin
- C := Cardinal(-1);
- for l := 0 to FProcs.Count - 1 do begin
- if FProcs.GetItem(l) = FCurrProc then begin
- C := l;
- break;
- end;
- end;
- ExceptionProc(C, FCurrentPosition, EC, Param);
- end;
-
- procedure FreePIFVariantList({$IFNDEF NOSMARTMM}MM: Pointer; {$ENDIF}List: TIfList);
- var
- I: Longint;
- begin
- for I := List.Count -1 downto 0 do
- begin
- DisposeVariant({$IFNDEF NOSMARTMM}MM, {$ENDIF}List.GetItem(I));
- end;
- List.Free;
- end;
- procedure TIFPSExec.AddSpecialProcImport(const FName: string;
- P: TIFPSOnSpecialProcImport; Tag: Pointer);
- var
- N: PSpecialProc;
- begin
- New(n);
- n^.P := P;
- N^.Name := FName;
- n^.namehash := MakeHash(FName);
- n^.Tag := Tag;
- FSpecialProcList.Add(n);
- end;
-
- function TIFPSExec.GetVar(const Name: string): Cardinal;
- var
- l: Longint;
- h: longint;
- begin
- h := makehash(Name);
- for l := FExportedVars.Count - 1 downto 0 do
- begin
- if (PIFPSExportedVar(FexportedVars.GetItem(L))^.FNameHash = h) and(PIFPSExportedVar(FexportedVars.GetItem(L))^.FName=Name) then
- begin
- Result := L;
- exit;
- end;
- end;
- Result := Cardinal(-1);
- end;
-
- function TIFPSExec.GetVarNo(C: Cardinal): PIFVariant;
- begin
- Result := FGlobalVars.GetItem(c);
- end;
-
- function TIFPSExec.GetVar2(const Name: string): PIFVariant;
- begin
- Result := GetVarNo(GetVar(Name));
- end;
-
- function TIFPSExec.GetProcNo(C: Cardinal): PIFProcRec;
- begin
- Result := FProcs.GetItem(c);
- end;
-
- end.
-
-