mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 07:19:22 +02:00
codetools: cfg parser: typecasts
git-svn-id: trunk@26966 -
This commit is contained in:
parent
317f836fa3
commit
121d88afc3
@ -25,12 +25,16 @@
|
|||||||
programs.
|
programs.
|
||||||
|
|
||||||
Working:
|
Working:
|
||||||
if, then, else, begin..end, ;, (), not, and, or, xor, =, <>, >, <, <=, >=,
|
if, then, else, begin..end, ;
|
||||||
:=, defined(), variable,
|
()
|
||||||
|
boolean operators: not, and, or, xor
|
||||||
|
operators: =, <>, >, <, <=, >=, :=,
|
||||||
|
variables
|
||||||
constants: decimal, hex, octal, binary, string, #decimal
|
constants: decimal, hex, octal, binary, string, #decimal
|
||||||
|
functions: string(), integer(), int64(), defined(), undefined()
|
||||||
|
procedures: undefine()
|
||||||
ToDo:
|
ToDo:
|
||||||
+=, string(), integer(), int64(), shl, shr, div, mod, *, +, -
|
+=, +
|
||||||
+, - as unary operator
|
|
||||||
}
|
}
|
||||||
unit CodeToolsCfgScript;
|
unit CodeToolsCfgScript;
|
||||||
|
|
||||||
@ -78,6 +82,8 @@ type
|
|||||||
function GetVariable(const Name: PChar;
|
function GetVariable(const Name: PChar;
|
||||||
CreateIfNotExists: Boolean = false): PCTCfgScriptVariable;
|
CreateIfNotExists: Boolean = false): PCTCfgScriptVariable;
|
||||||
property Values[const Name: string]: string read GetValues write SetValues; default;
|
property Values[const Name: string]: string read GetValues write SetValues; default;
|
||||||
|
procedure Undefine(Name: PChar);
|
||||||
|
procedure Define(Name: PChar; const Value: string);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -164,6 +170,8 @@ type
|
|||||||
procedure Push(Typ: TCTCfgScriptStackItemType; const StartPos: PChar);
|
procedure Push(Typ: TCTCfgScriptStackItemType; const StartPos: PChar);
|
||||||
procedure Pop(Count: integer = 1);
|
procedure Pop(Count: integer = 1);
|
||||||
procedure Delete(Index: integer);
|
procedure Delete(Index: integer);
|
||||||
|
function TopItem: PCTCfgScriptStackItem;
|
||||||
|
function TopItemOperand: PCTCfgScriptVariable;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TCTCfgScriptError }
|
{ TCTCfgScriptError }
|
||||||
@ -189,15 +197,18 @@ type
|
|||||||
procedure PushBooleanValue(b: boolean);
|
procedure PushBooleanValue(b: boolean);
|
||||||
procedure PushNumberValue(const Number: int64);
|
procedure PushNumberValue(const Number: int64);
|
||||||
function RunDefined(Negate: boolean): boolean;
|
function RunDefined(Negate: boolean): boolean;
|
||||||
|
function RunFunction: boolean;
|
||||||
procedure PushStringConstant;
|
procedure PushStringConstant;
|
||||||
procedure RunStatement(Skip: boolean);
|
procedure RunStatement(Skip: boolean);
|
||||||
procedure RunBegin(Skip: boolean);
|
procedure RunBegin(Skip: boolean);
|
||||||
procedure RunIf(Skip: boolean);
|
procedure RunIf(Skip: boolean);
|
||||||
|
procedure RunUndefine(Skip: boolean);
|
||||||
procedure RunAssignment(Skip: boolean);
|
procedure RunAssignment(Skip: boolean);
|
||||||
function RunExpression(var Value: TCTCfgScriptVariable): boolean;
|
function RunExpression: boolean; // if true the stack top has an operand
|
||||||
function AtomIsKeyWord: boolean;
|
|
||||||
function ExecuteStack(MaxLevel: integer): boolean;
|
function ExecuteStack(MaxLevel: integer): boolean;
|
||||||
function GetOperatorLevel(P: PChar): integer;
|
function GetOperatorLevel(P: PChar): integer;
|
||||||
|
function IsKeyWord(P: PChar): boolean;
|
||||||
|
function IsFunction(P: PChar): boolean;
|
||||||
public
|
public
|
||||||
Src: PChar;
|
Src: PChar;
|
||||||
AtomStart: PChar;
|
AtomStart: PChar;
|
||||||
@ -235,11 +246,15 @@ procedure SetCTCSVariableAsString(const V: PCTCfgScriptVariable; const s: string
|
|||||||
procedure SetCTCSVariableAsNumber(const V: PCTCfgScriptVariable; const i: int64);
|
procedure SetCTCSVariableAsNumber(const V: PCTCfgScriptVariable; const i: int64);
|
||||||
procedure SetCTCSVariableValue(const Src, Dest: PCTCfgScriptVariable);
|
procedure SetCTCSVariableValue(const Src, Dest: PCTCfgScriptVariable);
|
||||||
function GetCTCSVariableAsString(const V: PCTCfgScriptVariable): string;
|
function GetCTCSVariableAsString(const V: PCTCfgScriptVariable): string;
|
||||||
|
procedure MakeCTCSVariableString(const V: PCTCfgScriptVariable);
|
||||||
|
procedure MakeCTCSVariableInt64(const V: PCTCfgScriptVariable);
|
||||||
|
procedure MakeCTCSVariableInteger(const V: PCTCfgScriptVariable);
|
||||||
|
procedure AddCTCSVariables(const SumVar, AddVar: PCTCfgScriptVariable);
|
||||||
function CTCSNumberEqualsString(const Number: int64; const P: PChar): boolean; inline;
|
function CTCSNumberEqualsString(const Number: int64; const P: PChar): boolean; inline;
|
||||||
function CTCSStringToNumber(P: PChar; out Number: int64): boolean;
|
|
||||||
function CTCSVariableIsTrue(const V: PCTCfgScriptVariable): boolean; inline;
|
function CTCSVariableIsTrue(const V: PCTCfgScriptVariable): boolean; inline;
|
||||||
function CTCSVariableIsFalse(const V: PCTCfgScriptVariable): boolean;
|
function CTCSVariableIsFalse(const V: PCTCfgScriptVariable): boolean;
|
||||||
|
|
||||||
|
function CTCSStringToNumber(P: PChar; out Number: int64): boolean;
|
||||||
function AtomToCTCfgOperator(p: PChar): TCTCfgScriptOperator;
|
function AtomToCTCfgOperator(p: PChar): TCTCfgScriptOperator;
|
||||||
|
|
||||||
function dbgs(const t: TCTCfgScriptStackItemType): string; overload;
|
function dbgs(const t: TCTCfgScriptStackItemType): string; overload;
|
||||||
@ -528,6 +543,74 @@ begin
|
|||||||
V^.ValueType:=ctcsvNone;
|
V^.ValueType:=ctcsvNone;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure MakeCTCSVariableString(const V: PCTCfgScriptVariable);
|
||||||
|
var
|
||||||
|
s: String;
|
||||||
|
begin
|
||||||
|
case V^.ValueType of
|
||||||
|
ctcsvNone:
|
||||||
|
begin
|
||||||
|
V^.StrLen:=0;
|
||||||
|
V^.StrStart:=nil;
|
||||||
|
V^.ValueType:=ctcsvString;
|
||||||
|
end;
|
||||||
|
ctcsvString: ;
|
||||||
|
ctcsvNumber:
|
||||||
|
begin
|
||||||
|
s:=IntToStr(V^.Number);
|
||||||
|
V^.StrLen:=length(s);
|
||||||
|
V^.StrStart:= GetMem(length(s)+1);
|
||||||
|
System.Move(s[1],V^.StrStart^,length(s)+1);
|
||||||
|
V^.ValueType:=ctcsvString;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure MakeCTCSVariableInt64(const V: PCTCfgScriptVariable);
|
||||||
|
var
|
||||||
|
i: Int64;
|
||||||
|
begin
|
||||||
|
case V^.ValueType of
|
||||||
|
ctcsvNone:
|
||||||
|
begin
|
||||||
|
V^.Number:=0;
|
||||||
|
V^.ValueType:=ctcsvNumber;
|
||||||
|
end;
|
||||||
|
ctcsvString:
|
||||||
|
begin
|
||||||
|
i:=StrToInt64Def(V^.StrStart,0);
|
||||||
|
V^.Number:=i;
|
||||||
|
V^.ValueType:=ctcsvNumber;
|
||||||
|
end;
|
||||||
|
ctcsvNumber: ;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure MakeCTCSVariableInteger(const V: PCTCfgScriptVariable);
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
case V^.ValueType of
|
||||||
|
ctcsvNone:
|
||||||
|
begin
|
||||||
|
V^.Number:=0;
|
||||||
|
V^.ValueType:=ctcsvNumber;
|
||||||
|
end;
|
||||||
|
ctcsvString:
|
||||||
|
begin
|
||||||
|
i:=StrToIntDef(V^.StrStart,0);
|
||||||
|
V^.Number:=i;
|
||||||
|
V^.ValueType:=ctcsvNumber;
|
||||||
|
end;
|
||||||
|
ctcsvNumber: ;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure AddCTCSVariables(const SumVar, AddVar: PCTCfgScriptVariable);
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
function CTCSNumberEqualsString(const Number: int64; const P: PChar): boolean;
|
function CTCSNumberEqualsString(const Number: int64; const P: PChar): boolean;
|
||||||
var
|
var
|
||||||
n: int64;
|
n: int64;
|
||||||
@ -864,6 +947,36 @@ begin
|
|||||||
Result:=nil;
|
Result:=nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCTCfgScriptVariables.Undefine(Name: PChar);
|
||||||
|
var
|
||||||
|
Node: TAVLTreeNode;
|
||||||
|
Item: PCTCfgScriptVariable;
|
||||||
|
begin
|
||||||
|
Node:=FItems.FindKey(Name,@ComparePCharWithCTCSVariableName);
|
||||||
|
if Node=nil then exit;
|
||||||
|
Item:=PCTCfgScriptVariable(Node.Data);
|
||||||
|
FreeCTCSVariable(Item);
|
||||||
|
FItems.Delete(Node);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCTCfgScriptVariables.Define(Name: PChar; const Value: string);
|
||||||
|
var
|
||||||
|
V: PCTCfgScriptVariable;
|
||||||
|
i: Int64;
|
||||||
|
begin
|
||||||
|
V:=GetVariable(Name,true);
|
||||||
|
if Value='' then
|
||||||
|
ClearCTCSVariable(V)
|
||||||
|
else begin
|
||||||
|
try
|
||||||
|
i:=StrToInt64(Value);
|
||||||
|
SetCTCSVariableAsNumber(V,i);
|
||||||
|
except
|
||||||
|
SetCTCSVariableAsString(V,Value);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TCTConfigScriptEngine }
|
{ TCTConfigScriptEngine }
|
||||||
|
|
||||||
function TCTConfigScriptEngine.GetErrors(Index: integer): TCTCfgScriptError;
|
function TCTConfigScriptEngine.GetErrors(Index: integer): TCTCfgScriptError;
|
||||||
@ -899,40 +1012,51 @@ procedure TCTConfigScriptEngine.RunStatement(Skip: boolean);
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
IsKeyword: Boolean;
|
Handled: Boolean;
|
||||||
|
StartTop: LongInt;
|
||||||
begin
|
begin
|
||||||
debugln(['TCTConfigScriptEngine.ParseStatement Atom=',GetAtom]);
|
debugln(['TCTConfigScriptEngine.ParseStatement Atom=',GetAtom]);
|
||||||
|
StartTop:=FStack.Top;
|
||||||
case AtomStart^ of
|
case AtomStart^ of
|
||||||
#0: ;
|
#0: ;
|
||||||
';': ; // empty statement
|
';': ; // empty statement
|
||||||
'a'..'z','A'..'Z':
|
'a'..'z','A'..'Z':
|
||||||
begin
|
begin
|
||||||
// identifier or keyword
|
// identifier or keyword
|
||||||
IsKeyword:=false;
|
Handled:=false;
|
||||||
case UpChars[AtomStart^] of
|
case UpChars[AtomStart^] of
|
||||||
'B':
|
'B':
|
||||||
if CompareIdentifiers('BEGIN',AtomStart)=0 then begin
|
if CompareIdentifiers('BEGIN',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
RunBegin(Skip);
|
RunBegin(Skip);
|
||||||
end;
|
end;
|
||||||
'I':
|
'I':
|
||||||
if CompareIdentifiers('IF',AtomStart)=0 then begin
|
if CompareIdentifiers('IF',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
RunIf(Skip);
|
RunIf(Skip);
|
||||||
end;
|
end;
|
||||||
|
'U':
|
||||||
|
if CompareIdentifiers('Undefine',AtomStart)=0 then begin
|
||||||
|
Handled:=true;
|
||||||
|
RunUndefine(Skip);
|
||||||
end;
|
end;
|
||||||
if (not IsKeyword) and AtomIsKeyWord then begin
|
end;
|
||||||
|
if (not Handled) then begin
|
||||||
|
if IsKeyWord(AtomStart) then begin
|
||||||
AddError('unexpected keyword '+GetAtom);
|
AddError('unexpected keyword '+GetAtom);
|
||||||
exit;
|
end else if IsFunction(AtomStart) then begin
|
||||||
end;
|
if not RunFunction then exit;
|
||||||
if not IsKeyword then begin
|
end else begin
|
||||||
// parse assignment
|
// parse assignment
|
||||||
RunAssignment(Skip);
|
RunAssignment(Skip);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
else
|
else
|
||||||
ErrorUnexpectedAtom;
|
ErrorUnexpectedAtom;
|
||||||
end;
|
end;
|
||||||
|
// clean up stack
|
||||||
|
while FStack.Top>StartTop do FStack.Pop;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCTConfigScriptEngine.RunBegin(Skip: boolean);
|
procedure TCTConfigScriptEngine.RunBegin(Skip: boolean);
|
||||||
@ -977,7 +1101,6 @@ procedure TCTConfigScriptEngine.RunIf(Skip: boolean);
|
|||||||
}
|
}
|
||||||
var
|
var
|
||||||
IfStart: PChar;
|
IfStart: PChar;
|
||||||
Value: TCTCfgScriptVariable;
|
|
||||||
ExprIsTrue: Boolean;
|
ExprIsTrue: Boolean;
|
||||||
StartTop: LongInt;
|
StartTop: LongInt;
|
||||||
begin
|
begin
|
||||||
@ -985,8 +1108,11 @@ begin
|
|||||||
StartTop:=FStack.Top;
|
StartTop:=FStack.Top;
|
||||||
FStack.Push(ctcssIf,IfStart);
|
FStack.Push(ctcssIf,IfStart);
|
||||||
ReadRawNextPascalAtom(Src,AtomStart);
|
ReadRawNextPascalAtom(Src,AtomStart);
|
||||||
FillByte(Value,SizeOf(Value),0);
|
ExprIsTrue:=false;
|
||||||
ExprIsTrue:=RunExpression(Value) and CTCSVariableIsTrue(@Value);
|
if RunExpression then begin
|
||||||
|
ExprIsTrue:=CTCSVariableIsTrue(FStack.TopItemOperand);
|
||||||
|
FStack.Pop;
|
||||||
|
end;
|
||||||
debugln(['TCTConfigScriptEngine.RunIf expression=',ExprIsTrue]);
|
debugln(['TCTConfigScriptEngine.RunIf expression=',ExprIsTrue]);
|
||||||
|
|
||||||
// read then
|
// read then
|
||||||
@ -1004,14 +1130,35 @@ begin
|
|||||||
while FStack.Top>StartTop do FStack.Pop;
|
while FStack.Top>StartTop do FStack.Pop;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCTConfigScriptEngine.RunUndefine(Skip: boolean);
|
||||||
|
var
|
||||||
|
VarStart: PChar;
|
||||||
|
begin
|
||||||
|
ReadRawNextPascalAtom(Src,AtomStart);
|
||||||
|
if AtomStart^<>'(' then begin
|
||||||
|
AddError('expected (, but found '+GetAtomOrNothing);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
ReadRawNextPascalAtom(Src,AtomStart);
|
||||||
|
if (not IsIdentStartChar[AtomStart^]) or IsKeyWord(AtomStart) then begin
|
||||||
|
AddError('expected identifier, but found '+GetAtomOrNothing);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
VarStart:=AtomStart;
|
||||||
|
ReadRawNextPascalAtom(Src,AtomStart);
|
||||||
|
if AtomStart^<>')' then begin
|
||||||
|
AddError('expected ), but found '+GetAtomOrNothing);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
Variables.Undefine(VarStart);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCTConfigScriptEngine.RunAssignment(Skip: boolean);
|
procedure TCTConfigScriptEngine.RunAssignment(Skip: boolean);
|
||||||
{ Examples:
|
{ Examples:
|
||||||
a:=3;
|
a:=3;
|
||||||
}
|
}
|
||||||
var
|
var
|
||||||
VarStart: PChar;
|
VarStart: PChar;
|
||||||
OperatorStart: PChar;
|
|
||||||
Value: TCTCfgScriptVariable;
|
|
||||||
Variable: PCTCfgScriptVariable;
|
Variable: PCTCfgScriptVariable;
|
||||||
StartTop: TCTCfgScriptStackItemType;
|
StartTop: TCTCfgScriptStackItemType;
|
||||||
begin
|
begin
|
||||||
@ -1021,7 +1168,6 @@ begin
|
|||||||
FStack.Push(ctcssAssignment,VarStart);
|
FStack.Push(ctcssAssignment,VarStart);
|
||||||
ReadRawNextPascalAtom(Src,AtomStart);
|
ReadRawNextPascalAtom(Src,AtomStart);
|
||||||
debugln(['TCTConfigScriptEngine.RunAssignment Operator=',GetAtom]);
|
debugln(['TCTConfigScriptEngine.RunAssignment Operator=',GetAtom]);
|
||||||
OperatorStart:=AtomStart;
|
|
||||||
// read :=
|
// read :=
|
||||||
if AtomStart^=#0 then begin
|
if AtomStart^=#0 then begin
|
||||||
AddError('missing :=');
|
AddError('missing :=');
|
||||||
@ -1033,13 +1179,10 @@ begin
|
|||||||
end;
|
end;
|
||||||
// read expression
|
// read expression
|
||||||
ReadRawNextPascalAtom(Src,AtomStart);
|
ReadRawNextPascalAtom(Src,AtomStart);
|
||||||
FillByte(Value,SizeOf(Value),0);
|
if RunExpression and (not Skip) then begin
|
||||||
RunExpression(Value);
|
|
||||||
if (not Skip) then begin
|
|
||||||
Variable:=Variables.GetVariable(VarStart,true);
|
Variable:=Variables.GetVariable(VarStart,true);
|
||||||
debugln(['TCTConfigScriptEngine.RunAssignment ',GetIdentifier(VarStart),'=(Old=',dbgs(Variable),') := ',dbgs(PCTCfgScriptVariable(@Value))]);
|
debugln(['TCTConfigScriptEngine.RunAssignment ',GetIdentifier(VarStart),'=(Old=',dbgs(Variable),') := ',dbgs(FStack.TopItemOperand)]);
|
||||||
if OperatorStart=nil then ;
|
SetCTCSVariableValue(FStack.TopItemOperand,Variable);
|
||||||
SetCTCSVariableValue(@Value,Variable);
|
|
||||||
debugln(['TCTConfigScriptEngine.RunAssignment ',GetIdentifier(VarStart),' = ',dbgs(Variable)]);
|
debugln(['TCTConfigScriptEngine.RunAssignment ',GetIdentifier(VarStart),' = ',dbgs(Variable)]);
|
||||||
end;
|
end;
|
||||||
// clean up stack
|
// clean up stack
|
||||||
@ -1048,12 +1191,12 @@ end;
|
|||||||
|
|
||||||
procedure TCTConfigScriptEngine.PushNumberValue(const Number: int64);
|
procedure TCTConfigScriptEngine.PushNumberValue(const Number: int64);
|
||||||
var
|
var
|
||||||
Item: PCTCfgScriptStackItem;
|
Operand: PCTCfgScriptVariable;
|
||||||
begin
|
begin
|
||||||
FStack.Push(ctcssOperand,AtomStart);
|
FStack.Push(ctcssOperand,AtomStart);
|
||||||
Item:=@FStack.Items[FStack.Top];
|
Operand:=FStack.TopItemOperand;
|
||||||
Item^.Operand.ValueType:=ctcsvNumber;
|
Operand^.ValueType:=ctcsvNumber;
|
||||||
Item^.Operand.Number:=Number;
|
Operand^.Number:=Number;
|
||||||
ExecuteStack(1);
|
ExecuteStack(1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1069,14 +1212,14 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
ReadRawNextPascalAtom(Src,AtomStart);
|
ReadRawNextPascalAtom(Src,AtomStart);
|
||||||
if (not IsIdentStartChar[AtomStart^]) or AtomIsKeyWord then begin
|
if (not IsIdentStartChar[AtomStart^]) or IsKeyWord(AtomStart) then begin
|
||||||
AddError('expected identifier, but found '+GetAtomOrNothing);
|
AddError('expected identifier, but found '+GetAtomOrNothing);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
VarStart:=AtomStart;
|
VarStart:=AtomStart;
|
||||||
ReadRawNextPascalAtom(Src,AtomStart);
|
ReadRawNextPascalAtom(Src,AtomStart);
|
||||||
if AtomStart^<>')' then begin
|
if AtomStart^<>')' then begin
|
||||||
AddError('expected (, but found '+GetAtomOrNothing);
|
AddError('expected ), but found '+GetAtomOrNothing);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
b:=Variables.GetVariable(VarStart)<>nil;
|
b:=Variables.GetVariable(VarStart)<>nil;
|
||||||
@ -1085,9 +1228,58 @@ begin
|
|||||||
Result:=true;
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCTConfigScriptEngine.RunFunction: boolean;
|
||||||
|
var
|
||||||
|
StartTop: LongInt;
|
||||||
|
Value: TCTCfgScriptVariable;
|
||||||
|
FunctionName: PChar;
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
FunctionName:=AtomStart;
|
||||||
|
StartTop:=FStack.Top;
|
||||||
|
ReadRawNextPascalAtom(Src,AtomStart);
|
||||||
|
if AtomStart^<>'(' then begin
|
||||||
|
AddError('expected (, but found '+GetAtomOrNothing);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
ReadRawNextPascalAtom(Src,AtomStart);
|
||||||
|
|
||||||
|
FStack.Push(ctcssRoundBracketOpen,AtomStart);
|
||||||
|
FillByte(Value,SizeOf(Value),0);
|
||||||
|
if RunExpression then
|
||||||
|
SetCTCSVariableValue(FStack.TopItemOperand,@Value);
|
||||||
|
if AtomStart^<>')' then begin
|
||||||
|
AddError('expected ), but found '+GetAtomOrNothing);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// clean up stack
|
||||||
|
while FStack.Top>StartTop do FStack.Pop;
|
||||||
|
|
||||||
|
// execute function
|
||||||
|
debugln(['TCTConfigScriptEngine.RunFunction FunctionName="',GetAtom(FunctionName),'" Parameter=',dbgs(PCTCfgScriptVariable(@Value))]);
|
||||||
|
case UpChars[FunctionName^] of
|
||||||
|
'I':
|
||||||
|
if CompareIdentifiers(FunctionName,'int64')=0 then
|
||||||
|
MakeCTCSVariableInt64(@Value)
|
||||||
|
else if CompareIdentifiers(FunctionName,'integer')=0 then
|
||||||
|
MakeCTCSVariableInteger(@Value);
|
||||||
|
'S':
|
||||||
|
if CompareIdentifiers(FunctionName,'string')=0 then
|
||||||
|
MakeCTCSVariableString(@Value);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// put result on stack as operand
|
||||||
|
debugln(['TCTConfigScriptEngine.RunFunction FunctionName="',GetAtom(FunctionName),'" Result=',dbgs(PCTCfgScriptVariable(@Value))]);
|
||||||
|
FStack.Push(ctcssOperand,FunctionName);
|
||||||
|
SetCTCSVariableValue(@Value,FStack.TopItemOperand);
|
||||||
|
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCTConfigScriptEngine.PushStringConstant;
|
procedure TCTConfigScriptEngine.PushStringConstant;
|
||||||
var
|
var
|
||||||
Item: PCTCfgScriptStackItem;
|
Operand: PCTCfgScriptVariable;
|
||||||
|
|
||||||
procedure Add(p: PChar; Count: integer);
|
procedure Add(p: PChar; Count: integer);
|
||||||
var
|
var
|
||||||
@ -1095,11 +1287,11 @@ var
|
|||||||
NewLen: Integer;
|
NewLen: Integer;
|
||||||
begin
|
begin
|
||||||
if Count=0 then exit;
|
if Count=0 then exit;
|
||||||
OldLen:=Item^.Operand.StrLen;
|
OldLen:=Operand^.StrLen;
|
||||||
NewLen:=OldLen+Count;
|
NewLen:=OldLen+Count;
|
||||||
ReAllocMem(Item^.Operand.StrStart,NewLen);
|
ReAllocMem(Operand^.StrStart,NewLen);
|
||||||
System.Move(p^,Item^.Operand.StrStart[OldLen],Count);
|
System.Move(p^,Operand^.StrStart[OldLen],Count);
|
||||||
Item^.Operand.StrLen:=NewLen;
|
Operand^.StrLen:=NewLen;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
@ -1109,10 +1301,10 @@ var
|
|||||||
c: char;
|
c: char;
|
||||||
begin
|
begin
|
||||||
FStack.Push(ctcssOperand,AtomStart);
|
FStack.Push(ctcssOperand,AtomStart);
|
||||||
Item:=@FStack.Items[FStack.Top];
|
Operand:=FStack.TopItemOperand;
|
||||||
Item^.Operand.ValueType:=ctcsvString;
|
Operand^.ValueType:=ctcsvString;
|
||||||
Item^.Operand.StrLen:=0;
|
Operand^.StrLen:=0;
|
||||||
Item^.Operand.StrStart:=nil;
|
Operand^.StrStart:=nil;
|
||||||
p:=AtomStart;
|
p:=AtomStart;
|
||||||
while true do begin
|
while true do begin
|
||||||
case p^ of
|
case p^ of
|
||||||
@ -1161,7 +1353,7 @@ var
|
|||||||
c: Char;
|
c: Char;
|
||||||
begin
|
begin
|
||||||
FStack.Push(ctcssOperand,AtomStart);
|
FStack.Push(ctcssOperand,AtomStart);
|
||||||
Item:=@FStack.Items[FStack.Top];
|
Item:=FStack.TopItem;
|
||||||
p:=AtomStart;
|
p:=AtomStart;
|
||||||
c:=p^;
|
c:=p^;
|
||||||
if not (c in ['0'..'9']) then inc(p);
|
if not (c in ['0'..'9']) then inc(p);
|
||||||
@ -1188,6 +1380,7 @@ begin
|
|||||||
else break;
|
else break;
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
|
// decimal or float
|
||||||
case p^ of
|
case p^ of
|
||||||
'0'..'9': Number:=Number*10+ord(p^)-ord('0');
|
'0'..'9': Number:=Number*10+ord(p^)-ord('0');
|
||||||
else break;
|
else break;
|
||||||
@ -1215,20 +1408,19 @@ end;
|
|||||||
|
|
||||||
procedure TCTConfigScriptEngine.PushBooleanValue(b: boolean);
|
procedure TCTConfigScriptEngine.PushBooleanValue(b: boolean);
|
||||||
var
|
var
|
||||||
Item: PCTCfgScriptStackItem;
|
Operand: PCTCfgScriptVariable;
|
||||||
begin
|
begin
|
||||||
FStack.Push(ctcssOperand,AtomStart);
|
FStack.Push(ctcssOperand,AtomStart);
|
||||||
Item:=@FStack.Items[FStack.Top];
|
Operand:=FStack.TopItemOperand;
|
||||||
Item^.Operand.ValueType:=ctcsvNumber;
|
Operand^.ValueType:=ctcsvNumber;
|
||||||
if b then
|
if b then
|
||||||
Item^.Operand.Number:=1
|
Operand^.Number:=1
|
||||||
else
|
else
|
||||||
Item^.Operand.Number:=0;
|
Operand^.Number:=0;
|
||||||
ExecuteStack(1);
|
ExecuteStack(1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCTConfigScriptEngine.RunExpression(var Value: TCTCfgScriptVariable
|
function TCTConfigScriptEngine.RunExpression: boolean;
|
||||||
): boolean;
|
|
||||||
{ Examples:
|
{ Examples:
|
||||||
A is false if A=0 or A='0'
|
A is false if A=0 or A='0'
|
||||||
defined(A)
|
defined(A)
|
||||||
@ -1238,11 +1430,6 @@ function TCTConfigScriptEngine.RunExpression(var Value: TCTCfgScriptVariable
|
|||||||
binary operators:
|
binary operators:
|
||||||
|
|
||||||
}
|
}
|
||||||
procedure ErrorUnexpectedRoundBracketClose;
|
|
||||||
begin
|
|
||||||
AddError('expression expected, but ) found');
|
|
||||||
end;
|
|
||||||
|
|
||||||
function OperandAllowed: boolean;
|
function OperandAllowed: boolean;
|
||||||
begin
|
begin
|
||||||
case FStack.TopTyp of
|
case FStack.TopTyp of
|
||||||
@ -1270,14 +1457,17 @@ function TCTConfigScriptEngine.RunExpression(var Value: TCTCfgScriptVariable
|
|||||||
function PushBinaryOperator: boolean;
|
function PushBinaryOperator: boolean;
|
||||||
begin
|
begin
|
||||||
Result:=BinaryOperatorAllowed;
|
Result:=BinaryOperatorAllowed;
|
||||||
if not Result then exit;
|
if not Result then begin
|
||||||
|
RunExpression:=false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
ExecuteStack(GetOperatorLevel(AtomStart));
|
ExecuteStack(GetOperatorLevel(AtomStart));
|
||||||
FStack.Push(ctcssOperator,AtomStart);
|
FStack.Push(ctcssOperator,AtomStart);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
ExprStart: PChar;
|
ExprStart: PChar;
|
||||||
IsKeyword: Boolean;
|
Handled: Boolean;
|
||||||
Item: PCTCfgScriptStackItem;
|
Item: PCTCfgScriptStackItem;
|
||||||
StartTop: LongInt;
|
StartTop: LongInt;
|
||||||
v: PCTCfgScriptVariable;
|
v: PCTCfgScriptVariable;
|
||||||
@ -1300,16 +1490,18 @@ begin
|
|||||||
begin
|
begin
|
||||||
ExecuteStack(5);
|
ExecuteStack(5);
|
||||||
if FStack.TopTyp=ctcssRoundBracketOpen then begin
|
if FStack.TopTyp=ctcssRoundBracketOpen then begin
|
||||||
|
// empty ()
|
||||||
AddError('operand expected, but '+GetAtom+' found');
|
AddError('operand expected, but '+GetAtom+' found');
|
||||||
|
Result:=false;
|
||||||
|
break;
|
||||||
end else if (FStack.TopTyp=ctcssOperand)
|
end else if (FStack.TopTyp=ctcssOperand)
|
||||||
and (FStack.Top>0) and (FStack.Items[FStack.Top-1].Typ=ctcssRoundBracketOpen)
|
and (FStack.Top>0) and (FStack.Items[FStack.Top-1].Typ=ctcssRoundBracketOpen)
|
||||||
then begin
|
then begin
|
||||||
WriteDebugReportStack('AAA1');
|
WriteDebugReportStack('AAA1');
|
||||||
FStack.Delete(FStack.Top-1);
|
FStack.Delete(FStack.Top-1);
|
||||||
WriteDebugReportStack('AAA2');
|
WriteDebugReportStack('AAA2');
|
||||||
end
|
end else
|
||||||
else
|
break;
|
||||||
ErrorUnexpectedRoundBracketClose;
|
|
||||||
end;
|
end;
|
||||||
'=':
|
'=':
|
||||||
if not PushBinaryOperator then break;
|
if not PushBinaryOperator then break;
|
||||||
@ -1318,12 +1510,24 @@ begin
|
|||||||
if not PushBinaryOperator then break;
|
if not PushBinaryOperator then break;
|
||||||
end else begin
|
end else begin
|
||||||
AddError('invalid operator '+GetAtom);
|
AddError('invalid operator '+GetAtom);
|
||||||
|
Result:=false;
|
||||||
|
break;
|
||||||
end;
|
end;
|
||||||
'>':
|
'>':
|
||||||
if (Src-AtomStart=1) or (AtomStart[1] in ['=']) then begin
|
if (Src-AtomStart=1) or (AtomStart[1] in ['=']) then begin
|
||||||
if not PushBinaryOperator then break;
|
if not PushBinaryOperator then break;
|
||||||
end else begin
|
end else begin
|
||||||
AddError('invalid operator '+GetAtom);
|
AddError('invalid operator '+GetAtom);
|
||||||
|
Result:=false;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
'+':
|
||||||
|
if (Src-AtomStart=1) then begin
|
||||||
|
if not PushBinaryOperator then break;
|
||||||
|
end else begin
|
||||||
|
AddError('invalid operator '+GetAtom);
|
||||||
|
Result:=false;
|
||||||
|
break;
|
||||||
end;
|
end;
|
||||||
'a'..'z','A'..'Z':
|
'a'..'z','A'..'Z':
|
||||||
begin
|
begin
|
||||||
@ -1331,24 +1535,24 @@ begin
|
|||||||
|
|
||||||
debugln(['TCTConfigScriptEngine.RunExpression StackTop=',dbgs(FStack.TopTyp),' Atom=',GetAtom]);
|
debugln(['TCTConfigScriptEngine.RunExpression StackTop=',dbgs(FStack.TopTyp),' Atom=',GetAtom]);
|
||||||
// execute
|
// execute
|
||||||
IsKeyword:=false;
|
Handled:=false;
|
||||||
case UpChars[AtomStart^] of
|
case UpChars[AtomStart^] of
|
||||||
'A':
|
'A':
|
||||||
if CompareIdentifiers('and',AtomStart)=0 then begin
|
if CompareIdentifiers('and',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
if not PushBinaryOperator then break;
|
if not PushBinaryOperator then break;
|
||||||
end;
|
end;
|
||||||
'D':
|
'D':
|
||||||
case UpChars[AtomStart[1]] of
|
case UpChars[AtomStart[1]] of
|
||||||
'E':
|
'E':
|
||||||
if CompareIdentifiers('defined',AtomStart)=0 then begin
|
if CompareIdentifiers('defined',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
if not OperandAllowed then break;
|
if not OperandAllowed then break;
|
||||||
if not RunDefined(false) then break;
|
if not RunDefined(false) then break;
|
||||||
end;
|
end;
|
||||||
'I':
|
'I':
|
||||||
if CompareIdentifiers('div',AtomStart)=0 then begin
|
if CompareIdentifiers('div',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
if not PushBinaryOperator then break;
|
if not PushBinaryOperator then break;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1363,25 +1567,25 @@ begin
|
|||||||
end;
|
end;
|
||||||
'F':
|
'F':
|
||||||
if CompareIdentifiers('false',AtomStart)=0 then begin
|
if CompareIdentifiers('false',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
if not OperandAllowed then break;
|
if not OperandAllowed then break;
|
||||||
PushBooleanValue(false);
|
PushBooleanValue(false);
|
||||||
end;
|
end;
|
||||||
'M':
|
'M':
|
||||||
if CompareIdentifiers('mod',AtomStart)=0 then begin
|
if CompareIdentifiers('mod',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
if not PushBinaryOperator then break;
|
if not PushBinaryOperator then break;
|
||||||
end;
|
end;
|
||||||
'N':
|
'N':
|
||||||
if CompareIdentifiers('not',AtomStart)=0 then begin
|
if CompareIdentifiers('not',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
if not OperandAllowed then break;
|
if not OperandAllowed then break;
|
||||||
// Note: no execute, "not" is unary operator for the next operand
|
// Note: no execute, "not" is unary operator for the next operand
|
||||||
FStack.Push(ctcssOperator,AtomStart);
|
FStack.Push(ctcssOperator,AtomStart);
|
||||||
end;
|
end;
|
||||||
'O':
|
'O':
|
||||||
if CompareIdentifiers('or',AtomStart)=0 then begin
|
if CompareIdentifiers('or',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
if not PushBinaryOperator then break;
|
if not PushBinaryOperator then break;
|
||||||
end;
|
end;
|
||||||
'T':
|
'T':
|
||||||
@ -1392,36 +1596,46 @@ begin
|
|||||||
end;
|
end;
|
||||||
'R':
|
'R':
|
||||||
if CompareIdentifiers('true',AtomStart)=0 then begin
|
if CompareIdentifiers('true',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
if not OperandAllowed then break;
|
if not OperandAllowed then break;
|
||||||
PushBooleanValue(true);
|
PushBooleanValue(true);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
'U':
|
'U':
|
||||||
if CompareIdentifiers('undefined',AtomStart)=0 then begin
|
if CompareIdentifiers('undefined',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
if not OperandAllowed then break;
|
if not OperandAllowed then break;
|
||||||
if not RunDefined(true) then break;
|
if not RunDefined(true) then break;
|
||||||
end;
|
end;
|
||||||
'X':
|
'X':
|
||||||
if CompareIdentifiers('xor',AtomStart)=0 then begin
|
if CompareIdentifiers('xor',AtomStart)=0 then begin
|
||||||
IsKeyword:=true;
|
Handled:=true;
|
||||||
if not PushBinaryOperator then break;
|
if not PushBinaryOperator then break;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
if (not IsKeyword) and AtomIsKeyWord then begin
|
if (not Handled) and IsKeyWord(AtomStart) then begin
|
||||||
AddError('unexpected keyword '+GetAtom);
|
AddError('unexpected keyword '+GetAtom);
|
||||||
|
Result:=false;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
if not IsKeyword then begin
|
if (not Handled) then begin
|
||||||
// a variable
|
|
||||||
if not OperandAllowed then break;
|
if not OperandAllowed then break;
|
||||||
|
debugln(['TCTConfigScriptEngine.RunExpression ',GetAtom(AtomStart),' ',IsFunction(AtomStart)]);
|
||||||
|
if IsFunction(AtomStart) then begin
|
||||||
|
// a function
|
||||||
|
if not RunFunction then begin
|
||||||
|
Result:=false;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end else begin
|
||||||
|
// a variable
|
||||||
FStack.Push(ctcssOperand,AtomStart);
|
FStack.Push(ctcssOperand,AtomStart);
|
||||||
Item:=@FStack.Items[FStack.Top];
|
Item:=FStack.TopItem;
|
||||||
v:=Variables.GetVariable(AtomStart);
|
v:=Variables.GetVariable(AtomStart);
|
||||||
if v<>nil then begin
|
if v<>nil then begin
|
||||||
SetCTCSVariableValue(v,@Item^.Operand);
|
SetCTCSVariableValue(v,@Item^.Operand);
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
ExecuteStack(1);
|
ExecuteStack(1);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1448,7 +1662,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
if Result then begin
|
if Result then begin
|
||||||
ExecuteStack(10);
|
if not ExecuteStack(10) then
|
||||||
|
Result:=false;
|
||||||
if FStack.Top=StartTop+1 then begin
|
if FStack.Top=StartTop+1 then begin
|
||||||
// empty expression
|
// empty expression
|
||||||
AddError('operand expected, but '+GetAtom+' found');
|
AddError('operand expected, but '+GetAtom+' found');
|
||||||
@ -1461,11 +1676,13 @@ begin
|
|||||||
AddError('operator expected, but '+GetAtom+' found');
|
AddError('operator expected, but '+GetAtom+' found');
|
||||||
Result:=false;
|
Result:=false;
|
||||||
end
|
end
|
||||||
else begin
|
else if Result then begin
|
||||||
// success
|
// success
|
||||||
Item:=@FStack.Items[FStack.Top];
|
// delete ctcssExpression and keep the operand
|
||||||
SetCTCSVariableValue(@Item^.Operand,@Value);
|
FStack.Delete(FStack.Top-1);
|
||||||
debugln(['TCTConfigScriptEngine.RunExpression Result="',dbgs(PCTCfgScriptVariable(@Value)),'" ',dbgs(@Value)]);
|
Item:=FStack.TopItem;
|
||||||
|
inc(StartTop);
|
||||||
|
debugln(['TCTConfigScriptEngine.RunExpression Result="',dbgs(PCTCfgScriptVariable(@Item^.Operand)),'" ']);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1473,100 +1690,79 @@ begin
|
|||||||
while (FStack.Top>StartTop) do FStack.Pop;
|
while (FStack.Top>StartTop) do FStack.Pop;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCTConfigScriptEngine.AtomIsKeyWord: boolean;
|
function TCTConfigScriptEngine.IsKeyWord(P: PChar): boolean;
|
||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
case UpChars[AtomStart^] of
|
if p=nil then exit;
|
||||||
|
case UpChars[p^] of
|
||||||
'A':
|
'A':
|
||||||
if CompareIdentifiers('and',AtomStart)=0 then
|
if CompareIdentifiers('and',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'B':
|
'B':
|
||||||
if CompareIdentifiers('begin',AtomStart)=0 then
|
if CompareIdentifiers('begin',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'C':
|
'C':
|
||||||
if CompareIdentifiers('case',AtomStart)=0 then
|
if CompareIdentifiers('case',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'D':
|
'D':
|
||||||
case UpChars[AtomStart[1]] of
|
case UpChars[p[1]] of
|
||||||
'E':
|
'E':
|
||||||
if CompareIdentifiers('defined',AtomStart)=0 then
|
if CompareIdentifiers('defined',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'I':
|
'I':
|
||||||
if CompareIdentifiers('div',AtomStart)=0 then
|
if CompareIdentifiers('div',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
end;
|
end;
|
||||||
'E':
|
'E':
|
||||||
case UpChars[AtomStart[1]] of
|
case UpChars[p[1]] of
|
||||||
'L':
|
'L':
|
||||||
if CompareIdentifiers('else',AtomStart)=0 then
|
if CompareIdentifiers('else',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'N':
|
'N':
|
||||||
if CompareIdentifiers('end',AtomStart)=0 then
|
if CompareIdentifiers('end',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
end;
|
end;
|
||||||
'F':
|
'F':
|
||||||
case UpChars[AtomStart[1]] of
|
case UpChars[p[1]] of
|
||||||
'A':
|
'A':
|
||||||
if CompareIdentifiers('false',AtomStart)=0 then
|
if CompareIdentifiers('false',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'U':
|
'U':
|
||||||
if CompareIdentifiers('function',AtomStart)=0 then
|
if CompareIdentifiers('function',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
end;
|
end;
|
||||||
'I':
|
'I':
|
||||||
case UpChars[AtomStart[1]] of
|
case UpChars[p[1]] of
|
||||||
'F':
|
'F':
|
||||||
if CompareIdentifiers('if',AtomStart)=0 then
|
if CompareIdentifiers('if',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'N':
|
'N':
|
||||||
if CompareIdentifiers('in',AtomStart)=0 then
|
if (CompareIdentifiers('in',p)=0) then exit(true)
|
||||||
exit(true);
|
|
||||||
end;
|
end;
|
||||||
'M':
|
'M':
|
||||||
if CompareIdentifiers('mod',AtomStart)=0 then
|
if CompareIdentifiers('mod',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'N':
|
'N':
|
||||||
if CompareIdentifiers('not',AtomStart)=0 then
|
if CompareIdentifiers('not',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'O':
|
'O':
|
||||||
case UpChars[AtomStart[1]] of
|
case UpChars[p[1]] of
|
||||||
'F':
|
'F':
|
||||||
if CompareIdentifiers('of',AtomStart)=0 then
|
if CompareIdentifiers('of',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'R':
|
'R':
|
||||||
if CompareIdentifiers('or',AtomStart)=0 then
|
if CompareIdentifiers('or',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
end;
|
end;
|
||||||
'P':
|
'P':
|
||||||
if CompareIdentifiers('procedure',AtomStart)=0 then
|
if CompareIdentifiers('procedure',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'S':
|
'S':
|
||||||
case UpChars[AtomStart[1]] of
|
case UpChars[p[1]] of
|
||||||
'H':
|
'H':
|
||||||
case UpChars[AtomStart[2]] of
|
case UpChars[p[2]] of
|
||||||
'L':
|
'L':
|
||||||
if CompareIdentifiers('shl',AtomStart)=0 then
|
if CompareIdentifiers('shl',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'R':
|
'R':
|
||||||
if CompareIdentifiers('shr',AtomStart)=0 then
|
if CompareIdentifiers('shr',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
'T':
|
'T':
|
||||||
case UpChars[AtomStart[1]] of
|
case UpChars[p[1]] of
|
||||||
'H':
|
'H':
|
||||||
if CompareIdentifiers('then',AtomStart)=0 then
|
if CompareIdentifiers('then',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'R':
|
'R':
|
||||||
if CompareIdentifiers('true',AtomStart)=0 then
|
if CompareIdentifiers('true',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
end;
|
end;
|
||||||
'X':
|
'X':
|
||||||
if CompareIdentifiers('xor',AtomStart)=0 then
|
if CompareIdentifiers('xor',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
'U':
|
'U':
|
||||||
if CompareIdentifiers('undefined',AtomStart)=0 then
|
if CompareIdentifiers('undefined',p)=0 then exit(true);
|
||||||
exit(true);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1597,7 +1793,7 @@ begin
|
|||||||
if (OperatorItem^.Typ<>ctcssOperator)
|
if (OperatorItem^.Typ<>ctcssOperator)
|
||||||
or (GetOperatorLevel(OperatorItem^.StartPos)>MaxLevel) then
|
or (GetOperatorLevel(OperatorItem^.StartPos)>MaxLevel) then
|
||||||
exit;
|
exit;
|
||||||
OperandItem:=@FStack.Items[FStack.Top];
|
OperandItem:=FStack.TopItem;
|
||||||
|
|
||||||
// execute operator
|
// execute operator
|
||||||
Typ:=AtomToCTCfgOperator(OperatorItem^.StartPos);
|
Typ:=AtomToCTCfgOperator(OperatorItem^.StartPos);
|
||||||
@ -1616,7 +1812,7 @@ begin
|
|||||||
b:=CTCSVariableIsTrue(@OperandItem^.Operand);
|
b:=CTCSVariableIsTrue(@OperandItem^.Operand);
|
||||||
FStack.Pop(2);
|
FStack.Pop(2);
|
||||||
if (FStack.Top>=0) then begin
|
if (FStack.Top>=0) then begin
|
||||||
OperandItem:=@FStack.Items[FStack.Top];
|
OperandItem:=FStack.TopItem;
|
||||||
case Typ of
|
case Typ of
|
||||||
ctcsoAnd: b:=b and CTCSVariableIsTrue(@OperandItem^.Operand);
|
ctcsoAnd: b:=b and CTCSVariableIsTrue(@OperandItem^.Operand);
|
||||||
ctcsoOr: b:=b or CTCSVariableIsTrue(@OperandItem^.Operand);
|
ctcsoOr: b:=b or CTCSVariableIsTrue(@OperandItem^.Operand);
|
||||||
@ -1660,6 +1856,18 @@ begin
|
|||||||
PushBooleanValue(b);
|
PushBooleanValue(b);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
ctcsoPlus:
|
||||||
|
begin
|
||||||
|
if (FStack.Top>=2) then begin
|
||||||
|
LeftOperandItem:=@FStack.Items[FStack.Top-2];
|
||||||
|
|
||||||
|
FStack.Pop(3);
|
||||||
|
end else begin
|
||||||
|
// unary operator
|
||||||
|
FStack.Delete(FStack.Top-1);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
else
|
else
|
||||||
ErrorInvalidOperator;
|
ErrorInvalidOperator;
|
||||||
end;
|
end;
|
||||||
@ -1671,6 +1879,20 @@ begin
|
|||||||
Result:=CTCfgScriptOperatorLvl[AtomToCTCfgOperator(P)];
|
Result:=CTCfgScriptOperatorLvl[AtomToCTCfgOperator(P)];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCTConfigScriptEngine.IsFunction(P: PChar): boolean;
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
if p=nil then exit;
|
||||||
|
case UpChars[p^] of
|
||||||
|
'I':
|
||||||
|
if (CompareIdentifiers(p,'integer')=0)
|
||||||
|
or (CompareIdentifiers(p,'int64')=0)
|
||||||
|
then exit(true);
|
||||||
|
'S':
|
||||||
|
if CompareIdentifiers(p,'string')=0 then exit(true);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TCTConfigScriptEngine.Create;
|
constructor TCTConfigScriptEngine.Create;
|
||||||
begin
|
begin
|
||||||
FVariables:=TCTCfgScriptVariables.Create;
|
FVariables:=TCTCfgScriptVariables.Create;
|
||||||
@ -1923,6 +2145,22 @@ begin
|
|||||||
dec(Top);
|
dec(Top);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCTCfgScriptStack.TopItem: PCTCfgScriptStackItem;
|
||||||
|
begin
|
||||||
|
if Top<0 then
|
||||||
|
Result:=nil
|
||||||
|
else
|
||||||
|
Result:=@Items[Top];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCTCfgScriptStack.TopItemOperand: PCTCfgScriptVariable;
|
||||||
|
begin
|
||||||
|
if Top<0 then
|
||||||
|
Result:=nil
|
||||||
|
else
|
||||||
|
Result:=@Items[Top].Operand;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TCTCfgScriptError }
|
{ TCTCfgScriptError }
|
||||||
|
|
||||||
constructor TCTCfgScriptError.Create(const aMsg: string; anErrorPos: PChar);
|
constructor TCTCfgScriptError.Create(const aMsg: string; anErrorPos: PChar);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<CONFIG>
|
<CONFIG>
|
||||||
<ProjectOptions>
|
<ProjectOptions>
|
||||||
<Version Value="7"/>
|
<Version Value="8"/>
|
||||||
<General>
|
<General>
|
||||||
<Flags>
|
<Flags>
|
||||||
<MainUnitHasUsesSectionForAllUnits Value="False"/>
|
<MainUnitHasUsesSectionForAllUnits Value="False"/>
|
||||||
@ -42,7 +42,12 @@
|
|||||||
</Units>
|
</Units>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
<Version Value="8"/>
|
<Version Value="9"/>
|
||||||
|
<Parsing>
|
||||||
|
<SyntaxOptions>
|
||||||
|
<UseAnsiStrings Value="False"/>
|
||||||
|
</SyntaxOptions>
|
||||||
|
</Parsing>
|
||||||
<Other>
|
<Other>
|
||||||
<CompilerPath Value="$(CompPath)"/>
|
<CompilerPath Value="$(CompPath)"/>
|
||||||
</Other>
|
</Other>
|
||||||
|
@ -52,7 +52,7 @@ begin
|
|||||||
raise Exception.Create('unable to read '+Filename);
|
raise Exception.Create('unable to read '+Filename);
|
||||||
Src:=Code.Source;
|
Src:=Code.Source;
|
||||||
end else begin
|
end else begin
|
||||||
Src:='a:=2; b:=2; if a<=b then Result:=3';
|
Src:='a:=string(2); b:=2; if a<=b then Result:=3';
|
||||||
//Src:='if (TargetOS=''win32'') then Result:=3';
|
//Src:='if (TargetOS=''win32'') then Result:=3';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user