work on parameters to commands

This commit is contained in:
krakjoe 2014-02-19 00:33:49 +00:00
parent 1952750af6
commit e2e93ac259
7 changed files with 190 additions and 61 deletions

View File

@ -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
};

View File

@ -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,7 +631,13 @@ 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(

View File

@ -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

View File

@ -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
};

View File

@ -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
};

View File

@ -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);

View File

@ -27,13 +27,13 @@
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
const phpdbg_command_t phpdbg_set_commands[] = {
PHPDBG_COMMAND_D_EX(prompt, "usage: set prompt <string>", 'p', set_prompt, NULL, 0),
PHPDBG_COMMAND_D_EX(prompt, "usage: set prompt <string>", 'p', set_prompt, NULL, "s"),
#ifndef _WIN32
PHPDBG_COMMAND_D_EX(color, "usage: set color <element> <color>", 'c', set_color, NULL, 1),
PHPDBG_COMMAND_D_EX(colors, "usage: set colors <on|off>", 'C', set_colors, NULL, 1),
PHPDBG_COMMAND_D_EX(color, "usage: set color <element> <color>", 'c', set_color, NULL, "ss"),
PHPDBG_COMMAND_D_EX(colors, "usage: set colors <on|off>", 'C', set_colors, NULL, "b"),
#endif
PHPDBG_COMMAND_D_EX(oplog, "usage: set oplog <output>", 'O', set_oplog, NULL, 0),
PHPDBG_COMMAND_D_EX(break, "usage: set break [id] <on|off>", 'b', set_break, NULL, 0),
PHPDBG_COMMAND_D_EX(oplog, "usage: set oplog <output>", 'O', set_oplog, NULL, "s"),
PHPDBG_COMMAND_D_EX(break, "usage: set break [id] <on|off>", 'b', set_break, NULL, "lb"),
PHPDBG_END_COMMAND
};