LazDebuggerFp, FpDebug: Improve some error messages / Start on i18n

This commit is contained in:
Martin 2023-03-20 20:02:50 +01:00
parent 01dbdf31c0
commit afe8ba3180
16 changed files with 1104 additions and 271 deletions

View File

@ -17,37 +17,58 @@ resourcestring
+'Watches';
// %0:s is always linebreak
MsgfpErrAnyError = '%1:s';
MsgfpErrSymbolNotFound = 'Identifier not found: "%1:s"';
MsgfpErrNoMemberWithName = 'Member not found: %1:s';
MsgfpErrorNotAStructure = 'Cannot get member "%1:s" from non-structured type: %2:s';
MsgfpErrorBadFloatSize = 'Unsupported float value: Unknown precision';
MsgfpErrAddressIsNil = 'Cannot access data, Address is NIL';
MsgfpErrAnyError = '%1:s';
MsgfpErrSymbolNotFound_p = 'Identifier not found: "%1:s"%2:s';
MsgfpErrNoMemberWithName = 'Member not found: %1:s';
MsgfpErrorNotAStructure = 'Cannot get member "%1:s" from non-structured type: %2:s';
MsgfpErrorBadFloatSize = 'Unsupported float value: Unknown precision';
MsgfpErrAddressIsNil = 'Cannot access data, Address is NIL';
MsgfpErrIndexOutOfRange = 'Index out of range: %1:d';
MsgfpErrTypeNotIndexable = 'The value has no index';
MsgfpErrExpectedOrdinalVal_p = 'Expected an ordinal value, but found ''%1:s''%2:s';
MsgfpErrCannotCastToPointer_p = 'Can''t cast value to pointer ''%1:s''%2:s';
MsgfpErrCannotDeref_p = 'Can''t dereference expression ''%1:s''%2:s';
MsgfpErrPasParserInvalidExpression = 'Invalid Expression';
MsgfpErrPasParserUnexpectedToken = 'Unexpected token ''%1:s'' at pos %2:d';
MsgfpErrPasParserMissingExprAfterComma = 'Expected Expression after Comma, but found closing bracket %1:s';
MsgfpErrPasParserMissingIndexExpression = 'Expected Expression but found closing bracket: %1:s';
MsgfpErrInvalidNumber = 'Cannot parse number: %1:s';
MsgfpErrCannotDereferenceType = 'Cannot dereference Expression "%1:s"';
MsgfpErrTypeHasNoIndex = 'Cannot access indexed element in expression %1:s';
MsgfpErrChangeVariableNotSupported = 'Changing the value of this variable is not supported';
// 100 memreader error
MsgfpInternalErrfpErrFailedReadMem = 'Internal error: Failed to read data from memory';
MsgfpInternalErrCanNotReadInvalidMem = 'Internal error: Missing data location';
MsgfpErrReadMemSizeLimit = 'Memory read size exceeds limit';
MsgfpErrCanNotReadMemAtAddr = 'Failed to read Mem at Address $%1:x';
MsgfpErrFailedReadRegiseter = 'Failed to read data from register';
MsgfpErrFailedWriteMem = 'Failed to write data';
MsgfpInternalErrCanNotWriteInvalidMem = 'Internal error writing data: Missing data location';
MsgfpErrCanNotWriteMemAtAddr = 'Failed to write Mem at Address $%1:x';
MsgfpInternalErrfpErrFailedReadMem = 'Internal error: Failed to read data from memory';
MsgfpInternalErrCanNotReadInvalidMem = 'Internal error: Missing data location';
MsgfpErrReadMemSizeLimit = 'Memory read size exceeds limit';
MsgfpErrCanNotReadMemAtAddr = 'Failed to read Mem at Address $%1:x';
MsgfpErrFailedReadRegiseter = 'Failed to read data from register';
MsgfpErrFailedWriteMem = 'Failed to write data';
MsgfpInternalErrCanNotWriteInvalidMem = 'Internal error writing data: Missing data location';
MsgfpErrCanNotWriteMemAtAddr = 'Failed to write Mem at Address $%1:x';
MsgfpErrPasParserEmptyExpression = 'Empty expression';
MsgfpErrPasParserUnexpectedEndOfExpression = 'Unexpected end of expression after ''%1:s''';
MsgfpErrPasParserInvalidExpression = 'Invalid Expression';
MsgfpErrPasParserUnexpectedToken_p = 'Unexpected token ''%1:s''%2:s';
MsgfpErrPasParserUnknownIntrinsic_p = 'Intrinsic function ''%1:s'' not found%2:s';
MsgfpErrPasParserMissingOpenBracket_p = 'No opening bracket for ''%1:s'' found%2:s';
MsgfpErrPasParserWrongOpenBracket_p = 'Mismatched opening bracket (''%3:s'' at pos %2:d) for ''%1:s'' found%4:s';
MsgfpErrPasParserMissingIndexExpression = 'Expected Expression but found closing bracket: ''%1:s'' at pos %2:d';
MsgfpErrPasParserMissingExprAfterComma = 'Expected Expression after Comma, but found closing bracket %1:s at pos %2:d';
MsgfpErrPasParserIndexError_Wrapper = 'Index error at pos %2:d for ''%1:s''[]: %3:s';
MsgfpErrPasParserUnterminatedString_p = 'String not terminated%1:s';
MsgfpErrPasParserExpectedNumber_p = 'Expected Number, but found ''%1:s''%2:s';
MsgfpErrTypeHasNoIndex = 'Cannot access indexed element in expression %1:s';
MsgfpErrChangeVariableNotSupported = 'Changing the value of this variable is not supported';
(* Any resourcestring endig in *_p may or may not have one of the below included.
The value may also be an empty string instead.
*)
MsgfpErrPasParser_AtStart = ' at start of expression';
MsgfpErrPasParser_PositionAfter = ' at pos %1:d after ''%2:s''';
MsgfpErrPasParser_Position = ' at pos %1:d';
// 200 LocationParser
MsgfpErrLocationParser = 'Internal Error: Cannot calculate location.';
MsgfpErrLocationParserMemRead = '%1:s (while calculating location)'; // Pass on nested error
MsgfpErrLocationParserInit = 'Internal Error: Cannot calculate location (Init).';
MsgfpErrLocationParserMinStack = 'Not enough elements on stack.'; // internally used
MsgfpErrLocationParserNoAddressOnStack = 'Not an address on stack'; // internally used
MsgfpErrLocationParser = 'Internal Error: Cannot calculate location.';
MsgfpErrLocationParserMemRead = '%1:s (while calculating location)'; // Pass on nested error
MsgfpErrLocationParserInit = 'Internal Error: Cannot calculate location (Init).';
MsgfpErrLocationParserMinStack = 'Not enough elements on stack.'; // internally used
MsgfpErrLocationParserNoAddressOnStack = 'Not an address on stack'; // internally used
// 10000 Process/Control errors
MsgfpErrCreateProcess = 'Failed to start process "%1:s".%0:sError message: %2:d "%3:s".%0:s%4:s';
@ -57,37 +78,55 @@ const
fpErrNoError = TFpErrorCode(0); // not an error
fpErrAnyError = TFpErrorCode(1);
fpErrSymbolNotFound = TFpErrorCode(2);
fpErrNoMemberWithName = TFpErrorCode(3);
fpErrorNotAStructure = TFpErrorCode(4);
fpErrorBadFloatSize = TFpErrorCode(5);
fpErrAddressIsNil = TFpErrorCode(6);
fpErrPasParserInvalidExpression = TFpErrorCode(24);
fpErrPasParserUnexpectedToken = TFpErrorCode(25);
fpErrPasParserMissingExprAfterComma = TFpErrorCode(26);
fpErrPasParserMissingIndexExpression = TFpErrorCode(27);
fpErrInvalidNumber = TFpErrorCode(28);
fpErrCannotDereferenceType = TFpErrorCode(29);
fpErrTypeHasNoIndex = TFpErrorCode(30);
fpErrChangeVariableNotSupported = TFpErrorCode(31);
fpErrSymbolNotFound_p = TFpErrorCode( 2);
fpErrNoMemberWithName = TFpErrorCode( 3);
fpErrorNotAStructure = TFpErrorCode( 4);
fpErrorBadFloatSize = TFpErrorCode( 5);
fpErrAddressIsNil = TFpErrorCode( 6);
fpErrIndexOutOfRange = TFpErrorCode( 7);
fpErrTypeNotIndexable = TFpErrorCode( 8);
fpErrExpectedOrdinalVal_p = TFpErrorCode( 9);
fpErrCannotCastToPointer_p = TFpErrorCode(10);
fpErrCannotDeref_p = TFpErrorCode(11);
// 100 memreader error
fpInternalErrFailedReadMem = TFpErrorCode(100);
fpInternalErrCanNotReadInvalidMem = TFpErrorCode(101);
fpErrReadMemSizeLimit = TFpErrorCode(102);
fpErrCanNotReadMemAtAddr = TFpErrorCode(103);
fpErrFailedReadRegister = TFpErrorCode(104);
fpInternalErrCanNotWriteInvalidMem= TFpErrorCode(105);
fpErrFailedWriteMem = TFpErrorCode(106);
fpErrCanNotWriteMemAtAddr = TFpErrorCode(107);
fpInternalErrFailedReadMem = TFpErrorCode(100);
fpInternalErrCanNotReadInvalidMem = TFpErrorCode(101);
fpErrReadMemSizeLimit = TFpErrorCode(102);
fpErrCanNotReadMemAtAddr = TFpErrorCode(103);
fpErrFailedReadRegister = TFpErrorCode(104);
fpInternalErrCanNotWriteInvalidMem = TFpErrorCode(105);
fpErrFailedWriteMem = TFpErrorCode(106);
fpErrCanNotWriteMemAtAddr = TFpErrorCode(107);
// 200 LocationParser
fpErrLocationParser = TFpErrorCode(200);
fpErrLocationParserMemRead = TFpErrorCode(201);
fpErrLocationParserInit = TFpErrorCode(202);
fpErrLocationParserMinStack = TFpErrorCode(203);
fpErrLocationParserNoAddressOnStack = TFpErrorCode(204);
fpErrLocationParser = TFpErrorCode(200);
fpErrLocationParserMemRead = TFpErrorCode(201);
fpErrLocationParserInit = TFpErrorCode(202);
fpErrLocationParserMinStack = TFpErrorCode(203);
fpErrLocationParserNoAddressOnStack = TFpErrorCode(204);
// 500 parser
fpErrPasParserEmptyExpression = TFpErrorCode(500);
fpErrPasParserUnexpectedEndOfExpression = TFpErrorCode(501);
fpErrPasParserInvalidExpression = TFpErrorCode(502);
fpErrPasParserUnexpectedToken_p = TFpErrorCode(503);
fpErrPasParserUnknownIntrinsic_p = TFpErrorCode(504);
fpErrPasParserMissingOpenBracket_p = TFpErrorCode(530);
fpErrPasParserWrongOpenBracket_p = TFpErrorCode(531);
fpErrPasParserMissingIndexExpression = TFpErrorCode(532);
fpErrPasParserMissingExprAfterComma = TFpErrorCode(533);
fpErrPasParserIndexError_Wrapper = TFpErrorCode(534);
fpErrPasParserUnterminatedString_p = TFpErrorCode(535);
fpErrPasParserExpectedNumber_p = TFpErrorCode(536);
fpErrPasParser_AtStart = TFpErrorCode(595);
fpErrPasParser_PositionAfter = TFpErrorCode(596);
fpErrPasParser_Position = TFpErrorCode(597);
fpErrTypeHasNoIndex = TFpErrorCode(1540);
fpErrChangeVariableNotSupported = TFpErrorCode(1541);
// 10000 Process/Control errors
fpErrCreateProcess = TFpErrorCode(10000);
@ -113,9 +152,13 @@ type
end;
end;
TFpErrorTextLookup = function(AnErrorCode: TFpErrorCode; out AnErrorText: AnsiString): Boolean;
{ TFpErrorHandler }
TFpErrorHandler = class
private
FOnErrorTextLookup: TFpErrorTextLookup;
protected
function GetErrorRawString(AnErrorCode: TFpErrorCode): string;
public
@ -123,6 +166,8 @@ type
function CreateError(AnErrorCode: TFpErrorCode; AnError: TFpError; AData: array of const): TFpError;
function ErrorAsString(AnError: TFpError): string; virtual;
function ErrorAsString(AnErrorCode: TFpErrorCode; AData: array of const): string; virtual;
public
property OnErrorTextLookup: TFpErrorTextLookup read FOnErrorTextLookup write FOnErrorTextLookup;
end;
function GetFpErrorHandler: TFpErrorHandler;
@ -136,6 +181,7 @@ function NoError: TFpError; inline;
function CreateError(AnErrorCode: TFpErrorCode): TFpError; inline;
function CreateError(AnErrorCode: TFpErrorCode; AData: array of const): TFpError; inline;
function CreateError(AnErrorCode: TFpErrorCode; AnError: TFpError; AData: array of const): TFpError; inline;
function CreateError(AnErrorCode: TFpErrorCode; AData: array of const; AnError: TFpError): TFpError; inline;
function dbgs(AnError: TFpError): string; overload;
@ -190,6 +236,12 @@ begin
Result := ErrorHandler.CreateError(AnErrorCode, AnError, AData);
end;
function CreateError(AnErrorCode: TFpErrorCode; AData: array of const;
AnError: TFpError): TFpError;
begin
Result := ErrorHandler.CreateError(AnErrorCode, AnError, AData);
end;
function dbgs(AnError: TFpError): string;
begin
if IsError(AnError) then
@ -202,22 +254,44 @@ end;
function TFpErrorHandler.GetErrorRawString(AnErrorCode: TFpErrorCode): string;
begin
Result := '';
if FOnErrorTextLookup <> nil then
if FOnErrorTextLookup(AnErrorCode, Result) then
exit;
case AnErrorCode of
fpErrAnyError: Result := MsgfpErrAnyError;
fpErrAddressIsNil: Result := MsgfpErrAddressIsNil;
fpErrSymbolNotFound: Result := MsgfpErrSymbolNotFound;
fpErrSymbolNotFound_p: Result := MsgfpErrSymbolNotFound_p;
fpErrNoMemberWithName: Result := MsgfpErrNoMemberWithName;
fpErrorNotAStructure: Result := MsgfpErrorNotAStructure;
fpErrorBadFloatSize: Result := MsgfpErrorBadFloatSize;
fpErrIndexOutOfRange: Result := MsgfpErrIndexOutOfRange;
fpErrTypeNotIndexable: Result := MsgfpErrTypeNotIndexable;
fpErrExpectedOrdinalVal_p: Result := MsgfpErrExpectedOrdinalVal_p;
fpErrCannotCastToPointer_p: Result := MsgfpErrCannotCastToPointer_p;
fpErrCannotDeref_p: Result := MsgfpErrCannotDeref_p;
fpErrPasParserInvalidExpression: Result := MsgfpErrPasParserInvalidExpression;
fpErrPasParserUnexpectedToken: Result := MsgfpErrPasParserUnexpectedToken;
fpErrPasParserMissingExprAfterComma: Result := MsgfpErrPasParserMissingExprAfterComma;
fpErrPasParserMissingIndexExpression: Result := MsgfpErrPasParserMissingIndexExpression;
fpErrInvalidNumber: Result := MsgfpErrInvalidNumber;
fpErrCannotDereferenceType: Result := MsgfpErrCannotDereferenceType;
fpErrTypeHasNoIndex: Result := MsgfpErrTypeHasNoIndex;
fpErrChangeVariableNotSupported: Result := MsgfpErrChangeVariableNotSupported;
fpErrPasParserEmptyExpression: Result := MsgfpErrPasParserEmptyExpression;
fpErrPasParserUnexpectedEndOfExpression: Result := MsgfpErrPasParserUnexpectedEndOfExpression;
fpErrPasParserInvalidExpression: Result := MsgfpErrPasParserInvalidExpression;
fpErrPasParserUnexpectedToken_p: Result := MsgfpErrPasParserUnexpectedToken_p;
fpErrPasParserUnknownIntrinsic_p: Result := MsgfpErrPasParserUnknownIntrinsic_p;
fpErrPasParserMissingOpenBracket_p: Result := MsgfpErrPasParserMissingOpenBracket_p;
fpErrPasParserWrongOpenBracket_p: Result := MsgfpErrPasParserWrongOpenBracket_p;
fpErrPasParserMissingIndexExpression: Result := MsgfpErrPasParserMissingIndexExpression;
fpErrPasParserMissingExprAfterComma: Result := MsgfpErrPasParserMissingExprAfterComma;
fpErrPasParserIndexError_Wrapper: Result := MsgfpErrPasParserIndexError_Wrapper;
fpErrPasParserUnterminatedString_p: Result := MsgfpErrPasParserUnterminatedString_p;
fpErrPasParserExpectedNumber_p: Result := MsgfpErrPasParserExpectedNumber_p;
fpErrPasParser_AtStart: Result := MsgfpErrPasParser_AtStart;
fpErrPasParser_PositionAfter: Result := MsgfpErrPasParser_PositionAfter;
fpErrPasParser_Position: Result := MsgfpErrPasParser_Position;
fpErrTypeHasNoIndex: Result := MsgfpErrTypeHasNoIndex;
fpErrChangeVariableNotSupported: Result := MsgfpErrChangeVariableNotSupported;
fpInternalErrCanNotReadInvalidMem: Result := MsgfpInternalErrCanNotReadInvalidMem;
fpErrReadMemSizeLimit: Result := MsgfpErrReadMemSizeLimit;
@ -344,7 +418,7 @@ begin
try
Result := Format(s, RealData);
except
Result := 'Internal Error(2): ' + IntToStr(AnErrorCode);
Result := 'Internal Error: "' + s + '"';
end;
end;

View File

@ -34,6 +34,9 @@ uses
Classes, sysutils, math, DbgIntfBaseTypes, FpDbgInfo, FpdMemoryTools,
FpErrorMessages, FpDbgDwarf, {$ifdef FORCE_LAZLOGGER_DUMMY} LazLoggerDummy {$else} LazLoggerBase {$endif}, LazClasses;
const
MAX_ERR_EXPR_QUOTE_LEN = 200;
type
TFpPascalExpressionPartList= class;
@ -77,7 +80,8 @@ type
function GetResultValue: TFpValue;
function GetValid: Boolean;
procedure SetError(AMsg: String); // deprecated;
procedure SetError(AnErrorCode: TFpErrorCode; AData: array of const);
procedure SetError(AnErrorCode: TFpErrorCode; const AnNestedErr: TFpError = nil);
procedure SetError(AnErrorCode: TFpErrorCode; AData: array of const; const AnNestedErr: TFpError = nil);
procedure SetError(const AnErr: TFpError);
function PosFromPChar(APChar: PChar): Integer;
function LookupIntrinsic(AStart: PChar; ALen: Integer): TFpIntrinsicFunc;
@ -143,7 +147,10 @@ type
procedure SetStartChar(AValue: PChar);
procedure SetError(AMsg: String = ''); // deprecated;
procedure SetError(APart: TFpPascalExpressionPart; AMsg: String = ''); // deprecated;
procedure SetError(AnErrorCode: TFpErrorCode; AData: array of const);
function CreateErrorWithPos(AnErrorCode: TFpErrorCode; AData: array of const; APos: integer = -1): TFpError;
procedure SetErrorWithPos(AnErrorCode: TFpErrorCode; AData: array of const);
//procedure SetError(AnErrorCode: TFpErrorCode; const AnNestedErr: TFpError = nil);
procedure SetError(AnErrorCode: TFpErrorCode; AData: array of const; const AnNestedErr: TFpError = nil);
procedure SetError(AnError: TFpError);
protected
function DebugText(AIndent: String; {%H-}AWithResults: Boolean): String; virtual; // Self desc only
@ -176,6 +183,8 @@ type
procedure HandleEndOfExpression; virtual;
function GetText(AMaxLen: Integer=0): String;
function GetPos: Integer;
function GetFullText(AMaxLen: Integer=0): String; virtual; // including children
property StartChar: PChar read FStartChar write SetStartChar;
property EndChar: PChar read FEndChar write SetEndChar;
property Parent: TFpPascalExpressionPartContainer read FParent write SetParent;
@ -201,6 +210,7 @@ type
function DebugDump(AIndent: String; AWithResults: Boolean): String; override;
public
destructor Destroy; override;
function GetFullText(AMaxLen: Integer=0): String; virtual; // including children
function Add(APart: TFpPascalExpressionPart): Integer;
function IndexOf(APart: TFpPascalExpressionPart): Integer;
procedure Clear;
@ -604,6 +614,7 @@ type
TPasParserSymbolPointer = class(TFpSymbol)
private
FExpressionPart: TFpPascalExpressionPart;
FPointerLevels: Integer;
FPointedTo: TFpSymbol;
FContext: TFpDbgLocationContext;
@ -612,8 +623,8 @@ type
procedure TypeInfoNeeded; override;
function DoReadSize(const AValueObj: TFpValue; out ASize: TFpDbgValueSize): Boolean; override;
public
constructor Create(const APointedTo: TFpSymbol; AContext: TFpDbgLocationContext; APointerLevels: Integer);
constructor Create(const APointedTo: TFpSymbol; AContext: TFpDbgLocationContext);
constructor Create(const APointedTo: TFpSymbol; AnExpressionPart: TFpPascalExpressionPart; APointerLevels: Integer);
constructor Create(const APointedTo: TFpSymbol; AnExpressionPart: TFpPascalExpressionPart);
destructor Destroy; override;
function TypeCastValue(AValue: TFpValue): TFpValue; override;
end;
@ -622,13 +633,14 @@ type
TPasParserSymbolArrayDeIndex = class(TFpSymbolForwarder) // 1 index level off
private
FExpressionPart: TFpPascalExpressionPart;
FArray: TFpSymbol;
protected
//procedure ForwardToSymbolNeeded; override;
function GetNestedSymbolCount: Integer; override;
function GetNestedSymbol(AIndex: Int64): TFpSymbol; override;
public
constructor Create(const AnArray: TFpSymbol);
constructor Create(AnExpressionPart: TFpPascalExpressionPart; const AnArray: TFpSymbol);
destructor Destroy; override;
end;
@ -641,10 +653,11 @@ type
TFpPasParserValue = class(TFpValue)
private
FContext: TFpDbgLocationContext;
FExpressionPart: TFpPascalExpressionPart;
protected
function DebugText(AIndent: String): String; virtual;
public
constructor Create(AContext: TFpDbgLocationContext);
constructor Create(AnExpressionPart: TFpPascalExpressionPart);
property Context: TFpDbgLocationContext read FContext;
end;
@ -669,7 +682,7 @@ type
function GetDerefAddress: TFpDbgMemLocation; override;
function GetMember(AIndex: Int64): TFpValue; override;
public
constructor Create(AValue: TFpValue; ATypeInfo: TFpSymbol; AContext: TFpDbgLocationContext);
constructor Create(AValue: TFpValue; ATypeInfo: TFpSymbol; AnExpressionPart: TFpPascalExpressionPart);
destructor Destroy; override;
end;
@ -684,7 +697,7 @@ type
protected
function GetDbgSymbol: TFpSymbol; override; // returns a TPasParserSymbolPointer
public
constructor Create(ATypeInfo: TFpSymbol; AContext: TFpDbgLocationContext);
constructor Create(ATypeInfo: TFpSymbol; AnExpressionPart: TFpPascalExpressionPart);
destructor Destroy; override;
procedure IncRefLevel;
function GetTypeCastedValue(ADataVal: TFpValue): TFpValue; override;
@ -709,8 +722,8 @@ type
function GetAsCardinal: QWord; override; // reads men
function GetTypeInfo: TFpSymbol; override; // TODO: Cardinal? Why? // TODO: does not handle AOffset
public
constructor Create(AValue: TFpValue; AContext: TFpDbgLocationContext);
constructor Create(AValue: TFpValue; AContext: TFpDbgLocationContext; AOffset: Int64);
constructor Create(AValue: TFpValue; AnExpressionPart: TFpPascalExpressionPart);
constructor Create(AValue: TFpValue; AnExpressionPart: TFpPascalExpressionPart; AOffset: Int64);
destructor Destroy; override;
end;
@ -734,7 +747,7 @@ type
function GetAsString: AnsiString; override;
function GetAsWideString: WideString; override;
public
constructor Create(AValue: TFpValue; AContext: TFpDbgLocationContext);
constructor Create(AValue: TFpValue; AnExpressionPart: TFpPascalExpressionPart);
destructor Destroy; override;
property PointedToValue: TFpValue read GetPointedToValue;
end;
@ -757,6 +770,17 @@ begin
Result := DbgSName(AVal);
end;
function ValueToExprText(AnValue: TFpValue; AMaxLen: Integer = 0): String;
begin
if AnValue is TFpPasParserValue then
Result := TFpPasParserValue(AnValue).FExpressionPart.GetFullText(AMaxLen)
else
if AnValue.DbgSymbol <> nil then
Result := AnValue.DbgSymbol.Name
else
Result := '?';
end;
procedure TFpPascalExpressionPartList.Clear;
begin
assert(False, 'TFpPascalExpressionPartList.Clear: False');
@ -804,9 +828,10 @@ begin
Result := AIndent + DbgSName(Self) + ' DbsSym='+DbgSName(DbgSymbol)+' Type='+DbgSName(TypeInfo) + LineEnding;
end;
constructor TFpPasParserValue.Create(AContext: TFpDbgLocationContext);
constructor TFpPasParserValue.Create(AnExpressionPart: TFpPascalExpressionPart);
begin
FContext := AContext;
FExpressionPart := AnExpressionPart;
FContext := AnExpressionPart.Expression.Context.LocationContext;
inherited Create;
end;
@ -872,7 +897,10 @@ begin
end;
end
else begin
SetLastError(CreateError(fpErrAnyError, ['']));
if FValue is TFpPasParserValue then
SetLastError(FExpressionPart.CreateErrorWithPos(fpErrCannotCastToPointer_p,
[ValueToExprText(FValue, MAX_ERR_EXPR_QUOTE_LEN)]
));
end;
end;
@ -974,7 +1002,9 @@ begin
ti := FTypeSymbol.TypeInfo;
addr := DerefAddress;
if not IsTargetAddr(addr) then begin
//LastError := CreateError(fpErrAnyError, ['Internal dereference error']);
SetLastError(FExpressionPart.CreateErrorWithPos(fpErrCannotDeref_p,
[ValueToExprText(FValue, MAX_ERR_EXPR_QUOTE_LEN)]
));
exit;
end;
{$PUSH}{$R-}{$Q-} // TODO: check overflow
@ -1002,9 +1032,9 @@ begin
end;
constructor TFpPasParserValueCastToPointer.Create(AValue: TFpValue;
ATypeInfo: TFpSymbol; AContext: TFpDbgLocationContext);
ATypeInfo: TFpSymbol; AnExpressionPart: TFpPascalExpressionPart);
begin
inherited Create(AContext);
inherited Create(AnExpressionPart);
FValue := AValue;
FValue.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FValue, 'TPasParserSymbolValueCastToPointer'){$ENDIF};
FTypeSymbol := ATypeInfo;
@ -1032,16 +1062,16 @@ end;
function TFpPasParserValueMakeReftype.GetDbgSymbol: TFpSymbol;
begin
if FTypeSymbol = nil then begin
FTypeSymbol := TPasParserSymbolPointer.Create(FSourceTypeSymbol, FContext, FRefLevel);
FTypeSymbol := TPasParserSymbolPointer.Create(FSourceTypeSymbol, FExpressionPart, FRefLevel);
{$IFDEF WITH_REFCOUNT_DEBUG}FTypeSymbol.DbgRenameReference(@FSourceTypeSymbol, 'TPasParserSymbolValueMakeReftype'){$ENDIF};
end;
Result := FTypeSymbol;
end;
constructor TFpPasParserValueMakeReftype.Create(ATypeInfo: TFpSymbol;
AContext: TFpDbgLocationContext);
AnExpressionPart: TFpPascalExpressionPart);
begin
inherited Create(AContext);
inherited Create(AnExpressionPart);
FSourceTypeSymbol := ATypeInfo;
FSourceTypeSymbol.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FSourceTypeSymbol, 'TPasParserSymbolValueMakeReftype'){$ENDIF};
FRefLevel := 1;
@ -1161,15 +1191,15 @@ begin
end;
constructor TFpPasParserValueDerefPointer.Create(AValue: TFpValue;
AContext: TFpDbgLocationContext);
AnExpressionPart: TFpPascalExpressionPart);
begin
Create(AValue, AContext, 0);
Create(AValue, AnExpressionPart, 0);
end;
constructor TFpPasParserValueDerefPointer.Create(AValue: TFpValue;
AContext: TFpDbgLocationContext; AOffset: Int64);
AnExpressionPart: TFpPascalExpressionPart; AOffset: Int64);
begin
inherited Create(AContext);
inherited Create(AnExpressionPart);
FValue := AValue;
FValue.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FValue, 'TPasParserDerefPointerSymbolValue'){$ENDIF};
FAddressOffset := AOffset;
@ -1225,7 +1255,7 @@ begin
if FValue.TypeInfo = nil then
exit;
FTypeInfo := TPasParserSymbolPointer.Create(FValue.TypeInfo, FContext);
FTypeInfo := TPasParserSymbolPointer.Create(FValue.TypeInfo, FExpressionPart);
{$IFDEF WITH_REFCOUNT_DEBUG}FTypeInfo.DbgRenameReference(@FTypeInfo, 'TPasParserAddressOfSymbolValue');{$ENDIF}
Result := FTypeInfo;
end;
@ -1325,9 +1355,9 @@ begin
end;
constructor TFpPasParserValueAddressOf.Create(AValue: TFpValue;
AContext: TFpDbgLocationContext);
AnExpressionPart: TFpPascalExpressionPart);
begin
inherited Create(AContext);
inherited Create(AnExpressionPart);
FValue := AValue;
FValue.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FValue, 'TPasParserAddressOfSymbolValue'){$ENDIF};
end;
@ -1351,8 +1381,10 @@ begin
Result := inherited GetNestedSymbol(AIndex + 1);
end;
constructor TPasParserSymbolArrayDeIndex.Create(const AnArray: TFpSymbol);
constructor TPasParserSymbolArrayDeIndex.Create(
AnExpressionPart: TFpPascalExpressionPart; const AnArray: TFpSymbol);
begin
FExpressionPart := AnExpressionPart;
FArray := AnArray;
FArray.AddReference;
inherited Create('');
@ -1377,7 +1409,7 @@ begin
exit;
end;
assert(FPointerLevels > 1, 'TPasParserSymbolPointer.TypeInfoNeeded: FPointerLevels > 1');
t := TPasParserSymbolPointer.Create(FPointedTo, FContext, FPointerLevels-1);
t := TPasParserSymbolPointer.Create(FPointedTo, FExpressionPart, FPointerLevels-1);
SetTypeInfo(t);
t.ReleaseReference;
end;
@ -1390,10 +1422,11 @@ begin
end;
constructor TPasParserSymbolPointer.Create(const APointedTo: TFpSymbol;
AContext: TFpDbgLocationContext; APointerLevels: Integer);
AnExpressionPart: TFpPascalExpressionPart; APointerLevels: Integer);
begin
inherited Create('');
FContext := AContext;
FExpressionPart := AnExpressionPart;
FContext := FExpressionPart.Expression.Context.LocationContext;
FPointerLevels := APointerLevels;
FPointedTo := APointedTo;
FPointedTo.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(FPointedTo, 'TPasParserSymbolPointer'){$ENDIF};
@ -1404,9 +1437,9 @@ begin
end;
constructor TPasParserSymbolPointer.Create(const APointedTo: TFpSymbol;
AContext: TFpDbgLocationContext);
AnExpressionPart: TFpPascalExpressionPart);
begin
Create(APointedTo, AContext, 1);
Create(APointedTo, AnExpressionPart, 1);
end;
destructor TPasParserSymbolPointer.Destroy;
@ -1417,7 +1450,7 @@ end;
function TPasParserSymbolPointer.TypeCastValue(AValue: TFpValue): TFpValue;
begin
Result := TFpPasParserValueCastToPointer.Create(AValue, Self, FContext);
Result := TFpPasParserValueCastToPointer.Create(AValue, Self, FExpressionPart);
end;
@ -1442,7 +1475,10 @@ var
begin
Result := nil;
assert(Count >= 2, 'TFpPascalExpressionPartBracketIndex.DoGetResultValue: Count >= 2');
if Count < 2 then exit;
if Count < 2 then begin
SetError(fpErrPasParserMissingIndexExpression, [GetFullText(MAX_ERR_EXPR_QUOTE_LEN), GetPos]);
exit;
end;
TmpVal := Items[0].ResultValue;
if TmpVal = nil then exit;
@ -1467,7 +1503,10 @@ begin
TmpVal2 := TmpVal.Member[TmpIndex.AsCardinal]
else
begin
SetError('Can not calculate Index');
SetError(fpErrPasParserIndexError_Wrapper,
[Items[0].GetFullText(MAX_ERR_EXPR_QUOTE_LEN), Items[0].GetPos],
CreateErrorWithPos(fpErrExpectedOrdinalVal_p, [Items[i].GetFullText(MAX_ERR_EXPR_QUOTE_LEN)], Items[i].GetPos)
);
TmpVal.ReleaseReference;
exit;
end;
@ -1481,7 +1520,10 @@ begin
Offs := Int64(TmpIndex.AsCardinal)
else
begin
SetError('Can not calculate Index');
SetError(fpErrPasParserIndexError_Wrapper,
[Items[0].GetFullText(MAX_ERR_EXPR_QUOTE_LEN), Items[0].GetPos],
CreateErrorWithPos(fpErrExpectedOrdinalVal_p, [Items[i].GetFullText(MAX_ERR_EXPR_QUOTE_LEN)], Items[i].GetPos)
);
TmpVal.ReleaseReference;
exit;
end;
@ -1501,7 +1543,10 @@ begin
TmpVal2 := TmpVal.Member[Offs];
if IsError(TmpVal.LastError) then
SetError('Error dereferencing'); // TODO: set correct error
SetError(fpErrPasParserIndexError_Wrapper,
[Items[0].GetFullText(MAX_ERR_EXPR_QUOTE_LEN), Items[0].GetPos],
TmpVal.LastError
);
end;
skString, skAnsiString: begin
//TODO: move to FpDwarfValue.member ??
@ -1521,13 +1566,19 @@ begin
Offs := Int64(TmpIndex.AsCardinal)
else
begin
SetError('Can not calculate Index');
SetError(fpErrPasParserIndexError_Wrapper,
[Items[0].GetFullText(MAX_ERR_EXPR_QUOTE_LEN), Items[0].GetPos],
CreateErrorWithPos(fpErrExpectedOrdinalVal_p, [Items[i].GetFullText(MAX_ERR_EXPR_QUOTE_LEN)], Items[i].GetPos)
);
TmpVal.ReleaseReference;
exit;
end;
if (not TmpVal.GetSubString(Offs, 1, v)) or (v = '') then begin
SetError('Index out of range');
SetError(fpErrPasParserIndexError_Wrapper,
[Items[0].GetFullText(MAX_ERR_EXPR_QUOTE_LEN), Items[0].GetPos],
CreateError(fpErrIndexOutOfRange, [Offs])
);
TmpVal.ReleaseReference;
exit;
end;
@ -1558,13 +1609,19 @@ begin
Offs := Int64(TmpIndex.AsCardinal)
else
begin
SetError('Can not calculate Index');
SetError(fpErrPasParserIndexError_Wrapper,
[Items[0].GetFullText(MAX_ERR_EXPR_QUOTE_LEN), Items[0].GetPos],
CreateErrorWithPos(fpErrExpectedOrdinalVal_p, [Items[i].GetFullText(MAX_ERR_EXPR_QUOTE_LEN)], Items[i].GetPos)
);
TmpVal.ReleaseReference;
exit;
end;
if (not TmpVal.GetSubWideString(Offs, 1, w)) or (w='') then begin
SetError('Index out of range');
SetError(fpErrPasParserIndexError_Wrapper,
[Items[0].GetFullText(MAX_ERR_EXPR_QUOTE_LEN), Items[0].GetPos],
CreateError(fpErrIndexOutOfRange, [Offs])
);
TmpVal.ReleaseReference;
exit;
end;
@ -1577,7 +1634,10 @@ begin
end;
else
begin
SetError(fpErrTypeHasNoIndex, [GetText]);
SetError(fpErrPasParserIndexError_Wrapper,
[Items[0].GetFullText(MAX_ERR_EXPR_QUOTE_LEN), Items[0].GetPos],
CreateError(fpErrTypeNotIndexable, [])
);
TmpVal.ReleaseReference;
exit;
end;
@ -1660,7 +1720,7 @@ procedure TFpPascalExpressionPartBracketIndex.DoHandleEndOfExpression;
begin
inherited DoHandleEndOfExpression;
if (Count < 2) then
SetError(fpErrPasParserMissingIndexExpression, [GetText]);
SetError(fpErrPasParserMissingIndexExpression, [GetFullText(MAX_ERR_EXPR_QUOTE_LEN), GetPos]);
end;
function TFpPascalExpressionPartBracketIndex.HandleSeparator(
@ -1935,7 +1995,7 @@ begin
if Result = nil then begin
if CompareText(s, 'nil') = 0 then begin
tmp := TFpValueConstAddress.Create(NilLoc);
Result := TFpPasParserValueAddressOf.Create(tmp, Expression.Context.LocationContext);
Result := TFpPasParserValueAddressOf.Create(tmp, Self);
tmp.ReleaseReference;
{$IFDEF WITH_REFCOUNT_DEBUG}Result.DbgRenameReference(nil, 'DoGetResultValue');{$ENDIF}
end
@ -1950,7 +2010,7 @@ begin
{$IFDEF WITH_REFCOUNT_DEBUG}Result.DbgRenameReference(nil, 'DoGetResultValue');{$ENDIF}
end
else begin
SetError(fpErrSymbolNotFound, [GetText]);
SetErrorWithPos(fpErrSymbolNotFound_p, [GetText]);
exit;
end;
end
@ -1964,7 +2024,7 @@ end;
function GetFirstToken(AText: PChar): String;
begin
Result := AText[0];
if AText^ in ['a'..'z', 'A'..'Z', '_', '0'..'9'] then begin
if AText^ in ['a'..'z', 'A'..'Z', '_', '0'..'9', '$', '&', '%'] then begin
inc(AText);
while (AText^ in ['a'..'z', 'A'..'Z', '_', '0'..'9']) and (Length(Result) < 200) do begin
Result := Result + AText[0];
@ -2420,7 +2480,7 @@ begin
ThousandSeparator := ts;
if e <> 0 then begin
Result := nil;
SetError(fpErrInvalidNumber, [GetText]);
SetErrorWithPos(fpErrPasParserExpectedNumber_p, [GetText(MAX_ERR_EXPR_QUOTE_LEN)]);
exit;
end;
@ -2451,7 +2511,7 @@ begin
if not ok then begin
Result := nil;
SetError(fpErrInvalidNumber, [GetText]);
SetErrorWithPos(fpErrPasParserExpectedNumber_p, [GetText(MAX_ERR_EXPR_QUOTE_LEN)]);
exit;
end;
@ -2490,7 +2550,27 @@ end;
procedure TFpPascalExpression.Parse;
var
CurPtr, EndPtr, TokenEndPtr: PChar;
CurPart, NewPart: TFpPascalExpressionPart;
CurPart, PrevPart, NewPart: TFpPascalExpressionPart;
// "Foo-Error 'token' at pos N after 'prev token'"
procedure SetParserError(AnErrorCode: TFpErrorCode);
begin
if PrevPart = nil
then SetError(AnErrorCode, [GetFirstToken(CurPtr)], CreateError(fpErrPasParser_AtStart, []) )
else SetError(AnErrorCode, [GetFirstToken(CurPtr)], CreateError(fpErrPasParser_PositionAfter, [PosFromPChar(CurPtr), PrevPart.GetText(MAX_ERR_EXPR_QUOTE_LEN)]) );
end;
procedure SetParserError(AnErrorCode: TFpErrorCode; AData: array of const);
begin
if PrevPart = nil
then SetError(AnErrorCode, AData, CreateError(fpErrPasParser_AtStart, []) )
else SetError(AnErrorCode, AData, CreateError(fpErrPasParser_PositionAfter, [PosFromPChar(CurPtr), PrevPart.GetText(MAX_ERR_EXPR_QUOTE_LEN)]) );
end;
procedure SetParserErrorPosOnly(AnErrorCode: TFpErrorCode);
begin
if PrevPart = nil
then SetError(AnErrorCode, [], CreateError(fpErrPasParser_AtStart, []) )
else SetError(AnErrorCode, [], CreateError(fpErrPasParser_PositionAfter, [PosFromPChar(CurPtr), PrevPart.GetText(MAX_ERR_EXPR_QUOTE_LEN)]) );
end;
procedure AddPart(AClass: TFpPascalExpressionPartClass);
begin
@ -2507,7 +2587,7 @@ var
procedure AddIntrinsic(AnIntrinsic: TFpIntrinsicFunc);
begin
if AnIntrinsic = ifErrorNotFound then
SetError('Unknown build-in')
SetParserError(fpErrPasParserUnknownIntrinsic_p)
else
NewPart := TFpPascalExpressionPartIntrinsic.Create(Self, CurPtr, TokenEndPtr-1, AnIntrinsic);
end;
@ -2588,9 +2668,9 @@ var
1: AddPart(TFpPascalExpressionPartOperatorMemberOf);
2: if CurPart.SurroundingBracket is TFpPascalExpressionPartBracketIndex
then AddPart(TFpPascalExpressionPartOperatorArraySlice)
else SetError('Failed parsing ...');
else SetParserError(fpErrPasParserUnexpectedToken_p);
otherwise
SetError('Failed parsing ...');
SetParserError(fpErrPasParserUnexpectedToken_p);
end;
end;
@ -2620,16 +2700,16 @@ var
BracketPart: TFpPascalExpressionPartBracket;
begin
if (CurPart=nil) then begin
SetError(fpErrPasParserUnexpectedToken, [GetFirstToken(CurPtr), PosFromPChar(CurPtr)]);
SetParserError(fpErrPasParserUnexpectedToken_p);
exit;
end;
BracketPart := CurPart.SurroundingBracket;
if BracketPart = nil then begin
SetError('Closing bracket found without opening')
SetParserError(fpErrPasParserMissingOpenBracket_p);
end
else
if not (BracketPart is ABracketClass) then begin
SetError('Mismatch bracket')
SetParserError(fpErrPasParserWrongOpenBracket_p, [GetFirstToken(CurPtr), PosFromPChar(BracketPart.StartChar), BracketPart.GetText(MAX_ERR_EXPR_QUOTE_LEN)]);
end
else begin
TFpPascalExpressionPartBracket(BracketPart).CloseBracket;
@ -2666,10 +2746,10 @@ var
while TokenEndPtr^ in ['0'..'1'] do inc(TokenEndPtr);
'0'..'9':
if (CurPtr^ = '0') and ((CurPtr + 1)^ in ['x', 'X']) and
((CurPtr + 2)^ in ['a'..'z', 'A'..'Z', '0'..'9'])
((CurPtr + 2)^ in ['a'..'f', 'A'..'F', '0'..'9'])
then begin
inc(TokenEndPtr, 2);
while TokenEndPtr^ in ['a'..'z', 'A'..'Z', '0'..'9'] do inc(TokenEndPtr);
while TokenEndPtr^ in ['a'..'f', 'A'..'F', '0'..'9'] do inc(TokenEndPtr);
end
else begin
while TokenEndPtr^ in ['0'..'9'] do inc(TokenEndPtr);
@ -2678,15 +2758,19 @@ var
inc(TokenEndPtr);
while TokenEndPtr^ in ['0'..'9'] do inc(TokenEndPtr);
if TokenEndPtr^ in ['a'..'z', 'A'..'Z', '_'] then
SetError(fpErrPasParserUnexpectedToken, [GetFirstToken(CurPtr), PosFromPChar(CurPtr)])
SetParserError(fpErrPasParserUnexpectedToken_p)
else
AddPart(TFpPascalExpressionPartConstantNumberFloat);
exit;
end;
end;
end;
if TokenEndPtr^ in ['a'..'z', 'A'..'Z', '_'] then
SetError(fpErrPasParserUnexpectedToken, [GetFirstToken(CurPtr), PosFromPChar(CurPtr)])
if (TokenEndPtr < EndPtr) and (TokenEndPtr^ in ['0'..'9', 'a'..'z', 'A'..'Z']) or
(TokenEndPtr[-1] in ['x', '$', '&', '%'])
then begin
SetError(fpErrPasParserExpectedNumber_p, [GetFirstToken(CurPtr+1)], CreateError(fpErrPasParser_PositionAfter, [PosFromPChar(CurPtr+1), '#']) );
exit;
end
else
AddPart(TFpPascalExpressionPartConstantNumber);
end;
@ -2703,7 +2787,7 @@ var
procedure HandleComma;
begin
if (CurPart=nil) or (not CurPart.HandleSeparator(ppstComma, CurPart)) then
SetError(fpErrPasParserUnexpectedToken, [GetFirstToken(CurPtr), PosFromPChar(CurPtr)]);
SetParserError(fpErrPasParserUnexpectedToken_p);
end;
procedure AddConstChar;
@ -2727,36 +2811,47 @@ var
while (TokenEndPtr < EndPtr) and (TokenEndPtr^ <> '''') do
inc(TokenEndPtr);
str := str + copy(p, 1, TokenEndPtr - p);
if (TokenEndPtr < EndPtr) and (TokenEndPtr^ = '''') then
inc(TokenEndPtr)
else
SetError(fpErrPasParserInvalidExpression, []); // unterminated string
if (TokenEndPtr < EndPtr) and (TokenEndPtr^ = '''') then begin
inc(TokenEndPtr);
end
else begin
SetParserErrorPosOnly(fpErrPasParserUnterminatedString_p);
exit;
end;
end;
'#': begin
WasQuote := False;
inc(TokenEndPtr);
if not (TokenEndPtr < EndPtr) then
SetError(fpErrPasParserInvalidExpression, []);
if not (TokenEndPtr < EndPtr) then begin
SetError(fpErrPasParserUnexpectedEndOfExpression, [GetFirstToken(CurPtr)]);
exit;
end;
p := TokenEndPtr;
case TokenEndPtr^ of
'$': begin
inc(TokenEndPtr);
if (not (TokenEndPtr < EndPtr)) or (not (TokenEndPtr^ in ['0'..'9', 'a'..'f', 'A'..'F'])) then
SetError(fpErrPasParserInvalidExpression, []);
if (not (TokenEndPtr < EndPtr)) or (not (TokenEndPtr^ in ['0'..'9', 'a'..'f', 'A'..'F'])) then begin
SetError(fpErrPasParserExpectedNumber_p, [GetFirstToken(CurPtr+1)], CreateError(fpErrPasParser_PositionAfter, [PosFromPChar(CurPtr+1), '#']) );
exit;
end;
while (TokenEndPtr < EndPtr) and (TokenEndPtr^ in ['0'..'9', 'a'..'f', 'A'..'F']) do
inc(TokenEndPtr);
end;
'&': begin
inc(TokenEndPtr);
if (not (TokenEndPtr < EndPtr)) or (not (TokenEndPtr^ in ['0'..'7'])) then
SetError(fpErrPasParserInvalidExpression, []);
if (not (TokenEndPtr < EndPtr)) or (not (TokenEndPtr^ in ['0'..'7'])) then begin
SetError(fpErrPasParserExpectedNumber_p, [GetFirstToken(CurPtr+1)], CreateError(fpErrPasParser_PositionAfter, [PosFromPChar(CurPtr+1), '#']) );
exit;
end;
while (TokenEndPtr < EndPtr) and (TokenEndPtr^ in ['0'..'7']) do
inc(TokenEndPtr);
end;
'%': begin
inc(TokenEndPtr);
if (not (TokenEndPtr < EndPtr)) or (not (TokenEndPtr^ in ['0'..'1'])) then
SetError(fpErrPasParserInvalidExpression, []);
if (not (TokenEndPtr < EndPtr)) or (not (TokenEndPtr^ in ['0'..'1'])) then begin
SetError(fpErrPasParserExpectedNumber_p, [GetFirstToken(CurPtr+1)], CreateError(fpErrPasParser_PositionAfter, [PosFromPChar(CurPtr+1), '#']) );
exit;
end;
while (TokenEndPtr < EndPtr) and (TokenEndPtr^ in ['0'..'1']) do
inc(TokenEndPtr);
end;
@ -2764,10 +2859,17 @@ var
while (TokenEndPtr < EndPtr) and (TokenEndPtr^ in ['0'..'9']) do
inc(TokenEndPtr);
end;
else begin
SetError(fpErrPasParserExpectedNumber_p, [GetFirstToken(CurPtr+1)], CreateError(fpErrPasParser_PositionAfter, [PosFromPChar(CurPtr+1), '#']) );
exit;
end;
end;
c := StrToIntDef(copy(p , 1 , TokenEndPtr - p), -1);
if c < 0 then
SetError(fpErrPasParserInvalidExpression, []); // should not happen
if (c < 0) or ( (TokenEndPtr < EndPtr) and (TokenEndPtr^ in ['0'..'9', 'a'..'z', 'A'..'Z']) )
then begin
SetError(fpErrPasParserExpectedNumber_p, [GetFirstToken(CurPtr+1)], CreateError(fpErrPasParser_PositionAfter, [PosFromPChar(CurPtr+1), '#']) );
exit;
end;
if c > 255 then // todo: need wide handling
str := str + WideChar(c)
else
@ -2787,12 +2889,22 @@ var
end;
begin
if FTextExpression = '' then
if FTextExpression = '' then begin
SetError(fpErrPasParserEmptyExpression);
exit;
end;
CurPtr := @FTextExpression[1];
EndPtr := CurPtr + length(FTextExpression);
CurPart := nil;
while (CurPtr^ in [' ', #9, #10, #13]) and (CurPtr < EndPtr) do
Inc(CurPtr);
if CurPtr = EndPtr then begin
SetError(fpErrPasParserEmptyExpression);
exit;
end;
CurPart := nil;
PrevPart := nil;
While (CurPtr < EndPtr) and FValid do begin
if CurPtr^ in [' ', #9, #10, #13] then begin
while (CurPtr^ in [' ', #9, #10, #13]) and (CurPtr < EndPtr) do
@ -2831,14 +2943,14 @@ begin
'a'..'z',
'A'..'Z', '_': AddIdentifier;
else begin
//SetError(fpErrPasParserUnexpectedToken, [GetFirstToken(CurPtr), PosFromPChar(CurPtr)])
SetError(Format('Unexpected token ''%0:s'' at pos %1:d', [CurPtr^, PosFromPChar(CurPtr)])); // error
SetParserError(fpErrPasParserUnexpectedToken_p);
break;
end;
end;
if not FValid then
break;
PrevPart := NewPart;
if CurPart = nil then
CurPart := NewPart
else
@ -2856,7 +2968,7 @@ begin
CurPart := CurPart.TopParent;
end
else
SetError('No Expression');
SetError(fpErrPasParserEmptyExpression);
end
else
if CurPart <> nil then
@ -2892,10 +3004,17 @@ DebugLn(DBG_WARNINGS, ['Skipping error ', AMsg]);
DebugLn(DBG_WARNINGS, ['PARSER ERROR ', AMsg]);
end;
procedure TFpPascalExpression.SetError(AnErrorCode: TFpErrorCode; AData: array of const);
procedure TFpPascalExpression.SetError(AnErrorCode: TFpErrorCode;
const AnNestedErr: TFpError);
begin
SetError(AnErrorCode, [], AnNestedErr);
end;
procedure TFpPascalExpression.SetError(AnErrorCode: TFpErrorCode;
AData: array of const; const AnNestedErr: TFpError);
begin
FValid := False;
FError := ErrorHandler.CreateError(AnErrorCode, AData);
FError := ErrorHandler.CreateError(AnErrorCode, AnNestedErr, AData);
DebugLn(DBG_WARNINGS, ['Setting error ', ErrorHandler.ErrorAsString(FError)]);
end;
@ -3064,6 +3183,16 @@ begin
Result := Copy(FStartChar, 1, Len);
end;
function TFpPascalExpressionPart.GetPos: Integer;
begin
Result := FExpression.PosFromPChar(FStartChar);
end;
function TFpPascalExpressionPart.GetFullText(AMaxLen: Integer): String;
begin
Result := GetText(AMaxLen);
end;
procedure TFpPascalExpressionPart.SetError(AMsg: String);
begin
if AMsg = '' then
@ -3078,9 +3207,26 @@ begin
else Self.SetError(AMsg);
end;
procedure TFpPascalExpressionPart.SetError(AnErrorCode: TFpErrorCode; AData: array of const);
function TFpPascalExpressionPart.CreateErrorWithPos(AnErrorCode: TFpErrorCode;
AData: array of const; APos: integer): TFpError;
begin
FExpression.SetError(AnErrorCode, AData);
if APos < 0 then
APos := GetPos;
if APos = 1
then Result := CreateError(AnErrorCode, AData, CreateError(fpErrPasParser_AtStart, [] ))
else Result := CreateError(AnErrorCode, AData, CreateError(fpErrPasParser_Position, [GetPos]));
end;
procedure TFpPascalExpressionPart.SetErrorWithPos(AnErrorCode: TFpErrorCode;
AData: array of const);
begin
FExpression.SetError(CreateErrorWithPos(AnErrorCode, AData));
end;
procedure TFpPascalExpressionPart.SetError(AnErrorCode: TFpErrorCode;
AData: array of const; const AnNestedErr: TFpError);
begin
FExpression.SetError(AnErrorCode, AData, AnNestedErr);
end;
procedure TFpPascalExpressionPart.SetError(AnError: TFpError);
@ -3299,6 +3445,29 @@ begin
inherited Destroy;
end;
function TFpPascalExpressionPartContainer.GetFullText(AMaxLen: Integer): String;
var
s, e: PChar;
i: Integer;
p: TFpPascalExpressionPart;
Len: Integer;
begin
s := FStartChar;
e := FEndChar;
for i := 0 to Count - 1 do begin
p := Items[i];
if p.FStartChar < s then s := p.FStartChar;
if p.FEndChar > e then e := p.FEndChar;
end;
if e <> nil
then Len := e - s + 1
else Len := min(AMaxLen, 10);
if (AMaxLen > 0) and (Len > AMaxLen) then
Len := AMaxLen;
Result := Copy(s, 1, Len);
end;
function TFpPascalExpressionPartContainer.Add(APart: TFpPascalExpressionPart): Integer;
begin
APart.Parent := Self;
@ -3369,7 +3538,7 @@ end;
procedure TFpPascalExpressionPartBracket.CloseBracket;
begin
if AfterComma then begin
SetError(fpErrPasParserMissingExprAfterComma, [GetText]);
SetError(fpErrPasParserMissingExprAfterComma, [GetText(MAX_ERR_EXPR_QUOTE_LEN), GetPos]);
exit;
end;
FIsClosing := True;
@ -3546,10 +3715,12 @@ begin
if Count <> 1 then exit;
tmp := Items[0].ResultValue;
if (tmp = nil) or not IsTargetAddr(tmp.Address) then
if (tmp = nil) or not IsTargetAddr(tmp.Address) then begin
// seterror / cant take address
exit;
end;
Result := TFpPasParserValueAddressOf.Create(tmp, Expression.Context.LocationContext);
Result := TFpPasParserValueAddressOf.Create(tmp, Items[0]);
{$IFDEF WITH_REFCOUNT_DEBUG}Result.DbgRenameReference(nil, 'DoGetResultValue');{$ENDIF}
end;
@ -3592,7 +3763,7 @@ begin
if (tmp.DbgSymbol = nil) or (tmp.DbgSymbol.SymbolType <> stType) then
exit;
Result := TFpPasParserValueMakeReftype.Create(tmp.DbgSymbol, Expression.Context.LocationContext);
Result := TFpPasParserValueMakeReftype.Create(tmp.DbgSymbol, Items[0]);
{$IFDEF WITH_REFCOUNT_DEBUG}Result.DbgRenameReference(nil, 'DoGetResultValue'){$ENDIF};
end;
@ -3639,7 +3810,7 @@ begin
else
begin
Result := nil;
SetError(fpErrCannotDereferenceType, [GetText]);
SetErrorWithPos(fpErrCannotDeref_p, [GetText]);
end;
end;
@ -3794,7 +3965,7 @@ function TFpPascalExpressionPartOperatorPlusMinus.DoGetResultValue: TFpValue;
SetError('Error dereferencing'); // TODO: set correct error
exit;
end;
Result := TFpPasParserValueAddressOf.Create(TmpVal, Expression.Context.LocationContext);
Result := TFpPasParserValueAddressOf.Create(TmpVal, Self);
TmpVal.ReleaseReference;
end;
function AddValueToInt(AIntVal, AOtherVal: TFpValue): TFpValue;
@ -4622,7 +4793,7 @@ begin
tmp2 := tmp;
end;
if (tmp = nil) then begin
SetError(fpErrCannotDereferenceType, [Items[0].GetText]); // TODO: better error
SetErrorWithPos(MsgfpErrCannotDeref_p, [Items[0].GetText]); // TODO: better error
exit;
end;
end;

View File

@ -31,10 +31,15 @@ msgstr "%1:s"
msgid "Failed to attach to process \"%1:s\".%0:sError message: %2:d \"%3:s\".%0:s%4:s"
msgstr "Impossible d'attacher le processus \"%1:s\".%0:s Message d'erreur : %2:d \"%3:s\". %0:s%4:s"
#: fperrormessages.msgfperrcannotdereferencetype
#: fperrormessages.msgfperrcannotcasttopointer_p
#, object-pascal-format
msgid "Cannot dereference Expression \"%1:s\""
msgstr "Impossible de déréférencer l'expression \"%1:s\""
msgid "Can't cast value to pointer '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrcannotderef_p
#, object-pascal-format
msgid "Can't dereference expression '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrcannotreadmemataddr
#, object-pascal-format
@ -58,6 +63,12 @@ msgstr "La modification de la valeur de cette variable n'est pas prise en charge
msgid "Failed to start process \"%1:s\".%0:sError message: %2:d \"%3:s\".%0:s%4:s"
msgstr "Échec du démarrage du processus \"%1:s\".%0:s Message d'erreur : %2:d \"%3:s\". %0:s%4:s"
#: fperrormessages.msgfperrexpectedordinalval_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrexpectedordinalval_p"
msgid "Expected an ordinal value, but found '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrfailedreadregiseter
msgid "Failed to read data from register"
msgstr "Échec de la lecture des données du registre"
@ -67,10 +78,11 @@ msgctxt "fperrormessages.msgfperrfailedwritemem"
msgid "Failed to write data"
msgstr "Échec de l'écriture des données"
#: fperrormessages.msgfperrinvalidnumber
#: fperrormessages.msgfperrindexoutofrange
#, object-pascal-format
msgid "Cannot parse number: %1:s"
msgstr "Impossible d'analyser le nombre : %1:s"
msgctxt "fperrormessages.msgfperrindexoutofrange"
msgid "Index out of range: %1:d"
msgstr ""
#: fperrormessages.msgfperrlocationparser
msgid "Internal Error: Cannot calculate location."
@ -107,39 +119,106 @@ msgstr "Valeur flottante non prise en charge : précision inconnue"
msgid "Cannot get member \"%1:s\" from non-structured type: %2:s"
msgstr "Impossible d'obtenir le membre \"%1:s\" à partir du type non structuré : %2:s"
#: fperrormessages.msgfperrpasparseremptyexpression
msgid "Empty expression"
msgstr ""
#: fperrormessages.msgfperrpasparserexpectednumber_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserexpectednumber_p"
msgid "Expected Number, but found '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserindexerror_wrapper
#, object-pascal-format
msgid "Index error at pos %2:d for '%1:s'[]: %3:s"
msgstr ""
#: fperrormessages.msgfperrpasparserinvalidexpression
msgid "Invalid Expression"
msgstr "Expression invalide"
#: fperrormessages.msgfperrpasparsermissingexpraftercomma
#, object-pascal-format
msgid "Expected Expression after Comma, but found closing bracket %1:s"
#, object-pascal-format, fuzzy, badformat
#| msgid "Expected Expression after Comma, but found closing bracket %1:s"
msgid "Expected Expression after Comma, but found closing bracket %1:s at pos %2:d"
msgstr "Expression attendue après la virgule, mais crochet fermant trouvé %1:s"
#: fperrormessages.msgfperrpasparsermissingindexexpression
#, object-pascal-format
msgid "Expected Expression but found closing bracket: %1:s"
#, object-pascal-format, fuzzy, badformat
#| msgid "Expected Expression but found closing bracket: %1:s"
msgid "Expected Expression but found closing bracket: '%1:s' at pos %2:d"
msgstr "Expression attendue, mais crochet fermant trouvé : %1:s"
#: fperrormessages.msgfperrpasparserunexpectedtoken
#: fperrormessages.msgfperrpasparsermissingopenbracket_p
#, object-pascal-format
msgid "Unexpected token '%1:s' at pos %2:d"
msgstr "Élément inattendu '%1:s' à la position %2:d"
msgctxt "fperrormessages.msgfperrpasparsermissingopenbracket_p"
msgid "No opening bracket for '%1:s' found%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedendofexpression
#, object-pascal-format
msgid "Unexpected end of expression after '%1:s'"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedtoken_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunexpectedtoken_p"
msgid "Unexpected token '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunknownintrinsic_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunknownintrinsic_p"
msgid "Intrinsic function '%1:s' not found%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunterminatedstring_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunterminatedstring_p"
msgid "String not terminated%1:s"
msgstr ""
#: fperrormessages.msgfperrpasparserwrongopenbracket_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserwrongopenbracket_p"
msgid "Mismatched opening bracket ('%3:s' at pos %2:d) for '%1:s' found%4:s"
msgstr ""
#: fperrormessages.msgfperrpasparser_atstart
msgid " at start of expression"
msgstr ""
#: fperrormessages.msgfperrpasparser_position
#, object-pascal-format
msgid " at pos %1:d"
msgstr ""
#: fperrormessages.msgfperrpasparser_positionafter
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparser_positionafter"
msgid " at pos %1:d after '%2:s'"
msgstr ""
#: fperrormessages.msgfperrreadmemsizelimit
msgid "Memory read size exceeds limit"
msgstr "La taille de lecture de la mémoire dépasse la limite"
#: fperrormessages.msgfperrsymbolnotfound
#: fperrormessages.msgfperrsymbolnotfound_p
#, object-pascal-format
msgid "Identifier not found: \"%1:s\""
msgstr "Identifiant introuvable : \"%1:s\""
msgid "Identifier not found: \"%1:s\"%2:s"
msgstr ""
#: fperrormessages.msgfperrtypehasnoindex
#, object-pascal-format
msgid "Cannot access indexed element in expression %1:s"
msgstr "Impossible d'accéder à l'élément indexé dans l'expression %1:s"
#: fperrormessages.msgfperrtypenotindexable
msgctxt "fperrormessages.msgfperrtypenotindexable"
msgid "The value has no index"
msgstr ""
#: fperrormessages.msgfpinternalerrcannotreadinvalidmem
msgid "Internal error: Missing data location"
msgstr "Erreur interne : emplacement des données manquant"

View File

@ -19,9 +19,14 @@ msgstr ""
msgid "Failed to attach to process \"%1:s\".%0:sError message: %2:d \"%3:s\".%0:s%4:s"
msgstr ""
#: fperrormessages.msgfperrcannotdereferencetype
#: fperrormessages.msgfperrcannotcasttopointer_p
#, object-pascal-format
msgid "Cannot dereference Expression \"%1:s\""
msgid "Can't cast value to pointer '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrcannotderef_p
#, object-pascal-format
msgid "Can't dereference expression '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrcannotreadmemataddr
@ -45,6 +50,12 @@ msgstr ""
msgid "Failed to start process \"%1:s\".%0:sError message: %2:d \"%3:s\".%0:s%4:s"
msgstr ""
#: fperrormessages.msgfperrexpectedordinalval_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrexpectedordinalval_p"
msgid "Expected an ordinal value, but found '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrfailedreadregiseter
msgid "Failed to read data from register"
msgstr ""
@ -54,9 +65,10 @@ msgctxt "fperrormessages.msgfperrfailedwritemem"
msgid "Failed to write data"
msgstr ""
#: fperrormessages.msgfperrinvalidnumber
#: fperrormessages.msgfperrindexoutofrange
#, object-pascal-format
msgid "Cannot parse number: %1:s"
msgctxt "fperrormessages.msgfperrindexoutofrange"
msgid "Index out of range: %1:d"
msgstr ""
#: fperrormessages.msgfperrlocationparser
@ -94,32 +106,92 @@ msgstr ""
msgid "Cannot get member \"%1:s\" from non-structured type: %2:s"
msgstr ""
#: fperrormessages.msgfperrpasparseremptyexpression
msgid "Empty expression"
msgstr ""
#: fperrormessages.msgfperrpasparserexpectednumber_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserexpectednumber_p"
msgid "Expected Number, but found '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserindexerror_wrapper
#, object-pascal-format
msgid "Index error at pos %2:d for '%1:s'[]: %3:s"
msgstr ""
#: fperrormessages.msgfperrpasparserinvalidexpression
msgid "Invalid Expression"
msgstr ""
#: fperrormessages.msgfperrpasparsermissingexpraftercomma
#, object-pascal-format
msgid "Expected Expression after Comma, but found closing bracket %1:s"
msgid "Expected Expression after Comma, but found closing bracket %1:s at pos %2:d"
msgstr ""
#: fperrormessages.msgfperrpasparsermissingindexexpression
#, object-pascal-format
msgid "Expected Expression but found closing bracket: %1:s"
msgid "Expected Expression but found closing bracket: '%1:s' at pos %2:d"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedtoken
#: fperrormessages.msgfperrpasparsermissingopenbracket_p
#, object-pascal-format
msgid "Unexpected token '%1:s' at pos %2:d"
msgctxt "fperrormessages.msgfperrpasparsermissingopenbracket_p"
msgid "No opening bracket for '%1:s' found%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedendofexpression
#, object-pascal-format
msgid "Unexpected end of expression after '%1:s'"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedtoken_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunexpectedtoken_p"
msgid "Unexpected token '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunknownintrinsic_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunknownintrinsic_p"
msgid "Intrinsic function '%1:s' not found%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunterminatedstring_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunterminatedstring_p"
msgid "String not terminated%1:s"
msgstr ""
#: fperrormessages.msgfperrpasparserwrongopenbracket_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserwrongopenbracket_p"
msgid "Mismatched opening bracket ('%3:s' at pos %2:d) for '%1:s' found%4:s"
msgstr ""
#: fperrormessages.msgfperrpasparser_atstart
msgid " at start of expression"
msgstr ""
#: fperrormessages.msgfperrpasparser_position
#, object-pascal-format
msgid " at pos %1:d"
msgstr ""
#: fperrormessages.msgfperrpasparser_positionafter
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparser_positionafter"
msgid " at pos %1:d after '%2:s'"
msgstr ""
#: fperrormessages.msgfperrreadmemsizelimit
msgid "Memory read size exceeds limit"
msgstr ""
#: fperrormessages.msgfperrsymbolnotfound
#: fperrormessages.msgfperrsymbolnotfound_p
#, object-pascal-format
msgid "Identifier not found: \"%1:s\""
msgid "Identifier not found: \"%1:s\"%2:s"
msgstr ""
#: fperrormessages.msgfperrtypehasnoindex
@ -127,6 +199,11 @@ msgstr ""
msgid "Cannot access indexed element in expression %1:s"
msgstr ""
#: fperrormessages.msgfperrtypenotindexable
msgctxt "fperrormessages.msgfperrtypenotindexable"
msgid "The value has no index"
msgstr ""
#: fperrormessages.msgfpinternalerrcannotreadinvalidmem
msgid "Internal error: Missing data location"
msgstr ""

View File

@ -30,10 +30,15 @@ msgstr "%1:s"
msgid "Failed to attach to process \"%1:s\".%0:sError message: %2:d \"%3:s\".%0:s%4:s"
msgstr "Falha ao anexar ao processo \"%1:s\".%0:sMensagem de erro: %2:d \"%3:s\".%0:s%4:s"
#: fperrormessages.msgfperrcannotdereferencetype
#: fperrormessages.msgfperrcannotcasttopointer_p
#, object-pascal-format
msgid "Cannot dereference Expression \"%1:s\""
msgstr "Impossível desreferenciar Expressão \"%1:s\""
msgid "Can't cast value to pointer '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrcannotderef_p
#, object-pascal-format
msgid "Can't dereference expression '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrcannotreadmemataddr
#, object-pascal-format
@ -56,6 +61,12 @@ msgstr "Alteração do valor dessa variável não é suportada"
msgid "Failed to start process \"%1:s\".%0:sError message: %2:d \"%3:s\".%0:s%4:s"
msgstr "Falha ao iniciar o processo \"%1:s\".%0:sMensagem de erro: %2:d \"%3:s\".%0:s%4:s"
#: fperrormessages.msgfperrexpectedordinalval_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrexpectedordinalval_p"
msgid "Expected an ordinal value, but found '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrfailedreadregiseter
msgid "Failed to read data from register"
msgstr "Falha ao ler dados do registrador"
@ -65,10 +76,11 @@ msgctxt "fperrormessages.msgfperrfailedwritemem"
msgid "Failed to write data"
msgstr "Falha ao gravar dados"
#: fperrormessages.msgfperrinvalidnumber
#: fperrormessages.msgfperrindexoutofrange
#, object-pascal-format
msgid "Cannot parse number: %1:s"
msgstr "Impossível analisar número: %1:s"
msgctxt "fperrormessages.msgfperrindexoutofrange"
msgid "Index out of range: %1:d"
msgstr ""
#: fperrormessages.msgfperrlocationparser
msgid "Internal Error: Cannot calculate location."
@ -105,39 +117,106 @@ msgstr "Valor flutuante não suportado: Precisão desconhecida"
msgid "Cannot get member \"%1:s\" from non-structured type: %2:s"
msgstr "Impossível obter membro \"%1:s\" do tipo não estruturado: %2:s"
#: fperrormessages.msgfperrpasparseremptyexpression
msgid "Empty expression"
msgstr ""
#: fperrormessages.msgfperrpasparserexpectednumber_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserexpectednumber_p"
msgid "Expected Number, but found '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserindexerror_wrapper
#, object-pascal-format
msgid "Index error at pos %2:d for '%1:s'[]: %3:s"
msgstr ""
#: fperrormessages.msgfperrpasparserinvalidexpression
msgid "Invalid Expression"
msgstr "Expressão inválida"
#: fperrormessages.msgfperrpasparsermissingexpraftercomma
#, object-pascal-format
msgid "Expected Expression after Comma, but found closing bracket %1:s"
#, object-pascal-format, fuzzy, badformat
#| msgid "Expected Expression after Comma, but found closing bracket %1:s"
msgid "Expected Expression after Comma, but found closing bracket %1:s at pos %2:d"
msgstr "Expressão esperada após a vírgula, mas encontrado parêntese de fechamento %1:s"
#: fperrormessages.msgfperrpasparsermissingindexexpression
#, object-pascal-format
msgid "Expected Expression but found closing bracket: %1:s"
#, object-pascal-format, fuzzy, badformat
#| msgid "Expected Expression but found closing bracket: %1:s"
msgid "Expected Expression but found closing bracket: '%1:s' at pos %2:d"
msgstr "Expressão esperada mas encontrado parêntese de fechamento: %1:s"
#: fperrormessages.msgfperrpasparserunexpectedtoken
#: fperrormessages.msgfperrpasparsermissingopenbracket_p
#, object-pascal-format
msgid "Unexpected token '%1:s' at pos %2:d"
msgstr "Símbolo inesperado '%1:s' na posição %2:d"
msgctxt "fperrormessages.msgfperrpasparsermissingopenbracket_p"
msgid "No opening bracket for '%1:s' found%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedendofexpression
#, object-pascal-format
msgid "Unexpected end of expression after '%1:s'"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedtoken_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunexpectedtoken_p"
msgid "Unexpected token '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunknownintrinsic_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunknownintrinsic_p"
msgid "Intrinsic function '%1:s' not found%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunterminatedstring_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunterminatedstring_p"
msgid "String not terminated%1:s"
msgstr ""
#: fperrormessages.msgfperrpasparserwrongopenbracket_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserwrongopenbracket_p"
msgid "Mismatched opening bracket ('%3:s' at pos %2:d) for '%1:s' found%4:s"
msgstr ""
#: fperrormessages.msgfperrpasparser_atstart
msgid " at start of expression"
msgstr ""
#: fperrormessages.msgfperrpasparser_position
#, object-pascal-format
msgid " at pos %1:d"
msgstr ""
#: fperrormessages.msgfperrpasparser_positionafter
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparser_positionafter"
msgid " at pos %1:d after '%2:s'"
msgstr ""
#: fperrormessages.msgfperrreadmemsizelimit
msgid "Memory read size exceeds limit"
msgstr "Tamanho de leitura de memória excedeu o limite"
#: fperrormessages.msgfperrsymbolnotfound
#: fperrormessages.msgfperrsymbolnotfound_p
#, object-pascal-format
msgid "Identifier not found: \"%1:s\""
msgstr "Identificador não encontrado: \"%1:s\""
msgid "Identifier not found: \"%1:s\"%2:s"
msgstr ""
#: fperrormessages.msgfperrtypehasnoindex
#, object-pascal-format
msgid "Cannot access indexed element in expression %1:s"
msgstr "Impossível acessar elemento indexado na expressão %1:s"
#: fperrormessages.msgfperrtypenotindexable
msgctxt "fperrormessages.msgfperrtypenotindexable"
msgid "The value has no index"
msgstr ""
#: fperrormessages.msgfpinternalerrcannotreadinvalidmem
msgid "Internal error: Missing data location"
msgstr "Erro interno: Localização dos dados faltando"

View File

@ -29,10 +29,15 @@ msgstr "%1:s"
msgid "Failed to attach to process \"%1:s\".%0:sError message: %2:d \"%3:s\".%0:s%4:s"
msgstr "Не удалось присоединиться к процессу \"%1:s\".%0:sСообщение об ошибке: %2:d \"%3:s\".%0:s%4:s"
#: fperrormessages.msgfperrcannotdereferencetype
#: fperrormessages.msgfperrcannotcasttopointer_p
#, object-pascal-format
msgid "Cannot dereference Expression \"%1:s\""
msgstr "Невозможно разыменовать выражение \"%1:s\""
msgid "Can't cast value to pointer '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrcannotderef_p
#, object-pascal-format
msgid "Can't dereference expression '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrcannotreadmemataddr
#, object-pascal-format
@ -55,6 +60,12 @@ msgstr "Изменение значения этой переменной не
msgid "Failed to start process \"%1:s\".%0:sError message: %2:d \"%3:s\".%0:s%4:s"
msgstr "Не удалось запустить процесс \"%1:s\".%0:sСообщение об ошибке: %2:d \"%3:s\".%0:s%4:s"
#: fperrormessages.msgfperrexpectedordinalval_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrexpectedordinalval_p"
msgid "Expected an ordinal value, but found '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrfailedreadregiseter
msgid "Failed to read data from register"
msgstr "Не удалось прочитать данные из регистра"
@ -64,10 +75,11 @@ msgctxt "fperrormessages.msgfperrfailedwritemem"
msgid "Failed to write data"
msgstr "Не удалось записать данные"
#: fperrormessages.msgfperrinvalidnumber
#: fperrormessages.msgfperrindexoutofrange
#, object-pascal-format
msgid "Cannot parse number: %1:s"
msgstr "Невозможно проанализировать число: %1:s"
msgctxt "fperrormessages.msgfperrindexoutofrange"
msgid "Index out of range: %1:d"
msgstr ""
#: fperrormessages.msgfperrlocationparser
msgid "Internal Error: Cannot calculate location."
@ -104,39 +116,106 @@ msgstr "Вещественное значение не поддерживает
msgid "Cannot get member \"%1:s\" from non-structured type: %2:s"
msgstr "Невозможно получить элемент \"%1:s\" из неструктурного типа: %2:s"
#: fperrormessages.msgfperrpasparseremptyexpression
msgid "Empty expression"
msgstr ""
#: fperrormessages.msgfperrpasparserexpectednumber_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserexpectednumber_p"
msgid "Expected Number, but found '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserindexerror_wrapper
#, object-pascal-format
msgid "Index error at pos %2:d for '%1:s'[]: %3:s"
msgstr ""
#: fperrormessages.msgfperrpasparserinvalidexpression
msgid "Invalid Expression"
msgstr "Неверное выражение"
#: fperrormessages.msgfperrpasparsermissingexpraftercomma
#, object-pascal-format
msgid "Expected Expression after Comma, but found closing bracket %1:s"
#, object-pascal-format, fuzzy, badformat
#| msgid "Expected Expression after Comma, but found closing bracket %1:s"
msgid "Expected Expression after Comma, but found closing bracket %1:s at pos %2:d"
msgstr "После запятой ожидалось выражение, но найдена закрывающая скобка %1:s"
#: fperrormessages.msgfperrpasparsermissingindexexpression
#, object-pascal-format
msgid "Expected Expression but found closing bracket: %1:s"
#, object-pascal-format, fuzzy, badformat
#| msgid "Expected Expression but found closing bracket: %1:s"
msgid "Expected Expression but found closing bracket: '%1:s' at pos %2:d"
msgstr "Ожидалось выражение, но найдена закрывающая скобка: %1:s"
#: fperrormessages.msgfperrpasparserunexpectedtoken
#: fperrormessages.msgfperrpasparsermissingopenbracket_p
#, object-pascal-format
msgid "Unexpected token '%1:s' at pos %2:d"
msgstr "Неизвестный элемент '%1:s' в позиции %2:d"
msgctxt "fperrormessages.msgfperrpasparsermissingopenbracket_p"
msgid "No opening bracket for '%1:s' found%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedendofexpression
#, object-pascal-format
msgid "Unexpected end of expression after '%1:s'"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedtoken_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunexpectedtoken_p"
msgid "Unexpected token '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunknownintrinsic_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunknownintrinsic_p"
msgid "Intrinsic function '%1:s' not found%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunterminatedstring_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunterminatedstring_p"
msgid "String not terminated%1:s"
msgstr ""
#: fperrormessages.msgfperrpasparserwrongopenbracket_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserwrongopenbracket_p"
msgid "Mismatched opening bracket ('%3:s' at pos %2:d) for '%1:s' found%4:s"
msgstr ""
#: fperrormessages.msgfperrpasparser_atstart
msgid " at start of expression"
msgstr ""
#: fperrormessages.msgfperrpasparser_position
#, object-pascal-format
msgid " at pos %1:d"
msgstr ""
#: fperrormessages.msgfperrpasparser_positionafter
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparser_positionafter"
msgid " at pos %1:d after '%2:s'"
msgstr ""
#: fperrormessages.msgfperrreadmemsizelimit
msgid "Memory read size exceeds limit"
msgstr "Размер читаемой памяти превышает разрешённый"
#: fperrormessages.msgfperrsymbolnotfound
#: fperrormessages.msgfperrsymbolnotfound_p
#, object-pascal-format
msgid "Identifier not found: \"%1:s\""
msgstr "Идентификатор не найден: \"%1:s\""
msgid "Identifier not found: \"%1:s\"%2:s"
msgstr ""
#: fperrormessages.msgfperrtypehasnoindex
#, object-pascal-format
msgid "Cannot access indexed element in expression %1:s"
msgstr "Невозможно получить доступ к элементу по индексу в выражении %1:s"
#: fperrormessages.msgfperrtypenotindexable
msgctxt "fperrormessages.msgfperrtypenotindexable"
msgid "The value has no index"
msgstr ""
#: fperrormessages.msgfpinternalerrcannotreadinvalidmem
msgid "Internal error: Missing data location"
msgstr "Внутренняя ошибка: неизвестно расположение данных"

View File

@ -30,10 +30,15 @@ msgstr "%1:s"
msgid "Failed to attach to process \"%1:s\".%0:sError message: %2:d \"%3:s\".%0:s%4:s"
msgstr "\"%1:s\" işlemine eklenemedi.%0:sHata mesajı: %2:d \"%3:s\".%0:s%4:s"
#: fperrormessages.msgfperrcannotdereferencetype
#: fperrormessages.msgfperrcannotcasttopointer_p
#, object-pascal-format
msgid "Cannot dereference Expression \"%1:s\""
msgstr "\"%1:s\" İfadesinin başvurusu kaldırılamıyor"
msgid "Can't cast value to pointer '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrcannotderef_p
#, object-pascal-format
msgid "Can't dereference expression '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrcannotreadmemataddr
#, object-pascal-format
@ -56,6 +61,12 @@ msgstr "Bu değişkenin değerinin değiştirilmesi desteklenmiyor"
msgid "Failed to start process \"%1:s\".%0:sError message: %2:d \"%3:s\".%0:s%4:s"
msgstr "\"%1:s\" işlemi başlatılamadı.%0:sHata mesajı: %2:d \"%3:s\".%0:s%4:s"
#: fperrormessages.msgfperrexpectedordinalval_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrexpectedordinalval_p"
msgid "Expected an ordinal value, but found '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrfailedreadregiseter
msgid "Failed to read data from register"
msgstr "Kayıttan veri okunamadı"
@ -65,10 +76,11 @@ msgctxt "fperrormessages.msgfperrfailedwritemem"
msgid "Failed to write data"
msgstr "Veri yazılamadı"
#: fperrormessages.msgfperrinvalidnumber
#: fperrormessages.msgfperrindexoutofrange
#, object-pascal-format
msgid "Cannot parse number: %1:s"
msgstr "Sayı ayrıştırılamıyor: %1:s"
msgctxt "fperrormessages.msgfperrindexoutofrange"
msgid "Index out of range: %1:d"
msgstr ""
#: fperrormessages.msgfperrlocationparser
msgid "Internal Error: Cannot calculate location."
@ -105,39 +117,106 @@ msgstr "Desteklenmeyen kayan nokta değeri: Bilinmeyen hassasiyet"
msgid "Cannot get member \"%1:s\" from non-structured type: %2:s"
msgstr "Yapılandırılmamış türden \"%1:s\" üyesi alınamıyor: %2:s"
#: fperrormessages.msgfperrpasparseremptyexpression
msgid "Empty expression"
msgstr ""
#: fperrormessages.msgfperrpasparserexpectednumber_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserexpectednumber_p"
msgid "Expected Number, but found '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserindexerror_wrapper
#, object-pascal-format
msgid "Index error at pos %2:d for '%1:s'[]: %3:s"
msgstr ""
#: fperrormessages.msgfperrpasparserinvalidexpression
msgid "Invalid Expression"
msgstr "Geçersiz İfade"
#: fperrormessages.msgfperrpasparsermissingexpraftercomma
#, object-pascal-format
msgid "Expected Expression after Comma, but found closing bracket %1:s"
#, object-pascal-format, fuzzy, badformat
#| msgid "Expected Expression after Comma, but found closing bracket %1:s"
msgid "Expected Expression after Comma, but found closing bracket %1:s at pos %2:d"
msgstr "Virgülden Sonra Beklenen İfade, ancak %1:s kapanış parantezi bulundu"
#: fperrormessages.msgfperrpasparsermissingindexexpression
#, object-pascal-format
msgid "Expected Expression but found closing bracket: %1:s"
#, object-pascal-format, fuzzy, badformat
#| msgid "Expected Expression but found closing bracket: %1:s"
msgid "Expected Expression but found closing bracket: '%1:s' at pos %2:d"
msgstr "Beklenen İfade ancak kapanış ayracı bulundu: %1:s"
#: fperrormessages.msgfperrpasparserunexpectedtoken
#, object-pascal-format, fuzzy, badformat
msgid "Unexpected token '%1:s' at pos %2:d"
msgstr "%2:d konumunda beklenmeyen simge '%1:s'"
#: fperrormessages.msgfperrpasparsermissingopenbracket_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparsermissingopenbracket_p"
msgid "No opening bracket for '%1:s' found%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedendofexpression
#, object-pascal-format
msgid "Unexpected end of expression after '%1:s'"
msgstr ""
#: fperrormessages.msgfperrpasparserunexpectedtoken_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunexpectedtoken_p"
msgid "Unexpected token '%1:s'%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunknownintrinsic_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunknownintrinsic_p"
msgid "Intrinsic function '%1:s' not found%2:s"
msgstr ""
#: fperrormessages.msgfperrpasparserunterminatedstring_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserunterminatedstring_p"
msgid "String not terminated%1:s"
msgstr ""
#: fperrormessages.msgfperrpasparserwrongopenbracket_p
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparserwrongopenbracket_p"
msgid "Mismatched opening bracket ('%3:s' at pos %2:d) for '%1:s' found%4:s"
msgstr ""
#: fperrormessages.msgfperrpasparser_atstart
msgid " at start of expression"
msgstr ""
#: fperrormessages.msgfperrpasparser_position
#, object-pascal-format
msgid " at pos %1:d"
msgstr ""
#: fperrormessages.msgfperrpasparser_positionafter
#, object-pascal-format
msgctxt "fperrormessages.msgfperrpasparser_positionafter"
msgid " at pos %1:d after '%2:s'"
msgstr ""
#: fperrormessages.msgfperrreadmemsizelimit
msgid "Memory read size exceeds limit"
msgstr "Bellek okuma boyutu sınırııyor"
#: fperrormessages.msgfperrsymbolnotfound
#: fperrormessages.msgfperrsymbolnotfound_p
#, object-pascal-format
msgid "Identifier not found: \"%1:s\""
msgstr "Tanımlayıcı bulunamadı: \"%1:s\""
msgid "Identifier not found: \"%1:s\"%2:s"
msgstr ""
#: fperrormessages.msgfperrtypehasnoindex
#, object-pascal-format
msgid "Cannot access indexed element in expression %1:s"
msgstr "%1:s ifadesindeki dizine eklenen öğeye erişilemiyor"
#: fperrormessages.msgfperrtypenotindexable
msgctxt "fperrormessages.msgfperrtypenotindexable"
msgid "The value has no index"
msgstr ""
#: fperrormessages.msgfpinternalerrcannotreadinvalidmem
msgid "Internal error: Missing data location"
msgstr "Dahili hata: Eksik veri konumu"

View File

@ -28,7 +28,7 @@ var
e: TFpError;
e2: TFpError;
begin
e := CreateError(fpErrSymbolNotFound, ['a']);
e := CreateError(fpErrSymbolNotFound_p, ['a', '']);
e2 := CreateError(fpErrLocationParserMemRead, e, []);
ErrorHandler.ErrorAsString(e2);
end;

View File

@ -9,18 +9,6 @@ uses
FpErrorMessages, FpDbgInfo,
{$ifdef FORCE_LAZLOGGER_DUMMY} LazLoggerDummy {$else} LazLoggerBase {$endif};
type
{ TTestPascalParser }
TTestPascalParser = class(TTestCase)
published
procedure TestParser;
end;
implementation
type
{ TTestFpPascalExpression }
@ -30,12 +18,44 @@ type
property ExpressionPart;
end;
{ TTestPascalParser }
TTestPascalParser = class(TTestCase)
private
CurrentTestExprText: String;
CurrentTestExprObj: TTestFpPascalExpression;
procedure CreateExpr(t: string; ExpValid: Boolean; SkipExpValid: Boolean = False);
published
procedure TestParser;
procedure TestParserError;
end;
implementation
{ TTestFpPascalExpression }
procedure TTestPascalParser.TestParser;
procedure TTestPascalParser.CreateExpr(t: string; ExpValid: Boolean;
SkipExpValid: Boolean);
var
CurrentTestExprText: String;
CurrentTestExprObj: TTestFpPascalExpression;
s: String;
ctx: TFpDbgSimpleLocationContext;
sc: TFpDbgSymbolScope;
begin
ctx := TFpDbgSimpleLocationContext.Create(nil, 0, 4, 0, 0);
sc := TFpDbgSymbolScope.Create(ctx);
FreeAndNil(CurrentTestExprObj);
CurrentTestExprText := t;
CurrentTestExprObj := TTestFpPascalExpression.Create(CurrentTestExprText, sc);
DebugLn(CurrentTestExprObj.DebugDump);
if not SkipExpValid then begin
s := ErrorHandler.ErrorAsString(CurrentTestExprObj.Error);
AssertEquals('Valid '+s+ ' # '+CurrentTestExprText, ExpValid, CurrentTestExprObj.Valid);
end;
ctx.ReleaseReference;
sc.ReleaseReference;
end;
procedure TTestPascalParser.TestParser;
function GetChild(p: TFpPascalExpressionPart; i: array of integer): TFpPascalExpressionPart;
var
@ -70,24 +90,6 @@ var
TestExpr(GetChild(i), AClass, AText, AChildCount);
end;
procedure CreateExpr(t: string; ExpValid: Boolean);
var
s: String;
ctx: TFpDbgSimpleLocationContext;
sc: TFpDbgSymbolScope;
begin
ctx := TFpDbgSimpleLocationContext.Create(nil, 0, 4, 0, 0);
sc := TFpDbgSymbolScope.Create(ctx);
FreeAndNil(CurrentTestExprObj);
CurrentTestExprText := t;
CurrentTestExprObj := TTestFpPascalExpression.Create(CurrentTestExprText, sc);
DebugLn(CurrentTestExprObj.DebugDump);
s := ErrorHandler.ErrorAsString(CurrentTestExprObj.Error);
AssertEquals('Valid '+s+ ' # '+CurrentTestExprText, ExpValid, CurrentTestExprObj.Valid);
ctx.ReleaseReference;
sc.ReleaseReference;
end;
begin
CurrentTestExprObj := nil;
try
@ -540,6 +542,103 @@ begin
end;
end;
procedure TTestPascalParser.TestParserError;
procedure AssertPrintError;
var
s: String;
begin
CurrentTestExprObj.ResultValue;
AssertTrue('Got an error', IsError(CurrentTestExprObj.Error));
s := ErrorHandler.ErrorAsString(CurrentTestExprObj.Error);
AssertTrue('format error msg', pos('Internal Error:', s) < 1);
end;
procedure AssertError(const AnErrCode: array of TFpErrorCode);
var
GotErrCode: TFpErrorCode;
Err: TFpError;
i: Integer;
begin
CurrentTestExprObj.ResultValue;
Err := CurrentTestExprObj.Error;
AssertTrue('correct err code', IsError(Err));
for i := low(AnErrCode) to high(AnErrCode) do begin
AssertTrue('has sub error', Length(Err) >= i);
GotErrCode := CurrentTestExprObj.Error[i].ErrorCode;
AssertEquals('correct err code', AnErrCode[i], GotErrCode);
end;
AssertPrintError;
end;
procedure TestExpr(Expr: String; AnErrCode: TFpErrorCode);
begin
CreateExpr(Expr, False, True);
AssertError([AnErrCode]);
end;
procedure TestExpr(Expr: String; const AnErrCode: array of TFpErrorCode);
begin
CreateExpr(Expr, False, True);
AssertError(AnErrCode);
end;
var
s: String;
begin
// self test
s := ErrorHandler.ErrorAsString(CreateError(-1));
AssertFalse('self test format error msg', pos('Internal Error:', s) < 1);
s := ErrorHandler.ErrorAsString(CreateError(fpErrPasParserUnexpectedToken_p, []));
AssertFalse('self test format error msg', pos('Internal Error:', s) < 1);
TestExpr('£', fpErrPasParserUnexpectedToken_p);
TestExpr(':foobar', fpErrPasParserUnknownIntrinsic_p);
TestExpr('1..2', fpErrPasParserUnexpectedToken_p);
TestExpr('[1...2]', fpErrPasParserUnexpectedToken_p);
TestExpr('1)', fpErrPasParserMissingOpenBracket_p);
TestExpr('[1)', fpErrPasParserWrongOpenBracket_p);
TestExpr('1a ', fpErrPasParserExpectedNumber_p);
TestExpr('$ ', fpErrPasParserExpectedNumber_p);
TestExpr('$x', fpErrPasParserExpectedNumber_p);
TestExpr('$1x', fpErrPasParserExpectedNumber_p);
TestExpr('0x', fpErrPasParserExpectedNumber_p);
TestExpr('0x1z', fpErrPasParserExpectedNumber_p);
TestExpr('& ', fpErrPasParserExpectedNumber_p);
TestExpr('&1z ', fpErrPasParserExpectedNumber_p);
TestExpr('%9 ', fpErrPasParserExpectedNumber_p);
TestExpr('%1z ', fpErrPasParserExpectedNumber_p);
TestExpr('''a', fpErrPasParserUnterminatedString_p);
TestExpr('#', fpErrPasParserUnexpectedEndOfExpression);
TestExpr('# ', fpErrPasParserExpectedNumber_p);
TestExpr('#.', fpErrPasParserExpectedNumber_p);
TestExpr('#12a', fpErrPasParserExpectedNumber_p);
TestExpr('#af', fpErrPasParserExpectedNumber_p);
TestExpr('#$az', fpErrPasParserExpectedNumber_p);
TestExpr('#$z', fpErrPasParserExpectedNumber_p);
TestExpr('#&79', fpErrPasParserExpectedNumber_p);
TestExpr('#&9', fpErrPasParserExpectedNumber_p);
TestExpr('#%13', fpErrPasParserExpectedNumber_p);
TestExpr('#%3', fpErrPasParserExpectedNumber_p);
TestExpr('''abc''[]', fpErrPasParserMissingIndexExpression);
TestExpr('''abc''[#1]', [fpErrPasParserIndexError_Wrapper, fpErrExpectedOrdinalVal_p]);
TestExpr('''abc''[99]', [fpErrPasParserIndexError_Wrapper, fpErrIndexOutOfRange]);
TestExpr('1[99]', [fpErrPasParserIndexError_Wrapper, fpErrTypeNotIndexable]);
//TestExpr('@''ab''', fpErrCannotCastToPointer_p);
///TestExpr('^T(''ab'')', fpErrCannotCastToPointer_p);
end;
initialization

View File

@ -30,9 +30,9 @@ unit FpDebugDebuggerUtils;
interface
uses
FpDbgUtil, FpdMemoryTools, FpPascalParser,
FpDbgUtil, FpdMemoryTools, FpPascalParser, FpErrorMessages,
{$ifdef FORCE_LAZLOGGER_DUMMY} LazLoggerDummy {$else} LazLoggerBase {$endif},
DbgIntfDebuggerBase, sysutils, Classes, syncobjs, Forms;
DbgIntfDebuggerBase, sysutils, Classes, syncobjs, Forms, FpDebugStringConstants;
type
@ -189,12 +189,46 @@ type
property OnQueueIdle: TThreadMethod read GetOnQueueIdle write SetOnQueueIdle;
end;
function GetErrorText(AnErrorCode: TFpErrorCode; out AnErrorText: AnsiString): Boolean;
implementation
var
FPDBG_QUEUE: PLazLoggerLogGroup;
function GetErrorText(AnErrorCode: TFpErrorCode; out AnErrorText: AnsiString
): Boolean;
begin
Result := True;
case AnErrorCode of
fpErrSymbolNotFound_p: AnErrorText := LazErrSymbolNotFound_p;
fpErrIndexOutOfRange: AnErrorText := LazErrIndexOutOfRange;
fpErrTypeNotIndexable: AnErrorText := LazErrTypeNotIndexable;
fpErrExpectedOrdinalVal_p: AnErrorText := LazErrExpectedOrdinalVal_p;
fpErrCannotCastToPointer_p: AnErrorText := LazErrCannotCastToPointer_p;
fpErrCannotDeref_p: AnErrorText := LazErrCannotDeref_p;
fpErrPasParserEmptyExpression: AnErrorText := LazErrPasParserEmptyExpression;
fpErrPasParserUnexpectedEndOfExpression: AnErrorText := LazErrPasParserUnexpectedEndOfExpression;
fpErrPasParserUnexpectedToken_p: AnErrorText := LazErrPasParserUnexpectedToken_p;
fpErrPasParserUnknownIntrinsic_p: AnErrorText := LazErrPasParserUnknownIntrinsic_p;
fpErrPasParserMissingOpenBracket_p: AnErrorText := LazErrPasParserMissingOpenBracket_p;
fpErrPasParserWrongOpenBracket_p: AnErrorText := LazErrPasParserWrongOpenBracket_p;
fpErrPasParserMissingIndexExpression: AnErrorText := LazErrPasParserMissingIndexExpression;
fpErrPasParserMissingExprAfterComma: AnErrorText := LazErrPasParserMissingExprAfterComma;
fpErrPasParserIndexError_Wrapper: AnErrorText := LazErrPasParserIndexError_Wrapper;
fpErrPasParserUnterminatedString_p: AnErrorText := LazErrPasParserUnterminatedString_p;
fpErrPasParserExpectedNumber_p: AnErrorText := LazErrPasParserExpectedNumber_p;
fpErrPasParser_AtStart: AnErrorText := LazErrPasParser_AtStart;
fpErrPasParser_PositionAfter: AnErrorText := LazErrPasParser_PositionAfter;
fpErrPasParser_Position: AnErrorText := LazErrPasParser_Position;
else Result := False;
end;
end;
{ TFpDebugDebuggerPropertiesMemLimits }
procedure TFpDebugDebuggerPropertiesMemLimits.SetMaxMemReadSize(AValue: QWord);

View File

@ -1129,6 +1129,7 @@ begin
APasExpr.OnFunctionCall := @DoWatchFunctionCall;
APasExpr.ResultValue; // trigger full validation
if not APasExpr.Valid then begin
ErrorHandler.OnErrorTextLookup := @GetErrorText;
AResText := ErrorHandler.ErrorAsString(APasExpr.Error);
if FWatchValue <> nil then begin
FWatchValue.Value := AResText;

View File

@ -17,6 +17,35 @@ resourcestring
drsConverterNormalizeVariant = 'Convert variant to value type';
drsRunAllThreadsWhileEval = 'Run all threads while evaluating';
LazErrSymbolNotFound_p = 'Identifier not found: "%1:s"%2:s';
LazErrIndexOutOfRange = 'Index out of range: %1:d';
LazErrTypeNotIndexable = 'The value has no index';
LazErrExpectedOrdinalVal_p = 'Expected an ordinal value, but found ''%1:s''%2:s';
LazErrCannotCastToPointer_p = 'Can''t cast value to pointer ''%1:s''%2:s';
LazErrCannotDeref_p = 'Can''t dereference expression ''%1:s''%2:s';
LazErrPasParserEmptyExpression = 'Empty Expression';
LazErrPasParserUnexpectedEndOfExpression = 'Unexpected end of expression after ''%1:s''';
LazErrPasParserUnexpectedToken_p = 'Unexpected token ''%1:s''%2:s';
LazErrPasParserUnknownIntrinsic_p = 'Intrinsic function ''%1:s'' not found%2:s';
LazErrPasParserMissingOpenBracket_p = 'No opening bracket for ''%1:s'' found%2:s';
LazErrPasParserWrongOpenBracket_p = 'Mismatched opening bracket (''%3:s'' at pos %2:d) for ''%1:s'' found%4:s';
LazErrPasParserMissingIndexExpression = 'Expected Expression but found closing bracket: ''%1:s'' at pos %2:d';
LazErrPasParserMissingExprAfterComma = 'Expected Expression after Comma, but found closing bracket %1:s at pos %2:d';
LazErrPasParserIndexError_Wrapper = 'Index error at pos %2:d for ''%1:s''[]: %3:s';
LazErrPasParserUnterminatedString_p = 'String not terminated%1:s';
LazErrPasParserExpectedNumber_p = 'Expected Number, but found ''%1:s''%2:s';
(* Any resourcestring endig in *_p may or may not have one of the below included.
The value may also be an empty string instead.
*)
LazErrPasParser_AtStart = ' at start of expression';
LazErrPasParser_PositionAfter = ' at pos %1:d after ''%2:s''';
LazErrPasParser_Position = ' at pos %1:d';
implementation
end.

View File

@ -61,6 +61,9 @@
<UnitName Value="FpDebugFpcConvVariantNormalizer"/>
</Item>
</Files>
<i18n>
<EnableI18N Value="True"/>
</i18n>
<RequiredPkgs>
<Item>
<PackageName Value="CmdLineDebuggerBase"/>

View File

@ -10,7 +10,8 @@ uses
TTestWatchUtilities, TestCommonSources, TestDbgConfig, LazDebuggerIntf,
LazDebuggerIntfBaseTypes, LazDebuggerValueConverter, DbgIntfDebuggerBase,
DbgIntfBaseTypes, FpDbgInfo, FpPascalParser, FpDbgCommon, Forms,
IdeDebuggerBase, IdeDebuggerWatchResult, IdeDebuggerBackendValueConv;
IdeDebuggerBase, IdeDebuggerWatchResult, IdeDebuggerBackendValueConv,
FpDebugStringConstants;
type
@ -4079,6 +4080,12 @@ begin
//t.Add('', '^char(1)^+[1]', weMatchErr('Can not evaluate: "\[1\]"'));
t.Add('', '^char(1)^+[1]', weMatchErr('.'));
t.Add('', 'not_exist_fooxyz', weMatchFpErr(LazErrSymbolNotFound_p));
t.Add('', 'gvAnsi4[99]', weMatchFpErr(LazErrPasParserIndexError_Wrapper + '%x' + LazErrIndexOutOfRange)).IgnAll(stDwarf2);
t.Add('', 'gvIntStatArray[1,2]', weMatchFpErr(LazErrPasParserIndexError_Wrapper + '%x' + LazErrTypeNotIndexable));
t.Add('', 'gvIntStatArray^', weMatchFpErr(LazErrCannotDeref_p));
t.Add('', '^byte(''abc'')^', weMatchErr('.'));
t.EvaluateWatches;
t.CheckResults;

View File

@ -595,7 +595,7 @@ begin
if (i in [5..7]) and not(BrkIdx in [4, 5]) then
ErrCodeNotFound := fpErrNoMemberWithName
else
ErrCodeNotFound := fpErrSymbolNotFound;
ErrCodeNotFound := fpErrSymbolNotFound_p;
if i in [0, 5] then begin
@ -703,7 +703,7 @@ begin
r := AddFmtDef(Format('%sSet2%1:s', [s,s2]), '^\[\]', skSimple, '', [fTpMtch]);
UpdExpRes(r, stDwarf, '', skSimple); // no sets in dwarf2
AddError(Format('%sByte1%1:s^', [s,s2]), fpErrCannotDereferenceType); // ERROR
AddError(Format('%sByte1%1:s^', [s,s2]), fpErrCannotDeref_p); // ERROR
end; // i2
end; // i
@ -893,7 +893,7 @@ begin
AddExpInt('%0:sDynDynInt1%1:s[%0:sDynDynInt1%1:s[3,0], %0:sDynDynInt1%1:s[3,1]]', [s,s2], 1012, M_Int);
AddExpInt('%0:sDynDynInt1%1:s[%0:sDynDynInt1%1:s[3,0]][%0:sDynDynInt1%1:s[3,1]]', [s,s2], 1012, M_Int);
AddError('%0:sDynDynInt1%1:s[FooNoExistFoo, %0:sDynDynInt1%1:s[3,1]]', [s,s2], fpErrSymbolNotFound); // ERROR
AddError('%0:sDynDynInt1%1:s[FooNoExistFoo, %0:sDynDynInt1%1:s[3,1]]', [s,s2], fpErrSymbolNotFound_p); // ERROR
AddError('%0:sDynDynInt1%1:s[%0:sDynDynInt1%1:s[3,0].NoMember, %0:sDynDynInt1%1:s[3,1]]', [s,s2], fpErrorNotAStructure); // ERROR

View File

@ -322,6 +322,7 @@ type
function weMatch(AExpVal: String; ASymKind: TDBGSymbolKind; ATypeName: String=''): TWatchExpectationResult;
function weMatchErr(AExpVal: String): TWatchExpectationResult;
function weMatchFpErr(AExpVal: String): TWatchExpectationResult; // take stirng for FORMAT()
function weInteger(AExpVal: Int64; ATypeName: String=#1; ASize: Integer = 4): TWatchExpectationResult;
function weCardinal(AExpVal: QWord; ATypeName: String=#1; ASize: Integer = 4): TWatchExpectationResult;
@ -452,6 +453,27 @@ begin
Result.AddFlag(ehExpectErrorText);
end;
function weMatchFpErr(AExpVal: String): TWatchExpectationResult;
var
i, j: integer;
begin
AExpVal := QuoteRegExprMetaChars(AExpVal);
i := pos('%', AExpVal);
while (i > 0) and (i < Length(AExpVal)) do begin
j := i + 1;
while (j <= Length(AExpVal)) and not (AExpVal[j] in ['a'..'z', 'A'..'Z']) do inc(j);
AExpVal[i] := '.';
AExpVal[i+1] := '*';
delete(AExpVal, i+2, j-i-1);
i := pos('%', AExpVal);
end;
Result := Default(TWatchExpectationResult);
Result.ExpResultKind := rkMatch;
Result.ExpSymKind := skNone;
Result.ExpTextData := AExpVal;
Result.AddFlag(ehExpectErrorText);
end;
function weInteger(AExpVal: Int64; ATypeName: String; ASize: Integer
): TWatchExpectationResult;
begin