From 325b88a661bd51702cf70ec96dc1974de429b258 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 21 Jan 2008 23:25:34 +0000 Subject: [PATCH] * Introduced debugger command flag B_KDEBUG_DONT_PARSE_ARGUMENTS. For commands with this flag set, the parser won't parse the arguments provided (it will only check for matching parentheses and brackets), but will pass the unparsed argument list string to the command instead. * Set the new flag for the "expr" command, so one doesn't have to quote the expression to evaluate anymore (or put it in parentheses). * Fixed tokenizing of quoted and unquoted strings in expression mode. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23697 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/debug.h | 2 + src/system/kernel/debug/debug.cpp | 3 +- src/system/kernel/debug/debug_parser.cpp | 76 +++++++++++++++++++++--- 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/headers/private/kernel/debug.h b/headers/private/kernel/debug.h index 404b7b7264..726673833d 100644 --- a/headers/private/kernel/debug.h +++ b/headers/private/kernel/debug.h @@ -40,6 +40,8 @@ # define ASSERT_PRINT(x, format...) do { } while(0) #endif +#define B_KDEBUG_DONT_PARSE_ARGUMENTS (0x01) + extern int dbg_register_file[B_MAX_CPU_COUNT][14]; #ifdef __cplusplus diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index d85ad50e3e..0a52fae5fc 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -943,7 +943,8 @@ debug_init_post_vm(kernel_args *args) add_debugger_command_etc("expr", &cmd_expr, "Evaluates the given expression and prints the result", "\n" - "Evaluates the given expression and prints the result.\n", 0); + "Evaluates the given expression and prints the result.\n", + B_KDEBUG_DONT_PARSE_ARGUMENTS); debug_variables_init(); frame_buffer_console_init(args); diff --git a/src/system/kernel/debug/debug_parser.cpp b/src/system/kernel/debug/debug_parser.cpp index 27c6af821e..5a69a5ae38 100644 --- a/src/system/kernel/debug/debug_parser.cpp +++ b/src/system/kernel/debug/debug_parser.cpp @@ -208,6 +208,11 @@ public: fCommandMode = commandMode; } + const char* String() const + { + return fString; + } + const Token& NextToken() { if (fCurrentToken.type == TOKEN_END_OF_LINE) @@ -316,12 +321,14 @@ public: case '"': { + fCurrentChar--; _QuotedString(); break; } default: { + fCurrentChar--; _UnquotedString(); break; } @@ -465,8 +472,9 @@ class ExpressionParser { uint64 _ParseExpression(); uint64 _ParseCommand(int& returnCode); bool _ParseArgument(int& argc, char** argv); + void _GetUnparsedArgument(int& argc, char** argv); void _AddArgument(int& argc, char** argv, - const char* argument); + const char* argument, int32 length = -1); uint64 _ParseSum(); uint64 _ParseProduct(); uint64 _ParsePower(); @@ -645,10 +653,14 @@ ExpressionParser::_ParseCommand(int& returnCode) argv[argc++] = (char*)command->name; // get the arguments - while (fTokenizer.NextToken().type != TOKEN_END_OF_LINE) { - fTokenizer.RewindToken(); - if (!_ParseArgument(argc, argv)) - break; + if ((command->flags & B_KDEBUG_DONT_PARSE_ARGUMENTS) != 0) { + _GetUnparsedArgument(argc, argv); + } else { + while (fTokenizer.NextToken().type != TOKEN_END_OF_LINE) { + fTokenizer.RewindToken(); + if (!_ParseArgument(argc, argv)) + break; + } } // invoke the command @@ -713,14 +725,62 @@ ExpressionParser::_ParseArgument(int& argc, char** argv) void -ExpressionParser::_AddArgument(int& argc, char** argv, const char* argument) +ExpressionParser::_GetUnparsedArgument(int& argc, char** argv) +{ + int32 startPosition = fTokenizer.NextToken().position; + fTokenizer.RewindToken(); + + // match parentheses and brackets, but otherwise skip all tokens + int32 parentheses = 0; + int32 brackets = 0; + bool done = false; + while (!done) { + const Token& token = fTokenizer.NextToken(); + switch (token.type) { + case TOKEN_OPENING_PARENTHESIS: + parentheses++; + break; + case TOKEN_OPENING_BRACKET: + brackets++; + break; + case TOKEN_CLOSING_PARENTHESIS: + if (parentheses > 0) + parentheses--; + else + done = true; + break; + case TOKEN_CLOSING_BRACKET: + if (brackets > 0) + brackets--; + else + done = true; + break; + case TOKEN_END_OF_LINE: + done = true; + break; + } + } + + int32 endPosition = fTokenizer.CurrentToken().position; + fTokenizer.RewindToken(); + + _AddArgument(argc, argv, fTokenizer.String() + startPosition, + endPosition - startPosition); +} + + +void +ExpressionParser::_AddArgument(int& argc, char** argv, const char* argument, + int32 length) { if (argc == kMaxArgumentCount) parse_exception("too many arguments for command", 0); - size_t length = strlen(argument) + 1; + if (length < 0) + length = strlen(argument); + length++; char* buffer = (char*)allocate_temp_storage(length); - memcpy(buffer, argument, length); + strlcpy(buffer, argument, length); argv[argc++] = buffer; }