Author: bonefish Date: 2010-03-17 23:56:07 +0100 (Wed, 17 Mar 2010) New Revision: 35895 Changeset: http://dev.haiku-os.org/changeset/35895/haiku Modified: haiku/trunk/src/system/kernel/debug/debug_parser.cpp Log: * 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. Modified: haiku/trunk/src/system/kernel/debug/debug_parser.cpp =================================================================== --- haiku/trunk/src/system/kernel/debug/debug_parser.cpp 2010-03-17 18:51:41 UTC (rev 35894) +++ haiku/trunk/src/system/kernel/debug/debug_parser.cpp 2010-03-17 22:56:07 UTC (rev 35895) @@ -24,7 +24,7 @@ /* Grammar: - commandLine := commandPipe | ( "(" expression ")" ) + commandLine := ( commandPipe [ ";" commandLine ] ) | assignment expression := term | assignment assignment := lhs ( "=" | "+=" | "-=" | "*=" | "/=" | "%=" ) expression @@ -89,6 +89,7 @@ TOKEN_CLOSING_BRACE = '}', TOKEN_PIPE = '|', + TOKEN_SEMICOLON = ';', TOKEN_STRING = '"', TOKEN_UNKNOWN = '?', @@ -181,7 +182,15 @@ void SetCommandMode(bool commandMode) { + if (fCommandMode == commandMode) + return; + fCommandMode = commandMode; + + if (fReuseToken) { + // We can't reuse the token, since the parsing mode changed. + SetPosition(fCurrentToken.position); + } } const char* String() const @@ -290,6 +299,7 @@ case ']': case '{': case '}': + case ';': { int32 length = fCurrentChar - begin; fCurrentToken.SetTo(begin, length, _CurrentPos() - length, @@ -324,6 +334,7 @@ case '[': case ']': case '|': + case ';': fCurrentToken.SetTo(fCurrentChar, 1, _CurrentPos(), *fCurrentChar); fCurrentChar++; @@ -404,6 +415,10 @@ case '"': return true; + case '|': // TODO: Move when we support & and | in expressions. + case ';': + return fCommandMode; + case '{': case '}': case '=': @@ -509,27 +524,39 @@ const Token& token = fTokenizer.NextToken(); uint64 value = 0; - if (token.type == TOKEN_IDENTIFIER) { - fTokenizer.NextToken(); - if (token.type & TOKEN_ASSIGN_FLAG) { - // an assignment - fTokenizer.SetTo(expressionString); + while (true) { + int32 startPosition = token.position; + + if (token.type == TOKEN_IDENTIFIER) { + 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); returnCode = 0; - } else { - // no assignment, so let's assume it's a command - fTokenizer.SetTo(expressionString); - fTokenizer.SetCommandMode(true); - value = _ParseCommandPipe(returnCode); - } - } else if (token.type == TOKEN_STAR) { - // dereferenced address -- assignment - fTokenizer.SetTo(expressionString); - value = _ParseExpression(true); - returnCode = 0; - } else - parse_exception("expected command or assignment", 0); + } else + parse_exception("expected command or assignment", token.position); + // might be chained with ";" + if (fTokenizer.NextToken().type != TOKEN_SEMICOLON) + break; + + fTokenizer.SetCommandMode(false); + fTokenizer.NextToken(); + } + if (token.type != TOKEN_END_OF_LINE) parse_exception("parse error", token.position); @@ -843,6 +870,7 @@ case TOKEN_CLOSING_PARENTHESIS: case TOKEN_CLOSING_BRACKET: case TOKEN_PIPE: + case TOKEN_SEMICOLON: // those don't belong to us fTokenizer.RewindToken(); return false; @@ -890,6 +918,7 @@ done = true; break; case TOKEN_PIPE: + case TOKEN_SEMICOLON: if (parentheses == 0 && brackets == 0) done = true; break;