* 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:
Ingo Weinhold
2010-03-17 22:56:07 +00:00
parent bbba047c2d
commit 6365627b33
+48 -19
View File
@@ -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;