* Added support for giving multiple kernel debugger commands in a single
line, separated by ";". * Fixed incorrect parsing when "|" was not separated by a space from the previous argument. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35895 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -24,7 +24,7 @@
|
|||||||
/*
|
/*
|
||||||
Grammar:
|
Grammar:
|
||||||
|
|
||||||
commandLine := commandPipe | ( "(" expression ")" )
|
commandLine := ( commandPipe [ ";" commandLine ] ) | assignment
|
||||||
expression := term | assignment
|
expression := term | assignment
|
||||||
assignment := lhs ( "=" | "+=" | "-=" | "*=" | "/=" | "%=" )
|
assignment := lhs ( "=" | "+=" | "-=" | "*=" | "/=" | "%=" )
|
||||||
expression
|
expression
|
||||||
@@ -89,6 +89,7 @@ enum {
|
|||||||
TOKEN_CLOSING_BRACE = '}',
|
TOKEN_CLOSING_BRACE = '}',
|
||||||
|
|
||||||
TOKEN_PIPE = '|',
|
TOKEN_PIPE = '|',
|
||||||
|
TOKEN_SEMICOLON = ';',
|
||||||
|
|
||||||
TOKEN_STRING = '"',
|
TOKEN_STRING = '"',
|
||||||
TOKEN_UNKNOWN = '?',
|
TOKEN_UNKNOWN = '?',
|
||||||
@@ -181,7 +182,15 @@ public:
|
|||||||
|
|
||||||
void SetCommandMode(bool commandMode)
|
void SetCommandMode(bool commandMode)
|
||||||
{
|
{
|
||||||
|
if (fCommandMode == commandMode)
|
||||||
|
return;
|
||||||
|
|
||||||
fCommandMode = commandMode;
|
fCommandMode = commandMode;
|
||||||
|
|
||||||
|
if (fReuseToken) {
|
||||||
|
// We can't reuse the token, since the parsing mode changed.
|
||||||
|
SetPosition(fCurrentToken.position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* String() const
|
const char* String() const
|
||||||
@@ -290,6 +299,7 @@ public:
|
|||||||
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,
|
||||||
@@ -324,6 +334,7 @@ public:
|
|||||||
case '[':
|
case '[':
|
||||||
case ']':
|
case ']':
|
||||||
case '|':
|
case '|':
|
||||||
|
case ';':
|
||||||
fCurrentToken.SetTo(fCurrentChar, 1, _CurrentPos(),
|
fCurrentToken.SetTo(fCurrentChar, 1, _CurrentPos(),
|
||||||
*fCurrentChar);
|
*fCurrentChar);
|
||||||
fCurrentChar++;
|
fCurrentChar++;
|
||||||
@@ -404,6 +415,10 @@ public:
|
|||||||
case '"':
|
case '"':
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case '|': // TODO: Move when we support & and | in expressions.
|
||||||
|
case ';':
|
||||||
|
return fCommandMode;
|
||||||
|
|
||||||
case '{':
|
case '{':
|
||||||
case '}':
|
case '}':
|
||||||
case '=':
|
case '=':
|
||||||
@@ -509,26 +524,38 @@ ExpressionParser::EvaluateCommand(const char* expressionString, int& returnCode)
|
|||||||
const Token& token = fTokenizer.NextToken();
|
const Token& token = fTokenizer.NextToken();
|
||||||
uint64 value = 0;
|
uint64 value = 0;
|
||||||
|
|
||||||
if (token.type == TOKEN_IDENTIFIER) {
|
while (true) {
|
||||||
fTokenizer.NextToken();
|
int32 startPosition = token.position;
|
||||||
if (token.type & TOKEN_ASSIGN_FLAG) {
|
|
||||||
// an assignment
|
if (token.type == TOKEN_IDENTIFIER) {
|
||||||
fTokenizer.SetTo(expressionString);
|
fTokenizer.NextToken();
|
||||||
|
|
||||||
|
if (token.type & TOKEN_ASSIGN_FLAG) {
|
||||||
|
// an assignment
|
||||||
|
fTokenizer.SetPosition(startPosition);
|
||||||
|
value = _ParseExpression(true);
|
||||||
|
returnCode = 0;
|
||||||
|
} else {
|
||||||
|
// no assignment, so let's assume it's a command
|
||||||
|
fTokenizer.SetPosition(startPosition);
|
||||||
|
fTokenizer.SetCommandMode(true);
|
||||||
|
value = _ParseCommandPipe(returnCode);
|
||||||
|
}
|
||||||
|
} else if (token.type == TOKEN_STAR) {
|
||||||
|
// dereferenced address -- assignment
|
||||||
|
fTokenizer.SetPosition(startPosition);
|
||||||
value = _ParseExpression(true);
|
value = _ParseExpression(true);
|
||||||
returnCode = 0;
|
returnCode = 0;
|
||||||
} else {
|
} else
|
||||||
// no assignment, so let's assume it's a command
|
parse_exception("expected command or assignment", token.position);
|
||||||
fTokenizer.SetTo(expressionString);
|
|
||||||
fTokenizer.SetCommandMode(true);
|
// might be chained with ";"
|
||||||
value = _ParseCommandPipe(returnCode);
|
if (fTokenizer.NextToken().type != TOKEN_SEMICOLON)
|
||||||
}
|
break;
|
||||||
} else if (token.type == TOKEN_STAR) {
|
|
||||||
// dereferenced address -- assignment
|
fTokenizer.SetCommandMode(false);
|
||||||
fTokenizer.SetTo(expressionString);
|
fTokenizer.NextToken();
|
||||||
value = _ParseExpression(true);
|
}
|
||||||
returnCode = 0;
|
|
||||||
} else
|
|
||||||
parse_exception("expected command or assignment", 0);
|
|
||||||
|
|
||||||
if (token.type != TOKEN_END_OF_LINE)
|
if (token.type != TOKEN_END_OF_LINE)
|
||||||
parse_exception("parse error", token.position);
|
parse_exception("parse error", token.position);
|
||||||
@@ -843,6 +870,7 @@ ExpressionParser::_ParseArgument(int& argc, char** argv)
|
|||||||
case TOKEN_CLOSING_PARENTHESIS:
|
case TOKEN_CLOSING_PARENTHESIS:
|
||||||
case TOKEN_CLOSING_BRACKET:
|
case TOKEN_CLOSING_BRACKET:
|
||||||
case TOKEN_PIPE:
|
case TOKEN_PIPE:
|
||||||
|
case TOKEN_SEMICOLON:
|
||||||
// those don't belong to us
|
// those don't belong to us
|
||||||
fTokenizer.RewindToken();
|
fTokenizer.RewindToken();
|
||||||
return false;
|
return false;
|
||||||
@@ -890,6 +918,7 @@ ExpressionParser::_GetUnparsedArgument(int& argc, char** argv)
|
|||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
case TOKEN_PIPE:
|
case TOKEN_PIPE:
|
||||||
|
case TOKEN_SEMICOLON:
|
||||||
if (parentheses == 0 && brackets == 0)
|
if (parentheses == 0 && brackets == 0)
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user