| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101 |
- {
- Inno Setup Preprocessor
- Copyright (C) 2001-2002 Alex Yackimoff
- Inno Setup
- Copyright (C) 1997-2025 Jordan Russell
- Portions by Martijn Laan
- For conditions of distribution and use, see LICENSE.TXT.
- }
- unit ISPP.IdentMan;
- interface
- uses
- SysUtils, Classes, ISPP.Intf, ISPP.Base;
- type
- EIdentError = class(Exception);
- EMacroError = class(EIdentError);
- TIdentManager = class;
- PIdent = ^TIdent;
- TIdent = object
- Name: string;
- Hash: Integer;
- IdentType: TIdentType;
- end;
- PDefinable = ^TDefinable;
- TDefinable = object(TIdent)
- Scope: record
- LocalLevel: Integer; // 0 means public
- IsProtected: Boolean; // False means private, not used if Locality = 0
- end;
- end;
- PVariable = ^TVariable;
- TVariable = object(TDefinable)
- Dim: Integer;
- Value: array[0..0] of TIsppVariant;
- end;
- TExprPosition = record
- FileIndex, Line, Column: Integer;
- end;
- PMacro = ^TMacro;
- TMacro = object(TDefinable)
- Expression: string;
- DeclPos: TExprPosition;
- ParserOptions: TIsppParserOptions;
- ParamCount: Integer;
- Params: array[0..0] of TIsppMacroParam;
- end;
- PFunc = ^TFunc;
- TFunc = object(TIdent)
- Code: TIsppFunction;
- Ext: NativeInt;
- end;
- PActualParams = ^TActualParams;
- TActualParams = array of TVariable;
- IInternalFuncParams = interface(IIsppFuncParams)
- function Get(Index: NativeInt): PIsppVariant;
- function ResPtr: PIsppVariant;
- end;
- TDefineScope = (dsAny, dsPublic, dsProtected, dsPrivate); // order matters
- TIdentManager = class(TObject, IIdentManager)
- private
- FCustomIdents: IIdentManager;
- FFuncSender: NativeInt;
- FRefCount: Integer;
- FVarMan: TList;
- FLocalLevel: Integer;
- function FindIndex(const Name: string; AScope: TDefineScope): Integer;
- function Find(const Name: string; AScope: TDefineScope): PIdent;
- procedure FreeItem(Item: Pointer);
- function MacroIdents: IIdentManager;
- protected
- function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;
- public
- constructor Create(const CustomIdents: IIdentManager; FuncSender: NativeInt);
- destructor Destroy; override;
- function _AddRef: Integer; stdcall;
- function _Release: Integer; stdcall;
- procedure BeginLocal;
- procedure EndLocal;
- function Defined(const Name: string): Boolean;
- procedure DefineFunction(const Name: string; Handler: TIsppFunction;
- Ext: NativeInt);
- procedure DefineMacro(const Name, Expression: string; ExprPos: TExprPosition;
- const ParserOptions: TIsppParserOptions; Params: array of TIsppMacroParam;
- Scope: TDefineScope);
- procedure DefineVariable(const Name: string; Index: Integer;
- const Value: TIsppVariant; Scope: TDefineScope);
- procedure Delete(const Name: string; Scope: TDefineScope);
- procedure DimVariable(const Name: string; Length: Integer; Scope: TDefineScope; var ReDim: Boolean);
- function GetIdent(const Name: string; out CallContext: ICallContext): TIdentType;
- function TypeOf(const Name: string): Byte;
- function DimOf(const Name: String): Integer;
- end;
- const
- TYPE_ERROR = 0;
- TYPE_NULL = 1;
- TYPE_INTEGER = 2;
- TYPE_STRING = 3;
- TYPE_MACRO = 4;
- TYPE_FUNC = 5;
- TYPE_ARRAY = 6;
- implementation
- uses
- Windows, Types, ISPP.Preprocessor, ISPP.CTokenizer, ISPP.Parser,
- ISPP.VarUtils, ISPP.Consts, ISPP.Sessions;
- const
- MaxLocalArraySize = 16;
- GL: array[TDefineScope] of string = ('Public', 'Public', 'Protected', 'Private');
- function MakeHash(const S: string): Integer;
- begin
- Result := 0;
- for var I := 1 to Length(S) do
- Result := ((Result shl 7) or (Result shr 25)) + Ord(UpCase(S[I]));
- end;
- { TCallContext }
- type
- TCallContext = class(TInterfacedObject)
- private
- procedure ErrorDefined(const ArgName: string);
- procedure ErrorNotSpecified(const ArgName: string);
- procedure ErrorTooMany;
- procedure ErrorTooFew;
- procedure ErrorWrongType(const ArgName: string);
- protected
- function GroupingStyle: TArgGroupingStyle;
- end;
- procedure TCallContext.ErrorDefined(const ArgName: string);
- begin
- raise EIdentError.CreateFmt(SParamSpecifiedTwice, [ArgName])
- end;
- procedure TCallContext.ErrorNotSpecified(const ArgName: string);
- begin
- raise EIdentError.CreateFmt(SRequiredParamMissing, [ArgName])
- end;
- procedure TCallContext.ErrorTooMany;
- begin
- raise EIdentError.Create(STooManyActualParams);
- end;
- procedure TCallContext.ErrorTooFew;
- begin
- raise EIdentError.Create(SInsufficientParams)
- end;
- procedure TCallContext.ErrorWrongType(const ArgName: string);
- begin
- raise EIdentError.CreateFmt(SWrongParamType, [ArgName])
- end;
- function TCallContext.GroupingStyle: TArgGroupingStyle;
- begin
- Result := agsParenteses;
- end;
- { TVarCallContext }
- type
- TVarCallContext = class(TCallContext, ICallContext)
- private
- FVariable: PVariable;
- FIndex: Integer;
- protected
- constructor Create(Variable: PVariable);
- { ICallContext }
- procedure Add(const Name: string; const Value: TIsppVariant);
- function Call: TIsppVariant;
- function GroupingStyle: TArgGroupingStyle;
- procedure Clone(out NewContext: ICallContext);
- end;
- constructor TVarCallContext.Create(Variable: PVariable);
- begin
- FVariable := Variable;
- FIndex := -1;
- end;
- procedure TVarCallContext.Add(const Name: string;
- const Value: TIsppVariant);
- begin
- if FVariable.Dim <> 0 then
- begin
- if (Name = '') or (CompareText(Name, 'INDEX') = 0) then
- begin
- if FIndex <> -1 then ErrorDefined('Index');
- try
- FIndex := ToInt(Value).AsInteger;
- except on E: Exception do
- raise EIdentError(E.Message);
- end;
- end
- else
- raise EIdentError.CreateFmt(SUnknownParam, [Name]);
- if (FIndex < 0) or (FIndex >= FVariable.Dim) then
- raise EIdentError.CreateFmt(SIndexIsOutOfArraySize, [FIndex, FVariable.Name]);
- end
- else
- raise EIdentError.Create(SParameterlessVariable);
- end;
- function TVarCallContext.Call: TIsppVariant;
- begin
- if FIndex < 0 then
- if FVariable.Dim <> 0 then
- raise EIdentError.CreateFmt(SIndexNotSpecifiedForArray, [FVariable.Name])
- else
- FIndex := 0;
- Result.Typ := evLValue;
- Result.AsPtr := @(FVariable^.Value[FIndex]);
- SimplifyLValue(Result);
- end;
- function TVarCallContext.GroupingStyle: TArgGroupingStyle;
- begin
- if FVariable.Dim <> 0 then
- Result := agsBrackets
- else
- Result := agsNone
- end;
- { TMacroCallContext }
- var
- MacroStack: TStrings;
- procedure PushMacro(const Name: string);
- begin
- if MacroStack = nil then
- MacroStack := TStringList.Create
- else ;
- {if MacroStack.IndexOf(UpperCase(Name)) >= 0 then
- raise EMacroError.CreateFmt(SRecursiveMacroCall, [Name]);}
- MacroStack.Add(UpperCase(Name));
- end;
- procedure PopMacro;
- begin
- MacroStack.Delete(MacroStack.Count - 1);
- if MacroStack.Count = 0 then
- begin
- MacroStack.Free;
- MacroStack := nil
- end;
- end;
- type
- { TMacroLocalArrayCallContext }
- TMacroCallContext = class;
- TMacroLocalArrayCallContext = class(TCallContext, ICallContext)
- private
- FMacroContext: TMacroCallContext;
- FIndex: Integer;
- public
- constructor Create(MacroContext: TMacroCallContext);
- procedure Add(const Name: String; const Value: TIsppVariant);
- function Call: TIsppVariant;
- function GroupingStyle: TArgGroupingStyle;
- procedure Clone(out NewContext: ICallContext);
- end;
- { TMacroCallContext }
- TMacroArgument = record
- Value: TVariable;
- Defined: Boolean;
- end;
- PMacroArgArray = ^TMacroArgArray;
- TMacroArgArray = array[0..0] of TMacroArgument;
- TMacroCallContext = class(TCallContext, ICallContext, IIdentManager)
- private
- FIdentManager: IIdentManager;
- FMacro: PMacro;
- FList: PMacroArgArray;
- FCurrentParam: Integer;
- FLocalVars: TList;
- procedure AdjustLocalArray(Index: Integer);
- function FindFormalParam(const Name: string): Integer;
- protected
- constructor Create(const IdentManager: IIdentManager; Macro: PMacro);
- destructor Destroy; override;
- { IIdentManager}
- function GetIdent(const Name: string; out CallContext: ICallContext): TIdentType;
- function Defined(const Name: string): Boolean;
- function TypeOf(const Name: string): Byte;
- function DimOf(const Name: string): Integer;
- { ICallContext }
- procedure Add(const Name: string; const Value: TIsppVariant);
- function Call: TIsppVariant;
- procedure Clone(out NewContext: ICallContext);
- end;
- constructor TMacroLocalArrayCallContext.Create(MacroContext: TMacroCallContext);
- begin
- FMacroContext := MacroContext;
- FIndex := -1;
- end;
- procedure TMacroLocalArrayCallContext.Add(const Name: String;
- const Value: TIsppVariant);
- begin
- if (Name = '') or (CompareText(Name, 'INDEX') = 0) then
- begin
- if FIndex <> -1 then ErrorDefined('Index');
- try
- FIndex := ToInt(Value).AsInteger;
- except on E: Exception do
- raise EIdentError.Create(E.Message);
- end;
- end
- else
- raise EIdentError.CreateFmt(SUnknownParam, [Name]);
- if (FIndex < 0) or (FIndex >= MaxLocalArraySize) then
- raise EIdentError.Create(SLocalArraysIndexError);
- end;
- function TMacroLocalArrayCallContext.Call: TIsppVariant;
- begin
- if FIndex = -1 then FIndex := 0;
- FMacroContext.AdjustLocalArray(FIndex);
- Result.Typ := evLValue;
- Result.AsPtr := FMacroContext.FLocalVars[FIndex];
- end;
- function TMacroLocalArrayCallContext.GroupingStyle: TArgGroupingStyle;
- begin
- Result := agsBrackets;
- end;
- constructor TMacroCallContext.Create(const IdentManager: IIdentManager;
- Macro: PMacro);
- begin
- FIdentManager := IdentManager;
- FMacro := Macro;
- FList := AllocMem(SizeOf(TMacroArgument) * Macro^.ParamCount);
- end;
- destructor TMacroCallContext.Destroy;
- begin
- if Assigned(FLocalVars) then begin
- for var I := 0 to FLocalVars.Count - 1 do
- Dispose(PIsppVariant(FLocalVars[I]));
- FLocalVars.Free;
- end;
- FreeMem(FList)
- end;
- procedure TMacroCallContext.Add(const Name: string;
- const Value: TIsppVariant);
- var
- ParamIndex: Integer;
- begin
- if Name <> '' then
- ParamIndex := FindFormalParam(Name)
- else
- ParamIndex := FCurrentParam;
- if ParamIndex >= FMacro.ParamCount then
- ErrorTooMany;
- if FList[ParamIndex].Defined then
- ErrorDefined(FMacro.Params[ParamIndex].Name);
- if Value.Typ = evSpecial then //parser is in "skip" state
- else
- if Value.Typ = evNull then
- if pfHasDefault in FMacro.Params[ParamIndex].ParamFlags then
- FList[ParamIndex].Value.Value[0] := FMacro.Params[ParamIndex].DefValue
- else
- ErrorNotSpecified(FMacro.Params[ParamIndex].Name)
- else
- if (pfByRef in FMacro.Params[ParamIndex].ParamFlags) and
- (Value.Typ <> evLValue) then
- raise EIdentError.CreateFmt(SLValueRequiredForByRefParam, [FMacro.Params[ParamIndex].Name])
- else
- if (pfTypeDefined in FMacro.Params[ParamIndex].ParamFlags) and
- (GetRValue(Value).Typ <> FMacro.Params[ParamIndex].DefValue.Typ) then
- ErrorWrongType(FMacro.Params[ParamIndex].Name)
- else
- if pfByRef in FMacro.Params[ParamIndex].ParamFlags then
- begin
- FList[ParamIndex].Value.Value[0] := Value;
- SimplifyLValue(FList[ParamIndex].Value.Value[0]);
- end
- else
- begin
- if FMacro.Params[ParamIndex].DefValue.Typ = evCallContext then
- begin
- if (pfFunc in FMacro.Params[ParamIndex].ParamFlags) and
- (Value.AsCallContext.GroupingStyle <> agsParenteses) or
- not (pfFunc in FMacro.Params[ParamIndex].ParamFlags) and
- (Value.AsCallContext.GroupingStyle <> agsBrackets) then
- ErrorWrongType(FMacro.Params[ParamIndex].Name);
- end;
- FList[ParamIndex].Value.Value[0] := GetRValue(Value);
- end;
- FList[ParamIndex].Defined := True;
- FList[ParamIndex].Value.Name := FMacro.Params[ParamIndex].Name;
- FList[ParamIndex].Value.Dim := 0;
- Inc(FCurrentParam);
- end;
- function TMacroCallContext.Call: TIsppVariant;
- var
- I: Integer;
- Msg: string;
- begin
- PushMacro(FMacro.Name);
- try
- for I := 0 to FMacro.ParamCount - 1 do
- if not FList[I].Defined then
- if not (pfHasDefault in FMacro.Params[I].ParamFlags) then
- ErrorNotSpecified(FMacro.Params[I].Name)
- //raise EMacroError.CreateFmt(SNoReqParam, [FMacro.Params[I].Name])
- else
- begin
- FList[I].Value.Name := FMacro.Params[I].Name;
- FList[I].Value.Dim := 0;
- FList[I].Value.Value[0] := FMacro.Params[I].DefValue;
- FList[I].Defined := True;
- end;
- try
- Result := Parse(Self, FMacro.Expression, FMacro.DeclPos.Column,
- @FMacro.ParserOptions);
- except
- on E: EParsingError do
- begin
- if E.Position > 0 then
- begin
- if FMacro.DeclPos.FileIndex > 0 then
- Msg := Format(SErrorExecutingMacroFile, [FMacro.Name,
- PeekPreproc.IncludedFiles[FMacro.DeclPos.FileIndex],
- FMacro.DeclPos.Line, E.Position, E.Message])
- else
- Msg := Format(SErrorExecutingMacro, [FMacro.Name,
- FMacro.DeclPos.Line, E.Position, E.Message]);
- E.Message := Msg;
- E.Position := 0;
- end;
- raise;
- end;
- on E: Exception do
- begin
- E.Message := Format(SErrorExecutingMacroUnexpected, [FMacro.Name, E.Message]);
- raise;
- end;
- end;
- VerboseMsg(9, SSuccessfullyCalledMacro, [FMacro.Name]);
- finally
- PopMacro;
- end;
- end;
- function TMacroCallContext.Defined(const Name: string): Boolean;
- var
- I: Integer;
- begin
- Result := True;
- if CompareText(Name, SLocal) = 0 then Exit;
- for I := 0 to FMacro^.ParamCount - 1 do
- if CompareText(FMacro^.Params[I].Name, Name) = 0 then
- Exit;
- Result := FIdentManager.Defined(Name)
- end;
- function TMacroCallContext.FindFormalParam(const Name: string): Integer;
- begin
- for Result := 0 to FMacro.ParamCount - 1 do
- if CompareText(FMacro.Params[Result].Name, Name) = 0 then Exit;
- raise EMacroError.CreateFmt(SUnknownParam, [Name]);
- end;
- function TMacroCallContext.GetIdent(const Name: string;
- out CallContext: ICallContext): TIdentType;
- var
- I: Integer;
- begin
- Result := itVariable;
- if CompareText(SLocal, Name) = 0 then
- begin
- CallContext := TMacroLocalArrayCallContext.Create(Self);
- Exit;
- end
- else
- for I := 0 to FMacro^.ParamCount - 1 do
- if CompareText(FMacro^.Params[I].Name, Name) = 0 then
- begin
- if FMacro^.Params[I].DefValue.Typ = evCallContext then
- FList[I].Value.Value[0].AsCallContext.Clone(CallContext)
- else
- CallContext := TVarCallContext.Create(@FList[I].Value);
- Exit;
- end;
- Result := FIdentManager.GetIdent(Name, CallContext)
- end;
- function TMacroCallContext.TypeOf(const Name: string): Byte;
- var
- I: Integer;
- begin
- if CompareText(Name, SLocal) = 0 then
- begin
- Result := TYPE_ARRAY;
- Exit;
- end;
- for I := 0 to FMacro^.ParamCount - 1 do
- if CompareText(FMacro^.Params[I].Name, Name) = 0 then
- begin
- case GetRValue(FList[I].Value.Value[0]).Typ of
- evNull: Result := TYPE_NULL;
- evInt: Result := TYPE_INTEGER
- else
- Result := TYPE_STRING
- end;
- Exit;
- end;
- Result := FIdentManager.TypeOf(Name)
- end;
- {TFuncParam}
- type
- TFuncParam = class(TInterfacedObject, IIsppFuncParam)
- private
- FValue: PIsppVariant;
- protected
- constructor Create(Value: PIsppVariant);
- function GetType: TIsppVarType; stdcall;
- function GetAsInt64: Int64; stdcall;
- function GetAsString(Buf: PChar; BufSize: Cardinal): Integer; stdcall;
- end;
- constructor TFuncParam.Create(Value: PIsppVariant);
- begin
- FValue := Value
- end;
- function TFuncParam.GetAsInt64: Int64;
- begin
- Result := FValue^.AsInt64
- end;
- function TFuncParam.GetAsString(Buf: PChar; BufSize: Cardinal): Integer;
- begin
- StrLCopy(Buf, PChar(FValue^.AsStr), BufSize);
- Result := Length(FValue^.AsStr)
- end;
- function TFuncParam.GetType: TIsppVarType;
- begin
- Result := FValue^.Typ
- end;
- { TFuncCallContext }
- type
- TFuncCallContext = class(TCallContext, ICallContext, IInternalFuncParams,
- IIsppFuncResult)
- private
- FSender: NativeInt;
- FFunc: PFunc;
- FResult: TIsppVariant;
- FParams: TList;
- protected
- constructor Create(Sender: NativeInt; Func: PFunc);
- destructor Destroy; override;
- { IIsppFuncParams }
- function Get(Index: NativeInt): IIsppFuncParam; stdcall;
- function GetCount: NativeInt; stdcall;
- { IInternalFuncParams }
- function IInternalFuncParams.Get = InternalGet;
- function InternalGet(Index: NativeInt): PIsppVariant;
- function ResPtr: PIsppVariant;
- { IIsppFuncResult }
- procedure SetAsInt(Value: Int64); stdcall;
- procedure SetAsString(Value: PChar); stdcall;
- procedure SetAsNull; stdcall;
- procedure Error(Message: PChar); stdcall;
- { ICallContext }
- procedure Add(const Name: string; const Value: TIsppVariant);
- function Call: TIsppVariant;
- procedure Clone(out NewContext: ICallContext);
- end;
- constructor TFuncCallContext.Create(Sender: NativeInt; Func: PFunc);
- begin
- FSender := Sender;
- FFunc := Func;
- FParams := TList.Create;
- end;
- destructor TFuncCallContext.Destroy;
- begin
- FParams.Free;
- end;
- procedure TFuncCallContext.Add(const Name: string;
- const Value: TIsppVariant);
- var
- V: PIsppVariant;
- begin
- if Name <> '' then
- raise EIdentError.Create(SFuncsNoSupportNamedParams);
- New(V);
- CopyExpVar(Value, V^);
- FParams.Add(V);
- end;
- function TFuncCallContext.Call: TIsppVariant;
- var
- InternalParams: IInternalFuncParams;
- Error: TIsppFuncResult;
- Ext: NativeInt;
- begin
- InternalParams := Self;
- if FFunc.Ext = -1 then
- Ext := FSender
- else
- Ext := FFunc.Ext;
- Error := FFunc.Code(Ext, InternalParams, Self);
- case Error.Error of
- ISPPFUNC_FAIL: raise EIdentError.CreateFmt(SFuncError, [FFunc^.Name]);
- ISPPFUNC_MANYARGS: ErrorTooMany;
- ISPPFUNC_INSUFARGS: ErrorTooFew;
- ISPPFUNC_INTWANTED: raise EIdentError.Create(SIntegerExpressionExpected);
- ISPPFUNC_STRWANTED: raise EIdentError.Create(SStringExpressionExpected);
- end;
- Result := FResult;
- VerboseMsg(9, SSuccessfullyCalledFunction, [FFunc.Name]);
- end;
- procedure TFuncCallContext.Error(Message: PChar);
- begin
- raise Exception.Create(Message)
- end;
- function TFuncCallContext.Get(Index: NativeInt): IIsppFuncParam;
- begin
- Result := TFuncParam.Create(FParams[Index]);
- end;
- function TFuncCallContext.GetCount: NativeInt;
- begin
- Result := FParams.Count
- end;
- function TFuncCallContext.InternalGet(Index: NativeInt): PIsppVariant;
- begin
- Result := FParams[Index]
- end;
- function TFuncCallContext.ResPtr: PIsppVariant;
- begin
- Result := @FResult
- end;
- procedure TFuncCallContext.SetAsInt(Value: Int64);
- begin
- MakeInt(FResult, Value)
- end;
- procedure TFuncCallContext.SetAsNull;
- begin
- FResult := NULL
- end;
- procedure TFuncCallContext.SetAsString(Value: PChar);
- begin
- MakeStr(FResult, Value)
- end;
- { TIdentManager }
- constructor TIdentManager.Create(const CustomIdents: IIdentManager; FuncSender: NativeInt);
- begin
- FCustomIdents := CustomIdents;
- FVarMan := TList.Create;
- FFuncSender := FuncSender;
- end;
- destructor TIdentManager.Destroy;
- begin
- for var I := 0 to FVarMan.Count - 1 do
- FreeItem(FVarMan[I]);
- FVarMan.Free;
- end;
- function TIdentManager.Defined(const Name: string): Boolean;
- begin
- Result := Find(Name, dsAny) <> nil
- end;
- procedure TIdentManager.DefineFunction(const Name: string;
- Handler: TIsppFunction; Ext: NativeInt);
- var
- F: PFunc;
- begin
- if Find(Name, dsAny) <> nil then Exit;
- F := AllocMem(SizeOf(TFunc));
- F.Name := Name;
- F.Hash := MakeHash(Name);
- F.IdentType := itFunc;
- F.Code := Handler;
- F.Ext := Ext;
- FVarMan.Add(F);
- end;
- procedure TIdentManager.DefineMacro(const Name, Expression: string;
- ExprPos: TExprPosition; const ParserOptions: TIsppParserOptions;
- Params: array of TIsppMacroParam; Scope: TDefineScope);
- var
- P: PMacro;
- begin
- if Scope = dsAny then Scope := dsPublic;
- Delete(Name, Scope);
- for var I := 1 to High(Params) do
- for var J := 0 to I - 1 do
- if CompareText(Params[I].Name, Params[J].Name) = 0 then
- raise EIdentError.CreateFmt(SRedeclaredIdentifier, [Params[I].Name]);
- P := AllocMem(SizeOf(TMacro) + SizeOf(TIsppMacroParam) * Length(Params));
- try
- P^.Name := Name;
- P^.Hash := MakeHash(Name);
- P^.IdentType := itMacro;
- P^.Scope.IsProtected := Scope = dsProtected;
- if Scope >= dsProtected then P^.Scope.LocalLevel := FLocalLevel;
- P^.Expression := Expression;
- P^.DeclPos := ExprPos;
- P^.ParserOptions := ParserOptions;
- P^.ParamCount := Integer(Length(Params));
- for var I := 0 to High(Params) do
- P^.Params[I] := Params[I];
- FVarMan.Add(P);
- except
- FreeMem(P)
- end;
- VerboseMsg(4, SMacroDefined, [GL[Scope], Name]);
- end;
- procedure TIdentManager.DefineVariable(const Name: string; Index: Integer;
- const Value: TIsppVariant; Scope: TDefineScope);
- var
- V: PVariable;
- Ident: PIdent;
- begin
- if Scope = dsAny then Scope := dsPublic;
- Ident := Find(Name, Scope);
- if (Ident <> nil) and (Ident.IdentType = itVariable) and (PVariable(Ident).Dim <> 0) then
- begin
- V := PVariable(Ident);
- if (Index < 0) or (Index >= V.Dim) then
- raise EIdentError.CreateFmt(SIndexIsOutOfArraySize, [Index, Name]);
- V.Value[Index] := Value;
- end
- else
- begin
- if Index <> -1 then
- raise EIdentError.CreateFmt(SUndeclaredIdentifier, [Name]);
- Delete(Name, Scope);
- V := AllocMem(SizeOf(TVariable));
- V^.Name := Name;
- V^.Hash := MakeHash(Name);
- V^.IdentType := itVariable;
- V^.Scope.IsProtected := Scope = dsProtected;
- if Scope >= dsProtected then V^.Scope.LocalLevel := FLocalLevel;
- V^.Dim := 0;
- V^.Value[0] := Value;
- FVarMan.Add(V);
- end;
- VerboseMsg(4, SVariableDefined, [GL[Scope], Name]);
- end;
- procedure TIdentManager.Delete(const Name: string; Scope: TDefineScope);
- var
- P: PIdent;
- S: TDefineScope;
- const
- VM: array[itVariable..itMacro] of string = ('variable', 'macro');
- begin
- {if Scope = dsAny then
- begin
- P := Find(Name, dsPrivate);
- if P = nil then P := Find(Name, dsProtected);
- if P = nil then P := Find(Name, dsPublic)
- end
- else}
- P := Find(Name, Scope);
- if (P <> nil) and (P.IdentType in [itVariable, itMacro]) then
- begin
- //if PDefinable(P).Scope.Locality <> FLocalLevel then Exit;
- S := dsPublic;
- with PDefinable(P).Scope do
- if LocalLevel <> 0 then
- if IsProtected then
- S := dsProtected
- else
- S := dsPrivate;
- VerboseMsg(4, SUndefined, [GL[S],
- VM[P.IdentType], P.Name]);
- FVarMan.Remove(P);
- FreeItem(P);
- end
- end;
- procedure TIdentManager.DimVariable(const Name: string; Length: Integer;
- Scope: TDefineScope; var ReDim: Boolean);
- var
- V, VOld: PVariable;
- I, ReDimIndex: Integer;
- Msg: String;
- begin
- if Length > 0 then begin
- if Scope = dsAny then Scope := dsPublic;
- if ReDim then begin
- ReDimIndex := FindIndex(Name, Scope);
- if (ReDimIndex <> -1) and
- ((PIdent(FVarMan[ReDimIndex]).IdentType <> itVariable) or
- (PVariable(FVarMan[ReDimIndex]).Dim = 0)) then
- ReDimIndex := -1; //not a variable or not an array, #dim normally
- ReDim := ReDimIndex <> -1;
- end else
- ReDimIndex := -1;
- V := AllocMem(SizeOf(TVariable) + SizeOf(TIsppVariant) * (Length - 1));
- V.Name := Name;
- V.Hash := MakeHash(Name);
- V.IdentType := itVariable;
- V.Dim := Length;
- V^.Scope.IsProtected := Scope = dsProtected;
- if Scope >= dsProtected then V^.Scope.LocalLevel := FLocalLevel;
- if ReDimIndex = -1 then begin
- Delete(Name, Scope);
- for I := 0 to Length - 1 do
- V.Value[I] := NULL;
- FVarMan.Add(V);
- Msg := SArrayDeclared;
- end else begin
- VOld := PVariable(FVarMan[ReDimIndex]);
- for I := 0 to VOld.Dim - 1 do
- if I < Length then
- V.Value[I] := VOld.Value[I];
- for I := VOld.Dim to Length - 1 do
- V.Value[I] := NULL;
- FVarMan[ReDimIndex] := V;
- FreeItem(VOld);
- Msg := SArrayReDimmed;
- end;
- VerboseMsg(4, Msg, [GL[Scope], Name]);
- end else
- raise EIdentError.Create(SBadLength);
- end;
- function TIdentManager.FindIndex(const Name: string; AScope: TDefineScope): Integer;
- begin
- Result := -1;
- var H := MakeHash(Name);
- for var I := FVarMan.Count - 1 downto 0 do
- if (H = PIdent(FVarMan[I]).Hash) and (
- CompareText(PIdent(FVarMan[I]).Name, Name) = 0) then
- begin
- if (PIdent(FVarMan[I]).IdentType in [itVariable, itMacro]) then
- with PDefinable(FVarMan[I])^.Scope do
- case AScope of
- dsAny:
- if not ((LocalLevel = 0) or (LocalLevel = FLocalLevel) or IsProtected) then Continue;
- dsPublic:
- if LocalLevel <> 0 then Continue;
- dsProtected:
- if not (IsProtected and (LocalLevel <= FLocalLevel)) then Continue;
- else
- if IsProtected or (LocalLevel <> FLocalLevel) then Continue;
- end;
- Result := Integer(I);
- Exit
- end;
- end;
- function TIdentManager.Find(const Name: string; AScope: TDefineScope): PIdent;
- var
- I: Integer;
- begin
- I := FindIndex(Name, AScope);
- if I >= 0 then
- Result := FVarMan[I]
- else
- Result := nil;
- end;
- function TIdentManager.GetIdent(const Name: string;
- out CallContext: ICallContext): TIdentType;
- var
- P: PIdent;
- begin
- if CompareText(Name, 'DEFINED') = 0 then
- Result := itDefinedFunc
- else if CompareText(Name, 'TYPEOF') = 0 then
- Result := itTypeOfFunc
- else if CompareText(Name, 'DIMOF') = 0 then
- Result := itDimOfFunc
- else
- begin
- P := Find(Name, dsAny);
- if P <> nil then
- begin
- Result := P.IdentType;
- case P.IdentType of
- itVariable: CallContext := TVarCallContext.Create(PVariable(P));
- itMacro: CallContext := TMacroCallContext.Create(MacroIdents, PMacro(P));
- itFunc: CallContext := TFuncCallContext.Create(FFuncSender, PFunc(P));
- else
- Assert(False)
- end;
- end
- else
- Result := itUnknown;
- end;
- end;
- function TIdentManager.QueryInterface(const IID: TGUID; out Obj): HRESULT;
- begin
- if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE;
- end;
- function TIdentManager.TypeOf(const Name: string): Byte;
- var
- P: PIdent;
- begin
- Result := TYPE_ERROR;
- P := Find(Name, dsAny);
- if P <> nil then
- case P.IdentType of
- itVariable:
- if PVariable(P).Dim > 0 then
- Result := TYPE_ARRAY
- else
- case PVariable(P).Value[0].Typ of
- evNull: Result := TYPE_NULL;
- evInt: Result := TYPE_INTEGER;
- evStr: Result := TYPE_STRING
- end;
- itMacro: Result := TYPE_MACRO;
- itFunc: Result := TYPE_FUNC
- end
- end;
- function TIdentManager._AddRef: Integer;
- begin
- Result := InterlockedIncrement(FRefCount)
- end;
- function TIdentManager._Release: Integer;
- begin
- Result := InterlockedDecrement(FRefCount);
- if Result = 0 then
- Destroy;
- end;
- procedure TIdentManager.BeginLocal;
- begin
- Inc(FLocalLevel);
- end;
- procedure TIdentManager.EndLocal;
- begin
- for var I := FVarMan.Count - 1 downto 0 do
- if (PIdent(FVarMan.Items[I]).IdentType in [itVariable, itMacro]) and
- (PDefinable(FVarMan.Items[I]).Scope.LocalLevel = FLocalLevel) then
- begin
- FreeItem(FVarMan[I]);
- FVarMan.Delete(I);
- end;
- Dec(FLocalLevel);
- end;
- procedure TIdentManager.FreeItem(Item: Pointer);
- function ZeroToOne(A: Integer): Integer;
- begin
- if A = 0 then Result := 1 else Result := A
- end;
- begin
- with PIdent(Item)^ do
- begin
- Finalize(Name);
- case IdentType of
- itVariable: with PVariable(Item)^ do Finalize(Value[0], ZeroToOne(Dim));
- itMacro:
- with PMacro(Item)^ do
- begin
- Finalize(Params[0], ParamCount);
- Finalize(Expression);
- end;
- end;
- end;
- FreeMem(Item);
- end;
- function TIdentManager.MacroIdents: IIdentManager;
- begin
- if FCustomIdents <> nil then
- Result := FCustomIdents
- else
- Result := Self
- end;
- procedure TMacroCallContext.AdjustLocalArray(Index: Integer);
- var
- V: PIsppVariant;
- begin
- if not Assigned(FLocalVars) then
- FLocalVars := TList.Create;
- if FLocalVars.Count > Index then Exit;
- VerboseMsg(10, SAllocatingMacroLocalArrayUpToEle, [FMacro.Name, Index]);
- for var I := FLocalVars.Count to Index do begin
- New(V);
- V.Typ := evNull;
- FLocalVars.Add(V);
- end;
- end;
- procedure TVarCallContext.Clone(out NewContext: ICallContext);
- begin
- if FVariable.Dim = 0 then
- NewContext := Self
- else
- NewContext := TVarCallContext.Create(FVariable);
- end;
- procedure TMacroLocalArrayCallContext.Clone(out NewContext: ICallContext);
- begin
- NewContext := TMacroLocalArrayCallContext.Create(FMacroContext);
- end;
- procedure TMacroCallContext.Clone(out NewContext: ICallContext);
- begin
- NewContext := TMacroCallContext.Create(FIdentManager, FMacro);
- end;
- procedure TFuncCallContext.Clone(out NewContext: ICallContext);
- begin
- NewContext := TFuncCallContext.Create(FSender, FFunc);
- end;
- function TIdentManager.DimOf(const Name: String): Integer;
- var
- Ident: PIdent;
- begin
- Ident := Find(Name, dsAny);
- if Assigned(Ident) and (Ident.IdentType = itVariable) then
- Result := PVariable(Ident)^.Dim
- else
- Result := 0;
- end;
- function TMacroCallContext.DimOf(const Name: string): Integer;
- begin
- if CompareText(Name, SLocal) = 0 then
- Result := MaxLocalArraySize
- else
- Result := FIdentManager.DimOf(Name);
- end;
- end.
|