|
@@ -68,6 +68,7 @@ const
|
|
|
nErrWrongSwitchToggle = 1032;
|
|
|
nNoResourceSupport = 1033;
|
|
|
nResourceFileNotFound = 1034;
|
|
|
+ nErrInvalidMultiLineLineEnding = 1035;
|
|
|
|
|
|
// resourcestring patterns of messages
|
|
|
resourcestring
|
|
@@ -107,6 +108,7 @@ resourcestring
|
|
|
SInvalidDispatchFieldName = 'Invalid Dispatch field name';
|
|
|
SErrWrongSwitchToggle = 'Wrong switch toggle, use ON/OFF or +/-';
|
|
|
SNoResourceSupport = 'No support for resources of type "%s"';
|
|
|
+ SErrInvalidMultiLineLineEnding = 'Invalid multilinestring line ending type: use one of CR/LF/CRLF/SOURCE/PLATFORM' ;
|
|
|
|
|
|
type
|
|
|
TMessageType = (
|
|
@@ -162,6 +164,8 @@ type
|
|
|
tkAssignMul, // *=
|
|
|
tkAssignDivision, // /=
|
|
|
tkAtAt, // @@
|
|
|
+ // Three-character tokens
|
|
|
+ tkDotDotDot, // ... (mac mode)
|
|
|
// Reserved words
|
|
|
tkabsolute,
|
|
|
tkand,
|
|
@@ -294,7 +298,8 @@ type
|
|
|
msPrefixedAttributes, { Allow attributes, disable proc modifier [] }
|
|
|
msOmitRTTI, { treat class section 'published' as 'public' and typeinfo does not work on symbols declared with this switch }
|
|
|
msMultiHelpers, { off=only one helper per type, on=all }
|
|
|
- msImplicitFunctionSpec { implicit function specialization }
|
|
|
+ msImplicitFunctionSpec, { implicit function specialization }
|
|
|
+ msMultiLineStrings { Multiline strings }
|
|
|
);
|
|
|
TModeSwitches = Set of TModeSwitch;
|
|
|
|
|
@@ -417,14 +422,18 @@ type
|
|
|
end;
|
|
|
|
|
|
{ TLineReader }
|
|
|
+ TEOLStyle = (elPlatform,elSource,elLF,elCR,elCRLF);
|
|
|
|
|
|
TLineReader = class
|
|
|
Private
|
|
|
FFilename: string;
|
|
|
+ Protected
|
|
|
+ EOLStyle : TEOLStyle;
|
|
|
public
|
|
|
constructor Create(const AFilename: string); virtual;
|
|
|
function IsEOF: Boolean; virtual; abstract;
|
|
|
function ReadLine: string; virtual; abstract;
|
|
|
+ function LastEOLStyle: TEOLStyle; virtual;
|
|
|
property Filename: string read FFilename;
|
|
|
end;
|
|
|
|
|
@@ -569,6 +578,11 @@ const
|
|
|
'0', // false
|
|
|
'1' // true Note: True is <>'0'
|
|
|
);
|
|
|
+ MACDirectiveBool: array[boolean] of string = (
|
|
|
+ 'FALSE', // false
|
|
|
+ 'TRUE' // true Note: True is <>'0'
|
|
|
+ );
|
|
|
+
|
|
|
type
|
|
|
TMaxPrecInt = {$ifdef fpc}int64{$else}NativeInt{$endif};
|
|
|
TMaxFloat = {$ifdef fpc}extended{$else}double{$endif};
|
|
@@ -628,11 +642,13 @@ type
|
|
|
procedure Push(const AnOperand: String; OperandPosition: integer);
|
|
|
public
|
|
|
Expression: String;
|
|
|
+ MsgCurLine : Integer;
|
|
|
MsgPos: integer;
|
|
|
MsgNumber: integer;
|
|
|
MsgType: TMessageType;
|
|
|
MsgPattern: String; // Format parameter
|
|
|
- constructor Create;
|
|
|
+ isMac : Boolean;
|
|
|
+ constructor Create(aIsMac : Boolean = False);
|
|
|
destructor Destroy; override;
|
|
|
function Eval(const Expr: string): boolean;
|
|
|
property OnEvalVariable: TCEEvalVarEvent read FOnEvalVariable write FOnEvalVariable;
|
|
@@ -730,6 +746,8 @@ type
|
|
|
FModuleRow: Integer;
|
|
|
FMacros: TStrings; // Objects are TMacroDef
|
|
|
FDefines: TStrings;
|
|
|
+ FMultilineLineFeedStyle: TEOLStyle;
|
|
|
+ FMultilineLineTrimLeft: Integer;
|
|
|
FNonTokens: TTokens;
|
|
|
FOnComment: TPScannerCommentEvent;
|
|
|
FOnDirective: TPScannerDirectiveEvent;
|
|
@@ -794,17 +812,21 @@ type
|
|
|
procedure Error(MsgNumber: integer; const Msg: string);overload;
|
|
|
procedure Error(MsgNumber: integer; const Fmt: string; Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif});overload;
|
|
|
procedure PushSkipMode;
|
|
|
+ function GetMultiLineStringLineEnd(aReader: TLineReader): string;
|
|
|
+
|
|
|
function HandleDirective(const ADirectiveText: String): TToken; virtual;
|
|
|
function HandleLetterDirective(Letter: char; Enable: boolean): TToken; virtual;
|
|
|
procedure HandleBoolDirective(bs: TBoolSwitch; const Param: String); virtual;
|
|
|
procedure DoHandleComment(Sender: TObject; const aComment : string); virtual;
|
|
|
procedure DoHandleDirective(Sender: TObject; Directive, Param: String;
|
|
|
var Handled: boolean); virtual;
|
|
|
+ procedure HandleMultilineStringTrimLeft(const AParam : String);
|
|
|
+ procedure HandleMultilineStringLineEnding(const AParam : string);
|
|
|
procedure HandleIFDEF(const AParam: String);
|
|
|
procedure HandleIFNDEF(const AParam: String);
|
|
|
procedure HandleIFOPT(const AParam: String);
|
|
|
- procedure HandleIF(const AParam: String);
|
|
|
- procedure HandleELSEIF(const AParam: String);
|
|
|
+ procedure HandleIF(const AParam: String; aIsMac : Boolean);
|
|
|
+ procedure HandleELSEIF(const AParam: String; aIsMac : Boolean);
|
|
|
procedure HandleELSE(const AParam: String);
|
|
|
procedure HandleENDIF(const AParam: String);
|
|
|
procedure HandleDefine(Param: String); virtual;
|
|
@@ -812,6 +834,7 @@ type
|
|
|
procedure HandleError(Param: String); virtual;
|
|
|
procedure HandleMessageDirective(Param: String); virtual;
|
|
|
procedure HandleIncludeFile(Param: String); virtual;
|
|
|
+ procedure HandleIncludeString(Param: String); virtual;
|
|
|
procedure HandleResource(Param : string); virtual;
|
|
|
procedure HandleOptimizations(Param : string); virtual;
|
|
|
procedure DoHandleOptimization(OptName, OptValue: string); virtual;
|
|
@@ -828,6 +851,7 @@ type
|
|
|
procedure PushStackItem; virtual;
|
|
|
procedure PopStackItem; virtual;
|
|
|
function DoFetchTextToken: TToken;
|
|
|
+ function DoFetchMultilineTextToken: TToken;
|
|
|
function DoFetchToken: TToken;
|
|
|
procedure ClearFiles;
|
|
|
Procedure ClearMacros;
|
|
@@ -901,7 +925,8 @@ type
|
|
|
property SkipGlobalSwitches: Boolean read FSkipGlobalSwitches write FSkipGlobalSwitches;
|
|
|
property MaxIncludeStackDepth: integer read FMaxIncludeStackDepth write FMaxIncludeStackDepth default DefaultMaxIncludeStackDepth;
|
|
|
property ForceCaret : Boolean read GetForceCaret;
|
|
|
-
|
|
|
+ Property MultilineLineFeedStyle : TEOLStyle Read FMultilineLineFeedStyle Write FMultilineLineFeedStyle;
|
|
|
+ Property MultilineLineTrimLeft : Integer Read FMultilineLineTrimLeft Write FMultilineLineTrimLeft;
|
|
|
property LogEvents : TPScannerLogEvents read FLogEvents write FLogEvents;
|
|
|
property OnLog : TPScannerLogHandler read FOnLog write FOnLog;
|
|
|
property OnFormatPath: TPScannerFormatPathEvent read FOnFormatPath write FOnFormatPath;
|
|
@@ -960,6 +985,7 @@ const
|
|
|
'*=',
|
|
|
'/=',
|
|
|
'@@',
|
|
|
+ '...',
|
|
|
// Reserved words
|
|
|
'absolute',
|
|
|
'and',
|
|
@@ -1093,7 +1119,8 @@ const
|
|
|
'PREFIXEDATTRIBUTES',
|
|
|
'OMITRTTI',
|
|
|
'MULTIHELPERS',
|
|
|
- 'IMPLICITFUNCTIONSPECIALIZATION'
|
|
|
+ 'IMPLICITFUNCTIONSPECIALIZATION',
|
|
|
+ 'MULTILINESTRINGS'
|
|
|
);
|
|
|
|
|
|
LetterSwitchNames: array['A'..'Z'] of string=(
|
|
@@ -1461,12 +1488,16 @@ end;
|
|
|
function TCondDirectiveEvaluator.IsFalse(const Value: String): boolean;
|
|
|
begin
|
|
|
Result:=Value=CondDirectiveBool[false];
|
|
|
+ if (not Result) and isMac then
|
|
|
+ Result:=Value=MacDirectiveBool[false];
|
|
|
end;
|
|
|
|
|
|
// inline
|
|
|
function TCondDirectiveEvaluator.IsTrue(const Value: String): boolean;
|
|
|
begin
|
|
|
Result:=Value<>CondDirectiveBool[false];
|
|
|
+ if Result and isMac then
|
|
|
+ Result:=Value<>MacDirectiveBool[False];
|
|
|
end;
|
|
|
|
|
|
function TCondDirectiveEvaluator.IsInteger(const Value: String; out i: TMaxPrecInt
|
|
@@ -1786,7 +1817,7 @@ begin
|
|
|
OnLog(Self,Args);
|
|
|
if not (aMsgType in [mtError,mtFatal]) then exit;
|
|
|
end;
|
|
|
- raise EScannerError.CreateFmt(MsgPattern+' at '+IntToStr(MsgPos),Args);
|
|
|
+ raise EScannerError.CreateFmt(MsgPattern+' at pos '+IntToStr(MsgPos)+' line '+IntToStr(MsgCurLine),Args);
|
|
|
end;
|
|
|
|
|
|
procedure TCondDirectiveEvaluator.LogXExpectedButTokenFound(const X: String;
|
|
@@ -1810,6 +1841,12 @@ procedure TCondDirectiveEvaluator.ReadOperand(Skip: boolean);
|
|
|
'Abc'
|
|
|
(expression)
|
|
|
}
|
|
|
+
|
|
|
+ Function IsMacNoArgFunction(aName : string) : Boolean;
|
|
|
+ begin
|
|
|
+ Result:=SameText(aName,'DEFINED') or SameText(aName,'UNDEFINED');
|
|
|
+ end;
|
|
|
+
|
|
|
var
|
|
|
i: TMaxPrecInt;
|
|
|
e: extended;
|
|
@@ -1817,6 +1854,7 @@ var
|
|
|
Code: integer;
|
|
|
NameStartP: {$ifdef UsePChar}PChar{$else}integer{$endif};
|
|
|
p, Lvl: integer;
|
|
|
+
|
|
|
begin
|
|
|
{$IFDEF VerbosePasDirectiveEval}
|
|
|
writeln('TCondDirectiveEvaluator.ReadOperand START Token[',FTokenStart-PChar(Expression)+1,']="',GetTokenString,'" ',FToken,BoolToStr(Skip,' SKIP',''));
|
|
@@ -1886,7 +1924,9 @@ begin
|
|
|
tkIdentifier:
|
|
|
if Skip then
|
|
|
begin
|
|
|
+ aName:=GetTokenString;
|
|
|
NextToken;
|
|
|
+ // for macpas IFC we can have DEFINED A or DEFINED(A)...
|
|
|
if FToken=tkBraceOpen then
|
|
|
begin
|
|
|
// only one parameter is supported
|
|
@@ -1896,6 +1936,10 @@ begin
|
|
|
if FToken<>tkBraceClose then
|
|
|
LogXExpectedButTokenFound(')');
|
|
|
NextToken;
|
|
|
+ end
|
|
|
+ else if (IsMac and IsMacNoArgFunction(aName)) then
|
|
|
+ begin
|
|
|
+ NextToken;
|
|
|
end;
|
|
|
end
|
|
|
else
|
|
@@ -1926,6 +1970,14 @@ begin
|
|
|
Push(S,p);
|
|
|
NextToken;
|
|
|
end
|
|
|
+ else if (IsMac and IsMacNoArgFunction(aName)) then
|
|
|
+ begin
|
|
|
+ if FToken<>tkIdentifier then
|
|
|
+ LogXExpectedButTokenFound('identifier');
|
|
|
+ aName:=GetTokenString;
|
|
|
+ Push(CondDirectiveBool[OnEvalVariable(Self,aName,S)],p);
|
|
|
+ NextToken;
|
|
|
+ end
|
|
|
else
|
|
|
begin
|
|
|
// variable
|
|
@@ -2289,9 +2341,9 @@ begin
|
|
|
{$ENDIF}
|
|
|
end;
|
|
|
|
|
|
-constructor TCondDirectiveEvaluator.Create;
|
|
|
+constructor TCondDirectiveEvaluator.Create(aIsMac: Boolean);
|
|
|
begin
|
|
|
-
|
|
|
+ IsMac:=aIsMac
|
|
|
end;
|
|
|
|
|
|
destructor TCondDirectiveEvaluator.Destroy;
|
|
@@ -2315,6 +2367,9 @@ begin
|
|
|
NextToken;
|
|
|
ReadExpression;
|
|
|
Result:=IsTrue(FStack[0].Operand);
|
|
|
+ {$IFDEF VerbosePasDirectiveEval}
|
|
|
+ Writeln('COND Eval: ', Expr,' -> ',Result);
|
|
|
+ {$ENDIF}
|
|
|
end;
|
|
|
|
|
|
{ TMacroDef }
|
|
@@ -2330,6 +2385,17 @@ end;
|
|
|
constructor TLineReader.Create(const AFilename: string);
|
|
|
begin
|
|
|
FFileName:=AFileName;
|
|
|
+ if LineEnding=#13 then
|
|
|
+ {%H-}EOLStyle:=elCR
|
|
|
+ else if LineEnding=#13#10 then
|
|
|
+ {%H-}EOLStyle:=elCRLF
|
|
|
+ else
|
|
|
+ EOLStyle:=elLF
|
|
|
+end;
|
|
|
+
|
|
|
+function TLineReader.LastEOLStyle: TEOLStyle;
|
|
|
+begin
|
|
|
+ Result:=EOLStyle;
|
|
|
end;
|
|
|
|
|
|
{ ---------------------------------------------------------------------
|
|
@@ -2418,11 +2484,20 @@ begin
|
|
|
EOL:=(FContent[FPos] in [#10,#13]);
|
|
|
until isEOF or EOL;
|
|
|
If EOL then
|
|
|
+ begin
|
|
|
+ if FContent[FPOS]=#10 then
|
|
|
+ EOLSTYLE:=elLF
|
|
|
+ else
|
|
|
+ EOLStyle:=elCR;
|
|
|
Result:=Copy(FContent,LPos,FPos-LPos)
|
|
|
+ end
|
|
|
else
|
|
|
Result:=Copy(FContent,LPos,FPos-LPos+1);
|
|
|
If (not isEOF) and (FContent[FPos]=#13) and (FContent[FPos+1]=#10) then
|
|
|
+ begin
|
|
|
inc(FPos);
|
|
|
+ EOLStyle:=elCRLF;
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
{ TFileStreamLineReader }
|
|
@@ -3007,7 +3082,7 @@ begin
|
|
|
Result:=tkoperator;
|
|
|
end;
|
|
|
|
|
|
-Procedure TPascalScanner.PopStackItem;
|
|
|
+procedure TPascalScanner.PopStackItem;
|
|
|
|
|
|
var
|
|
|
IncludeStackItem: TIncludeStackItem;
|
|
@@ -3262,6 +3337,167 @@ begin
|
|
|
[FormatPath(CurFilename),CurRow,CurColumn,FLastMsg]);
|
|
|
end;
|
|
|
|
|
|
+function TPascalScanner.GetMultiLineStringLineEnd(aReader : TLineReader) : string;
|
|
|
+
|
|
|
+Var
|
|
|
+ aLF : String;
|
|
|
+ aStyle: TEOLStyle;
|
|
|
+
|
|
|
+
|
|
|
+begin
|
|
|
+ aStyle:=MultilineLineFeedStyle;
|
|
|
+ if aStyle=elSource then
|
|
|
+ aStyle:=aReader.LastEOLStyle;
|
|
|
+ case aStyle of
|
|
|
+ elCR : aLF:=#13;
|
|
|
+ elCRLF : aLF:=#13#10;
|
|
|
+ elLF : aLF:=#10;
|
|
|
+ elPlatform : alf:=sLineBreak;
|
|
|
+ else
|
|
|
+ aLF:=#10;
|
|
|
+ end;
|
|
|
+ Result:=aLF;
|
|
|
+end;
|
|
|
+
|
|
|
+function TPascalScanner.DoFetchMultilineTextToken:TToken;
|
|
|
+
|
|
|
+var
|
|
|
+ StartPos,OldLength : Integer;
|
|
|
+ TokenStart : {$ifdef UsePChar}PChar{$else}integer{$endif};
|
|
|
+ {$ifndef UsePChar}
|
|
|
+ s: String;
|
|
|
+ l: integer;
|
|
|
+ {$endif}
|
|
|
+
|
|
|
+
|
|
|
+ Procedure AddToCurString(addLF : Boolean);
|
|
|
+ var
|
|
|
+ SectionLength,i : Integer;
|
|
|
+ aLF : String;
|
|
|
+
|
|
|
+ begin
|
|
|
+ i:=MultilineLineTrimLeft;
|
|
|
+ if I=-1 then
|
|
|
+ I:=StartPos+1;
|
|
|
+ if I>0 then
|
|
|
+ begin
|
|
|
+ While ({$ifdef UsePChar} TokenStart^{$ELSE}FCurLine[TokenStart]{$ENDIF} in [' ',#9]) and (TokenStart<=FTokenPos) and (I>0) do
|
|
|
+ begin
|
|
|
+ Inc(TokenStart);
|
|
|
+ Dec(I);
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else if I=-2 then
|
|
|
+ begin
|
|
|
+ While ({$ifdef UsePChar} TokenStart^{$ELSE}FCurLine[TokenStart]{$ENDIF} in [' ',#9]) and (TokenStart<=FTokenPos) do
|
|
|
+ Inc(TokenStart);
|
|
|
+ end;
|
|
|
+
|
|
|
+ SectionLength := FTokenPos - TokenStart+Ord(AddLF);
|
|
|
+ {$ifdef UsePChar}
|
|
|
+ SetLength(FCurTokenString, OldLength + SectionLength);
|
|
|
+ if SectionLength > 0 then
|
|
|
+ Move(TokenStart^, FCurTokenString[OldLength + 1], SectionLength);
|
|
|
+ {$else}
|
|
|
+ FCurTokenString:=FCurTokenString+copy(FCurLine,TokenStart,SectionLength);
|
|
|
+ {$endif}
|
|
|
+ if AddLF then
|
|
|
+ begin
|
|
|
+ alf:=GetMultiLineStringLineEnd(FCurSourceFile);
|
|
|
+ FCurTokenString:=FCurTokenString+aLF;
|
|
|
+ Inc(OldLength,Length(aLF));
|
|
|
+ end;
|
|
|
+ Inc(OldLength, SectionLength);
|
|
|
+ end;
|
|
|
+
|
|
|
+begin
|
|
|
+ Result:=tkEOF;
|
|
|
+ OldLength:=0;
|
|
|
+ FCurTokenString := '';
|
|
|
+ {$ifndef UsePChar}
|
|
|
+ s:=FCurLine;
|
|
|
+ l:=length(s);
|
|
|
+ StartPos:=FTokenPos;
|
|
|
+ {$ELSE}
|
|
|
+ StartPos:=FTokenPos-PChar(FCurLine);
|
|
|
+ {$endif}
|
|
|
+
|
|
|
+ repeat
|
|
|
+ {$ifndef UsePChar}
|
|
|
+ if FTokenPos>l then break;
|
|
|
+ {$endif}
|
|
|
+ case {$ifdef UsePChar}FTokenPos[0]{$else}s[FTokenPos]{$endif} of
|
|
|
+ '^' :
|
|
|
+ begin
|
|
|
+ TokenStart := FTokenPos;
|
|
|
+ Inc(FTokenPos);
|
|
|
+ if {$ifdef UsePChar}FTokenPos[0] in Letters{$else}(FTokenPos<l) and (s[FTokenPos] in Letters){$endif} then
|
|
|
+ Inc(FTokenPos);
|
|
|
+ if Result=tkEOF then Result := tkChar else Result:=tkString;
|
|
|
+ end;
|
|
|
+ '#':
|
|
|
+ begin
|
|
|
+ TokenStart := FTokenPos;
|
|
|
+ Inc(FTokenPos);
|
|
|
+ if {$ifdef UsePChar}FTokenPos[0]='$'{$else}(FTokenPos<l) and (s[FTokenPos]='$'){$endif} then
|
|
|
+ begin
|
|
|
+ Inc(FTokenPos);
|
|
|
+ repeat
|
|
|
+ Inc(FTokenPos);
|
|
|
+ until {$ifdef UsePChar}not (FTokenPos[0] in HexDigits){$else}(FTokenPos>l) or not (s[FTokenPos] in HexDigits){$endif};
|
|
|
+ end else
|
|
|
+ repeat
|
|
|
+ Inc(FTokenPos);
|
|
|
+ until {$ifdef UsePChar}not (FTokenPos[0] in Digits){$else}(FTokenPos>l) or not (s[FTokenPos] in Digits){$endif};
|
|
|
+ if Result=tkEOF then Result := tkChar else Result:=tkString;
|
|
|
+ end;
|
|
|
+ '`':
|
|
|
+ begin
|
|
|
+ TokenStart := FTokenPos;
|
|
|
+ Inc(FTokenPos);
|
|
|
+
|
|
|
+ while true do
|
|
|
+ begin
|
|
|
+ if {$ifdef UsePChar}FTokenPos[0] = '`'{$else}(FTokenPos<=l) and (s[FTokenPos]=''''){$endif} then
|
|
|
+ if {$ifdef UsePChar}FTokenPos[1] = '`'{$else}(FTokenPos<l) and (s[FTokenPos+1]=''''){$endif} then
|
|
|
+ Inc(FTokenPos)
|
|
|
+ else
|
|
|
+ break;
|
|
|
+
|
|
|
+ if {$ifdef UsePChar}FTokenPos[0] = #0{$else}FTokenPos>l{$endif} then
|
|
|
+ begin
|
|
|
+ FTokenPos:=FTokenPos-1;
|
|
|
+ AddToCurString(true);
|
|
|
+ // Writeln('Curtokenstring : >>',FCurTOkenString,'<<');
|
|
|
+ if not Self.FetchLine then
|
|
|
+ Error(nErrOpenString,SErrOpenString);
|
|
|
+ // Writeln('Current line is now : ',FCurLine);
|
|
|
+ {$ifndef UsePChar}
|
|
|
+ s:=FCurLine;
|
|
|
+ l:=length(s);
|
|
|
+ {$ELSE}
|
|
|
+ FTokenPos:=PChar(FCurLine);
|
|
|
+ {$endif}
|
|
|
+ TokenStart:=FTokenPos;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ Inc(FTokenPos);
|
|
|
+ end;
|
|
|
+ Inc(FTokenPos);
|
|
|
+ Result := tkString;
|
|
|
+ end;
|
|
|
+ else
|
|
|
+ Break;
|
|
|
+ end;
|
|
|
+ AddToCurString(false);
|
|
|
+ until false;
|
|
|
+ if length(FCurTokenString)>1 then
|
|
|
+ begin
|
|
|
+ FCurTokenString[1]:='''';
|
|
|
+ FCurTokenString[Length(FCurTokenString)]:='''';
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
function TPascalScanner.DoFetchTextToken:TToken;
|
|
|
var
|
|
|
OldLength : Integer;
|
|
@@ -3407,6 +3643,42 @@ begin
|
|
|
DoLog(mtInfo,nLogOpeningFile,SLogOpeningFile,[FormatPath(FCurFileName)],True);
|
|
|
end;
|
|
|
|
|
|
+procedure TPascalScanner.HandleIncludeString(Param: String);
|
|
|
+
|
|
|
+var
|
|
|
+ NewSourceFile: TLineReader;
|
|
|
+ aString,aLine: string;
|
|
|
+
|
|
|
+begin
|
|
|
+ Param:=Trim(Param);
|
|
|
+ if Length(Param)>1 then
|
|
|
+ begin
|
|
|
+ if (Param[1]='''') then
|
|
|
+ begin
|
|
|
+ if Param[length(Param)]<>'''' then
|
|
|
+ Error(nErrOpenString,SErrOpenString,[]);
|
|
|
+ Param:=copy(Param,2,length(Param)-2);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ NewSourceFile := FileResolver.FindIncludeFile(Param);
|
|
|
+ if not Assigned(NewSourceFile) then
|
|
|
+ Error(nErrIncludeFileNotFound, SErrIncludeFileNotFound, [Param]);
|
|
|
+ try
|
|
|
+ AString:='';
|
|
|
+ While not NewSourceFile.IsEOF Do
|
|
|
+ begin
|
|
|
+ ALine:=NewSourceFile.ReadLine;
|
|
|
+ if aString<>'' then
|
|
|
+ aString:=aString+GetMultiLineStringLineEnd(NewSourceFile);
|
|
|
+ AString:=aString+aLine;
|
|
|
+ end;
|
|
|
+ finally
|
|
|
+ NewSourceFile.Free;
|
|
|
+ end;
|
|
|
+ FCurTokenString:=''''+AString+'''';
|
|
|
+ FCurToken:=tkString;
|
|
|
+end;
|
|
|
+
|
|
|
procedure TPascalScanner.HandleResource(Param: string);
|
|
|
|
|
|
Var
|
|
@@ -3631,7 +3903,7 @@ begin
|
|
|
MValue:=Trim(Param);
|
|
|
MName:=Trim(Copy(MValue,1,Index-1));
|
|
|
Delete(MValue,1,Index+1);
|
|
|
- AddMacro(MName,MValue);
|
|
|
+ AddMacro(MName,Trim(MValue));
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -3964,7 +4236,7 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-procedure TPascalScanner.HandleIF(const AParam: String);
|
|
|
+procedure TPascalScanner.HandleIF(const AParam: String; aIsMac: Boolean);
|
|
|
|
|
|
begin
|
|
|
PushSkipMode;
|
|
@@ -3972,6 +4244,8 @@ begin
|
|
|
PPSkipMode := ppSkipAll
|
|
|
else
|
|
|
begin
|
|
|
+ ConditionEval.MsgCurLine:=CurTokenPos.Row;
|
|
|
+ ConditionEval.isMac:=aIsMac;
|
|
|
if ConditionEval.Eval(AParam) then
|
|
|
PPSkipMode := ppSkipElseBranch
|
|
|
else
|
|
@@ -3987,12 +4261,13 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-procedure TPascalScanner.HandleELSEIF(const AParam: String);
|
|
|
+procedure TPascalScanner.HandleELSEIF(const AParam: String; aIsMac : Boolean);
|
|
|
begin
|
|
|
if PPSkipStackIndex = 0 then
|
|
|
Error(nErrInvalidPPElse,sErrInvalidPPElse);
|
|
|
if PPSkipMode = ppSkipIfBranch then
|
|
|
begin
|
|
|
+ ConditionEval.isMac:=aIsMac;
|
|
|
if ConditionEval.Eval(AParam) then
|
|
|
begin
|
|
|
PPSkipMode := ppSkipElseBranch;
|
|
@@ -4058,7 +4333,11 @@ begin
|
|
|
Result:=tkComment;
|
|
|
P:=Pos(' ',ADirectiveText);
|
|
|
If P=0 then
|
|
|
- P:=Length(ADirectiveText)+1;
|
|
|
+ begin
|
|
|
+ P:=Pos(#9,ADirectiveText);
|
|
|
+ If P=0 then
|
|
|
+ P:=Length(ADirectiveText)+1;
|
|
|
+ end;
|
|
|
Directive:=Copy(ADirectiveText,2,P-2); // 1 is $
|
|
|
Param:=ADirectiveText;
|
|
|
Delete(Param,1,P);
|
|
@@ -4073,12 +4352,16 @@ begin
|
|
|
HandleIFNDEF(Param);
|
|
|
'IFOPT':
|
|
|
HandleIFOPT(Param);
|
|
|
+ 'IFC',
|
|
|
'IF':
|
|
|
- HandleIF(Param);
|
|
|
+ HandleIF(Param,UpperCase(Directive)='IFC');
|
|
|
+ 'ELIFC',
|
|
|
'ELSEIF':
|
|
|
- HandleELSEIF(Param);
|
|
|
+ HandleELSEIF(Param,UpperCase(Directive)='ELIFC');
|
|
|
+ 'ELSEC',
|
|
|
'ELSE':
|
|
|
HandleELSE(Param);
|
|
|
+ 'ENDC',
|
|
|
'ENDIF':
|
|
|
HandleENDIF(Param);
|
|
|
'IFEND':
|
|
@@ -4102,7 +4385,9 @@ begin
|
|
|
Case UpperCase(Directive) of
|
|
|
'ASSERTIONS':
|
|
|
DoBoolDirective(bsAssertions);
|
|
|
- 'DEFINE':
|
|
|
+ 'DEFINE',
|
|
|
+ 'DEFINEC',
|
|
|
+ 'SETC':
|
|
|
HandleDefine(Param);
|
|
|
'GOTO':
|
|
|
DoBoolDirective(bsGoto);
|
|
@@ -4118,6 +4403,11 @@ begin
|
|
|
DoBoolDirective(bsHints);
|
|
|
'I','INCLUDE':
|
|
|
Result:=HandleInclude(Param);
|
|
|
+ 'INCLUDESTRING','INCLUDESTRINGFILE':
|
|
|
+ begin
|
|
|
+ HandleIncludeString(Param);
|
|
|
+ Result:=tkString;
|
|
|
+ end;
|
|
|
'INTERFACES':
|
|
|
HandleInterfaces(Param);
|
|
|
'LONGSTRINGS':
|
|
@@ -4130,6 +4420,10 @@ begin
|
|
|
HandleMode(Param);
|
|
|
'MODESWITCH':
|
|
|
HandleModeSwitch(Param);
|
|
|
+ 'MULTILINESTRINGLINEENDING':
|
|
|
+ HandleMultilineStringLineEnding(Param);
|
|
|
+ 'MULTILINESTRINGTRIMLEFT':
|
|
|
+ HandleMultilineStringTrimLeft(Param);
|
|
|
'NOTE':
|
|
|
DoLog(mtNote,nUserDefined,SUserDefined,[Param]);
|
|
|
'NOTES':
|
|
@@ -4163,6 +4457,11 @@ begin
|
|
|
DoBoolDirective(bsWarnings);
|
|
|
'WRITEABLECONST':
|
|
|
DoBoolDirective(bsWriteableConst);
|
|
|
+ 'ALIGN',
|
|
|
+ 'CALLING',
|
|
|
+ 'INLINE',
|
|
|
+ 'PACKRECORDS',
|
|
|
+ 'PACKENUM' : ;
|
|
|
else
|
|
|
Handled:=false;
|
|
|
end;
|
|
@@ -4250,6 +4549,44 @@ begin
|
|
|
OnDirective(Sender,Directive,Param,Handled);
|
|
|
end;
|
|
|
|
|
|
+procedure TPascalScanner.HandleMultilineStringTrimLeft(const AParam: String);
|
|
|
+
|
|
|
+Var
|
|
|
+ S : String;
|
|
|
+ i : integer;
|
|
|
+
|
|
|
+begin
|
|
|
+ S:=UpperCase(Trim(aParam));
|
|
|
+ Case UpperCase(S) of
|
|
|
+ 'ALL' : I:=-2;
|
|
|
+ 'AUTO' : I:=-1;
|
|
|
+ 'NONE' : I:=0;
|
|
|
+ else
|
|
|
+ If not TryStrToInt(S,I) then
|
|
|
+ I:=0;
|
|
|
+ end;
|
|
|
+ MultilineLineTrimLeft:=I;
|
|
|
+
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TPascalScanner.HandleMultilineStringLineEnding(const AParam: string);
|
|
|
+
|
|
|
+Var
|
|
|
+ S : TEOLStyle;
|
|
|
+
|
|
|
+begin
|
|
|
+ Case UpperCase(Trim(aParam)) of
|
|
|
+ 'CR' : s:=elCR;
|
|
|
+ 'LF' : s:=elLF;
|
|
|
+ 'CRLF' : s:=elCRLF;
|
|
|
+ 'SOURCE' : s:=elSource;
|
|
|
+ 'PLATFORM' : s:=elPlatform;
|
|
|
+ else
|
|
|
+ Error(nErrInvalidMultiLineLineEnding,sErrInvalidMultiLineLineEnding);
|
|
|
+ end;
|
|
|
+ MultilineLineFeedStyle:=S;
|
|
|
+end;
|
|
|
+
|
|
|
function TPascalScanner.DoFetchToken: TToken;
|
|
|
|
|
|
var
|
|
@@ -4347,6 +4684,13 @@ begin
|
|
|
end;
|
|
|
'#', '''':
|
|
|
Result:=DoFetchTextToken;
|
|
|
+ '`' :
|
|
|
+ begin
|
|
|
+ If not (msMultiLineStrings in CurrentModeSwitches) then
|
|
|
+ Error(nErrInvalidCharacter, SErrInvalidCharacter,
|
|
|
+ [{$ifdef UsePChar}FTokenPos[0]{$else}s[FTokenPos]{$endif}]);
|
|
|
+ Result:=DoFetchMultilineTextToken;
|
|
|
+ end;
|
|
|
'&':
|
|
|
begin
|
|
|
TokenStart := FTokenPos;
|
|
@@ -4534,7 +4878,13 @@ begin
|
|
|
else if {$ifdef UsePChar}FTokenPos[0]='.'{$else}(FTokenPos<=l) and (s[FTokenPos]='.'){$endif} then
|
|
|
begin
|
|
|
Inc(FTokenPos);
|
|
|
- Result := tkDotDot;
|
|
|
+ if {$ifdef UsePChar}FTokenPos[0]='.'{$else}(FTokenPos<=l) and (s[FTokenPos]='.'){$endif} then
|
|
|
+ begin
|
|
|
+ Inc(FTokenPos);
|
|
|
+ Result:=tkDotDotDot;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ Result := tkDotDot;
|
|
|
end
|
|
|
else
|
|
|
Result := tkDot;
|
|
@@ -4932,6 +5282,10 @@ end;
|
|
|
|
|
|
procedure TPascalScanner.OnCondEvalLog(Sender: TCondDirectiveEvaluator;
|
|
|
Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif});
|
|
|
+
|
|
|
+Var
|
|
|
+ Msg : String;
|
|
|
+
|
|
|
begin
|
|
|
{$IFDEF VerbosePasDirectiveEval}
|
|
|
writeln('TPascalScanner.OnCondEvalLog "',Sender.MsgPattern,'"');
|
|
@@ -4940,7 +5294,8 @@ begin
|
|
|
if Sender.MsgType<=mtError then
|
|
|
begin
|
|
|
SetCurMsg(Sender.MsgType,Sender.MsgNumber,Sender.MsgPattern,Args);
|
|
|
- raise EScannerError.Create(FLastMsg);
|
|
|
+ Msg:=Format('%s(%d,%d) : %s',[FormatPath(FCurFileName),CurRow,CurColumn,FLastMsg]);
|
|
|
+ raise EScannerError.Create(Msg);
|
|
|
end
|
|
|
else
|
|
|
DoLog(Sender.MsgType,Sender.MsgNumber,Sender.MsgPattern,Args,true);
|