From e2e93ac259150fde9e3660838a2e836daa939acb Mon Sep 17 00:00:00 2001 From: krakjoe Date: Wed, 19 Feb 2014 00:33:49 +0000 Subject: [PATCH] work on parameters to commands --- phpdbg_break.c | 18 +++--- phpdbg_cmd.c | 158 ++++++++++++++++++++++++++++++++++++++++++------ phpdbg_cmd.h | 14 ++--- phpdbg_list.c | 8 +-- phpdbg_print.c | 6 +- phpdbg_prompt.c | 37 +++++++----- phpdbg_set.c | 10 +-- 7 files changed, 190 insertions(+), 61 deletions(-) diff --git a/phpdbg_break.c b/phpdbg_break.c index 67267550c5..870f68a481 100644 --- a/phpdbg_break.c +++ b/phpdbg_break.c @@ -31,15 +31,15 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); * Commands */ const phpdbg_command_t phpdbg_break_commands[] = { - PHPDBG_COMMAND_D_EX(file, "specify breakpoint by file:line", 'F', break_file, NULL, 1), - PHPDBG_COMMAND_D_EX(func, "specify breakpoint by global function name", 'f', break_func, NULL, 1), - PHPDBG_COMMAND_D_EX(method, "specify breakpoint by class::method", 'm', break_method, NULL, 1), - PHPDBG_COMMAND_D_EX(address, "specify breakpoint by address", 'a', break_address, NULL, 1), - PHPDBG_COMMAND_D_EX(op, "specify breakpoint by opcode", 'O', break_op, NULL, 1), - PHPDBG_COMMAND_D_EX(on, "specify breakpoint by condition", 'o', break_on, NULL, 1), - PHPDBG_COMMAND_D_EX(at, "specify breakpoint by location and condition", 'A', break_at, NULL, 1), - PHPDBG_COMMAND_D_EX(lineno, "specify breakpoint by line of currently executing file", 'l', break_lineno, NULL, 1), - PHPDBG_COMMAND_D_EX(del, "delete breakpoint by identifier number", 'd', break_del, NULL, 1), + PHPDBG_COMMAND_D_EX(file, "specify breakpoint by file:line", 'F', break_file, NULL, "f"), + PHPDBG_COMMAND_D_EX(func, "specify breakpoint by global function name", 'f', break_func, NULL, "s"), + PHPDBG_COMMAND_D_EX(method, "specify breakpoint by class::method", 'm', break_method, NULL, "m"), + PHPDBG_COMMAND_D_EX(address, "specify breakpoint by address", 'a', break_address, NULL, "a"), + PHPDBG_COMMAND_D_EX(op, "specify breakpoint by opcode", 'O', break_op, NULL, "s"), + PHPDBG_COMMAND_D_EX(on, "specify breakpoint by condition", 'o', break_on, NULL, "c"), + PHPDBG_COMMAND_D_EX(at, "specify breakpoint by location and condition", 'A', break_at, NULL, "*c"), + PHPDBG_COMMAND_D_EX(lineno, "specify breakpoint by line of currently executing file", 'l', break_lineno, NULL, "l"), + PHPDBG_COMMAND_D_EX(del, "delete breakpoint by identifier number", 'd', break_del, NULL, "l"), PHPDBG_END_COMMAND }; diff --git a/phpdbg_cmd.c b/phpdbg_cmd.c index 27b8e15de8..c0149b3ad2 100644 --- a/phpdbg_cmd.c +++ b/phpdbg_cmd.c @@ -471,11 +471,132 @@ PHPDBG_API void phpdbg_stack_push(phpdbg_param_t *stack, phpdbg_param_t *param) stack->len++; } /* }}} */ +PHPDBG_API int phpdbg_stack_verify(phpdbg_command_t *command, const phpdbg_param_t **stack, char **why TSRMLS_DC) { + if (command && command->args) { + const phpdbg_param_t *top = (stack != NULL) ? *stack : NULL; + const char *arg = command->args; + size_t expected = strlen(command->args), + received = 0L; + zend_bool optional = 0; + + if (*arg == '|') { + expected--; + optional = 1; + arg++; + } + + if (arg && !top && !optional) { + asprintf(why, + "%s expected arguments and received none", command->name); + return FAILURE; + } + + while (top && arg) { + + switch (*arg) { + case '|': { + expected--; + optional = 1; + arg++; + } continue; + + case 'i': if (top->type != STR_PARAM) { + asprintf(why, + "%s expected raw input and got %s at parameter %d", + command->name, phpdbg_get_param_type(top TSRMLS_CC), + (command->args - arg) + 1); + return FAILURE; + } break; + + case 's': if (top->type != STR_PARAM) { + asprintf(why, + "%s expected string and got %s at parameter %d", + command->name, phpdbg_get_param_type(top TSRMLS_CC), + (command->args - arg) + 1); + return FAILURE; + } break; + + case 'n': if (top->type != NUMERIC_PARAM) { + asprintf(why, + "%s expected number and got %s at parameter %d", + command->name, phpdbg_get_param_type(top TSRMLS_CC), + (command->args - arg) + 1); + return FAILURE; + } break; + + case 'm': if (top->type != METHOD_PARAM) { + asprintf(why, + "%s expected method and got %s at parameter %d", + command->name, phpdbg_get_param_type(top TSRMLS_CC), + (command->args - arg) + 1); + return FAILURE; + } break; + + case 'a': if (top->type != ADDR_PARAM) { + asprintf(why, + "%s expected address and got %s at parameter %d", + command->name, phpdbg_get_param_type(top TSRMLS_CC), + (command->args - arg) + 1); + return FAILURE; + } break; + + case 'f': if (top->type != FILE_PARAM) { + asprintf(why, + "%s expected file:line and got %s at parameter %d", + command->name, phpdbg_get_param_type(top TSRMLS_CC), + (command->args - arg) + 1); + return FAILURE; + } break; + + case 'c': if (top->type != COND_PARAM) { + asprintf(why, + "%s expected condition and got %s at parameter %d", + command->name, phpdbg_get_param_type(top TSRMLS_CC), + (command->args - arg) + 1); + return FAILURE; + } break; + + case 'b': if (top->type != NUMERIC_PARAM) { + asprintf(why, + "%s expected boolean and got %s at parameter %d", + command->name, phpdbg_get_param_type(top TSRMLS_CC), + (command->args - arg) + 1); + return FAILURE; + } else if (top->num > 1 || top->num < 0) { + asprintf(why, + "%s expected boolean and got number at parameter %d", + command->name, phpdbg_get_param_type(top TSRMLS_CC), + (command->args - arg) + 1); + return FAILURE; + } break; + + case '*': { /* do nothing */ } break; + } + top = top->next; + received++; + arg++; + } + + if ((received < expected) && (arg && *arg) && !optional) { + asprintf(why, + "%s expected %d arguments (%s) and received %d", + command->name, + expected, + command->args, + received); + return FAILURE; + } + } + + return SUCCESS; +} + /* {{{ */ -PHPDBG_API phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *commands, phpdbg_param_t **top, char **why) { +PHPDBG_API phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *commands, const phpdbg_command_t *parent, phpdbg_param_t **top, char **why) { const phpdbg_command_t *command = commands; phpdbg_param_t *name = *top; phpdbg_command_t *matched[3] = {NULL, NULL, NULL}; + ulong matches = 0L; while (command && command->name && command->handler) { @@ -491,23 +612,18 @@ PHPDBG_API phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *comman } switch (matches) { - case 0: { + case 0: if (!parent) { asprintf( why, "The command %s could not be found", name->str); - } break; + return NULL; + } else return parent; case 1: { (*top) = (*top)->next; - if (matched[0]->subs && (*top) && ((*top)->type == STR_PARAM)) { - command = phpdbg_stack_resolve(matched[0]->subs, top, why); - if (command) { - return command; - } - } - - return matched[0]; + + command = matched[0]; } break; default: { @@ -515,9 +631,15 @@ PHPDBG_API phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *comman why, "The command %s is ambigious, matching %d commands", name->str, matches); - } + } return NULL; } - + + if (command->subs && (*top) && ((*top)->type == STR_PARAM)) { + return phpdbg_stack_resolve(command->subs, command, top, why); + } else { + return command; + } + return NULL; } /* }}} */ @@ -550,14 +672,14 @@ PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, char **why) { case STR_PARAM: { handler = phpdbg_stack_resolve( - phpdbg_prompt_commands, &command, why); + phpdbg_prompt_commands, NULL, &command, why); if (handler) { - return handler->handler(command, NULL TSRMLS_CC); - } else { - return FAILURE; + if (phpdbg_stack_verify(handler, &command, why) == SUCCESS) { + return handler->handler(command, NULL TSRMLS_CC); + } } - } break; + } return FAILURE; default: asprintf( diff --git a/phpdbg_cmd.h b/phpdbg_cmd.h index d22650c671..23766c62da 100644 --- a/phpdbg_cmd.h +++ b/phpdbg_cmd.h @@ -105,7 +105,7 @@ struct _phpdbg_command_t { char alias; /* Alias */ phpdbg_command_handler_t handler; /* Command handler */ const phpdbg_command_t *subs; /* Sub Commands */ - char arg_type; /* Accept args? */ + char *args; /* Argument Spec */ }; /* }}} */ @@ -147,7 +147,7 @@ PHPDBG_API void phpdbg_destroy_input(char** TSRMLS_DC); * Stack Management */ PHPDBG_API void phpdbg_stack_push(phpdbg_param_t *stack, phpdbg_param_t *param); -PHPDBG_API phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *commands, phpdbg_param_t **top, char **why); +PHPDBG_API phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *commands, const phpdbg_command_t *parent, phpdbg_param_t **top, char **why); PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, char **why); PHPDBG_API void phpdbg_stack_free(phpdbg_param_t *stack); @@ -168,17 +168,17 @@ PHPDBG_API void phpdbg_param_debug(const phpdbg_param_t *param, const char *msg) */ #define PHPDBG_COMMAND_HANDLER(name) phpdbg_do_##name -#define PHPDBG_COMMAND_D_EX(name, tip, alias, handler, children, has_args) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##handler, children, has_args} +#define PHPDBG_COMMAND_D_EX(name, tip, alias, handler, children, args) \ + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##handler, children, args} -#define PHPDBG_COMMAND_D(name, tip, alias, children, has_args) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##name, children, has_args} +#define PHPDBG_COMMAND_D(name, tip, alias, children, args) \ + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##name, children, args} #define PHPDBG_COMMAND(name) int phpdbg_do_##name(const phpdbg_param_t *param, const phpdbg_input_t *input TSRMLS_DC) #define PHPDBG_COMMAND_ARGS param, input TSRMLS_CC -#define PHPDBG_END_COMMAND {NULL, 0, NULL, 0, '\0', NULL, NULL, '\0'} +#define PHPDBG_END_COMMAND {NULL, 0, NULL, 0, '\0', NULL, NULL, '\0', '\0'} /* * Default Switch Case diff --git a/phpdbg_list.c b/phpdbg_list.c index 7177def8d6..a1bd8c0ff5 100644 --- a/phpdbg_list.c +++ b/phpdbg_list.c @@ -33,10 +33,10 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); const phpdbg_command_t phpdbg_list_commands[] = { - PHPDBG_COMMAND_D_EX(lines, "lists the specified lines", 'l', list_lines, NULL, 1), - PHPDBG_COMMAND_D_EX(class, "lists the specified class", 'c', list_class, NULL, 1), - PHPDBG_COMMAND_D_EX(method, "lists the specified method", 'm', list_method, NULL, 1), - PHPDBG_COMMAND_D_EX(func, "lists the specified function", 'f', list_func, NULL, 1), + PHPDBG_COMMAND_D_EX(lines, "lists the specified lines", 'l', list_lines, NULL, "l"), + PHPDBG_COMMAND_D_EX(class, "lists the specified class", 'c', list_class, NULL, "s"), + PHPDBG_COMMAND_D_EX(method, "lists the specified method", 'm', list_method, NULL, "m"), + PHPDBG_COMMAND_D_EX(func, "lists the specified function", 'f', list_func, NULL, "s"), PHPDBG_END_COMMAND }; diff --git a/phpdbg_print.c b/phpdbg_print.c index 7e549a2779..ed630c200c 100644 --- a/phpdbg_print.c +++ b/phpdbg_print.c @@ -29,9 +29,9 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); const phpdbg_command_t phpdbg_print_commands[] = { PHPDBG_COMMAND_D_EX(exec, "print out the instructions in the execution context", 'e', print_exec, NULL, 0), PHPDBG_COMMAND_D_EX(opline, "print out the instruction in the current opline", 'o', print_opline, NULL, 0), - PHPDBG_COMMAND_D_EX(class, "print out the instructions in the specified class", 'c', print_class, NULL, 1), - PHPDBG_COMMAND_D_EX(method, "print out the instructions in the specified method", 'm', print_method, NULL, 1), - PHPDBG_COMMAND_D_EX(func, "print out the instructions in the specified function", 'f', print_func, NULL, 1), + PHPDBG_COMMAND_D_EX(class, "print out the instructions in the specified class", 'c', print_class, NULL, "s"), + PHPDBG_COMMAND_D_EX(method, "print out the instructions in the specified method", 'm', print_method, NULL, "m"), + PHPDBG_COMMAND_D_EX(func, "print out the instructions in the specified function", 'f', print_func, NULL, "s"), PHPDBG_COMMAND_D_EX(stack, "print out the instructions in the current stack", 's', print_stack, NULL, 0), PHPDBG_END_COMMAND }; diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index 6aff5dd0d1..1e1f048ebf 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -44,29 +44,29 @@ int yyparse(phpdbg_param_t *stack, yyscan_t scanner); /* {{{ command declarations */ const phpdbg_command_t phpdbg_prompt_commands[] = { - PHPDBG_COMMAND_D(exec, "set execution context", 'e', NULL, 1), + PHPDBG_COMMAND_D(exec, "set execution context", 'e', NULL, "s"), PHPDBG_COMMAND_D(compile, "attempt compilation", 'c', NULL, 0), - PHPDBG_COMMAND_D(step, "step through execution", 's', NULL, 1), + PHPDBG_COMMAND_D(step, "step through execution", 's', NULL, "b"), PHPDBG_COMMAND_D(next, "continue execution", 'n', NULL, 0), PHPDBG_COMMAND_D(run, "attempt execution", 'r', NULL, 0), - PHPDBG_COMMAND_D(eval, "evaluate some code", 'E', NULL, 1), + PHPDBG_COMMAND_D(eval, "evaluate some code", 'E', NULL, "i"), PHPDBG_COMMAND_D(until, "continue past the current line", 'u', NULL, 0), PHPDBG_COMMAND_D(finish, "continue past the end of the stack", 'F', NULL, 0), PHPDBG_COMMAND_D(leave, "continue until the end of the stack", 'L', NULL, 0), - PHPDBG_COMMAND_D(print, "print something", 'p', phpdbg_print_commands, 2), - PHPDBG_COMMAND_D(break, "set breakpoint", 'b', phpdbg_break_commands, 1), + PHPDBG_COMMAND_D(print, "print something", 'p', phpdbg_print_commands, "s"), + PHPDBG_COMMAND_D(break, "set breakpoint", 'b', phpdbg_break_commands, 0), PHPDBG_COMMAND_D(back, "show trace", 't', NULL, 0), - PHPDBG_COMMAND_D(frame, "switch to a frame", 'f', NULL, 1), - PHPDBG_COMMAND_D(list, "lists some code", 'l', phpdbg_list_commands, 2), - PHPDBG_COMMAND_D(info, "displays some informations", 'i', phpdbg_info_commands, 1), + PHPDBG_COMMAND_D(frame, "switch to a frame", 'f', NULL, "n"), + PHPDBG_COMMAND_D(list, "lists some code", 'l', phpdbg_list_commands, "*"), + PHPDBG_COMMAND_D(info, "displays some informations", 'i', phpdbg_info_commands, "s"), PHPDBG_COMMAND_D(clean, "clean the execution environment", 'X', NULL, 0), PHPDBG_COMMAND_D(clear, "clear breakpoints", 'C', NULL, 0), - PHPDBG_COMMAND_D(help, "show help menu", 'h', phpdbg_help_commands, 2), - PHPDBG_COMMAND_D(quiet, "silence some output", 'Q', NULL, 1), - PHPDBG_COMMAND_D(set, "set phpdbg configuration", 'S', phpdbg_set_commands, 1), - PHPDBG_COMMAND_D(register,"register a function", 'R', NULL, 1), - PHPDBG_COMMAND_D(source, "execute a phpdbginit", '.', NULL, 1), - PHPDBG_COMMAND_D(shell, "shell a command", '-', NULL, 1), + PHPDBG_COMMAND_D(help, "show help menu", 'h', phpdbg_help_commands, "|s"), + PHPDBG_COMMAND_D(quiet, "silence some output", 'Q', NULL, "b"), + PHPDBG_COMMAND_D(set, "set phpdbg configuration", 'S', phpdbg_set_commands, "s"), + PHPDBG_COMMAND_D(register,"register a function", 'R', NULL, "s"), + PHPDBG_COMMAND_D(source, "execute a phpdbginit", '.', NULL, "s"), + PHPDBG_COMMAND_D(shell, "shell a command", '-', NULL, 0), PHPDBG_COMMAND_D(quit, "exit phpdbg", 'q', NULL, 0), PHPDBG_END_COMMAND }; /* }}} */ @@ -989,8 +989,10 @@ int phpdbg_interactive(TSRMLS_D) /* {{{ */ }*/ phpdbg_error("%s", why); } - if (why) + if (why) { free(why); + why = NULL; + } break; case PHPDBG_LEAVE: @@ -1005,6 +1007,11 @@ int phpdbg_interactive(TSRMLS_D) /* {{{ */ } } + if (why) { + free(why); + why = NULL; + } + yy_delete_buffer(state, scanner); yylex_destroy(scanner); diff --git a/phpdbg_set.c b/phpdbg_set.c index 6280086da4..a0dac2ea5b 100644 --- a/phpdbg_set.c +++ b/phpdbg_set.c @@ -27,13 +27,13 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); const phpdbg_command_t phpdbg_set_commands[] = { - PHPDBG_COMMAND_D_EX(prompt, "usage: set prompt ", 'p', set_prompt, NULL, 0), + PHPDBG_COMMAND_D_EX(prompt, "usage: set prompt ", 'p', set_prompt, NULL, "s"), #ifndef _WIN32 - PHPDBG_COMMAND_D_EX(color, "usage: set color ", 'c', set_color, NULL, 1), - PHPDBG_COMMAND_D_EX(colors, "usage: set colors ", 'C', set_colors, NULL, 1), + PHPDBG_COMMAND_D_EX(color, "usage: set color ", 'c', set_color, NULL, "ss"), + PHPDBG_COMMAND_D_EX(colors, "usage: set colors ", 'C', set_colors, NULL, "b"), #endif - PHPDBG_COMMAND_D_EX(oplog, "usage: set oplog ", 'O', set_oplog, NULL, 0), - PHPDBG_COMMAND_D_EX(break, "usage: set break [id] ", 'b', set_break, NULL, 0), + PHPDBG_COMMAND_D_EX(oplog, "usage: set oplog ", 'O', set_oplog, NULL, "s"), + PHPDBG_COMMAND_D_EX(break, "usage: set break [id] ", 'b', set_break, NULL, "lb"), PHPDBG_END_COMMAND }; -- 2.40.0