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:
Ingo Weinhold
2008-01-16 03:55:19 +00:00
parent 267428a36a
commit 5c62817c6f
+63 -6
View File
@@ -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();