diff --git a/phpdbg_bp.c b/phpdbg_bp.c index a1ce1816748..76d8b01764a 100644 --- a/phpdbg_bp.c +++ b/phpdbg_bp.c @@ -45,32 +45,42 @@ static void phpdbg_class_breaks_dtor(void *data) /* {{{ */ void phpdbg_set_breakpoint_file(const char *path, long line_num TSRMLS_DC) /* {{{ */ { - phpdbg_breakfile_t new_break; - zend_llist *break_files_ptr; - size_t path_len = strlen(path); + struct stat sb; - new_break.filename = estrndup(path, path_len); - new_break.line = line_num; + if (VCWD_STAT(path, &sb) != FAILURE) { + if (sb.st_mode & S_IFREG|S_IFLNK) { + phpdbg_breakfile_t new_break; + zend_llist *break_files_ptr; + size_t path_len = strlen(path); - PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; + new_break.filename = estrndup(path, path_len); + new_break.line = line_num; - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], - new_break.filename, path_len, (void**)&break_files_ptr) == FAILURE) { - zend_llist break_files; + PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; - zend_llist_init(&break_files, sizeof(phpdbg_breakfile_t), - phpdbg_llist_breakfile_dtor, 0); + if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], + new_break.filename, path_len, (void**)&break_files_ptr) == FAILURE) { + zend_llist break_files; - zend_hash_update(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], - new_break.filename, path_len, &break_files, sizeof(zend_llist), - (void**)&break_files_ptr); - } + zend_llist_init(&break_files, sizeof(phpdbg_breakfile_t), + phpdbg_llist_breakfile_dtor, 0); - new_break.id = PHPDBG_G(bp_count)++; - zend_llist_add_element(break_files_ptr, &new_break); + zend_hash_update(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], + new_break.filename, path_len, &break_files, sizeof(zend_llist), + (void**)&break_files_ptr); + } - phpdbg_notice("Breakpoint #%d added at %s:%ld", - new_break.id, new_break.filename, new_break.line); + new_break.id = PHPDBG_G(bp_count)++; + zend_llist_add_element(break_files_ptr, &new_break); + + phpdbg_notice("Breakpoint #%d added at %s:%ld", + new_break.id, new_break.filename, new_break.line); + } else { + phpdbg_error("Cannot set breakpoint in %s, it is not a regular file", path); + } + } else { + phpdbg_error("Cannot stat %s, it does not exist", path); + } } /* }}} */ void phpdbg_set_breakpoint_symbol(const char *name TSRMLS_DC) /* {{{ */ diff --git a/phpdbg_break.c b/phpdbg_break.c index 03d87f6e199..21500436346 100644 --- a/phpdbg_break.c +++ b/phpdbg_break.c @@ -29,15 +29,11 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); PHPDBG_BREAK(file) /* {{{ */ { switch (param->type) { - case EMPTY_PARAM: - phpdbg_error("No expression provided"); - break; case FILE_PARAM: phpdbg_set_breakpoint_file(param->file.name, param->file.line TSRMLS_CC); break; - default: - phpdbg_error("Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC)); - break; + + phpdbg_default_switch_case(); } return SUCCESS; @@ -46,16 +42,11 @@ PHPDBG_BREAK(file) /* {{{ */ PHPDBG_BREAK(method) /* {{{ */ { switch (param->type) { - case EMPTY_PARAM: - phpdbg_error("No expression provided"); - break; case METHOD_PARAM: phpdbg_set_breakpoint_method(param->method.class, param->method.name TSRMLS_CC); break; - - default: - phpdbg_error("Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC)); - break; + + phpdbg_default_switch_case(); } return SUCCESS; @@ -64,16 +55,11 @@ PHPDBG_BREAK(method) /* {{{ */ PHPDBG_BREAK(address) /* {{{ */ { switch (param->type) { - case EMPTY_PARAM: - phpdbg_error("No expression provided"); - break; case ADDR_PARAM: phpdbg_set_breakpoint_opline(param->addr TSRMLS_CC); break; - default: - phpdbg_error( - "Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC)); - return FAILURE; + + phpdbg_default_switch_case(); } return SUCCESS; @@ -81,34 +67,30 @@ PHPDBG_BREAK(address) /* {{{ */ PHPDBG_BREAK(on) /* {{{ */ { - if (param->type == STR_PARAM) { - phpdbg_set_breakpoint_expression(param->str, param->len TSRMLS_CC); - } else { - phpdbg_error( - "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); - return FAILURE; - } + switch (param->type) { + case STR_PARAM: + phpdbg_set_breakpoint_expression(param->str, param->len TSRMLS_CC); + break; + + phpdbg_default_switch_case(); + } + return SUCCESS; } /* }}} */ PHPDBG_BREAK(lineno) /* {{{ */ { - if (!PHPDBG_G(exec)) { - phpdbg_error("Not file context found!"); - return SUCCESS; - } - switch (param->type) { - case EMPTY_PARAM: - phpdbg_error("No expression provided!"); - break; - case NUMERIC_PARAM: - phpdbg_set_breakpoint_file(phpdbg_current_file(TSRMLS_C), param->num TSRMLS_CC); - break; - default: - phpdbg_error( - "Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC)); - return FAILURE; + case NUMERIC_PARAM: { + if (PHPDBG_G(exec)) { + phpdbg_set_breakpoint_file(phpdbg_current_file(TSRMLS_C), param->num TSRMLS_CC); + } else { + phpdbg_error( + "Execution context not set !"); + } + } break; + + phpdbg_default_switch_case(); } return SUCCESS; @@ -117,15 +99,11 @@ PHPDBG_BREAK(lineno) /* {{{ */ PHPDBG_BREAK(func) /* {{{ */ { switch (param->type) { - case EMPTY_PARAM: - phpdbg_error("No expression provided!"); - break; case STR_PARAM: phpdbg_set_breakpoint_symbol(param->str TSRMLS_CC); break; - default: - phpdbg_error("Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC)); - break; + + phpdbg_default_switch_case(); } return SUCCESS; diff --git a/phpdbg_help.c b/phpdbg_help.c index e7de30af935..4526f9fa834 100644 --- a/phpdbg_help.c +++ b/phpdbg_help.c @@ -94,6 +94,8 @@ PHPDBG_HELP(print) /* {{{ */ phpdbg_writeln("Will print the instructions for the global function my_function"); phpdbg_writeln("\t%sprint opline", PROMPT); phpdbg_writeln("Will print the instruction for the current opline"); + phpdbg_writeln("\t%sprint exec", PROMPT); + phpdbg_writeln("Will print the instructions for the execution context"); phpdbg_writeln(EMPTY); phpdbg_writeln("Specific printers loaded are show below:"); phpdbg_notice("Commands"); diff --git a/phpdbg_list.c b/phpdbg_list.c index 981367b1977..1b7938cab0d 100644 --- a/phpdbg_list.c +++ b/phpdbg_list.c @@ -31,44 +31,6 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); -static inline void i_phpdbg_list_func(const char *str, size_t len TSRMLS_DC) -{ - HashTable *func_table = EG(function_table); - zend_function* fbc; - char *func_name = str; - size_t func_name_len = len; - - /* search active scope if begins with period */ - if (func_name[0] == '.') { - if (EG(scope)) { - func_name++; - func_name_len--; - - func_table = &EG(scope)->function_table; - } else { - phpdbg_error("No active class"); - return; - } - } else if (!EG(function_table)) { - phpdbg_error("No function table loaded"); - return; - } else { - func_table = EG(function_table); - } - - /* use lowercase names, case insensitive */ - func_name = zend_str_tolower_dup(func_name, func_name_len); - - if (zend_hash_find(func_table, func_name, func_name_len+1, - (void**)&fbc) == SUCCESS) { - phpdbg_list_function(fbc TSRMLS_CC); - } else { - phpdbg_error("Function %s not found", func_name); - } - - efree(func_name); -} - PHPDBG_LIST(lines) /* {{{ */ { if (!PHPDBG_G(exec) || !zend_is_executing(TSRMLS_C)) { @@ -81,10 +43,10 @@ PHPDBG_LIST(lines) /* {{{ */ case EMPTY_PARAM: phpdbg_list_file(phpdbg_current_file(TSRMLS_C), param->type == EMPTY_PARAM ? 0 : param->num, - zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC); + zend_get_executed_lineno(TSRMLS_C), 0 TSRMLS_CC); break; case FILE_PARAM: - phpdbg_list_file(param->file.name, param->file.line, 0 TSRMLS_CC); + phpdbg_list_file(param->file.name, param->file.line, 0, 0 TSRMLS_CC); break; default: phpdbg_error("Unsupported parameter type (%s) for function", @@ -96,12 +58,13 @@ PHPDBG_LIST(lines) /* {{{ */ PHPDBG_LIST(func) /* {{{ */ { - if (param->type == STR_PARAM) { - i_phpdbg_list_func( - param->str, param->len TSRMLS_CC); - } else { - phpdbg_error( - "Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC)); + switch (param->type) { + case STR_PARAM: + phpdbg_list_function_byname( + param->str, param->len TSRMLS_CC); + break; + + phpdbg_default_switch_case(); } return SUCCESS; @@ -109,28 +72,29 @@ PHPDBG_LIST(func) /* {{{ */ PHPDBG_LIST(method) /* {{{ */ { - if (param->type == METHOD_PARAM) { - zend_class_entry **ce; + switch (param->type) { + case METHOD_PARAM: { + zend_class_entry **ce; - if (zend_lookup_class(param->method.class, strlen(param->method.class), &ce TSRMLS_CC) == SUCCESS) { - zend_function *function; - char *lcname = zend_str_tolower_dup( - param->method.name, strlen(param->method.name)); + if (zend_lookup_class(param->method.class, strlen(param->method.class), &ce TSRMLS_CC) == SUCCESS) { + zend_function *function; + char *lcname = zend_str_tolower_dup( + param->method.name, strlen(param->method.name)); - if (zend_hash_find(&(*ce)->function_table, lcname, strlen(lcname)+1, (void**) &function) == SUCCESS) { - phpdbg_list_function( - function TSRMLS_CC); + if (zend_hash_find(&(*ce)->function_table, lcname, strlen(lcname)+1, (void**) &function) == SUCCESS) { + phpdbg_list_function( + function TSRMLS_CC); + } else { + phpdbg_error("Could not find ::%s in %s", param->method.name, param->method.class); + } + + efree(lcname); } else { - phpdbg_error("Could not find ::%s in %s", param->method.name, param->method.class); + phpdbg_error("Could not find the class %s", param->method.class); } + } break; - efree(lcname); - } else { - phpdbg_error("Could not find the class %s", param->method.class); - } - } else { - phpdbg_error( - "Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC)); + phpdbg_default_switch_case(); } return SUCCESS; @@ -138,59 +102,36 @@ PHPDBG_LIST(method) /* {{{ */ PHPDBG_LIST(class) /* {{{ */ { - if (param->type == STR_PARAM) { - zend_class_entry **ce; + switch (param->type) { + case STR_PARAM: { + zend_class_entry **ce; - if (zend_lookup_class(param->str, param->len, &ce TSRMLS_CC) == SUCCESS) { - if ((*ce)->type == ZEND_USER_CLASS) { - if ((*ce)->info.user.filename) { - phpdbg_list_file( - (*ce)->info.user.filename, - (*ce)->info.user.line_end - (*ce)->info.user.line_start + 1, - (*ce)->info.user.line_start TSRMLS_CC - ); + if (zend_lookup_class(param->str, param->len, &ce TSRMLS_CC) == SUCCESS) { + if ((*ce)->type == ZEND_USER_CLASS) { + if ((*ce)->info.user.filename) { + phpdbg_list_file( + (*ce)->info.user.filename, + (*ce)->info.user.line_end - (*ce)->info.user.line_start + 1, + (*ce)->info.user.line_start, 0 TSRMLS_CC + ); + } else { + phpdbg_error("The source of the requested class (%s) cannot be found", (*ce)->name); + } } else { - phpdbg_error("The source of the requested class (%s) cannot be found", (*ce)->name); + phpdbg_error("The class requested (%s) is not user defined", (*ce)->name); } } else { - phpdbg_error("The class requested (%s) is not user defined", (*ce)->name); + phpdbg_error("The requested class (%s) could not be found", param->str); } - } else { - phpdbg_error("The requested class (%s) could not be found", param->str); - } - } else { - phpdbg_error( - "Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC)); + } break; + + phpdbg_default_switch_case(); } return SUCCESS; } /* }}} */ -void phpdbg_list_dispatch(phpdbg_param_t *param TSRMLS_DC) /* {{{ */ -{ - switch (param->type) { - case NUMERIC_PARAM: - case EMPTY_PARAM: - return PHPDBG_LIST_HANDLER(lines)(param TSRMLS_CC); - - case FILE_PARAM: - return PHPDBG_LIST_HANDLER(lines)(param TSRMLS_CC); - - case STR_PARAM: { - i_phpdbg_list_func(param->str, param->len TSRMLS_CC); - } break; - - case METHOD_PARAM: - return PHPDBG_LIST_HANDLER(method)(param TSRMLS_CC); - - default: - phpdbg_error( - "Unsupported parameter type (%s) for function", phpdbg_get_param_type(param TSRMLS_CC)); - break; - } -} /* }}} */ - -void phpdbg_list_file(const char *filename, long count, long offset TSRMLS_DC) /* {{{ */ +void phpdbg_list_file(const char *filename, long count, long offset, int highlight TSRMLS_DC) /* {{{ */ { unsigned char *mem, *pos, *last_pos, *end_pos; struct stat st; @@ -202,12 +143,13 @@ void phpdbg_list_file(const char *filename, long count, long offset TSRMLS_DC) / int all_content = (count == 0); unsigned int line = 0, displayed = 0; - if (VCWD_STAT(filename, &st) == -1) { + if (VCWD_STAT(filename, &st) == FAILURE) { phpdbg_error("Failed to stat file %s", filename); return; } + #ifndef _WIN32 - if ((fd = VCWD_OPEN(filename, O_RDONLY)) == -1) { + if ((fd = VCWD_OPEN(filename, O_RDONLY)) == FAILURE) { phpdbg_error("Failed to open file %s to list", filename); return; } @@ -249,7 +191,13 @@ void phpdbg_list_file(const char *filename, long count, long offset TSRMLS_DC) / if (!offset || offset <= line) { /* Without offset, or offset reached */ - phpdbg_writeln("%05u: %.*s", line, (int)(pos - last_pos), last_pos); + if (!highlight) { + phpdbg_writeln("%05u: %.*s", line, (int)(pos - last_pos), last_pos); + } else { + if (highlight != line) { + phpdbg_writeln(" %05u: %.*s", line, (int)(pos - last_pos), last_pos); + } else phpdbg_writeln(">%05u: %.*s", line, (int)(pos - last_pos), last_pos); + } ++displayed; } @@ -284,6 +232,44 @@ void phpdbg_list_function(const zend_function *fbc TSRMLS_DC) /* {{{ */ ops = (zend_op_array*)fbc; phpdbg_list_file(ops->filename, - ops->line_end - ops->line_start + 1, ops->line_start TSRMLS_CC); + ops->line_end - ops->line_start + 1, ops->line_start, 0 TSRMLS_CC); } /* }}} */ +void phpdbg_list_function_byname(const char *str, size_t len TSRMLS_DC) +{ + HashTable *func_table = EG(function_table); + zend_function* fbc; + char *func_name = (char*) str; + size_t func_name_len = len; + + /* search active scope if begins with period */ + if (func_name[0] == '.') { + if (EG(scope)) { + func_name++; + func_name_len--; + + func_table = &EG(scope)->function_table; + } else { + phpdbg_error("No active class"); + return; + } + } else if (!EG(function_table)) { + phpdbg_error("No function table loaded"); + return; + } else { + func_table = EG(function_table); + } + + /* use lowercase names, case insensitive */ + func_name = zend_str_tolower_dup(func_name, func_name_len); + + if (zend_hash_find(func_table, func_name, func_name_len+1, + (void**)&fbc) == SUCCESS) { + phpdbg_list_function(fbc TSRMLS_CC); + } else { + phpdbg_error("Function %s not found", func_name); + } + + efree(func_name); +} + diff --git a/phpdbg_list.h b/phpdbg_list.h index 5c5fffa6b82..7d06d84e5da 100644 --- a/phpdbg_list.h +++ b/phpdbg_list.h @@ -41,9 +41,9 @@ PHPDBG_LIST(class); PHPDBG_LIST(method); PHPDBG_LIST(func); +void phpdbg_list_function_byname(const char *, size_t TSRMLS_DC); void phpdbg_list_function(const zend_function* TSRMLS_DC); -void phpdbg_list_file(const char*, long, long TSRMLS_DC); -void phpdbg_list_dispatch(phpdbg_param_t *param TSRMLS_DC); +void phpdbg_list_file(const char*, long, long, int TSRMLS_DC); static const phpdbg_command_t phpdbg_list_commands[] = { PHPDBG_LIST_EX_D(lines, "lists the specified lines", 'l'), diff --git a/phpdbg_print.c b/phpdbg_print.c index 92609089998..9a4a1585d61 100644 --- a/phpdbg_print.c +++ b/phpdbg_print.c @@ -57,7 +57,7 @@ static inline void phpdbg_print_function_helper(zend_function *method TSRMLS_DC) phpdbg_writeln( "\t#%d-%d %s() %s", op_array->line_start, op_array->line_end, - method->common.function_name, + method->common.function_name ? method->common.function_name : "{main}", op_array->filename ? op_array->filename : "unknown"); } @@ -86,43 +86,62 @@ static inline void phpdbg_print_function_helper(zend_function *method TSRMLS_DC) } } +PHPDBG_PRINT(exec) /* {{{ */ +{ + if (PHPDBG_G(exec)) { + if (!PHPDBG_G(ops)) { + phpdbg_compile(TSRMLS_C); + } + + if (PHPDBG_G(ops)) { + phpdbg_notice( + "Context %s", PHPDBG_G(exec)); + + phpdbg_print_function_helper((zend_function*) PHPDBG_G(ops) TSRMLS_CC); + } + } else { + phpdbg_error("No execution context set"); + } + + return SUCCESS; +} /* }}} */ + PHPDBG_PRINT(class) /* {{{ */ { zend_class_entry **ce; - if (param->type == STR_PARAM) { - if (zend_lookup_class(param->str, param->len, &ce TSRMLS_CC) == SUCCESS) { - phpdbg_notice( - "%s %s: %s", - ((*ce)->type == ZEND_USER_CLASS) ? - "User" : "Internal", - ((*ce)->ce_flags & ZEND_ACC_INTERFACE) ? - "Interface" : - ((*ce)->ce_flags & ZEND_ACC_ABSTRACT) ? - "Abstract Class" : - "Class", - (*ce)->name); - - phpdbg_writeln("Methods (%d):", zend_hash_num_elements(&(*ce)->function_table)); - if (zend_hash_num_elements(&(*ce)->function_table)) { - HashPosition position; - zend_function *method; + switch (param->type) { + case STR_PARAM: { + if (zend_lookup_class(param->str, param->len, &ce TSRMLS_CC) == SUCCESS) { + phpdbg_notice( + "%s %s: %s", + ((*ce)->type == ZEND_USER_CLASS) ? + "User" : "Internal", + ((*ce)->ce_flags & ZEND_ACC_INTERFACE) ? + "Interface" : + ((*ce)->ce_flags & ZEND_ACC_ABSTRACT) ? + "Abstract Class" : + "Class", + (*ce)->name); - for (zend_hash_internal_pointer_reset_ex(&(*ce)->function_table, &position); - zend_hash_get_current_data_ex(&(*ce)->function_table, (void**) &method, &position) == SUCCESS; - zend_hash_move_forward_ex(&(*ce)->function_table, &position)) { - phpdbg_print_function_helper(method TSRMLS_CC); + phpdbg_writeln("Methods (%d):", zend_hash_num_elements(&(*ce)->function_table)); + if (zend_hash_num_elements(&(*ce)->function_table)) { + HashPosition position; + zend_function *method; + + for (zend_hash_internal_pointer_reset_ex(&(*ce)->function_table, &position); + zend_hash_get_current_data_ex(&(*ce)->function_table, (void**) &method, &position) == SUCCESS; + zend_hash_move_forward_ex(&(*ce)->function_table, &position)) { + phpdbg_print_function_helper(method TSRMLS_CC); + } } + } else { + phpdbg_error( + "The class %s could not be found", param->str); } - } else { - phpdbg_error( - "Cannot find class %s", param->str); - return FAILURE; - } - } else { - phpdbg_error( - "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); - return FAILURE; + } break; + + phpdbg_default_switch_case(); } return SUCCESS; @@ -130,33 +149,34 @@ PHPDBG_PRINT(class) /* {{{ */ PHPDBG_PRINT(method) /* {{{ */ { - if (param->type == METHOD_PARAM) { - zend_class_entry **ce; - - if (zend_lookup_class(param->method.class, strlen(param->method.class), &ce TSRMLS_CC) == SUCCESS) { - zend_function *fbc; - char *lcname = zend_str_tolower_dup(param->method.name, strlen(param->method.name)); + switch (param->type) { + case METHOD_PARAM: { + zend_class_entry **ce; - if (zend_hash_find(&(*ce)->function_table, lcname, strlen(lcname)+1, (void**)&fbc) == SUCCESS) { - phpdbg_notice( - "%s Method %s", - (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal", - fbc->common.function_name); - - phpdbg_print_function_helper(fbc TSRMLS_CC); + if (zend_lookup_class(param->method.class, strlen(param->method.class), &ce TSRMLS_CC) == SUCCESS) { + zend_function *fbc; + char *lcname = zend_str_tolower_dup(param->method.name, strlen(param->method.name)); + + if (zend_hash_find(&(*ce)->function_table, lcname, strlen(lcname)+1, (void**)&fbc) == SUCCESS) { + phpdbg_notice( + "%s Method %s", + (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal", + fbc->common.function_name); + + phpdbg_print_function_helper(fbc TSRMLS_CC); + } else { + phpdbg_error( + "The method %s could not be found", param->method.name); + } + + efree(lcname); } else { phpdbg_error( - "The method %s could not be found", param->method.name); + "The class %s could not be found", param->method.class); } - - efree(lcname); - } else { - phpdbg_error( - "Failed to find the requested class %s", param->method.class); - } - } else { - phpdbg_error( - "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); + } break; + + phpdbg_default_switch_case(); } return SUCCESS; @@ -164,51 +184,51 @@ PHPDBG_PRINT(method) /* {{{ */ PHPDBG_PRINT(func) /* {{{ */ { - if (param->type == STR_PARAM) { - HashTable *func_table = EG(function_table); - zend_function* fbc; - const char *func_name = param->str; - size_t func_name_len = param->len; - char *lcname; - /* search active scope if begins with period */ - if (func_name[0] == '.') { - if (EG(scope)) { - func_name++; - func_name_len--; + switch (param->type) { + case STR_PARAM: { + HashTable *func_table = EG(function_table); + zend_function* fbc; + const char *func_name = param->str; + size_t func_name_len = param->len; + char *lcname; + /* search active scope if begins with period */ + if (func_name[0] == '.') { + if (EG(scope)) { + func_name++; + func_name_len--; - func_table = &EG(scope)->function_table; - } else { - phpdbg_error("No active class"); - return SUCCESS; - } - } else if (!EG(function_table)) { - phpdbg_error( - "No function table loaded"); - return SUCCESS; - } else { - func_table = EG(function_table); - } + func_table = &EG(scope)->function_table; + } else { + phpdbg_error("No active class"); + return SUCCESS; + } + } else if (!EG(function_table)) { + phpdbg_error( + "No function table loaded"); + return SUCCESS; + } else { + func_table = EG(function_table); + } - lcname = zend_str_tolower_dup(func_name, func_name_len); + lcname = zend_str_tolower_dup(func_name, func_name_len); + + if (zend_hash_find(func_table, lcname, strlen(lcname)+1, (void**)&fbc) == SUCCESS) { + phpdbg_notice( + "%s %s %s", + (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal", + (fbc->common.scope) ? "Method" : "Function", + fbc->common.function_name); + + phpdbg_print_function_helper(fbc TSRMLS_CC); + } else { + phpdbg_error( + "The function %s could not be found", func_name); + } + + efree(lcname); + } break; - if (zend_hash_find(func_table, lcname, strlen(lcname)+1, (void**)&fbc) == SUCCESS) { - phpdbg_notice( - "%s %s %s", - (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal", - (fbc->common.scope) ? "Method" : "Function", - fbc->common.function_name); - - phpdbg_print_function_helper(fbc TSRMLS_CC); - } else { - phpdbg_error( - "Function %s not found", func_name); - } - - efree(lcname); - - } else { - phpdbg_error( - "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); + phpdbg_default_switch_case(); } return SUCCESS; diff --git a/phpdbg_print.h b/phpdbg_print.h index 01bc27fa43e..dc6a13338cd 100644 --- a/phpdbg_print.h +++ b/phpdbg_print.h @@ -34,6 +34,7 @@ /** * Printer Forward Declarations */ +PHPDBG_PRINT(exec); PHPDBG_PRINT(opline); PHPDBG_PRINT(class); PHPDBG_PRINT(method); @@ -43,6 +44,7 @@ PHPDBG_PRINT(func); * Commands */ static const phpdbg_command_t phpdbg_print_commands[] = { + PHPDBG_PRINT_D(exec, "print execution context instructions", 'e'), PHPDBG_PRINT_D(opline, "print the current opline information", 'o'), PHPDBG_PRINT_D(class, "print out the instructions in the specified class", 'c'), PHPDBG_PRINT_D(method, "print out the instructions in the specified method", 'm'), diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index 91cc881d60e..b78efb426ab 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -101,6 +101,8 @@ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TS zend_bool in_code = 0; while (fgets(cmd, PHPDBG_MAX_CMD, fp) != NULL) { + phpdbg_command_t *selected = NULL; + cmd_len = strlen(cmd)-1; while (*cmd && isspace(cmd[cmd_len-1])) @@ -141,7 +143,7 @@ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TS goto next_line; } - switch (phpdbg_do_cmd(phpdbg_prompt_commands, cmd, cmd_len TSRMLS_CC)) { + switch (phpdbg_do_cmd(phpdbg_prompt_commands, &selected, cmd, cmd_len TSRMLS_CC)) { case FAILURE: phpdbg_error( "Unrecognized command in %s:%d: %s!", init_file, line, cmd); @@ -188,42 +190,49 @@ void phpdbg_welcome(zend_bool cleaning TSRMLS_DC) /* {{{ */ static PHPDBG_COMMAND(exec) /* {{{ */ { - if (param->type == EMPTY_PARAM) { - phpdbg_error("No expression provided"); - return SUCCESS; - } else { - if (param->type == STR_PARAM) { - if (PHPDBG_G(exec)) { - phpdbg_notice("Unsetting old execution context: %s", PHPDBG_G(exec)); - efree(PHPDBG_G(exec)); - PHPDBG_G(exec) = NULL; - } - - if (PHPDBG_G(ops)) { - phpdbg_notice("Destroying compiled opcodes"); - phpdbg_clean(0 TSRMLS_CC); - } + switch (param->type) { + case STR_PARAM: { + struct stat sb; - PHPDBG_G(exec) = phpdbg_resolve_path(param->str TSRMLS_CC); + if (VCWD_STAT(param->str, &sb) != FAILURE) { + if (sb.st_mode & S_IFREG|S_IFLNK) { + if (PHPDBG_G(exec)) { + phpdbg_notice("Unsetting old execution context: %s", PHPDBG_G(exec)); + efree(PHPDBG_G(exec)); + PHPDBG_G(exec) = NULL; + } - if (!PHPDBG_G(exec)) { - phpdbg_error("Cannot get real file path"); - return FAILURE; - } + if (PHPDBG_G(ops)) { + phpdbg_notice("Destroying compiled opcodes"); + phpdbg_clean(0 TSRMLS_CC); + } - PHPDBG_G(exec_len) = strlen(PHPDBG_G(exec)); + PHPDBG_G(exec) = phpdbg_resolve_path(param->str TSRMLS_CC); + + if (!PHPDBG_G(exec)) { + phpdbg_error("Cannot get real file path"); + return SUCCESS; + } + + PHPDBG_G(exec_len) = strlen(PHPDBG_G(exec)); + + phpdbg_notice("Set execution context: %s", PHPDBG_G(exec)); + + } else { + phpdbg_error("Cannot use %s as execution context, not a valid file or symlink", param->str); + } + } else { + phpdbg_error("Cannot stat %s, ensure the file exists", param->str); + } + } break; + + phpdbg_default_switch_case(); + } - phpdbg_notice("Set execution context: %s", PHPDBG_G(exec)); - } else { - phpdbg_error("Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); - } - } - - return SUCCESS; } /* }}} */ -static inline int phpdbg_compile(TSRMLS_D) /* {{{ */ +int phpdbg_compile(TSRMLS_D) /* {{{ */ { zend_file_handle fh; @@ -253,8 +262,9 @@ static PHPDBG_COMMAND(compile) /* {{{ */ { if (!PHPDBG_G(exec)) { phpdbg_error("No execution context"); - return FAILURE; + return SUCCESS; } + if (!EG(in_execution)) { if (PHPDBG_G(ops)) { phpdbg_error("Destroying previously compiled opcodes"); @@ -262,23 +272,28 @@ static PHPDBG_COMMAND(compile) /* {{{ */ } } - return phpdbg_compile(TSRMLS_C); + phpdbg_compile(TSRMLS_C); + + return SUCCESS; } /* }}} */ static PHPDBG_COMMAND(step) /* {{{ */ { - if (param->type == EMPTY_PARAM || param->type == NUMERIC_PARAM) { - if (param->type == NUMERIC_PARAM && param->num) { - PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; - } else { - PHPDBG_G(flags) &= ~PHPDBG_IS_STEPPING; - } + switch (param->type) { + case EMPTY_PARAM: + case NUMERIC_PARAM: { + if (param->type == NUMERIC_PARAM && param->num) { + PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; + } else { + PHPDBG_G(flags) &= ~PHPDBG_IS_STEPPING; + } - phpdbg_notice("Stepping %s", - (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off"); - } else { - phpdbg_error("Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); - } + phpdbg_notice("Stepping %s", + (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off"); + } break; + + phpdbg_default_switch_case(); + } return SUCCESS; } /* }}} */ @@ -297,7 +312,7 @@ static PHPDBG_COMMAND(run) /* {{{ */ { if (EG(in_execution)) { phpdbg_error("Cannot start another execution while one is in progress"); - return FAILURE; + return SUCCESS; } if (PHPDBG_G(ops) || PHPDBG_G(exec)) { @@ -307,8 +322,9 @@ static PHPDBG_COMMAND(run) /* {{{ */ if (!PHPDBG_G(ops)) { if (phpdbg_compile(TSRMLS_C) == FAILURE) { - phpdbg_error("Failed to compile %s, cannot run", PHPDBG_G(exec)); - return FAILURE; + phpdbg_error( + "Failed to compile %s, cannot run", PHPDBG_G(exec)); + goto out; } } @@ -328,55 +344,51 @@ static PHPDBG_COMMAND(run) /* {{{ */ if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { phpdbg_error("Caught excetion in VM"); - return FAILURE; - } else return SUCCESS; + goto out; + } } zend_end_try(); EG(active_op_array) = orig_op_array; EG(opline_ptr) = orig_opline; EG(return_value_ptr_ptr) = orig_retval_ptr; - return SUCCESS; } else { phpdbg_error("Nothing to execute!"); - return FAILURE; } + +out: + return SUCCESS; } /* }}} */ static PHPDBG_COMMAND(eval) /* {{{ */ { - if (param->type == EMPTY_PARAM) { - phpdbg_error("No expression provided!"); - return FAILURE; - } else { - if (param->type == STR_PARAM) { - zend_bool stepping = (PHPDBG_G(flags) & PHPDBG_IS_STEPPING); - zval retval; + switch (param->type) { + case STR_PARAM: { + zend_bool stepping = (PHPDBG_G(flags) & PHPDBG_IS_STEPPING); + zval retval; - PHPDBG_G(flags) &= ~ PHPDBG_IS_STEPPING; + PHPDBG_G(flags) &= ~ PHPDBG_IS_STEPPING; - /* disable stepping while eval() in progress */ - PHPDBG_G(flags) |= PHPDBG_IN_EVAL; - if (zend_eval_stringl(param->str, param->len, - &retval, "eval()'d code" TSRMLS_CC) == SUCCESS) { - zend_print_zval_r( - &retval, 0 TSRMLS_CC); - phpdbg_writeln(EMPTY); - zval_dtor(&retval); - } - PHPDBG_G(flags) &= ~PHPDBG_IN_EVAL; + /* disable stepping while eval() in progress */ + PHPDBG_G(flags) |= PHPDBG_IN_EVAL; + if (zend_eval_stringl(param->str, param->len, + &retval, "eval()'d code" TSRMLS_CC) == SUCCESS) { + zend_print_zval_r( + &retval, 0 TSRMLS_CC); + phpdbg_writeln(EMPTY); + zval_dtor(&retval); + } + PHPDBG_G(flags) &= ~PHPDBG_IN_EVAL; + + /* switch stepping back on */ + if (stepping) { + PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; + } + } break; + + phpdbg_default_switch_case(); + } - /* switch stepping back on */ - if (stepping) { - PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; - } - } else { - phpdbg_error( - "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); - return FAILURE; - } - } - return SUCCESS; } /* }}} */ @@ -384,7 +396,7 @@ static PHPDBG_COMMAND(back) /* {{{ */ { if (!EG(in_execution)) { phpdbg_error("Not executing!"); - return FAILURE; + return SUCCESS; } switch (param->type) { @@ -393,9 +405,9 @@ static PHPDBG_COMMAND(back) /* {{{ */ zval zbacktrace; zval **tmp; HashPosition position; - int i = 0, + int i = 0, limit = (param->type == NUMERIC_PARAM) ? param->num : 0; - + zend_fetch_debug_backtrace( &zbacktrace, 0, 0, limit TSRMLS_CC); @@ -410,63 +422,61 @@ static PHPDBG_COMMAND(back) /* {{{ */ phpdbg_writeln(EMPTY); zval_dtor(&zbacktrace); - - return SUCCESS; } break; - - default: { - phpdbg_error( - "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); - return FAILURE; - } + + phpdbg_default_switch_case(); } + + return SUCCESS; } /* }}} */ static PHPDBG_COMMAND(print) /* {{{ */ { - if (param->type == EMPTY_PARAM) { - phpdbg_writeln(SEPARATE); - phpdbg_notice("Execution Context Information"); + switch (param->type) { + case EMPTY_PARAM: { + phpdbg_writeln(SEPARATE); + phpdbg_notice("Execution Context Information"); #ifdef HAVE_LIBREADLINE - phpdbg_writeln("Readline\tyes"); + phpdbg_writeln("Readline\tyes"); #else - phpdbg_writeln("Readline\tno"); + phpdbg_writeln("Readline\tno"); #endif - phpdbg_writeln("Exec\t\t%s", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none"); - phpdbg_writeln("Compiled\t%s", PHPDBG_G(ops) ? "yes" : "no"); - phpdbg_writeln("Stepping\t%s", (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off"); - phpdbg_writeln("Quietness\t%s", (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "on" : "off"); - phpdbg_writeln("Oplog\t\t%s", PHPDBG_G(oplog) ? "on" : "off"); + phpdbg_writeln("Exec\t\t%s", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none"); + phpdbg_writeln("Compiled\t%s", PHPDBG_G(ops) ? "yes" : "no"); + phpdbg_writeln("Stepping\t%s", (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off"); + phpdbg_writeln("Quietness\t%s", (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "on" : "off"); + phpdbg_writeln("Oplog\t\t%s", PHPDBG_G(oplog) ? "on" : "off"); - if (PHPDBG_G(ops)) { - phpdbg_writeln("Opcodes\t\t%d", PHPDBG_G(ops)->last); + if (PHPDBG_G(ops)) { + phpdbg_writeln("Opcodes\t\t%d", PHPDBG_G(ops)->last); - if (PHPDBG_G(ops)->last_var) { - phpdbg_writeln("Variables\t%d", PHPDBG_G(ops)->last_var-1); - } else { - phpdbg_writeln("Variables\tNone"); - } - } + if (PHPDBG_G(ops)->last_var) { + phpdbg_writeln("Variables\t%d", PHPDBG_G(ops)->last_var-1); + } else { + phpdbg_writeln("Variables\tNone"); + } + } - phpdbg_writeln("Executing\t%s", EG(in_execution) ? "yes" : "no"); - if (EG(in_execution)) { - phpdbg_writeln("VM Return\t%d", PHPDBG_G(vmret)); - } - phpdbg_writeln("Classes\t\t%d", zend_hash_num_elements(EG(class_table))); - phpdbg_writeln("Functions\t%d", zend_hash_num_elements(EG(function_table))); - phpdbg_writeln("Constants\t%d", zend_hash_num_elements(EG(zend_constants))); - phpdbg_writeln("Included\t%d", zend_hash_num_elements(&EG(included_files))); + phpdbg_writeln("Executing\t%s", EG(in_execution) ? "yes" : "no"); + if (EG(in_execution)) { + phpdbg_writeln("VM Return\t%d", PHPDBG_G(vmret)); + } + phpdbg_writeln("Classes\t\t%d", zend_hash_num_elements(EG(class_table))); + phpdbg_writeln("Functions\t%d", zend_hash_num_elements(EG(function_table))); + phpdbg_writeln("Constants\t%d", zend_hash_num_elements(EG(zend_constants))); + phpdbg_writeln("Included\t%d", zend_hash_num_elements(&EG(included_files))); - phpdbg_print_breakpoints(PHPDBG_BREAK_FILE TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_SYM TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_COND TSRMLS_CC); - - phpdbg_writeln(SEPARATE); - } else { - phpdbg_error("You must use a specific printer"); + phpdbg_print_breakpoints(PHPDBG_BREAK_FILE TSRMLS_CC); + phpdbg_print_breakpoints(PHPDBG_BREAK_SYM TSRMLS_CC); + phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD TSRMLS_CC); + phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE TSRMLS_CC); + phpdbg_print_breakpoints(PHPDBG_BREAK_COND TSRMLS_CC); + + phpdbg_writeln(SEPARATE); + } break; + + phpdbg_default_switch_case(); } return SUCCESS; @@ -490,11 +500,8 @@ static PHPDBG_COMMAND(break) /* {{{ */ case STR_PARAM: phpdbg_set_breakpoint_symbol(param->str TSRMLS_CC); break; - - default: - phpdbg_error( - "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); - return FAILURE; + + phpdbg_default_switch_case(); } return SUCCESS; @@ -516,7 +523,7 @@ static PHPDBG_COMMAND(clean) /* {{{ */ { if (EG(in_execution)) { phpdbg_error("Cannot clean environment while executing"); - return FAILURE; + return SUCCESS; } phpdbg_notice("Cleaning Execution Environment"); @@ -571,130 +578,149 @@ static PHPDBG_COMMAND(aliases) /* {{{ */ prompt_command->name, prompt_command->tip); } } - + ++prompt_command; } phpdbg_help_footer(); - + return SUCCESS; } /* }}} */ static PHPDBG_COMMAND(oplog) /* {{{ */ { - if (param->type == EMPTY_PARAM || - ((param->type == NUMERIC_PARAM) && !param->num)) { - if (PHPDBG_G(oplog)) { - phpdbg_notice("Disabling oplog"); - fclose( - PHPDBG_G(oplog)); - return SUCCESS; - } else { - phpdbg_error("No oplog currently open"); - return FAILURE; - } - } else { - if (param->type == STR_PARAM) { - /* open oplog */ + switch (param->type) { + case EMPTY_PARAM: + case NUMERIC_PARAM: + if ((param->type != NUMERIC_PARAM) || !param->num) { + if (PHPDBG_G(oplog)) { + phpdbg_notice("Disabling oplog"); + fclose( + PHPDBG_G(oplog)); + } else { + phpdbg_error("No oplog currently open"); + } + } + break; + + case STR_PARAM: { + /* open oplog */ FILE *old = PHPDBG_G(oplog); PHPDBG_G(oplog) = fopen(param->str, "w+"); if (!PHPDBG_G(oplog)) { phpdbg_error("Failed to open %s for oplog", param->str); PHPDBG_G(oplog) = old; - return FAILURE; } else { if (old) { phpdbg_notice("Closing previously open oplog"); fclose(old); } phpdbg_notice("Successfully opened oplog %s", param->str); - - return SUCCESS; } - } else { - phpdbg_error( - "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); - return FAILURE; - } + } break; + + phpdbg_default_switch_case(); } + + return SUCCESS; } /* }}} */ static PHPDBG_COMMAND(help) /* {{{ */ { - if (param->type == EMPTY_PARAM) { - const phpdbg_command_t *prompt_command = phpdbg_prompt_commands; - const phpdbg_command_t *help_command = phpdbg_help_commands; - - phpdbg_help_header(); - phpdbg_writeln("To get help regarding a specific command type \"help command\""); + switch (param->type) { + case EMPTY_PARAM: { + const phpdbg_command_t *prompt_command = phpdbg_prompt_commands; + const phpdbg_command_t *help_command = phpdbg_help_commands; - phpdbg_notice("Commands"); + phpdbg_help_header(); + phpdbg_writeln("To get help regarding a specific command type \"help command\""); - while (prompt_command && prompt_command->name) { - phpdbg_writeln( - "\t%s\t%s", prompt_command->name, prompt_command->tip); - ++prompt_command; - } + phpdbg_notice("Commands"); - phpdbg_notice("Helpers Loaded"); + while (prompt_command && prompt_command->name) { + phpdbg_writeln( + "\t%s\t%s", prompt_command->name, prompt_command->tip); + ++prompt_command; + } - while (help_command && help_command->name) { - phpdbg_writeln("\t%s\t%s", help_command->name, help_command->tip); - ++help_command; - } + phpdbg_notice("Helpers Loaded"); - phpdbg_notice("Command Line Options and Flags"); - phpdbg_writeln("\tOption\tExample\t\t\tPurpose"); - phpdbg_writeln(EMPTY); - phpdbg_writeln("\t-c\t-c/my/php.ini\t\tSet php.ini file to load"); - phpdbg_writeln("\t-d\t-dmemory_limit=4G\tSet a php.ini directive"); - phpdbg_writeln("\t-n\t-N/A\t\t\tDisable default php.ini"); - phpdbg_writeln("\t-e\t-emytest.php\t\tSet execution context"); - phpdbg_writeln("\t-v\tN/A\t\t\tEnable opline output while executing"); - phpdbg_writeln("\t-s\tN/A\t\t\tEnable stepping"); - phpdbg_writeln("\t-b\tN/A\t\t\tDisable the use of colours"); - phpdbg_writeln("\t-i\t-imy.init\t\tSet the phpdbginit file"); - phpdbg_writeln("\t-I\tN/A\t\t\tDisable loading .phpdbginit"); - phpdbg_writeln("\t-O\t-Omy.oplog\t\tSets oplog output file"); - phpdbg_help_footer(); - } else { - phpdbg_error( - "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); - return FAILURE; - } + while (help_command && help_command->name) { + phpdbg_writeln("\t%s\t%s", help_command->name, help_command->tip); + ++help_command; + } + + phpdbg_notice("Command Line Options and Flags"); + phpdbg_writeln("\tOption\tExample\t\t\tPurpose"); + phpdbg_writeln(EMPTY); + phpdbg_writeln("\t-c\t-c/my/php.ini\t\tSet php.ini file to load"); + phpdbg_writeln("\t-d\t-dmemory_limit=4G\tSet a php.ini directive"); + phpdbg_writeln("\t-n\t-N/A\t\t\tDisable default php.ini"); + phpdbg_writeln("\t-e\t-emytest.php\t\tSet execution context"); + phpdbg_writeln("\t-v\tN/A\t\t\tEnable opline output while executing"); + phpdbg_writeln("\t-s\tN/A\t\t\tEnable stepping"); + phpdbg_writeln("\t-b\tN/A\t\t\tDisable the use of colours"); + phpdbg_writeln("\t-i\t-imy.init\t\tSet the phpdbginit file"); + phpdbg_writeln("\t-I\tN/A\t\t\tDisable loading .phpdbginit"); + phpdbg_writeln("\t-O\t-Omy.oplog\t\tSets oplog output file"); + phpdbg_help_footer(); + } break; + + phpdbg_default_switch_case(); + } return SUCCESS; } /* }}} */ -static PHPDBG_COMMAND(quiet) { /* {{{ */ - if (param->type == NUMERIC_PARAM) { - if (param->num) { - PHPDBG_G(flags) |= PHPDBG_IS_QUIET; - } else { - PHPDBG_G(flags) &= ~PHPDBG_IS_QUIET; - } - phpdbg_notice("Quietness %s", - (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "enabled" : "disabled"); - } else { - phpdbg_error( - "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); - return FAILURE; +static PHPDBG_COMMAND(quiet) /* {{{ */ +{ + switch (param->type) { + case NUMERIC_PARAM: { + if (param->num) { + PHPDBG_G(flags) |= PHPDBG_IS_QUIET; + } else { + PHPDBG_G(flags) &= ~PHPDBG_IS_QUIET; + } + phpdbg_notice("Quietness %s", + (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "enabled" : "disabled"); + } break; + + phpdbg_default_switch_case(); } - + return SUCCESS; } /* }}} */ static PHPDBG_COMMAND(list) /* {{{ */ { - phpdbg_list_dispatch(param TSRMLS_CC); + switch (param->type) { + case NUMERIC_PARAM: + case EMPTY_PARAM: + return PHPDBG_LIST_HANDLER(lines)(param TSRMLS_CC); + + case FILE_PARAM: + return PHPDBG_LIST_HANDLER(lines)(param TSRMLS_CC); + + case STR_PARAM: + phpdbg_list_function_byname(param->str, param->len TSRMLS_CC); + break; + + case METHOD_PARAM: + return PHPDBG_LIST_HANDLER(method)(param TSRMLS_CC); + break; + + phpdbg_default_switch_case(); + } return SUCCESS; } /* }}} */ -int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_len TSRMLS_DC) /* {{{ */ +int phpdbg_do_cmd( const phpdbg_command_t *command, + phpdbg_command_t **selected, + char *cmd_line, size_t cmd_len TSRMLS_DC) /* {{{ */ { int rc = FAILURE; - + char *expr = NULL; #ifndef _WIN32 const char *cmd = strtok_r(cmd_line, " ", &expr); @@ -703,12 +729,14 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_le #endif size_t expr_len = (cmd != NULL) ? strlen(cmd) : 0; + phpdbg_param_t *param = NULL; + while (command && command->name && command->handler) { if ((command->name_len == expr_len && memcmp(cmd, command->name, expr_len) == 0) || ((expr_len == 1) && (command->alias && command->alias == cmd_line[0]))) { - phpdbg_param_t *param = emalloc(sizeof(phpdbg_param_t)); + param = emalloc(sizeof(phpdbg_param_t)); PHPDBG_G(last) = (phpdbg_command_t*) command; @@ -716,31 +744,41 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_le if (PHPDBG_G(lparam)) { //phpdbg_clear_param( // PHPDBG_G(lparam) TSRMLS_CC); - //efree(PHPDBG_G(lparam)); + //efree(PHPDBG_G(lparam)); } - + phpdbg_parse_param( expr, - (cmd_len - expr_len) ? (((cmd_len - expr_len) - sizeof(" "))+1) : 0, + (cmd_len - expr_len) ? (((cmd_len - expr_len) - sizeof(" "))+1) : 0, param TSRMLS_CC); PHPDBG_G(lparam) = param; if (command->subs && (param->type == STR_PARAM)) { - if (phpdbg_do_cmd(command->subs, param->str, param->len TSRMLS_CC) == SUCCESS) { + if (phpdbg_do_cmd(command->subs, selected, param->str, param->len TSRMLS_CC) == SUCCESS) { rc = SUCCESS; - break; + /* because we can */ + phpdbg_clear_param(param TSRMLS_CC); + efree(param); + goto done; } } - phpdbg_debug("phpdbg_do_cmd(%s, \"%s\")", - command->name, phpdbg_get_param_type(param TSRMLS_CC)); + *selected = (phpdbg_command_t*) command; rc = command->handler(param TSRMLS_CC); - break; - } - ++command; - } + + break; + } + ++command; + } + +done: + if (selected && param) { + phpdbg_debug( + "phpdbg_do_cmd(%s, \"%s\"): %d", + command->name, phpdbg_get_param_type(param TSRMLS_CC), (rc==SUCCESS)); + } return rc; } /* }}} */ @@ -773,11 +811,14 @@ int phpdbg_interactive(TSRMLS_D) /* {{{ */ cmd[cmd_len] = '\0'; if (*cmd && cmd_len > 0L) { + /* keep a cursor to selected command */ + phpdbg_command_t *selected = NULL; + #ifdef HAVE_LIBREADLINE add_history(cmd); #endif - switch (ret = phpdbg_do_cmd(phpdbg_prompt_commands, cmd, cmd_len TSRMLS_CC)) { + switch (ret = phpdbg_do_cmd(phpdbg_prompt_commands, &selected, cmd, cmd_len TSRMLS_CC)) { case FAILURE: if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { phpdbg_error("Failed to execute %s!", cmd); @@ -966,7 +1007,8 @@ zend_vm_enter: #define DO_INTERACTIVE() do {\ phpdbg_list_file(\ zend_get_executed_filename(TSRMLS_C), \ - 2, \ + 3, \ + zend_get_executed_lineno(TSRMLS_C)-1, \ zend_get_executed_lineno(TSRMLS_C) \ TSRMLS_CC\ );\ diff --git a/phpdbg_prompt.h b/phpdbg_prompt.h index 3781d833175..f3839d03150 100644 --- a/phpdbg_prompt.h +++ b/phpdbg_prompt.h @@ -33,7 +33,7 @@ /** * Command Executor */ -int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_len TSRMLS_DC); +int phpdbg_do_cmd(const phpdbg_command_t *command, phpdbg_command_t **selected, char *cmd_line, size_t cmd_len TSRMLS_DC); /** * Command Declarators @@ -51,6 +51,7 @@ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TS void phpdbg_welcome(zend_bool cleaning TSRMLS_DC); int phpdbg_interactive(TSRMLS_D); void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags TSRMLS_DC); +int phpdbg_compile(TSRMLS_D); void phpdbg_clean(zend_bool full TSRMLS_DC); #if PHP_VERSION_ID >= 50500 @@ -59,4 +60,11 @@ void phpdbg_execute_ex(zend_execute_data *execute_data TSRMLS_DC); void phpdbg_execute_ex(zend_op_array *op_array TSRMLS_DC); #endif +#define phpdbg_default_switch_case() \ + default:\ + phpdbg_error(\ + "Unsupported parameter type (%s) for command", \ + phpdbg_get_param_type(param TSRMLS_CC)); \ + break + #endif /* PHPDBG_PROMPT_H */