Added unary "*" operator for dereferencing addresses to the
debugger expression language. By default it reads a uint32 value.
Another target size (1, 2, 4, or 8 bytes) can be specified in braces
after the "*" (e.g. "*{2}address" for uint16).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23551 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -28,7 +28,7 @@
|
|||||||
term := sum
|
term := sum
|
||||||
sum := product ( ( "+" | "-" ) product )*
|
sum := product ( ( "+" | "-" ) product )*
|
||||||
product := unary ( ( "*" | "/" | "%" ) unary )*
|
product := unary ( ( "*" | "/" | "%" ) unary )*
|
||||||
unary := [ "-" ] atom
|
unary := atom | ( ( "-" | "*" [ "{" expression "}" ] ) unary )
|
||||||
atom := variable | ( "(" expression ")" ) | ( "[" command "]" )
|
atom := variable | ( "(" expression ")" ) | ( "[" command "]" )
|
||||||
variable := identifier
|
variable := identifier
|
||||||
identifier := ( "_" | "a" - "z" | "A" - "Z" )
|
identifier := ( "_" | "a" - "z" | "A" - "Z" )
|
||||||
@@ -84,6 +84,8 @@ enum {
|
|||||||
TOKEN_CLOSING_PARENTHESIS = ')',
|
TOKEN_CLOSING_PARENTHESIS = ')',
|
||||||
TOKEN_OPENING_BRACKET = '[',
|
TOKEN_OPENING_BRACKET = '[',
|
||||||
TOKEN_CLOSING_BRACKET = ']',
|
TOKEN_CLOSING_BRACKET = ']',
|
||||||
|
TOKEN_OPENING_BRACE = '{',
|
||||||
|
TOKEN_CLOSING_BRACE = '}',
|
||||||
|
|
||||||
TOKEN_STRING = '"',
|
TOKEN_STRING = '"',
|
||||||
TOKEN_UNKNOWN = '?',
|
TOKEN_UNKNOWN = '?',
|
||||||
@@ -227,6 +229,11 @@ public:
|
|||||||
return (fCommandMode ? _NextTokenCommand() : _NextTokenExpression());
|
return (fCommandMode ? _NextTokenCommand() : _NextTokenExpression());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Token& CurrentToken() const
|
||||||
|
{
|
||||||
|
return fCurrentToken;
|
||||||
|
}
|
||||||
|
|
||||||
void RewindToken()
|
void RewindToken()
|
||||||
{
|
{
|
||||||
fReuseToken = true;
|
fReuseToken = true;
|
||||||
@@ -298,6 +305,8 @@ public:
|
|||||||
case ')':
|
case ')':
|
||||||
case '[':
|
case '[':
|
||||||
case ']':
|
case ']':
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
{
|
{
|
||||||
int32 length = fCurrentChar - begin;
|
int32 length = fCurrentChar - begin;
|
||||||
fCurrentToken.SetTo(begin, length, _CurrentPos() - length,
|
fCurrentToken.SetTo(begin, length, _CurrentPos() - length,
|
||||||
@@ -409,6 +418,8 @@ public:
|
|||||||
case '"':
|
case '"':
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
case '=':
|
case '=':
|
||||||
case '+':
|
case '+':
|
||||||
case '-':
|
case '-':
|
||||||
@@ -775,14 +786,60 @@ ExpressionParser::_ParseProduct()
|
|||||||
uint64
|
uint64
|
||||||
ExpressionParser::_ParseUnary()
|
ExpressionParser::_ParseUnary()
|
||||||
{
|
{
|
||||||
const Token& token = fTokenizer.NextToken();
|
switch (fTokenizer.NextToken().type) {
|
||||||
if (token.type == TOKEN_END_OF_LINE)
|
|
||||||
parse_exception("unexpected end of expression", token.position);
|
|
||||||
|
|
||||||
switch (token.type) {
|
|
||||||
case TOKEN_MINUS:
|
case TOKEN_MINUS:
|
||||||
return -_ParseUnary();
|
return -_ParseUnary();
|
||||||
|
|
||||||
|
case TOKEN_STAR:
|
||||||
|
{
|
||||||
|
int32 starPosition = fTokenizer.CurrentToken().position;
|
||||||
|
|
||||||
|
// optional "{ ... }" specifying the size to read
|
||||||
|
uint64 size = 4;
|
||||||
|
if (fTokenizer.NextToken().type == TOKEN_OPENING_BRACE) {
|
||||||
|
int32 position = fTokenizer.CurrentToken().position;
|
||||||
|
size = _ParseExpression();
|
||||||
|
|
||||||
|
if (size != 1 && size != 2 && size != 4 && size != 8) {
|
||||||
|
snprintf(sTempBuffer, sizeof(sTempBuffer),
|
||||||
|
"invalid size (%llu) for unary * operator", size);
|
||||||
|
parse_exception(sTempBuffer, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
_EatToken(TOKEN_CLOSING_BRACE);
|
||||||
|
} else
|
||||||
|
fTokenizer.RewindToken();
|
||||||
|
|
||||||
|
const void* address = (const void*)(addr_t)_ParseUnary();
|
||||||
|
|
||||||
|
// read bytes from address into a tempory buffer
|
||||||
|
uint64 buffer;
|
||||||
|
if (user_memcpy(&buffer, address, size) != B_OK) {
|
||||||
|
snprintf(sTempBuffer, sizeof(sTempBuffer),
|
||||||
|
"failed to dereference address %p", address);
|
||||||
|
parse_exception(sTempBuffer, starPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the value to uint64
|
||||||
|
uint64 value = 0;
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
value = *(uint8*)&buffer;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = *(uint16*)&buffer;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
value = *(uint32*)&buffer;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
value = buffer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fTokenizer.RewindToken();
|
fTokenizer.RewindToken();
|
||||||
return _ParseAtom();
|
return _ParseAtom();
|
||||||
|
|||||||
Reference in New Issue
Block a user