From 5a0422d8c6415692a0de5a8678063076259c7bfe Mon Sep 17 00:00:00 2001 From: krakjoe Date: Sat, 16 Nov 2013 20:57:10 +0000 Subject: [PATCH] establish relationship between parent and child commands extend alias help automatically invoke child commands --- Changelog.md | 3 + phpdbg.h | 1 + phpdbg_break.h | 4 +- phpdbg_help.c | 33 +++++++++- phpdbg_help.h | 39 +++++++----- phpdbg_list.h | 4 +- phpdbg_print.h | 2 +- phpdbg_prompt.c | 161 ++++++++++++++++++++++++------------------------ phpdbg_prompt.h | 6 +- 9 files changed, 148 insertions(+), 105 deletions(-) diff --git a/Changelog.md b/Changelog.md index 40da6884ee..43753383d2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,9 @@ Version 0.0.2 0000-00-00 ------------------------ 1. Added until/u command +2. Added printers for class and method +3. Make uniform commands and aliases where possible +4. Include all alias information and sub-command information in help Version 0.0.1 2013-11-15 diff --git a/phpdbg.h b/phpdbg.h index 2d82db35cf..e38f478a82 100644 --- a/phpdbg.h +++ b/phpdbg.h @@ -132,6 +132,7 @@ struct _phpdbg_command_t { size_t tip_len; /* Menu tip length */ char alias; /* Alias */ phpdbg_command_handler_t handler; /* Command handler */ + const phpdbg_command_t *subs; /* Sub Commands */ }; ZEND_BEGIN_MODULE_GLOBALS(phpdbg) diff --git a/phpdbg_break.h b/phpdbg_break.h index cb29b7a0d6..13addb0cdf 100644 --- a/phpdbg_break.h +++ b/phpdbg_break.h @@ -26,9 +26,9 @@ * Command Declarators */ #define PHPDBG_BREAK_D(name, tip) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, 0, phpdbg_do_break_##name} + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, 0, phpdbg_do_break_##name, NULL} #define PHPDBG_BREAK_EX_D(name, tip, alias) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_break_##name} + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_break_##name, NULL} #define PHPDBG_BREAK(name) \ int phpdbg_do_break_##name(phpdbg_param_t *param TSRMLS_DC) diff --git a/phpdbg_help.c b/phpdbg_help.c index 16cefeb96a..e7de30af93 100644 --- a/phpdbg_help.c +++ b/phpdbg_help.c @@ -28,13 +28,16 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); PHPDBG_HELP(exec) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("Will attempt execution, if compilation has not yet taken place, it occurs now"); phpdbg_writeln("The execution context must be set before execution can take place"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(step) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("You can enable and disable stepping at any phpdbg prompt during execution"); phpdbg_writeln(EMPTY); phpdbg_writeln("Examples:"); @@ -42,33 +45,41 @@ PHPDBG_HELP(step) /* {{{ */ phpdbg_writeln("Will enable stepping"); phpdbg_writeln(EMPTY); phpdbg_writeln("While stepping is enabled you are presented with a prompt after the execution of each opcode"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(next) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("While stepping through execution, or after a breakpoint, use the next command to step back into the vm and execute the next opcode"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(until) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("While stepping through execution, or after a breakpoint, use the until command to step back into the vm and reaches the next source line"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(compile) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("Pre-compilation of the execution context provides the opportunity to inspect the opcodes before they are executed"); phpdbg_writeln("The execution context must be set for compilation to succeed"); phpdbg_writeln("If errors occur during compilation they must be resolved before execution can take place"); phpdbg_writeln("It is a good idea to clean the environment between each compilation with the clean command"); phpdbg_writeln("You do not need to exit phpdbg to retry compilation"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(print) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("By default, print will show information about the current execution environment"); phpdbg_writeln("Other printing commands give access to address, file and line information"); phpdbg_writeln(EMPTY); @@ -97,25 +108,31 @@ PHPDBG_HELP(print) /* {{{ */ ++print_command; } } + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(run) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("Run the code inside the debug vm, you should have break points and variables set before running"); phpdbg_writeln("The execution context must not be set, but not necessarily compiled before execution occurs"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(eval) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("Access to eval() allows you to change the environment during execution, careful though !!"); phpdbg_writeln("Note: When using eval in phpdbg do not prefix the code with return"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(break) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("Setting a breakpoint stops execution at a specific stage"); phpdbg_writeln(EMPTY); phpdbg_writeln("Examples:"); @@ -150,26 +167,31 @@ PHPDBG_HELP(break) /* {{{ */ } } phpdbg_writeln("Conditional breaks are costly, use them sparingly !!"); - + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(clean) /* {{{ */ -{ +{ + phpdbg_help_header(); phpdbg_writeln("While debugging you may experience errors because of attempts to redeclare classes, constants or functions"); phpdbg_writeln("Cleaning the environment cleans these tables, so that files can be recompiled without exiting phpdbg"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(clear) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("Clearing breakpoints means you can once again run code without interruption"); phpdbg_writeln("Careful though, all breakpoints are lost; be sure debugging is complete before clearing"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(quiet) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("Setting quietness on will stop the OPLINE output during execution"); phpdbg_writeln(EMPTY); phpdbg_writeln("Examples:"); @@ -179,22 +201,26 @@ PHPDBG_HELP(quiet) /* {{{ */ phpdbg_writeln("Will enable OPLINE output again"); phpdbg_writeln(EMPTY); phpdbg_writeln("Quietness is disabled while stepping through execution automatically"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(back) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("The backtrace is gathered with the default debug_backtrace functionality"); phpdbg_writeln(EMPTY); phpdbg_writeln("Examples:"); phpdbg_writeln("You can set the limit on the trace"); phpdbg_writeln("\t%sback 5", PROMPT); phpdbg_writeln("Will limit the number of frames to 5, the default is no limit"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(list) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("The list command displays source code for the given argument"); phpdbg_writeln(EMPTY); phpdbg_writeln("Examples:"); @@ -225,11 +251,13 @@ PHPDBG_HELP(list) /* {{{ */ ++list_command; } } + phpdbg_help_footer(); return SUCCESS; } /* }}} */ PHPDBG_HELP(oplog) /* {{{ */ { + phpdbg_help_header(); phpdbg_writeln("Even when quietness is enabled you may wish to save opline logs to a file"); phpdbg_writeln("Setting a new oplog closes the previously open log"); phpdbg_writeln("The log includes a high resolution timestamp on each entry"); @@ -242,5 +270,6 @@ PHPDBG_HELP(oplog) /* {{{ */ phpdbg_writeln("Will close the currently open log file, disabling oplog"); phpdbg_writeln(EMPTY); phpdbg_writeln("Note: upon failure to open a new oplog, the last oplog is held open"); + phpdbg_help_footer(); return SUCCESS; } /* }}} */ diff --git a/phpdbg_help.h b/phpdbg_help.h index 1e39420324..363acf6f56 100644 --- a/phpdbg_help.h +++ b/phpdbg_help.h @@ -26,8 +26,8 @@ /** * Command Declarators */ -#define PHPDBG_HELP_D(name, tip) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, 0, phpdbg_do_help_##name} +#define PHPDBG_HELP_D(name, tip, alias) \ + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_help_##name, NULL} #define PHPDBG_HELP(name) \ int phpdbg_do_help_##name(phpdbg_param_t *param TSRMLS_DC) @@ -54,22 +54,27 @@ PHPDBG_HELP(oplog); * Commands */ static const phpdbg_command_t phpdbg_help_commands[] = { - PHPDBG_HELP_D(exec, "the execution context should be a valid path"), - PHPDBG_HELP_D(compile, "pre-compilation allows inspection of code before execution"), - PHPDBG_HELP_D(step, "stepping through execution allows inspection of the opline as it is executed"), - PHPDBG_HELP_D(next, "continue executing while stepping or after breaking"), - PHPDBG_HELP_D(run, "execution inside the phpdbg vm allows detailed inspection and debugging"), - PHPDBG_HELP_D(eval, "access to eval() allows you to affect the environment during execution"), - PHPDBG_HELP_D(until, "continue until the program reaches a source line different than the current one"), - PHPDBG_HELP_D(print, "printing allows inspection of the execution environment"), - PHPDBG_HELP_D(break, "breakpoints allow execution interruption"), - PHPDBG_HELP_D(clean, "resetting the environment is useful while debugging and recompiling"), - PHPDBG_HELP_D(clear, "clearing breakpoints allows you to run code without interruption"), - PHPDBG_HELP_D(back, "show debug backtrace information during execution"), - PHPDBG_HELP_D(quiet, "be quiet during execution"), - PHPDBG_HELP_D(list, "listing code gives you quick access to code while executing"), - PHPDBG_HELP_D(oplog, "keep clutter off the screen by sending oplogs to a file"), + PHPDBG_HELP_D(exec, "the execution context should be a valid path", 'e'), + PHPDBG_HELP_D(compile, "pre-compilation allows inspection of code before execution", 'c'), + PHPDBG_HELP_D(step, "stepping through execution allows inspection of the opline as it is executed", 's'), + PHPDBG_HELP_D(next, "continue executing while stepping or after breaking", 'n'), + PHPDBG_HELP_D(run, "execution inside the phpdbg vm allows detailed inspection and debugging", 'r'), + PHPDBG_HELP_D(eval, "access to eval() allows you to affect the environment during execution", 'E'), + PHPDBG_HELP_D(until, "continue until the program reaches a source line different than the current one", 'u'), + PHPDBG_HELP_D(print, "printing allows inspection of the execution environment", 'p'), + PHPDBG_HELP_D(break, "breakpoints allow execution interruption", 'b'), + PHPDBG_HELP_D(clean, "resetting the environment is useful while debugging and recompiling", 'X'), + PHPDBG_HELP_D(clear, "clearing breakpoints allows you to run code without interruption", 'c'), + PHPDBG_HELP_D(back, "show debug backtrace information during execution", 't'), + PHPDBG_HELP_D(quiet, "be quiet during execution", 's'), + PHPDBG_HELP_D(list, "listing code gives you quick access to code while executing", 'l'), + PHPDBG_HELP_D(oplog, "keep clutter off the screen by sending oplogs to a file", 'O'), {NULL, 0, 0} }; +#define phpdbg_help_header() \ + phpdbg_notice("Welcome to phpdbg, the interactive PHP debugger, v%s", PHPDBG_VERSION); +#define phpdbg_help_footer() \ + phpdbg_notice("Please report bugs to <%s>", PHPDBG_ISSUES); + #endif /* PHPDBG_HELP_H */ diff --git a/phpdbg_list.h b/phpdbg_list.h index 53113aab30..66d0e70bae 100644 --- a/phpdbg_list.h +++ b/phpdbg_list.h @@ -28,9 +28,9 @@ * Command Declarators */ #define PHPDBG_LIST_D(name, tip) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, 0, phpdbg_do_list_##name} + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, 0, phpdbg_do_list_##name, NULL} #define PHPDBG_LIST_EX_D(name, tip, alias) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_list_##name} + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_list_##name, NULL} #define PHPDBG_LIST(name) \ int phpdbg_do_list_##name(phpdbg_param_t *param TSRMLS_DC) diff --git a/phpdbg_print.h b/phpdbg_print.h index 9cffbe64b5..01bc27fa43 100644 --- a/phpdbg_print.h +++ b/phpdbg_print.h @@ -27,7 +27,7 @@ * Command Declarators */ #define PHPDBG_PRINT_D(name, tip, alias) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_print_##name} + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_print_##name, NULL} #define PHPDBG_PRINT(name) \ int phpdbg_do_print_##name(phpdbg_param_t *param TSRMLS_DC) diff --git a/phpdbg_prompt.c b/phpdbg_prompt.c index 9e6d73f622..91cc881d60 100644 --- a/phpdbg_prompt.c +++ b/phpdbg_prompt.c @@ -59,13 +59,13 @@ static const phpdbg_command_t phpdbg_prompt_commands[] = { PHPDBG_COMMAND_EX_D(run, "attempt execution", 'r'), PHPDBG_COMMAND_EX_D(eval, "evaluate some code", 'E'), PHPDBG_COMMAND_EX_D(until, "continue until reaches next line", 'u'), - PHPDBG_COMMAND_EX_D(print, "print something", 'p'), - PHPDBG_COMMAND_EX_D(break, "set breakpoint", 'b'), + PHPDBG_COMMANDS_D(print, "print something", 'p', phpdbg_print_commands), + PHPDBG_COMMANDS_D(break, "set breakpoint", 'b', phpdbg_break_commands), PHPDBG_COMMAND_EX_D(back, "show trace", 't'), - PHPDBG_COMMAND_EX_D(list, "list specified line or function", 'l'), + PHPDBG_COMMANDS_D(list, "lists some code", 'l', phpdbg_list_commands), PHPDBG_COMMAND_EX_D(clean, "clean the execution environment", 'X'), PHPDBG_COMMAND_EX_D(clear, "clear breakpoints", 'C'), - PHPDBG_COMMAND_EX_D(help, "show help menu", 'h'), + PHPDBG_COMMANDS_D(help, "show help menu", 'h', phpdbg_help_commands), PHPDBG_COMMAND_EX_D(quiet, "silence some output", 'Q'), PHPDBG_COMMAND_EX_D(aliases, "show alias list", 'a'), PHPDBG_COMMAND_EX_D(oplog, "sets oplog output", 'O'), @@ -382,33 +382,44 @@ static PHPDBG_COMMAND(eval) /* {{{ */ static PHPDBG_COMMAND(back) /* {{{ */ { - zval zbacktrace; - zval **tmp; - HashPosition position; - int i = 0, limit = 0; - - if (!EG(in_execution)) { - phpdbg_error("Not executing!"); - return FAILURE; - } - - limit = (param->type == NUMERIC_PARAM) ? param->num : 0; - - zend_fetch_debug_backtrace(&zbacktrace, 0, 0, limit TSRMLS_CC); - - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position); - zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), (void**)&tmp, &position) == SUCCESS; - zend_hash_move_forward_ex(Z_ARRVAL(zbacktrace), &position)) { - if (i++) { - phpdbg_writeln(","); - } - zend_print_flat_zval_r(*tmp TSRMLS_CC); - } + if (!EG(in_execution)) { + phpdbg_error("Not executing!"); + return FAILURE; + } - phpdbg_writeln(EMPTY); - zval_dtor(&zbacktrace); + switch (param->type) { + case EMPTY_PARAM: + case NUMERIC_PARAM: { + zval zbacktrace; + zval **tmp; + HashPosition position; + int i = 0, + limit = (param->type == NUMERIC_PARAM) ? param->num : 0; + + zend_fetch_debug_backtrace( + &zbacktrace, 0, 0, limit TSRMLS_CC); + + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position); + zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), (void**)&tmp, &position) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL(zbacktrace), &position)) { + if (i++) { + phpdbg_writeln(","); + } + zend_print_flat_zval_r(*tmp TSRMLS_CC); + } - return SUCCESS; + 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; + } + } } /* }}} */ static PHPDBG_COMMAND(print) /* {{{ */ @@ -455,14 +466,7 @@ static PHPDBG_COMMAND(print) /* {{{ */ phpdbg_writeln(SEPARATE); } else { - if (param->type == STR_PARAM) { - if (phpdbg_do_cmd(phpdbg_print_commands, param->str, param->len TSRMLS_CC) == FAILURE) { - phpdbg_error("Failed to find print command %s", param->str); - return FAILURE; - } - } else { - phpdbg_error("You must use a specific printer"); - } + phpdbg_error("You must use a specific printer"); } return SUCCESS; @@ -470,17 +474,6 @@ static PHPDBG_COMMAND(print) /* {{{ */ static PHPDBG_COMMAND(break) /* {{{ */ { - if (param->type == EMPTY_PARAM) { - phpdbg_error("No expression found"); - return FAILURE; - } - - /* allow advanced breakers to run */ - if (param->type == STR_PARAM && - phpdbg_do_cmd(phpdbg_break_commands, param->str, param->len TSRMLS_CC) == SUCCESS) { - return SUCCESS; - } - switch (param->type) { case ADDR_PARAM: phpdbg_set_breakpoint_opline(param->addr TSRMLS_CC); @@ -557,20 +550,32 @@ static PHPDBG_COMMAND(aliases) /* {{{ */ { const phpdbg_command_t *prompt_command = phpdbg_prompt_commands; - phpdbg_notice("Welcome to phpdbg, the interactive PHP debugger, v%s", - PHPDBG_VERSION); - - phpdbg_notice("Aliases"); - + phpdbg_help_header(); + phpdbg_writeln("Below are the aliased, short versions of all supported commands"); while (prompt_command && prompt_command->name) { if (prompt_command->alias) { - phpdbg_writeln("\t%c -> %s\t%s", prompt_command->alias, - prompt_command->name, prompt_command->tip); + if (prompt_command->subs) { + const phpdbg_command_t *sub_command = prompt_command->subs; + phpdbg_writeln(EMPTY); + phpdbg_writeln("\t%c -> %s", prompt_command->alias, prompt_command->name); + while (sub_command && sub_command->name) { + if (sub_command->alias) { + phpdbg_writeln("\t|------- %c -> %s\t%s", sub_command->alias, + sub_command->name, sub_command->tip); + } + ++sub_command; + } + phpdbg_writeln(EMPTY); + } else { + phpdbg_writeln("\t%c -> %s\t%s", prompt_command->alias, + prompt_command->name, prompt_command->tip); + } } + ++prompt_command; } - - phpdbg_notice("Please report bugs to <%s>", PHPDBG_ISSUES); + phpdbg_help_footer(); + return SUCCESS; } /* }}} */ @@ -616,17 +621,11 @@ static PHPDBG_COMMAND(oplog) /* {{{ */ static PHPDBG_COMMAND(help) /* {{{ */ { - phpdbg_notice("Welcome to phpdbg, the interactive PHP debugger, v%s", - PHPDBG_VERSION); - - if (param->type == STR_PARAM) { - if (phpdbg_do_cmd(phpdbg_help_commands, param->str, param->len TSRMLS_CC) == FAILURE) { - phpdbg_error("Failed to find help command: %s", param->str); - } - } else { + 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\""); phpdbg_notice("Commands"); @@ -657,10 +656,13 @@ static PHPDBG_COMMAND(help) /* {{{ */ 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; } - phpdbg_notice("Please report bugs to <%s>", PHPDBG_ISSUES); - return SUCCESS; } /* }}} */ @@ -684,12 +686,6 @@ static PHPDBG_COMMAND(quiet) { /* {{{ */ static PHPDBG_COMMAND(list) /* {{{ */ { - /* allow advanced listers to run */ - if (param->type == STR_PARAM && - phpdbg_do_cmd(phpdbg_list_commands, param->str, param->len TSRMLS_CC) == SUCCESS) { - return SUCCESS; - } - phpdbg_list_dispatch(param TSRMLS_CC); return SUCCESS; @@ -711,11 +707,11 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_le 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)); - + PHPDBG_G(last) = (phpdbg_command_t*) command; - + /* urm ... */ if (PHPDBG_G(lparam)) { //phpdbg_clear_param( @@ -724,12 +720,19 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_le } phpdbg_parse_param( - expr, + expr, (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) { + rc = SUCCESS; + break; + } + } + phpdbg_debug("phpdbg_do_cmd(%s, \"%s\")", command->name, phpdbg_get_param_type(param TSRMLS_CC)); diff --git a/phpdbg_prompt.h b/phpdbg_prompt.h index 7fe6d0dbe8..3781d83317 100644 --- a/phpdbg_prompt.h +++ b/phpdbg_prompt.h @@ -39,9 +39,11 @@ int phpdbg_do_cmd(const phpdbg_command_t *command, char *cmd_line, size_t cmd_le * Command Declarators */ #define PHPDBG_COMMAND_D(name, tip) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, 0, phpdbg_do_##name} + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, 0, phpdbg_do_##name, NULL} #define PHPDBG_COMMAND_EX_D(name, tip, alias) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##name} + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##name, NULL} +#define PHPDBG_COMMANDS_D(name, tip, alias, children) \ + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##name, children} #define PHPDBG_COMMAND(name) \ int phpdbg_do_##name(phpdbg_param_t *param TSRMLS_DC) -- 2.40.0