home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kompon / d23456 / CAJSCRPT.ZIP / ifpasscript / ifspas.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-08  |  269KB  |  8,070 lines

  1. {
  2. IfPasScript
  3.  
  4. version: 2.62
  5. Last stable version: 2.62
  6.  
  7. Features:
  8.  - Support for standard types: Byte, Shortint, Char, Word, SmallInt,
  9.    Cardinal, Longint, Integer, String, Real, Double, Single, Extended,
  10.    Comp, Boolean, Array, Record, Variant
  11.  - Classes (Declared inside or outside script)
  12.  - Variables, Constants
  13.  - Standard statements: Begin/End, If/Then/Else, For/To/Downto/Do,
  14.    Case x Of, Repeat/Until, While, With, Uses, Try/Except/Finally,
  15.  - Exit, Continue, Break
  16.  - Functions (Declared inside or outside script)
  17.  - Array of Const parameters, Var parameters
  18.  - External modules (attached script engines)
  19.  - A lot of libraries like Databases, Forms, Dll calls, Delphi calls...
  20.  - Documentation and examples
  21. }
  22. unit ifspas;
  23. {$I ifs_def.inc}
  24. interface
  25. uses
  26.   ifs_var, ifs_utl{$IFNDEF NOCLASSES}, ifs_obj{$ENDIF}{$IFDEF VARIANTSUNIT}, Variants{$ENDIF};
  27. const
  28.   Version = '2.62';
  29.  
  30. type
  31.   TIfPasScript = class;
  32.   TIFSError = record
  33.     ErrorCode: TIfPasScriptError;
  34.     ErrorPosition: Longint;
  35.     ErrorParam: String;
  36.     ErrorModule: string;
  37.   end;
  38.   TCs2PascalScript = TIfPasScript;
  39.   TOnUses = function(id: Pointer; Sender: TIfPasScript; Name: string): TIfPasScriptError;
  40.   TOnRunLine = function(id: Pointer; Sender: TIfPasScript; Position: Longint): TIfPasScriptError;
  41.   TResourceFree = procedure(id: Pointer; Data: Pointer);
  42.   TOnExternal = function(id: Pointer; Sender: TIFPasScript; const Param, FuncName: string; Func: PProcedure): Boolean;
  43.   TPerformType = (PtSet, ptMinus, PtPlus, PtMul, ptDiv, PtIntDiv, PtIntMod, PtAnd, ptOr, ptXor, PtShl, PtShr, PtGreater, PtLess,PtEqual, PtNotEqual, PtGreaterEqual, PtLessEqual{$IFNDEF NOCLASSES}, ptIs, ptAs{$ENDIF});
  44.   TIfPasScript = class
  45.   Private
  46.     FUses: TIfStringList;
  47.     FFreeOnCleanup: Boolean;
  48.     FAllocatedResources: TIfList;
  49. {$IFNDEF NOCLASSES}
  50.     CreatedClasses: TIfList;
  51. {$ENDIF}
  52.     Parser: TIfPascalParser;
  53.     FISUnit: Boolean;
  54.     FModuleName: string;
  55.     MainOffset: Longint;
  56.     fId: Pointer;
  57.     FError: TIFSError;
  58.     FOnUses: TOnUses;
  59.     FOnRunLine: TOnRunLine;
  60.     FOnExternal: TOnExternal;
  61.     FBeginNesting: Longint;
  62.     FMaxBeginNesting: Longint;
  63.     FMaxArrayLength: Longint;
  64.     function GetIdentifier(WithList: TIfList; Vars: PVariableManager; Mode: Byte; var w: PIfVariant): Byte;
  65.     {mode 0 = normal; 1 = AsVariable; 2 = asProcPointer}
  66.     function IdentifierExists(AlsoVariables: Boolean; SubVars: PVariableManager; const s: string): Boolean;
  67.     function ProcessVars(Vars: PVariableManager): Boolean;
  68.     function ProcessConsts(Vars: PVariableManager): Boolean;
  69.     function ReadType(Parser: TIfPascalParser; AllowClasses: Boolean; const Name: string): PTypeRec;
  70.     function RunBegin(WithList: TIFList; Vars: PVariableManager; Skip: Boolean): Boolean;
  71.     function Calc(WithList: TIFList; Vars: PVariableManager; res: PIfVariant; StopOn: TIfPasToken; OnlyConst: Boolean): Boolean;
  72.     function DoProc(WithList: TIFList; {$IFNDEF NOCLASSES}Myself: PCreatedClass; {$ENDIF}proc: PProcedure; Vars: PVariableManager): PIfVariant;
  73.     function ReadParams(WithList: TIFList; ProcDef: string; Vars, Params: PVariableManager): Boolean;
  74. {$IFNDEF NOCLASSES}
  75.     function DoClassConstructor(WithList: TIFList; Myclass: PTypeRec; proc: PProcedure; Vars: PVariableManager): PIfVariant;
  76. {$ENDIF}
  77.     function Perform(V1: PIfVariant; v2: PIfVariant; t: TPerformType): Boolean;
  78.     function MakeCompat(v: PIfVariant; FType: PTypeRec): Boolean;
  79.     procedure AddStandard;
  80.     function GetErrorCode: TIfPasScriptError;
  81.     function GetErrorPos: Longint;
  82.     function GetErrorString: string;
  83.     function GetErrorModule: string;
  84.     procedure LoadData;
  85.   protected
  86.     Variables: PVariableManager;
  87.     Types: PTypeManager;
  88.     Procedures: PProcedureManager;
  89.     CurrProc: PProcedure;
  90.     FAttachedOnes: TIfList;
  91.     FLastException: TIFSError;
  92.   Public
  93.     procedure RunError(SE: TIfPasScript; C: TIfPasScriptError);
  94.     procedure RunError2(SE: TIfPasScript; C: TIfPasScriptError; Ext: string);
  95.  
  96.     function GetVariable(const Name: string): PIfVariant;
  97.     function GetFunction(s: string): PProcedure;
  98.     function GetType(const s: string): PTypeRec;
  99.  
  100.     function RemoveFunction(D: PProcedure): Boolean; // does not dispose it
  101.  
  102.     function AddVariable(Name, FType: string; Constant: Boolean): PIfVariant;
  103.     function AddFunction(proc: Pointer; Decl: string; Ext: Pointer): PProcedure;
  104.     function AddType(const Name, Decl: string): PTypeRec;
  105.     function AddTypeEx(Name: string): PTypeRec;
  106. {$IFNDEF NOCLASSES}
  107.     function AddClass(const Name, Decl: string; RegProc: Pointer): PTypeRec;
  108. {$ENDIF}
  109. {$IFDEF VARIANTSUPPORT}
  110.     function CallFunction(P: PProcedure; Params: Array of Variant): Variant;
  111. {$IFNDEF NOCLASSES}
  112.     function CallMethod(P: PProcedure; MySelf: PCreatedClass; Params: Array of Variant): Variant;
  113. {$ENDIF}
  114. {$ENDIF}
  115.  
  116.     {$IFDEF VARIANTSUPPORT}
  117.     function VariantToIFVariant(const v: Variant; Res: PIfVariant): Boolean;
  118.     function IfVariantToVariant(v: PIfVariant; Var res: Variant): Boolean;
  119.     {$ENDIF}
  120.  
  121.     function CopyVariant(p: PIfVariant): PIfVariant;
  122.     function CreateReal(const E: Extended): PIfVariant;
  123.     function CreateString(const s: string): PIfVariant;
  124.     function CreateInteger(I: Longint): PIfVariant;
  125.     function CreateBool(b: Boolean): PIfVariant;
  126.     function CreateVarType(p: PIfVariant): PIfVariant;
  127.  
  128.     procedure Cleanup;
  129.  
  130.     procedure RunScript;
  131.     function RunScriptProc(Func: PProcedure; Parameters: PVariableManager): PIfVariant;
  132. {$IFNDEF NOCLASSES}
  133.     function RunScriptConstructor(FType: PTypeRec; Func: PProcedure; Parameters: PVariableManager): PIfVariant;
  134.     function RunInherited(proc: PProcedure; Params: PVariableManager; res: PIfVariant): TIfPasScriptError;
  135.     function SetProperty(prop, Data: PIfVariant): Boolean;
  136.     function GetProperty(prop: PIfVariant): PIfVariant; // nil = error
  137. {$ENDIF}
  138.  
  139.     function Attach(ScriptEngine: TIfPasScript): Boolean;
  140.     function Attach2(ScriptEngine: TIfPasScript; FreeOnCleanup: Boolean): Boolean;
  141.  
  142.     procedure AddResource(FreeProc: TResourceFree; Data: Pointer);
  143.     procedure RemoveResource(Data: Pointer);
  144.     function IsValidResource(FreeProc: TResourceFree; Data: Pointer): Boolean;
  145.     function FindResource(FreeProc: TResourceFree): Pointer;
  146.  
  147.     procedure SetText(const Data: string);
  148.     procedure SetPData(const Data: string);
  149.     function GetPData(var Data: string): Boolean;
  150.  
  151.     constructor Create(id: Pointer);
  152.     destructor Destroy; Override;
  153.  
  154.     property ModuleName: string read FModuleName write FModuleName;
  155.  
  156.     property IsUnit: Boolean read FIsUnit;
  157.     property OnRunLine: TOnRunLine Read FOnRunLine Write FOnRunLine;
  158.     property OnUses: TOnUses Read FOnUses Write FOnUses;
  159.     property OnExternal: TOnExternal read FOnExternal write FOnExternal;
  160.  
  161.     property ErrorCode: TCs2Error Read GetErrorCode;
  162.     property ErrorPos: Longint Read GetErrorPos;
  163.     property ErrorString: string Read GetErrorString;
  164.     property ErrorModule: string read GetErrorModule;
  165.  
  166.     property MaxBeginNesting: Longint read FMaxBeginNesting write FMaxBeginNesting;
  167.     property MaxArrayLength: Longint read FMaxArrayLength write FMaxArrayLength;
  168.   end;
  169. {$IFNDEF NOCLASSES}
  170. function GetClassVariable(Self: PIfVariant; ProcClass: PIFSClassType; const Name: string; var thevar: PIfVariant; AlsoProtected: Boolean): Boolean;
  171. function GetClassVariable2(Self: PCreatedClass; ProcClass: PIFSClassType; const Name: string; var thevar: PIfVariant; AlsoProtected: Boolean): Boolean;
  172. function GetClassProcedure(Self: PIfVariant; ProcClass: PIFSClassType; const Name: string; var proc: PProcedure; AlsoProtected: Boolean): Boolean;
  173. function GetInheritedProc(CurrProc: PProcedure): PProcedure;
  174. {$ENDIF}
  175.  
  176. procedure RegisterStdLib(p: TIfPasScript; OnlySafe: Boolean);
  177. {If onlysafe is true, All Floating point functions are disabled (cos, sin, tan, round etc)}
  178. {Register all standard functions:}
  179. {
  180. Installs:
  181.   Function StrGet(S : String; I : Integer) : Char;
  182.   Function StrSet(c : Char; I : Integer; var s : String) : Char;
  183.   Function Ord(C : Char) : Byte;
  184.   Function Chr(B : Byte) : Char;
  185.   Function StrToInt(s : string;def : Longint) : Longint;
  186.   Function IntToStr(i : Longint) : String;
  187.   Function Uppercase(s : string) : string;
  188.   Function Lowercase(s : string) : string;
  189.   Function Trim(s : string) : string;
  190.   Function Copy(S : String; Indx, Count : Integer) : String;
  191.   Procedure Delete(var S : String; Indx, Count : Integer);
  192.   Function Pos(SubStr, S : String) : Integer;
  193.   Procedure Insert(Source : String; var Dest : String; Indx : Integer);
  194.   Function Length(s : String) : Longint;
  195.   procedure SetLength(var S: String; L: Longint);
  196.   Function Sin(e : Extended) : Extended;
  197.   Function Cos(e : Extended) : Extended;
  198.   Function Sqrt(e : Extended) : Extended;
  199.   Function Round(e : Extended) : Longint;
  200.   Function Trunc(e : Extended) : Longint;
  201.   Function Int(e : Extended) : Longint;
  202.   Function Pi : Extended;
  203.   Function Abs(e : Extended) : Extended;
  204.   Function Sqrt(e : Extended) : Extended;
  205.   Function FloatToStr(e : Extended) : String;
  206.   Function Padl(s : string;I : longInt) : string;
  207.   Function Padr(s : string;I : longInt) : string;
  208.   Function Padz(s : string;I : longInt) : string;
  209.   Function Replicate(c : char;I : longInt) : string;
  210.   Function StringOfChar(c : char;I : longInt) : string;
  211.   procedure SetArrayLength(var u: array; Length: Longint);
  212.   function GetArrayLength(var u: array): Longint;
  213.   function GetType(const data): String;
  214.   function Assigned(const data): Boolean;
  215.   function Low(var u: array): Longint;
  216.   function High(var u: array): Longint;
  217.  
  218. Type
  219.   TObject = class
  220.   public
  221.     Constructor Create;
  222.     Destructor Destroy; virtual;
  223.     procedure Free;
  224.  
  225.     function ClassNameIs(FType: string): Boolean;
  226.     function ClassName: string;
  227.     function GetAncestors: string;
  228.   end;
  229.  
  230. }
  231.  
  232. procedure RegisterExceptionLib(Sender: TIfPasScript);
  233.  
  234. {
  235.   function GetLastErrorCode: word;
  236.   function GetLastErrorParam: string;
  237.   function GetLastErrorModule: string;
  238.   function GetLastErrorAsString: string;
  239.   function GetLastErrorPosition: Longint;
  240.   procedure RaiseError(ErrorCode: Word; Param: string);
  241.  
  242. }
  243. {$IFDEF USEIDISPATCH}
  244. type
  245.   TIDispatchToIFVariant = function (ScriptEngine: TIFPasScript; Res: PIfVariant; I: IDispatch): Boolean;
  246.   TIFVariantToIDispatch = function (ScriptEngine: TIFPasScript; var Res: IDispatch; I: PIfVariant): Boolean;
  247. var
  248.   IDispatchToIFVariantProc: TIDispatchToIFVariant = nil;
  249.   IFVariantToIDispatchProc: TIFVariantToIDispatch = nil;
  250. {$ENDIF}
  251.  
  252. implementation
  253.  
  254. type
  255.   PResourceData = ^TResourceData;
  256.   TResourceData = record
  257.     Data: Pointer;
  258.     FreeProc: TResourceFree;
  259.   end;
  260.  
  261. function IntProcDefParam(s: string; I: Integer): Integer;
  262. {
  263. Parse the incode-script procedure definition from a string.
  264. When I=0 this function will return the result type.
  265. When I=-1 this function will return the number of parameters.
  266. When I=1 this function will return the first parameter type.
  267. When I=2 this function will return the second parameter type.
  268. etc.
  269. }
  270. var
  271.   res: Integer;
  272. begin
  273.   if I = 0 then
  274.   {Return result-type} IntProcDefParam := StrToInt(Fw(s)) else
  275.     if I = -1 then
  276.     {Return param count} begin
  277.       res := 0;
  278.       Delete(s, 1, Length(Fw(s))); {result}
  279.       rs(s);
  280.       while Length(s) > 0 do begin
  281.         Inc(res);
  282.         Delete(s, 1, Length(Fw(s))); {Delete parameter name}
  283.         rs(s);
  284.         Delete(s, 1, Length(Fw(s))); {Delete parameter type}
  285.         rs(s);
  286.       end; {while}
  287.       IntProcDefParam := res;
  288.     end {else if} else begin
  289.       res := 0;
  290.       if I < 1 then begin
  291.         IntProcDefParam := -1;
  292.         exit;
  293.       end;
  294.       Delete(s, 1, Length(Fw(s))); {result}
  295.       rs(s);
  296.       while Length(s) > 0 do begin
  297.         Inc(res);
  298.         Delete(s, 1, Length(Fw(s))); {delete parameter name}
  299.         rs(s);
  300.         if res = I then begin
  301.           IntProcDefParam := StrToInt(Fw(s));
  302.           exit;
  303.         end;
  304.         Delete(s, 1, Length(Fw(s))); {delete type}
  305.         rs(s);
  306.       end; {while}
  307.       IntProcDefParam := 0;
  308.     end {Else Else if}
  309. end; {IntProcDefParam}
  310. //-------------------------------------------------------------------
  311.  
  312. function IntProcDefName(s: string; I: Integer): string;
  313. {
  314. Parse the incode-script procedure definition from a string.
  315. i=0 will return the procedure name
  316. I=1 will return the first one
  317. }
  318. var
  319.   res: Integer;
  320. begin
  321.   res := 0;
  322.   if I < 1 then begin
  323.     IntProcDefName := '';
  324.     exit;
  325.   end;
  326.   Delete(s, 1, Length(Fw(s))); {result}
  327.   rs(s);
  328.   while Length(s) > 0 do begin
  329.     Inc(res);
  330.     if res = I then begin
  331.       IntProcDefName := Fw(s);
  332.       exit;
  333.     end;
  334.     Delete(s, 1, Length(Fw(s))); {delete parameter name}
  335.     rs(s);
  336.     Delete(s, 1, Length(Fw(s))); {delete type}
  337.     rs(s);
  338.   end; {while}
  339.   IntProcDefName := '';
  340. end; {IntProcDefParam}
  341. procedure DestroyWithList(I: TIFList);
  342. var
  343.   u: Integer;
  344. begin
  345.   for u := 0 to I.Count-1 do
  346.   begin
  347.     DestroyCajVariant(I.GetItem(u));
  348.   end;
  349.   I.Free;
  350. end;
  351.  
  352. {$IFNDEF NOCLASSES}
  353. function IsSameClassFamily(s1, s2: PIFSClassType; EnableSwitch: Boolean): Boolean;
  354. var
  355.   s3: PIFSClassType;
  356. begin
  357.   if (s1.VarNoStart > s2.VarNoStart) and EnableSwitch then begin
  358.     s3 := s1;
  359.     s1 := s2;
  360.     s2 := s3;
  361.   end;
  362.   while (s1 <> s2) do begin
  363.     if assigned(s2^.InheritsFrom) then
  364.       s2 := s2^.InheritsFrom^.Ext
  365.     else begin
  366.       s2 := nil;
  367.       break;
  368.     end;
  369.   end;
  370.   IsSameClassFamily := s2 <> nil;
  371. end;
  372.  
  373. //-------------------------------------------------------------------
  374.  
  375. function GetClassProcedure(Self: PIfVariant; ProcClass: PIFSClassType; const Name: string; var proc: PProcedure; AlsoProtected: Boolean): Boolean;
  376. var
  377.   pc: PIFSClassType;
  378.   I: Integer;
  379.  
  380.   procedure CheckForward;
  381.   var
  382.     n: TIfList;
  383.     I, I2: Integer;
  384.     E: PProcedure;
  385.   begin
  386.     if (proc^.Flags and $30) <> 0 then begin
  387.       n := TIfList.Create;
  388.       if assigned(Self) then
  389.         ProcClass := Self.CV_Class^.ClassType^.Ext;
  390.       while assigned(ProcClass) and (ProcClass <> proc^.ClassType^.Ext) do begin
  391.         n.Add(ProcClass);
  392.         if assigned(ProcClass^.InheritsFrom) then
  393.           ProcClass := ProcClass^.InheritsFrom^.Ext
  394.         else
  395.           ProcClass := nil;
  396.       end;
  397.       for I := n.Count - 1 downto 0 do begin
  398.         ProcClass := n.GetItem(I);
  399.         for I2 := 0 to (ProcClass^.Procedures.Count - 1) do begin
  400.           E := ProcClass^.Procedures.GetItem(I2);
  401.           if copy(E^.Name, 2, Length(E^.Name) - 1) = Name then begin
  402.             if (E^.Flags and $30) <> $20 then begin
  403.               break;
  404.             end else
  405.               proc := E;
  406.           end; {if}
  407.         end; {for}
  408.       end; {for}
  409.       n.Free;
  410.     end;
  411.   end;
  412. begin
  413.   pc := ProcClass;
  414.   while assigned(pc) do begin
  415.     for I := 0 to pc^.Procedures.Count - 1 do begin
  416.       proc := pc^.Procedures.GetItem(I);
  417.       if copy(proc^.Name, 2, Length(proc^.Name) - 1) = Name then begin
  418.         if (proc.Flags and $3) = $2 then begin
  419.           CheckForward;
  420.           GetClassProcedure := True;
  421.           exit;
  422.         end;
  423.         if AlsoProtected then begin
  424.           if pc = ProcClass then begin
  425.             CheckForward;
  426.             GetClassProcedure := True;
  427.             exit;
  428.           end else
  429.             if (proc.Flags and $3) = $1 then begin
  430.               CheckForward;
  431.               GetClassProcedure := True;
  432.               exit;
  433.             end;
  434.           if (proc.Flags and $3) = $3 then begin
  435.             CheckForward;
  436.             GetClassProcedure := True;
  437.             exit;
  438.           end;
  439.         end;
  440.       end;
  441.     end; {for}
  442.     if assigned(pc^.InheritsFrom) then
  443.       pc := pc^.InheritsFrom^.Ext
  444.     else
  445.       pc := nil;
  446.   end; {while}
  447.   GetClassProcedure := False;
  448. end;
  449. //-------------------------------------------------------------------
  450.  
  451. function FindProc(TheClass: PTypeRec; const Name: string): PProcedure;
  452. var
  453.   Curr: PTypeRec;
  454.   res: PProcedure;
  455.  
  456.   function SearchList(List: TIfList): PProcedure;
  457.   var
  458.     I: Integer;
  459.     n: PProcedure;
  460.   begin
  461.     for I := 0 to List.Count - 1 do begin
  462.       n := List.GetItem(I);
  463.       if n^.Name = Name then begin
  464.         SearchList := n;
  465.         exit;
  466.       end;
  467.     end;
  468.     SearchList := nil;
  469.   end; {searchlist}
  470. begin
  471.   Curr := TheClass;
  472.   res := nil;
  473.   while assigned(Curr) do begin
  474.     res := SearchList(PIFSClassType(Curr^.Ext)^.Procedures);
  475.     if res = nil then
  476.       Curr := PIFSClassType(Curr^.Ext)^.InheritsFrom
  477.     else
  478.       break;
  479.   end;
  480.   FindProc := res;
  481. end;
  482. //-------------------------------------------------------------------
  483. function GetClassVariable(Self: PIfVariant; ProcClass: PIFSClassType; const Name: string; var thevar: PIfVariant; AlsoProtected: Boolean): Boolean;
  484. begin
  485.   GetclassVariable := GetClassVariable2(Self^.CV_Class, ProcClass, Name, TheVar, AlsoProtected);
  486. end;
  487.  
  488. //-------------------------------------------------------------------
  489. function GetClassVariable2(Self: PCreatedClass; ProcClass: PIFSClassType; const Name: string; var thevar: PIfVariant; AlsoProtected: Boolean): Boolean;
  490. var
  491.   TC: PCreatedClass;
  492.   ct: PIFSClassType;
  493.   pp: PPropertyDef;
  494.   I: Longint;
  495.   u, s: string;
  496. begin
  497.   TC := Self;
  498.   if not IsSameClassFamily(TC^.ClassType^.Ext, ProcClass, True) then begin
  499.     GetClassVariable2 := False;
  500.     exit;
  501.   end;
  502.   ct := ProcClass;
  503.   while assigned(ct) do begin
  504.     s := ct^.Variables.u;
  505.     I := ct^.VarNoStart;
  506.     while Length(s) > 0 do begin
  507.       u := Fw(s);
  508.       Rfw(s); {remove name}
  509.       Rfw(s); {remove type}
  510.       if copy(u, 2, Length(u) - 1) = Name then begin
  511.         thevar := Vm_Get(TC^.Variables, I);
  512.         if (thevar.Flags and $6) = $4 then begin
  513.           GetClassVariable2 := True;
  514.           exit;
  515.         end;
  516.         if AlsoProtected then begin
  517.           if ct = ProcClass then begin
  518.             GetClassVariable2 := True;
  519.             exit;
  520.           end else if (thevar.Flags and $6) = $6 then begin
  521.             GetClassVariable2 := True;
  522.             exit;
  523.           end;
  524.         end; {if}
  525.       end; {while}
  526.       Inc(I);
  527.     end;
  528.     for I := 0 to Longint(ct^.Properties.Count) - 1 do begin
  529.       pp := ct^.Properties.GetItem(I);
  530.       if pp^.Name = Name then begin
  531.         thevar := Vm_Get(TC^.Variables, Longint(PIFSClassType(Self^.ClassType.Ext)^.VarNoStart + PIFSClassType(Self^.ClassType.Ext)^.VarCount) + I + Longint(ct^.PropStart));
  532.         if (thevar.Flags and $6) = $4 then begin
  533.           GetClassVariable2 := True;
  534.           exit;
  535.         end;
  536.         if AlsoProtected then begin
  537.           if ct = ProcClass then begin
  538.             GetClassVariable2 := True;
  539.             exit;
  540.           end else if (thevar.Flags and $6) = $6 then begin
  541.             GetClassVariable2 := True;
  542.             exit;
  543.           end;
  544.         end;
  545.       end;
  546.     end;
  547.     if assigned(ct.InheritsFrom) then
  548.       ct := ct.InheritsFrom^.Ext
  549.     else
  550.       ct := nil;
  551.   end;
  552.   GetClassVariable2 := False;
  553. end;
  554. //-------------------------------------------------------------------
  555.  
  556. //-------------------------------------------------------------------
  557.  
  558. function TIfPasScript.SetProperty(prop, Data: PIfVariant): Boolean;
  559. var
  560.   v: PVariableManager;
  561. begin
  562.   SetProperty := False;
  563.   if (prop.CV_PropFlags and $2) = 0 then begin
  564.     RunError(Self, ECanNotWriteProperty);
  565.     exit;
  566.   end;
  567.   if (prop.CV_PropFlags and $8) <> 0 then begin
  568.     v := VM_Create(nil);
  569.     Vm_Add(v, CreateCajVariant(PCreatedClass(prop^.CV_Self)^.ClassType), 'SELF')^.CV_Class := prop^.CV_Self;
  570.     Vm_Add(v, CopyVariant(Data), 'DATA');
  571.     DestroyCajVariant(RunScriptProc(prop.CV_PropWrite, v));
  572.     if FError.ErrorCode = EParameterError then begin
  573.       FError.ErrorCode := ENoError;
  574.       RunError(Self, ETypeMismatch);
  575.       VM_Destroy(v);
  576.       exit;
  577.     end;
  578.     VM_Destroy(v);
  579.   end else begin
  580.     if not Perform(prop.CV_PropWrite, Data, PtSet) then
  581.       exit;
  582.   end;
  583.   SetProperty := True;
  584. end;
  585. //-------------------------------------------------------------------
  586.  
  587. function TIfPasScript.GetProperty(prop: PIfVariant): PIfVariant;
  588. var
  589.   v: PVariableManager;
  590.   res: PIfVariant;
  591. begin
  592.   GetProperty := nil;
  593.   if (prop.CV_PropFlags and $1) = 0 then begin
  594.     RunError(Self, ECanNotReadProperty);
  595.     exit;
  596.   end;
  597.   if (prop.CV_PropFlags and $4) <> 0 then begin
  598.     v := VM_Create(nil);
  599.     Vm_Add(v, CreateCajVariant(PCreatedClass(prop^.CV_Self)^.ClassType), 'SELF')^.CV_Class := prop^.CV_Self;
  600.     res := RunScriptProc(prop.CV_PropRead, v);
  601.     if FError.ErrorCode = EParameterError then begin
  602.       FError.ErrorCode := ENoError;
  603.       RunError(Self, ETypeMismatch);
  604.       VM_Destroy(v);
  605.       exit;
  606.     end;
  607.     VM_Destroy(v);
  608.     GetProperty := res;
  609.   end else begin
  610.     GetProperty := CopyVariant(prop.CV_PropRead);
  611.   end;
  612. end;
  613. //-------------------------------------------------------------------
  614. {$ENDIF}
  615.  
  616. function TIfPasScript.Perform(V1: PIfVariant; v2: PIfVariant; t: TPerformType): Boolean;
  617. var
  618.   Err: Boolean;
  619.   I: Longint;
  620.   p: PIfVariant;
  621.  
  622.   procedure AddArrayVar(var v: TIfList; I: PIfVariant);
  623.   var
  624.     n: PIfVariant;
  625.   begin
  626.     New(n);
  627.     n^.VType^.atypeid := CSV_Var;
  628.     n^.CV_Var := nil;
  629.     Perform(n, I, PtSet);
  630.   end;
  631.  
  632.   procedure MakeItReal(v: Extended);
  633.   begin
  634.     ChangeType(V1, TM_Add(Types, '', CSV_Extended, nil));
  635.     V1^.Cv_Extended := v;
  636.   end;
  637.  
  638.   procedure MakeItBool(v: Boolean);
  639.   begin
  640.     ChangeType(V1, TM_Add(Types, '', CSV_Bool, nil));
  641.     V1^.Cv_Bool := v;
  642.   end;
  643.  
  644.   procedure MakeItString(const v: string);
  645.   begin
  646.     ChangeType(V1, TM_Add(Types, '', CSV_String, nil));
  647.     V1^.Cv_Str := v;
  648.   end;
  649.  
  650. begin
  651.   V1 := GetVarLink(V1);
  652.   v2 := GetVarLink(v2);
  653.   {$IFDEF VARIANTSUPPORT}
  654.   if (v2^.VType^.ATypeId = CSV_Variant) and (V1^.Vtype^.atypeid <> CSV_Variant) then begin
  655.     v2 := v2^.CV_Variant;
  656.     if v2 = nil then
  657.     begin
  658.       Perform := False;
  659.       RunError(Self, EVariantIsNil);
  660.       exit;
  661.     end;
  662.   end;
  663.   {$ENDIF}
  664.   if V1^.VType^.atypeid = CSV_Record then begin
  665.     if V1.VType <> v2.VType then begin
  666.       Perform := False;
  667.       RunError(Self, ETypeMismatch);
  668.       exit;
  669.     end;
  670.   end else
  671.     if ((V1^.VType^.atypeid <> v2^.VType^.atypeid) and
  672.       not (IsIntRealType(V1) and IsIntRealType(v2)) and
  673.       not (IsStringType(V1) and IsStringType(v2)) and
  674.       not (V1^.VType^.atypeid = CSV_Var)){$IFNDEF NOCLASSES} and
  675.     not ((V1^.VType^.atypeid = CSV_Class) and (v2^.VType^.atypeid = CSV_ClassRef)
  676.       and ((t = ptAs) or (t = ptIs))){$ENDIF} and
  677.       {$IFDEF VARIANTSUPPORT}
  678.       not (V1^.VType^.atypeid = CSV_Variant) and
  679.       {$ENDIF}
  680.     not (((t = PtSet) or (t = PtEqual) or (t = PtNotEqual)) and
  681.       (v2^.VType^.atypeid = CSV_Special) and ((V1^.VType^.atypeid = CSV_Var){$IFNDEF NOCLASSES}
  682.       or (V1^.VType^.atypeid = CSV_Class) or
  683.       (V1^.VType^.atypeid = CSV_ClassRef){$ENDIF}
  684.       {$IFDEF VARIANTSUPPORT} or (V1^.VType^.ATypeId = CSV_Variant){$ENDIF}
  685.       or (V1^.VType^.atypeid = CSV_ProcVariable)))
  686.       then begin
  687.       Perform := False;
  688.       RunError(Self, ETypeMismatch);
  689.       exit;
  690.     end;
  691.   Err := False;
  692.   case t of
  693. {$IFNDEF NOCLASSES}
  694.     ptIs: begin
  695. {$IFDEF VARIANTSUPPORT}
  696.         if v1^.VType^.ATypeID = CSV_Variant then
  697.         begin
  698.           v1 := v1^.CV_Variant;
  699.           if v1 = nil then
  700.           begin
  701.             Perform := False;
  702.             RunError(Self, EVariantIsNil);
  703.             exit;
  704.           end;
  705.           if V2^.VType^.ATypeID = CSV_Variant then
  706.           begin
  707.             v2:= v2^.CV_Variant;
  708.             if V2 = nil then
  709.             begin
  710.               Perform := False;
  711.               RunError(Self, EVariantIsNil);
  712.               exit;
  713.             end;
  714.           end;
  715.         end;
  716. {$ENDIF}
  717.         case V1^.VType^.atypeid of
  718.           CSV_Class: begin
  719.               if not assigned(v2^.Cv_ClassRef) then begin
  720.                 MakeItBool(False);
  721.               end else begin
  722.                 if not assigned(V1^.CV_Class) then begin
  723.                   MakeItBool(False)
  724.                 end else
  725.                   if IsSameClassFamily(v2^.Cv_ClassRef^.Ext, V1^.CV_Class^.ClassType^.Ext, True) then begin
  726.                     MakeItBool(True);
  727.                   end else begin
  728.                     MakeItBool(False);
  729.                   end;
  730.               end;
  731.             end;
  732.         else begin
  733.             RunError(Self, ETypeMismatch);
  734.             Err := True;
  735.           end;
  736.         end;
  737.       end;
  738.     ptAs: begin
  739. {$IFDEF VARIANTSUPPORT}
  740.         if v1^.VType^.ATypeID = CSV_Variant then
  741.         begin
  742.           v1 := v1^.CV_Variant;
  743.           if v1 = nil then
  744.           begin
  745.             Perform := False;
  746.             RunError(Self, EVariantIsNil);
  747.             exit;
  748.           end;
  749.           if V2^.VType^.ATypeID = CSV_Variant then
  750.           begin
  751.             v2:= v2^.CV_Variant;
  752.             if V2 = nil then
  753.             begin
  754.               Perform := False;
  755.               RunError(Self, EVariantIsNil);
  756.               exit;
  757.             end;
  758.           end;
  759.         end;
  760. {$ENDIF}
  761.         case V1^.VType^.atypeid of
  762.           CSV_Class: begin
  763.               if not assigned(v2^.Cv_ClassRef) then begin
  764.                 Err := True;
  765.                 RunError(Self, ETypeMismatch);
  766.               end else begin
  767.                 if not assigned(V1^.CV_Class) then begin
  768.                   RunError(Self, EClassNotCreated);
  769.                   Err := True;
  770.                 end else
  771.                   if IsSameClassFamily(v2^.Cv_ClassRef^.Ext, V1^.CV_Class^.ClassType^.Ext, True) then begin
  772.                     V1^.VType := v2^.Cv_ClassRef;
  773.                   end else begin
  774.                     Err := True;
  775.                     RunError(Self, ETypeMismatch);
  776.                   end;
  777.               end;
  778.             end;
  779.         else begin
  780.             RunError(Self, ETypeMismatch);
  781.             Err := True;
  782.           end;
  783.         end;
  784.       end;
  785. {$ENDIF}
  786.     PtSet: begin
  787.         if IsIntegerType(V1) and not IsIntegerType(v2) then begin
  788.           RunError(Self, ETypeMismatch);
  789.           Err := True;
  790.         end else
  791.           case V1^.VType^.atypeid of
  792. {$IFDEF VARIANTSUPPORT}
  793.             CSV_Variant:
  794.             begin
  795.                 if v2^.VType^.ATypeId = CSV_Special then
  796.                 begin
  797.                   if V2^.CV_Spec = 0 then
  798.                   begin
  799.                     destroyCajVariant(v1^.CV_Variant);
  800.                     V1^.Cv_Variant := nil;
  801.                   end;
  802.                 end else begin
  803.                   if v2^.VType^.ATypeiD = CSV_Variant then
  804.                   begin
  805.                     DestroyCajVariant(V1^.CV_Variant);
  806.                     V1^.CV_Variant := copyVariant(v2^.CV_Variant);
  807.                   end else begin
  808.                     DestroyCajVariant(V1^.CV_Variant);
  809.                     V1^.CV_Variant := copyVariant(v2);
  810.                   end;
  811.                 end;
  812.             end;
  813. {$ENDIF}
  814.             CSV_Special: begin
  815.                 V1^.CV_Spec := v2^.CV_Spec;
  816.               end;
  817.             CSV_ProcVariable: begin
  818.                 if v2^.VType^.atypeid = CSV_Special then begin
  819.                   if v2^.CV_Spec = 0 then { nil }  begin
  820.                     V1^.Cv_Proc := nil;
  821. {$IFNDEF NOCLASSES}V1^.Cv_ProcSelf := nil;
  822. {$ENDIF}
  823.                   end;
  824.                 end else if V1^.VType <> v2^.VType then begin
  825.                   if v2^.VType^.Ext = nil then
  826.                   begin
  827.                     if not assigned(v2^.CV_Proc) then
  828.                     begin
  829.                       RunError(Self, ETypeMismatch);
  830.                       Err := True;
  831.                     end else begin
  832.                       if {$IFNDEF NOCLASSES}(PIFSProcType(v1^.VType^.ext)^.Method = (PProcedure(v2^.CV_Proc)^.ClassType = nil)) or{$ENDIF}
  833.                        (PIFSProcType(v1^.VType^.ext)^.Decl <> PProcedure(V2^.Cv_Proc)^.Decl) then
  834.                       begin
  835.                         RunError(Self, ETypeMismatch);
  836.                         err := true;
  837.                       end else
  838.                       begin
  839.                         V1^.CV_Proc := v2^.CV_Proc;
  840.                         {$IFNDEF NOCLASSES}v1^.CV_ProcSelf := V2^.CV_ProcSelf;{$ENDIF}
  841.                       end;
  842.                     end;
  843.                   end else begin
  844.                     RunError(Self, ETypeMismatch);
  845.                     Err := True;
  846.                   end;
  847.                 end else begin
  848.                   V1^.Cv_Proc := v2^.Cv_Proc;
  849. {$IFNDEF NOCLASSES}V1^.Cv_ProcSelf := v2^.Cv_ProcSelf;
  850. {$ENDIF}
  851.                 end;
  852.               end;
  853.             CSV_UByte: V1^.Cv_UByte := GetInteger(v2);
  854.             CSV_SByte: V1^.Cv_SByte := GetInteger(v2);
  855.             CSV_Char: begin
  856.                 V1^.Cv_Str := GetString(v2);
  857.                 if Length(V1^.Cv_Str) > 1 then begin
  858.                   Err := True;
  859.                   RunError(Self, ETypeMismatch);
  860.                 end else
  861.                   V1^.Cv_Char := V1^.Cv_Str[1];
  862.               end;
  863.             CSV_UInt16: V1^.Cv_UInt16 := GetInteger(v2);
  864.             CSV_SInt16: V1^.Cv_SInt16 := GetInteger(v2);
  865.             CSV_UInt32: V1^.Cv_UInt32 := GetInteger(v2);
  866.             CSV_SInt32: V1^.Cv_SInt32 := GetInteger(v2);
  867.             CSV_String: V1^.Cv_Str := GetString(v2);
  868.             CSV_Real: V1^.CV_Real := GetReal(v2);
  869.             CSV_Single: V1^.CV_Single := GetReal(v2);
  870.             CSV_Double: V1^.CV_Double := GetReal(v2);
  871.             CSV_Extended: V1^.Cv_Extended := GetReal(v2);
  872.             CSV_Comp: V1^.CV_comp := GetReal(v2);
  873. {$IFNDEF NOCLASSES}
  874.             CSV_ExternalObject:
  875.               begin
  876.                 if V1^.VType <> V2^.VType then
  877.                 begin
  878.                   Err := True;
  879.                   RunError(Self, ETypeMismatch);
  880.                 end else
  881.                 begin
  882.                   v1^.CV_ExternalObject := V2^.CV_ExternalObject;
  883.                 end;
  884.               end;
  885. {$ENDIF}
  886.             CSV_Bool: begin
  887.                 if v2^.VType^.atypeid = CSV_Bool then
  888.                   V1^.Cv_Bool := v2^.Cv_Bool
  889.                 else begin
  890.                   Err := True;
  891.                   RunError(Self, ETypeMismatch);
  892.                 end;
  893.               end;
  894.             CSV_Record: begin
  895.                 for I := 0 to V1^.CV_RecItems.Count - 1 do begin
  896.                   if not Perform(V1^.CV_RecItems.GetItem(I), v2^.CV_RecItems.GetItem(I), PtSet) then begin
  897.                     Err := True;
  898.                     RunError(Self, ETypeMismatch);
  899.                   end;
  900.                 end;
  901.               end;
  902. {$IFNDEF NOCLASSES}
  903.             CSV_Class: begin
  904.                 if v2^.VType^.atypeid = CSV_Special then begin
  905.                   if v2^.CV_Spec = 0 then { nil } begin
  906.                     V1^.CV_Class := nil;
  907.                   end;
  908.                 end else
  909.                   if not assigned(v2^.CV_Class) then begin
  910.                     V1.CV_Class := nil;
  911.                   end else
  912.                     if IsSameClassFamily(V1^.VType^.Ext, v2^.CV_Class^.ClassType^.Ext, False) then begin
  913.                       V1^.CV_Class := v2^.CV_Class;
  914.                     end else begin
  915.                       Err := True;
  916.                       RunError(Self, ETypeMismatch);
  917.                     end;
  918.               end;
  919. {$ENDIF}
  920.             CSV_Array: begin
  921.                 for I := 0 to V1^.CV_ArrItems.Count - 1 do begin
  922.                   DestroyCajVariant(V1^.CV_ArrItems.GetItem(I));
  923.                 end;
  924.                 V1^.CV_ArrItems.Clear;
  925.                 for I := 0 to v2^.CV_ArrItems.Count - 1 do begin
  926.                   p := CreateCajVariant(PIfVariant(v2.CV_ArrItems.GetItem(I))^.VType);
  927.                   V1^.CV_ArrItems.Add(p);
  928.                   if not Perform(V1^.CV_ArrItems.GetItem(I), v2^.CV_ArrItems.GetItem(I), PtSet) then begin
  929.                     Err := True;
  930.                     RunError(Self, ETypeMismatch);
  931.                     break;
  932.                   end;
  933.                 end;
  934.               end;
  935.             CSV_Internal: begin
  936.                 V1^.Cv_Int1 := v2^.Cv_Int1;
  937.                 V1^.Cv_Int2 := v2^.Cv_Int2;
  938.               end;
  939. {$IFNDEF NOCLASSES}
  940.             CSV_ClassRef: begin
  941.                 if v2^.VType^.atypeid = CSV_Special then begin
  942.                   if v2^.CV_Spec = 0 then { nil } begin
  943.                     V1^.Cv_ClassRef := nil;
  944.                   end;
  945.                 end else
  946.  
  947.                   if IsSameClassFamily(V1^.VType^.Ext, v2^.VType^.Ext, True) then
  948.                     V1^.Cv_ClassRef := v2^.Cv_ClassRef
  949.                   else begin
  950.                     RunError(Self, ETypeMismatch);
  951.                     Err := True;
  952.                   end;
  953.               end;
  954. {$ENDIF}
  955.             CSV_Var: begin
  956.                 V1^.VType := v2^.VType;
  957.                 case v2^.VType^.atypeid of
  958.                   CSV_UByte: V1^.Cv_UByte := v2^.Cv_UByte;
  959.                   CSV_SByte: V1^.Cv_SByte := v2^.Cv_SByte;
  960.                   CSV_UInt16: V1^.Cv_UInt16 := v2^.Cv_UInt16;
  961.                   CSV_SInt16: V1^.Cv_SInt16 := v2^.Cv_SInt16;
  962.                   CSV_UInt32: V1^.Cv_UInt32 := v2^.Cv_UInt32;
  963.                   CSV_SInt32: V1^.Cv_SInt32 := v2^.Cv_SInt32;
  964.                   CSV_Char: V1^.Cv_Char := v2^.Cv_Char;
  965.                   CSV_String: V1^.Cv_Str := v2^.Cv_Str;
  966.                   CSV_Real: V1^.CV_Real := v2^.CV_Real;
  967.                   CSV_Single: V1^.CV_Single := v2^.CV_Single;
  968.                   CSV_Double: V1^.CV_Double := v2^.CV_Double;
  969.                   CSV_Extended: V1^.Cv_Extended := v2^.Cv_Extended;
  970.                   CSV_Comp: V1^.CV_comp := v2^.CV_comp;
  971.                   CSV_Bool: V1^.Cv_Bool := v2^.Cv_Bool;
  972.                   CSV_Variant: begin
  973.                     if V2^.CV_Variant = nil then
  974.                     begin
  975.                       V1^.Vtype := TM_Add(Types, '', CSV_Special, nil);
  976.                       V1^.CV_Spec := 0;
  977.                     end else
  978.                     begin
  979.                       V1 := CopyVariant(v2);
  980.                     end;
  981.                   end;
  982.                   CSV_Record: begin
  983.                     v1^.CV_RecItems := TIFList.Create;
  984.                     for I := 0 to V2^.CV_RecItems.Count-1 do
  985.                     begin
  986.                       v1^.CV_RecItems.Add(CopyVariant(V2^.CV_RecItems.GetItem(i)));
  987.                     end;
  988.                   end;
  989.                   CSV_ProcVariable: begin
  990.                       if v2^.VType^.atypeid = CSV_Special then begin
  991.                         if v2^.CV_Spec = 0 then { nil }  begin
  992.                           V1^.Cv_Proc := nil;
  993. {$IFNDEF NOCLASSES}V1^.Cv_ProcSelf := nil;
  994. {$ENDIF}
  995.                         end;
  996.                       end else begin
  997. {$IFNDEF NOCLASSES}
  998.                         V1^.Cv_ProcSelf := v2^.Cv_ProcSelf;
  999. {$ENDIF}
  1000.                         V1^.Cv_Proc := v2^.Cv_Proc;
  1001.                       end;
  1002.                     end;
  1003.                   CSV_Array: begin
  1004.                       V1^.CV_ArrItems := TIfList.Create;
  1005.                       for I := 0 to v2^.CV_ArrItems.Count - 1 do begin
  1006.                         p := CreateCajVariant(PIfVariant(v2.CV_ArrItems.GetItem(I))^.VType);
  1007.                         V1^.CV_ArrItems.Add(p);
  1008.                         if not Perform(V1^.CV_ArrItems.GetItem(I), v2^.CV_ArrItems.GetItem(I), PtSet) then begin
  1009.                           Err := True;
  1010.                           RunError(Self, ETypeMismatch);
  1011.                           break;
  1012.                         end;
  1013.                       end;
  1014.                     end;
  1015. {$IFNDEF NOCLASSES}
  1016.                   CSV_Class: begin
  1017.                       if v2^.VType^.atypeid = CSV_Special then begin
  1018.                         if v2^.CV_Spec = 0 then { nil } begin
  1019.                           V1^.CV_Class := nil;
  1020.                         end;
  1021.                       end else
  1022.                         V1^.CV_Class := v2^.CV_Class;
  1023.                     end;
  1024.                   CSV_ClassRef: begin
  1025.                       if v2^.VType^.atypeid = CSV_Special then begin
  1026.                         if v2^.CV_Spec = 0 then { nil } begin
  1027.                           V1^.Cv_ClassRef := nil;
  1028.                         end;
  1029.                       end else
  1030.  
  1031.                         V1^.Cv_ClassRef := v2^.Cv_ClassRef;
  1032.                     end;
  1033.                   CSV_ExternalObject: begin
  1034.                       V1^.CV_ExternalObject := v2^.CV_ExternalObject;
  1035.                     end;
  1036. {$ENDIF}
  1037.                   CSV_Internal: begin
  1038.                       V1^.Cv_Int1 := v2^.Cv_Int1;
  1039.                       V1^.Cv_Int2 := v2^.Cv_Int2;
  1040.                     end;
  1041.                 end;
  1042.               end;
  1043.           else begin
  1044.               RunError(Self, ETypeMismatch);
  1045.               Err := True;
  1046.             end;
  1047.           end;
  1048.       end;
  1049.     ptMinus:
  1050.     begin
  1051. {$IFDEF VARIANTSUPPORT}
  1052.         if v1^.VType^.ATypeID = CSV_Variant then
  1053.         begin
  1054.           v1 := v1^.CV_Variant;
  1055.           if v1 = nil then
  1056.           begin
  1057.             Perform := False;
  1058.             RunError(Self, EVariantIsNil);
  1059.             exit;
  1060.           end;
  1061.           if V2^.VType^.ATypeID = CSV_Variant then
  1062.           begin
  1063.             v2:= v2^.CV_Variant;
  1064.             if V2 = nil then
  1065.             begin
  1066.               Perform := False;
  1067.               RunError(Self, EVariantIsNil);
  1068.               exit;
  1069.             end;
  1070.           end;
  1071.         end;
  1072. {$ENDIF}
  1073.       case V1^.VType^.atypeid of
  1074.         CSV_UByte: begin
  1075.             if IsRealType(v2) then
  1076.               MakeItReal(V1^.Cv_UByte - GetReal(v2))
  1077.             else
  1078.               V1^.Cv_UByte := V1^.Cv_UByte - TCSV_UByte(GetInteger(v2));
  1079.           end;
  1080.         CSV_SByte: begin
  1081.             if IsRealType(v2) then
  1082.               MakeItReal(V1^.Cv_SByte - GetReal(v2))
  1083.             else
  1084.               V1^.Cv_SByte := V1^.Cv_SByte - TCSV_SByte(GetInteger(v2));
  1085.           end;
  1086.         CSV_UInt16: begin
  1087.             if IsRealType(v2) then
  1088.               MakeItReal(V1^.Cv_UInt16 - GetReal(v2))
  1089.             else
  1090.               V1^.Cv_UInt16 := V1^.Cv_UInt16 - TCSV_UInt16(GetInteger(v2));
  1091.           end;
  1092.         CSV_SInt16: begin
  1093.             if IsRealType(v2) then
  1094.               MakeItReal(V1^.Cv_SInt16 - GetReal(v2))
  1095.             else
  1096.               V1^.Cv_SInt16 := V1^.Cv_SInt16 - TCSV_SInt16(GetInteger(v2));
  1097.           end;
  1098.         CSV_UInt32: begin
  1099.             if IsRealType(v2) then
  1100.               MakeItReal(V1^.Cv_UInt32 - GetReal(v2))
  1101.             else
  1102.               V1^.Cv_UInt32 :=  V1^.Cv_UInt32 - TCSV_UInt32(GetInteger(v2));
  1103.           end;
  1104.         CSV_SInt32: begin
  1105.             if IsRealType(v2) then
  1106.               MakeItReal(V1^.Cv_SInt32 - GetReal(v2))
  1107.             else
  1108.               V1^.Cv_SInt32 := V1^.Cv_SInt32 - TCSV_SInt32(GetInteger(v2));
  1109.           end;
  1110.         CSV_Real: begin
  1111.             V1^.CV_Real := V1^.CV_Real - GetReal(v2);
  1112.           end;
  1113.         CSV_Single: begin
  1114.             V1^.CV_Single := V1^.CV_Single - GetReal(v2);
  1115.           end;
  1116.         CSV_Double: begin
  1117.             V1^.CV_Double := V1^.CV_Double - GetReal(v2);
  1118.           end;
  1119.         CSV_Extended: begin
  1120.             V1^.Cv_Extended := V1^.Cv_Extended - GetReal(v2);
  1121.           end;
  1122.         CSV_Comp: begin
  1123.             V1^.CV_comp := V1^.CV_comp - GetReal(v2);
  1124.           end;
  1125.       else begin
  1126.           RunError(Self, ETypeMismatch);
  1127.           Err := True;
  1128.         end;
  1129.       end { CASE };
  1130.     end;
  1131.     PtPlus:
  1132.     begin
  1133. {$IFDEF VARIANTSUPPORT}
  1134.         if v1^.VType^.ATypeID = CSV_Variant then
  1135.         begin
  1136.           v1 := v1^.CV_Variant;
  1137.           if v1 = nil then
  1138.           begin
  1139.             Perform := False;
  1140.             RunError(Self, EVariantIsNil);
  1141.             exit;
  1142.           end;
  1143.           if V2^.VType^.ATypeID = CSV_Variant then
  1144.           begin
  1145.             v2:= v2^.CV_Variant;
  1146.             if V2 = nil then
  1147.             begin
  1148.               Perform := False;
  1149.               RunError(Self, EVariantIsNil);
  1150.               exit;
  1151.             end;
  1152.           end;
  1153.         end;
  1154. {$ENDIF}
  1155.       case V1^.VType^.atypeid of
  1156.         CSV_UByte: begin
  1157.             if IsRealType(v2) then
  1158.               MakeItReal(V1^.Cv_UByte + GetReal(v2))
  1159.             else
  1160.               V1^.Cv_UByte := V1^.Cv_UByte + TCSV_UByte(GetInteger(v2));
  1161.           end;
  1162.         CSV_SByte: begin
  1163.             if IsRealType(v2) then
  1164.               MakeItReal(V1^.Cv_SByte + GetReal(v2))
  1165.             else
  1166.               V1^.Cv_SByte := V1^.Cv_SByte + TCSV_SByte(GetInteger(v2));
  1167.           end;
  1168.         CSV_UInt16: begin
  1169.             if IsRealType(v2) then
  1170.               MakeItReal(V1^.Cv_UInt16 + GetReal(v2))
  1171.             else
  1172.               V1^.Cv_UInt16 := V1^.Cv_UInt16 + TCSV_Uint16(GetInteger(v2));
  1173.           end;
  1174.         CSV_SInt16: begin
  1175.             if IsRealType(v2) then
  1176.               MakeItReal(V1^.Cv_SInt16 + GetReal(v2))
  1177.             else
  1178.               V1^.Cv_SInt16 := V1^.Cv_SInt16 + TCSV_Sint16(GetInteger(v2));
  1179.           end;
  1180.         CSV_UInt32: begin
  1181.             if IsRealType(v2) then
  1182.               MakeItReal(V1^.Cv_UInt32 + GetReal(v2))
  1183.             else
  1184.               V1^.Cv_UInt32 := V1^.Cv_UInt32 + TCSV_Uint32(GetInteger(v2));
  1185.           end;
  1186.         CSV_SInt32: begin
  1187.             if IsRealType(v2) then
  1188.               MakeItReal(V1^.Cv_SInt32 + GetReal(v2))
  1189.             else
  1190.               V1^.Cv_SInt32 := V1^.Cv_SInt32 + TCSV_Sint32(GetInteger(v2));
  1191.           end;
  1192.         CSV_Real: begin
  1193.             V1^.CV_Real := V1^.CV_Real + GetReal(v2);
  1194.           end;
  1195.         CSV_Single: begin
  1196.             V1^.CV_Single := V1^.CV_Single + GetReal(v2);
  1197.           end;
  1198.         CSV_Double: begin
  1199.             V1^.CV_Double := V1^.CV_Double + GetReal(v2);
  1200.           end;
  1201.         CSV_Extended: begin
  1202.             V1^.Cv_Extended := V1^.Cv_Extended + GetReal(v2);
  1203.           end;
  1204.         CSV_Comp: begin
  1205.             V1^.CV_comp := V1^.CV_comp + GetReal(v2);
  1206.           end;
  1207.         CSV_Char: begin
  1208.             MakeItString(V1^.Cv_Char + v2^.Cv_Char);
  1209.           end;
  1210.         CSV_String: begin
  1211.             V1^.Cv_Str := V1^.Cv_Str + GetString(v2);
  1212.           end;
  1213.       else begin
  1214.           Err := True;
  1215.           RunError(Self, ETypeMismatch);
  1216.         end;
  1217.       end { CASE };
  1218.     end;
  1219.     PtMul:
  1220.       begin
  1221. {$IFDEF VARIANTSUPPORT}
  1222.         if v1^.VType^.ATypeID = CSV_Variant then
  1223.         begin
  1224.           v1 := v1^.CV_Variant;
  1225.           if v1 = nil then
  1226.           begin
  1227.             Perform := False;
  1228.             RunError(Self, EVariantIsNil);
  1229.             exit;
  1230.           end;
  1231.           if V2^.VType^.ATypeID = CSV_Variant then
  1232.           begin
  1233.             v2:= v2^.CV_Variant;
  1234.             if V2 = nil then
  1235.             begin
  1236.               Perform := False;
  1237.               RunError(Self, EVariantIsNil);
  1238.               exit;
  1239.             end;
  1240.           end;
  1241.         end;
  1242. {$ENDIF}
  1243.       case V1^.VType^.atypeid of
  1244.         CSV_UByte: begin
  1245.             if IsRealType(v2) then
  1246.               MakeItReal(V1^.Cv_UByte * GetReal(v2))
  1247.             else
  1248.               V1^.Cv_UByte := V1^.Cv_UByte * TCSV_UByte(GetInteger(v2));
  1249.           end;
  1250.         CSV_SByte: begin
  1251.             if IsRealType(v2) then
  1252.               MakeItReal(V1^.Cv_SByte * GetReal(v2))
  1253.             else
  1254.               V1^.Cv_SByte := V1^.Cv_SByte * TCSV_SByte(GetInteger(v2));
  1255.           end;
  1256.         CSV_UInt16: begin
  1257.             if IsRealType(v2) then
  1258.               MakeItReal(V1^.Cv_UInt16 * GetReal(v2))
  1259.             else
  1260.               V1^.Cv_UInt16 := V1^.Cv_UInt16 * TCSV_Uint16(GetInteger(v2));
  1261.           end;
  1262.         CSV_SInt16: begin
  1263.             if IsRealType(v2) then
  1264.               MakeItReal(V1^.Cv_SInt16 * GetReal(v2))
  1265.             else
  1266.               V1^.Cv_SInt16 := V1^.Cv_SInt16 * TCSV_SInt16(GetInteger(v2));
  1267.           end;
  1268.         CSV_UInt32: begin
  1269.             if IsRealType(v2) then
  1270.               MakeItReal(V1^.Cv_UInt32 * GetReal(v2))
  1271.             else
  1272.               V1^.Cv_UInt32 := V1^.Cv_UInt32 * TCSV_uint32(GetInteger(v2));
  1273.           end;
  1274.         CSV_SInt32: begin
  1275.             if IsRealType(v2) then
  1276.               MakeItReal(V1^.Cv_SInt32 * GetReal(v2))
  1277.             else
  1278.               V1^.Cv_SInt32 := V1^.Cv_SInt32 * TCSV_Sint32(GetInteger(v2));
  1279.           end;
  1280.         CSV_Real: begin
  1281.             V1^.CV_Real := V1^.CV_Real * GetReal(v2);
  1282.           end;
  1283.         CSV_Single: begin
  1284.             V1^.CV_Single := V1^.CV_Single * GetReal(v2);
  1285.           end;
  1286.         CSV_Double: begin
  1287.             V1^.CV_Double := V1^.CV_Double * GetReal(v2);
  1288.           end;
  1289.         CSV_Extended: begin
  1290.             V1^.Cv_Extended := V1^.Cv_Extended * GetReal(v2);
  1291.           end;
  1292.         CSV_Comp: begin
  1293.             V1^.CV_comp := V1^.CV_comp * GetReal(v2);
  1294.           end;
  1295.       else begin
  1296.           Err := True;
  1297.           RunError(Self, ETypeMismatch);
  1298.         end;
  1299.       end { CASE };
  1300.     end;
  1301.     ptDiv: begin
  1302. {$IFDEF VARIANTSUPPORT}
  1303.         if v1^.VType^.ATypeID = CSV_Variant then
  1304.         begin
  1305.           v1 := v1^.CV_Variant;
  1306.           if v1 = nil then
  1307.           begin
  1308.             Perform := False;
  1309.             RunError(Self, EVariantIsNil);
  1310.             exit;
  1311.           end;
  1312.           if V2^.VType^.ATypeID = CSV_Variant then
  1313.           begin
  1314.             v2:= v2^.CV_Variant;
  1315.             if V2 = nil then
  1316.             begin
  1317.               Perform := False;
  1318.               RunError(Self, EVariantIsNil);
  1319.               exit;
  1320.             end;
  1321.           end;
  1322.         end;
  1323. {$ENDIF}
  1324.         if GetReal(v2) = 0 then begin
  1325.           RunError(Self, EDivideByZero);
  1326.           Err := True;
  1327.         end else
  1328.           case V1^.VType^.atypeid of
  1329.             CSV_UByte: begin
  1330.                 MakeItReal(V1^.Cv_UByte / GetReal(v2));
  1331.               end;
  1332.             CSV_SByte: begin
  1333.                 MakeItReal(V1^.Cv_SByte / GetReal(v2));
  1334.               end;
  1335.             CSV_UInt16: begin
  1336.                 MakeItReal(V1^.Cv_UInt16 / GetReal(v2));
  1337.               end;
  1338.             CSV_SInt16: begin
  1339.                 MakeItReal(V1^.Cv_SInt16 / GetReal(v2));
  1340.               end;
  1341.             CSV_UInt32: begin
  1342.                 MakeItReal(V1^.Cv_UInt32 / GetReal(v2));
  1343.               end;
  1344.             CSV_SInt32: begin
  1345.                 MakeItReal(V1^.Cv_SInt32 / GetReal(v2));
  1346.               end;
  1347.             CSV_Real: begin
  1348.                 V1^.CV_Real := V1^.CV_Real / GetReal(v2);
  1349.               end;
  1350.             CSV_Single: begin
  1351.                 V1^.CV_Single := V1^.CV_Single / GetReal(v2);
  1352.               end;
  1353.             CSV_Double: begin
  1354.                 V1^.CV_Double := V1^.CV_Double / GetReal(v2);
  1355.               end;
  1356.             CSV_Extended: begin
  1357.                 V1^.Cv_Extended := V1^.Cv_Extended / GetReal(v2);
  1358.               end;
  1359.             CSV_Comp: begin
  1360.                 V1^.CV_comp := V1^.CV_comp / GetReal(v2);
  1361.               end;
  1362.           else begin
  1363.               Err := True;
  1364.               RunError(Self, ETypeMismatch);
  1365.             end;
  1366.           end { CASE };
  1367.       end; { begin }
  1368.     PtIntDiv: begin
  1369. {$IFDEF VARIANTSUPPORT}
  1370.         if v1^.VType^.ATypeID = CSV_Variant then
  1371.         begin
  1372.           v1 := v1^.CV_Variant;
  1373.           if v1 = nil then
  1374.           begin
  1375.             Perform := False;
  1376.             RunError(Self, EVariantIsNil);
  1377.             exit;
  1378.           end;
  1379.           if V2^.VType^.ATypeID = CSV_Variant then
  1380.           begin
  1381.             v2:= v2^.CV_Variant;
  1382.             if V2 = nil then
  1383.             begin
  1384.               Perform := False;
  1385.               RunError(Self, EVariantIsNil);
  1386.               exit;
  1387.             end;
  1388.           end;
  1389.         end;
  1390. {$ENDIF}
  1391.         if not IsIntegerType(v2) then begin
  1392.           RunError(Self, ETypeMismatch);
  1393.           Perform := False;
  1394.           exit;
  1395.         end;
  1396.         if GetInteger(v2) = 0 then begin
  1397.           RunError(Self, EDivideByZero);
  1398.           Perform := False;
  1399.           exit;
  1400.         end;
  1401.         case V1^.VType^.atypeid of
  1402.           CSV_UByte: begin
  1403.               V1^.Cv_UByte := V1^.Cv_UByte div TCSV_UByte(GetInteger(v2));
  1404.             end;
  1405.           CSV_SByte: begin
  1406.               V1^.Cv_SByte := V1^.Cv_SByte div TCSV_SByte(GetInteger(v2));
  1407.             end;
  1408.           CSV_UInt16: begin
  1409.               V1^.Cv_UInt16 := V1^.Cv_UInt16 div TCSV_Uint16(GetInteger(v2));
  1410.             end;
  1411.           CSV_SInt16: begin
  1412.               V1^.Cv_SInt16 := V1^.Cv_SInt16 div TCSV_Sint16(GetInteger(v2));
  1413.             end;
  1414.           CSV_UInt32: begin
  1415.               V1^.Cv_UInt32 := V1^.Cv_UInt32 div TCSV_Uint32(GetInteger(v2));
  1416.             end;
  1417.           CSV_SInt32: begin
  1418.               V1^.Cv_SInt32 := V1^.Cv_SInt32 div TCSV_Sint32(GetInteger(v2));
  1419.             end;
  1420.         else begin
  1421.             Err := True;
  1422.             RunError(Self, ETypeMismatch);
  1423.           end;
  1424.         end;
  1425.       end;
  1426.     PtIntMod: begin
  1427. {$IFDEF VARIANTSUPPORT}
  1428.         if v1^.VType^.ATypeID = CSV_Variant then
  1429.         begin
  1430.           v1 := v1^.CV_Variant;
  1431.           if v1 = nil then
  1432.           begin
  1433.             Perform := False;
  1434.             RunError(Self, EVariantIsNil);
  1435.             exit;
  1436.           end;
  1437.           if V2^.VType^.ATypeID = CSV_Variant then
  1438.           begin
  1439.             v2:= v2^.CV_Variant;
  1440.             if V2 = nil then
  1441.             begin
  1442.               Perform := False;
  1443.               RunError(Self, EVariantIsNil);
  1444.               exit;
  1445.             end;
  1446.           end;
  1447.         end;
  1448. {$ENDIF}
  1449.         if not IsIntegerType(v2) then begin
  1450.           Perform := False;
  1451.           RunError(Self, ETypeMismatch);
  1452.           exit;
  1453.         end;
  1454.         case V1^.VType^.atypeid of
  1455.           CSV_UByte: begin
  1456.               V1^.Cv_UByte := V1^.Cv_UByte mod TCSV_UByte(GetInteger(v2));
  1457.             end;
  1458.           CSV_SByte: begin
  1459.               V1^.Cv_SByte := V1^.Cv_SByte mod TCSV_SByte(GetInteger(v2));
  1460.             end;
  1461.           CSV_UInt16: begin
  1462.               V1^.Cv_UInt16 := V1^.Cv_UInt16 mod TCSV_uInt16(GetInteger(v2));
  1463.             end;
  1464.           CSV_SInt16: begin
  1465.               V1^.Cv_SInt16 := V1^.Cv_SInt16 mod TCSV_SInt16(GetInteger(v2));
  1466.             end;
  1467.           CSV_UInt32: begin
  1468.               V1^.Cv_UInt32 := V1^.Cv_UInt32 mod TCSV_UInt32(GetInteger(v2));
  1469.             end;
  1470.           CSV_SInt32: begin
  1471.               V1^.Cv_SInt32 := V1^.Cv_SInt32 mod TCSV_SInt32(GetInteger(v2));
  1472.             end;
  1473.         else begin
  1474.             Err := True;
  1475.             RunError(Self, ETypeMismatch);
  1476.           end;
  1477.         end;
  1478.       end;
  1479.     PtAnd: begin
  1480. {$IFDEF VARIANTSUPPORT}
  1481.         if v1^.VType^.ATypeID = CSV_Variant then
  1482.         begin
  1483.           v1 := v1^.CV_Variant;
  1484.           if v1 = nil then
  1485.           begin
  1486.             Perform := False;
  1487.             RunError(Self, EVariantIsNil);
  1488.             exit;
  1489.           end;
  1490.           if V2^.VType^.ATypeID = CSV_Variant then
  1491.           begin
  1492.             v2:= v2^.CV_Variant;
  1493.             if V2 = nil then
  1494.             begin
  1495.               Perform := False;
  1496.               RunError(Self, EVariantIsNil);
  1497.               exit;
  1498.             end;
  1499.           end;
  1500.         end;
  1501. {$ENDIF}
  1502.         if (not IsIntegerType(v2)) and (not ISBooleanType(v2)) then begin
  1503.           RunError(Self, ETypeMismatch);
  1504.           Perform := False;
  1505.           exit;
  1506.         end;
  1507.         case V1^.VType^.atypeid of
  1508.           CSV_UByte: begin
  1509.               V1^.Cv_UByte := V1^.Cv_UByte and TCSV_UByte(GetInteger(v2));
  1510.             end;
  1511.           CSV_SByte: begin
  1512.               V1^.Cv_SByte := V1^.Cv_SByte and TCSV_SByte(GetInteger(v2));
  1513.             end;
  1514.           CSV_UInt16: begin
  1515.               V1^.Cv_UInt16 := V1^.Cv_UInt16 and TCSV_UInt16(GetInteger(v2));
  1516.             end;
  1517.           CSV_SInt16: begin
  1518.               V1^.Cv_SInt16 := V1^.Cv_SInt16 and TCSV_SInt16(GetInteger(v2));
  1519.             end;
  1520.           CSV_UInt32: begin
  1521.               V1^.Cv_UInt32 := V1^.Cv_UInt32 and TCSV_UInt32(GetInteger(v2));
  1522.             end;
  1523.           CSV_SInt32: begin
  1524.               V1^.Cv_SInt32 := V1^.Cv_SInt32 and TCSV_SInt32(GetInteger(v2));
  1525.             end;
  1526.           CSV_Bool: begin
  1527.               V1^.Cv_Bool := V1^.Cv_Bool and GetBoolean(v2);
  1528.             end;
  1529.         else begin
  1530.             Err := True;
  1531.             RunError(Self, ETypeMismatch);
  1532.           end;
  1533.         end;
  1534.       end;
  1535.     ptOr: begin
  1536. {$IFDEF VARIANTSUPPORT}
  1537.         if v1^.VType^.ATypeID = CSV_Variant then
  1538.         begin
  1539.           v1 := v1^.CV_Variant;
  1540.           if v1 = nil then
  1541.           begin
  1542.             Perform := False;
  1543.             RunError(Self, EVariantIsNil);
  1544.             exit;
  1545.           end;
  1546.           if V2^.VType^.ATypeID = CSV_Variant then
  1547.           begin
  1548.             v2:= v2^.CV_Variant;
  1549.             if V2 = nil then
  1550.             begin
  1551.               Perform := False;
  1552.               RunError(Self, EVariantIsNil);
  1553.               exit;
  1554.             end;
  1555.           end;
  1556.         end;
  1557. {$ENDIF}
  1558.         if (not IsIntegerType(v2)) and (not ISBooleanType(v2)) then begin
  1559.           RunError(Self, ETypeMismatch);
  1560.           Perform := False;
  1561.           exit;
  1562.         end;
  1563.         case V1^.VType^.atypeid of
  1564.           CSV_UByte: begin
  1565.               V1^.Cv_UByte := V1^.Cv_UByte or TCSV_UByte(GetInteger(v2));
  1566.             end;
  1567.           CSV_SByte: begin
  1568.               V1^.Cv_SByte := V1^.Cv_SByte or TCSV_SByte(GetInteger(v2));
  1569.             end;
  1570.           CSV_UInt16: begin
  1571.               V1^.Cv_UInt16 := V1^.Cv_UInt16 or TCSV_uInt16(GetInteger(v2));
  1572.             end;
  1573.           CSV_SInt16: begin
  1574.               V1^.Cv_SInt16 := V1^.Cv_SInt16 or TCSV_SInt16(GetInteger(v2));
  1575.             end;
  1576.           CSV_UInt32: begin
  1577.               V1^.Cv_UInt32 := V1^.Cv_UInt32 or TCSV_UInt32(GetInteger(v2));
  1578.             end;
  1579.           CSV_SInt32: begin
  1580.               V1^.Cv_SInt32 := V1^.Cv_SInt32 or TCSV_SInt32(GetInteger(v2));
  1581.             end;
  1582.           CSV_Bool: begin
  1583.               V1^.Cv_Bool := V1^.Cv_Bool or GetBoolean(v2);
  1584.             end;
  1585.         else begin
  1586.             Err := True;
  1587.             RunError(Self, ETypeMismatch);
  1588.  
  1589.           end;
  1590.         end;
  1591.       end;
  1592.     ptXor: begin
  1593. {$IFDEF VARIANTSUPPORT}
  1594.         if v1^.VType^.ATypeID = CSV_Variant then
  1595.         begin
  1596.           v1 := v1^.CV_Variant;
  1597.           if v1 = nil then
  1598.           begin
  1599.             Perform := False;
  1600.             RunError(Self, EVariantIsNil);
  1601.             exit;
  1602.           end;
  1603.           if V2^.VType^.ATypeID = CSV_Variant then
  1604.           begin
  1605.             v2:= v2^.CV_Variant;
  1606.             if V2 = nil then
  1607.             begin
  1608.               Perform := False;
  1609.               RunError(Self, EVariantIsNil);
  1610.               exit;
  1611.             end;
  1612.           end;
  1613.         end;
  1614. {$ENDIF}
  1615.         if (not IsIntegerType(v2)) and (not ISBooleanType(v2)) then begin
  1616.           Perform := False;
  1617.           RunError(Self, ETypeMismatch);
  1618.           exit;
  1619.         end;
  1620.         case V1^.VType^.atypeid of
  1621.           CSV_UByte: begin
  1622.               V1^.Cv_UByte := V1^.Cv_UByte xor TCSV_UByte(GetInteger(v2));
  1623.             end;
  1624.           CSV_SByte: begin
  1625.               V1^.Cv_SByte := V1^.Cv_SByte xor TCSV_SByte(GetInteger(v2));
  1626.             end;
  1627.           CSV_UInt16: begin
  1628.               V1^.Cv_UInt16 := V1^.Cv_UInt16 xor TCSV_UInt16(GetInteger(v2));
  1629.             end;
  1630.           CSV_SInt16: begin
  1631.               V1^.Cv_SInt16 := V1^.Cv_SInt16 xor TCSV_SInt16(GetInteger(v2));
  1632.             end;
  1633.           CSV_UInt32: begin
  1634.               V1^.Cv_UInt32 := V1^.Cv_UInt32 xor TCSV_UInt32(GetInteger(v2));
  1635.             end;
  1636.           CSV_SInt32: begin
  1637.               V1^.Cv_SInt32 := V1^.Cv_SInt32 xor TCSV_SInt32(GetInteger(v2));
  1638.             end;
  1639.           CSV_Bool: begin
  1640.               V1^.Cv_Bool := V1^.Cv_Bool xor GetBoolean(v2);
  1641.             end;
  1642.         else begin
  1643.             Err := True;
  1644.             RunError(Self, ETypeMismatch);
  1645.           end;
  1646.         end;
  1647.       end;
  1648.     PtShr: begin
  1649. {$IFDEF VARIANTSUPPORT}
  1650.         if v1^.VType^.ATypeID = CSV_Variant then
  1651.         begin
  1652.           v1 := v1^.CV_Variant;
  1653.           if v1 = nil then
  1654.           begin
  1655.             Perform := False;
  1656.             RunError(Self, EVariantIsNil);
  1657.             exit;
  1658.           end;
  1659.           if V2^.VType^.ATypeID = CSV_Variant then
  1660.           begin
  1661.             v2:= v2^.CV_Variant;
  1662.             if V2 = nil then
  1663.             begin
  1664.               Perform := False;
  1665.               RunError(Self, EVariantIsNil);
  1666.               exit;
  1667.             end;
  1668.           end;
  1669.         end;
  1670. {$ENDIF}
  1671.         if not IsIntegerType(v2) then begin
  1672.           Perform := True;
  1673.           RunError(Self, ETypeMismatch);
  1674.           exit;
  1675.         end;
  1676.         case V1^.VType^.atypeid of
  1677.           CSV_UByte: begin
  1678.               V1^.Cv_UByte := V1^.Cv_UByte shr TCSV_UByte(GetInteger(v2));
  1679.             end;
  1680.           CSV_SByte: begin
  1681.               V1^.Cv_SByte := V1^.Cv_SByte shr TCSV_SByte(GetInteger(v2));
  1682.             end;
  1683.           CSV_UInt16: begin
  1684.               V1^.Cv_UInt16 := V1^.Cv_UInt16 shr TCSV_UInt16(GetInteger(v2));
  1685.             end;
  1686.           CSV_SInt16: begin
  1687.               V1^.Cv_SInt16 := V1^.Cv_SInt16 shr TCSV_SInt16(GetInteger(v2));
  1688.             end;
  1689.           CSV_UInt32: begin
  1690.               V1^.Cv_UInt32 := V1^.Cv_UInt32 shr TCSV_UInt32(GetInteger(v2));
  1691.             end;
  1692.           CSV_SInt32: begin
  1693.               V1^.Cv_SInt32 := V1^.Cv_SInt32 shr TCSV_SInt32(GetInteger(v2));
  1694.             end;
  1695.         else begin
  1696.             Err := True;
  1697.             RunError(Self, ETypeMismatch);
  1698.           end;
  1699.         end;
  1700.       end;
  1701.     PtShl: begin
  1702. {$IFDEF VARIANTSUPPORT}
  1703.         if v1^.VType^.ATypeID = CSV_Variant then
  1704.         begin
  1705.           v1 := v1^.CV_Variant;
  1706.           if v1 = nil then
  1707.           begin
  1708.             Perform := False;
  1709.             RunError(Self, EVariantIsNil);
  1710.             exit;
  1711.           end;
  1712.           if V2^.VType^.ATypeID = CSV_Variant then
  1713.           begin
  1714.             v2:= v2^.CV_Variant;
  1715.             if V2 = nil then
  1716.             begin
  1717.               Perform := False;
  1718.               RunError(Self, EVariantIsNil);
  1719.               exit;
  1720.             end;
  1721.           end;
  1722.         end;
  1723. {$ENDIF}
  1724.         if not IsIntegerType(v2) then begin
  1725.           Perform := True;
  1726.           RunError(Self, ETypeMismatch);
  1727.           exit;
  1728.         end;
  1729.         case V1^.VType^.atypeid of
  1730.           CSV_UByte: begin
  1731.               V1^.Cv_UByte := V1^.Cv_UByte shl TCSV_UByte(GetInteger(v2));
  1732.             end;
  1733.           CSV_SByte: begin
  1734.               V1^.Cv_SByte := V1^.Cv_SByte shl TCSV_SByte(GetInteger(v2));
  1735.             end;
  1736.           CSV_UInt16: begin
  1737.               V1^.Cv_UInt16 := V1^.Cv_UInt16 shl TCSV_UInt16(GetInteger(v2));
  1738.             end;
  1739.           CSV_SInt16: begin
  1740.               V1^.Cv_SInt16 := V1^.Cv_SInt16 shl TCSV_SInt16(GetInteger(v2));
  1741.             end;
  1742.           CSV_UInt32: begin
  1743.               V1^.Cv_UInt32 := V1^.Cv_UInt32 shl TCSV_UInt32(GetInteger(v2));
  1744.             end;
  1745.           CSV_SInt32: begin
  1746.               V1^.Cv_SInt32 := V1^.Cv_SInt32 shl TCSV_SInt32(GetInteger(v2));
  1747.             end;
  1748.         else begin
  1749.             Err := True;
  1750.             RunError(Self, ETypeMismatch);
  1751.           end;
  1752.         end;
  1753.       end;
  1754.     PtGreater:
  1755.     begin
  1756. {$IFDEF VARIANTSUPPORT}
  1757.       if (v1^.VType^.ATypeID = CSV_Variant) and (V1^.CV_Variant = nil) then
  1758.       begin
  1759.         Perform := False;
  1760.         RunError(Self, EVariantIsNil);
  1761.         exit;
  1762.       end;
  1763.       if (v2^.VType^.ATypeID = CSV_Variant) and (V2^.CV_Variant = nil) then
  1764.       begin
  1765.         Perform := False;
  1766.         RunError(Self, EVariantIsNil);
  1767.         exit;
  1768.       end;
  1769. {$ENDIF}
  1770.       case V1^.VType^.atypeid of
  1771.         CSV_UByte: if IsRealType(v2) then
  1772.             MakeItBool(V1^.Cv_UByte > GetReal(v2))
  1773.           else
  1774.             MakeItBool(V1^.Cv_UByte > TCSV_UByte(GetInteger(v2)));
  1775.         CSV_SByte: if IsRealType(v2) then
  1776.             MakeItBool(V1^.Cv_SByte > GetReal(v2))
  1777.           else
  1778.             MakeItBool(V1^.Cv_SByte > TCSV_SByte(GetInteger(v2)));
  1779.         CSV_Char: if v2^.VType^.atypeid = CSV_Char then
  1780.             MakeItBool(V1^.Cv_Char > v2^.Cv_Char)
  1781.           else begin
  1782.             Err := True;
  1783.             RunError(Self, ETypeMismatch);
  1784.           end;
  1785.         CSV_UInt16: if IsRealType(v2) then
  1786.             MakeItBool(V1^.Cv_UInt16 > GetReal(v2))
  1787.           else
  1788.             MakeItBool(V1^.Cv_UInt16 > TCSV_UInt16(GetInteger(v2)));
  1789.         CSV_SInt16: if IsRealType(v2) then
  1790.             MakeItBool(V1^.Cv_SInt16 > GetReal(v2))
  1791.           else
  1792.             MakeItBool(V1^.Cv_SInt16 > TCSV_SInt16(GetInteger(v2)));
  1793.         CSV_UInt32: if IsRealType(v2) then
  1794.             MakeItBool(V1^.Cv_UInt32 > GetReal(v2))
  1795.           else
  1796.             MakeItBool(V1^.Cv_UInt32 > TCSV_UInt32(GetInteger(v2)));
  1797.         CSV_SInt32: if IsRealType(v2) then
  1798.             MakeItBool(V1^.Cv_SInt32 > GetReal(v2))
  1799.           else
  1800.             MakeItBool(V1^.Cv_SInt32 > TCSV_SInt32(GetInteger(v2)));
  1801.         CSV_Real: MakeItBool(V1^.CV_Real > GetReal(v2));
  1802.         CSV_Single: MakeItBool(V1^.CV_Single > GetReal(v2));
  1803.         CSV_Double: MakeItBool(V1^.CV_Double > GetReal(v2));
  1804.         CSV_Extended: MakeItBool(V1^.Cv_Extended > GetReal(v2));
  1805.         CSV_Comp: MakeItBool(V1^.CV_comp > GetReal(v2));
  1806.         CSV_Bool: MakeItBool(V1^.Cv_Bool > v2^.Cv_Bool);
  1807.         CSV_String: MakeItBool(V1^.Cv_Str > v2^.Cv_Str);
  1808.       else begin
  1809.           Err := True;
  1810.           RunError(Self, ETypeMismatch);
  1811.         end;
  1812.       end; {case item}
  1813.     end;
  1814.     PtLess:
  1815.     begin
  1816. {$IFDEF VARIANTSUPPORT}
  1817.       if (v1^.VType^.ATypeID = CSV_Variant) and (V1^.CV_Variant = nil) then
  1818.       begin
  1819.         Perform := False;
  1820.         RunError(Self, EVariantIsNil);
  1821.         exit;
  1822.       end;
  1823.       if (v2^.VType^.ATypeID = CSV_Variant) and (V2^.CV_Variant = nil) then
  1824.       begin
  1825.         Perform := False;
  1826.         RunError(Self, EVariantIsNil);
  1827.         exit;
  1828.       end;
  1829. {$ENDIF}
  1830.       case V1^.VType^.atypeid of
  1831.         CSV_UByte: if IsRealType(v2) then
  1832.             MakeItBool(V1^.Cv_UByte < GetReal(v2))
  1833.           else
  1834.             MakeItBool(V1^.Cv_UByte < TCSV_UByte(GetInteger(v2)));
  1835.         CSV_SByte: if IsRealType(v2) then
  1836.             MakeItBool(V1^.Cv_SByte < GetReal(v2))
  1837.           else
  1838.             MakeItBool(V1^.Cv_SByte < TCSV_SByte(GetInteger(v2)));
  1839.         CSV_Char: if v2^.VType^.atypeid = CSV_Char then
  1840.             MakeItBool(V1^.Cv_Char < v2^.Cv_Char)
  1841.           else begin
  1842.             Err := True;
  1843.             RunError(Self, ETypeMismatch);
  1844.           end;
  1845.  
  1846.         CSV_UInt16: if IsRealType(v2) then
  1847.             MakeItBool(V1^.Cv_UInt16 < GetReal(v2))
  1848.           else
  1849.             MakeItBool(V1^.Cv_UInt16 < TCSV_UInt16(GetInteger(v2)));
  1850.         CSV_SInt16: if IsRealType(v2) then
  1851.             MakeItBool(V1^.Cv_SInt16 < GetReal(v2))
  1852.           else
  1853.             MakeItBool(V1^.Cv_SInt16 < TCSV_SInt16(GetInteger(v2)));
  1854.         CSV_UInt32: if IsRealType(v2) then
  1855.             MakeItBool(V1^.Cv_UInt32 < GetReal(v2))
  1856.           else
  1857.             MakeItBool(V1^.Cv_UInt32 < TCSV_UInt32(GetInteger(v2)));
  1858.         CSV_SInt32: if IsRealType(v2) then
  1859.             MakeItBool(V1^.Cv_SInt32 < GetReal(v2))
  1860.           else
  1861.             MakeItBool(V1^.Cv_SInt32 < TCSV_SInt32(GetInteger(v2)));
  1862.         CSV_Real: MakeItBool(V1^.CV_Real < GetReal(v2));
  1863.         CSV_Single: MakeItBool(V1^.CV_Single < GetReal(v2));
  1864.         CSV_Double: MakeItBool(V1^.CV_Double < GetReal(v2));
  1865.         CSV_Extended: MakeItBool(V1^.Cv_Extended < GetReal(v2));
  1866.         CSV_Comp: MakeItBool(V1^.CV_comp < GetReal(v2));
  1867.         CSV_Bool: MakeItBool(V1^.Cv_Bool < v2^.Cv_Bool);
  1868.         CSV_String: MakeItBool(V1^.Cv_Str < v2^.Cv_Str);
  1869.       else begin
  1870.           Err := True;
  1871.           RunError(Self, ETypeMismatch);
  1872.         end;
  1873.       end; {case item}
  1874.     end;
  1875.     PtGreaterEqual:
  1876.     begin
  1877. {$IFDEF VARIANTSUPPORT}
  1878.       if (v1^.VType^.ATypeID = CSV_Variant) and (V1^.CV_Variant = nil) then
  1879.       begin
  1880.         Perform := False;
  1881.         RunError(Self, EVariantIsNil);
  1882.         exit;
  1883.       end;
  1884.       if (v2^.VType^.ATypeID = CSV_Variant) and (V2^.CV_Variant = nil) then
  1885.       begin
  1886.         Perform := False;
  1887.         RunError(Self, EVariantIsNil);
  1888.         exit;
  1889.       end;
  1890. {$ENDIF}
  1891.       case V1^.VType^.atypeid of
  1892.         CSV_UByte: if IsRealType(v2) then
  1893.             MakeItBool(V1^.Cv_UByte >= GetReal(v2))
  1894.           else
  1895.             MakeItBool(V1^.Cv_UByte >= TCSV_UByte(GetInteger(v2)));
  1896.         CSV_SByte: if IsRealType(v2) then
  1897.             MakeItBool(V1^.Cv_SByte >= GetReal(v2))
  1898.           else
  1899.             MakeItBool(V1^.Cv_SByte >= TCSV_SByte(GetInteger(v2)));
  1900.         CSV_Char: if v2^.VType^.atypeid = CSV_Char then
  1901.             MakeItBool(V1^.Cv_Char >= v2^.Cv_Char)
  1902.           else begin
  1903.             Err := True;
  1904.             RunError(Self, ETypeMismatch);
  1905.           end;
  1906.         CSV_UInt16: if IsRealType(v2) then
  1907.             MakeItBool(V1^.Cv_UInt16 >= GetReal(v2))
  1908.           else
  1909.             MakeItBool(V1^.Cv_UInt16 >= TCSV_UInt16(GetInteger(v2)));
  1910.         CSV_SInt16: if IsRealType(v2) then
  1911.             MakeItBool(V1^.Cv_SInt16 >= GetReal(v2))
  1912.           else
  1913.             MakeItBool(V1^.Cv_SInt16 >= TCSV_SInt16(GetInteger(v2)));
  1914.         CSV_UInt32: if IsRealType(v2) then
  1915.             MakeItBool(V1^.Cv_UInt32 >= GetReal(v2))
  1916.           else
  1917.             MakeItBool(V1^.Cv_UInt32 >= TCSV_UInt32(GetInteger(v2)));
  1918.         CSV_SInt32: if IsRealType(v2) then
  1919.             MakeItBool(V1^.Cv_SInt32 >= GetReal(v2))
  1920.           else
  1921.             MakeItBool(V1^.Cv_SInt32 >= TCSV_SInt32(GetInteger(v2)));
  1922.         CSV_Real: MakeItBool(V1^.CV_Real >= GetReal(v2));
  1923.         CSV_Single: MakeItBool(V1^.CV_Single >= GetReal(v2));
  1924.         CSV_Double: MakeItBool(V1^.CV_Double >= GetReal(v2));
  1925.         CSV_Extended: MakeItBool(V1^.Cv_Extended >= GetReal(v2));
  1926.         CSV_Comp: MakeItBool(V1^.CV_comp >= GetReal(v2));
  1927.         CSV_Bool: MakeItBool(V1^.Cv_Bool >= v2^.Cv_Bool);
  1928.         CSV_String: MakeItBool(V1^.Cv_Str >= v2^.Cv_Str);
  1929.       else begin
  1930.           Err := True;
  1931.           RunError(Self, ETypeMismatch);
  1932.         end;
  1933.       end; {case item}
  1934.     end;
  1935.     PtLessEqual:
  1936.     begin
  1937. {$IFDEF VARIANTSUPPORT}
  1938.       if (v1^.VType^.ATypeID = CSV_Variant) and (V1^.CV_Variant = nil) then
  1939.       begin
  1940.         Perform := False;
  1941.         RunError(Self, EVariantIsNil);
  1942.         exit;
  1943.       end;
  1944.       if (v2^.VType^.ATypeID = CSV_Variant) and (V2^.CV_Variant = nil) then
  1945.       begin
  1946.         Perform := False;
  1947.         RunError(Self, EVariantIsNil);
  1948.         exit;
  1949.       end;
  1950. {$ENDIF}
  1951.       case V1^.VType^.atypeid of
  1952.         CSV_UByte: if IsRealType(v2) then
  1953.             MakeItBool(V1^.Cv_UByte <= GetReal(v2))
  1954.           else
  1955.             MakeItBool(V1^.Cv_UByte <= TCSV_UByte(GetInteger(v2)));
  1956.         CSV_SByte: if IsRealType(v2) then
  1957.             MakeItBool(V1^.Cv_SByte <= GetReal(v2))
  1958.           else
  1959.             MakeItBool(V1^.Cv_SByte <= TCSV_SByte(GetInteger(v2)));
  1960.         CSV_Char: if v2^.VType^.atypeid = CSV_Char then
  1961.             MakeItBool(V1^.Cv_Char <= v2^.Cv_Char)
  1962.           else begin
  1963.             Err := True;
  1964.             RunError(Self, ETypeMismatch);
  1965.           end;
  1966.         CSV_UInt16: if IsRealType(v2) then
  1967.             MakeItBool(V1^.Cv_UInt16 <= GetReal(v2))
  1968.           else
  1969.             MakeItBool(V1^.Cv_UInt16 <= TCSV_UInt16(GetInteger(v2)));
  1970.         CSV_SInt16: if IsRealType(v2) then
  1971.             MakeItBool(V1^.Cv_SInt16 <= GetReal(v2))
  1972.           else
  1973.             MakeItBool(V1^.Cv_SInt16 <= TCSV_SInt16(GetInteger(v2)));
  1974.         CSV_UInt32: if IsRealType(v2) then
  1975.             MakeItBool(V1^.Cv_UInt32 <= GetReal(v2))
  1976.           else
  1977.             MakeItBool(V1^.Cv_UInt32 <= TCSV_UInt32(GetInteger(v2)));
  1978.         CSV_SInt32: if IsRealType(v2) then
  1979.             MakeItBool(V1^.Cv_SInt32 <= GetReal(v2))
  1980.           else
  1981.             MakeItBool(V1^.Cv_SInt32 <= TCSV_SInt32(GetInteger(v2)));
  1982.         CSV_Real: MakeItBool(V1^.CV_Real <= GetReal(v2));
  1983.         CSV_Single: MakeItBool(V1^.CV_Single <= GetReal(v2));
  1984.         CSV_Double: MakeItBool(V1^.CV_Double <= GetReal(v2));
  1985.         CSV_Extended: MakeItBool(V1^.Cv_Extended <= GetReal(v2));
  1986.         CSV_Comp: MakeItBool(V1^.CV_comp <= GetReal(v2));
  1987.         CSV_Bool: MakeItBool(V1^.Cv_Bool <= v2^.Cv_Bool);
  1988.         CSV_String: MakeItBool(V1^.Cv_Str <= v2^.Cv_Str);
  1989.       else begin
  1990.           Err := True;
  1991.           RunError(Self, ETypeMismatch);
  1992.         end;
  1993.       end; {case item}
  1994.     end;
  1995.     PtEqual:
  1996.     begin
  1997.       case V1^.VType^.atypeid of
  1998. {$IFDEF VARIANTSUPPORT}
  1999.         CSV_Variant:
  2000.         begin
  2001.           if v2^.VType^.ATypeId = CSV_Variant then
  2002.           begin
  2003.             if (v1^.CV_Variant = nil) or (v2^.CV_Variant = nil) then
  2004.             begin
  2005.               MakeItBool(V1^.CV_Variant = V2^.CV_Variant);
  2006.             end else begin
  2007.               Err := not Perform(V1^.CV_Variant, v2^.CV_Variant, t);
  2008.             end;
  2009.           end else begin
  2010.             if v2^.VType^.ATypeid = CSV_Special then
  2011.             begin
  2012.               if v2^.CV_Spec =0 then
  2013.               begin
  2014.                 MakeItBool(v1^.CV_Variant = nil);
  2015.               end;
  2016.             end else if not assigned(v1^.Cv_Variant) then
  2017.             begin
  2018.               RunError(Self, EVariantIsNil);
  2019.               Perform := False;
  2020.               exit;
  2021.             end else
  2022.               Err := not Perform(V1^.CV_Variant, v2, t);
  2023.           end;
  2024.         end;
  2025. {$ENDIF}
  2026.         CSV_UByte: if IsRealType(v2) then
  2027.             MakeItBool(V1^.Cv_UByte = GetReal(v2))
  2028.           else
  2029.             MakeItBool(V1^.Cv_UByte = TCSV_UByte(GetInteger(v2)));
  2030.         CSV_SByte: if IsRealType(v2) then
  2031.             MakeItBool(V1^.Cv_SByte = GetReal(v2))
  2032.           else
  2033.             MakeItBool(V1^.Cv_SByte = TCSV_SByte(GetInteger(v2)));
  2034.         CSV_Char: if v2^.VType^.atypeid = CSV_Char then
  2035.             MakeItBool(V1^.Cv_Char = v2^.Cv_Char)
  2036.           else begin
  2037.             Err := True;
  2038.             RunError(Self, ETypeMismatch);
  2039.           end;
  2040.         CSV_UInt16: if IsRealType(v2) then
  2041.             MakeItBool(V1^.Cv_UInt16 = GetReal(v2))
  2042.           else
  2043.             MakeItBool(V1^.Cv_UInt16 = TCSV_UInt16(GetInteger(v2)));
  2044.         CSV_SInt16: if IsRealType(v2) then
  2045.             MakeItBool(V1^.Cv_SInt16 = GetReal(v2))
  2046.           else
  2047.             MakeItBool(V1^.Cv_SInt16 = TCSV_SInt16(GetInteger(v2)));
  2048.         CSV_UInt32: if IsRealType(v2) then
  2049.             MakeItBool(V1^.Cv_UInt32 = GetReal(v2))
  2050.           else
  2051.             MakeItBool(V1^.Cv_UInt32 = TCSV_UInt32(GetInteger(v2)));
  2052.         CSV_SInt32: if IsRealType(v2) then
  2053.             MakeItBool(V1^.Cv_SInt32 = GetReal(v2))
  2054.           else
  2055.             MakeItBool(V1^.Cv_SInt32 = TCSV_SInt32(GetInteger(v2)));
  2056.         CSV_Real: MakeItBool(V1^.CV_Real = GetReal(v2));
  2057.         CSV_Single: MakeItBool(V1^.CV_Single = GetReal(v2));
  2058.         CSV_Double: MakeItBool(V1^.CV_Double = GetReal(v2));
  2059.         CSV_Extended: MakeItBool(V1^.Cv_Extended = GetReal(v2));
  2060.         CSV_Comp: MakeItBool(V1^.CV_comp = GetReal(v2));
  2061.         CSV_Bool: MakeItBool(V1^.Cv_Bool = v2^.Cv_Bool);
  2062.         CSV_String: MakeItBool(V1^.Cv_Str = v2^.Cv_Str);
  2063.         CSV_Special: MakeItBool(V1^.CV_Spec = v2^.CV_Spec);
  2064. {$IFNDEF NOCLASSES}
  2065.         CSV_Class: begin
  2066.             if v2^.VType^.atypeid = CSV_Special then begin
  2067.               if v2^.CV_Spec = 0 then { nil } begin
  2068.                 MakeItBool(V1^.CV_Class = nil);
  2069.               end;
  2070.             end else
  2071.               MakeItBool(V1^.CV_Class = v2^.CV_Class);
  2072.           end;
  2073.         CSV_ClassRef: begin
  2074.             if v2^.VType^.atypeid = CSV_Special then begin
  2075.               if v2^.CV_Spec = 0 then { nil } begin
  2076.                 MakeItBool(V1^.Cv_ClassRef = nil);
  2077.               end;
  2078.             end else
  2079.               MakeItBool(V1^.Cv_ClassRef = v2^.Cv_ClassRef);
  2080.           end;
  2081. {$ENDIF}
  2082.         CSV_ProcVariable: begin
  2083.             if v2^.VType^.atypeid = CSV_Special then begin
  2084.               if v2^.CV_Spec = 0 then { nil } begin
  2085.                 MakeItBool(V1^.Cv_Proc = nil);
  2086.               end;
  2087.             end else
  2088.               MakeItBool((V1^.Cv_Proc = v2^.Cv_Proc){$IFNDEF NOCLASSES} and (V1^.Cv_ProcSelf = v2^.Cv_ProcSelf){$ENDIF});
  2089.           end;
  2090.       else begin
  2091.           Err := True;
  2092.           RunError(Self, ETypeMismatch);
  2093.         end;
  2094.       end; {case item}
  2095.     end;
  2096.     PtNotEqual:
  2097.     begin
  2098.       case V1^.VType^.atypeid of
  2099. {$IFDEF VARIANTSUPPORT}
  2100.         CSV_Variant:
  2101.         begin
  2102.           if v2^.VType^.ATypeId = CSV_Variant then
  2103.           begin
  2104.             if (v1^.CV_Variant = nil) or (v2^.CV_Variant = nil) then
  2105.             begin
  2106.               MakeItBool(V1^.CV_Variant <> V2^.CV_Variant);
  2107.             end else begin
  2108.               Err := not Perform(V1^.CV_Variant, v2^.CV_Variant, t);
  2109.             end;
  2110.           end else begin
  2111.             if v2^.VType^.ATypeid = CSV_Special then
  2112.             begin
  2113.               if v2^.CV_Spec =0 then
  2114.               begin
  2115.                 MakeItBool(v1^.CV_Variant <> nil);
  2116.               end;
  2117.             end else if not assigned(v1^.Cv_Variant) then
  2118.             begin
  2119.               RunError(Self, EVariantIsNil);
  2120.               Perform := False;
  2121.               exit;
  2122.             end else
  2123.               Err := not Perform(V1^.CV_Variant, v2, t);
  2124.           end;
  2125.         end;
  2126. {$ENDIF}
  2127.         CSV_UByte: if IsRealType(v2)
  2128.           then MakeItBool(V1^.Cv_UByte <> GetReal(v2))
  2129.           else MakeItBool(V1^.Cv_UByte <> TCSV_UByte(GetInteger(v2)));
  2130.         CSV_SByte: if IsRealType(v2)
  2131.           then MakeItBool(V1^.Cv_SByte <> GetReal(v2))
  2132.           else MakeItBool(V1^.Cv_SByte <> TCSV_SByte(GetInteger(v2)));
  2133.         CSV_Char: if v2^.VType^.atypeid = CSV_Char
  2134.           then MakeItBool(V1^.Cv_Char <> v2^.Cv_Char)
  2135.           else begin
  2136.             Err := True;
  2137.             RunError(Self, ETypeMismatch);
  2138.           end;
  2139.         CSV_UInt16: if IsRealType(v2)
  2140.           then MakeItBool(V1^.Cv_UInt16 <> GetReal(v2))
  2141.           else MakeItBool(V1^.Cv_UInt16 <> TCSV_UInt16(GetInteger(v2)));
  2142.         CSV_SInt16: if IsRealType(v2)
  2143.           then MakeItBool(V1^.Cv_SInt16 <> GetReal(v2))
  2144.           else MakeItBool(V1^.Cv_SInt16 <> TCSV_SInt16(GetInteger(v2)));
  2145.         CSV_UInt32: if IsRealType(v2)
  2146.           then MakeItBool(V1^.Cv_UInt32 <> GetReal(v2))
  2147.           else MakeItBool(V1^.Cv_UInt32 <> TCSV_UInt32(GetInteger(v2)));
  2148.         CSV_SInt32: if IsRealType(v2)
  2149.           then MakeItBool(V1^.Cv_SInt32 <> GetReal(v2))
  2150.           else MakeItBool(V1^.Cv_SInt32 <> TCSV_SInt32(GetInteger(v2)));
  2151.         CSV_Real: MakeItBool(V1^.CV_Real <> GetReal(v2));
  2152.         CSV_Single: MakeItBool(V1^.CV_Single <> GetReal(v2));
  2153.         CSV_Double: MakeItBool(V1^.CV_Double <> GetReal(v2));
  2154.         CSV_Extended: MakeItBool(V1^.Cv_Extended <> GetReal(v2));
  2155.         CSV_Comp: MakeItBool(V1^.CV_comp <> GetReal(v2));
  2156.         CSV_Bool: MakeItBool(V1^.Cv_Bool <> v2^.Cv_Bool);
  2157.         CSV_String: MakeItBool(V1^.Cv_Str <> v2^.Cv_Str);
  2158.         CSV_Special: MakeItBool(V1^.CV_Spec <> v2^.CV_Spec);
  2159. {$IFNDEF NOCLASSES}
  2160.         CSV_Class: begin
  2161.             if v2^.VType^.atypeid = CSV_Special then begin
  2162.               if v2^.CV_Spec = 0 then { nil } begin
  2163.                 MakeItBool(V1^.CV_Class <> nil);
  2164.               end;
  2165.             end else
  2166.               MakeItBool(V1^.CV_Class <> v2^.CV_Class);
  2167.           end;
  2168.         CSV_ClassRef: begin
  2169.             if v2^.VType^.atypeid = CSV_Special then begin
  2170.               if v2^.CV_Spec = 0 then { nil } begin
  2171.                 MakeItBool(V1^.Cv_ClassRef <> nil);
  2172.               end;
  2173.             end else
  2174.               MakeItBool(V1^.Cv_ClassRef <> v2^.Cv_ClassRef);
  2175.           end;
  2176. {$ENDIF}
  2177.         CSV_ProcVariable: begin
  2178.             if v2^.VType^.atypeid = CSV_Special then begin
  2179.               if v2^.CV_Spec = 0 then { nil } begin
  2180.                 MakeItBool(V1^.Cv_Proc <> nil);
  2181.               end;
  2182.             end else
  2183.               MakeItBool((V1^.Cv_Proc <> v2^.Cv_Proc){$IFNDEF NOCLASSES} or (V1^.Cv_ProcSelf <> v2^.Cv_ProcSelf){$ENDIF});
  2184.           end;
  2185.       else begin
  2186.           Err := True;
  2187.           RunError(Self, ETypeMismatch);
  2188.         end;
  2189.       end; {case item}
  2190.     end;
  2191.   end;
  2192.   Perform := not Err;
  2193. end;
  2194.  
  2195. //-------------------------------------------------------------------
  2196.  
  2197. function TIfPasScript.ReadType(Parser: TIfPascalParser; AllowClasses: Boolean; const Name: string): PTypeRec;
  2198. var
  2199.   Ex: Pointer;
  2200.  
  2201.   function ReadRecord: PTypeRec;
  2202.   var
  2203.     Exu: PIFSRecordType;
  2204.     s, CurrNames: string;
  2205.  
  2206.     function IsDuplicate(p: string): Boolean;
  2207.     begin
  2208.       IsDuplicate := False;
  2209.       if (Pos(p + ' ', s) = 1) or (Pos(' ' + p + ' ', s) <> 0) then
  2210.         IsDuplicate := True;
  2211.       if (Pos(p + ' ', CurrNames) = 1) or (Pos(' ' + p + ' ', CurrNames) <> 0) then
  2212.         IsDuplicate := True;
  2213.     end;
  2214.   begin
  2215.     Parser.Next;
  2216.     s := '';
  2217.     while Parser.CurrTokenId <> CSTII_End do begin
  2218.       CurrNames := '';
  2219.       repeat
  2220.         if Parser.CurrTokenId <> CSTI_Identifier then begin
  2221.           RunError(Self, EIdentifierExpected);
  2222.           ReadRecord := nil;
  2223.           exit;
  2224.         end;
  2225.         if IsDuplicate(Parser.GetToken) then begin
  2226.           RunError(Self, EDuplicateIdentifier);
  2227.           ReadRecord := nil;
  2228.           exit;
  2229.         end else
  2230.           CurrNames := CurrNames + Parser.GetToken + ' ';
  2231.         Parser.Next;
  2232.         if (Parser.CurrTokenId = CSTI_Comma) then begin
  2233.           Parser.Next;
  2234.         end else if (Parser.CurrTokenId = CSTI_Colon) then begin
  2235.           break;
  2236.         end else begin
  2237.           RunError(Self, EColonExpected);
  2238.           ReadRecord := nil;
  2239.           exit;
  2240.         end;
  2241.       until False;
  2242.       Parser.Next;
  2243.       Ex := ReadType(Parser, False, '');
  2244.       if Ex = nil then begin
  2245.         ReadRecord := nil;
  2246.         exit;
  2247.       end;
  2248.       if (Parser.CurrTokenId <> CSTI_Semicolon) and (Parser.CurrTokenId <> CSTII_End) then begin
  2249.         RunError(Self, ESemiColonExpected);
  2250.         ReadRecord := nil;
  2251.         exit;
  2252.       end;
  2253.       while Length(CurrNames) > 0 do begin
  2254.         s := s + copy(CurrNames, 1, Pos(' ', CurrNames) - 1) + ' ' + inttostr(Longint(Ex)) + ' ';
  2255.         Delete(CurrNames, 1, Pos(' ', CurrNames));
  2256.       end;
  2257.       if Parser.CurrTokenId = CSTI_Semicolon then
  2258.         Parser.Next;
  2259.     end;
  2260.     Parser.Next;
  2261.     New(Exu);
  2262.     Exu^.u := s;
  2263.     ReadRecord := TM_Add(Types, Name, CSV_Record, Exu);
  2264.   end; // readclass
  2265. {$IFNDEF NOCLASSES}
  2266.  
  2267.   function ReadClass: PTypeRec;
  2268.   type
  2269.     TClassPlace = (cpPrivate, cpPublic, cpProtected);
  2270.   var
  2271.     I, Nc: PTypeRec;
  2272.     CurrPlace: TClassPlace;
  2273.     AllowVars: Boolean;
  2274.  
  2275.     Myclass: PIFSClassType;
  2276.  
  2277.     function CheckDuplicate(const s: string): Boolean;
  2278.     var
  2279.       u: string;
  2280.       I: Integer;
  2281.  
  2282.       function Rf(const s: string): string;
  2283.       begin
  2284.         Rf := copy(s, 2, Length(s) - 1);
  2285.       end;
  2286.     begin
  2287.       if s = 'SELF' then begin
  2288.         CheckDuplicate := True;
  2289.         exit;
  2290.       end;
  2291.       u := Myclass.Variables.u;
  2292.       while Length(u) > 0 do begin
  2293.         if Rf(Fw(u)) = s then begin
  2294.           CheckDuplicate := True;
  2295.           exit;
  2296.         end;
  2297.         Rfw(u);
  2298.         Rfw(u);
  2299.       end;
  2300.       for I := 0 to Myclass.Properties.Count - 1 do begin
  2301.         if PPropertyDef(Myclass.Properties.GetItem(I))^.Name = s then begin
  2302.           CheckDuplicate := True;
  2303.           exit;
  2304.         end;
  2305.       end;
  2306.       for I := 0 to Myclass.Procedures.Count - 1 do begin
  2307.         u := PProcedure(Myclass.Procedures.GetItem(I))^.Name;
  2308.         if Pos('!', u) = 1 then begin
  2309.           Delete(u, 1, 1);
  2310.           if s = u then begin
  2311.             CheckDuplicate := True;
  2312.             exit;
  2313.           end;
  2314.         end;
  2315.       end;
  2316.       CheckDuplicate := False;
  2317.     end;
  2318.  
  2319.     function AddProc: Boolean;
  2320.     var
  2321.       p: PProcedure;
  2322.       IsFunc: Boolean;
  2323.       t: PTypeRec;
  2324.       iv: Byte;
  2325.       vn: string;
  2326.  
  2327.       function CheckOverridable(InhClass: PTypeRec): Boolean;
  2328.  
  2329.         function SearchList(List: TIfList): Byte;
  2330.         var
  2331.           I: Integer;
  2332.           n: PProcedure;
  2333.         begin
  2334.           for I := 0 to List.Count - 1 do begin
  2335.             n := List.GetItem(I);
  2336.             if n^.Name = p^.Name then begin
  2337.               if (n^.Decl = p^.Decl) and ((n^.Flags and not $30) = (p^.Flags and not $30)) and ((n^.Flags or $30) <> 0) then begin
  2338.                 SearchList := 1;
  2339.                 exit;
  2340.               end;
  2341.               SearchList := 2;
  2342.               exit;
  2343.             end;
  2344.           end;
  2345.           SearchList := 0;
  2346.         end; {searchlist}
  2347.       begin
  2348.         CheckOverridable := False;
  2349.         while assigned(InhClass) do begin
  2350.           case SearchList(PIFSClassType(InhClass^.Ext)^.Procedures) of
  2351.             0: InhClass := PIFSClassType(InhClass^.Ext)^.InheritsFrom;
  2352.             1: begin
  2353.                 CheckOverridable := True;
  2354.                 exit;
  2355.               end;
  2356.             2: exit;
  2357.           end; {case}
  2358.         end; {if}
  2359.       end; {checkoverridable}
  2360.  
  2361.       function PCheckDuplic(const n: string): Boolean;
  2362.       var
  2363.         u, a: string;
  2364.       begin
  2365.         PCheckDuplic := False;
  2366.         if n = p^.Name then PCheckDuplic := True else begin
  2367.           u := p^.Decl;
  2368.           rs(u);
  2369.           while Length(u) > 0 do begin
  2370.             a := Fw(u);
  2371.             Rfw(u); {remove name}
  2372.             Rfw(u); {remove type}
  2373.             if Pos('!', a) = 1 then
  2374.               Delete(a, 1, 1);
  2375.             if a = n then begin
  2376.               PCheckDuplic := True;
  2377.               exit;
  2378.             end;
  2379.           end;
  2380.           u := vn;
  2381.           while Length(u) > 0 do begin
  2382.             a := Fw(u);
  2383.             Rfw(u); {remove name}
  2384.             if a = n then begin
  2385.               PCheckDuplic := True;
  2386.               exit;
  2387.             end;
  2388.           end;
  2389.         end;
  2390.       end;
  2391.  
  2392.     begin
  2393.       New(p);
  2394.       p^.FScriptEngine := Self;
  2395.       p^.Mode := 0;
  2396.       p^.offset := -1;
  2397.       p^.ClassType := Nc;
  2398.       case CurrPlace of
  2399.         cpPrivate: p^.Flags := $1;
  2400.         cpPublic: p^.Flags := $2;
  2401.         cpProtected: p^.Flags := $3;
  2402.       end;
  2403.       if Parser.CurrTokenId = CSTII_Constructor then begin
  2404.         IsFunc := False;
  2405.         p^.Flags := p^.Flags or $40
  2406.       end else if Parser.CurrTokenId = CSTII_Destructor then begin
  2407.         IsFunc := False;
  2408.         p^.Flags := p^.Flags or $80
  2409.       end else if Parser.CurrTokenId = CSTII_Function then begin
  2410.         IsFunc := True;
  2411.       end else
  2412.         IsFunc := False; {procedure}
  2413.       Parser.Next;
  2414.       if Parser.CurrTokenId <> CSTI_Identifier then begin
  2415.         RunError(Self, EIdentifierExpected);
  2416.         Dispose(p);
  2417.         AddProc := False;
  2418.         exit;
  2419.       end;
  2420.       if CheckDuplicate(Parser.GetToken) then begin
  2421.         RunError(Self, EDuplicateIdentifier);
  2422.         AddProc := False;
  2423.         Dispose(p);
  2424.         exit;
  2425.       end;
  2426.       p^.Name := '!' + Parser.GetToken;
  2427.       Parser.Next;
  2428.       if Parser.CurrTokenId = CSTI_OpenRound then begin
  2429.         Parser.Next;
  2430.         if Parser.CurrTokenId = CSTI_CloseRound then begin
  2431.           Parser.Next;
  2432.         end else begin
  2433.           repeat
  2434.             if Parser.CurrTokenId = CSTII_Var then begin
  2435.               Parser.Next;
  2436.               iv := 1; {var}
  2437.             end else iv := 0; {normal}
  2438.             if Parser.CurrTokenId <> CSTI_Identifier then begin
  2439.               RunError(Self, EIdentifierExpected);
  2440.               AddProc := False;
  2441.               Dispose(p);
  2442.               exit;
  2443.             end; {if}
  2444.             vn := '';
  2445.             if CheckDuplicate(Parser.GetToken) or PCheckDuplic(Parser.GetToken) then begin
  2446.               RunError(Self, EDuplicateIdentifier);
  2447.               AddProc := False;
  2448.               Dispose(p);
  2449.               exit;
  2450.             end;
  2451.             vn := Parser.GetToken;
  2452.             Parser.Next;
  2453.             while Parser.CurrTokenId = CSTI_Comma do begin
  2454.               Parser.Next;
  2455.               if Parser.CurrTokenId <> CSTI_Identifier then begin
  2456.                 RunError(Self, EIdentifierExpected);
  2457.                 AddProc := False;
  2458.                 Dispose(p);
  2459.                 exit;
  2460.               end; {if}
  2461.               if (CheckDuplicate(Parser.GetToken)) or PCheckDuplic(Parser.GetToken) then begin
  2462.                 RunError(Self, EDuplicateIdentifier);
  2463.                 AddProc := False;
  2464.                 Dispose(p);
  2465.                 exit;
  2466.               end; {if}
  2467.               vn := vn + ' ' + Parser.GetToken;
  2468.               Parser.Next;
  2469.             end; {while}
  2470.             if Parser.CurrTokenId <> CSTI_Colon then begin
  2471.               RunError(Self, EColonExpected);
  2472.               AddProc := False;
  2473.               Dispose(p);
  2474.               exit;
  2475.             end;
  2476.             Parser.Next;
  2477.             t := GetTypeLink(TM_Get(Types, Parser.GetToken));
  2478.             if t = nil then begin
  2479.               RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  2480.               Dispose(p);
  2481.               AddProc := False;
  2482.               exit;
  2483.             end;
  2484.             if iv = 0 then begin
  2485.               while Length(vn) > 0 do begin
  2486.                 p^.Decl := p^.Decl + ' ' + Fw(vn) + ' ' + inttostr(Longint(t));
  2487.                 Rfw(vn);
  2488.               end;
  2489.             end else
  2490.               if iv = 1 then begin
  2491.                 while Length(vn) > 0 do begin
  2492.                   p^.Decl := p^.Decl + ' !' + Fw(vn) + ' ' + inttostr(Longint(t));
  2493.                   Rfw(vn);
  2494.                 end;
  2495.               end;
  2496.             Parser.Next;
  2497.             if Parser.CurrTokenId = CSTI_Semicolon then begin
  2498.               Parser.Next;
  2499.             end else
  2500.               if (Parser.CurrTokenId <> CSTI_CloseRound) then begin
  2501.                 RunError(Self, ESemiColonExpected);
  2502.                 Dispose(p);
  2503.                 AddProc := False;
  2504.                 exit;
  2505.               end else
  2506.                 break;
  2507.           until False;
  2508.           Parser.Next;
  2509.         end;
  2510.       end;
  2511.       if IsFunc then begin
  2512.         if Parser.CurrTokenId <> CSTI_Colon then begin
  2513.           RunError(Self, EColonExpected);
  2514.           Dispose(p);
  2515.           AddProc := False;
  2516.           exit;
  2517.         end;
  2518.         Parser.Next;
  2519.         t := GetTypeLink(TM_Get(Types, Parser.GetToken));
  2520.         if t = nil then begin
  2521.           RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  2522.           Dispose(p);
  2523.           AddProc := False;
  2524.           exit;
  2525.         end;
  2526.         p^.Decl := inttostr(Longint(t)) + p^.Decl;
  2527.         Parser.Next;
  2528.       end else
  2529.         p^.Decl := '0' + p^.Decl;
  2530.  
  2531.       if Parser.CurrTokenId <> CSTI_Semicolon then begin
  2532.         RunError(Self, ESemiColonExpected);
  2533.         AddProc := False;
  2534.         Dispose(p);
  2535.         exit;
  2536.       end;
  2537.       Parser.Next;
  2538.       if Parser.CurrTokenId = CSTII_Virtual then begin
  2539.         p^.Flags := p^.Flags or $10;
  2540.         Parser.Next;
  2541.         if Parser.CurrTokenId <> CSTI_Semicolon then begin
  2542.           RunError(Self, ESemiColonExpected);
  2543.           AddProc := False;
  2544.           Dispose(p);
  2545.           exit;
  2546.         end;
  2547.         Parser.Next;
  2548.       end else if Parser.CurrTokenId = CSTII_Override then begin
  2549.         if not CheckOverridable(I) then begin
  2550.           RunError(Self, ECanNotOverride);
  2551.           AddProc := False;
  2552.           Dispose(p);
  2553.           exit;
  2554.         end;
  2555.         p^.Flags := p^.Flags or $20;
  2556.         Parser.Next;
  2557.         if Parser.CurrTokenId <> CSTI_Semicolon then begin
  2558.           RunError(Self, ESemiColonExpected);
  2559.           AddProc := False;
  2560.           Dispose(p);
  2561.           exit;
  2562.         end;
  2563.         Parser.Next;
  2564.       end;
  2565.       Procedures.Add(p);
  2566.       Myclass.Procedures.Add(p);
  2567.       AddProc := True;
  2568.     end; //addproc
  2569.  
  2570.     function AddVar: Boolean;
  2571.  
  2572.       procedure ReallyAddVar(const Name: string; FType: PTypeRec);
  2573.       begin
  2574.         case CurrPlace of
  2575.           cpPrivate: Myclass.Variables.u := Myclass.Variables.u + '1' + Name + ' ' + inttostr(Longint(FType)) + ' ';
  2576.           cpPublic: Myclass.Variables.u := Myclass.Variables.u + '2' + Name + ' ' + inttostr(Longint(FType)) + ' ';
  2577.           cpProtected: Myclass.Variables.u := Myclass.Variables.u + '3' + Name + ' ' + inttostr(Longint(FType)) + ' ';
  2578.         end;
  2579.         Inc(Myclass.VarCount);
  2580.       end;
  2581.     var
  2582.       Vars: string;
  2583.       FType: PTypeRec;
  2584.  
  2585.       function IVarCheck(const s: string): Boolean;
  2586.       var
  2587.         u: string;
  2588.       begin
  2589.         u := Vars;
  2590.         while Length(u) > 0 do begin
  2591.           if Fw(u) = s then begin
  2592.             IVarCheck := True;
  2593.             exit;
  2594.           end;
  2595.           Rfw(u);
  2596.         end;
  2597.         IVarCheck := False;
  2598.       end;
  2599.  
  2600.     begin
  2601.       if CheckDuplicate(Parser.GetToken) or (IVarCheck(Parser.GetToken)) then begin
  2602.         RunError(Self, EDuplicateIdentifier);
  2603.         AddVar := False;
  2604.         exit;
  2605.       end; {if}
  2606.       Vars := Parser.GetToken;
  2607.       Parser.Next;
  2608.       while Parser.CurrTokenId = CSTI_Comma do begin
  2609.         Parser.Next;
  2610.         if Parser.CurrTokenId <> CSTI_Identifier then begin
  2611.           RunError(Self, EIdentifierExpected);
  2612.           AddVar := False;
  2613.           exit;
  2614.         end; {if}
  2615.         if CheckDuplicate(Parser.GetToken) or (IVarCheck(Parser.GetToken)) then begin
  2616.           RunError(Self, EDuplicateIdentifier);
  2617.           AddVar := False;
  2618.           exit;
  2619.         end; {if}
  2620.         Vars := Vars + ' ' + Parser.GetToken;
  2621.         Parser.Next;
  2622.       end; {if}
  2623.       if Parser.CurrTokenId <> CSTI_Colon then begin
  2624.         RunError(Self, EColonExpected);
  2625.         AddVar := False;
  2626.         exit;
  2627.       end; {if}
  2628.       Parser.Next;
  2629.       FType := ReadType(Parser, False, '');
  2630.       if FType = nil then begin
  2631.         RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  2632.         AddVar := False;
  2633.         exit;
  2634.       end;
  2635.       if Parser.CurrTokenId <> CSTI_Semicolon then begin
  2636.         RunError(Self, ESemiColonExpected);
  2637.         AddVar := False;
  2638.         exit;
  2639.       end;
  2640.       Parser.Next;
  2641.       while Length(Vars) > 0 do begin
  2642.         ReallyAddVar(Fw(Vars), FType);
  2643.         Rfw(Vars);
  2644.       end;
  2645.       AddVar := True;
  2646.     end; // addvar
  2647.  
  2648.     function AddProperty: Boolean;
  2649.     var
  2650.       p: PPropertyDef;
  2651.       proc: PProcedure;
  2652.       FType: PTypeRec;
  2653.  
  2654.       function FindProc(const Name: string): Boolean;
  2655.       var
  2656.         I: Integer;
  2657.       begin
  2658.         for I := 0 to Myclass.Procedures.Count - 1 do begin
  2659.           if PProcedure(Myclass.Procedures.GetItem(I))^.Name = '!' + Name then begin
  2660.             proc := Myclass.Procedures.GetItem(I);
  2661.             FindProc := True;
  2662.             exit;
  2663.           end;
  2664.         end;
  2665.         FindProc := False;
  2666.       end;
  2667.  
  2668.       function CheckProc(read: Boolean): Boolean;
  2669.       var
  2670.         s: string;
  2671.       begin
  2672.         CheckProc := False;
  2673.         s := proc.Decl;
  2674.         if read then begin
  2675.           if Fw(s) <> inttostr(Longint(FType)) then begin
  2676.             exit;
  2677.           end;
  2678.           Rfw(s);
  2679.           if s <> '' then
  2680.             exit;
  2681.         end else begin
  2682.           if Fw(s) <> '0' then
  2683.             exit;
  2684.           Rfw(s);
  2685.           Rfw(s);
  2686.           if Fw(s) <> inttostr(Longint(FType)) then
  2687.             exit;
  2688.           Rfw(s);
  2689.           if s <> '' then
  2690.             exit;
  2691.         end;
  2692.         CheckProc := True;
  2693.       end;
  2694.  
  2695.       function CheckVariable(const Name: string): Longint;
  2696.       var
  2697.         s: string;
  2698.         I: Integer;
  2699.       begin
  2700.         s := Myclass^.Variables.u;
  2701.         CheckVariable := -1;
  2702.         I := 0;
  2703.         while Length(s) > 0 do begin
  2704.           if copy(Fw(s), 2, Length(Fw(s)) - 1) = Name then begin
  2705.             Rfw(s);
  2706.             if Fw(s) <> inttostr(Longint(FType)) then begin
  2707.               RunError(Self, ETypeMismatch);
  2708.               exit;
  2709.             end;
  2710.             CheckVariable := I;
  2711.             exit;
  2712.           end;
  2713.           Rfw(s);
  2714.           Rfw(s);
  2715.           Inc(I);
  2716.         end;
  2717.         RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  2718.       end;
  2719.     begin
  2720.       Parser.Next;
  2721.       if Parser.CurrTokenId <> CSTI_Identifier then begin
  2722.         RunError(Self, EIdentifierExpected);
  2723.         AddProperty := False;
  2724.         exit;
  2725.       end;
  2726.       New(p);
  2727.       if CheckDuplicate(Parser.GetToken) then begin
  2728.         RunError(Self, EDuplicateIdentifier);
  2729.         Dispose(p);
  2730.         AddProperty := False;
  2731.         exit;
  2732.       end;
  2733.       p^.Name := Parser.GetToken;
  2734.       case CurrPlace of
  2735.         cpPrivate: p^.CV_PropFlags := $10;
  2736.         cpPublic: p^.CV_PropFlags := $20;
  2737.         cpProtected: p^.CV_PropFlags := $30;
  2738.       end;
  2739.       Parser.Next;
  2740.       if Parser.CurrTokenId <> CSTI_Colon then begin
  2741.         RunError(Self, EColonExpected);
  2742.         Dispose(p);
  2743.         AddProperty := False;
  2744.         exit;
  2745.       end;
  2746.       Parser.Next;
  2747.       FType := GetTypeLink(TM_Get(Types, Parser.GetToken));
  2748.       p^.CV_Type := FType;
  2749.  
  2750.       if FType = nil then begin
  2751.         RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  2752.         Dispose(p);
  2753.         AddProperty := False;
  2754.         exit;
  2755.       end;
  2756.       Parser.Next;
  2757.       if Parser.GetToken = 'READ' then begin
  2758.         Parser.Next;
  2759.         if FindProc(Parser.GetToken) then begin
  2760.           if not CheckProc(True) then begin
  2761.             RunError(Self, ETypeMismatch);
  2762.             Dispose(p);
  2763.             AddProperty := False;
  2764.             exit;
  2765.           end;
  2766.           p^.CV_PropFlags := p^.CV_PropFlags or 5;
  2767.           p^.CV_PropRead := proc;
  2768.         end else begin
  2769.           p.CV_PropRead := Pointer(CheckVariable(Parser.GetToken));
  2770.           if Longint(p^.CV_PropRead) = -1 then begin
  2771.             Dispose(p);
  2772.             AddProperty := False;
  2773.             exit;
  2774.           end;
  2775.           p^.CV_PropFlags := p^.CV_PropFlags or 1;
  2776.         end;
  2777.         Parser.Next;
  2778.       end;
  2779.       if Parser.GetToken = 'WRITE' then begin
  2780.         Parser.Next;
  2781.         if FindProc(Parser.GetToken) then begin
  2782.           if not CheckProc(False) then begin
  2783.             RunError(Self, ETypeMismatch);
  2784.             Dispose(p);
  2785.             AddProperty := False;
  2786.             exit;
  2787.           end;
  2788.           p^.CV_PropFlags := p^.CV_PropFlags or 10;
  2789.           p^.CV_PropWrite := proc;
  2790.         end else begin
  2791.           p.CV_PropWrite := Pointer(CheckVariable(Parser.GetToken));
  2792.           if Longint(p^.CV_PropWrite) = -1 then begin
  2793.             Dispose(p);
  2794.             AddProperty := False;
  2795.             exit;
  2796.           end;
  2797.           p^.CV_PropFlags := p^.CV_PropFlags or 2;
  2798.         end;
  2799.         Parser.Next;
  2800.       end;
  2801.       if Parser.CurrTokenId <> CSTI_Semicolon then begin
  2802.         RunError(Self, ESemiColonExpected);
  2803.         Dispose(p);
  2804.         AddProperty := False;
  2805.         exit;
  2806.       end;
  2807.       Parser.Next;
  2808.       if (p^.CV_PropFlags and $3) = 0 then begin
  2809.         RunError(Self, ECanNotReadOrWriteProperty);
  2810.         Dispose(p);
  2811.         AddProperty := False;
  2812.         exit;
  2813.       end;
  2814.       AddProperty := True;
  2815.       Myclass.Properties.Add(p);
  2816.     end;
  2817.   begin
  2818.     CurrPlace := cpPublic;
  2819.     AllowVars := True; // No vars are allowed after a procedure definition
  2820.     Parser.Next;
  2821.     if Parser.CurrTokenId = CSTI_OpenRound then begin
  2822.       Parser.Next;
  2823.       I := GetTypeLink(TM_Get(Types, Parser.GetToken));
  2824.       if not assigned(I) then begin
  2825.         RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  2826.         ReadClass := nil;
  2827.         exit;
  2828.       end; {if}
  2829.       if I.atypeid <> CSV_Class then begin
  2830.         RunError(Self, EClassTypeExpected);
  2831.         ReadClass := nil;
  2832.         exit;
  2833.       end; {if}
  2834.       Parser.Next;
  2835.       if Parser.CurrTokenId <> CSTI_CloseRound then begin
  2836.         RunError(Self, ECloseRoundExpected);
  2837.         ReadClass := nil;
  2838.         exit;
  2839.       end; {if}
  2840.       Parser.Next;
  2841.     end else {if}  begin
  2842.       if Parser.CurrTokenId = CSTII_Of then begin
  2843.         Parser.Next;
  2844.         if Parser.CurrTokenId <> CSTI_Identifier then begin
  2845.           RunError(Self, EIdentifierExpected);
  2846.           ReadClass := nil;
  2847.           exit;
  2848.         end;
  2849.         I := GetTypeLink(TM_Get(Types, Parser.GetToken));
  2850.         if I^.atypeid <> CSV_Class then begin
  2851.           RunError(Self, EClassTypeExpected);
  2852.           ReadClass := nil;
  2853.           exit;
  2854.         end;
  2855.         ReadClass := TM_Add(Types, Name, CSV_ClassRef, I);
  2856.         exit;
  2857.       end;
  2858.       I := GetTypeLink(TM_Get(Types, 'TOBJECT'));
  2859.       if not assigned(I) then begin
  2860.         RunError(Self, EClassTypeExpected);
  2861.         ReadClass := nil;
  2862.         exit;
  2863.       end; {if}
  2864.     end; {else if}
  2865.     New(Myclass);
  2866.     Myclass^.InheritsFrom := I;
  2867.     Myclass^.VarNoStart := PIFSClassType(Myclass^.InheritsFrom^.Ext)^.VarNoStart + PIFSClassType(Myclass^.InheritsFrom^.Ext)^.VarCount;
  2868.     Myclass^.PropStart := PIFSClassType(Myclass^.InheritsFrom^.Ext)^.PropStart + PIFSClassType(Myclass^.InheritsFrom^.Ext)^.Properties.Count;
  2869.     Myclass^.VarCount := 0;
  2870.     Myclass^.Variables.u := '';
  2871.     Myclass^.Procedures := TIfList.Create;
  2872.     Myclass^.Properties := TIfList.Create;
  2873.     Nc := TM_Add(Types, Name, CSV_Class, Myclass);
  2874.     while Parser.CurrTokenId <> CSTII_End do begin
  2875.       if Parser.CurrTokenId = CSTII_Private then begin
  2876.         CurrPlace := cpPrivate;
  2877.         Parser.Next;
  2878.         AllowVars := True;
  2879.       end else if Parser.CurrTokenId = CSTII_Public then begin
  2880.         CurrPlace := cpPublic;
  2881.         Parser.Next;
  2882.         AllowVars := True;
  2883.       end else if Parser.CurrTokenId = CSTII_Published then begin
  2884.         CurrPlace := cpPublic;
  2885.         Parser.Next;
  2886.         AllowVars := True;
  2887.       end else if Parser.CurrTokenId = CSTII_Protected then begin
  2888.         CurrPlace := cpProtected;
  2889.         Parser.Next;
  2890.         AllowVars := True;
  2891.       end else if (Parser.CurrTokenId = CSTII_Property) then begin
  2892.         if not AddProperty then begin
  2893.           ReadClass := nil;
  2894.           exit;
  2895.         end;
  2896.       end else if (Parser.CurrTokenId = CSTII_Procedure) or
  2897.         (Parser.CurrTokenId = CSTII_Function) or
  2898.         (Parser.CurrTokenId = CSTII_Constructor) or
  2899.         (Parser.CurrTokenId = CSTII_Destructor) then begin
  2900.         if not AddProc then begin
  2901.           ReadClass := nil;
  2902.           exit;
  2903.         end;
  2904.         AllowVars := False;
  2905.       end else if Parser.CurrTokenId = CSTI_Identifier then begin
  2906.         if not AllowVars then begin
  2907.           RunError(Self, EEndExpected);
  2908.           ReadClass := nil;
  2909.           exit;
  2910.         end;
  2911.         if not AddVar then begin
  2912.           ReadClass := nil;
  2913.           exit;
  2914.         end;
  2915.       end else begin
  2916.         RunError(Self, EEndExpected);
  2917.         ReadClass := nil;
  2918.         exit;
  2919.       end;
  2920.     end;
  2921.     Parser.Next;
  2922.     ReadClass := Nc;
  2923.   end; {ReadClass}
  2924. {$ENDIF}
  2925.  
  2926.   function ReadProcedure: PTypeRec;
  2927.   var
  2928.     Func: Boolean;
  2929.     Data: PIFSProcType;
  2930.     vn: string;
  2931.     iv: Byte;
  2932.     t: PTypeRec;
  2933.  
  2934.     function PCheckDuplic(const n: string): Boolean;
  2935.     var
  2936.       u, a: string;
  2937.     begin
  2938.       PCheckDuplic := False;
  2939.       u := Data^.Decl;
  2940.       rs(u);
  2941.       while Length(u) > 0 do begin
  2942.         a := Fw(u);
  2943.         Rfw(u); {remove name}
  2944.         Rfw(u); {remove type}
  2945.         if Pos('!', a) = 1 then
  2946.           Delete(a, 1, 1);
  2947.         if a = n then begin
  2948.           PCheckDuplic := True;
  2949.           exit;
  2950.         end;
  2951.       end;
  2952.       u := vn;
  2953.       while Length(u) > 0 do begin
  2954.         a := Fw(u);
  2955.         Rfw(u); {remove name}
  2956.         if a = n then begin
  2957.           PCheckDuplic := True;
  2958.           exit;
  2959.         end;
  2960.       end;
  2961.     end;
  2962.   begin
  2963.     ReadProcedure := nil;
  2964.     Func := Parser.CurrTokenId = CSTII_Function;
  2965.     Parser.Next;
  2966.     New(Data);
  2967.     Data^.Decl := '';
  2968.     Data^.Method := False;
  2969.     if Parser.CurrTokenId = CSTI_OpenRound then begin
  2970.       Parser.Next;
  2971.       if Parser.CurrTokenId = CSTI_CloseRound then begin
  2972.         Parser.Next;
  2973.       end else begin
  2974.         repeat
  2975.           if Parser.CurrTokenId = CSTII_Var then begin
  2976.             Parser.Next;
  2977.             iv := 1; {var}
  2978.           end else iv := 0; {normal}
  2979.           if Parser.CurrTokenId <> CSTI_Identifier then begin
  2980.             RunError(Self, EIdentifierExpected);
  2981.             Dispose(Data);
  2982.             exit;
  2983.           end; {if}
  2984.           vn := '';
  2985.           if PCheckDuplic(Parser.GetToken) then begin
  2986.             RunError(Self, EDuplicateIdentifier);
  2987.             Dispose(Data);
  2988.             exit;
  2989.           end;
  2990.           vn := Parser.GetToken;
  2991.           Parser.Next;
  2992.           while Parser.CurrTokenId = CSTI_Comma do begin
  2993.             Parser.Next;
  2994.             if Parser.CurrTokenId <> CSTI_Identifier then begin
  2995.               RunError(Self, EIdentifierExpected);
  2996.               Dispose(Data);
  2997.               exit;
  2998.             end; {if}
  2999.             if PCheckDuplic(Parser.GetToken) then begin
  3000.               RunError(Self, EDuplicateIdentifier);
  3001.               Dispose(Data);
  3002.               exit;
  3003.             end; {if}
  3004.             vn := vn + ' ' + Parser.GetToken;
  3005.             Parser.Next;
  3006.           end; {while}
  3007.           if Parser.CurrTokenId <> CSTI_Colon then begin
  3008.             RunError(Self, EColonExpected);
  3009.             Dispose(Data);
  3010.             exit;
  3011.           end;
  3012.           Parser.Next;
  3013.           t := GetTypeLink(TM_Get(Types, Parser.GetToken));
  3014.           if t = nil then begin
  3015.             RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3016.             Dispose(Data);
  3017.             exit;
  3018.           end;
  3019.           if iv = 0 then begin
  3020.             while Length(vn) > 0 do begin
  3021.               Data^.Decl := Data^.Decl + ' ' + Fw(vn) + ' ' + inttostr(Longint(t));
  3022.               Rfw(vn);
  3023.             end;
  3024.           end else
  3025.             if iv = 1 then begin
  3026.               while Length(vn) > 0 do begin
  3027.                 Data^.Decl := Data^.Decl + ' !' + Fw(vn) + ' ' + inttostr(Longint(t));
  3028.                 Rfw(vn);
  3029.               end;
  3030.             end;
  3031.           Parser.Next;
  3032.           if Parser.CurrTokenId = CSTI_Semicolon then begin
  3033.             Parser.Next;
  3034.           end else
  3035.             if (Parser.CurrTokenId <> CSTI_CloseRound) then begin
  3036.               RunError(Self, ESemiColonExpected);
  3037.               Dispose(Data);
  3038.               exit;
  3039.             end else
  3040.               break;
  3041.         until False;
  3042.         Parser.Next;
  3043.       end;
  3044.     end;
  3045.     if Func then begin
  3046.       if Parser.CurrTokenId <> CSTI_Colon then begin
  3047.         RunError(Self, EColonExpected);
  3048.         Dispose(Data);
  3049.         exit;
  3050.       end;
  3051.       Parser.Next;
  3052.       t := GetTypeLink(TM_Get(Types, Parser.GetToken));
  3053.       if t = nil then begin
  3054.         RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3055.         Dispose(Data);
  3056.         exit;
  3057.       end;
  3058.       Data^.Decl := inttostr(Longint(t)) + Data^.Decl;
  3059.       Parser.Next;
  3060.     end else
  3061.       Data^.Decl := '0' + Data^.Decl;
  3062.     {$IFNDEF NOCLASSES}
  3063.     if Parser.CurrTokenId = CSTII_Of then
  3064.     begin
  3065.       Parser.Next;
  3066.       if Parser.GetToken <> 'OBJECT' then
  3067.       begin
  3068.         RunError(Self, EObjectExpected);
  3069.         Dispose(Data);
  3070.         exit;
  3071.       end;
  3072.       Parser.Next;
  3073.       Data^.Method := true;
  3074.     end;
  3075.     {$ENDIF}
  3076.     Result := TM_Add(Types, Name, CSV_ProcVariable, Data);
  3077.   end; // readprocedure
  3078. begin
  3079.   if (Parser.CurrTokenId = CSTII_Procedure) or (Parser.CurrTokenId = CSTII_Function) then begin
  3080.     ReadType := ReadProcedure;
  3081.   end else
  3082. {$IFNDEF NOCLASSES}
  3083.     if Parser.CurrTokenId = CSTII_Class then begin
  3084.       if not AllowClasses then begin
  3085.         RunError(Self, EClassNotAllowedHere);
  3086.         ReadType := nil;
  3087.         exit;
  3088.       end;
  3089.       ReadType := ReadClass;
  3090.     end else {$ENDIF}
  3091.       if Parser.CurrTokenId = CSTII_Array then begin
  3092.         Parser.Next;
  3093.         if Parser.CurrTokenId <> CSTII_Of then begin
  3094.           RunError(Self, EOfExpected);
  3095.           ReadType := nil;
  3096.           exit;
  3097.         end;
  3098.         Parser.Next;
  3099.         if Parser.CurrTokenId = CSTII_Const then begin
  3100.           ReadType := TM_Add(Types, Name, CSV_Array, TM_Add(Types,  '', CSV_Var, nil));
  3101.           Parser.Next;
  3102.         end else begin
  3103.           Ex := ReadType(Parser, False, '');
  3104.           if Ex <> nil then
  3105.             ReadType := TM_Add(Types, Name, CSV_Array, Ex)
  3106.           else begin
  3107.             ReadType := nil;
  3108.             RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3109.           end;
  3110.         end;
  3111.       end else if Parser.CurrTokenId = CSTII_Record then begin
  3112.         ReadType := ReadRecord;
  3113.       end else begin
  3114.         Ex := GetTypeLink(TM_Get(Types, Parser.GetToken));
  3115.         Parser.Next;
  3116.         if Ex = nil then begin
  3117.           RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3118.           ReadType := nil;
  3119.           exit;
  3120.         end;
  3121.         if PTypeRec(Ex)^.Ident = '' then begin
  3122.           PTypeRec(Ex)^.Ident := Name;
  3123.           ReadType := Ex;
  3124.  
  3125.         end else begin
  3126.           if Name = '' then
  3127.             ReadType := Ex
  3128.           else
  3129.             ReadType := TM_Add(Types, Name, CSV_TypeCopy, Ex);
  3130.         end;
  3131.       end;
  3132. end;
  3133. //-------------------------------------------------------------------
  3134. {$IFNDEF NOCLASSES}
  3135.  
  3136. function TIfPasScript.AddClass(const Name, Decl: string; RegProc: Pointer): PTypeRec;
  3137. var
  3138.   p: PTypeRec;
  3139.   I: Integer;
  3140.   proc: PProcedure;
  3141. begin
  3142.   p := AddType(Name, Decl);
  3143.   if p = nil then begin
  3144.     AddClass := nil;
  3145.     exit;
  3146.   end;
  3147.   for I := 0 to PIFSClassType(p^.Ext)^.Procedures.Count - 1 do begin
  3148.     proc := PIFSClassType(p^.Ext)^.Procedures.GetItem(I);
  3149.     proc^.Mode := 1;
  3150.     proc^.proc1 := RegProc;
  3151.   end;
  3152.   AddClass := p;
  3153. end;
  3154. {$ENDIF}
  3155. //-------------------------------------------------------------------
  3156. function TIfPasScript.AddTypeEx(Name: string): PTypeRec;
  3157. begin
  3158.   Result := TM_Add(Types, FastUppercase(Name), CSV_Var, nil);
  3159. end;
  3160. //-------------------------------------------------------------------
  3161. function TIfPasScript.AddType(const Name, Decl: string): PTypeRec;
  3162. var
  3163.   Parser: TIfPascalParser;
  3164.   E: TIFParserError;
  3165.   p: PTypeRec;
  3166. begin
  3167.   Parser := TIfPascalParser.Create;
  3168.   if not Parser.SetText(Decl, E) then
  3169.   begin
  3170.     AddType := nil;
  3171.     Parser.Free;
  3172.     exit;
  3173.   end;
  3174.   p := ReadType(Parser, True, FastUppercase(Name));
  3175.   if p = nil then begin
  3176.     AddType := nil;
  3177.     RunError(Self, ENoError);
  3178.   end else
  3179.     AddType := p;
  3180.   Parser.Free;  
  3181. end; {AddType}
  3182. //-------------------------------------------------------------------
  3183.  
  3184. function TIfPasScript.GetIdentifier(WithList: TIfList; Vars: PVariableManager; Mode: Byte; var w: PIfVariant): Byte;
  3185. {
  3186. When it returns nil in W and Result = True then a procedure is called
  3187. that has no result.
  3188.  
  3189. returns:
  3190.   2: Successful returns variant that needs to be freed.
  3191.   1: Successful returns variant and need assignment.
  3192.   False: Not
  3193.  
  3194. }
  3195.  
  3196.   function GetRecordSubVar(p: PIfVariant; const Name: string): PIfVariant;
  3197.   var
  3198.     s: string;
  3199.     I: Integer;
  3200.   begin
  3201.     s := PIFSRecordType(p.VType.Ext)^.u;
  3202.     I := 0;
  3203.     while Length(s) > 0 do begin
  3204.       if Fw(s) = Name then begin
  3205.         GetRecordSubVar := p.CV_RecItems.GetItem(I);
  3206.         exit;
  3207.       end;
  3208.       Rfw(s); {Remove name}
  3209.       Rfw(s); {Remove type}
  3210.       Inc(I);
  3211.     end;
  3212.     GetRecordSubVar := nil;
  3213.   end;
  3214.  
  3215. var
  3216. {$IFNDEF NOCLASSES}
  3217.   TempType: PTypeRec;
  3218.   VM: PVariableManager;
  3219.   AL: Longint;
  3220. {$ENDIF}
  3221.   p: PProcedure;
  3222.   C, c2: PIfVariant;
  3223.   AssignmentNeeded: Boolean;
  3224. begin
  3225.   GetIdentifier := 0;
  3226.   AssignmentNeeded := False;
  3227. {$IFNDEF NOCLASSES}
  3228.   if Parser.CurrTokenId = CSTII_Inherited then begin
  3229.     if Mode <> 0 then begin
  3230.       RunError(Self, EVariableExpected);
  3231.       exit;
  3232.     end;
  3233.     if (CurrProc = nil) or (CurrProc^.ClassType = nil) then begin
  3234.       RunError(Self, ENoInheritedAllowedHere);
  3235.       exit;
  3236.     end;
  3237.     Parser.Next;
  3238.     if Parser.CurrTokenId = CSTI_Semicolon then begin
  3239.       if IntProcDefParam(CurrProc^.Decl, 0) <> 0 then begin
  3240.         C := CreateCajVariant(Pointer(IntProcDefParam(CurrProc^.Decl, 0)));
  3241.       end else
  3242.         C := nil;
  3243.       RunInherited(CurrProc, Vars, C);
  3244.       if FError.ErrorCode <> 0 then begin
  3245.         exit;
  3246.       end;
  3247.       DestroyCajVariant(C);
  3248.     end else begin
  3249.       if Parser.CurrTokenId <> CSTI_Identifier then begin
  3250.         RunError(Self, EIdentifierExpected);
  3251.         exit;
  3252.       end;
  3253.       if not GetClassProcedure(nil, CurrProc^.ClassType^.Ext, Parser.GetToken, p, True) then begin
  3254.         RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3255.         exit;
  3256.       end;
  3257.       p := GetInheritedProc(p);
  3258.       if not assigned(p) then begin
  3259.         RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3260.         exit;
  3261.       end;
  3262.       Parser.Next;
  3263.       w := DoProc(WithList ,GetVarLink(Vm_Get(Vars, VM_Find(Vars, 'SELF')))^.CV_Class, p, Vars);
  3264.       if ErrorCode <> 0 then begin
  3265.         exit;
  3266.       end;
  3267.       if w = nil then begin
  3268.         GetIdentifier := 2;
  3269.         exit;
  3270.       end;
  3271.     end;
  3272.   end {CSTII_Inherited} else {$ENDIF}
  3273.   if Parser.CurrTokenId = CSTI_OpenRound then begin
  3274.     if Mode = 1 then begin
  3275.       RunError(Self, EVariableExpected);
  3276.       exit;
  3277.     end;
  3278.     Parser.Next;
  3279.     w := CreateVarType(nil);
  3280.     if not calc(WithList, Vars, w, CSTI_CloseRound, False) then begin
  3281.       DestroyCajVariant(w);
  3282.       exit;
  3283.     end;
  3284.     if Parser.CurrTokenId <> CSTI_CloseRound then begin
  3285.       RunError(Self, ECloseRoundExpected);
  3286.       DestroyCajVariant(w);
  3287.       exit;
  3288.     end;
  3289.     Parser.Next;
  3290.   end {CSTI_OpenRound} else if Parser.CurrTokenId = CSTI_Identifier then begin
  3291.     {$IFNDEF NOCLASSES}
  3292.     w := nil;
  3293.     if WithList.Count > 0 then
  3294.     begin
  3295.       for AL := 0 to WithList.Count -1 do
  3296.       begin
  3297.         if GetvarLink(WithList.GetItem(AL))^.VType.atypeid = CSV_Class then
  3298.         begin
  3299.           if GetClassVariable2(GetvarLink(WithList.GetItem(AL))^.CV_Class, GetvarLink(WithList.GetItem(AL))^.VType^.Ext, Parser.GetToken, w, True) then begin
  3300.             AssignmentNeeded := True;
  3301.             Parser.Next;
  3302.             Break;
  3303.           end else if GetClassProcedure(nil, GetvarLink(WithList.GetItem(AL))^.VType^.Ext, Parser.GetToken, p, True) then begin
  3304.             if Mode = 1 then begin
  3305.               RunError(Self, EVariableExpected);
  3306.               exit;
  3307.             end;
  3308.             Parser.Next;
  3309.             if Mode = 2 then begin
  3310.               w := CreateCajVariant(TM_Add(Types, '', CSV_ProcVariable, nil));
  3311.               w^.Cv_Proc := p;
  3312.               w^.Cv_ProcSelf := GetvarLink(WithList.GetItem(AL))^.CV_Class;
  3313.             end else begin
  3314.               if (P = CurrProc) and (assigned(vars)) and (IntProcDefParam(P^.Decl, 0)<>0) and (Parser.CurrTokenId <> CSTI_OpenRound) then
  3315.               begin
  3316.                 w := VM_Get(Vars, VM_Find(Vars, 'RESULT'));
  3317.                 AssignmentNeeded := True;
  3318.               end else
  3319.               begin
  3320.                 w := DoProc(WithList, GetvarLink(WithList.GetItem(AL))^.CV_Class, p, Vars);
  3321.                 if ErrorCode <> 0 then begin
  3322.                   exit;
  3323.                 end;
  3324.               end;
  3325.             end;
  3326.             if w = nil then begin
  3327.               GetIdentifier := 2;
  3328.               exit;
  3329.             end;
  3330.             break;
  3331.           end else W := nil;
  3332.         end;
  3333.       end;
  3334.     end;
  3335.     if not assigned(w) then
  3336.     if (TM_Get(Types, Parser.GetToken) <> nil) and not (PM_FIND(Procedures, Parser.GetToken) <> -1)then begin
  3337.       if Mode = 1 then begin
  3338.         RunError(Self, EVariableExpected);
  3339.         exit;
  3340.       end;
  3341.       TempType := GetTypeLink(TM_Get(Types, Parser.GetToken));
  3342.       if TempType^.atypeid <> CSV_Class then begin
  3343.         RunError(Self, EClassTypeExpected);
  3344.         exit;
  3345.       end;
  3346.       Parser.Next;
  3347.       if Parser.CurrTokenId = CSTI_Period then begin
  3348.         if Mode = 2 then begin
  3349.           RunError(Self, EVariableExpected);
  3350.           exit;
  3351.         end;
  3352.         Parser.Next;
  3353.         if Parser.CurrTokenId <> CSTI_Identifier then begin
  3354.           RunError(Self, EIdentifierExpected);
  3355.           exit;
  3356.         end;
  3357.         p := FindProc(TempType, '!' + Parser.GetToken);
  3358.         if p = nil then begin
  3359.           RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3360.           exit;
  3361.         end;
  3362.         w := DoClassConstructor(WithList, TempType, p, Vars);
  3363.         if FError.ErrorCode <> 0 then begin
  3364.           exit;
  3365.         end;
  3366.       end else if Parser.CurrTokenId = CSTI_OpenRound then begin
  3367.         Parser.Next;
  3368.         w := CreateCajVariant(TempType);
  3369.         if not calc(WithList, Vars, w, CSTI_CloseRound, False) then begin
  3370.           DestroyCajVariant(w);
  3371.           exit;
  3372.         end;
  3373.         if Parser.CurrTokenId <> CSTI_CloseRound then begin
  3374.           RunError(Self, ECloseRoundExpected);
  3375.           DestroyCajVariant(w);
  3376.           exit;
  3377.         end;
  3378.         Parser.Next;
  3379.       end else begin
  3380.         w := CreateCajVariant(TM_Add(Types, '', CSV_ClassRef, TempType));
  3381.         w^.Cv_ClassRef := TempType;
  3382.       end;
  3383.     end else 
  3384. {$ENDIF}
  3385.     if assigned(Vars) and (VM_Find(Vars, Parser.GetToken) <> -1) then begin
  3386.       AssignmentNeeded := True;
  3387.       w := GetVarLink(Vm_Get(Vars, VM_Find(Vars, Parser.GetToken)));
  3388.       Parser.Next;
  3389.     end else if VM_Find(Variables, Parser.GetToken) <> -1 then begin
  3390.       AssignmentNeeded := True;
  3391.       w := GetVarLink(Vm_Get(Variables, VM_Find(Variables, Parser.GetToken)));
  3392.       Parser.Next;
  3393.     end else if PM_Find(Procedures, Parser.GetToken) <> -1 then begin
  3394.       if Mode = 1 then begin
  3395.         RunError(Self, EVariableExpected);
  3396.         exit;
  3397.       end;
  3398.       p := PM_Get(Procedures, PM_Find(Procedures, Parser.GetToken));
  3399.       Parser.Next;
  3400.       if Mode = 2 then begin
  3401.         w := CreateCajVariant(TM_Add(Types, '', CSV_ProcVariable, nil));
  3402.         w^.Cv_Proc := p;
  3403. {$IFNDEF NOCLASSES}w^.Cv_ProcSelf := nil;{$ENDIF}
  3404.       end else begin
  3405.         if (P = CurrProc) and (assigned(vars)) and (IntProcDefParam(P^.Decl, 0)<>0) and (Parser.CurrTokenId <> CSTI_OpenRound) then
  3406.         begin
  3407.           w := VM_Get(Vars, VM_Find(Vars, 'RESULT'));
  3408.           AssignmentNeeded := True;
  3409.         end else
  3410.         begin
  3411.           w := DoProc(WithList, {$IFNDEF NOCLASSES}nil, {$ENDIF}p, Vars);
  3412.           if ErrorCode <> 0 then begin
  3413.             exit;
  3414.           end;
  3415.         end;
  3416.       end;
  3417.       if w = nil then begin
  3418.         GetIdentifier := 2;
  3419.         exit;
  3420.       end;
  3421.     end else begin
  3422.       RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3423.       exit;
  3424.     end;
  3425.   end else begin
  3426.     RunError(Self, EIdentifierExpected);
  3427.     exit;
  3428.   end;
  3429.   if (Parser.CurrTokenId = CSTI_Dereference) and (w^.VType^.ATypeId = CSV_ProcVariable) then
  3430.   begin
  3431.     if Mode <> 0 then
  3432.     begin
  3433.       if not AssignmentNeeded then DestroyCajVariant(w);
  3434.       RunError(Self, EVariableExpected);
  3435.       exit;
  3436.     end;
  3437.     Parser.Next;
  3438.     c := w;
  3439.     w := DoProc(WithList, {$IFNDEF NOCLASSES}W^.CV_ProcSelf,{$ENDIF} w^.Cv_Proc, Vars);
  3440.     if not AssignmentNeeded then DestroyCajVariant(C);
  3441.     if ErrorCode <> ENoError then
  3442.     begin
  3443.       exit;
  3444.     end;
  3445.     if w = nil then begin
  3446.       GetIdentifier := 2;
  3447.       exit;
  3448.     end;
  3449.   end;
  3450.   while (Parser.CurrTokenId = CSTI_OpenBlock) or (Parser.CurrTokenId = CSTI_Period) do begin
  3451. {$IFNDEF NOCLASSES}
  3452.     if (w^.VType^.atypeid = CSV_Property) then begin
  3453.       if Mode = 1 then begin
  3454.         if AssignmentNeeded then DestroyCajVariant(W);
  3455.         RunError(Self, EVariableExpected);
  3456.         exit;
  3457.       end;
  3458.       C := w;
  3459.       w := GetProperty(w);
  3460.       if not AssignmentNeeded then begin
  3461.         DestroyCajVariant(C);
  3462.       end;
  3463.       if w = nil then begin
  3464.         exit;
  3465.       end;
  3466.       AssignmentNeeded := False;
  3467.     end;
  3468.     if (w^.VType^.atypeid = CSV_ExternalObjectProperty) then begin
  3469.       if Mode = 1 then begin
  3470.         if AssignmentNeeded then DestroyCajVariant(W);
  3471.         RunError(Self, EVariableExpected);
  3472.         exit;
  3473.       end;
  3474.       C := w;
  3475.       if (not assigned(w^.CV_ExtObj)) or (PCreatedCustomObject(w^.CV_ExtObj)^.AlreadyFreed) then
  3476.       begin
  3477.         RunError(Self, EClassNotCreated);
  3478.         if AssignmentNeeded then DestroyCajVariant(c);
  3479.         exit;
  3480.       end;
  3481.       w := CreatecajVariant(PCreatedCustomObject(c^.CV_ExtObj).P.GetPropertyType(c^.CV_PropertyNo));
  3482.       if not PCreatedCustomObject(c^.CV_ExtObj).P.GetProperty(c^.CV_PropertyNo, w) then
  3483.       begin
  3484.         RunError(Self, ECanNotReadProperty);
  3485.         DestroycajVariant(w);
  3486.         if AssignmentNeeded then DestroyCajVariant(c);
  3487.         exit;
  3488.       end;
  3489.       if not AssignmentNeeded then DestroyCajVariant(C);
  3490.       if w = nil then begin
  3491.         RunError(Self, ETypeMismatch);
  3492.         exit;
  3493.       end;
  3494.       AssignmentNeeded := False;
  3495.     end;
  3496. {$ENDIF}
  3497.     if Parser.CurrTokenId = CSTI_OpenBlock then begin
  3498.       Parser.Next;
  3499.       if not AssignmentNeeded then begin
  3500.         RunError(Self, ETypeMismatch);
  3501.         DestroyCajVariant(w);
  3502.         exit;
  3503.       end;
  3504.       while True do begin
  3505.         if w^.VType^.atypeid <> CSV_Array then begin
  3506.           RunError(Self, ETypeMismatch);
  3507.           if not AssignmentNeeded then DestroyCajVariant(w);
  3508.           exit;
  3509.         end; {if}
  3510.         C := CreateCajVariant(TM_Add(Types, '', CSV_SInt32, nil));
  3511.         if not calc(WithList, Vars, C, CSTI_CloseBlock, False) then begin
  3512.           DestroyCajVariant(C);
  3513.           if not AssignmentNeeded then DestroyCajVariant(w);
  3514.           exit;
  3515.         end; {if}
  3516.         if AssignmentNeeded then
  3517.         begin
  3518.           w := w^.CV_ArrItems.GetItem(C^.Cv_SInt32);
  3519.           DestroyCajVariant(C);
  3520.         end else begin
  3521.           c2 := w^.CV_ArrItems.GetItem(C^.Cv_SInt32);
  3522.           DestroyCajVariant(C);
  3523.           if c2 = nil then begin
  3524.             RunError(Self, EOutOfRange);
  3525.             DestroyCajVariant(w);
  3526.             exit;
  3527.           end;
  3528.           c2 := CopyVariant(c2);
  3529.           DestroyCajVariant(w);
  3530.           if c2 = nil then begin
  3531.             exit;
  3532.           end;
  3533.           w := c2;
  3534.         end;
  3535.         if Parser.CurrTokenId = CSTI_CloseBlock then begin
  3536.           Parser.Next;
  3537.           break;
  3538.         end;
  3539.         if Parser.CurrTokenId = CSTI_Comma then begin
  3540.           Parser.Next;
  3541.         end else begin
  3542.           RunError(Self, ECloseBlockExpected);
  3543.           exit;
  3544.         end;
  3545.       end;
  3546.     end else if Parser.CurrTokenId = CSTI_Period then begin
  3547.       Parser.Next;
  3548.       if w^.VType^.atypeid = CSV_Record then begin
  3549.         if Parser.CurrTokenId <> CSTI_Identifier then begin
  3550.           RunError(Self, EIdentifierExpected);
  3551.           if not AssignmentNeeded then DestroyCajVariant(w);
  3552.           exit;
  3553.         end;
  3554.         if AssignmentNeeded then begin
  3555.           w := GetRecordSubVar(w, Parser.GetToken);
  3556.           if w = nil then begin
  3557.             RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3558.             exit;
  3559.           end;
  3560.           Parser.Next;
  3561.         end else begin
  3562.           c2 := w;
  3563.           w := GetRecordSubVar(w, Parser.GetToken);
  3564.           if w = nil then begin
  3565.             RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3566.             DestroyCajVariant(c2);
  3567.             exit;
  3568.           end;
  3569.           Parser.Next;
  3570.         end;
  3571.       end{$IFNDEF NOCLASSES} else if w^.VType^.atypeid = CSV_Class then begin
  3572.         if Mode = 1 then begin
  3573.           if not AssignmentNeeded then DestroyCajVariant(w);
  3574.           RunError(Self, EVariableExpected);
  3575.           exit;
  3576.         end;
  3577.         if not assigned(w^.CV_Class) or (w^.CV_Class^.AlreadyFreed) then begin
  3578.           if not AssignmentNeeded then DestroyCajVariant(w);
  3579.           if not assigned(w^.CV_Class) then
  3580.             RunError(Self, EClassNotCreated)
  3581.           else
  3582.             RunError(Self, EClassAlreadyFreed);
  3583.           exit;
  3584.         end;
  3585.         if assigned(CurrProc) and (assigned(CurrProc^.ClassType)) then begin
  3586.           if not GetClassVariable2(w^.CV_Class, CurrProc^.ClassType^.Ext, Parser.GetToken, C, True) then begin
  3587.             if GetClassProcedure(w, CurrProc^.ClassType^.Ext, Parser.GetToken, p, True) then begin
  3588.               C := w;
  3589.               Parser.Next;
  3590.               if Mode = 2 then begin
  3591.                 w := CreateCajVariant(TM_Add(Types, '', CSV_ProcVariable, nil));
  3592.                 w^.Cv_Proc := p;
  3593.                 w^.Cv_ProcSelf := c^.CV_Class;
  3594.                 if not AssignmentNeeded then DestroyCajVariant(C);
  3595.                 AssignmentNeeded := False;
  3596.               end else begin
  3597.                 w := DoProc(WithList, w^.CV_Class, p, Vars);
  3598.                 if not AssignmentNeeded then DestroyCajVariant(C);
  3599.                 if ErrorCode <> 0 then begin
  3600.                   exit;
  3601.                 end else begin
  3602.                   AssignmentNeeded := False;
  3603.                 end;
  3604.               end;
  3605.               if w = nil then begin
  3606.                 GetIdentifier := 2;
  3607.                 exit;
  3608.               end;
  3609.             end else begin
  3610.               RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3611.               if not AssignmentNeeded then DestroyCajVariant(C);
  3612.               exit;
  3613.             end;
  3614.           end else begin
  3615.             if not AssignmentNeeded then DestroyCajVariant(w);
  3616.             w := C;
  3617.             AssignmentNeeded := True;
  3618.             Parser.Next;
  3619.           end;
  3620.         end else begin
  3621.           if Mode = 1 then begin
  3622.             RunError(Self, EVariableExpected);
  3623.             if not AssignmentNeeded then DestroyCajVariant(C);
  3624.             exit;
  3625.           end;
  3626.           if not GetClassVariable2(w^.CV_Class, w^.VType^.Ext, Parser.GetToken, C, False) then begin
  3627.             if GetClassProcedure(w, w^.VType^.Ext, Parser.GetToken, p, False) then begin
  3628.               C := w;
  3629.               Parser.Next;
  3630.               if Mode = 2 then begin
  3631.                 w := CreateCajVariant(TM_Add(Types, '', CSV_ProcVariable, nil));
  3632.                 w^.Cv_Proc := p;
  3633.                 w^.Cv_ProcSelf := c^.CV_Class;
  3634.                 if not AssignmentNeeded then DestroyCajVariant(C);
  3635.                 AssignmentNeeded := False;
  3636.               end else begin
  3637.                 w := DoProc(WithList, w^.CV_Class, p, Vars);
  3638.                 if not AssignmentNeeded then begin
  3639.                   DestroyCajVariant(C);
  3640.                 end;
  3641.                 if ErrorCode <> 0 then begin
  3642.                   exit;
  3643.                 end else
  3644.                   AssignmentNeeded := False;
  3645.               end;
  3646.               if w = nil then begin
  3647.                 GetIdentifier := 2;
  3648.                 exit;
  3649.               end;
  3650.             end else begin
  3651.               RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3652.               if not AssignmentNeeded then DestroyCajVariant(C);
  3653.               exit;
  3654.             end;
  3655.           end else begin
  3656.             if not AssignmentNeeded then DestroyCajVariant(w);
  3657.             w := C;
  3658.             AssignmentNeeded := True;
  3659.             Parser.Next;
  3660.           end;
  3661.         end;
  3662.       end else if w^.VType^.atypeid = CSV_ClassRef then begin
  3663.         if w^.Cv_ClassRef = nil then begin
  3664.           RunError(Self, EClassReferenceNotAssigned);
  3665.           if not AssignmentNeeded then DestroyCajVariant(w);
  3666.           exit;
  3667.         end;
  3668.         if not GetClassProcedure(nil, w^.Cv_ClassRef^.Ext, Parser.GetToken, p, False) then begin
  3669.           RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3670.           if not AssignmentNeeded then DestroyCajVariant(w);
  3671.           exit;
  3672.         end;
  3673.         if (p^.Flags and $40) = 0 then begin
  3674.           RunError(Self, EConstructorExpected);
  3675.           if not AssignmentNeeded then DestroyCajVariant(w);
  3676.           exit;
  3677.         end;
  3678.         C := w;
  3679.         w := DoClassConstructor(WithList, w^.Cv_ClassRef, p, Vars);
  3680.         if not AssignmentNeeded then DestroyCajVariant(C);
  3681.         if FError.ErrorCode <> 0 then begin
  3682.           exit;
  3683.         end;
  3684.         AssignmentNeeded := False;
  3685.       end else if w^.VType^.atypeid = CSV_ExternalObject then
  3686.       begin
  3687.         if Mode = 1 then begin
  3688.           if not AssignmentNeeded then DestroyCajVariant(w);
  3689.           RunError(Self, EVariableExpected);
  3690.           exit;
  3691.         end;
  3692.         if not assigned(w^.CV_ExternalObject) then
  3693.         begin
  3694.           RunError(Self, EClassNotCreated);
  3695.           if not AssignmentNeeded then DestroyCajVariant(w);
  3696.           exit;
  3697.         end;
  3698.         if PCreatedCustomObject(w^.CV_ExternalObject)^.AlreadyFreed then
  3699.         begin
  3700.           RunError(Self, EClassAlreadyFreed);
  3701.           if not AssignmentNeeded then DestroyCajVariant(w);
  3702.           exit;
  3703.         end;
  3704.         if PCreatedCustomObject(w^.CV_ExternalObject)^.P.FindProperty(Parser.GetToken) <> -1 then
  3705.         begin
  3706.           AL := PCreatedCustomObject(w^.CV_ExternalObject)^.P.FindProperty(Parser.GetToken);
  3707.           Parser.Next;
  3708.           c := w;
  3709.           w := CreateCajVariant(TM_Add(Types, '', CSV_ExternalObjectProperty, nil));
  3710.           W^.cv_ExtObj := c^.CV_ExternalObject;
  3711.           w^.cv_PropertyNo := al;
  3712.           if not AssignmentNeeded then DestroyCajVariant(c);
  3713.           AssignmentNeeded := False;
  3714.         end else if PCreatedCustomObject(w^.CV_ExternalObject)^.P.FindProc(Parser.GetToken) <> -1 then
  3715.         begin
  3716.           AL := PCreatedCustomObject(w^.CV_ExternalObject)^.P.FindProc(Parser.GetToken);
  3717.           VM := VM_Create(nil);
  3718.           Parser.Next;
  3719.           if not ReadParams(WithList, PCreatedCustomObject(w^.CV_ExternalObject)^.P.GetProcHeader(Al), Vars, VM) then
  3720.           begin
  3721.            if not AssignmentNeeded then DestroyCajVariant(w);
  3722.             VM_Destroy(VM);
  3723.             exit;
  3724.           end;
  3725.           c := W;
  3726.           W := PCreatedCustomObject(w^.CV_ExternalObject)^.P.CallProc(AL, VM);
  3727.           if not AssignmentNeeded then DestroyCajVariant(c);
  3728.           AssignmentNeeded := False;
  3729.           VM_Destroy(VM);
  3730.           if w = nil then
  3731.           begin
  3732.             GetIdentifier := 2;
  3733.             exit;
  3734.           end;
  3735.         end else
  3736.         begin
  3737.           RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3738.           if not AssignmentNeeded then DestroyCajVariant(w);
  3739.           exit;
  3740.         end;
  3741.       end {$ENDIF} else begin
  3742.         RunError(Self, ETypeMismatch);
  3743.       end;
  3744.     end else begin
  3745.       if not AssignmentNeeded then DestroyCajVariant(w);
  3746.       RunError(Self, ENotSupported);
  3747.       exit;
  3748.     end;
  3749.     if (Parser.CurrTokenId = CSTI_Dereference) and (w^.VType^.ATypeId = CSV_ProcVariable) then
  3750.     begin
  3751.       if Mode <> 0 then
  3752.       begin
  3753.         if not AssignmentNeeded then DestroyCajVariant(w);
  3754.         RunError(Self, EVariableExpected);
  3755.         exit;
  3756.       end;
  3757.       Parser.Next;
  3758.       c := w;
  3759.       w := DoProc(WithList, {$IFNDEF NOCLASSES}W^.CV_ProcSelf,{$ENDIF} w^.Cv_Proc, Vars);
  3760.       if not AssignmentNeeded then DestroyCajVariant(c);
  3761.       if ErrorCode <> ENoError then
  3762.       begin
  3763.         exit;
  3764.       end;
  3765.       if w = nil then begin
  3766.         GetIdentifier := 2;
  3767.         exit;
  3768.       end;
  3769.     end;
  3770.   end; {while}
  3771.   if AssignmentNeeded then
  3772.     GetIdentifier := 1
  3773.   else
  3774.     GetIdentifier := 2;
  3775. end; {GetIdentifier}
  3776. //-------s------------------------------------------------------------
  3777.  
  3778. function TIfPasScript.IdentifierExists(AlsoVariables: Boolean; SubVars: PVariableManager; const s: string): Boolean;
  3779. { Check if an identifier exists }
  3780.  
  3781.   function UsesExists(s: string): Boolean;
  3782.   var
  3783.     I: Integer;
  3784.   begin
  3785.     UsesExists := False;
  3786.     for I := 0 to FUses.Count - 1 do
  3787.       if FUses.GetItem(I) = s then begin
  3788.         UsesExists := True;
  3789.         break;
  3790.       end;
  3791.   end; { UsesExists }
  3792. begin
  3793.   IdentifierExists := False;
  3794. {$IFNDEF NOCLASSES}
  3795.   if s = 'SELF' then
  3796.     IdentifierExists := True
  3797.   else {$ENDIF}if UsesExists(s) then
  3798.       IdentifierExists := True
  3799.     else if PM_Find(Procedures, s) <> -1 then
  3800.       IdentifierExists := True
  3801.     else if AlsoVariables and (VM_Find(Variables, s) <> -1) then
  3802.       IdentifierExists := True
  3803.     else if TM_Get(Types, s) <> nil then
  3804.       IdentifierExists := True
  3805.     else if assigned(SubVars) and (VM_Find(SubVars, s) <> -1) then
  3806.       IdentifierExists := True
  3807. end; {IdentifierExists}
  3808.  
  3809. //-------------------------------------------------------------------
  3810. function TIfPasScript.GetPData(var Data: string): Boolean;
  3811. begin
  3812.   GetPData := Parser.GetData(Data);
  3813. end;
  3814. //-------------------------------------------------------------------
  3815. procedure TIfPasScript.SetText(const Data: string);
  3816. var
  3817.   E: TIFParserError;
  3818. begin
  3819.   if not Parser.SetText(Data, E) then
  3820.   begin
  3821.     case E.Kind of
  3822.       iCommentError: RunError(Self, ECommentError); 
  3823.       iStringError: RunError(Self, EStringError);
  3824.       iCharError: RunError(Self, ECharError);
  3825.       else
  3826.        RunError(Self, ESyntaxError);
  3827.     end;
  3828.     FError.ErrorPosition := E.Position;
  3829.     Exit;
  3830.   end;
  3831.   LoadData;
  3832. end;
  3833.  
  3834. procedure TIfPasScript.SetPData(const Data: string);
  3835. begin
  3836.   if not Parser.SetData(Data) then
  3837.   begin
  3838.     RunError2(Self, ECustomError, 'Could not load PData');
  3839.     exit;
  3840.   end;
  3841.   LoadData;
  3842. end;
  3843.  
  3844. //-------------------------------------------------------------------
  3845. procedure TIfPasScript.LoadData;
  3846. { Assign a text to the script engine, this also checks for uses and variables. }
  3847. var
  3848.   HaveHadProgram,
  3849.     HaveHadUnit,
  3850.     HaveHadUses: Boolean;
  3851.  
  3852.  
  3853.   function ProcessUses: Boolean;
  3854.   {Process Uses block}
  3855.   var
  3856.     I: Integer;
  3857.   begin
  3858.     ProcessUses := False;
  3859.     while Parser.CurrTokenId <> CSTI_EOF do begin
  3860.       if Parser.CurrTokenId <> CSTI_Identifier then begin
  3861.         RunError(Self, EIdentifierExpected);
  3862.         exit;
  3863.       end; {If}
  3864.       if IdentifierExists(True, nil, Parser.GetToken) then begin
  3865.         RunError(Self, EDuplicateIdentifier);
  3866.         exit;
  3867.       end; {If}
  3868.       FUses.Add(Parser.GetToken);
  3869.       if assigned(OnUses) then begin
  3870.         I := OnUses(fId, Self, Parser.GetToken);
  3871.         if I <> ENoError then begin
  3872.           RunError(Self, I);
  3873.           exit;
  3874.         end; {If}
  3875.       end {If}
  3876.       else begin
  3877.         RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3878.         exit;
  3879.       end; {Else if}
  3880.       Parser.Next;
  3881.       if (Parser.CurrTokenId = CSTI_Semicolon) then begin
  3882.         Parser.Next;
  3883.         break;
  3884.       end {if}
  3885.       else if (Parser.CurrTokenId <> CSTI_Comma) then begin
  3886.         RunError(Self, ESemiColonExpected);
  3887.         exit;
  3888.       end else {Else if}  begin
  3889.         Parser.Next;
  3890.       end;
  3891.     end;
  3892.     if Parser.CurrTokenId = CSTI_EOF then begin
  3893.       RunError(Self, EUnexpectedEndOfFile);
  3894.     end {If}
  3895.     else begin
  3896.       ProcessUses := True;
  3897.     end; {Else If}
  3898.   end; {ProcessUses}
  3899.  
  3900.   function DoFuncHeader: Boolean;
  3901.   var
  3902.     FuncParam: string;
  3903.     FuncName: string;
  3904.     CurrVar: string;
  3905.     CurrType: Pointer;
  3906.     FuncRes: Pointer;
  3907.     PT: Byte;
  3908.     Cp: PProcedure;
  3909.   {$IFNDEF NOCLASSES}
  3910.     Myclass: PTypeRec;
  3911.  
  3912.     function GetclassProc: Boolean;
  3913.     var
  3914.       I: Integer;
  3915.       p: PProcedure;
  3916.     begin
  3917.       for I := 0 to PIFSClassType(Myclass.Ext)^.Procedures.Count - 1 do begin
  3918.         p := PIFSClassType(Myclass.Ext)^.Procedures.GetItem(I);
  3919.         if (Pos('!', p^.Name) = 1) and (copy(p^.Name, 2, Length(p^.Name) - 1) = FuncName) then begin
  3920.           if (p^.Mode = 0) and (p^.offset <> -1) then begin
  3921.             RunError(Self, EDuplicateIdentifier);
  3922.             Result := False;
  3923.             exit;
  3924.           end else begin
  3925.             Cp := p;
  3926.             Result := True;
  3927.             exit;
  3928.           end;
  3929.         end;
  3930.       end;
  3931.       RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  3932.       Result := False;
  3933.     end;
  3934.   {$ENDIF}
  3935.     function MKString(const S: string): string;
  3936.     begin
  3937.       MKString := copy(s, 2, length(s)-2);
  3938.     end;
  3939.  
  3940.     function Duplic(s: string): Boolean;
  3941.     var
  3942.       s2, s3: string;
  3943.       I: Integer;
  3944.     begin
  3945.       if s = FuncName then begin
  3946.         Duplic := True;
  3947.         exit;
  3948.       end; {if}
  3949.       if (FuncRes <> nil) and (s = 'RESULT') then begin
  3950.         Duplic := True;
  3951.         exit;
  3952.       end;
  3953.       s2 := CurrVar;
  3954.       while Pos('|', s2) > 0 do begin
  3955.         if Pos('!', s2) = 1 then
  3956.           Delete(s2, 1, 1);
  3957.         if copy(s2, 1, Pos('|', s2) - 1) = s then begin
  3958.           Duplic := True;
  3959.           exit;
  3960.         end; {if}
  3961.         Delete(s2, 1, Pos('|', s2));
  3962.       end; {while}
  3963.       s2 := '0 ' + FuncParam;
  3964.       for I := 1 to IntProcDefParam(s2, -1) do begin
  3965.         s3 := IntProcDefName(s2, 0);
  3966.         if Pos('!', s2) = 1 then
  3967.           Delete(s2, 1, 1);
  3968.         if s3 = s then begin
  3969.           Duplic := True;
  3970.           exit;
  3971.         end; {if}
  3972.       end; {for}
  3973.       Duplic := False;
  3974.     end; {duplic}
  3975.   begin
  3976.     DoFuncHeader := False;
  3977.     if Parser.CurrTokenId = CSTII_Procedure then begin
  3978.       PT := 0;
  3979.       FuncRes := nil
  3980.     end else
  3981.       if Parser.CurrTokenId = CSTII_Constructor then begin
  3982.         PT := 2;
  3983.         FuncRes := nil
  3984.       end else
  3985.         if Parser.CurrTokenId = CSTII_Destructor then begin
  3986.           PT := 3;
  3987.           FuncRes := nil
  3988.         end else begin
  3989.           PT := 1;
  3990.           FuncRes := Pointer(1);
  3991.         end;
  3992.     Parser.Next;
  3993.     if Parser.CurrTokenId <> CSTI_Identifier then begin
  3994.       RunError(Self, EIdentifierExpected);
  3995.       exit;
  3996.     end; {if}
  3997.     if IdentifierExists(True, nil, Parser.GetToken) then begin
  3998. {$IFNDEF NOCLASSES}
  3999.       Myclass := GetTypeLink(TM_Get(Types, Parser.GetToken));
  4000.       if not assigned(Myclass) or (Myclass^.atypeid <> CSV_Class) then begin
  4001. {$ENDIF}
  4002.         RunError(Self, EDuplicateIdentifier);
  4003.         exit;
  4004. {$IFNDEF NOCLASSES}
  4005.       end;
  4006.       Parser.Next;
  4007.       if Parser.CurrTokenId <> CSTI_Period then begin
  4008.         RunError(Self, EPeriodExpected);
  4009.         exit;
  4010.       end;
  4011.       Parser.Next;
  4012. {$ENDIF}
  4013.     end{$IFNDEF NOCLASSES} else Myclass := nil{$ENDIF}; {if}
  4014.     FuncName := Parser.GetToken;
  4015. {$IFNDEF NOCLASSES}
  4016.     if assigned(Myclass) then begin
  4017.       if not GetclassProc then
  4018.         exit;
  4019.       if ((Cp^.Flags and $40) <> 0) then begin
  4020.         if (PT <> 2) then begin
  4021.           RunError(Self, EParameterError);
  4022.           exit;
  4023.         end;
  4024.       end else if ((Cp^.Flags and $80) <> 0) then begin
  4025.         if (PT <> 3) then begin
  4026.           RunError(Self, EParameterError);
  4027.           exit;
  4028.         end;
  4029.       end else if (Fw(Cp^.Decl) = '0') then begin
  4030.         if PT <> 0 then begin
  4031.           RunError(Self, EParameterError);
  4032.           exit;
  4033.         end;
  4034.       end else begin
  4035.         if PT <> 1 then begin
  4036.           RunError(Self, EParameterError);
  4037.           exit;
  4038.         end;
  4039.       end;
  4040.     end else begin
  4041. {$ENDIF}
  4042.       if (PT <> 0) and (PT <> 1) then begin
  4043.         RunError(Self, EIdentifierExpected);
  4044.         exit;
  4045.       end;
  4046. {$IFNDEF NOCLASSES} end;
  4047. {$ENDIF}
  4048.     FuncParam := '';
  4049.     CurrVar := '';
  4050.     Parser.Next;
  4051.     if Parser.CurrTokenId = CSTI_OpenRound then begin
  4052.       Parser.Next;
  4053.       if Parser.CurrTokenId = CSTI_CloseRound then begin
  4054.         Parser.Next;
  4055.       end else begin
  4056.         while True do begin
  4057.           if Parser.CurrTokenId = CSTII_Var then begin
  4058.             CurrVar := '!';
  4059.             Parser.Next;
  4060.           end; {if}
  4061.           while True do begin
  4062.             if Parser.CurrTokenId <> CSTI_Identifier then begin
  4063.               RunError(Self, EIdentifierExpected);
  4064.               exit;
  4065.             end; {if}
  4066.             if IdentifierExists(True, nil, Parser.GetToken) or Duplic(Parser.GetToken)
  4067.               then begin
  4068.               RunError(Self, EDuplicateIdentifier);
  4069.               exit;
  4070.             end; {if}
  4071.             CurrVar := CurrVar + Parser.GetToken + '|';
  4072.             Parser.Next;
  4073.             if Parser.CurrTokenId = CSTI_Colon then
  4074.               break;
  4075.             if Parser.CurrTokenId <> CSTI_Comma then begin
  4076.               RunError(Self, ECommaExpected);
  4077.               exit;
  4078.             end; {if}
  4079.             Parser.Next;
  4080.           end; {while}
  4081.           Parser.Next;
  4082.           CurrType := ReadType(Parser, False, '');
  4083.           if CurrType = nil then begin
  4084.             RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  4085.             exit;
  4086.           end; {if}
  4087.           if Pos('!', CurrVar) = 1 then begin
  4088.             Delete(CurrVar, 1, 1);
  4089.             while Pos('|', CurrVar) > 0 do begin
  4090.               FuncParam := FuncParam + ' !' + copy(CurrVar, 1, Pos('|', CurrVar) -
  4091.                 1) + ' ' + inttostr(Longint(CurrType));
  4092.               Delete(CurrVar, 1, Pos('|', CurrVar));
  4093.             end; {while}
  4094.           end else begin
  4095.             while Pos('|', CurrVar) > 0 do begin
  4096.               FuncParam := FuncParam + ' ' + copy(CurrVar, 1, Pos('|', CurrVar) -
  4097.                 1) + ' ' + inttostr(Longint(CurrType));
  4098.               Delete(CurrVar, 1, Pos('|', CurrVar));
  4099.             end; {while}
  4100.           end; {if}
  4101.           if Parser.CurrTokenId = CSTI_CloseRound then begin
  4102.             Parser.Next;
  4103.             break;
  4104.           end; {if}
  4105.           if Parser.CurrTokenId <> CSTI_Semicolon then begin
  4106.             RunError(Self, ESemiColonExpected);
  4107.             exit;
  4108.           end; {if}
  4109.           Parser.Next;
  4110.         end; {while}
  4111.       end; {else if}
  4112.     end; {if}
  4113.     if FuncRes <> nil then begin
  4114.       if Parser.CurrTokenId <> CSTI_Colon then begin
  4115.         RunError(Self, EColonExpected);
  4116.         exit;
  4117.       end;
  4118.       Parser.Next;
  4119.       FuncRes := ReadType(Parser, False, '');
  4120.       if FuncRes = nil then begin
  4121.         RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  4122.         exit;
  4123.       end;
  4124.     end;
  4125.     FuncParam := inttostr(Longint(FuncRes)) + FuncParam;
  4126.     if Parser.CurrTokenId <> CSTI_Semicolon then begin
  4127.       RunError(Self, ESemiColonExpected);
  4128.       exit;
  4129.     end;
  4130.     Parser.Next;
  4131. {$IFNDEF NOCLASSES}
  4132.     if assigned(Myclass) then begin
  4133.       if Cp.Decl <> FuncParam then begin
  4134.         RunError(Self, EParameterError);
  4135.         exit;
  4136.       end; {if}
  4137.       Cp.offset := Parser.CurrTokenPos;
  4138.     end
  4139.     else
  4140. {$ENDIF}
  4141.       CP := PM_AddInt(Procedures, Self, FuncName, FuncParam, {$IFNDEF NOCLASSES}nil, {$ENDIF}nil, Parser.CurrTokenPos);
  4142.     if Parser.CurrTokenId = CSTII_External then
  4143.     begin
  4144.       {$IFNDEF NOCLASSES}
  4145.       if Assigned(MyClass) then begin
  4146.         RunError(Self, EBeginExpected);
  4147.         exit;
  4148.       end;
  4149.       {$ENDIF}
  4150.       Parser.Next;
  4151.       if Parser.CurrTokenID <> CSTI_String then
  4152.       begin
  4153.         RunError(Self, EStringExpected);
  4154.         exit;
  4155.       end;
  4156.       FuncParam := MkString(Parser.GetToken);
  4157.       Parser.Next;
  4158.       if Parser.CurrTokenId = CSTI_Identifier then
  4159.       begin
  4160.         if Parser.GetToken <> 'NAME' then
  4161.         begin
  4162.           RunError(Self, ESemicolonExpected);
  4163.           exit;
  4164.         end;
  4165.         Parser.Next;
  4166.         if Parser.CurrtokenId <> CSTI_String then
  4167.         begin
  4168.           RunError(Self, EStringExpected);
  4169.           exit;
  4170.         end;
  4171.         FuncName := MKString(Parser.GetToken);
  4172.         Parser.Next;
  4173.       end;
  4174.       if Parser.CurrTokenId <> CSTI_Semicolon then
  4175.       begin
  4176.         RunError(Self, ESemiColonExpected);
  4177.         exit;
  4178.       end;
  4179.       Parser.Next;
  4180.       if @FOnExternal = nil then begin
  4181.         RunError(Self, EUnknownIdentifier);
  4182.         exit;
  4183.       end;
  4184.       if not FOnExternal(fId, Self, FuncParam, Funcname, CP) then
  4185.       begin
  4186.         RunError(Self, EUnknownIdentifier);
  4187.         exit;
  4188.       end;
  4189.       DoFuncHeader := True;
  4190.       exit;
  4191.     end;
  4192.     if Parser.CurrTokenId = CSTII_Var then begin
  4193.       while (Parser.CurrTokenId <> CSTII_Begin) and (Parser.CurrTokenId <>
  4194.         CSTI_EOF) do
  4195.         Parser.Next;
  4196.     end;
  4197.     RunBegin(nil, nil, True);
  4198.     if Parser.CurrTokenId <> CSTI_Semicolon then begin
  4199.       RunError(Self, ESemiColonExpected);
  4200.       exit;
  4201.     end;
  4202.     Parser.Next;
  4203.     DoFuncHeader := True;
  4204.   end; {DoFuncHeader}
  4205.  
  4206.   function ProcessTypes: Boolean;
  4207.   var
  4208.     Name: string;
  4209.     p: PTypeRec;
  4210.   begin
  4211.     ProcessTypes := False;
  4212.     Parser.Next;
  4213.     repeat
  4214.       if Parser.CurrTokenId <> CSTI_Identifier then begin
  4215.         RunError(Self, EIdentifierExpected);
  4216.         exit;
  4217.       end; {if}
  4218.       Name := Parser.GetToken;
  4219.       if IdentifierExists(True, nil, Name) then begin
  4220.         RunError(Self, EDuplicateIdentifier);
  4221.         exit;
  4222.       end; {if}
  4223.       Parser.Next;
  4224.       if Parser.CurrTokenId <> CSTI_Equal then begin
  4225.         RunError(Self, EIsExpected);
  4226.         exit;
  4227.       end;
  4228.       Parser.Next;
  4229.       p := ReadType(Parser, True, Name);
  4230.       if p = nil then begin
  4231.         exit;
  4232.       end;
  4233.       if Parser.CurrTokenId <> CSTI_Semicolon then begin
  4234.         RunError(Self, ESemiColonExpected);
  4235.         exit;
  4236.       end;
  4237.       Parser.Next;
  4238.     until Parser.CurrTokenId <> CSTI_Identifier;
  4239.     ProcessTypes := True;
  4240.   end; {ProcessTypes}
  4241. {$IFNDEF NOCLASSES}
  4242.  
  4243.   function CheckClassProcs: Boolean;
  4244.   var
  4245.     I: Integer;
  4246.     p: PProcedure;
  4247.   begin
  4248.     for I := 0 to Procedures.Count - 1 do begin
  4249.       p := Procedures.GetItem(I);
  4250.       if (p^.Mode = 0) and (p^.offset = -1) then begin
  4251.         RunError2(Self, EUnsatisfiedForward, p^.ClassType^.Ident + '.' + copy(p^.Name, 2, Length(p^.Name) - 1));
  4252.         Result := False;
  4253.         exit;
  4254.       end;
  4255.     end;
  4256.     Result := True;
  4257.   end; {CheckClassProcs}
  4258. {$ENDIF}
  4259. begin
  4260.   Cleanup;
  4261.   FISUnit := False;
  4262.   FModuleName := 'MAIN';
  4263.   FUses.Clear;
  4264.   VM_Clear(Variables);
  4265.   TM_Destroy(Types);
  4266.   Types := TM_Create;
  4267.   PM_Clear(Procedures);
  4268.   AddStandard;
  4269.   Vm_Add(Variables, CreateBool(True), 'TRUE')^.Flags := 1;
  4270.   Vm_Add(Variables, CreateBool(False), 'FALSE')^.Flags := 1;
  4271.   with Vm_Add(Variables, CreateCajVariant(TM_Add(Types, '', CSV_Special, nil)), 'NIL')^ do
  4272.   begin
  4273.     CV_Spec := 0;
  4274.     Flags := 1;
  4275.   end;
  4276.   FUses.Add('SYSTEM');
  4277.   if assigned(OnUses) then
  4278.     OnUses(fId, Self, 'SYSTEM');
  4279.  
  4280.   RunError(Self, ENoError);
  4281.   MainOffset := -1;
  4282.   HaveHadProgram := False;
  4283.   HaveHadUses := False;
  4284.   HaveHadUnit := False;
  4285.   while Parser.CurrTokenId <> CSTI_EOF do begin
  4286.     if (Parser.CurrTokenId = CSTII_Program) and (HaveHadProgram = False) and
  4287.       (HaveHadUses = False) and (HaveHadUnit = False) then begin
  4288.       Parser.Next;
  4289.       if Parser.CurrTokenId <> CSTI_Identifier then begin
  4290.         RunError(Self, EIdentifierExpected);
  4291.         exit;
  4292.       end; {if}
  4293.       FModuleName := Parser.GetToken;
  4294.       Parser.Next;
  4295.       if Parser.CurrTokenId <> CSTI_Semicolon then begin
  4296.         RunError(Self, ESemiColonExpected);
  4297.         exit;
  4298.       end; {if}
  4299.       Parser.Next;
  4300.       HaveHadProgram := True;
  4301.     end else if (Parser.CurrTokenId = CSTII_Unit)and (HaveHadProgram = False) and
  4302.       (HaveHadUses = False) and (HaveHadUnit = False)  then begin
  4303.       Parser.Next;
  4304.       if Parser.CurrTokenId <> CSTI_Identifier then
  4305.       begin
  4306.         RunError(Self, EIdentifierExpected);
  4307.         exit;
  4308.       end;
  4309.       FModuleName := Parser.GetToken;
  4310.       Parser.Next;
  4311.       if Parser.CurrTokenId <> CSTI_Semicolon then begin
  4312.         RunError(Self, ESemiColonExpected);
  4313.         exit;
  4314.       end; {if}
  4315.       Parser.Next;
  4316.       HaveHadUnit := True;
  4317.       FISUnit := True;
  4318.     end else if (Parser.CurrTokenId = CSTII_Uses) and (HaveHadUses = False) then begin
  4319.       Parser.Next;
  4320.       if not ProcessUses then
  4321.         exit;
  4322.       HaveHadUses := True;
  4323.     end {else if}
  4324.     else if (Parser.CurrTokenId = CSTII_Type) then begin
  4325.       if not ProcessTypes then
  4326.         exit;
  4327.     end
  4328.     else if (Parser.CurrTokenId = CSTII_Var) then begin
  4329.       if not ProcessVars(Variables) then
  4330.         exit;
  4331.     end {Else if}
  4332.     else if (Parser.CurrTokenId = CSTII_Const) then begin
  4333.       if not ProcessConsts(Variables) then
  4334.         exit;
  4335.     end
  4336.     else if (Parser.CurrTokenId = CSTII_Procedure) or
  4337.       (Parser.CurrTokenId = CSTII_Function) or
  4338.       (Parser.CurrTokenId = CSTII_Constructor) or
  4339.       (Parser.CurrTokenId = CSTII_Destructor) then begin
  4340.       if not DoFuncHeader then
  4341.         exit;
  4342.     end {else if}
  4343.     else if (Parser.CurrTokenId = CSTII_Begin) then begin
  4344. {$IFNDEF NOCLASSES}
  4345.       if not CheckClassProcs then
  4346.         exit;
  4347. {$ENDIF}
  4348.       MainOffset := Parser.CurrTokenPos;
  4349.       exit;
  4350.     end {Else if}
  4351.     else if (Parser.CurrTokenId = CSTII_End) and FISUnit then
  4352.     begin
  4353. {$IFNDEF NOCLASSES}
  4354.       if not CheckClassProcs then
  4355.         exit;
  4356. {$ENDIF}
  4357.       MainOffset := Parser.CurrTokenPos;
  4358.       exit;
  4359.     end { Else if}
  4360.     else if (Parser.CurrTokenId = CSTI_EOF) then begin
  4361.       RunError(Self, EUnexpectedEndOfFile);
  4362.     end {Else if}
  4363.     else begin
  4364.       RunError(Self, EBeginExpected);
  4365.       exit;
  4366.     end; {Else If}
  4367.   end; {While}
  4368. end; {SetText}
  4369.  
  4370. //-------------------------------------------------------------------
  4371.  
  4372. function TIfPasScript.ProcessConsts(Vars: PVariableManager): Boolean;
  4373.         { Process constants block (const s = '') }
  4374. var
  4375.   Name: string;
  4376.   Value: PIfVariant;
  4377.   WithList: TIfList;
  4378. begin
  4379.   ProcessConsts := False;
  4380.   Parser.Next;
  4381.   repeat
  4382.     if Parser.CurrTokenId <> CSTI_Identifier then begin
  4383.       RunError(Self, EIdentifierExpected);
  4384.       exit;
  4385.     end;
  4386.     Name := Parser.GetToken;
  4387.     if IdentifierExists(True, Vars, Name) then begin
  4388.       RunError(Self, EDuplicateIdentifier);
  4389.       exit;
  4390.     end;
  4391.     Parser.Next;
  4392.     if Parser.CurrTokenId <> CSTI_Equal then begin
  4393.       RunError(Self, EIsExpected);
  4394.       exit;
  4395.     end;
  4396.     Parser.Next;
  4397.     Value := CreateCajVariant(TM_Add(Types, '', CSV_Var, nil));
  4398.     Value^.CV_Var := nil;
  4399.     WithList := TIFList.Create;
  4400.     if not calc(WithList, Vars, Value, CSTI_Semicolon, True) then begin
  4401.       DestroyCajVariant(Value);
  4402.       DestroyWithList(WithList);
  4403.       exit;
  4404.     end;
  4405.     DestroyWithList(WithList);
  4406.     Value^.Flags := $1;
  4407.     Vm_Add(Vars, Value, Name);
  4408.     Parser.Next;
  4409.   until Parser.CurrTokenId <> CSTI_Identifier;
  4410.   ProcessConsts := True;
  4411. end;
  4412. //-------------------------------------------------------------------
  4413.  
  4414. function TIfPasScript.ProcessVars(Vars: PVariableManager): Boolean;
  4415.         { Process Vars block }
  4416. var
  4417.   Names: string;
  4418.   n: PTypeRec;
  4419.   function IsDuplic(N, S: string): boolean;
  4420.   begin
  4421.     while Pos('|', N) > 0 do begin
  4422.       if copy(N, 1, Pos('|', N) - 1) = s then begin IsDuplic := True; exit; end;
  4423.       Delete(N, 1, Pos('|', N));
  4424.     end; {if}
  4425.     IsDuplic := False;
  4426.   end;
  4427. begin
  4428.   Parser.Next;
  4429.   ProcessVars := False;
  4430.   while True do begin
  4431.     case Parser.CurrTokenId of
  4432.       CSTI_EOF: begin
  4433.           RunError(Self, EUnexpectedEndOfFile);
  4434.           exit;
  4435.         end;
  4436.     end;
  4437.     if Parser.CurrTokenId <> CSTI_Identifier then begin
  4438.       RunError(Self, EIdentifierExpected);
  4439.       exit;
  4440.     end;
  4441.     if IdentifierExists(False, Vars, Parser.GetToken) then begin
  4442.       RunError(Self, EDuplicateIdentifier);
  4443.       exit;
  4444.     end; {if}
  4445.  
  4446.     Names := Parser.GetToken + '|';
  4447.     Parser.Next;
  4448.     while Parser.CurrTokenId = CSTI_Comma do begin
  4449.       Parser.Next;
  4450.       if Parser.CurrTokenId <> CSTI_Identifier then begin
  4451.         RunError(Self, EIdentifierExpected);
  4452.         exit;
  4453.       end; {if}
  4454.       if isDuplic(Names, Parser.GetToken) or IdentifierExists(False, Vars, Parser.GetToken) then begin
  4455.         RunError(Self, EDuplicateIdentifier);
  4456.         exit;
  4457.       end; {if}
  4458.       Names := Names + Parser.GetToken + '|';
  4459.       Parser.Next;
  4460.     end; {while}
  4461.     if Parser.CurrTokenId <> CSTI_Colon then begin
  4462.       RunError(Self, EColonExpected);
  4463.       exit;
  4464.     end; {if}
  4465.     Parser.Next;
  4466.     n := ReadType(Parser, False, '');
  4467.     if n = nil then begin
  4468.       exit;
  4469.     end; {if}
  4470.     while Pos('|', Names) > 0 do begin
  4471.       Vm_Add(Vars, CreateCajVariant(n), copy(Names, 1, Pos('|', Names) - 1));
  4472.       Delete(Names, 1, Pos('|', Names));
  4473.     end; {if}
  4474.     if Parser.CurrTokenId <> CSTI_Semicolon then begin
  4475.       RunError(Self, ESemiColonExpected);
  4476.       exit;
  4477.     end; {if}
  4478.     Parser.Next;
  4479.     if Parser.CurrTokenId <> CSTI_Identifier then
  4480.       break;
  4481.   end; {while}
  4482.   ProcessVars := True;
  4483. end; {ProcessVars}
  4484.  
  4485. //-------------------------------------------------------------------
  4486.  
  4487. constructor TIfPasScript.Create(id: Pointer);
  4488. begin
  4489.   inherited Create;
  4490.   fId := id;
  4491. {$IFNDEF NOCLASSES}
  4492.   CreatedClasses := TIfList.Create;
  4493. {$ENDIF}
  4494.   FModuleName := 'MAIN';
  4495.   FISUnit := False;
  4496.   FMaxBeginNesting := High(Longint);
  4497.   FMaxArrayLength := High(Longint);
  4498.  
  4499.   Parser := TIfPascalParser.Create;
  4500.   FAttachedOnes := TIfList.Create;
  4501.   FUses := TIfStringList.Create;
  4502.   FAllocatedResources := TIfList.Create;
  4503.   RunError(Self, ENoError);
  4504.   MainOffset := -1;
  4505.   Procedures := PM_Create;
  4506.   Variables := VM_Create(nil);
  4507.   Types := TM_Create;
  4508.   OnUses := nil;
  4509.   OnRunLine := nil;
  4510. end; {Create}
  4511. //-------------------------------------------------------------------
  4512.  
  4513. destructor TIfPasScript.Destroy;
  4514. begin
  4515.   Cleanup;
  4516.   Parser.Free;
  4517.   VM_Destroy(Variables);
  4518.   PM_Destroy(Procedures);
  4519.   TM_Destroy(Types);
  4520.   FAttachedOnes.Free;
  4521.   FAllocatedResources.Free;
  4522.   {$IFNDEF NOCLASSES}
  4523.   CreatedClasses.Free;
  4524.   {$ENDIF}
  4525.   FUses.Free;
  4526.   inherited Destroy;
  4527. end; {Create}
  4528. //-------------------------------------------------------------------
  4529.  
  4530. function TIfPasScript.GetErrorCode: TIfPasScriptError;
  4531. begin
  4532.   GetErrorCode := FError.ErrorCode;
  4533. end;
  4534.  
  4535. function TIfPasScript.GetErrorPos: Longint;
  4536. begin
  4537.   GetErrorPos := FError.ErrorPosition;
  4538. end;
  4539.  
  4540. function TIfPasScript.GetErrorString: string;
  4541. begin
  4542.   GetErrorString := FError.ErrorParam;
  4543. end;
  4544.  
  4545. function TIfPasScript.GetErrorModule: string;
  4546. begin
  4547.   GetErrorModule := FError.ErrorModule;
  4548. end;
  4549.  
  4550.  
  4551. procedure TIfPasScript.RunError(SE: TIfPasScript; C: TIfPasScriptError);
  4552. begin
  4553.   if C = ENoError then begin
  4554.     FError.ErrorCode := C;
  4555.     FError.ErrorPosition := -1;
  4556.     FError.ErrorParam := '';
  4557.     FError.ErrorModule := '';
  4558.   end {if}
  4559.   else begin
  4560.     if FError.ErrorCode = ENoError then begin
  4561.       FError.ErrorCode := C;
  4562.       FError.ErrorPosition := Se.Parser.CurrTokenPos;
  4563.       FError.ErrorParam := '';
  4564.       FError.ErrorModule := Se.ModuleName;
  4565.     end;
  4566.   end; {else if}
  4567. end; {RunError}
  4568. //-------------------------------------------------------------------
  4569.  
  4570. procedure TIfPasScript.RunError2(SE: TIfPasScript; C: TIfPasScriptError; Ext: string);
  4571. begin
  4572.   if C = ENoError then begin
  4573.     FError.ErrorCode := C;
  4574.     FError.ErrorPosition := -1;
  4575.     FError.ErrorParam := '';
  4576.     FError.ErrorModule := '';
  4577.   end {if}
  4578.   else begin
  4579.     if FError.ErrorCode = ENoError then begin
  4580.       FError.ErrorCode := C;
  4581.       FError.ErrorPosition := Se.Parser.CurrTokenPos;
  4582.       FError.ErrorParam := Ext;
  4583.       FError.ErrorModule := Se.ModuleName;
  4584.     end;
  4585.   end; {else if}
  4586. end; {RunError2}
  4587.  
  4588. //-------------------------------------------------------------------
  4589. // Procedure: RunScript
  4590. //   Purpose: Process the script commands
  4591. //-------------------------------------------------------------------
  4592.  
  4593. procedure TIfPasScript.RunScript;
  4594. var
  4595.   WithList: TIfList;
  4596. begin
  4597.   CurrProc := nil;
  4598.   if MainOffset = -1 then exit;
  4599.  
  4600.   RunError(Self, ENoError); // Reset the error code and position
  4601.   Parser.CurrTokenPos := MainOffset; // Position for the next token
  4602.   //
  4603.   // RunBegin actually parses the script and expects a final period
  4604.   //-----------------
  4605.   WithList := TIFList.Create;
  4606.   if RunBegin(WithList, nil, False) then begin
  4607.     if Parser.CurrTokenId <> CSTI_Period then RunError(Self, EPeriodExpected);
  4608.   end;
  4609.   if FError.ErrorCode = EExitCommand then
  4610.     FError.ErrorCode := 0;
  4611.   DestroyWithList(WithList);
  4612.   FBeginNesting := 0;
  4613.  
  4614. end; {RunScript}
  4615. //-------------------------------------------------------------------
  4616. type
  4617.   PSmallCalculation = ^TSmallCalculation;
  4618.   TSmallCalculation = packed record
  4619.     TType: Byte;
  4620.                                   {
  4621.                                   0 = Variant
  4622.  
  4623.                                   2 = *
  4624.                                   3 = /
  4625.                                   4 = DIV
  4626.                                   5 = MOD
  4627.                                   6 = AND
  4628.                                   7 = SHR
  4629.                                   8 = SHL
  4630.  
  4631.                                   9 = +
  4632.                                   10 = -
  4633.                                   11 = OR
  4634.                                   12 = XOR
  4635.  
  4636.                                   13 = =
  4637.                                   14 = >
  4638.                                   15 = <
  4639.                                   16 = <>
  4640.                                   17 = <=
  4641.                                   18 = >=
  4642.                                   19 = AS
  4643.                                   20 = IS
  4644.                                   }
  4645.     CajVariant: PIfVariant;
  4646.   end;
  4647.  
  4648. function TIfPasScript.calc(WithList: TIFList; Vars: PVariableManager; res: PIfVariant; StopOn: TIfPasToken; OnlyConst: Boolean): Boolean;
  4649. { Calculate an expression }
  4650. var
  4651.   Items: TIfList;
  4652.   PreCalc: string;
  4653.   temp4: PIfVariant;
  4654.   Work: PSmallCalculation;
  4655.  
  4656.   function ChrToStr(s: string): Char;
  4657.     {Turn a char intto a string}
  4658.   begin
  4659.     Delete(s, 1, 1); {First char : #}
  4660.     ChrToStr := Chr(StrToInt(s));
  4661.   end;
  4662.  
  4663.   function PString(s: string): string;
  4664.     { remove the ' from the strings}
  4665.   begin
  4666.     s := copy(s, 2, Length(s) - 2);
  4667.     PString := s;
  4668.   end;
  4669.  
  4670.   function DoPrecalc: Boolean;
  4671.     {Pre calculate (- not +)}
  4672.   begin
  4673.     DoPrecalc := True;
  4674.     while Length(PreCalc) > 0 do begin
  4675.       if PreCalc[1] = '-' then begin
  4676.         if not DoMinus(Work^.CajVariant) then begin
  4677.           RunError(Self, ETypeMismatch);
  4678.           exit;
  4679.         end;
  4680.       end else if PreCalc[1] = '|' then begin
  4681.         if not DoNot(Work^.CajVariant) then begin
  4682.           RunError(Self, ETypeMismatch);
  4683.           exit;
  4684.         end;
  4685.       end else if PreCalc[1] = '+' then begin
  4686.         {plus has no effect}
  4687.       end else begin
  4688.         DoPrecalc := False;
  4689.         exit;
  4690.       end;
  4691.       Delete(PreCalc, 1, 1);
  4692.     end;
  4693.   end;
  4694.  
  4695.   procedure DisposeList;
  4696.     { Dispose the items }
  4697.   var
  4698.     I: Integer;
  4699.     p: PSmallCalculation;
  4700.   begin
  4701.     for I := 0 to Items.Count - 1 do begin
  4702.       p := Items.GetItem(I);
  4703.       if p^.TType = 0 then
  4704.         DestroyCajVariant(p^.CajVariant);
  4705.       Dispose(p);
  4706.     end;
  4707.     Items.Destroy;
  4708.   end;
  4709.  
  4710.   function ParseString: string;
  4711.     { Parse a string }
  4712.   var
  4713.     temp3: string;
  4714.   begin
  4715.     temp3 := '';
  4716.     while (Parser.CurrTokenId = CSTI_String) or
  4717.       (Parser.CurrTokenId = CSTI_Char) do begin
  4718.       if Parser.CurrTokenId = CSTI_String
  4719.         then begin
  4720.         temp3 := temp3 + PString(Parser.GetToken);
  4721.         Parser.Next;
  4722.         if Parser.CurrTokenId = CSTI_String then
  4723.           temp3 := temp3 + #39;
  4724.       end {if}
  4725.       else begin
  4726.         temp3 := temp3 + ChrToStr(Parser.GetToken);
  4727.         Parser.Next;
  4728.       end; {else if}
  4729.     end; {while}
  4730.     ParseString := temp3;
  4731.   end;
  4732.  
  4733.   procedure Calculate;
  4734.     { Calculate the full expression }
  4735.   var
  4736.     l: PSmallCalculation;
  4737.     I: Longint;
  4738.   begin
  4739.     I := 0;
  4740.     while I < Longint(Items.Count - 1) div 2 do begin
  4741.       l := PSmallCalculation(Items.GetItem(I * 2 + 1));
  4742.       if ((l^.TType >= 2) and (l^.TType <= 8)) or (l^.TType = 19) then begin
  4743.         case l^.TType of
  4744. {$IFNDEF NOCLASSES}
  4745.           19: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4746.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4747.               ^.CajVariant, ptAs)
  4748.             then
  4749.               exit;
  4750. {$ENDIF}
  4751.           2: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4752.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4753.               ^.CajVariant, PtMul)
  4754.             then
  4755.               exit;
  4756.           3: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4757.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4758.               ^.CajVariant, ptDiv)
  4759.             then
  4760.               exit;
  4761.           4: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4762.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4763.               ^.CajVariant, PtIntDiv)
  4764.             then
  4765.               exit;
  4766.           5: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4767.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4768.               ^.CajVariant, PtIntMod)
  4769.             then
  4770.               exit;
  4771.           6: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4772.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4773.               ^.CajVariant, PtAnd)
  4774.             then
  4775.               exit;
  4776.           7: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4777.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4778.               ^.CajVariant, PtShr)
  4779.             then
  4780.               exit;
  4781.           8: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4782.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4783.               ^.CajVariant, PtShl)
  4784.             then
  4785.               exit;
  4786.         end;
  4787.         if ErrorCode <> 0 then
  4788.           exit;
  4789.         l := PSmallCalculation(Items.GetItem(I * 2 + 2));
  4790.         DestroyCajVariant(l^.CajVariant);
  4791.         Dispose(l);
  4792.         Items.Remove(l);
  4793.         l := PSmallCalculation(Items.GetItem(I * 2 + 1));
  4794.         Dispose(l);
  4795.         Items.Remove(l);
  4796.       end else Inc(I);
  4797.     end;
  4798.  
  4799.     I := 0;
  4800.     while I < Longint(Items.Count - 1) div 2 do begin
  4801.       l := PSmallCalculation(Items
  4802.         .GetItem(I * 2 + 1));
  4803.       if (l^.TType >= 9) and (l^.TType <= 12) then begin
  4804.         case l^.TType of
  4805.           9: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4806.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4807.               ^.CajVariant, PtPlus)
  4808.             then
  4809.               exit;
  4810.           10: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4811.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4812.               ^.CajVariant, ptMinus)
  4813.             then
  4814.               exit;
  4815.           11: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4816.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4817.               ^.CajVariant, ptOr)
  4818.             then
  4819.               exit;
  4820.           12: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4821.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4822.               ^.CajVariant, ptXor)
  4823.             then
  4824.               exit;
  4825.         end;
  4826.         if ErrorCode <> 0 then
  4827.           exit;
  4828.         l := PSmallCalculation(Items.GetItem(I * 2 + 2));
  4829.         DestroyCajVariant(l^.CajVariant);
  4830.         Dispose(l);
  4831.         Items.Remove(l);
  4832.         l := PSmallCalculation(Items
  4833.           .GetItem(I * 2 + 1));
  4834.         Dispose(l);
  4835.         Items.Remove(l);
  4836.       end else Inc(I);
  4837.     end;
  4838.     I := 0;
  4839.     while I < Longint(Items.Count - 1) div 2 do begin
  4840.       l := PSmallCalculation(Items.GetItem(I * 2 + 1));
  4841.       if ((l^.TType >= 13) and (l^.TType <= 18)) or (l^.TType = 20) then begin
  4842.         case l^.TType of
  4843.           13: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4844.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4845.               ^.CajVariant, PtEqual)
  4846.             then
  4847.               exit;
  4848.           14: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4849.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4850.               ^.CajVariant, PtGreater)
  4851.             then
  4852.               exit;
  4853.           15: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4854.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4855.               ^.CajVariant, PtLess)
  4856.             then
  4857.               exit;
  4858.           16: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4859.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4860.               ^.CajVariant, PtNotEqual)
  4861.             then
  4862.               exit;
  4863.           17: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4864.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4865.               ^.CajVariant, PtLessEqual)
  4866.             then
  4867.               exit;
  4868.           18: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4869.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4870.               ^.CajVariant, PtGreaterEqual)
  4871.             then
  4872.               exit;
  4873. {$IFNDEF NOCLASSES}
  4874.           20: if not Perform(PSmallCalculation(Items.GetItem(I * 2))^.
  4875.               CajVariant, PSmallCalculation(Items.GetItem(I * 2 + 2))
  4876.               ^.CajVariant, ptIs)
  4877.             then
  4878.               exit;
  4879. {$ENDIF}
  4880.         end;
  4881.         if ErrorCode <> 0 then
  4882.           exit;
  4883.         l := PSmallCalculation(Items.GetItem(I * 2 + 2));
  4884.         DestroyCajVariant(l^.CajVariant);
  4885.         Dispose(l);
  4886.         Items.Remove(l);
  4887.         l := PSmallCalculation(Items.GetItem(I * 2 + 1));
  4888.         Dispose(l);
  4889.         Items.Remove(l);
  4890.       end else Inc(I);
  4891.     end;
  4892.   end; {Calculate}
  4893.  
  4894. begin
  4895.   Items := TIfList.Create;
  4896.   calc := False;
  4897.   res := GetVarLink(res);
  4898.   while True do begin
  4899.     if Parser.CurrTokenId = StopOn then
  4900.       break;
  4901.     case Parser.CurrTokenId of
  4902.       CSTII_Else,
  4903.         CSTII_To,
  4904.         CSTII_DownTo,
  4905.         CSTII_do,
  4906.         CSTII_until,
  4907.         CSTI_Semicolon,
  4908.         CSTII_End,
  4909.         CSTI_Comma,
  4910.         CSTI_CloseRound: begin
  4911.           break;
  4912.         end; {Csti_Else...}
  4913.       CSTI_EOF: begin
  4914.           RunError(Self, EUnexpectedEndOfFile);
  4915.           DisposeList;
  4916.           exit;
  4917.         end; {CSTI_Eof}
  4918.     end; {case}
  4919.     if (Items.Count and $1) = 0 then begin
  4920.       PreCalc := '';
  4921.       while (Parser.CurrTokenId = CSTI_Minus) or
  4922.         (Parser.CurrTokenId = CSTII_Not) or
  4923.         (Parser.CurrTokenId = CSTI_Plus)
  4924.         do begin
  4925.         if (Parser.CurrTokenId = CSTI_Minus) then
  4926.           PreCalc := PreCalc + '-';
  4927.         if (Parser.CurrTokenId = CSTII_Not) then
  4928.           PreCalc := PreCalc + '|';
  4929.         if (Parser.CurrTokenId = CSTI_Plus) then
  4930.           PreCalc := PreCalc + '+';
  4931.         Parser.Next;
  4932.       end; {While}
  4933.  
  4934.       New(Work);
  4935.       case Parser.CurrTokenId of
  4936.         CSTI_AddressOf: begin
  4937.             Parser.Next;
  4938.             case Getidentifier(WithList, Vars, 2, temp4) of
  4939.               0: begin
  4940.                 Dispose(Work);
  4941.                 DisposeList;
  4942.                 exit;
  4943.               end;
  4944.               1: begin
  4945.                 RunError(Self, ETypeMismatch);
  4946.                 Dispose(Work);
  4947.                 DisposeList;
  4948.                 exit;
  4949.               end;
  4950.               2: begin
  4951.                 if temp4^.VType^.atypeid <> CSV_ProcVariable then
  4952.                 begin
  4953.                   RunError(Self, ETypeMismatch);
  4954.                   DestroycajVariant(temp4);
  4955.                   Dispose(Work);
  4956.                   DisposeList;
  4957.                   exit;
  4958.                 end;
  4959.               end;
  4960.             end;
  4961.             Work^.CajVariant := temp4;
  4962.             Work^.TType := 0;
  4963.             Items.Add(Work);
  4964.           end;
  4965.         CSTI_OpenBlock: begin
  4966.             Parser.Next;
  4967.             if res^.VType^.atypeid = CSV_Array then begin
  4968.               Work^.CajVariant := CreateCajVariant(res^.VType);
  4969.               while True do begin
  4970.                 temp4 := CreateCajVariant(res^.VType^.Ext);
  4971.                 if not calc(Withlist, Vars, temp4, CSTI_CloseBlock, False) then begin
  4972.                   DestroyCajVariant(temp4);
  4973.                   DestroyCajVariant(Work^.CajVariant);
  4974.                   Dispose(Work);
  4975.                   DisposeList;
  4976.                   exit;
  4977.                 end;
  4978.                 Work^.CajVariant^.CV_ArrItems.Add(temp4);
  4979.                 if Parser.CurrTokenId = CSTI_CloseBlock then
  4980.                   break;
  4981.                 if (Parser.CurrTokenId <> CSTI_Comma) then begin
  4982.                   RunError(Self, ECloseBlockExpected);
  4983.                   DestroyCajVariant(Work^.CajVariant);
  4984.                   Dispose(Work);
  4985.                   DisposeList;
  4986.                   exit;
  4987.                 end;
  4988.                 Parser.Next;
  4989.               end;
  4990.               Parser.Next;
  4991.               Work^.TType := 0;
  4992.               Items.Add(Work);
  4993.             end else begin
  4994.               RunError(Self, ETypeMismatch);
  4995.               Dispose(Work);
  4996.               DisposeList;
  4997.               exit;
  4998.             end;
  4999.           end;
  5000.         CSTI_OpenRound: begin
  5001.             Parser.Next;
  5002.             Work^.CajVariant := CreateCajVariant(TM_Add(Types, '', CSV_Var, nil));
  5003.             Work^.CajVariant^.CV_Var := nil;
  5004.             Work^.TType := 0;
  5005.             if not calc(WithList, Vars, Work^.CajVariant, CSTI_CloseRound, OnlyConst) then begin
  5006.               DestroyCajVariant(Work^.CajVariant);
  5007.               Dispose(Work);
  5008.               DisposeList;
  5009.               exit;
  5010.             end; {if}
  5011.             if not DoPrecalc then begin
  5012.               DestroyCajVariant(Work^.CajVariant);
  5013.               Dispose(Work);
  5014.               DisposeList;
  5015.               exit;
  5016.             end; {if}
  5017.             Parser.Next;
  5018.             Items.Add(Work);
  5019.           end; {CSTI_OpenRound}
  5020.         CSTII_Inherited,
  5021.           CSTI_Identifier: begin
  5022.             case GetIdentifier(WithList, Vars, 0, temp4) of
  5023.               0: begin
  5024.                   Dispose(Work);
  5025.                   DisposeList;
  5026.                   exit;
  5027.                 end;
  5028.               1: Work^.CajVariant := CopyVariant(temp4);
  5029.               2: Work^.CajVariant := temp4;
  5030.             end;
  5031.             if Work^.CajVariant = nil then begin
  5032.               RunError(Self, ETypeMismatch);
  5033.               Dispose(Work);
  5034.               DisposeList;
  5035.               exit;
  5036.             end;
  5037. {$IFNDEF NOCLASSES}
  5038.             if Work^.CajVariant^.VType^.atypeid = CSV_Property then begin
  5039.               temp4 := GetProperty(Work^.CajVariant);
  5040.               DestroyCajVariant(Work^.CajVariant);
  5041.               if temp4 = nil then begin
  5042.                 Dispose(Work);
  5043.                 DisposeList;
  5044.                 exit;
  5045.               end;
  5046.               Work^.CajVariant := temp4;
  5047.             end;
  5048.             if (Work^.CajVariant^.VType^.atypeid = CSV_ExternalObjectProperty) then begin
  5049.               Temp4 := Work.CajVariant;
  5050.               if (not assigned(Temp4^.CV_ExtObj)) or (PCreatedCustomObject(Temp4^.CV_ExtObj)^.AlreadyFreed) then
  5051.               begin
  5052.                 RunError(Self, EClassNotCreated);
  5053.                 DestroycajVariant(Temp4);
  5054.                 Dispose(Work);
  5055.                 DisposeList;
  5056.                 exit;
  5057.               end;
  5058.               Work^.CajVariant := CreatecajVariant(PCreatedCustomObject(temp4^.CV_ExtObj).P.GetPropertyType(temp4^.CV_PropertyNo));
  5059.               if not PCreatedCustomObject(temp4^.CV_ExtObj).P.GetProperty(temp4^.CV_PropertyNo, Work^.CajVariant) then
  5060.               begin
  5061.                 RunError(Self, ECanNotReadProperty);
  5062.                 DestroyCajVariant(Work^.CajVariant);
  5063.                 DestroycajVariant(Temp4);
  5064.                 Dispose(Work);
  5065.                 DisposeList;
  5066.                 exit;
  5067.               end;
  5068.               DestroyCajVariant(Temp4);
  5069.               if Work^.CajVariant = nil then begin
  5070.                 RunError(Self, ETypeMismatch);
  5071.                 DestroycajVariant(Work^.CajVariant);
  5072.                 Dispose(Work);
  5073.                 DisposeList;
  5074.                 exit;
  5075.               end;
  5076.             end;
  5077. {$ENDIF}
  5078.             Work^.TType := 0;
  5079.             if not DoPrecalc then begin
  5080.               DestroyCajVariant(Work^.CajVariant);
  5081.               Dispose(Work);
  5082.               DisposeList;
  5083.               exit;
  5084.             end; {if}
  5085.             Items.Add(Work);
  5086.           end; {CSTI_Identifier, CSTII_Inherited}
  5087.         CSTI_Integer: begin
  5088.             if ((res^.VType^.atypeid >= CSV_SByte) and (res^.VType^.atypeid <= CSV_SInt32)){ or
  5089.               ((res^.VType^.atypeid >= CSV_Real) and (res^.VType^.atypeid <= CSV_Comp)) }then
  5090.               Work^.CajVariant := CreateCajVariant(res^.VType)
  5091.             else
  5092.               Work^.CajVariant := CreateCajVariant(TM_Add(Types, '', CSV_SInt32, nil));
  5093.             Work^.TType := 0;
  5094.             if IsRealType(Work^.CajVariant) then
  5095.               SetReal(Work^.CajVariant, StrToInt(Parser.GetToken))
  5096.             else
  5097.               SetInteger(Work^.CajVariant, StrToInt(Parser.GetToken));
  5098.             if not DoPrecalc then begin
  5099.               DestroyCajVariant(Work^.CajVariant);
  5100.               Dispose(Work);
  5101.               DisposeList;
  5102.               exit;
  5103.             end; {if}
  5104.             Parser.Next;
  5105.             Items.Add(Work);
  5106.           end; {CSTI_Integer}
  5107.         CSTI_Real: begin
  5108.             if (res^.VType^.atypeid >= CSV_Real) and (res^.VType^.atypeid <= CSV_Comp) then
  5109.               Work^.CajVariant := CreateCajVariant(res^.VType)
  5110.             else
  5111.               Work^.CajVariant := CreateCajVariant(TM_Add(Types, '', CSV_Extended, nil));
  5112.             Work^.TType := 0;
  5113.             SetReal(Work^.CajVariant, StrToReal(Parser.GetToken));
  5114.             if not DoPrecalc then begin
  5115.               DestroyCajVariant(Work^.CajVariant);
  5116.               Dispose(Work);
  5117.               DisposeList;
  5118.               exit;
  5119.             end;
  5120.             Parser.Next;
  5121.             Items.Add(Work);
  5122.           end; {CSTI_Real}
  5123.         CSTI_String, CSTI_Char: begin
  5124.  
  5125.             Work^.CajVariant := CreateCajVariant(TM_Add(Types, '', CSV_String, nil));
  5126.             Work^.TType := 0;
  5127.             Work^.CajVariant^.Cv_Str := ParseString;
  5128.             if not DoPrecalc then begin
  5129.               DestroyCajVariant(Work^.CajVariant);
  5130.               Dispose(Work);
  5131.               DisposeList;
  5132.               exit;
  5133.             end; {if}
  5134.             Items.Add(Work);
  5135.           end; {CSTI_String}
  5136.         CSTI_HexInt: begin
  5137.             Work^.TType := 0;
  5138.             if (res^.VType^.atypeid >= CSV_SByte) and (res^.VType^.atypeid <= CSV_SInt32) then
  5139.               Work^.CajVariant := CreateCajVariant(res^.VType)
  5140.             else
  5141.               Work^.CajVariant := CreateCajVariant(TM_Add(Types, '', CSV_SInt32, nil));
  5142.             SetInteger(Work^.CajVariant, StrToInt(Parser.GetToken));
  5143.             if not DoPrecalc then begin
  5144.               DestroyCajVariant(Work^.CajVariant);
  5145.               Dispose(Work);
  5146.               DisposeList;
  5147.               exit;
  5148.             end; {if}
  5149.             Parser.Next;
  5150.             Items.Add(Work);
  5151.           end; {CSTI_HexInt}
  5152.       else begin
  5153.           RunError(Self, EErrorInExpression);
  5154.           Dispose(Work);
  5155.           DisposeList;
  5156.           exit;
  5157.         end;
  5158.       end; {case}
  5159.     end {if}
  5160.     else begin
  5161.       New(Work);
  5162.       case Parser.CurrTokenId of
  5163.         CSTI_Equal: Work^.TType := 13;
  5164.         CSTI_NotEqual: Work^.TType := 16;
  5165.         CSTI_Greater: Work^.TType := 14;
  5166.         CSTI_GreaterEqual: Work^.TType := 18;
  5167.         CSTI_Less: Work^.TType := 15;
  5168.         CSTI_LessEqual: Work^.TType := 17;
  5169.         CSTI_Plus: Work^.TType := 9;
  5170.         CSTI_Minus: Work^.TType := 10;
  5171.         CSTI_Divide: begin
  5172.             Work^.TType := 3;
  5173.             if res^.VType^.atypeid = CSV_Var then
  5174.               ChangeType(res, TM_Add(Types, '', CSV_Extended, nil));
  5175.           end;
  5176.         CSTI_Multiply: Work^.TType := 2;
  5177.         CSTII_and: Work^.TType := 6;
  5178.         CSTII_div: Work^.TType := 4;
  5179.         CSTII_mod: Work^.TType := 5;
  5180.         CSTII_or: Work^.TType := 11;
  5181.         CSTII_shl: Work^.TType := 8;
  5182.         CSTII_shr: Work^.TType := 7;
  5183.         CSTII_xor: Work^.TType := 12;
  5184. {$IFNDEF NOCLASSES}
  5185.         CSTII_As: Work^.TType := 19;
  5186.         CSTII_Is: Work^.TType := 20;
  5187. {$ENDIF}
  5188.       else begin
  5189.           RunError(Self, EErrorInExpression);
  5190.           Dispose(Work);
  5191.           DisposeList;
  5192.           exit;
  5193.         end; {else case}
  5194.       end; {case}
  5195.       Items.Add(Work);
  5196.       Parser.Next;
  5197.     end; {else if}
  5198.   end; {while}
  5199.   Calculate;
  5200.   if ErrorCode = 0 then begin
  5201.     if Items.Count <> 1 then begin
  5202.       RunError(Self, EErrorInExpression);
  5203.       calc := False;
  5204.     end else begin
  5205.       Work := Items.GetItem(0);
  5206.       if Perform(res, Work^.CajVariant, PtSet) then
  5207.         calc := True
  5208.       else
  5209.         calc := False;
  5210.     end; {if}
  5211.   end; {if}
  5212.   DisposeList;
  5213. end; {Calc}
  5214.  
  5215. function TIfPasScript.MakeCompat(v: PIfVariant; FType: PTypeRec): Boolean;
  5216. var
  5217.   n: PIfVariant;
  5218. begin
  5219.   if v^.VType = FType then
  5220.     MakeCompat := True
  5221.   else if (v^.VType^.atypeid = CSV_Array) and (FType^.atypeid = CSV_Array) and (FType^.Ext = nil) then
  5222.     MakeCompat := True
  5223.   else begin
  5224.     n := CreateCajVariant(v^.VType);
  5225.     if not Perform(n, v, PtSet) then begin
  5226.       MakeCompat := False;
  5227.       DestroyCajVariant(n);
  5228.       exit;
  5229.     end;
  5230.     ChangeType(v, FType);
  5231.     if not Perform(v, n, PtSet) then begin
  5232.       MakeCompat := False;
  5233.       DestroyCajVariant(n);
  5234.       exit;
  5235.     end;
  5236.     DestroyCajVariant(n);
  5237.     MakeCompat := True;
  5238.   end;
  5239. end;
  5240. {$IFNDEF NOCLASSES}
  5241.  
  5242. function TIfPasScript.RunInherited(proc: PProcedure; Params: PVariableManager; res: PIfVariant): TIfPasScriptError;
  5243. var
  5244.   u: PIfVariant;
  5245.   p: PVariableManager;
  5246.   I: Integer;
  5247. begin
  5248.   proc := GetInheritedProc(proc);
  5249.   p := VM_Create(nil);
  5250.   for I := 0 to IntProcDefParam(proc^.Decl, -1) do begin
  5251.     Vm_Add(p, CopyVariant(Vm_Get(Params, 0)), '');
  5252.   end;
  5253.   VM_SetName(p, 0, 'SELF');
  5254.   u := RunScriptProc(proc, p);
  5255.   VM_Destroy(p);
  5256.   if FError.ErrorCode <> 0 then begin
  5257.     RunInherited := FError.ErrorCode;
  5258.   end else begin
  5259.     if assigned(u) then begin
  5260.       Perform(res, u, PtSet);
  5261.       DestroyCajVariant(u);
  5262.     end;
  5263.     RunInherited := 0;
  5264.   end;
  5265. end;
  5266. {$ENDIF}
  5267.  
  5268. function TIfPasScript.RunScriptProc(Func: PProcedure; Parameters: PVariableManager): PIfVariant;
  5269. {Call an internal/external Procedure}
  5270. var
  5271.   OldProc: PProcedure;
  5272.   w: PIfVariant;
  5273.   I: Longint;
  5274.   WithList: TIfList;
  5275. {$IFNDEF NOCLASSES}SaveSelf: PIfVariant;
  5276. {$ENDIF}
  5277.  
  5278.   function IRem(s: string): string;
  5279.   {Remove the !}
  5280.   begin
  5281.     Delete(s, 1, 1);
  5282.     IRem := s;
  5283.   end; {irem}
  5284.  
  5285.  
  5286.  
  5287.   {$IFNDEF NOCLASSES}procedure AddSelf;
  5288.   var
  5289.     u: PIfVariant;
  5290.   begin
  5291.     SaveSelf := Vm_Get(Parameters, 0);
  5292.     if GetVarLink(SaveSelf)^.VType <> Func^.ClassType then begin
  5293.       u := CreateCajVariant(Func^.ClassType);
  5294.       u^.CV_Class := GetVarLink(SaveSelf)^.CV_Class;
  5295.       VM_Set(Parameters, 0, u);
  5296.     end;
  5297.   end;
  5298.  
  5299.   procedure RestoreSelf;
  5300.   begin
  5301.     if (SaveSelf <> Vm_Get(Parameters, 0)) and (Func^.ClassType <> nil) then begin
  5302.       DestroyCajVariant(Vm_Get(Parameters, 0));
  5303.       VM_Set(Parameters, 0, SaveSelf);
  5304.     end;
  5305.   end;
  5306. {$ENDIF}
  5307. begin
  5308.   RunScriptProc := nil;
  5309.   RunError(Self, ENoError); //reset
  5310.   if not assigned(Func) then begin
  5311.     FError.ErrorCode := EUnknownIdentifier;
  5312.     FError.ErrorPosition := -1;
  5313.     exit;
  5314.   end;
  5315.   if Func^.FScriptEngine <> self then
  5316.   begin
  5317.     RunScriptProc := TIFPasScript(Func^.FScriptEngine).RunScriptProc(Func, Parameters);
  5318.     if TIFPasScript(Func^.FScriptEngine).ErrorCode <> 0 then
  5319.     begin
  5320.       RunError2(Func^.FScriptEngine, TIfPasScript(Func^.FScriptEngine).ErrorCode, TIFPasScript(Func^.FScriptEngine).ErrorString);
  5321.     end;
  5322.    exit;
  5323.   end;
  5324. {$IFNDEF NOCLASSES}
  5325.   if assigned(Func^.ClassType) then begin
  5326.     if (VM_Count(Parameters) = 0) or (VM_GetName(Parameters, 0) <> 'SELF') then begin
  5327.       FError.ErrorCode := EParameterError;
  5328.       FError.ErrorPosition := -1;
  5329.       exit;
  5330.     end;
  5331.     AddSelf;
  5332.     if IntProcDefParam(Func^.Decl, -1) <> VM_Count(Parameters) - 1 then begin
  5333.       FError.ErrorPosition := -1; { -1 means that the count is not the same }
  5334.       FError.ErrorCode := EParameterError;
  5335.       exit;
  5336.     end;
  5337.   end else {$ENDIF}begin
  5338.     if IntProcDefParam(Func^.Decl, -1) <> VM_Count(Parameters) then begin
  5339.       FError.ErrorPosition := -1; { -1 means that the count is not the same }
  5340.       FError.ErrorCode := EParameterError;
  5341.       exit;
  5342.     end;
  5343.   end;
  5344.   for I := 1 to IntProcDefParam(Func^.Decl, -1) do begin
  5345. {$IFNDEF NOCLASSES}
  5346.     if assigned(Func^.ClassType) then
  5347.       w := Vm_Get(Parameters, I)
  5348.     else
  5349. {$ENDIF}
  5350.       w := Vm_Get(Parameters, I - 1);
  5351.     if Pos('!', IntProcDefName(Func^.Decl, I)) = 1 then begin
  5352.       if (w^.VType^.atypeid <> CSV_Var) or (not assigned(w^.CV_Var)) then begin
  5353.         FError.ErrorPosition := I - 1;
  5354.         FError.ErrorCode := EParameterError;
  5355. {$IFNDEF NOCLASSES}RestoreSelf;
  5356. {$ENDIF}
  5357.         exit;
  5358.       end;
  5359.       if PIfVariant(w^.CV_Var)^.VType <> Pointer(IntProcDefParam(Func^.Decl, I)) then begin
  5360.         FError.ErrorPosition := I - 1;
  5361.         FError.ErrorCode := EParameterError;
  5362. {$IFNDEF NOCLASSES}RestoreSelf;
  5363. {$ENDIF}
  5364.         exit;
  5365.       end;
  5366. {$IFNDEF NOCLASSES}
  5367.       if assigned(Func^.ClassType) then
  5368.         VM_SetName(Parameters, I, copy(IntProcDefName(Func^.Decl, I), 2, Length(IntProcDefName(Func^.Decl, I))))
  5369.       else
  5370. {$ENDIF}      
  5371.         VM_SetName(Parameters, I - 1, copy(IntProcDefName(Func^.Decl, I), 2, Length(IntProcDefName(Func^.Decl, I))));
  5372.     end else begin
  5373.       if not MakeCompat(w, Pointer(IntProcDefParam(Func^.Decl, I))) then begin
  5374.         FError.ErrorPosition := I - 1;
  5375.         FError.ErrorCode := EParameterError;
  5376. {$IFNDEF NOCLASSES}RestoreSelf;
  5377. {$ENDIF}
  5378.         exit;
  5379.       end;
  5380. {$IFNDEF NOCLASSES}
  5381.       if assigned(Func^.ClassType) then
  5382.         VM_SetName(Parameters, I, IntProcDefName(Func^.Decl, I))
  5383.       else
  5384. {$ENDIF}
  5385.         VM_SetName(Parameters, I - 1, IntProcDefName(Func^.Decl, I));
  5386.     end;
  5387.   end; {for}
  5388.   OldProc := CurrProc;
  5389.   CurrProc := Func;
  5390.   if Func^.Mode = 0 then begin
  5391.     if IntProcDefParam(Func^.Decl, 0) <> 0 then begin
  5392.       w := CreateCajVariant(Pointer(IntProcDefParam(Func^.Decl, 0)));
  5393.       Vm_Add(Parameters, w, 'RESULT');
  5394.     end {if}
  5395.     else w := nil;
  5396.     I := Parser.CurrTokenPos;
  5397.     Parser.CurrTokenPos := Func^.offset;
  5398.     if Parser.CurrTokenId = CSTII_Var then begin
  5399.       if not ProcessVars(Parameters) then begin
  5400.         DestroyCajVariant(w);
  5401.         if IntProcDefParam(Func^.Decl, 0) <> 0 then begin
  5402.           VM_Delete(Parameters, VM_Find(Parameters, 'RESULT'));
  5403.         end; {if}
  5404. {$IFNDEF NOCLASSES}RestoreSelf;
  5405. {$ENDIF}
  5406.         exit;
  5407.       end; {if}
  5408.     end; {if}
  5409.     WithList := TIfList.Create;
  5410. {$IFNDEF NOCLASSES}
  5411.     if assigned(Func^.ClassType) then
  5412.     begin
  5413.       WithList.Add(CreateVarType(VM_Get(Parameters,0)));
  5414.     end;
  5415. {$ENDIF}
  5416.     if not RunBegin(WithList, Parameters, False) then begin
  5417.       if FError.ErrorCode = EExitCommand then
  5418.         FError.ErrorCode := 0
  5419.       else begin
  5420.         if IntProcDefParam(Func^.Decl, 0) <> 0 then begin
  5421.           VM_Delete(Parameters, VM_Find(Parameters, 'RESULT'));
  5422.         end; {if}
  5423.         DestroyCajVariant(w);
  5424.         DestroyWithList(WithList);
  5425. {$IFNDEF NOCLASSES}RestoreSelf;
  5426. {$ENDIF}
  5427.         exit;
  5428.       end;
  5429.     end; {if}
  5430.     DestroyWithList(WithList);
  5431.     if IntProcDefParam(Func^.Decl, 0) <> 0 then begin
  5432.       VM_Delete(Parameters, VM_Find(Parameters, 'RESULT'));
  5433.     end; {if}
  5434.     Parser.CurrTokenPos := I;
  5435.     RunScriptProc := w;
  5436. {$IFNDEF NOCLASSES}RestoreSelf;
  5437. {$ENDIF}
  5438.     RunError(Self, ENoError);
  5439.     exit;
  5440.   end {if}
  5441.   else if Func^.Mode = 1 then begin
  5442.     if IntProcDefParam(Func^.Decl, 0) <> 0 then
  5443.       w := CreateCajVariant(Pointer(IntProcDefParam(Func^.Decl, 0)))
  5444.     else
  5445.       w := nil;
  5446. {$IFNDEF NOCLASSES}
  5447.     if assigned(Func^.ClassType) then
  5448.       RunError(Self, Func^.proc1(Func^.FScriptEngine, fId, Func, Parameters, w))
  5449.     else
  5450. {$ENDIF}
  5451.       RunError(Self, Func^.proc1(Func^.FScriptEngine, fId, Func, Parameters, w));
  5452.     if FError.ErrorCode = EExitCommand then
  5453.       FError.ErrorCode := 0
  5454.     else
  5455.       if FError.ErrorCode <> ENoError then begin
  5456.         DestroyCajVariant(w);
  5457. {$IFNDEF NOCLASSES}RestoreSelf;
  5458. {$ENDIF}
  5459.         exit;
  5460.       end; {if}
  5461.     RunScriptProc := w;
  5462.   end
  5463.   else begin
  5464.     if IntProcDefParam(Func^.Decl, 0) <> 0 then
  5465.       w := CreateCajVariant(Pointer(IntProcDefParam(Func^.Decl, 0)))
  5466.     else
  5467.       w := nil;
  5468. {$IFNDEF NOCLASSES}
  5469.     if assigned(Func^.ClassType) then
  5470.       RunError(Self, Func^.proc2(Func^.FScriptEngine, fId, Func, Parameters, w))
  5471.     else
  5472. {$ENDIF}
  5473.       RunError(Self, Func^.proc2(Func^.FScriptEngine, fId, Func, Parameters, w));
  5474.     if FError.ErrorCode = EExitCommand then
  5475.       FError.ErrorCode := 0
  5476.     else
  5477.       if FError.ErrorCode <> ENoError then begin
  5478.         DestroyCajVariant(w);
  5479. {$IFNDEF NOCLASSES}RestoreSelf;
  5480. {$ENDIF}
  5481.         exit;
  5482.       end; {if}
  5483.     RunScriptProc := w;
  5484.   end; {if}
  5485.   CurrProc := OldProc;
  5486. {$IFNDEF NOCLASSES}RestoreSelf;
  5487. {$ENDIF}
  5488. end;
  5489. {$IFNDEF NOCLASSES}
  5490.  
  5491. function TIfPasScript.RunScriptConstructor(FType: PTypeRec; Func: PProcedure; Parameters: PVariableManager): PIfVariant;
  5492. {Call an internal/external constructor.
  5493. Note the first parameters must be a dummy one, something like:
  5494. VM_Add(Parameters, Nil, '');
  5495.  
  5496. And then the real parameters. This is because SELF must be the first
  5497. parameter but it is self-created.
  5498.  
  5499. }
  5500. var
  5501.   OldProc: PProcedure;
  5502.   slf, w: PIfVariant;
  5503.   WithList: TIFList;
  5504.   I: Longint;
  5505.   CC: PCreatedClass;
  5506.  
  5507.   function IRem(s: string): string;
  5508.   {Remove the !}
  5509.   begin
  5510.     Delete(s, 1, 1);
  5511.     IRem := s;
  5512.   end; {irem}
  5513.  
  5514.   procedure CreateVars;
  5515.   var
  5516.     I, AA: Longint;
  5517.     C: PIFSClassType;
  5518.     s, Name: string;
  5519.     u: PTypeRec;
  5520.     n: PIfVariant;
  5521.  
  5522.     function CreateProperty(p: PPropertyDef): PCajvariant;
  5523.     var
  5524.       prop: PCajvariant;
  5525.     begin
  5526.       prop := CreateCajVariant(TM_Add(Types, '', CSV_Property, p^.CV_Type));
  5527.       prop^.CV_Self := CC;
  5528.       prop^.CV_PropFlags := p^.CV_PropFlags;
  5529.       if (p^.CV_PropFlags and $5) = $1 then
  5530.         prop^.CV_PropRead := Vm_Get(CC^.Variables, Longint(p^.CV_PropRead))
  5531.       else
  5532.         prop^.CV_PropRead := p^.CV_PropRead;
  5533.       if (p^.CV_PropFlags and $A) = $2 then
  5534.         prop^.CV_PropWrite := Vm_Get(CC^.Variables, Longint(p^.CV_PropWrite))
  5535.       else
  5536.         prop^.CV_PropWrite := p^.CV_PropWrite;
  5537.       if (prop^.CV_PropFlags and $30) = $10 then
  5538.         prop^.Flags := prop^.Flags or 2
  5539.       else if (prop^.CV_PropFlags and $30) = $20 then
  5540.         prop^.Flags := prop^.Flags or 4
  5541.       else if (prop^.CV_PropFlags and $30) = $30 then
  5542.         prop^.Flags := prop^.Flags or 6;
  5543.       CreateProperty := prop;
  5544.     end;
  5545.   begin
  5546.     for I := 0 to (PIFSClassType(CC^.ClassType^.Ext)^.VarNoStart + PIFSClassType(CC^.ClassType^.Ext)^.VarCount) - 1 do begin
  5547.       PVariableManager(CC^.Variables)^.Names.Add('');
  5548.       PVariableManager(CC^.Variables)^.Ptr.Add(nil);
  5549.     end;
  5550.     C := PIFSClassType(CC^.ClassType^.Ext);
  5551.     while assigned(C) do begin
  5552.       s := C^.Variables.u;
  5553.       I := C^.VarNoStart;
  5554.       while Length(s) > 0 do begin
  5555.         Name := Fw(s);
  5556.         Rfw(s);
  5557.         u := Pointer(StrToIntDef(Fw(s), 0));
  5558.         Rfw(s);
  5559.         n := CreateCajVariant(u);
  5560.         case Name[1] of
  5561.           '1': n^.Flags := $2;
  5562.           '2': n^.Flags := $4;
  5563.           '3': n^.Flags := $6;
  5564.         end;
  5565.         PVariableManager(CC^.Variables)^.Ptr.SetItem(I, n);
  5566.         Delete(Name, 1, 1);
  5567.         PVariableManager(CC^.Variables)^.Names.SetItem(I, Name);
  5568.         Inc(I);
  5569.       end; {while}
  5570.       if assigned(C^.InheritsFrom) then
  5571.         C := (C^.InheritsFrom^.Ext)
  5572.       else
  5573.         C := nil;
  5574.     end; {while}
  5575.     AA := VM_Count(CC^.Variables);
  5576.     C := PIFSClassType(CC^.ClassType^.Ext);
  5577.     for I := 0 to (PIFSClassType(CC^.ClassType^.Ext)^.PropStart + PIFSClassType(CC^.ClassType^.Ext)^.Properties.Count) - 1 do begin
  5578.       PVariableManager(CC^.Variables)^.Names.Add('');
  5579.       PVariableManager(CC^.Variables)^.Ptr.Add(nil);
  5580.     end;
  5581.     while assigned(C) do begin
  5582.       for I := 0 to C^.Properties.Count - 1 do begin
  5583.         VM_Set(CC^.Variables, AA + Longint(C^.PropStart) + I, CreateProperty(C^.Properties.GetItem(I)));
  5584.       end;
  5585.       if assigned(C^.InheritsFrom) then
  5586.         C := (C^.InheritsFrom^.Ext)
  5587.       else
  5588.         C := nil;
  5589.     end;
  5590.   end;
  5591.  
  5592. begin
  5593.   if Func^.FScriptEngine <> self then
  5594.   begin
  5595.     RunScriptConstructor := TIFPasScript(Func^.FScriptEngine).RunScriptConstructor
  5596.     (FType, Func, Parameters);
  5597.     if TIFPasScript(Func^.FScriptEngine).ErrorCode <> 0 then
  5598.     begin
  5599.       RunError2(Func^.FScriptEngine, TIfPasScript(Func^.FScriptEngine).ErrorCode, TIFPasScript(Func^.FScriptEngine).ErrorString);
  5600.     end;
  5601.    exit;
  5602.   end;
  5603.   RunError(Self, ENoError);
  5604.   if (Func^.Flags and $40) = 0 then begin
  5605.     FError.ErrorCode := EConstructorExpected;
  5606.     RunScriptConstructor := nil;
  5607.     FError.ErrorPosition := 0;
  5608.     exit;
  5609.   end;
  5610.   New(CC);
  5611.   CC^.Variables := VM_Create(nil);
  5612.   CC^.ClassType := FType;
  5613.   CreateVars;
  5614.   CC^.AlreadyFreed := False;
  5615.   CreatedClasses.Add(CC);
  5616.   slf := CreateCajVariant(FType);
  5617.   slf^.CV_Class := CC;
  5618.   DestroyCajVariant(Vm_Get(Parameters, 0));
  5619.   VM_Set(Parameters, 0, CreateCajVariant(Func^.ClassType));
  5620.   with Vm_Get(Parameters, 0)^ do begin
  5621.     CV_Class := slf^.CV_Class;
  5622.     Flags := 1;
  5623.   end;
  5624.   VM_SetName(Parameters, 0, 'SELF');
  5625.   RunScriptConstructor := nil;
  5626.   if not assigned(Func) then begin
  5627.     FError.ErrorCode := EUnknownIdentifier;
  5628.     DestroyCajVariant(slf);
  5629.     FError.ErrorPosition := -1;
  5630.     exit;
  5631.   end;
  5632.   if IntProcDefParam(Func^.Decl, -1) <> VM_Count(Parameters) - 1 then begin
  5633.     FError.ErrorPosition := -1; { -1 means that the count is not the same }
  5634.     DestroyCajVariant(slf);
  5635.     FError.ErrorCode := EParameterError;
  5636.     exit;
  5637.   end;
  5638.   for I := 1 to IntProcDefParam(Func^.Decl, -1) do begin
  5639.     w := Vm_Get(Parameters, I);
  5640.     if Pos('!', IntProcDefName(Func^.Decl, I)) = 1 then begin
  5641.       if (w^.VType^.atypeid <> CSV_Var) or (not assigned(w^.CV_Var)) then begin
  5642.         FError.ErrorPosition := I - 1;
  5643.         FError.ErrorCode := EParameterError;
  5644.         DestroyCajVariant(slf);
  5645.         exit;
  5646.       end;
  5647.       if PIfVariant(w^.CV_Var)^.VType <> Pointer(IntProcDefParam(Func^.Decl, I)) then begin
  5648.         FError.ErrorPosition := I - 1;
  5649.         FError.ErrorCode := EParameterError;
  5650.         DestroyCajVariant(slf);
  5651.         exit;
  5652.       end;
  5653.       VM_SetName(Parameters, I, copy(IntProcDefName(Func^.Decl, I), 2, Length(IntProcDefName(Func^.Decl, I))))
  5654.     end else begin
  5655.       if not MakeCompat(w, Pointer(IntProcDefParam(Func^.Decl, I))) then begin
  5656.         FError.ErrorPosition := I - 1;
  5657.         FError.ErrorCode := EParameterError;
  5658.         DestroyCajVariant(slf);
  5659.         exit;
  5660.       end;
  5661.       VM_SetName(Parameters, I, IntProcDefName(Func^.Decl, I))
  5662.     end;
  5663.   end; {for}
  5664.   OldProc := CurrProc;
  5665.   CurrProc := Func;
  5666.   if Func^.Mode = 0 then begin
  5667.     I := Parser.CurrTokenPos;
  5668.     Parser.CurrTokenPos := Func^.offset;
  5669.     if Parser.CurrTokenId = CSTII_Var then begin
  5670.       if not ProcessVars(Parameters) then begin
  5671.         DestroyCajVariant(slf);
  5672.         exit;
  5673.       end; {if}
  5674.     end; {if}
  5675.     WithList := TIFList.Create;
  5676.     WithList.Add(CreateVarType(slf));
  5677.     if not RunBegin(WithList, Parameters, False) then begin
  5678.       if FError.ErrorCode = EExitCommand then
  5679.         FError.ErrorCode := 0
  5680.       else begin
  5681.         DestroyCajVariant(slf);
  5682.         DestroyWithList(WithList);
  5683.         exit;
  5684.       end;
  5685.     end; {if}
  5686.     DestroyWithList(WithList);
  5687.     Parser.CurrTokenPos := I;
  5688.     RunScriptConstructor := slf;
  5689.     RunError(Self, 0);
  5690.     exit;
  5691.   end {if}
  5692.   else if Func^.Mode = 1 then begin
  5693.     w := nil;
  5694.     RunError(Self, Func.Proc1(Func^.FScriptEngine, fId, Func, Parameters, w));
  5695.     if FError.ErrorCode = EExitCommand then
  5696.       FError.ErrorCode := 0
  5697.     else
  5698.       if ErrorCode <> ENoError then begin
  5699.         DestroyCajVariant(slf);
  5700.         exit;
  5701.       end; {if}
  5702.     RunScriptConstructor := slf;
  5703.   end{if}
  5704.   else begin
  5705.     w := nil;
  5706.     RunError(Self, Func.Proc2(Func^.FScriptEngine, fId, Func, Parameters, w));
  5707.     if FError.ErrorCode = EExitCommand then
  5708.       FError.ErrorCode := 0
  5709.     else
  5710.       if ErrorCode <> ENoError then begin
  5711.         DestroyCajVariant(slf);
  5712.         exit;
  5713.       end; {if}
  5714.     RunScriptConstructor := slf;
  5715.   end; {if}
  5716.   CurrProc := OldProc;
  5717. end;
  5718.  
  5719. function TIfPasScript.DoClassConstructor(WithList: TIFList; Myclass: PTypeRec; proc: PProcedure; Vars: PVariableManager): PIfVariant;
  5720. {Call an internal/external Procedure}
  5721. var
  5722.   OldProc: PProcedure;
  5723.   slf: PIfVariant;
  5724.   I: Longint;
  5725.   Params: PVariableManager;
  5726.   CC: PCreatedClass;
  5727.  
  5728.   function IRem(s: string): string;
  5729.   {Remove the !}
  5730.   begin
  5731.     Delete(s, 1, 1);
  5732.     IRem := s;
  5733.   end; {irem}
  5734.  
  5735.   procedure CreateVars;
  5736.   var
  5737.     AA, I: Longint;
  5738.     C: PIFSClassType;
  5739.     s, Name: string;
  5740.     u: PTypeRec;
  5741.     n: PIfVariant;
  5742.  
  5743.     function CreateProperty(p: PPropertyDef): PCajvariant;
  5744.     var
  5745.       prop: PCajvariant;
  5746.     begin
  5747.       prop := CreateCajVariant(TM_Add(Types, '', CSV_Property, p^.CV_Type));
  5748.       prop^.CV_Self := CC;
  5749.       prop^.CV_PropFlags := p^.CV_PropFlags;
  5750.       if (p^.CV_PropFlags and $5) = $1 then
  5751.         prop^.CV_PropRead := Vm_Get(CC^.Variables, Longint(p^.CV_PropRead))
  5752.       else
  5753.         prop^.CV_PropRead := p^.CV_PropRead;
  5754.       if (p^.CV_PropFlags and $A) = $2 then
  5755.         prop^.CV_PropWrite := Vm_Get(CC^.Variables, Longint(p^.CV_PropWrite))
  5756.       else
  5757.         prop^.CV_PropWrite := p^.CV_PropWrite;
  5758.       if (prop^.CV_PropFlags and $30) = $10 then
  5759.         prop^.Flags := prop^.Flags or 2
  5760.       else if (prop^.CV_PropFlags and $30) = $20 then
  5761.         prop^.Flags := prop^.Flags or 4
  5762.       else if (prop^.CV_PropFlags and $30) = $30 then
  5763.         prop^.Flags := prop^.Flags or 6;
  5764.       CreateProperty := prop;
  5765.     end;
  5766.   begin
  5767.     for I := 0 to Longint((PIFSClassType(CC^.ClassType^.Ext)^.VarNoStart + PIFSClassType(CC^.ClassType^.Ext)^.VarCount)) - 1 do begin
  5768.       PVariableManager(CC^.Variables)^.Names.Add('');
  5769.       PVariableManager(CC^.Variables)^.Ptr.Add(nil);
  5770.     end;
  5771.     C := PIFSClassType(CC^.ClassType^.Ext);
  5772.     while assigned(C) do begin
  5773.       s := C^.Variables.u;
  5774.       I := C^.VarNoStart;
  5775.       while Length(s) > 0 do begin
  5776.         Name := Fw(s);
  5777.         Rfw(s);
  5778.         u := Pointer(StrToIntDef(Fw(s), 0));
  5779.         Rfw(s);
  5780.         n := CreateCajVariant(u);
  5781.         case Name[1] of
  5782.           '1': n^.Flags := $2;
  5783.           '2': n^.Flags := $4;
  5784.           '3': n^.Flags := $6;
  5785.         end;
  5786.         PVariableManager(CC^.Variables)^.Ptr.SetItem(I, n);
  5787.         Delete(Name, 1, 1);
  5788.         PVariableManager(CC^.Variables)^.Names.SetItem(I, Name);
  5789.         Inc(I);
  5790.       end; {while}
  5791.       if assigned(C^.InheritsFrom) then
  5792.         C := (C^.InheritsFrom^.Ext)
  5793.       else
  5794.         C := nil;
  5795.     end; {while}
  5796.     AA := VM_Count(CC^.Variables);
  5797.     C := PIFSClassType(CC^.ClassType^.Ext);
  5798.     for I := 0 to (PIFSClassType(CC^.ClassType^.Ext)^.PropStart + PIFSClassType(CC^.ClassType^.Ext)^.Properties.Count) - 1 do begin
  5799.       PVariableManager(CC^.Variables)^.Names.Add('');
  5800.       PVariableManager(CC^.Variables)^.Ptr.Add(nil);
  5801.     end;
  5802.     while assigned(C) do begin
  5803.       for I := 0 to C^.Properties.Count - 1 do begin
  5804.         VM_Set(CC^.Variables, AA + Longint(C^.PropStart) + I, CreateProperty(C^.Properties.GetItem(I)));
  5805.       end;
  5806.       if assigned(C^.InheritsFrom) then
  5807.         C := (C^.InheritsFrom^.Ext)
  5808.       else
  5809.         C := nil;
  5810.     end;
  5811.   end;
  5812.  
  5813. begin
  5814.   if (proc^.Flags and $40) = 0 then begin
  5815.     DoClassConstructor := nil;
  5816.     RunError(Self, EConstructorExpected);
  5817.     exit;
  5818.   end;
  5819.   DoClassConstructor := nil;
  5820.   Params := VM_Create(nil);
  5821.   New(CC);
  5822.   CC^.Variables := VM_Create(nil);
  5823.   CC^.ClassType := Myclass;
  5824.   CreateVars;
  5825.   CC^.AlreadyFreed := False;
  5826.   CreatedClasses.Add(CC);
  5827.   slf := CreateCajVariant(Myclass);
  5828.   slf^.CV_Class := CC;
  5829.   with Vm_Add(Params, CreateCajVariant(proc^.ClassType), 'SELF')^ do begin
  5830.     CV_Class := slf^.CV_Class;
  5831.     Flags := 1;
  5832.   end;
  5833.   Parser.Next;
  5834.   if not ReadParams(WithList, proc^.Decl, Vars, Params) then
  5835.   begin
  5836.     VM_Destroy(Params);
  5837.     DestroyCajVariant(slf);
  5838.     exit;
  5839.   end;
  5840.   OldProc := CurrProc;
  5841.   CurrProc := proc;
  5842.   {Now we have all the parameters}
  5843.   if proc^.Mode = 0 then begin
  5844.     I := Parser.CurrTokenPos;
  5845.     Parser.CurrTokenPos := proc^.offset;
  5846.     if Parser.CurrTokenId = CSTII_Var then begin
  5847.       if not ProcessVars(Params) then begin
  5848.         DestroyCajVariant(slf);
  5849.         exit;
  5850.       end; {if}
  5851.     end; {if}
  5852.     WithList := TIfList.Create; // old withlist is no longer needed
  5853.     WithList.add(CreateVarType(VM_Get(Params, 0)));
  5854.     if not RunBegin(Withlist, Params, False) then begin
  5855.       if FError.ErrorCode = EExitCommand then
  5856.         FError.ErrorCode := 0
  5857.       else begin
  5858.         DestroyCajVariant(slf);
  5859.         DestroyWithList(WithList);
  5860.         exit;
  5861.       end;
  5862.     end; {if}
  5863.     DestroyWithList(WithList);
  5864.     Parser.CurrTokenPos := I;
  5865.     DoClassConstructor := slf;
  5866.     VM_Destroy(Params);
  5867.   end {if}
  5868.   else if Proc^.Mode = 1 then begin
  5869.     RunError(Self, Proc^.Proc1(Proc^.FScriptEngine, fId, proc, Params, nil));
  5870.     if FError.ErrorCode = EExitCommand then
  5871.       FError.ErrorCode := 0
  5872.     else
  5873.       if FError.ErrorCode <> ENoError then begin
  5874.         VM_Destroy(Params);
  5875.         DestroyCajVariant(slf);
  5876.         exit;
  5877.       end; {if}
  5878.     VM_Destroy(Params);
  5879.     DoClassConstructor := slf;
  5880.   end {if}
  5881.   else begin
  5882.     RunError(Self, Proc^.Proc2(Proc^.FScriptEngine, fId, proc, Params, nil));
  5883.     if FError.ErrorCode = EExitCommand then
  5884.       FError.ErrorCode := 0
  5885.     else
  5886.       if FError.ErrorCode <> ENoError then begin
  5887.         VM_Destroy(Params);
  5888.         DestroyCajVariant(slf);
  5889.         exit;
  5890.       end; {if}
  5891.     VM_Destroy(Params);
  5892.     DoClassConstructor := slf;
  5893.   end; {if}
  5894.   CurrProc := OldProc;
  5895. end; {DoClassConstructor}
  5896. {$ENDIF}
  5897.  
  5898. function TIfPasScript.ReadParams(WithList: TIFList; ProcDef: string; Vars, Params: PVariableManager): Boolean;
  5899. {Call an internal/external Procedure}
  5900. var
  5901.   w: PIfVariant;
  5902.   I: Longint;
  5903.  
  5904.   function IRem(s: string): string;
  5905.   {Remove the !}
  5906.   begin
  5907.     Delete(s, 1, 1);
  5908.     IRem := s;
  5909.   end; {irem}
  5910. begin
  5911.   ReadParams := False;
  5912.   if (IntProcDefParam(procDef, -1) <> 0) and (Parser.CurrTokenId <> CSTI_OpenRound) then begin
  5913.     RunError(Self, ERoundOpenExpected);
  5914.     exit;
  5915.   end; {if}
  5916.   if (IntProcDefParam(procDef, -1) = 0) and (Parser.CurrTokenId = CSTI_OpenRound) then begin
  5917.     Parser.Next;
  5918.     if Parser.CurrTokenId = CSTI_CloseRound then begin
  5919.       Parser.Next;
  5920.     end else begin
  5921.       RunError(Self, ECloseRoundExpected);
  5922.       exit;
  5923.     end;
  5924.   end; {if}
  5925.   if Parser.CurrTokenId = CSTI_OpenRound then begin
  5926.     for I := 1 to IntProcDefParam(procDef, -1) do begin
  5927.       Parser.Next;
  5928.       if Pos('!', IntProcDefName(procDef, I)) = 1 then begin
  5929.         {Expect a variable}
  5930.         case GetIdentifier(WithList, Vars, 1, w) of
  5931.           0: begin
  5932.               exit;
  5933.             end;
  5934.           2: begin
  5935.               DestroyCajVariant(w);
  5936.               RunError(Self, EVariableExpected);
  5937.               exit;
  5938.             end;
  5939.         end;
  5940.         if (w^.Flags and $1) <> 0 then begin
  5941.           RunError(Self, EVariableExpected);
  5942.           VM_Destroy(Params);
  5943.           exit;
  5944.         end; {if}
  5945.         w := GetVarLink(w);
  5946.         if (Longint(w^.VType) <> IntProcDefParam(procDef, I)) and not ((PTypeRec(IntProcDefParam(procDef, I))^.Ext = nil) and (PTypeRec(IntProcDefParam(procDef, I))^.atypeid = CSV_Array)) then begin
  5947.           RunError(Self, ETypeMismatch);
  5948.           exit;
  5949.         end;
  5950.         Vm_Add(Params, CreateCajVariant(TM_Add(Types, '', CSV_Var, nil)), FastUppercase(IRem(IntProcDefName(procDef, I))))^.CV_Var := w;
  5951.       end {if}
  5952.       else begin
  5953.         w := Vm_Add(Params, CreateCajVariant(Pointer(IntProcDefParam(procDef, I))), IntProcDefName(procDef, I));
  5954.         if not calc(WithList, Vars, w, CSTI_CloseRound, False) then begin
  5955.           exit;
  5956.         end; {if}
  5957.       end; {else if}
  5958.       if I = IntProcDefParam(procDef, -1) then begin
  5959.         if Parser.CurrTokenId <> CSTI_CloseRound then begin
  5960.           RunError(Self, ERoundCloseExpected);
  5961.           exit;
  5962.         end; {if}
  5963.       end {if}
  5964.       else begin
  5965.         if Parser.CurrTokenId <> CSTI_Comma then begin
  5966.           RunError(Self, ECommaExpected);
  5967.           exit;
  5968.         end; {if}
  5969.       end; {else if}
  5970.     end; {for}
  5971.     Parser.Next;
  5972.   end; {if}
  5973.   ReadParams := True;
  5974. end;
  5975.  
  5976. function TIfPasScript.DoProc(WithList: TIFList; {$IFNDEF NOCLASSES}Myself: PCreatedClass; {$ENDIF}proc: PProcedure; Vars: PVariableManager): PIfVariant;
  5977. {Call an internal/external Procedure}
  5978. var
  5979.   OldProc: PProcedure;
  5980.   w: PIfVariant;
  5981.   I: Longint;
  5982.   Params: PVariableManager;
  5983.  
  5984.   function IRem(s: string): string;
  5985.   {Remove the !}
  5986.   begin
  5987.     Delete(s, 1, 1);
  5988.     IRem := s;
  5989.   end; {irem}
  5990. {$IFNDEF NOCLASSES}
  5991.  
  5992.   procedure AddSelf;
  5993.   begin
  5994.     with Vm_Add(Params, CreateCajVariant(proc^.ClassType), 'SELF')^ do begin
  5995.       CV_Class := Myself;
  5996.       Flags := 1;
  5997.     end;
  5998.   end;
  5999. {$ENDIF}
  6000. begin
  6001.   DoProc := nil;
  6002.   Params := VM_Create(nil);
  6003. {$IFNDEF NOCLASSES}
  6004.   if assigned(Myself) then begin
  6005.     AddSelf;
  6006.   end;
  6007. {$ENDIF}
  6008.   if not ReadParams(WithList, Proc^.Decl, Vars, Params) then
  6009.   begin
  6010.     VM_Destroy(Params);
  6011.     exit;
  6012.   end;
  6013.   OldProc := CurrProc;
  6014.   CurrProc := proc;
  6015.   {Now we have all the parameters}
  6016.   if proc^.Mode = 0then begin
  6017.     if Proc^.FScriptEngine = self then
  6018.     begin
  6019.       if IntProcDefParam(proc^.Decl, 0) <> 0 then begin
  6020.         w := CreateCajVariant(Pointer(IntProcDefParam(proc^.Decl, 0)));
  6021.         Vm_Add(Params, CreateCajVariant(TM_Add(Types, '', CSV_Var, nil)), 'RESULT')^.CV_Var := w;
  6022.       end {if}
  6023.       else w := nil;
  6024.       I := Parser.CurrTokenPos;
  6025.       Parser.CurrTokenPos := Proc^.Offset;
  6026.       if Parser.CurrTokenId = CSTII_Var then begin
  6027.         if not ProcessVars(Params) then begin
  6028.           VM_Destroy(Params);
  6029.           DestroyCajVariant(w);
  6030.           exit;
  6031.         end; {if}
  6032.       end; {if}
  6033.       WithList := TIFList.Create;
  6034.       {$IFNDEF NOCLASSES}
  6035.       if assigned(Proc^.ClassType) then
  6036.       begin
  6037.         WithList.Add(CreateVarType(VM_Get(Params, 0)));
  6038.       end;
  6039.       {$ENDIF}
  6040.       if not RunBegin(WithList, Params, False) then begin
  6041.         if FError.ErrorCode = EExitCommand then
  6042.           FError.ErrorCode := 0
  6043.         else begin
  6044.           VM_Destroy(Params);
  6045.           DestroyWithList(WithList);
  6046.           DestroyCajVariant(w);
  6047.           exit;
  6048.         end;
  6049.       end; {if}
  6050.       DestroyWithList(WithList);
  6051.       Parser.CurrTokenPos := I;
  6052.       DoProc := w;
  6053.       VM_Destroy(Params);
  6054.     end else
  6055.     begin
  6056.       DoProc := TIFPasScript(Proc^.FScriptEngine).RunScriptProc(Proc, Params);
  6057.       if TIFPasScript(Proc^.FScriptEngine).ErrorCode <> 0 then
  6058.       begin
  6059.         RunError2(Proc^.FScriptEngine, TIFPasScript(Proc^.FScriptEngine).ErrorCode, TIFPasScript(Proc^.FScriptEngine).ErrorString);
  6060.         DoProc := nil;
  6061.       end;
  6062.       VM_Destroy(Params);
  6063.     end;
  6064.   end {if}
  6065.   else if Proc^.Mode = 1 then begin
  6066.     if IntProcDefParam(proc^.Decl, 0) <> 0 then
  6067.       w := CreateCajVariant(Pointer(IntProcDefParam(proc^.Decl, 0)))
  6068.     else
  6069.       w := nil;
  6070.     RunError(Self, Proc^.Proc1(Proc^.FScriptEngine, fId, proc, Params, w));
  6071.     if FError.ErrorCode = EExitCommand then
  6072.       FError.ErrorCode := 0
  6073.     else
  6074.       if FError.ErrorCode <> ENoError then begin
  6075.         VM_Destroy(Params);
  6076.         DestroyCajVariant(w);
  6077.         exit;
  6078.       end; {if}
  6079.     VM_Destroy(Params);
  6080.     DoProc := w;
  6081.   end {if}else begin
  6082.     if IntProcDefParam(proc^.Decl, 0) <> 0 then
  6083.       w := CreateCajVariant(Pointer(IntProcDefParam(proc^.Decl, 0)))
  6084.     else
  6085.       w := nil;
  6086.     RunError(Self, Proc^.Proc2(Proc^.FScriptEngine, fId, proc, Params, w));
  6087.     if FError.ErrorCode = EExitCommand then
  6088.       FError.ErrorCode := 0
  6089.     else
  6090.       if FError.ErrorCode <> ENoError then begin
  6091.         VM_Destroy(Params);
  6092.         DestroyCajVariant(w);
  6093.         exit;
  6094.       end; {if}
  6095.     VM_Destroy(Params);
  6096.     DoProc := w;
  6097.   end; {if}
  6098.   CurrProc := OldProc;
  6099. end; {DoProc}
  6100.  
  6101. //-------------------------------------------------------------------
  6102. // Procedure: RunBegin
  6103. //   Purpose: Steps through the script, parsing the tokens
  6104. //-------------------------------------------------------------------
  6105. type
  6106.   TBeginMode = (mbTry, mbRepeat, mbBegin, mbOneLiner);
  6107. function TIfPasScript.RunBegin(WithList: TIFList; Vars: PVariableManager; Skip: Boolean): Boolean;
  6108.       { Run the Script, this is the main part of the script engine }
  6109. var
  6110.   C, c2, C3: PIfVariant;
  6111.   IPos, IStart, ii, IEnd: Longint;
  6112.   b: Boolean;
  6113. {$IFNDEF NOCLASSES}
  6114.   NewWithList: TIFList;
  6115. {$ENDIF}
  6116.   BeginMode: TBeginMode;
  6117.   lBreak: Boolean;
  6118. begin
  6119.   if Parser.CurrTokenId = CSTII_repeat then BeginMode := mbrepeat else
  6120.   if Parser.CurrTokenId = CSTII_try then BeginMode := mbTry else
  6121.     BeginMode := mbOneLiner;
  6122.   Inc(FBeginNesting);
  6123.   if FBeginNesting > FMaxBeginNesting then
  6124.   begin
  6125.     Dec(FBeginNesting);
  6126.     RunError(Self, EOutOfMemoryError);
  6127.     RunBegin := False;
  6128.     Exit;
  6129.   end;
  6130.  
  6131.   if Skip then begin
  6132.     if (Parser.CurrTokenId = CSTII_Begin) or (Parser.CurrTokenId = CSTII_Case) or (Parser.CurrTokenId = CSTII_repeat) or (Parser.CurrTokenId = CSTII_Try) or (Parser.CurrtokenId = CSTII_Except) or (Parser.CurrTokenId = CSTII_Finally) then begin
  6133.       IPos := 1;
  6134.       Parser.Next;
  6135.       while Parser.CurrTokenId <> CSTI_EOF do begin
  6136.         case Parser.CurrTokenId of
  6137.           CSTII_Case, CSTII_Begin, CSTII_try, CSTII_repeat: Inc(IPos);
  6138.           CSTII_until, CSTII_End: begin
  6139.               Dec(IPos);
  6140.               if IPos = 0 then begin
  6141.                 RunBegin := True;
  6142.                 Parser.Next;
  6143.                 Dec(FBeginNesting);
  6144.                 exit;
  6145.               end;
  6146.             end;
  6147.         end;
  6148.         Parser.Next;
  6149.       end;
  6150.       RunError(Self, EUnexpectedEndOfFile);
  6151.       RunBegin := False;
  6152.       Dec(FBeginNesting);
  6153.       exit;              
  6154.     end else begin
  6155.       IPos := 1;
  6156.       while Parser.CurrTokenId <> CSTI_EOF do begin
  6157.         case Parser.CurrTokenId of
  6158.           CSTII_If: Inc(IPos);
  6159.           CSTI_Semicolon: begin
  6160.               RunBegin := True;
  6161.               Dec(FBeginNesting);
  6162.               exit;
  6163.             end;
  6164.           CSTII_Else: begin
  6165.               Dec(IPos);
  6166.               if IPos = 0 then begin
  6167.                 RunBegin := True;
  6168.                 Dec(FBeginNesting);
  6169.                 exit;
  6170.               end;
  6171.             end;
  6172.           CSTII_Begin, CSTII_Case, CSTII_repeat: begin
  6173.               RunBegin(WithList, Vars, True);
  6174.               continue;
  6175.             end;
  6176.           CSTII_End, CSTII_until: begin
  6177.               RunBegin := True;
  6178.               Dec(FBeginNesting);
  6179.               exit;
  6180.             end;
  6181.         end;
  6182.         Parser.Next;
  6183.       end;
  6184.       RunError(Self, EUnexpectedEndOfFile);
  6185.       RunBegin := False;
  6186.       Dec(FBeginNesting);
  6187.       exit;
  6188.     end;
  6189.   end;
  6190.   RunBegin := False;
  6191.   if (Parser.CurrTokenId = CSTII_Begin) or (Parser.CurrtokenId = CSTII_Except) or (Parser.CurrtokenID = CSTII_Finally)  then begin
  6192.     BeginMode := mbBegin;
  6193.     Parser.Next; {skip begin}
  6194.   end else
  6195.   if (Parser.CurrTokenId = CSTII_Repeat) or (Parser.CurrtokenID = CSTII_Try) then
  6196.     Parser.Next;
  6197.  
  6198.   while True do begin
  6199.  
  6200.     case Parser.CurrTokenId of
  6201.       CSTI_EOF: begin
  6202.           RunError(Self, EUnexpectedEndOfFile);
  6203.           Dec(FBeginNesting);
  6204.           exit;
  6205.         end;
  6206.       CSTII_Else: begin
  6207.           if BeginMode = mbOneLiner then begin
  6208.             RunBegin := True;
  6209.             Dec(FBeginNesting);
  6210.             exit;
  6211.           end
  6212.           else begin
  6213.             RunError(Self, EErrorInStatement);
  6214.             RunBegin := False;
  6215.             Dec(FBeginNesting);
  6216.             exit;
  6217.           end;
  6218.         end;
  6219.       CSTII_Try: begin
  6220.         if RunBegin(WithList, Vars, False) then
  6221.         begin
  6222.           if Parser.CurrTokenId = CSTII_Finally then begin
  6223.             RunBegin(WithList, vars, False);
  6224.           end else if Parser.CurrTokenId = CSTII_Except then begin
  6225.             RunBegin(WithList, Vars, True);
  6226.           end;
  6227.         end else begin
  6228.           if FError.ErrorCode < ERuntimeError then exit;
  6229.           FLastException := FError;
  6230.           RunError(Self, ENoError);
  6231.           while (Parser.CurrTokenId <> CSTII_Except) and (Parser.CurrTokenId <> CSTII_Finally) do
  6232.           begin
  6233.             if Parser.CurrTokenID = CSTI_Eof then
  6234.             begin
  6235.               RunError(Self, EUnexpectedEndOfFile);
  6236.               exit;
  6237.             end;
  6238.             Parser.Next;
  6239.           end;
  6240.           if Parser.CurrTokenId = CSTII_Finally then begin
  6241.             if not RunBegin(WithList, vars, False) then
  6242.               exit;
  6243.             FError := FLastException;
  6244.             Exit;
  6245.           end else if Parser.CurrTokenId = CSTII_Except then begin
  6246.             if not RunBegin(WithList, Vars, FLastException.ErrorCode = EExitCommand) then
  6247.               exit;
  6248.             FLastException := FError;
  6249.           end;
  6250.         end;
  6251.       end;
  6252.       CSTII_Finally,
  6253.       CSTII_Except: begin
  6254.           if BeginMode = mbTry then begin
  6255.             RunBegin := True;
  6256.             Dec(FBeginNesting);
  6257.             exit;
  6258.           end else begin
  6259.             case BeginMode of
  6260.               mbRepeat: RunError(Self, EUntilExpected);
  6261.               mbOneLiner, mbBegin: RunError(Self, EEndExpected);
  6262.             end;
  6263.             RunBegin := False;
  6264.             Dec(FBeginNesting);
  6265.             exit;
  6266.           end;
  6267.         end;
  6268.  
  6269.       CSTII_End: begin
  6270.           if (BeginMode = mbBegin) or (BeginMode = mbOneLiner) then begin
  6271.             RunBegin := True;
  6272.             if beginMode <> mbOneLiner then 
  6273.             Parser.Next;
  6274.             Dec(FBeginNesting);
  6275.             exit;
  6276.           end else begin
  6277.             case BeginMode of
  6278.               mbTry: RunError(Self, EExceptExpected);
  6279.               mbRepeat: RunError(Self, EUntilExpected); 
  6280.             end;
  6281.             RunBegin := False;
  6282.             Dec(FBeginNesting);
  6283.             exit;
  6284.           end;
  6285.         end; {CSTII_End}
  6286.       CSTII_until: begin
  6287.           if BeginMode = mbBegin then begin
  6288.             RunBegin := True;
  6289.             Dec(FBeginNesting);
  6290.             exit;
  6291.           end else begin
  6292.             case BeginMode of
  6293.               mbTry: RunError(Self, EExceptExpected);
  6294.               mbOneLiner, mbBegin: RunError(Self, EEndExpected);
  6295.             end;
  6296.             RunError(Self, EEndExpected);
  6297.             RunBegin := False;
  6298.             Dec(FBeginNesting);
  6299.             exit;
  6300.           end;
  6301.         end; {CSTII_Until}
  6302. //-------------------------------------------------------
  6303. // Exit command - aborts the script
  6304. //-------------------------------------------------------
  6305.       CSTII_Exit: begin
  6306.           RunBegin := False;
  6307.           RunError(Self, EExitCommand);
  6308.           Dec(FBeginNesting);
  6309.           exit;
  6310.         end; { CSTII_Exit}
  6311. //-------------------------------------------------------
  6312. // Break command - breaks out of loop
  6313. //-------------------------------------------------------
  6314.       CSTII_Break: begin
  6315.           RunBegin := True;
  6316.           Dec(FBeginNesting);
  6317.           exit;
  6318.         end; { CSTII_Break }
  6319. //-------------------------------------------------------
  6320. // Continue command - breaks out of loop
  6321. //-------------------------------------------------------
  6322.       CSTII_Continue: begin
  6323.           RunBegin := True;
  6324.           Dec(FBeginNesting);
  6325.           exit;
  6326.         end; { CSTII_Break }
  6327.  
  6328. //-------------------------------------------------------
  6329. // Semicolon is handled specially
  6330. //-------------------------------------------------------
  6331.       CSTI_Semicolon: begin
  6332.           if BeginMode = mbOneLiner then begin
  6333.             RunBegin := True;
  6334.             Dec(FBeginNesting);
  6335.             exit;
  6336.           end;
  6337.           Parser.Next;
  6338.         end; {CSTI_SemiColon}
  6339. //-------------------------------------------------------
  6340. // Process an IF statement
  6341. //-------------------------------------------------------
  6342.       CSTII_If: begin
  6343.  
  6344.           if assigned(OnRunLine) then begin
  6345.             RunError(Self, OnRunLine(fId, Self, Parser.CurrTokenPos));
  6346.             if ErrorCode <> ENoError then
  6347.             begin
  6348.               Dec(FBeginNesting);
  6349.               exit;
  6350.             end;
  6351.           end;
  6352.           Parser.Next;
  6353.           C := CreateCajVariant(TM_Add(Types, '', CSV_Bool, nil));
  6354.           if not calc(WithList, Vars, C, CSTII_Then, False) then begin
  6355.             DestroyCajVariant(C);
  6356.             Dec(FBeginNesting);
  6357.             exit;
  6358.           end; {if}
  6359.           if Parser.CurrTokenId <> CSTII_Then
  6360.             then begin
  6361.             RunError(Self, EThenExpected);
  6362.             DestroyCajVariant(C);
  6363.             Dec(FBeginNesting);
  6364.             exit;
  6365.           end;
  6366.           Parser.Next; {skip THEN}
  6367.           if C^.Cv_Bool then begin
  6368.             DestroyCajVariant(C);
  6369.             if not RunBegin(WithList, Vars, False) then begin
  6370.               Dec(FBeginNesting);
  6371.               exit;
  6372.             end; {if}
  6373.             if Parser.CurrTokenId = CSTII_Else then begin
  6374.               if assigned(OnRunLine) then begin
  6375.                 RunError(Self, OnRunLine(fId, Self, Parser.CurrTokenPos));
  6376.                 if ErrorCode <> ENoError then
  6377.                 begin
  6378.                   Dec(FBeginNesting);
  6379.                   exit;
  6380.                 end;
  6381.               end;
  6382.               Parser.Next;
  6383.               if not RunBegin(WithList, Vars, True) then begin
  6384.                 Dec(FBeginNesting);
  6385.                 exit;
  6386.               end; {if}
  6387.             end; {if}
  6388.           end {if}
  6389.           else begin
  6390.             DestroyCajVariant(C);
  6391.             if not RunBegin(WithList, Vars, True) then begin
  6392.               Dec(FBeginNesting);
  6393.               exit;
  6394.             end; {if}
  6395.             if Parser.CurrTokenId = CSTII_Else then begin
  6396.               Parser.Next;
  6397.               if assigned(OnRunLine) then begin
  6398.                 RunError(Self, OnRunLine(fId, Self, Parser.CurrTokenPos));
  6399.                 if ErrorCode <> ENoError then
  6400.                 begin
  6401.                   Dec(FBeginNesting);
  6402.                   exit;
  6403.                 end;
  6404.               end;
  6405.               if not RunBegin(WithList, Vars, False) then begin
  6406.                 Dec(FBeginNesting);
  6407.                 exit;
  6408.               end; {if}
  6409.             end; {if}
  6410.           end; {if}
  6411.         end; {CSTII_If}
  6412.  
  6413. //--------------------------------------------------------------------
  6414. // Process the WHILE DO loop ***************************************--
  6415. //--------------------------------------------------------------------
  6416.       CSTII_While: begin
  6417.           lBreak := False;
  6418.  
  6419.           Parser.Next; // Find Next token
  6420.  
  6421.           C := CreateCajVariant(TM_Add(Types, '', CSV_Bool, nil)); // Create a boolean variable
  6422.           IPos := Parser.CurrTokenPos; // Save position of variable
  6423.  
  6424.           // Test the expression up to the DO command
  6425.           //-------------------------------------------
  6426.           if not calc(WithList, Vars, C, CSTII_do, False) then begin
  6427.             DestroyCajVariant(C);
  6428.             Dec(FBeginNesting);
  6429.             exit;
  6430.           end; {if}
  6431.  
  6432.           // If not a DO command, this is an error
  6433.           //-----------------------------------------
  6434.           if Parser.CurrTokenId <> CSTII_do then begin
  6435.             RunError(Self, EDoExpected);
  6436.             DestroyCajVariant(C);
  6437.             Dec(FBeginNesting);
  6438.             exit;
  6439.           end;
  6440.  
  6441.           Parser.Next;
  6442.  
  6443.           // Save the DO block starting position
  6444.           //--------------------------------------
  6445.           IStart := Parser.CurrTokenPos;
  6446.  
  6447.           //-------------------------------
  6448.           // Start the loop processing
  6449.           //-------------------------------
  6450.           while C^.Cv_Bool and (not lBreak) do begin
  6451.              // See if any command to run
  6452.              // ---------------------------
  6453.             if assigned(OnRunLine) then begin
  6454.               RunError(Self, OnRunLine(fId, Self, Parser.CurrTokenPos));
  6455.               if ErrorCode <> ENoError then begin
  6456.                 Dec(FBeginNesting);
  6457.                 exit;
  6458.               end;
  6459.             end;
  6460.  
  6461.              // Call routine to process the code
  6462.              //----------------------------------
  6463.             if not RunBegin(WithList, Vars, False) then begin
  6464.               DestroyCajVariant(C);
  6465.               Dec(FBeginNesting);
  6466.               exit;
  6467.             end;
  6468.  
  6469.             // If a break were returned
  6470.             //--------------------------
  6471.             if Parser.CurrTokenId = CSTII_Break then begin
  6472.               lBreak := True;
  6473.             end;
  6474.  
  6475.             // Go back to the variable test position
  6476.             //----------------------------------------
  6477.             Parser.CurrTokenPos := IPos;
  6478.  
  6479.             // Test the condition again, if false, exit
  6480.             //-----------------------------------------
  6481.             if not calc(WithList, Vars, C, CSTII_do, False) then begin
  6482.               DestroyCajVariant(C);
  6483.               Dec(FBeginNesting);
  6484.               exit;
  6485.             end;
  6486.  
  6487.             // Reset to the DO starting block
  6488.             //---------------------------------
  6489.             Parser.CurrTokenPos := IStart;
  6490.           end;
  6491.  
  6492.           DestroyCajVariant(C);
  6493.           if not RunBegin(WithList, Vars, True) then begin
  6494.             Dec(FBeginNesting);
  6495.             exit;
  6496.           end;
  6497.         end;
  6498. //--------------------------------------------------------------------
  6499. // Process the REPEAT UNTIL loop ***********************************--
  6500. //--------------------------------------------------------------------
  6501.       CSTII_repeat: begin
  6502.           lBreak := False;
  6503.  
  6504.           C := CreateCajVariant(TM_Add(Types, '', CSV_Bool, nil)); // Create a boolean variable
  6505.  
  6506.           IStart := Parser.CurrTokenPos;
  6507.  
  6508.           //-------------------------------
  6509.           // Start the loop processing
  6510.           //-------------------------------
  6511.           repeat
  6512.             Parser.CurrTokenPos := IStart;
  6513.              // See if any command to run
  6514.              // ---------------------------
  6515.             if assigned(OnRunLine) then begin
  6516.               RunError(Self, OnRunLine(fId, Self, Parser.CurrTokenPos));
  6517.               if ErrorCode <> ENoError then begin
  6518.                 Dec(FBeginNesting);
  6519.                 exit;
  6520.               end;
  6521.             end;
  6522.  
  6523.              // Call routine to process the code
  6524.              //----------------------------------
  6525.             if not RunBegin(withlist, Vars, False) then begin
  6526.               DestroyCajVariant(C);
  6527.               Dec(FBeginNesting);
  6528.               exit;
  6529.             end;
  6530.  
  6531.             // If a break were returned
  6532.             //--------------------------
  6533.             if Parser.CurrTokenId = CSTII_Break then begin
  6534.               lBreak := True;
  6535.               break;
  6536.             end;
  6537.  
  6538.             if Parser.CurrTokenId <> CSTII_until then begin
  6539.               RunError(Self, EUntilExpected);
  6540.               DestroyCajVariant(C);
  6541.               Dec(FBeginNesting);
  6542.               exit;
  6543.             end;
  6544.  
  6545.             Parser.Next;
  6546.  
  6547.             // Test the condition again, if false, exit
  6548.             //-----------------------------------------
  6549.             if not calc(withlist, Vars, C, CSTI_Semicolon, False) then begin
  6550.               DestroyCajVariant(C);
  6551.               Dec(FBeginNesting);
  6552.               exit;
  6553.             end;
  6554.           until C^.Cv_Bool;
  6555.  
  6556.           DestroyCajVariant(C);
  6557.  
  6558.           if lBreak then begin
  6559.             Parser.CurrTokenPos := IStart;
  6560.             if not RunBegin(WithList, Vars, True) then begin Dec(FBeginNesting);exit;end;
  6561.           end;
  6562.         end;
  6563.  
  6564. //-------------------------------------------------------
  6565. // FOR LOOP is handled here
  6566. //-------------------------------------------------------
  6567.       CSTII_For: begin
  6568.           // Found the FOR keyword
  6569.           // ----------------------
  6570.           Parser.Next; // Find the next token
  6571.  
  6572.           // It should be an identifier
  6573.           //------------------------------
  6574.           if Parser.CurrTokenId <> CSTI_Identifier then begin
  6575.             RunError(Self, EIdentifierExpected);
  6576.             Dec(FBeginNesting);
  6577.             exit;
  6578.           end; {if}
  6579.  
  6580.           // The variable must exist
  6581.           //------------------------------
  6582.           if assigned(Vars) and
  6583.             (VM_Find(Vars, Parser.GetToken) <> -1)
  6584.             then C := GetVarLink(Vm_Get(Vars, VM_Find(Vars,
  6585.               Parser.GetToken)))
  6586.           else
  6587.             if VM_Find(Variables, Parser.GetToken) <> -1
  6588.               then C := GetVarLink(Vm_Get(Variables, VM_Find(Variables,
  6589.                 Parser.GetToken)))
  6590.             else begin
  6591.               RunError2(Self, EUnknownIdentifier, Parser.GetToken);
  6592.               Dec(FBeginNesting);
  6593.               exit;
  6594.             end; {if}
  6595.  
  6596.           // It cannot be a constant
  6597.           //------------------------------
  6598.           if (C^.Flags and $1) <> 0 then begin
  6599.             RunError(Self, EVariableExpected);
  6600.             Dec(FBeginNesting);
  6601.             exit;
  6602.           end; {if}
  6603.  
  6604.           // And it must be an integer
  6605.           //------------------------------
  6606.           if not IsIntegerType(C) then begin
  6607.             RunError(Self, EIntegerExpected);
  6608.           end; {if}
  6609.  
  6610.           Parser.Next; // Find the next token
  6611.  
  6612.           // Expecting an assignment statement
  6613.           //----------------------------------------
  6614.           if Parser.CurrTokenId <> CSTI_Assignment then begin
  6615.             RunError(Self, EAssignmentExpected);
  6616.             Dec(FBeginNesting);
  6617.             exit;
  6618.           end; {if}
  6619.  
  6620.           Parser.Next; // Find the next token
  6621.  
  6622.           // Calculate expression of token from current position
  6623.           // to the TO keyword
  6624.           //--------------------------------------------------
  6625.           if not calc(WithList, Vars, C, CSTII_To, False)
  6626.             then begin Dec(FBeginNesting);exit;end;
  6627.  
  6628.           // Get the result of the calculation
  6629.           //---------------------------------------
  6630.           IStart := GetInteger(C);
  6631.  
  6632.           if (Parser.CurrTokenId <> CSTII_To) and
  6633.             (Parser.CurrTokenId <> CSTII_DownTo) then begin
  6634.             RunError(Self, EToExpected);
  6635.             Dec(FBeginNesting);
  6636.             exit;
  6637.           end; {if}
  6638.  
  6639.           // See if we are going up or down
  6640.           //-----------------------------------
  6641.           b := (Parser.CurrTokenId = CSTII_DownTo);
  6642.  
  6643.           Parser.Next; // Find the next token
  6644.  
  6645.           if not calc(WithList, Vars, C, CSTII_do, False)
  6646.             then begin Dec(FBeginNesting);exit;end;
  6647.  
  6648.           // Get the result of the calculation
  6649.           //---------------------------------------
  6650.           IEnd := GetInteger(C);
  6651.  
  6652.           if Parser.CurrTokenId <> CSTII_do then begin
  6653.             RunError(Self, EDoExpected);
  6654.             Dec(FBeginNesting);
  6655.             exit;
  6656.           end; {if}
  6657.  
  6658.           Parser.Next; // Find the next token
  6659.  
  6660.           lBreak := False; // Assume the loop will complete
  6661.           IPos := Parser.CurrTokenPos;
  6662.  
  6663.           if b then begin
  6664.             C^.Flags := C^.Flags or $1;
  6665.  
  6666.             // Start the loop
  6667.             //------------------------------
  6668.             for ii := IStart downto IEnd do begin
  6669.               if assigned(OnRunLine) then begin
  6670.                 RunError(Self, OnRunLine(fId, Self, Parser.CurrTokenPos));
  6671.                 if ErrorCode <> ENoError then begin Dec(FBeginNesting);exit; end;
  6672.               end;
  6673.  
  6674.               // Make the loop variable visible to program
  6675.               //--------------------------------------------
  6676.               SetInteger(C, ii);
  6677.               if not RunBegin(WithList, Vars, False) then begin
  6678.                 C^.Flags := C^.Flags and not $1;
  6679.                 Dec(FBeginNesting);
  6680.                 exit;
  6681.               end;
  6682.  
  6683.               // If a break were returned
  6684.               //--------------------------
  6685.               if Parser.CurrTokenId = CSTII_Break
  6686.                 then lBreak := True;
  6687.  
  6688.               Parser.CurrTokenPos := IPos;
  6689.  
  6690.               if lBreak then break;
  6691.  
  6692.             end;
  6693.             C^.Flags := C^.Flags and not $1;
  6694.             if not RunBegin(WithList, Vars, True) then
  6695.             begin
  6696.               Dec(FBeginNesting);
  6697.               exit;
  6698.             end;
  6699.           end {if}
  6700.           else begin
  6701.             C^.Flags := C^.Flags or $1;
  6702.             for ii := IStart to IEnd do begin
  6703.               if assigned(OnRunLine) then begin
  6704.                 RunError(Self, OnRunLine(fId, Self, Parser.CurrTokenPos));
  6705.                 if ErrorCode <> ENoError then begin
  6706.                   Dec(FBeginNesting);
  6707.                   exit;
  6708.                 end;
  6709.               end;
  6710.  
  6711.               SetInteger(C, ii);
  6712.               if not RunBegin(WithList, Vars, False) then begin
  6713.                 C^.Flags := C^.Flags and not $1;
  6714.                 Dec(FBeginNesting);
  6715.                 exit;
  6716.               end;
  6717.  
  6718.               // If a break were returned
  6719.               //--------------------------
  6720.               if Parser.CurrTokenId = CSTII_Break
  6721.                 then lBreak := True;
  6722.  
  6723.               Parser.CurrTokenPos := IPos;
  6724.  
  6725.               // If a break were returned
  6726.                             //--------------------------
  6727.               if lBreak then break
  6728.  
  6729.             end;
  6730.             C^.Flags := C^.Flags and not $1;
  6731.             if not RunBegin(WithList, Vars, True) then
  6732.             begin
  6733.               Dec(FBeginNesting);
  6734.               exit;
  6735.             end;
  6736.           end {if}
  6737.         end;
  6738. //-------------------------------------------------------
  6739. // Begin a block
  6740. //-------------------------------------------------------
  6741.       CSTII_Begin: begin
  6742.           if not RunBegin(WithList, Vars, False) then
  6743.           begin
  6744.             Dec(FBeginNesting);
  6745.             exit;
  6746.           end;
  6747.         end; {CSTII_Begin}
  6748. //-------------------------------------------------------
  6749. // CASE <x> OF
  6750. //-------------------------------------------------------
  6751.       CSTII_Case: begin
  6752.           Parser.Next;
  6753.           C := CreateCajVariant(TM_Add(Types, '', CSV_Var, nil));
  6754.           C^.CV_Var := nil; {Say that calc can assign any type}
  6755.           if not calc(WithList, Vars, C, CSTII_Of, False) then begin
  6756.             DestroyCajVariant(C);
  6757.             Dec(FBeginNesting);
  6758.             exit;
  6759.           end; {If}
  6760.           if Parser.CurrTokenId <> CSTII_Of then begin
  6761.             RunError(Self, EOfExpected);
  6762.             Dec(FBeginNesting);
  6763.             exit;
  6764.           end; {If}
  6765.           Parser.Next;
  6766.           b := False;
  6767.           while Parser.CurrTokenId <> CSTII_End do begin
  6768.             if Parser.CurrTokenId = CSTII_Else then begin
  6769.               Parser.Next;
  6770.               if not RunBegin(WithList, Vars, b) then
  6771.               begin
  6772.                 Dec(FBeginNesting);
  6773.                 exit;
  6774.               end;
  6775.               if Parser.CurrTokenId = CSTI_Semicolon then begin
  6776.                 Parser.Next;
  6777.               end;
  6778.               if Parser.CurrTokenId <> CSTII_End then begin
  6779.                 RunError(Self, EEndExpected);
  6780.                 Dec(FBeginNesting);
  6781.                 exit;
  6782.               end;
  6783.               break;
  6784.             end;
  6785.             if assigned(OnRunLine) then begin
  6786.               RunError(Self, OnRunLine(fId, Self, Parser.CurrTokenPos));
  6787.               if ErrorCode <> ENoError then
  6788.               begin
  6789.                 Dec(FBeginNesting);
  6790.                 exit;
  6791.               end;
  6792.             end;
  6793.             c2 := CreateCajVariant(C^.VType);
  6794.             if not calc(WithList, Vars, c2, CSTI_Colon, False) then begin
  6795.               DestroyCajVariant(C);
  6796.               DestroyCajVariant(c2);
  6797.               Dec(FBeginNesting);
  6798.               exit;
  6799.             end; {If}
  6800.             if not Perform(c2, C, PtEqual) then begin
  6801.               DestroyCajVariant(C);
  6802.               DestroyCajVariant(c2);
  6803.               Dec(FBeginNesting);
  6804.               exit;
  6805.             end; {If}
  6806.             while Parser.CurrTokenId = CSTI_Comma do
  6807.             begin
  6808.               Parser.Next;
  6809.               C3 := CreateCajVariant(C^.VType);
  6810.               if not calc(WithList, Vars, c3, CSTI_Colon, False) then begin
  6811.                 DestroyCajVariant(C);
  6812.                 DestroyCajVariant(c2);
  6813.                 DestroyCajVariant(C3);
  6814.                 Dec(FBeginNesting);
  6815.                 exit;
  6816.               end; {If}
  6817.               if not Perform(c3, C, PtEqual) then begin
  6818.                 DestroyCajVariant(C);
  6819.                 DestroyCajVariant(c2);
  6820.                 DestroyCajVariant(c3);
  6821.                 Dec(FBeginNesting);
  6822.                 exit;
  6823.               end; {If}
  6824.               if not Perform(C2, C3, ptOr) then
  6825.               begin
  6826.                 DestroyCajVariant(C);
  6827.                 DestroyCajVariant(c2);
  6828.                 Dec(FBeginNesting);
  6829.                 exit;
  6830.               end;
  6831.             end;
  6832.             if Parser.CurrTokenId <> CSTI_Colon then begin
  6833.               RunError(Self, EColonExpected);
  6834.               DestroyCajVariant(C);
  6835.               DestroyCajVariant(c2);
  6836.               Dec(FBeginNesting);
  6837.               exit;
  6838.             end; {If}
  6839.             Parser.Next;
  6840.             if not RunBegin(WithList, Vars, (not c2^.Cv_Bool or b)) then begin
  6841.               DestroyCajVariant(C);
  6842.               DestroyCajVariant(c2);
  6843.               Dec(FBeginNesting);
  6844.               exit;
  6845.             end;
  6846.             if c2^.Cv_Bool then
  6847.               b := True;
  6848.             if Parser.CurrTokenId = CSTI_Semicolon then begin
  6849.               Parser.Next;
  6850.             end;
  6851.             DestroyCajVariant(c2);
  6852.           end; {While}
  6853.           DestroyCajVariant(C);
  6854.           Parser.Next; {Skip end}
  6855.         end; {CSTII_Case}
  6856.       {$IFNDEF NOClASSES}
  6857.       CSTII_With: begin
  6858.         Parser.Next;
  6859.         NewWithList := TIFList.Create;
  6860.         case GetIdentifier(WithList, Vars, 0, C) of
  6861.           0:
  6862.             begin
  6863.               DestroyWithList(NewWithList);
  6864.               Dec(FBeginNesting);
  6865.               Exit;
  6866.             end; // case 0
  6867.           1: c := CreateVarType(C);
  6868.           2:;
  6869.         end; //case
  6870.         if GetVarLink(c)^.VType^.ATypeId <> CSV_Class then
  6871.         begin
  6872.           DestroyCajVariant(c);
  6873.           DestroyWithList(NewWithList);
  6874.           RunError(Self, EClassTypeExpected);
  6875.           Dec(FBeginNesting);
  6876.           exit;
  6877.         end;
  6878.         if (GetVarLink(c)^.CV_Class = nil) then
  6879.         begin
  6880.           DestroyCajVariant(c);
  6881.           DestroyWithList(NewWithList);
  6882.           RunError(Self, EClassNotCreated);
  6883.           Dec(FBeginNesting);
  6884.           exit;
  6885.         end;
  6886.         if (GetVarLink(c)^.CV_Class^.AlreadyFreed) then
  6887.         begin
  6888.           DestroyCajVariant(c);
  6889.           DestroyWithList(NewWithList);
  6890.           RunError(Self, EClassAlreadyFreed);
  6891.           Dec(FBeginNesting);
  6892.           exit;
  6893.         end;
  6894.         NewWithList.Add(c);
  6895.         while Parser.CurrTokenId <> CSTII_Do do begin
  6896.           if Parser.CurrTokenId <> CSTI_Comma then
  6897.           begin
  6898.             DestroyWithList(NewWithList);
  6899.             RunError(Self, ECommaExpected);
  6900.             Dec(FBeginNesting);
  6901.             exit;
  6902.           end;
  6903.           Parser.Next;
  6904.           case GetIdentifier(WithList, Vars, 0, C) of
  6905.             0:
  6906.               begin
  6907.                 DestroyWithList(NewWithList);
  6908.                 Dec(FBeginNesting);
  6909.                 Exit;
  6910.               end;
  6911.             1: c := CreateVarType(C);
  6912.             2:;
  6913.           end; //case
  6914.           if GetVarLink(c)^.VType^.ATypeId <> CSV_Class then
  6915.           begin
  6916.             DestroyCajVariant(c);
  6917.             DestroyWithList(NewWithList);
  6918.             RunError(Self, EClassTypeExpected);
  6919.             Dec(FBeginNesting);
  6920.             exit;
  6921.           end;
  6922.           if (GetVarLink(c)^.CV_Class = nil) then
  6923.           begin
  6924.             DestroyCajVariant(c);
  6925.             DestroyWithList(NewWithList);
  6926.             RunError(Self, EClassNotCreated);
  6927.             Dec(FBeginNesting);
  6928.             exit;
  6929.           end;
  6930.           if (GetVarLink(c)^.CV_Class^.AlreadyFreed) then
  6931.           begin
  6932.             DestroyCajVariant(c);
  6933.             DestroyWithList(NewWithList);
  6934.             RunError(Self, EClassAlreadyFreed);
  6935.             Dec(FBeginNesting);
  6936.             exit;
  6937.           end;
  6938.           nEwWithList.Add(c);
  6939.         end; //while
  6940.         for ii := 0 to WithList.Count -1 do
  6941.         begin
  6942.           NewWithList.Add(CreateVarType(WithList.GetItem(II)));
  6943.         end; 
  6944.         Parser.Next;
  6945.         if not RunBegin(NewWithList, Vars, False) then
  6946.         begin
  6947.           DestroyWithList(NewWithList);
  6948.           Dec(FBeginNesting);
  6949.           exit;
  6950.         end;
  6951.         DestroyWithList(NewWithList);
  6952.      end; {CSTII_With}
  6953.      {$ENDIF}
  6954. //-------------------------------------------------------
  6955. // Found an identifier
  6956. //-------------------------------------------------------
  6957.       CSTII_Inherited,
  6958.         CSTI_OpenRound,
  6959.         CSTI_Identifier: begin
  6960.           if assigned(OnRunLine) then begin
  6961.             RunError(Self, OnRunLine(fId, Self, Parser.CurrTokenPos));
  6962.             if ErrorCode <> ENoError then begin
  6963.               Dec(FBeginNesting);
  6964.               exit;
  6965.             end;
  6966.           end;
  6967.           case GetIdentifier(WithList, Vars, 0, C) of
  6968.             0: begin Dec(FBeginNesting);exit;end;
  6969.             1: begin
  6970.                 if Parser.CurrTokenId <> CSTI_Assignment then begin
  6971.                   RunError(Self, EAssignmentExpected);
  6972.                   Dec(FBeginNesting);
  6973.                   exit;
  6974.                 end;
  6975.                 Parser.Next;
  6976. {$IFNDEF NOCLASSES}
  6977.                 if C^.VType^.atypeid = CSV_Property then begin
  6978.                   c2 := CreateCajVariant(TM_Add(Types, '', CSV_Var, nil));
  6979.                   if not calc(WithList, Vars, c2, CSTI_Semicolon, False) then begin
  6980.                     Dec(FBeginNesting);
  6981.                     exit;
  6982.                   end;
  6983.                   if not SetProperty(C, c2) then begin
  6984.                     DestroyCajVariant(c2);
  6985.                     Dec(FBeginNesting);
  6986.                     exit;
  6987.                   end;
  6988.                   DestroyCajVariant(c2);
  6989.                 end else begin
  6990.                   if not calc(WithList, Vars, C, CSTI_Semicolon, False) then begin
  6991.                     Dec(FBeginNesting);
  6992.                     exit;
  6993.                   end;
  6994.                 end;
  6995. {$ELSE}
  6996.                 if not calc(WithList, Vars, C, CSTI_Semicolon, False) then begin
  6997.                   Dec(FBeginNesting);
  6998.                   exit;
  6999.                 end;
  7000. {$ENDIF}
  7001.               end;
  7002.             2: begin
  7003.                 {$IFNDEF NOCLASSES}
  7004.                 if assigned(c) and (C^.VType^.atypeid = CSV_ExternalObjectProperty) then begin
  7005.                   if Parser.CurrTokenId <> CSTI_Assignment then
  7006.                   begin
  7007.                     DestroyCajVariant(c);
  7008.                     RunError(Self, EAssignmentExpected);
  7009.                     Dec(FBeginNesting);
  7010.                     exit;
  7011.                   end;
  7012.                   Parser.Next;
  7013.                   if (not assigned(c^.CV_ExtObj)) or (PCreatedCustomObject(c^.CV_ExtObj)^.AlreadyFreed) then
  7014.                   begin
  7015.                     DestroyCajVariant(c);
  7016.                     Dec(FBeginNesting);
  7017.                     RunError(Self, EClassNotCreated);
  7018.                     exit;
  7019.                   end;
  7020.                   c2 := CreateCajVariant(PCreatedCustomObject(C^.CV_ExtObj)^.P.GetPropertyType(c^.CV_PropertyNo));
  7021.                   if not calc(WithList, Vars, c2, CSTI_Semicolon, False) then begin
  7022.                     DestroyCajVariant(C);
  7023.                     Dec(FBeginNesting);
  7024.                     exit;
  7025.                   end;
  7026.                   if not PCreatedCustomObject(C^.CV_ExtObj)^.P.SetProperty(c^.CV_PropertyNo, c2) then begin
  7027.                     DestroyCajVariant(c);
  7028.                     DestroyCajVariant(c2);
  7029.                     Dec(FBeginNesting);
  7030.                     exit;
  7031.                   end;
  7032.                   DestroyCajVariant(c2);
  7033.                   DestroyCajVariant(c);
  7034.                 end else{$ENDIF}
  7035.                   DestroyCajVariant(C);
  7036.               end;
  7037.           end;
  7038.         end; {CSTI_Identifier}
  7039.     else begin
  7040.         RunError(Self, EErrorInStatement);
  7041.         Dec(FBeginNesting);
  7042.         exit;
  7043.       end; {Else case}
  7044.     end; {Case}
  7045.   end; {While}
  7046.   RunBegin := True;
  7047.   Dec(FBeginNesting);
  7048. end; {RunBegin}
  7049. {$IFNDEF NOCLASSES}
  7050.  
  7051. function TObjProc(Sender: TIfPasScript; ScriptID: Pointer; proc: PProcedure; Params: PVariableManager; res: PIfVariant): TIfPasScriptError;
  7052. var
  7053.   Self: PIfVariant;
  7054.   nn: PVariableManager;
  7055.   p: PProcedure;
  7056.   PT: PTypeRec;
  7057.   s: string;
  7058. begin
  7059.   Self := GetVarLink(Vm_Get(Params, 0));
  7060.   if proc^.Name = '!CLASSNAME' then begin
  7061.     SetString(res, Self^.CV_Class^.ClassType^.Ident);
  7062.   end else if proc^.Name = '!CLASSNAMEIS' then begin
  7063.     s := FastUppercase(GetString(GetVarLink(Vm_Get(Params, 1))));
  7064.     PT := Self^.CV_Class^.ClassType;
  7065.     SetBoolean(res, False);
  7066.     while assigned(PT) do begin
  7067.       if PT^.Ident = s then begin
  7068.         SetBoolean(res, True);
  7069.         break;
  7070.       end;
  7071.       PT := PIFSClassType(PT^.Ext)^.InheritsFrom;
  7072.     end;
  7073.   end else if proc^.Name = '!GETANCESTORS' then begin
  7074.     PT := Self^.CV_Class^.ClassType;
  7075.     s := PT^.Ident;
  7076.     PT := PIFSClassType(PT^.Ext)^.InheritsFrom;
  7077.     while assigned(PT) do begin
  7078.       s := PT.Ident + '.' + s;
  7079.       PT := PIFSClassType(PT^.Ext)^.InheritsFrom;
  7080.     end;
  7081.     SetString(res, s);
  7082.   end else if proc^.Name = '!CREATE' then begin
  7083.   end else if (proc^.Name = '!DESTROY') then begin
  7084.     if assigned(Self^.CV_Class) and not (Self^.CV_Class^.AlreadyFreed) then begin
  7085.       VM_Destroy(Self.CV_Class^.Variables);
  7086.       Self.CV_Class^.AlreadyFreed := True;
  7087.     end else begin
  7088.       if Self^.CV_Class^.AlreadyFreed then
  7089.         TObjProc := EClassAlreadyFreed
  7090.       else
  7091.         TObjProc := EClassNotCreated;
  7092.       exit;
  7093.     end;
  7094.   end else if proc^.Name = '!FREE' then begin
  7095.     GetClassProcedure(Self, Sender.GetType('TObject')^.Ext, 'DESTROY', p, True);
  7096.     nn := VM_Create(nil);
  7097.     Vm_Add(nn, Self, 'SELF');
  7098.     DestroyCajVariant(Sender.RunScriptProc(p, nn));
  7099.     if Sender.ErrorCode <> 0 then begin
  7100.       TObjProc := Sender.ErrorCode;
  7101.       exit;
  7102.     end;
  7103.     VM_Delete(nn, 0);
  7104.     VM_Destroy(nn);
  7105.   end;
  7106.   TObjProc := ENoError;
  7107. end;
  7108. {$ENDIF}
  7109.  
  7110. function Trim(s: string):string;
  7111. begin
  7112.   while (length(s) > 0)  and (s[1] = ' ') do
  7113.     delete(s, 1, 1);
  7114.   while (length(s) > 0)  and (s[length(s)] = ' ') do
  7115.     delete(s, Length(s), 1);
  7116.   Trim := s;
  7117. end;
  7118.  
  7119. function ExProc(Sender: TIfPasScript; ScriptID: Pointer; proc: PProcedure; Params: PVariableManager; res: PIfVariant): TIfPasScriptError;
  7120. var
  7121.   I: Word;
  7122. begin
  7123.   if Proc^.Name = 'GETLASTERRORCODE' then begin
  7124.     SetInteger(res, Sender.FLastException.ErrorCode);
  7125.   end else if Proc^.Name = 'GETLASTERRORPOSITION' then begin
  7126.     SetInteger(Res, Sender.FLastException.ErrorPosition);
  7127.   end else if Proc^.Name = 'GETLASTERRORPARAM' then begin
  7128.     SetString(Res, Sender.FLastException.ErrorParam);
  7129.   end else if Proc^.Name = 'GETLASTERRORMODULE' then begin
  7130.     SetString(Res, Sender.FLastException.ErrorModule);
  7131.   end else if Proc^.Name = 'GETLASTERRORASSTRING' then begin
  7132.     SetString(Res, ErrorToString(Sender.FLastException.ErrorCode, Sender.FLastException.ErrorParam));
  7133.   end else if Proc^.Name = 'RAISEERROR' then
  7134.   begin
  7135.     I := GetInteger(VM_Get(Params, 0));
  7136.     if I < ERuntimeError then
  7137.       I := ECustomError;
  7138.     Sender.RunError2(Sender, I, GetString(Vm_Get(Params, 1)));
  7139.     Result := I;
  7140.     Exit;
  7141.   end;
  7142.   Result := ENoError;
  7143. end;
  7144.  
  7145. function StdProc(Sender: TIfPasScript; ScriptID: Pointer; proc: PProcedure; Params: PVariableManager; res: PIfVariant): TIfPasScriptError;
  7146. var
  7147.   C: PIfVariant;
  7148.   i1, i2: Longint;
  7149.   cStr: string;
  7150.  
  7151.   function mkchr(C: PIfVariant): Integer;
  7152.   begin
  7153.     if C^.VType^.atypeid = CSV_String then begin
  7154.       if Length(C^.Cv_Str) = 1 then begin
  7155.         mkchr := Ord(C^.Cv_Str[1]);
  7156.       end else
  7157.         mkchr := -1;
  7158.     end else begin
  7159.       mkchr := Ord(C^.Cv_Char);
  7160.     end;
  7161.   end;
  7162. begin
  7163.   StdProc := ENoError;
  7164.   if Proc^.Name = 'LOW' then begin
  7165.     SetInteger(Res, 0);
  7166.   end else if Proc^.Name = 'HIGH' then begin
  7167.     C := GetVarLink(Vm_Get(Params, 0));
  7168.     SetInteger(Res, C^.CV_ArrItems.Count-1);
  7169.   end else if Proc^.Name = 'SETLENGTH' then begin
  7170.     C := GetVarLink(Vm_Get(Params, 0));
  7171.     SetLength(C^.CV_Str, GetInteger(VM_Get(Params, 1)));
  7172.   end else if Proc^.Name = 'ASSIGNED' then begin
  7173.     C := GetVarLink(Vm_Get(Params, 0));
  7174.     case C^.VType.atypeid of
  7175.     {$IFNDEF NOCLASSES}
  7176.       CSV_Class: SetBoolean(Res, Assigned(C^.CV_Class) and (not C^.CV_Class^.AlreadyFreed));
  7177.       CSV_ClassRef: SetBoolean(Res, Assigned(C^.Cv_ClassRef));
  7178.       CSV_ExternalObject: SetBoolean(Res, Assigned(c^.CV_ExternalObject));
  7179.     {$ENDIF}
  7180.       CSV_ProcVariable: SetBoolean(Res, Assigned(C^.CV_Proc)); 
  7181.       CSV_Variant: SetBoolean(Res, assigned(C^.CV_Variant));
  7182.     else
  7183.       StdProc := ETypeMismatch;
  7184.     end;
  7185.   end else
  7186.   if proc^.Name = 'GETTYPE' then begin
  7187.     C := GetVarLink(Vm_Get(Params, 0));
  7188.     if C^.VType.Ident <> '' then
  7189.       SetString(res, C^.VType.Ident)
  7190.     else
  7191.       SetString(res, 'VAR');
  7192.   end else if proc^.Name = 'STRGET' then begin
  7193.     C := GetVarLink(Vm_Get(Params, 0));
  7194.     i1 := GetInteger(GetVarLink(Vm_Get(Params, 1)));
  7195.     if (i1 < 1) or (i1 > Length(C^.Cv_Str)) then begin
  7196.       StdProc := EOutOfRange;
  7197.       exit;
  7198.     end;
  7199.     res^.Cv_Char := C^.Cv_Str[i1];
  7200.   end else if proc^.Name = 'STRSET' then begin
  7201.     C := GetVarLink(Vm_Get(Params, 2));
  7202.     i1 := GetInteger(GetVarLink(Vm_Get(Params, 1)));
  7203.     if (i1 < 1) or (i1 > Length(C^.Cv_Str)) then begin
  7204.       StdProc := EOutOfRange;
  7205.       exit;
  7206.     end;
  7207.     I2 := mkchr(GetVarLink(Vm_Get(Params, 0)));
  7208.     if I2 = -1 then begin
  7209.       StdProc := EOutOfRange;
  7210.       exit;
  7211.     end;
  7212.     C^.Cv_Str[i1] := Chr(I2);
  7213.   end else if (proc^.Name = 'ORD') then begin
  7214.     i1 := mkchr(GetVarLink(Vm_Get(Params, 0)));
  7215.     if i1 = -1 then begin
  7216.       StdProc := EOutOfRange;
  7217.       exit;
  7218.     end;
  7219.     res^.Cv_UByte := i1;
  7220.   end else if proc^.Name = 'CHR' then begin
  7221.     res^.Cv_Char := Chr(GetInteger(GetVarLink(Vm_Get(Params, 0))));
  7222.   end else if proc^.Name = 'UPPERCASE' then begin
  7223.     SetString(res, FastUppercase(GetString(GetVarLink(Vm_Get(Params, 0)))));
  7224.   end else if proc^.Name = 'LOWERCASE' then begin
  7225.     SetString(res, FastLowercase(GetString(GetVarLink(Vm_Get(Params, 0)))));
  7226.   end else if proc^.Name = 'TRIM' then begin
  7227.     SetString(res, Trim(GetString(GetVarLink(Vm_Get(Params, 0)))));
  7228.   end else if (proc^.Name = 'POS') then begin
  7229.     SetInteger(res, Pos(GetString(GetVarLink(Vm_Get(Params, 0))),
  7230.       GetString(GetVarLink(Vm_Get(Params, 1)))));
  7231.   end else if proc^.Name = 'INTTOSTR' then begin
  7232.     SetString(res, inttostr(GetInteger(GetVarLink(Vm_Get(Params, 0)))));
  7233.   end else if proc^.Name = 'STRTOINT' then begin
  7234.     SetInteger(res, StrToIntDef(GetString(GetVarLink(Vm_Get(Params, 0))),
  7235.       GetInteger(GetVarLink(Vm_Get(Params, 1)))));
  7236.   end else if proc^.Name = 'COPY' then begin
  7237.     SetString(res, copy(GetString(GetVarLink(Vm_Get(Params, 0))),
  7238.       GetInteger(GetVarLink(Vm_Get(Params, 1))),
  7239.       GetInteger(GetVarLink(Vm_Get(Params, 2)))));
  7240.   end else if proc^.Name = 'LEFT' then begin
  7241.     SetString(res, copy(GetString(GetVarLink(Vm_Get(Params, 0))), 1,
  7242.       GetInteger(GetVarLink(Vm_Get(Params, 1)))));
  7243.   end else if proc^.Name = 'DELETE' then begin
  7244.     C := GetVarLink(Vm_Get(Params, 0));
  7245.     Delete(C^.Cv_Str, GetInteger(GetVarLink(Vm_Get(Params, 1))),
  7246.       GetInteger(GetVarLink(Vm_Get(Params, 2))));
  7247.   end else if proc^.Name = 'INSERT' then begin
  7248.     C := GetVarLink(Vm_Get(Params, 1));
  7249.     insert(GetString(GetVarLink(Vm_Get(Params, 0))), C^.Cv_Str,
  7250.       GetInteger(GetVarLink(Vm_Get(Params, 2))));
  7251.   end else if proc^.Name = 'SETARRAYLENGTH' then begin
  7252.     C := GetVarLink(Vm_Get(Params, 0));
  7253.     i1 := GetInteger(GetVarLink(Vm_Get(Params, 1)));
  7254.     if i1 > Sender.MaxArrayLength then
  7255.     begin
  7256.       StdProc := EOutOfMemoryError;
  7257.       exit;
  7258.     end;
  7259.     if i1 > Longint(C^.CV_ArrItems.Count) then begin
  7260.       for I2 := 1 to i1 - Longint(C^.CV_ArrItems.Count) do begin
  7261.         C^.CV_ArrItems.Add(CreateCajVariant(C^.VType^.Ext));
  7262.       end;
  7263.     end else if i1 < Longint(C^.CV_ArrItems.Count) then begin
  7264.       for I2 := 1 to Longint(C^.CV_ArrItems.Count) - i1 do begin
  7265.         DestroyCajVariant(C^.CV_ArrItems.GetItem(C^.CV_ArrItems.Count - 1));
  7266.         C^.CV_ArrItems.Delete(C^.CV_ArrItems.Count - 1);
  7267.       end;
  7268.     end;
  7269.   end else if proc^.Name = 'GETARRAYLENGTH' then begin
  7270.     SetInteger(res, GetVarLink(Vm_Get(Params, 0))^.CV_ArrItems.Count);
  7271.   end else if proc^.Name = 'LENGTH' then begin
  7272.     SetInteger(res, Length(GetString(GetVarLink(Vm_Get(Params, 0)))));
  7273.   end else if proc^.Name = 'SIN' then begin
  7274.     SetReal(res, Sin(GetReal(GetVarLink(Vm_Get(Params, 0)))));
  7275.   end else if proc^.Name = 'COS' then begin
  7276.     SetReal(res, Cos(GetReal(GetVarLink(Vm_Get(Params, 0)))));
  7277.   end else if proc^.Name = 'TAN' then begin
  7278.     SetReal(res, Sin(GetReal(GetVarLink(Vm_Get(Params, 0)))) / Cos(GetReal(GetVarLink(Vm_Get(Params, 0)))));
  7279.   end else if proc^.Name = 'SQRT' then begin
  7280.     SetReal(res, Sqrt(GetReal(GetVarLink(Vm_Get(Params, 0)))));
  7281.   end else if proc^.Name = 'PI' then begin
  7282.     SetReal(res, pi);
  7283.   end else if proc^.Name = 'ROUND' then begin
  7284.     SetInteger(res, Round(GetReal(GetVarLink(Vm_Get(Params, 0)))));
  7285.   end else if proc^.Name = 'TRUNC' then begin
  7286.     SetInteger(res, Trunc(GetReal(GetVarLink(Vm_Get(Params, 0)))));
  7287.   end else if proc^.Name = 'INT' then begin
  7288.     SetInteger(res, Trunc(GetReal(GetVarLink(Vm_Get(Params, 0))) + 0.5));
  7289.   end else if proc^.Name = 'ABS' then begin
  7290.     SetReal(res, Abs(GetReal(GetVarLink(Vm_Get(Params, 0)))));
  7291.   end else if proc^.Name = 'SQRT' then begin
  7292.     SetReal(res, Sqrt(GetReal(GetVarLink(Vm_Get(Params, 0)))));
  7293.   end else if proc^.Name = 'FLOATTOSTR' then begin
  7294.     SetString(res, FloatToStr(GetReal(GetVarLink(Vm_Get(Params, 0)))));
  7295.   end else if proc^.Name = 'PADZ' then begin
  7296.     SetString(res, Padz(GetString(GetVarLink(Vm_Get(Params, 0))),
  7297.       GetInteger(GetVarLink(Vm_Get(Params, 1)))));
  7298.   end else if proc^.Name = 'PADL' then begin
  7299.     SetString(res, Padl(GetString(GetVarLink(Vm_Get(Params, 0))),
  7300.       GetInteger(GetVarLink(Vm_Get(Params, 1)))));
  7301.   end else if proc^.Name = 'PADR' then begin
  7302.     SetString(res, Padr(GetString(GetVarLink(Vm_Get(Params, 0))),
  7303.       GetInteger(GetVarLink(Vm_Get(Params, 1)))));
  7304.   end else if proc^.Name = 'VERSION' then begin
  7305.     SetString(res, Version);
  7306.   end else if (proc^.Name = 'REPLICATE') or (proc^.Name = 'STRINGOFCHAR') then begin
  7307.     cStr := GetString(GetVarLink(Vm_Get(Params, 0)));
  7308.     SetString(res, StringOfChar(cStr[1],
  7309.       GetInteger(GetVarLink(Vm_Get(Params, 1)))));
  7310.  
  7311.   end;
  7312.  
  7313. end;
  7314.  
  7315. procedure TIfPasScript.Cleanup;
  7316. var
  7317.   p: PResourceData;
  7318. {$IFNDEF NOCLASSES}
  7319.   p1: PCreatedClass;
  7320. {$ENDIF}
  7321.   I: Integer;
  7322. begin
  7323.   FLastException.ErrorCode := 0;
  7324.   for i := 0 to VM_Count(Variables)-1 do
  7325.   begin
  7326.     ChangeType(VM_Get(Variables, I), VM_Get(Variables, I)^.VType); 
  7327.   end;
  7328.   FBeginNesting:=0;
  7329.   for I := 0 to FAttachedOnes.Count -1 do
  7330.   begin
  7331.     if TIfPasScript(FAttachedOnes.GetItem(I)).FFreeOnCleanup then
  7332.       TIfPasScript(FAttachedOnes.GetItem(I)).Free;
  7333.   end;
  7334.   FAttachedOnes.Clear;
  7335.   for I := FAllocatedResources.Count - 1 downto 0 do begin
  7336.     p := FAllocatedResources.GetItem(I);
  7337.     p.FreeProc(fId, p.Data);
  7338.     Dispose(p);
  7339.   end;
  7340.   FAllocatedResources.Clear;
  7341. {$IFNDEF NOCLASSES}
  7342.   for I := 0 to CreatedClasses.Count - 1 do begin
  7343.     p1 := CreatedClasses.GetItem(I);
  7344.     if not p1^.AlreadyFreed then begin
  7345.       VM_Destroy(p1^.Variables);
  7346.     end;
  7347.     Dispose(p1);
  7348.   end;
  7349.   CreatedClasses.Clear;
  7350. {$ENDIF}
  7351. end;
  7352.  
  7353. //
  7354. //  Purpose: Adds a pointer to a needed resource
  7355. //
  7356. //-------------------------------------------------------------------
  7357.  
  7358. procedure TIfPasScript.AddResource(FreeProc: TResourceFree; Data: Pointer);
  7359. var
  7360.   p: PResourceData;
  7361. begin
  7362.   New(p);
  7363.   p^.Data := Data;
  7364.   p^.FreeProc := FreeProc;
  7365.   FAllocatedResources.Add(p);
  7366. end;
  7367.  
  7368.  
  7369. function TIfPasScript.FindResource(FreeProc: TResourceFree): Pointer;
  7370. var
  7371.   I: Longint;
  7372.   p: PResourceData;
  7373. begin
  7374.   for I := FAllocatedResources.Count - 1 downto 0 do begin
  7375.     p := FAllocatedResources.GetItem(I);
  7376.     if @p^.FreeProc = @FreeProc then begin
  7377.       FindResource := p^.Data;
  7378.       exit;
  7379.     end;
  7380.   end;
  7381.   FindResource := nil;
  7382. end;
  7383.  
  7384. //
  7385. //  Purpose: Removes a resource pointer and cleans up the memory
  7386. //
  7387. //-------------------------------------------------------------------
  7388.  
  7389. procedure TIfPasScript.RemoveResource(Data: Pointer);
  7390. var
  7391.   I: Longint;
  7392.   p: PResourceData;
  7393. begin
  7394.   for I := FAllocatedResources.Count - 1 downto 0 do begin
  7395.     p := FAllocatedResources.GetItem(I);
  7396.     if p^.Data = Data then begin
  7397.       FAllocatedResources.Delete(I);
  7398.       Dispose(p);
  7399.       break;
  7400.     end;
  7401.   end;
  7402. end;
  7403.  
  7404. //-------------------------------------------------------------------
  7405.  
  7406. function TIfPasScript.IsValidResource(FreeProc: TResourceFree; Data: Pointer): Boolean;
  7407. var
  7408.   I: Longint;
  7409.   p: PResourceData;
  7410. begin
  7411.   IsValidResource := True;
  7412.  
  7413.   for I := FAllocatedResources.Count - 1 downto 0 do begin
  7414.     p := FAllocatedResources.GetItem(I);
  7415.     if (p^.Data = Data) and (@p^.FreeProc = @FreeProc)
  7416.       then exit;
  7417.   end;
  7418.   IsValidResource := False;
  7419. end;
  7420.  
  7421. function TIfPasScript.GetVariable(const Name: string): PIfVariant;
  7422. begin
  7423.   GetVariable := Vm_Get(Variables, VM_Find(Variables, FastUppercase(Name)));
  7424. end;
  7425.  
  7426. function TIfPasScript.AddVariable(Name, FType: string; Constant: Boolean): PIfVariant;
  7427. var
  7428.   Parser: TIfPascalParser;
  7429.   ptype: PTypeRec;
  7430.   p: PIfVariant;
  7431.   E: TIFParserError;
  7432. begin
  7433.   Name := FastUppercase(Name);
  7434.   Parser := TIFPascalParser.Create;
  7435.   if not Parser.SetText(FType, e) then
  7436.   begin
  7437.     AddVariable := nil;
  7438.     Parser.Free;
  7439.     exit;
  7440.   end;
  7441.   Parser.CurrTokenPos := 0;
  7442.   ptype := ReadType(Parser, False, '');
  7443.   if ptype = nil then begin
  7444.     AddVariable := nil;
  7445.     RunError(Self, 0);
  7446.   end else begin
  7447.     if Constant then begin
  7448.       p := Vm_Add(Variables, CreateCajVariant(ptype), Name);
  7449.       p^.Flags := 1;
  7450.       AddVariable := p;
  7451.     end else
  7452.       AddVariable := Vm_Add(Variables, CreateCajVariant(ptype), Name);
  7453.   end;
  7454.   Parser.Free;
  7455. end;
  7456. function TIfPasScript.RemoveFunction(D: PProcedure): Boolean;
  7457. var
  7458.   i: Longint;
  7459. begin
  7460.   for i := Procedures.Count-1 downto 0do
  7461.   begin
  7462.     if Procedures.GetItem(I) = D then
  7463.     begin
  7464.       Procedures.Delete(I);
  7465.       RemoveFunction := True;
  7466.       exit;
  7467.     end;
  7468.   end;
  7469.   RemoveFunction := False;
  7470. end;
  7471.  
  7472. function TIfPasScript.AddFunction(proc: Pointer; Decl: string; Ext: Pointer): PProcedure;
  7473. var
  7474.   Parser: TIfPascalParser;
  7475.   CurrVar: string;
  7476.   FuncName,
  7477.     FuncParam: string;
  7478.   FuncRes,
  7479.     CurrType: Longint;
  7480.   E: TIFParserError;
  7481.  
  7482. begin
  7483.   Parser := TIfPascalParser.Create;
  7484.   AddFunction := nil;
  7485.   if not Parser.SetText(Decl, E) then
  7486.   begin
  7487.     parser.Free;
  7488.     exit;
  7489.   end;
  7490.   if Parser.CurrTokenId = CSTII_Procedure then
  7491.     FuncRes := 0
  7492.   else
  7493.     FuncRes := 1;
  7494.   Parser.Next;
  7495.   FuncName := Parser.GetToken;
  7496.   Parser.Next;
  7497.   FuncParam := '';
  7498.   CurrVar := '';
  7499.   if Parser.CurrTokenId = CSTI_OpenRound then begin
  7500.     Parser.Next;
  7501.     while True do begin
  7502.       if Parser.CurrTokenId = CSTII_Var then begin
  7503.         CurrVar := '!';
  7504.         Parser.Next;
  7505.       end; {if}
  7506.       while True do begin
  7507.         if Parser.CurrTokenId <> CSTI_Identifier then begin
  7508.           parser.Free;
  7509.           exit;
  7510.         end;
  7511.         CurrVar := CurrVar + Parser.GetToken + '|';
  7512.         Parser.Next;
  7513.         if Parser.CurrTokenId = CSTI_Colon then break;
  7514.         if Parser.CurrTokenId <> CSTI_Comma then begin
  7515.           parser.Free;
  7516.           exit;
  7517.         end;
  7518.         Parser.Next;
  7519.       end; {while}
  7520.       Parser.Next;
  7521.  
  7522.       CurrType := Longint(ReadType(Parser, False, ''));
  7523.       if Pos('!', CurrVar) = 1 then begin
  7524.         Delete(CurrVar, 1, 1);
  7525.         while Pos('|', CurrVar) > 0 do begin
  7526.           FuncParam := FuncParam + ' !' + copy(CurrVar, 1, Pos('|', CurrVar) - 1) + ' ' + inttostr(CurrType);
  7527.           Delete(CurrVar, 1, Pos('|', CurrVar));
  7528.         end; {while}
  7529.       end else begin
  7530.         while Pos('|', CurrVar) > 0 do begin
  7531.           FuncParam := FuncParam + ' ' + copy(CurrVar, 1, Pos('|', CurrVar) - 1) + ' ' + inttostr(CurrType);
  7532.           Delete(CurrVar, 1, Pos('|', CurrVar));
  7533.         end; {while}
  7534.       end; {if}
  7535.       if Parser.CurrTokenId = CSTI_CloseRound then begin
  7536.         Parser.Next;
  7537.         break;
  7538.       end; {if}
  7539.       Parser.Next;
  7540.     end;
  7541.   end;
  7542.   if FuncRes = 1 then begin
  7543.     Parser.Next;
  7544.     FuncRes := Longint(ReadType(Parser, False, ''));
  7545.   end;
  7546.   FuncParam := inttostr(FuncRes) + FuncParam;
  7547.   AddFunction := PM_AddExt(Procedures, Self, FuncName, FuncParam, {$IFNDEF NOCLASSES}nil, {$ENDIF}Ext, proc);
  7548.   Parser.Free;
  7549. end;
  7550.  
  7551. function TIfPasScript.CreateReal(const E: Extended): PIfVariant;
  7552. var
  7553.   p: PIfVariant;
  7554. begin
  7555.   p := CreateCajVariant(TM_Add(Types, '', CSV_Extended, nil));
  7556.   p^.Cv_Extended := E;
  7557.   CreateReal := p;
  7558. end;
  7559.  
  7560. function TIfPasScript.CreateString(const s: string): PIfVariant;
  7561. var
  7562.   p: PIfVariant;
  7563. begin
  7564.   p := CreateCajVariant(TM_Add(Types, '', CSV_String, nil));
  7565.   p^.Cv_Str := s;
  7566.   CreateString := p;
  7567. end;
  7568.  
  7569. function TIfPasScript.CreateVarType(p: PIfVariant): PIfVariant;
  7570. var
  7571.   n: PIfVariant;
  7572. begin
  7573.   n := CreateCajVariant(TM_Add(Types, '', CSV_Var, nil));
  7574.   n^.CV_Var := GetVarLink(p);
  7575.   CreateVarType := n;
  7576. end;
  7577.  
  7578. function TIfPasScript.CreateInteger(I: Longint): PIfVariant;
  7579. var
  7580.   p: PIfVariant;
  7581. begin
  7582.   p := CreateCajVariant(TM_Add(Types, '', CSV_SInt32, nil));
  7583.   p^.Cv_SInt32 := I;
  7584.   CreateInteger := p;
  7585. end;
  7586.  
  7587. function TIfPasScript.CreateBool(b: Boolean): PIfVariant;
  7588. var
  7589.   p: PIfVariant;
  7590. begin
  7591.   p := CreateCajVariant(TM_Add(Types, '', CSV_Bool, nil));
  7592.   p^.Cv_Bool := b;
  7593.   CreateBool := p;
  7594. end;
  7595.  
  7596. //
  7597. //  Purpose: Adds various internal function calls
  7598. //
  7599. //-------------------------------------------------------------------
  7600. procedure RegisterExceptionLib(Sender: TIfPasScript);
  7601.  
  7602. begin
  7603.   Sender.AddFunction(@ExProc, 'function GetLastErrorCode: word;', nil);
  7604.   Sender.AddFunction(@ExProc, 'function GetLastErrorParam: string;', nil);
  7605.   Sender.AddFunction(@ExProc, 'function GetLastErrorModule: string;', nil);
  7606.   Sender.AddFunction(@ExProc, 'function GetLastErrorAsString: string;', nil);
  7607.   Sender.AddFunction(@ExProc, 'procedure RaiseError(ErrorCode: Word; Param: string);', nil);
  7608.   Sender.AddFunction(@ExProc, 'function GetLastErrorPosition: Longint;', nil);
  7609.  
  7610. end;
  7611. //
  7612. //  Purpose: Adds various internal function calls
  7613. //
  7614. //-------------------------------------------------------------------
  7615.  
  7616. procedure RegisterStdLib(p: TIfPasScript; OnlySafe: Boolean);
  7617. {Register standard library}
  7618. begin
  7619.   p.AddFunction(@StdProc, 'function StrGet(var s: string; I: Longint): char', nil);
  7620.   p.AddFunction(@StdProc, 'procedure StrSet(c: char; i: Longint; var s: string): char', nil);
  7621.   p.AddFunction(@StdProc, 'function Ord(c: char): Byte', nil);
  7622.   p.AddFunction(@StdProc, 'function Chr(b: Byte): Char', nil);
  7623.   p.AddFunction(@StdProc, 'function StrToInt(s: string; I: Longint): Integer', nil);
  7624.   p.AddFunction(@StdProc, 'function IntToStr(i: Longint): string', nil);
  7625.   p.AddFunction(@StdProc, 'function Uppercase(s: string): string', nil);
  7626.   p.AddFunction(@StdProc, 'function Copy(s: string; i1, i2: Longint): string', nil);
  7627.   p.AddFunction(@StdProc, 'procedure Delete(var s: string; i1,i2: Longint)', nil);
  7628.   p.AddFunction(@StdProc, 'procedure Insert(s1: string; var s: string; i1: Longint)', nil);
  7629.   p.AddFunction(@StdProc, 'function Pos(s1, s2: string): Longint', nil);
  7630.   p.AddFunction(@StdProc, 'function Length(s: string): Longint', nil);
  7631.   p.AddFunction(@StdProc, 'function LowerCase(s: string): string', nil);
  7632.   p.AddFunction(@StdProc, 'function Trim(s: string): string', nil);
  7633.   p.AddFunction(@StdProc, 'function Int(s: Extended): Longint', nil);
  7634.   p.AddFunction(@StdProc, 'function FloatToStr(s: Extended): string', nil);
  7635.   p.AddFunction(@StdProc, 'function replicate(s: string; i: Longint): string', nil);
  7636.   p.AddFunction(@StdProc, 'function Version: string', nil);
  7637.   p.AddFunction(@StdProc, 'function Left(s: string; i: Longint): string', nil);
  7638.   p.AddFunction(@StdProc, 'function StringOfChar(s: string; i: Integer): string', nil);
  7639.   p.AddFunction(@StdProc, 'procedure SetLength(var S: String; L: Longint);', nil);
  7640.   PM_AddExt(p.Procedures, p, 'GETTYPE', IntToStr(Longint(TM_Get(p.Types, 'STRING')))+' MYVAR '+IntToStr(Longint(TM_Get(p.Types, '!VAR'))), {$IFNDEF NOCLASSES}nil, {$ENDIF}nil, @stdproc);
  7641.   PM_AddExt(p.Procedures, p, 'GETARRAYLENGTH', IntToStr(Longint(TM_Get(p.Types, 'LONGINT')))+' !ARR '+IntToStr(Longint(TM_Get(p.Types, '!ARRAY'))), {$IFNDEF NOCLASSES}nil, {$ENDIF}nil, @stdproc);
  7642.   PM_AddExt(p.Procedures, p, 'SETARRAYLENGTH', '0 !ARR '+IntToStr(Longint(TM_Get(p.Types, '!ARRAY')))+' NEWLEN '+IntToStr(Longint(TM_Get(p.Types, 'LONGINT'))), {$IFNDEF NOCLASSES}nil, {$ENDIF}nil, @stdproc);
  7643.   PM_AddExt(p.Procedures, p, 'ASSIGNED', IntToStr(Longint(TM_Get(p.Types, 'BOOLEAN')))+' MYVAR '+IntToStr(Longint(TM_Get(p.Types, '!VAR'))), {$IFNDEF NOCLASSES}nil, {$ENDIF}nil, @stdproc);
  7644.  
  7645.   PM_AddExt(p.Procedures, p, 'LOW', IntToStr(Longint(TM_Get(p.Types, 'LONGINT')))+' !ARR '+IntToStr(Longint(TM_Get(p.Types, '!ARRAY'))), {$IFNDEF NOCLASSES}nil, {$ENDIF}nil, @stdproc);
  7646.   PM_AddExt(p.Procedures, p, 'HIGH', IntToStr(Longint(TM_Get(p.Types, 'LONGINT')))+' !ARR '+IntToStr(Longint(TM_Get(p.Types, '!ARRAY'))), {$IFNDEF NOCLASSES}nil, {$ENDIF}nil, @stdproc);
  7647.  
  7648.   if not OnlySafe then begin
  7649.     p.AddFunction(@StdProc, 'function sin(s: Extended): Extended', nil);
  7650.     p.AddFunction(@StdProc, 'function cos(s: Extended): Extended', nil);
  7651.     p.AddFunction(@StdProc, 'function tan(s: Extended): Extended', nil);
  7652.     p.AddFunction(@StdProc, 'function SQRT(s: Extended): Extended', nil);
  7653.     p.AddFunction(@StdProc, 'function Round(s: Extended): Longint', nil);
  7654.     p.AddFunction(@StdProc, 'function Trunc(s: Extended): Longint', nil);
  7655.     p.AddFunction(@StdProc, 'function PI: Extended', nil);
  7656.   end;
  7657. end;
  7658. //-------------------------------------------------------------------
  7659.  
  7660. procedure TIfPasScript.AddStandard;
  7661. var
  7662. {$IFNDEF NOCLASSES}
  7663.   TObjClass: PIFSClassType;
  7664.   n: PProcedure;
  7665. {$ENDIF}
  7666.   u: PTypeRec;
  7667. begin
  7668.   TM_Add(Types, 'BYTE', CSV_UByte, nil);
  7669.   TM_Add(Types, 'SHORTINT', CSV_SByte, nil);
  7670.   TM_Add(Types, 'CHAR', CSV_Char, nil);
  7671.   TM_Add(Types, 'WORD', CSV_UInt16, nil);
  7672.   TM_Add(Types, 'SMALLINT', CSV_SInt16, nil);
  7673.   TM_Add(Types, 'CARDINAL', CSV_UInt32, nil);
  7674.   u := TM_Add(Types, 'LONGINT', CSV_SInt32, nil);
  7675.   TM_Add(Types, 'INTEGER', CSV_TypeCopy, u);
  7676.   TM_Add(Types, 'STRING', CSV_String, nil);
  7677.   TM_Add(Types, 'REAL', CSV_Real, nil);
  7678.   TM_Add(Types, 'SINGLE', CSV_Single, nil);
  7679.   TM_Add(Types, 'DOUBLE', CSV_Double, nil);
  7680.   TM_Add(Types, 'EXTENDED', CSV_Extended, nil);
  7681.   TM_Add(Types, 'COMP', CSV_Comp, nil);
  7682.   TM_Add(Types, 'BOOLEAN', CSV_Bool, nil);
  7683.   TM_Add(Types, 'RESOURCEPOINTER', CSV_Internal, nil); // can be used for resources (See AddResource)
  7684.  
  7685.   TM_Add(Types, '!ARRAY', CSV_Array, nil); // only for internal use! (SetArrayLength; GetArrayLength)
  7686.   TM_Add(Types, '!VAR', CSV_Var, nil); // only for internal use! (GetType)
  7687. {$IFDEF VARIANTSUPPORT}
  7688.   TM_Add(Types, 'VARIANT', CSV_Variant, nil);
  7689. {$ENDIF}
  7690. {$IFNDEF NOCLASSES}
  7691.   New(TObjClass);
  7692.   TObjClass.InheritsFrom := nil;
  7693.   TObjClass.VarNoStart := 0;
  7694.   TObjClass.VarCount := 0;
  7695.   TObjClass.Variables.u := '';
  7696.   TObjClass.PropStart := 0;
  7697.   TObjClass.Procedures := TIfList.Create;
  7698.   TObjClass.Properties := TIfList.Create;
  7699.   u := TM_Add(Types, 'TOBJECT', CSV_Class, TObjClass);
  7700.   n := AddFunction(@TObjProc, 'procedure Create', TObjClass);
  7701.   n^.Flags := $40 or $2; {public Constructor}
  7702.   n^.Name := '!' + n^.Name;
  7703.   n^.ClassType := u;
  7704.   TObjClass.Procedures.Add(n);
  7705.   n := AddFunction(@TObjProc, 'procedure Destroy', TObjClass);
  7706.   n^.Flags := $80 or $10 or $2; {Public virtualstart destructor}
  7707.   n^.ClassType := u;
  7708.   n^.Name := '!' + n^.Name;
  7709.   TObjClass.Procedures.Add(n);
  7710.   n := AddFunction(@TObjProc, 'procedure Free', TObjClass);
  7711.   n^.Flags := $2; {Public}
  7712.   n^.ClassType := u;
  7713.   n^.Name := '!' + n^.Name;
  7714.   TObjClass.Procedures.Add(n);
  7715.   n := AddFunction(@TObjProc, 'function ClassNameIs(ftype: string): Boolean', TObjClass);
  7716.   n^.Flags := $2; {Public}
  7717.   n^.ClassType := u;
  7718.   n^.Name := '!' + n^.Name;
  7719.   TObjClass.Procedures.Add(n);
  7720.   n := AddFunction(@TObjProc, 'function ClassName: String', TObjClass);
  7721.   n^.Flags := $2; {Public}
  7722.   n^.ClassType := u;
  7723.   n^.Name := '!' + n^.Name;
  7724.   TObjClass.Procedures.Add(n);
  7725.   n := AddFunction(@TObjProc, 'function GetAncestors: string', TObjClass);
  7726.   n^.Flags := $2; {Public}
  7727.   n^.ClassType := u;
  7728.   n^.Name := '!' + n^.Name;
  7729.   TObjClass.Procedures.Add(n);
  7730. {$ENDIF}
  7731. end;
  7732. //-------------------------------------------------------------------
  7733.  
  7734. function TIfPasScript.GetFunction(s: string): PProcedure;
  7735. {$IFNDEF NOCLASSES}
  7736. var
  7737.   ptype: PTypeRec;
  7738.   p: PProcedure;
  7739. {$ENDIF}
  7740. begin
  7741. {$IFNDEF NOCLASSES}
  7742.   if Pos('.', s) > 0 then begin
  7743.     ptype := GetType(FastUppercase(copy(s, 1, Pos('.', s) - 1)));
  7744.     Delete(s, 1, Pos('.', s));
  7745.     if ptype^.atypeid = CSV_Class then begin
  7746.       if GetClassProcedure(nil, ptype^.Ext, FastUppercase(s), p, True) then
  7747.         GetFunction := p
  7748.       else
  7749.         GetFunction := nil;
  7750.     end else
  7751.       GetFunction := nil;
  7752.   end else begin
  7753. {$ENDIF}
  7754.     GetFunction := PM_Get(Procedures, PM_Find(Procedures, FastUppercase(s)));
  7755. {$IFNDEF NOCLASSES} end;
  7756. {$ENDIF}
  7757. end;
  7758. //-------------------------------------------------------------------
  7759.  
  7760. function TIfPasScript.CopyVariant(p: PIfVariant): PIfVariant;
  7761. var
  7762.   r: PIfVariant;
  7763. begin
  7764.   if p = nil then begin
  7765.     CopyVariant := nil;
  7766.     exit;
  7767.   end;
  7768. {$IFNDEF NOCLASSES}
  7769.   if p^.VType^.atypeid = CSV_Property then begin
  7770.     p := GetProperty(p);
  7771.     if p = nil then begin
  7772.       CopyVariant := nil;
  7773.       exit;
  7774.     end;
  7775.     CopyVariant := p;
  7776.   end else begin
  7777. {$ENDIF}
  7778.     r := CreateCajVariant(p^.VType);
  7779.     Perform(r, p, PtSet);
  7780.     CopyVariant := r;
  7781. {$IFNDEF NOCLASSES}
  7782.   end;
  7783. {$ENDIF}
  7784. end;
  7785. //-------------------------------------------------------------------
  7786. {$IFDEF VARIANTSUPPORT}
  7787. function TIfPasScript.VariantToIFVariant(const v: Variant; Res: PIfVariant): Boolean;
  7788. var
  7789.   f: word;
  7790.   I: Longint;
  7791.   L: PIFVariant;
  7792. begin
  7793.   f := VarType(v);
  7794.   VariantToIFVariant := True;
  7795.   if (f and varArray) = 0 then
  7796.   begin
  7797.     case f and varTypeMask of
  7798.       {$IFDEF USEIDISPATCH}
  7799.       varDispatch:
  7800.         begin
  7801.           if assigned(IDispatchToIFVariantProc) then
  7802.             VariantToIFVariant := IDispatchToIFVariantProc(Self, Res, V)
  7803.           else
  7804.             VariantToIFVariant := False;
  7805.         end;
  7806.       {$ENDIF}
  7807.       varEmpty,varNull: ChangeType(Res, TM_Add(Types, '', CSV_Special, nil))^.CV_Spec := 0; {nil}
  7808.       varSmallInt: ChangeType(Res, TM_Add(Types, '', CSV_SInt16, nil))^.CV_SInt16 := v;
  7809.       varInteger: ChangeType(Res, TM_Add(Types, '', CSV_SInt32, nil))^.CV_SInt32 := v;
  7810.       varSingle: ChangeType(Res, TM_Add(Types, '', CSV_Single, nil))^.CV_Single := v;
  7811.       varDouble, VarDate: ChangeType(Res, TM_Add(Types, '', CSV_Double, nil))^.CV_Double := v;
  7812.       varBoolean: ChangeType(Res, TM_Add(Types, '', CSV_Bool, nil))^.CV_Bool := v;
  7813.       varByte: ChangeType(Res, TM_Add(Types, '', CSV_UByte, nil))^.CV_UByte := v;
  7814.       varString: ChangeType(Res, TM_Add(Types, '', CSV_String, nil))^.CV_Str := v;
  7815.       else
  7816.       begin
  7817.         VariantToIFVariant := False;
  7818.       end;
  7819.     end;
  7820.   end else
  7821.   begin
  7822.     if VarArrayDimCount(v) > 0 then
  7823.     begin
  7824.       VariantToIFVariant := False;
  7825.       exit;
  7826.     end;
  7827.     ChangeType(Res, TM_Add(Types, '', CSV_Array, Res^.VType));
  7828.     for I := VarArrayLowBound(V, 0) to VarArrayHighBound(V, 0) do
  7829.     begin
  7830.       L := CreateVarType(nil);
  7831.       Res.CV_ArrItems.Add(l);
  7832.       if not VariantToIFVariant(v[I], L) then
  7833.       begin
  7834.         VariantToIFVariant := False;
  7835.         exit;
  7836.       end;
  7837.     end;
  7838.   end;
  7839. end;
  7840.  
  7841. function TIfPasScript.IfVariantToVariant(v: PIfVariant; Var res: Variant): Boolean;
  7842. var
  7843.   I: Longint;
  7844.   q: Variant;
  7845.   {$IFNDEF NOCLASSES}{$IFDEF USEIDISPATCH}n: IDispatch;{$ENDIF}{$ENDIF}
  7846. begin
  7847.   if v = nil then
  7848.   begin
  7849.     res := null;
  7850.     IFVariantToVariant := True;
  7851.     exit;
  7852.   end;
  7853.   v := GetVarLink(v);
  7854.   res := Unassigned;
  7855.   IfVariantToVariant := True;
  7856.   if v^.VType^.atypeid = CSV_Array then
  7857.   begin
  7858.     if (PTypeRec(v^.VType^.Ext)^.atypeid = CSV_Array) or (PTypeRec(v^.VType^.Ext)^.atypeid = CSV_Var) then
  7859.     begin
  7860.       IFVariantToVariant := False; 
  7861.     end;
  7862.     res := VarArrayCreate([0, v^.CV_ArrItems.Count-1], varVariant);
  7863.     for i := 0 to v^.CV_ArrItems.Count-1 do
  7864.     begin
  7865.       IfVariantToVariant(v, q);
  7866.       res[i] := q;
  7867.     end;
  7868.   end else
  7869.   begin
  7870.     case v^.VType^.ATypeId of
  7871.       CSV_Special: Res := null;
  7872.       CSV_UByte: res := v^.CV_UByte;
  7873.       CSV_SByte: res := v^.CV_SByte;
  7874.       CSV_UInt16: res := v^.CV_UInt16;
  7875.       CSV_SInt16: res := v^.CV_SInt16;
  7876.       CSV_UInt32: res := Longint(v^.CV_UInt32);
  7877.       CSV_SInt32: res := v^.CV_SInt32;
  7878.       CSV_Char: res := v^.CV_Char;
  7879.       CSV_String: res := v^.CV_Str;
  7880.       CSV_Real: res := v^.CV_Real;
  7881.       CSV_Single: res := v^.CV_Single;
  7882.       CSV_Double: res := v^.CV_Double;
  7883.       CSV_Extended: res := v^.CV_Extended;
  7884.       CSV_Comp: res := v^.CV_Comp;
  7885.       CSV_Bool: res := v^.CV_Bool;
  7886.       {$IFNDEF NOCLASSES}
  7887.       {$IFDEF USEIDISPATCH}
  7888.       CSV_ExternalObject:
  7889.         begin
  7890.           if assigned(IFVariantToIDispatchProc) then
  7891.           begin
  7892.             if IFVariantToIDispatchProc(Self, n, v) then
  7893.               res := n
  7894.             else
  7895.               IFVariantToVariant := False;
  7896.           end else
  7897.             IFVariantToVariant := False;
  7898.         end;
  7899.         {$ENDIF}
  7900.         {$ENDIF}
  7901.     else
  7902.       IFVariantToVariant := False;
  7903.     end;
  7904.   end;
  7905. end;
  7906.  
  7907. function TIfPasScript.CallFunction(P: PProcedure; Params: Array of Variant): Variant;
  7908. var
  7909.   RealParams: PVariableManager;
  7910.   i: Longint;
  7911.   n: PIFVariant;
  7912.   a: Variant;
  7913. begin
  7914.   RunError(Self, 0);
  7915.   {$IFNDEF NOCLASSES}
  7916.   if assigned(p^.ClassType) then  // use CallMethod instead
  7917.   begin
  7918.     FError.Errorcode := ETypeMismatch;
  7919.     FError.ErrorPosition := -1;
  7920.     exit;
  7921.   end;
  7922.   {$ENDIF}
  7923.   CallFunction := null;
  7924.   RealParams := VM_Create(nil);
  7925.   for i := Low(Params) to High(Params) do
  7926.   begin
  7927.     n := CreateVarType(nil);
  7928.     VM_Add(RealParams, n, '');
  7929.     if not VariantToIFVariant(Params[i], N) then
  7930.     begin
  7931.       FError.Errorcode := ETypeMismatch;
  7932.       FError.ErrorPosition := -1;
  7933.       VM_Destroy(RealParams);
  7934.       CallFunction := null;
  7935.       exit;
  7936.     end;
  7937.   end;
  7938.   n := RunScriptProc(P, RealParams);
  7939.   VM_Destroy(RealParams);
  7940.   IfVariantToVariant(n, a);
  7941.   CallFunction := a;
  7942. end;
  7943.  
  7944.  
  7945. //-------------------------------------------------------------------
  7946. {$IFNDEF NOCLASSES}
  7947. function TIfPasScript.CallMethod(P: PProcedure; mySelf: PCreatedClass; Params: Array of Variant): Variant;
  7948. var
  7949.   RealParams: PVariableManager;
  7950.   i: Longint;
  7951.   n: PIFVariant;
  7952.   a: Variant;
  7953. begin
  7954.   RunError(Self, 0);
  7955.   if not assigned(p^.ClassType) then  // use CallFunction instead
  7956.   begin
  7957.     FError.Errorcode := ETypeMismatch;
  7958.     FError.ErrorPosition := -1;
  7959.     exit;
  7960.   end;
  7961.   CallMethod := null;
  7962.   RealParams := VM_Create(nil);
  7963.   n := CreateCajVariant(MySelf^.ClassType);
  7964.   n^.CV_Class := MySelf;
  7965.   VM_Add(RealParams, n, 'SELF');
  7966.   for i := Low(Params) to High(Params) do
  7967.   begin
  7968.     n := CreateVarType(nil);
  7969.     VM_Add(RealParams, n, '');
  7970.     if not VariantToIFVariant(Params[i], N) then
  7971.     begin
  7972.       FError.Errorcode := ETypeMismatch;
  7973.       FError.ErrorPosition := -1;
  7974.       VM_Destroy(RealParams);
  7975.       CallMethod := null;
  7976.       exit;
  7977.     end;
  7978.   end;
  7979.   n := RunScriptProc(P, RealParams);
  7980.   VM_Destroy(RealParams);
  7981.   IfVariantToVariant(n, a);
  7982.   CallMethod := a;
  7983. end;
  7984.  
  7985. {$ENDIF}
  7986. {$ENDIF}
  7987.  
  7988. //-------------------------------------------------------------------
  7989. function TIfPasScript.Attach(ScriptEngine: TIfPasScript): Boolean;
  7990. begin
  7991.   Attach := Attach2(ScriptEngine, True);
  7992. end;
  7993.  
  7994. function TIfPasScript.Attach2(ScriptEngine: TIfPasScript; FreeOnCleanup: Boolean): Boolean;
  7995. var
  7996.   I: Longint;
  7997.   nt: PTypeRec;
  7998.   nc: PIfVariant;
  7999.   np: PProcedure;
  8000. begin
  8001.   if (ScriptEngine = nil) or (ScriptEngine = Self) or (ScriptEngine.MainOffset = -1) or (Not ScriptEngine.IsUnit)then begin
  8002.     Attach2 := False;
  8003.     exit;
  8004.   end;
  8005.   for I := 0 to FAttachedOnes.Count -1 do
  8006.   begin
  8007.     if FastUppercase(TIFPasScript(FAttachedOnes.GetItem(I)).ModuleName) = (ScriptEngine.ModuleName) then
  8008.     begin
  8009.       Attach2 := False;
  8010.       exit;
  8011.     end;
  8012.   end;
  8013.   ScriptEngine.FFreeOnCleanup := FreeOnCleanup;
  8014.   for I:= 0 to ScriptEngine.Types.List.Count -1 do
  8015.   begin
  8016.     nt := ScriptEngine.Types.List.GetItem(I);
  8017.     TM_Add(Types, nt^.Ident, CSV_TypeCopy, nt);
  8018.   end;
  8019.   for i := 0 to VM_Count(ScriptEngine.Variables)-1 do
  8020.   begin
  8021.     nc := VM_Get(ScriptEngine.Variables, I);
  8022.     if VM_Find(Variables, VM_GetName(ScriptEngine.Variables, I))=-1 then
  8023.     begin
  8024.       VM_Add(Variables, CreateVarType(nc), VM_GetName(ScriptEngine.Variables, I));
  8025.     end;
  8026.   end;
  8027.   for i := 0 to ScriptEngine.Procedures.Count-1 do
  8028.   begin
  8029.     np := ScriptEngine.Procedures.GetItem(I);
  8030.     if np^.Mode = 0 then
  8031.       PM_AddInt(Procedures, np^.FScriptEngine, np^.Name, np^.Decl, {$IFNDEF NOCLASSES}np^.ClassType, {$ENDIF}np^._Ext, np^.Offset)^.Flags := np^.Flags
  8032.     else
  8033.       PM_AddExt(Procedures, np^.FScriptEngine, np^.Name, np^.Decl, {$IFNDEF NOCLASSES}np^.ClassType, {$ENDIF}np^._Ext, @np^.Proc1)^.Flags := np^.Flags;
  8034.   end;
  8035.   FAttachedOnes.Add(ScriptEngine);
  8036.   Attach2 := True;
  8037. end;
  8038. //-------------------------------------------------------------------
  8039. function TIfPasScript.GetType(const s: string): PTypeRec;
  8040. begin
  8041.   GetType := GetTypeLink(TM_Get(Types, FastUppercase(s)));
  8042. end;
  8043. //-------------------------------------------------------------------
  8044. {$IFNDEF NOCLASSES}
  8045.  
  8046. function GetInheritedProc(CurrProc: PProcedure): PProcedure;
  8047. var
  8048.   p: PIFSClassType;
  8049.   n: PProcedure;
  8050.   I: Integer;
  8051. begin
  8052.   p := PTypeRec(CurrProc^.ClassType)^.Ext;
  8053.   repeat
  8054.     p := p^.InheritsFrom^.Ext;
  8055.     for I := 0 to p^.Procedures.Count - 1 do begin
  8056.       n := p^.Procedures.GetItem(I);
  8057.       if n^.Name = CurrProc^.Name then begin
  8058.         GetInheritedProc := n;
  8059.         exit;
  8060.       end;
  8061.     end;
  8062.   until p = nil;
  8063.   GetInheritedProc := nil;
  8064. end;
  8065. {$ENDIF}
  8066.  
  8067. end.
  8068.  
  8069.  
  8070.