]> granicus.if.org Git - php/commitdiff
Work in progress chekpoint of changes to help module. To allow peer review and feedback
authorTerry Ellison <Terry@ellisons.org.uk>
Sun, 2 Feb 2014 16:35:28 +0000 (16:35 +0000)
committerTerry Ellison <Terry@ellisons.org.uk>
Sun, 2 Feb 2014 16:35:28 +0000 (16:35 +0000)
16 files changed:
phpdbg_break.c
phpdbg_break.h
phpdbg_help.c
phpdbg_help.h
phpdbg_info.c
phpdbg_info.h
phpdbg_list.c
phpdbg_list.h
phpdbg_print.c
phpdbg_print.h
phpdbg_prompt.c
phpdbg_prompt.h
phpdbg_set.c
phpdbg_set.h
phpdbg_utils.c
phpdbg_utils.h

index f56f76facd90dd0a76c6aef2bcf1387ba12960a2..67267550c542fe3b2c708d35a50c2f1b75d50faa 100644 (file)
 
 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_END_COMMAND
+};
+
 PHPDBG_BREAK(file) /* {{{ */
 {
        switch (param->type) {
index f90e351d6de2e1b467a950f9da3a27c96b11db48..38f1298c932a08fceee6f8654588b265df9f7e91 100644 (file)
@@ -39,20 +39,6 @@ PHPDBG_BREAK(on);
 PHPDBG_BREAK(lineno);
 PHPDBG_BREAK(del);
 
-/**
- * Commands
- */
-static 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_END_COMMAND
-};
+extern const phpdbg_command_t phpdbg_break_commands[];
 
 #endif /* PHPDBG_BREAK_H */
index a02cb41c1437f5e181bab05207053d5fad3d1b95..ec0af2ac79d81b19cf4d6f1e3f2648ded0ba179b 100644 (file)
    | Authors: Felipe Pena <felipe@php.net>                                |
    | Authors: Joe Watkins <joe.watkins@live.co.uk>                        |
    | Authors: Bob Weinand <bwoebi@php.net>                                |
+   | Authors: Terry Ellison <terry@ellisons.org.uk>                       |
    +----------------------------------------------------------------------+
 */
 
 #include "phpdbg.h"
 #include "phpdbg_help.h"
+#include "phpdbg_prompt.h"
 #include "phpdbg_print.h"
 #include "phpdbg_utils.h"
 #include "phpdbg_break.h"
 #include "phpdbg_list.h"
 #include "phpdbg_info.h"
 #include "phpdbg_set.h"
+#include "zend.h"
 
 ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
 
-PHPDBG_HELP(exec) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("\tWill 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_notice("Examples");
-       phpdbg_writeln("\t%sstepping 1", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%ss 1", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill 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_write("Step back into the vm and execute the next opcode");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%snext", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sn", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill cause control to be passed back to the vm, continuing execution");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: is only useful while executing");
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
+/* {{{ Commands Table */
+#define PHPDBG_COMMAND_HELP_D(name, tip, alias, action) \
+       {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, action, NULL, 0}
+
+const phpdbg_command_t phpdbg_help_commands[] = {
+       PHPDBG_COMMAND_HELP_D(aliases,    "show alias list", 'a', phpdbg_do_help_aliases),
+       PHPDBG_COMMAND_HELP_D(options,    "command line options", 0, NULL),
+       PHPDBG_COMMAND_HELP_D(overview,   "help overview", 0, NULL),
+       PHPDBG_COMMAND_HELP_D(phpdbginit, "phpdbginit file format", 0, NULL),
+       PHPDBG_COMMAND_HELP_D(syntax,     "syntax overview", 0, NULL),
+       PHPDBG_END_COMMAND
+};  /* }}} */
+
+/* {{{ pretty_format.  Takes a text string, expands any formatting escapes and wrap the text */
+static char *pretty_format(char *text TSRMLS_DC) {
+       char *new, *p, *q;
+
+       const char  *prompt_escape = phpdbg_get_prompt(TSRMLS_C);
+       unsigned int prompt_escape_len = strlen(prompt_escape);
+       unsigned int prompt_len = strlen(PHPDBG_G(prompt)[0]);
+
+       const char  *bold_on_escape  = PHPDBG_G(flags) & PHPDBG_IS_COLOURED ? "\033[1m" : "";
+       const char  *bold_off_escape = PHPDBG_G(flags) & PHPDBG_IS_COLOURED ? "\033[0m" : "";
+       unsigned int bold_escape_len = strlen(bold_on_escape);
+
+       unsigned int term_width = phpdbg_get_terminal_width(TSRMLS_C);
+       unsigned int size = 0;
+
+       int in_bold = 0;
+
+       char *last_new_blank = NULL;          /* position in new buffer of last blank char */
+       unsigned int last_blank_count = 0;    /* printable char offset of last blank char */
+    unsigned int line_count = 0;          /* number printable chars on current line */
+
+       /* First pass calculates a safe size for the pretty print version */
+       for (p = text; *p; p++) {
+               if ( UNEXPECTED(p[0] == '*') && p[1] == '*' ) {
+                       size += bold_escape_len - 2;
+                       p++;
+               } else if ( UNEXPECTED(p[0] == '$') && p[1] == 'P' ) {
+                       size += prompt_escape_len - 2;
+                       p++;
+               } else if ( UNEXPECTED(p[0] == '\\') ) {
+                       p++;
+               }
+       }
+       size += (p-text)+1;
+
+       new = emalloc(size);
+       /*
+        * Second pass substitutes the bold and prompt escape sequences and line wrap
+        *
+        * ** toggles bold on and off if PHPDBG_IS_COLOURED flag is set
+     * $P substitutes the prompt sequence
+     * Lines are wrapped by replacing the last blank with a CR before <term width>
+     * characters.  (This defaults to 100 if the width can't be detected).  In the
+     * pathelogical case where no blanks are found, then the wrap occurs at the 
+     * first blank.   
+     */        
+       for (p = text, q = new; *p; p++) {
+               if ( UNEXPECTED(*p == ' ') ) {
+                       last_new_blank = q;
+                       last_blank_count = line_count++;
+                       *q++ = ' ';
+               } else if ( UNEXPECTED(*p == '\n') ) {
+                       last_new_blank = NULL;
+                       *q++ = *p;
+                       last_blank_count = 0;
+                       line_count = 0;
+               } else if ( UNEXPECTED(p[0] == '*') && p[1] == '*' ) {
+                       if (bold_escape_len) {          
+                               in_bold = !in_bold;
+                               memcpy (q, in_bold ? bold_on_escape : bold_off_escape, bold_escape_len);
+                               q += bold_escape_len;
+                               /* bold on/off has zero print width so line count is unchanged */
+                       }
+                       p++;
+               } else if ( UNEXPECTED(p[0] == '$') && p[1] == 'P' ) {
+                       memcpy (q, prompt_escape, prompt_escape_len);
+                       q += prompt_escape_len;
+                       line_count += prompt_len;
+                       p++;
+               } else if ( UNEXPECTED(p[0] == '\\') ) {
+                       p++;
+                       *q++ = *p;
+                       line_count++;
+               } else {
+                       *q++ = *p;
+                       line_count++;
+               }
 
-PHPDBG_HELP(until) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("Step back into the vm, skipping breakpoints until the next source line");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%suntil", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%su", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill cause control to be passed back to the vm, continuing execution");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: is only useful while executing");
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
+               if (UNEXPECTED(line_count>=term_width) && last_new_blank) {
+                       *last_new_blank = '\n';
+                       last_new_blank = NULL;
+                       line_count -= last_blank_count;
+                       last_blank_count = 0;
+               }
+       }
+       *q++ = '\0';
 
-PHPDBG_HELP(finish) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("Step back into the vm, skipping breakpoints until past the end of the current stack");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%sfinish", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sF", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill cause control to be passed back to the vm, continuing execution");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: this allows all breakpoints that would otherwise break execution in the current scope to be skipped");
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
+       if ((q-new)>size) {
+               phpdbg_error("Output overrun of %lu bytes", ((q-new) - size)); 
+       }
+       return new;
+}  /* }}} */
 
-PHPDBG_HELP(leave) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("Step back into the vm, skipping breakpoints until the current stack is returning");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%sleave", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sL", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill cause a break when instructed to leave the current context");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: this allows inspection of the return value before it is returned");
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
+/* {{{ get_help. Retries and formats text from the phpdbg help text table */
+static char *get_help(const char * const key TSRMLS_DC) {
+       phpdbg_help_text_t *p = phpdbg_help_text;
 
-PHPDBG_HELP(compile) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("Pre-compilation of the execution context provides the opportunity to inspect opcodes before execution");
-       phpdbg_writeln("The execution context must be set for compilation to succeed");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%scompile", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sc", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill compile the current execution context, populating class/function/constant/etc tables");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: It is a good idea to clean the environment between each compilation");
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
+       /* note that phpdbg_help_text is collated in key order */
+       for( ;p->key[0]<key[0]; p++ ) {}  /* skip to matching first char */
 
-PHPDBG_HELP(print) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("By default, print will show information about the current execution context");
-       phpdbg_writeln("Other printing commands give access to instruction information");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%sprint class \\my\\class", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sp c \\my\\class", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the instructions for the methods in \\my\\class");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sprint method \\my\\class::method", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sp m \\my\\class::method", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the instructions for \\my\\class::method");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sprint func .getSomething", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sp f .getSomething", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the instructions for ::getSomething in the active scope");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sprint func my_function", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sp f my_function", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the instructions for the global function my_function");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sprint opline", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sp o", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the instruction for the current opline");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sprint exec", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sp e", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the instructions for the execution context");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sprint stack", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sp s", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the instructions for the current stack");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Specific printers loaded are show below:");
-       phpdbg_notice("Commands");
-       {
-               const phpdbg_command_t *print_command = phpdbg_print_commands;
-
-               phpdbg_writeln("\tAlias\tCommand\t\tPurpose");
-               while (print_command && print_command->name) {
-                       if (print_command->alias) {
-                               phpdbg_writeln("\t[%c]\t%s\t\t%s", print_command->alias, print_command->name, print_command->tip);
-                       } else {
-                               phpdbg_writeln("\t[ ]\t%s\t\t%s", print_command->name, print_command->tip);
-                       }
-                       ++print_command;
+       while (p->key[0]==key[0]) {
+               if (!strcmp(p->key+1, key+1)) {
+                       return p->text;
                }
+               p++;
        }
-       phpdbg_help_footer();
-       return SUCCESS;
+       return estrdup("");   /* return empty string to denote no match found */
 } /* }}} */
 
-PHPDBG_HELP(run) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("Execute the current context inside the phpdbg vm");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%srun", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sr", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill cause execution of the context, if it is set.");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: The execution context must 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(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%seval $variable", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sE $variable", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print_r($variable) on the console, if it is defined");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%seval $variable = \"Hello phpdbg :)\"", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sE $variable = \"Hello phpdbg :)\"", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill set $variable in the current scope");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: eval() will always show the result; 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_notice("Examples");
-       phpdbg_writeln("\t%sbreak [file] test.php:1", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb [F] test.php:1", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break execution on line 1 of test.php");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak [func] my_function", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb [f] my_function", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break execution on entry to my_function");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak [method] \\my\\class::method", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb [m] \\my\\class::method", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break execution on entry to \\my\\class::method");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak [address] 0x7ff68f570e08", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb [a] 0x7ff68f570e08", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break at the opline with the address provided");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak [address] my_function#1", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb [a] my_function#1", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break at the opline number 1 of the function my_function");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak [address] \\my\\class::method#2", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb [a] \\my\\class::method#2", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break at the opline number 2 of the method \\my\\class::method");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak address test.php:3", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb a test.php:3", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break at the opline number 3 of test.php");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak [lineno] 200", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb [l] 200", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break at line 200 of the currently executing file");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak on ($expression == true)", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb on ($expression == true)", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break when the condition evaluates to true");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak at phpdbg::isGreat if ($expression == true)", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break at every opcode in phpdbg::isGreat when the condition evaluates to true");
-       phpdbg_writeln("\t%sbreak at test.php:20 if ($expression == true)", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break at every opcode on line 20 of test.php when the condition evaluates to true");
-       phpdbg_write("\t");
-       phpdbg_notice("The location can be anything accepted by file, func, method, or address break commands");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak op ZEND_ADD", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb O ZEND_ADD", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill break on every occurence of the opcode provided");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%sbreak del 1", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sb d 1", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill remove the breakpoint with the given identifier");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: An address is only valid for the current compilation");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("The parameters enclosed by [] are usually optional, but help avoid ambigious commands");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Specific breakers loaded are show below:");
-       phpdbg_notice("Commands");
-       {
-               const phpdbg_command_t *break_command = phpdbg_break_commands;
-
-               phpdbg_writeln("\tAlias\tCommand\t\tPurpose");
-               while (break_command && break_command->name) {
-                       if (break_command->alias) {
-                               phpdbg_writeln("\t[%c]\t%s\t\t%s", break_command->alias, break_command->name, break_command->tip);
-                       } else {
-                               phpdbg_writeln("\t[ ]\t%s\t\t%s", break_command->name, break_command->tip);
+/* {{{ get_command.  Return one or more matching commands from a command table.
+ * Unlike the command parser, the help search is sloppy that is partial matches can occur
+ *   * Any single character key is taken as an alias and only an exact match is allowed
+ *   * Other keys are matched again the table on the first len characters.
+ *   * This means that non-unique keys can generate multiple matches
+ *   * The command summary is an emalloced string containing one line for each match
+ *   * The function only returns a command entry if a unique match occurs.
+ *
+ * The rationale here is to assist users in finding help on commands. So "h fr" will
+ * generate a summary line for "help frame" and return the frame record.  But "h cl" will
+ * generate two summary records for the "clear" and "clean" and a NULL command record. 
+ */
+#define ALIAS_FMT "Command: **%s**  Alias: **%c**  **%s**\n"
+static const phpdbg_command_t *get_command(
+                       const char *key, size_t len,            /* pointer and length of key */ 
+                       char **command_summary,                 /* address of command summary text */
+                       const phpdbg_command_t * const commands /* command table to be scanned */
+            TSRMLS_DC) {
+       const phpdbg_command_t *c, *c_found;
+       unsigned int num_matches = 0;
+       char *summary;
+
+       if (len == 1) {
+               for (c=commands; c->name; c++) {
+                       if (c->alias == key[0]) {
+                               num_matches++;
+                               if (command_summary) {
+                                       spprintf(&summary, 0, ALIAS_FMT, c->name, c->alias, c->tip);
+                               }
+                               c_found = c;    
+                               break;
                        }
-                       ++break_command;
                }
-       }
-       phpdbg_writeln("Note: 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("Note: all breakpoints are lost; be sure debugging is complete before clearing");
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
-
-PHPDBG_HELP(info) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("info commands provide quick access to various types of information about the PHP environment");
-       phpdbg_writeln("Specific info commands are show below:");
-       phpdbg_notice("Commands");
-       {
-               const phpdbg_command_t *info_command = phpdbg_info_commands;
-
-               phpdbg_writeln("\tAlias\tCommand\t\tPurpose");
-               while (info_command && info_command->name) {
-                       if (info_command->alias) {
-                               phpdbg_writeln("\t[%c]\t%s\t\t%s", info_command->alias, info_command->name, info_command->tip);
-                       } else {
-                               phpdbg_writeln("\t[ ]\t%s\t\t%s", info_command->name, info_command->tip);
+       } else {
+               for (c=commands; c->name; c++) {
+                       if (!strncmp(c->name, key, len)) {
+                               ++num_matches;
+                               c_found = c;    
+                               if (command_summary) {
+                                       if (num_matches == 1) {
+                                               spprintf(&summary, 0, ALIAS_FMT, c->name, c->alias, c->tip);
+                                       } else { /* num_matches > 1 */
+                                               /* very rare so "keep it simple" string concat of summaries */
+                                               char *tmp = summary;
+                                               spprintf(&summary, 0, "%s" ALIAS_FMT, tmp, c->name, c->alias, c->tip);  
+                                               efree(tmp);
+                                       }
+                               }
                        }
-                       ++info_command;
                }
        }
 
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
+       if (command_summary) {
+               *command_summary = (num_matches > 0) ? summary : NULL;
+       } 
+       return (num_matches == 1) ? c_found : NULL;  /* NULL return denotes no single match found */
 
-PHPDBG_HELP(quiet) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("Setting quietness on will stop the OPLINE output during execution");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%squiet 1", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sQ 1", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill silence OPLINE output, while");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%squiet 0", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sQ 0", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill enable OPLINE output again");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: Quietness is disabled automatically while stepping");
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
-
-PHPDBG_HELP(back) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("The backtrace is built with the default debug backtrace functionality");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%sback 5", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%st 5", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill limit the number of frames to 5, the default is no limit");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: it is not necessary for an exception to be thrown to show a backtrace");
-       phpdbg_help_footer();
-       return SUCCESS;
 } /* }}} */
 
-PHPDBG_HELP(frame) /* {{{ */
+PHPDBG_COMMAND(help) /* {{{ */
 {
-       phpdbg_help_header();
-       phpdbg_writeln("When viewing a backtrace, it is sometimes useful to jump to a frame in that trace");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%sframe 2", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sf 2", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill go to frame 2, temporarily affecting scope and allowing access to the variables in that frame");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: the current frame is restored when execution continues");
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
+       char *banner, *help_text, *pretty_banner, *pretty_help_text;
+       const phpdbg_command_t *cmd;
+
+       if (param->type == EMPTY_PARAM) {
+               char * help_text = pretty_format(get_help("_overview" TSRMLS_CC) TSRMLS_CC);
+               phpdbg_write("\n%s\n", help_text);
+               efree(help_text);
+               return SUCCESS;
+       }
 
-PHPDBG_HELP(list) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("The list command displays source code for the given argument");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%slist [lines] 2", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sl [l] 2", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print next 2 lines from the current file");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%slist [func] my_function", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sl [f] my_function", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the source of the global function \"my_function\"");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%slist [func] .mine", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sl [f] .mine", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the source of the method \"mine\" from the active scope");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%slist [method] my::method", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sl [m] my::method", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the source of \"my::method\"");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%slist c myClass", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sl c myClass", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill print the source of \"myClass\"");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: before listing functions you must have a populated function table, try compile!!");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("The parameters enclosed by [] are usually optional, but help avoid ambigious commands");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Specific listers loaded are show below:");
-       phpdbg_notice("Commands");
-       {
-               const phpdbg_command_t *list_command = phpdbg_list_commands;
-
-               phpdbg_writeln("\tAlias\tCommand\t\tPurpose");
-               while (list_command && list_command->name) {
-                       if (list_command->alias) {
-                               phpdbg_writeln("\t[%c]\t%s\t\t%s", list_command->alias, list_command->name, list_command->tip);
-                       } else {
-                               phpdbg_writeln("\t[ ]\t%s\t\t%s", list_command->name, list_command->tip);
+       if (param->type == STR_PARAM) {
+           cmd = get_command( param->str, param->len, &banner, phpdbg_prompt_commands TSRMLS_CC);
+
+               if (banner) {
+                       pretty_banner = pretty_format(banner TSRMLS_CC);
+                       help_text = get_help((cmd ? cmd->name : "_ZZ_duplicate") TSRMLS_CC);
+                       pretty_help_text = pretty_format(help_text TSRMLS_CC);
+                       phpdbg_write("%s\n%s\n", pretty_banner, pretty_help_text);
+                       efree(banner);
+                       efree(pretty_banner);
+                       efree(pretty_help_text);
+                       return SUCCESS;
+
+               } else if (param->type == STR_PARAM) {
+                       cmd = get_command( param->str, param->len, NULL, phpdbg_help_commands TSRMLS_CC);
+                       if (cmd) {
+                               char *name;
+                               spprintf(&name, cmd->name_len+2, "_%s", cmd->name);
+                               help_text = get_help(name TSRMLS_CC);
+                               pretty_help_text = pretty_format(help_text TSRMLS_CC);
+                               phpdbg_write("%s\n", pretty_help_text);
+                               efree(pretty_help_text);
+                               efree(name);
+                               return SUCCESS;
                        }
-                       ++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");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%soplog /path/to/my.oplog", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sO /path/to/my.oplog", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill open the file /path/to/my.oplog for writing, creating it if it does not exist");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("\t%soplog 0", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sO 0", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill 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;
+       phpdbg_error("No help can be found for the subject \"%s\"", param->str);
+       return FAILURE;
+
+
 } /* }}} */
 
-PHPDBG_HELP(set) /* {{{ */
+PHPDBG_HELP(aliases) /* {{{ */
 {
-       phpdbg_help_header();
-       phpdbg_writeln("Configure how phpdbg looks and behaves with the set command");
-       phpdbg_writeln("Specific set commands are show below:");
-       phpdbg_notice("Commands");
-       {
-               const phpdbg_command_t *set_command = phpdbg_set_commands;
-
-               phpdbg_writeln("\tAlias\tCommand\t\tPurpose");
-               while (set_command && set_command->name) {
-                       if (set_command->alias) {
-                               phpdbg_writeln("\t[%c]\t%s\t\t%s", set_command->alias, set_command->name, set_command->tip);
-                       } else {
-                               phpdbg_writeln("\t[ ]\t%s\t\t%s", set_command->name, set_command->tip);
-                       }
-                       ++set_command;
-               }
-       }
-#ifndef _WIN32
-       phpdbg_notice("Colors");
-       {
-               const phpdbg_color_t *color = phpdbg_get_colors(TSRMLS_C);
-               
-               if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) {
-                       phpdbg_writeln("\t%-20s\t\tExample", "Name");
-               } else {
-                       phpdbg_writeln("\tName");
-               }
-               
-               while (color && color->name) {
-                       if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) {
-                               phpdbg_writeln(
-                                       "\t%-20s\t\t\033[%smphpdbg rocks :)\033[0m", color->name, color->code);
-                       } else {
-                               phpdbg_writeln("\t%s", color->name);
+       const phpdbg_command_t *c, *c_sub;
+       char *help_text;
+       int len;
+
+       /* Print out aliases for all commands except help as this one comes last */
+       phpdbg_writeln("Below are the aliased, short versions of all supported commands");
+       for(c = phpdbg_prompt_commands; c->name; c++) {
+               if (c->alias && c->alias != 'h') {
+                       phpdbg_writeln(" %c     %-20s  %s", c->alias, c->name, c->tip);
+                       if (c->subs) {
+                               len = 20 - 1 - c->name_len;
+                               for(c_sub = c->subs; c_sub->alias; c_sub++) {
+                                       if (c_sub->alias) {
+                                               phpdbg_writeln(" %c %c   %s %-*s  %s", 
+                                                       c->alias, c_sub->alias, c->name, len, c_sub->name, c_sub->tip);
+                                       }
+                               }
+                               phpdbg_writeln(EMPTY);
                        }
-                       ++color;
                }
        }
-       phpdbg_writeln("The <element> for set color can be \"prompt\", \"notice\", or \"error\"");
-#endif
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
 
-PHPDBG_HELP(register) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("Register any global function for use as a command in phpdbg console");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%sregister scandir", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%sR scandir", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill register the scandir function for use in phpdbg");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: arguments passed as strings, return (if present) print_r'd on console");
-       if (zend_hash_num_elements(&PHPDBG_G(registered))) {
-               HashPosition position;
-               char *name = NULL;
-               zend_uint name_len = 0;
-
-               phpdbg_notice("Registered Functions (%d)", zend_hash_num_elements(&PHPDBG_G(registered)));
-               for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(registered), &position);
-                       zend_hash_get_current_key_ex(&PHPDBG_G(registered), &name, &name_len, NULL, 1, &position) == HASH_KEY_IS_STRING;
-                       zend_hash_move_forward_ex(&PHPDBG_G(registered), &position)) {
-                       phpdbg_writeln("|-------> %s", name);
-                       efree(name);
-               }
+       /* Print out aliases for help as this one comes last, with the added text on how aliases are used */
+    c = get_command( "h", 1, NULL, phpdbg_prompt_commands TSRMLS_CC);
+       phpdbg_writeln(" %c     %-20s  %s\n", c->alias, c->name, c->tip);
+       len = 20 - 1 - c->name_len;
+       for(c_sub = c->subs; c_sub->alias; c_sub++) {
+               if (c_sub->alias) {
+                       phpdbg_writeln(" %c %c   %s %-*s  %s", 
+                               c->alias, c_sub->alias, c->name, len, c_sub->name, c_sub->tip);
+               }
        }
+       help_text = pretty_format(get_help("_ZZ_aliases" TSRMLS_CC) TSRMLS_CC);
+       phpdbg_write("\n%s\n", help_text);
+       efree(help_text);
 
-       phpdbg_help_footer();
        return SUCCESS;
 } /* }}} */
 
-PHPDBG_HELP(source) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("Sourcing a phpdbginit during your debugging session might save some time");
-       phpdbg_writeln("The source command can also be used to export breakpoints to a phpdbginit file");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%ssource /my/init", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%s. /my/init", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill execute the phpdbginit file at /my/init");
-       phpdbg_writeln("\t%ssource export /my/init", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%s. export /my/init", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill export breakpoints to /my/init in phpdbginit file format");
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
 
-PHPDBG_HELP(shell) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("Direct access to shell commands saves having to switch windows/consoles");
-       phpdbg_writeln(EMPTY);
-       phpdbg_notice("Examples");
-       phpdbg_writeln("\t%sshell ls /usr/src/php-src", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\t%s- ls /usr/src/php-src", phpdbg_get_prompt(TSRMLS_C));
-       phpdbg_writeln("\tWill execute ls /usr/src/php-src, displaying the output in the console");
-       phpdbg_writeln(EMPTY);
-       phpdbg_writeln("Note: read only commands please!");
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
-
-PHPDBG_HELP(options) /* {{{ */
-{
-       phpdbg_help_header();
-       phpdbg_writeln("Below are the command line options supported by phpdbg");
-       phpdbg_notice("Command Line Options and Flags");
-       phpdbg_writeln(" -c\t-c/my/php.ini\t\tSet php.ini file to load");
-       phpdbg_writeln(" -d\t-dmemory_limit=4G\tSet a php.ini directive");
-       phpdbg_writeln(" -n\tN/A\t\t\tDisable default php.ini");
-       phpdbg_writeln(" -q\tN/A\t\t\tSupress welcome banner");
-       phpdbg_writeln(" -e\t-emytest.php\t\tSet execution context");
-       phpdbg_writeln(" -v\tN/A\t\t\tEnable oplog output");
-       phpdbg_writeln(" -s\tN/A\t\t\tEnable stepping");
-       phpdbg_writeln(" -b\tN/A\t\t\tDisable colour");
-       phpdbg_writeln(" -i\t-imy.init\t\tSet .phpdbginit file");
-       phpdbg_writeln(" -I\tN/A\t\t\tIgnore default .phpdbginit");
-       phpdbg_writeln(" -O\t-Omy.oplog\t\tSets oplog output file");
-       phpdbg_writeln(" -r\tN/A\t\t\tRun execution context");
-       phpdbg_writeln(" -E\tN/A\t\t\tEnable step through eval, careful!");
-       phpdbg_writeln(" -S\t-Scli\t\t\tOverride SAPI name, careful!");
-#ifndef _WIN32
-       phpdbg_writeln(" -l\t-l4000\t\t\tSetup remote console ports");
-       phpdbg_writeln(" -a\t-a192.168.0.3\t\tSetup remote console bind address");
-#endif
-       phpdbg_writeln(" -V\tN/A\t\t\tVersion number");
-       phpdbg_notice("Passing -rr will quit automatically after execution");
-#ifndef _WIN32
-       phpdbg_writeln("Remote Console Mode");
-       phpdbg_notice("For security, phpdbg will bind only to the loopback interface by default");
-       phpdbg_writeln("-a without an argument implies all; phpdbg will bind to all available interfaces.");
-       phpdbg_writeln("specify both stdin and stdout with -lstdin/stdout; by default stdout is stdin * 2.");
-       phpdbg_notice("Steps should be taken to secure this service if bound to a public interface/port");
-#endif
-       phpdbg_help_footer();
-       return SUCCESS;
-} /* }}} */
+/* {{{ Help Text Table 
+ * Contains help text entries keyed by a lowercase ascii key.
+ * Text is in ascii and enriched by a simple markup:
+ *   ** toggles bold font emphasis.
+ *   $P insert an bold phpdbg> prompt.
+ *   \  escapes the following character. Note that this is itself escaped inside string 
+ *      constants so \\\\ is required to output a single \ e.g. as in namespace names.
+ *
+ * Text will be wrapped according to the STDOUT terminal width, so paragraphs are
+ * flowed using the C stringizing and the CR definition.  Also note that entries 
+ * are collated in alphabetic order on key.
+ */ 
+#define CR "\n"
+phpdbg_help_text_t phpdbg_help_text[] = {
+{"_options",
+"Below are the command line options supported by phpdbg" CR CR
+                          /* note the extra 4 space index in because of the extra **** */
+"**Command Line Options and Flags**" CR
+"  **Option**  **Example Argument**    **Description**" CR
+"  **-c**      **-c**/my/php.ini       Set php.ini file to load" CR
+"  **-d**      **-d**memory_limit=4G   Set a php.ini directive" CR
+"  **-n**                          Disable default php.ini" CR
+"  **-q**                          Supress welcome banner" CR
+"  **-e**      **-e**mytest.php        Set execution context" CR
+"  **-v**                          Enable oplog output" CR
+"  **-s**                          Enable stepping" CR
+"  **-b**                          Disable colour" CR
+"  **-i**      **-i**my.init           Set .phpdbginit file" CR
+"  **-I**                          Ignore default .phpdbginit" CR
+"  **-O**      **-O**my.oplog          Sets oplog output file" CR
+"  **-r**                          Run execution context" CR
+"  **-rr**                         Run execution context and quit after execution" CR
+"  **-E**                          Enable step through eval, careful!" CR
+"  **-S**      **-S**cli               Override SAPI name, careful!" CR
+"  **-l**      **-l**4000              Setup remote console ports" CR
+"  **-a**      **-a**192.168.0.3       Setup remote console bind address" CR
+"  **-V**                          Print version number" CR CR
+
+"**Remote Console Mode**" CR CR
+
+"This mode is enabled by specifying the **-a** option.  Phpdbg will bind only to the loopback "
+"interface by default, and this can only be overridden by explicitly setting the remote console "
+"bind address using the **-a** option. If **-a** is specied without an argument, then phpdbg "
+"will bind to all available interfaces.  You should be aware of the security implications of "
+"doing this, so measures should be taken to secure this service if bound to a publicly accessible "
+"interface/port." CR CR
+
+"Specify both stdin and stdout with -lstdin/stdout; by default stdout is stdin * 2."
+}, 
+
+{"_overview", 
+"**phpdbg** is a lightweight, powerful and easy to use debugging platform for PHP5.4+" CR
+"It supports the following commands:" CR CR
+
+"**Information**" CR
+"  **list**     list PHP source" CR
+"  **info**     displays information on the debug session" CR
+"  **help**     provide help on a topic" CR
+"  **print**    print argument " CR
+"  **frame**    select a stack frame and print a stack frame summary" CR CR
+
+"**Compilation**" CR
+"  **compile**  compile a PHP source" CR CR
+
+"**Starting and Stopping Execution**" CR
+"  **exec**     set execution context" CR
+"  **clean**    clean the execution environment" CR
+"  **run**      attempt execution" CR
+"  **eval**     evaluate some code" CR
+"  **stepping** Enable or disable per opcode stepping mode" CR
+"  **next**     continue execution" CR
+"  **until**    continue execution up to the given location" CR
+"  **finish**   continue up to end of the current execution frame" CR
+"  **leave**    continue up to end of the current execution frame and halt after the calling instruction" CR
+"  **break**    set a breakpoint at the specified target" CR
+"  **clear**    clear one or all breakpoints" CR CR
+
+"**Miscellaneous**" CR
+"  **quiet**    silence some output" CR
+"  **set**      set the phpdbg configuration" CR
+"  **source**   execute a phpdbginit script" CR
+"  **register** register a phpdbginit function as a command alias" CR
+"  **shell**    shell a command" CR
+"  **quit**     exit phpdbg" CR CR
+
+"Type **help <command>** or (**help alias**) to get detailed help on any of the above commands, "
+"for example **help list** or **h l**.  Note that help will also match partial commands if unique "
+"(and list out options if not unique), so **help clea** will give help on the **clean** command, "
+"but **help cl** will list the summary for **clean** and **clear**." CR CR
+
+"Type **help aliases** to show a full alias list, including any registered phpdginit functions" CR
+"Type **help syntax** for a general introduction to the command syntax." CR
+"Type **help options** for a list of phpdbg command line options." CR
+"Type **help phpdbginit** to show how to customise the debugger environment."
+}, 
+{"_phpdbginit", 
+"Phpdgb uses an debugger script file to initialize the debugger context.  By default, phpdbg looks "
+"for the file named **.phpdbginit** in the current working directory.  This location can be "
+"overridden on the command line using the **-i** switch (see **help options** for a more "
+"details)." CR CR
+
+"Debugger scripts can also be executed using the **script** command." CR CR
+
+"A script file can contain a sequence of valid debugger commands, comments and embedded PHP code. " "Comment lines are prefixed by the **#** character. PHP code is delimited by the start and end "
+"escape tags **<:** and **:>**." CR CR
+
+"**Examples**" CR CR
+//********Need decent script example
+}, 
+
+{"_syntax", 
+"All **phpdbg** commands are case sensitive.  Commands start with a keyword, and some keywords "
+"(**break**, **info**, **set**, **print** and **list**) may include a subcommand keyword.  All "
+"keywords have a single letter alias (most lowercase, some uppercase) that may be used instead "
+"of spelling out the keyword in full.  Note that keywords cannot be abbreviated other than by "
+"substitution by the alias." CR CR
+
+"Some commands take one or more optional arguments which are interpreted in the context of the "
+"command. In some cases the format of the argument enables the secondard keyword to be omitted." CR CR
+       
+"Type **help** for an overview of all commands and type **help <command>** to get detailed help "
+"on any specific command." CR CR
+
+"**Valid Examples**" CR CR
+
+"     $P quit" CR
+"     $P q" CR
+"     Quit the debugger" CR CR
+
+"     $P eval $total[2]" CR
+"     $P E $total[2]" CR
+"     Evaluate and print the variable $total[2] in the current stack frame" CR
+"    " CR
+"     $P break lineno 200" CR
+"     $P b my_source.php:200" CR
+"     Break at line 200 in the current source and in file **my_source.php**. " CR CR
+
+"     $P b A ClassX::get_args if $arg[0] == \"fred\"" CR
+"     $P b d 3" CR
+"     Break at ClassX::get_args() if $arg[0] == \"fred\" and delete breakpoint 3" CR CR
+
+"**Examples of invalid commands**" CR
+"     $P break line 23" CR
+"     The command keyword is **lineno**; **line** is not allowed" CR CR
+
+"     $P NEXT" CR
+"     Commands are case sensitive.  The keyword is **next**" CR CR
+
+"     $P s on" CR
+"     **step** takes an integer argument **0** or **1**; on/off is not allowed." CR CR
+
+"     $P #This is a comment" CR
+"     Comments introduced by the **#** character are only allowed in **phpdbginit** script files."
+}, 
+
+{"_ZZ_aliases", 
+"Note that aliases can be used for either command or sub-command keywords or both, so **info b** "
+"is a synomyn for **info break** and **l func** for **list func**, etc." CR CR
+
+"Note that help will also accept any alias as a parameter and provide help on that command, for example **h p** will provide help on the print command."
+}, 
+
+{"_ZZ_duplicate", 
+"Parameter is not unique. For detailed help select help on one of the above commands."
+}, 
+
+{"back", 
+"Provide a formatted backtrace using the standard debug_backtrace() functionality.  An optional "
+"unsigned integer argument specifying the maximum number of frames to be traced; if omitted then "
+"a complete backtrace is given." CR CR
+
+"**Examples**" CR CR
+"    $P back 5" CR
+"    $P t " CR
+" " CR
+"A backtrace can be executed at any time during execution."
+},
+
+{"break", 
+"Breakpoints can be set at a range of targets within the execution environment.  Execution will "
+"be paused if the program flow hits a breakpoint.  The break target can be one of the following "
+"types:" CR CR
+
+"  **Target**   **Alias** **Purpose**" CR
+"  **file**     **F**     specify breakpoint by file:line" CR
+"  **lineno**   **l**     specify breakpoint by line of currently executing file" CR
+"  **func**     **f**     specify breakpoint by global function name" CR
+"  **method**   **m**     specify breakpoint by class::method" CR
+"  **address**  **a**     specify breakpoint by address" CR
+"  **op**       **O**     specify breakpoint by opcode" CR
+"  **on**       **o**     specify breakpoint by condition" CR
+"  **at**       **A**     specify breakpoint by location and condition" CR
+"  **del**      **d**     delete breakpoint by breakpoint identifier number" CR CR
+
+"The syntax of the target argument is dependent on the target type and in the case of file, func "
+"method, and address targets the target keyword or alias is optional and can be omitted." CR CR
+
+"**Break on** takes a string argument which must be a valid PHP expression." CR CR
+
+"**Break at** takes two arguments. The first is any valid target as per the file, lineno, func "
+"and address types.  The second is a valid PHP expression which will trigger the break in "
+"execution, if evaluated as true in a boolean context at the specified target." CR CR
+
+"Note that breakpoints can also be temporarily enabled and disabled by the set break command." CR CR
+
+"**Examples**" CR CR
+"    $P break file test.php:100" CR
+"    $P b F test.php:100" CR
+"    $P b test.php:100" CR
+"    Break execution at line 100 of test.php" CR CR
+
+"    $P break lineno 200" CR
+"    $P b l 200" CR
+"    $P b 200" CR
+"    Break execution at line 200 of the currently PHP script file" CR CR
+
+"    $P break func \\\\mynamespace\\\\my_function" CR
+"    $P b f \\\\mynamespace\\\\my_function" CR
+"    $P b \\\\mynamespace\\\\my_function" CR
+"    Break execution on entry to \\\\mynamespace\\\\my_function" CR CR
+
+"    $P break method classX::method" CR
+"    $P b m classX::method" CR
+"    $P b classX::method" CR
+"    Break execution on entry to classX::method" CR CR
+
+"    $P break address 0x7ff68f570e08" CR
+"    $P b a 0x7ff68f570e08" CR
+"    $P b 0x7ff68f570e08" CR
+"    Break at the opline at the address 0x7ff68f570e08" CR CR
+
+"    $P break address my_function#14" CR
+"    $P b a my_function#14" CR
+"    $P b my_function#14" CR
+"    Break at the opline #14 of the function my_function" CR CR
+
+"    $P break address \\\\my\\\\class::method#2" CR
+"    $P b a \\\\my\\\\class::method#2" CR
+"    $P b \\\\my\\\\class::method#2" CR
+"    Break at the opline #2 of the method \\\\my\\\\class::method" CR CR
+
+"    $P break address test.php#3" CR
+"    $P b a test.php#3" CR
+"    Break at the opline #3 of test.php" CR CR
+
+"    $P break on $cnt > 10" CR
+"    $P b o $cnt > 10" CR
+"    Break when the condition ($cnt > 10) evaluates to true" CR CR
+
+"    $P break at phpdbg::isGreat if $opt == 'S'" CR
+"    Break at any opcode in phpdbg::isGreat when the condition ($opt == 'S') is true" CR CR
+
+"    $P break at test.php:20 if !isset($x)" CR
+"    Break at every opcode on line 20 of test.php when the condition evaluates to true" CR CR
+
+"    $P break op ZEND_ADD" CR
+"    $P b O ZEND_ADD" CR
+"    Break on any occurence of the opcode ZEND_ADD" CR CR
+
+"    $P break del 2" CR
+"    $P b d 2" CR
+"    Remove breakpoint 2" CR CR
+
+"Note: Conditional breaks are costly in terms of runtime overhead. Use them only when required "
+"as they significantly slow execution." CR CR
+
+"Note: An address is only valid for the current compilation."
+}, 
+
+{"clean", 
+"Classes, constants or functions can only be declared once in PHP.  You may experience errors "
+"during a debug session if you attempt to recompile a PHP source.  The clean command clears "
+"the Zend runtime tables which holds the sets of compiled classes, constants and functions, "
+"releasing any associated storage back into the storage pool.  This enables recompilation to "
+"take place." CR CR
+
+"Note that you cannot selectively trim any of these resource pools. You can only do a complete "
+"clean."
+}, 
+
+{"clear", 
+"Clearing breakpoints means you can once again run code without interruption." CR CR
+
+"Note: use break delete N to clear a specific breakpoint." CR CR
+
+"Note: if all breakpoints are cleared, then the PHP script will run until normal completion."
+}, 
+
+{"compile", 
+"The execution context can be pre-compiled before execution, to provide the opportunity to "
+"inspect the generated opcode output.  The execution context must be defined before the compile "
+"command can be used.  Use the command **exec** to set the execution context." CR CR
+
+"**Examples**" CR CR
+"    $P compile" CR
+"    $P c" CR CR
+
+"Note: Then that it is usually necessary to issue a **clean** command to reset the environment prior "
+"to compilation."
+}, 
+//********** Needs rewriting -- don't like -- careful thought  -- what happens if you evaluate a function during execution, with and without breakpoints, with and without stepping ??
+
+{"eval", 
+"The **eval** command takes a string expression which it evaluates and then displays. Note that "
+"**eval** allows assignments and other write statements, thus enabling you to change the "
+"environment during execution, so care is needed here." CR CR
+
+"**Examples**" CR CR
+"    $P eval $variable" CR
+"    $P E $variable" CR
+"    Will print_r($variable) on the console, if it is defined" CR CR
+
+"    $P eval $variable = \"Hello phpdbg :)\"" CR
+"    $P E $variable = \"Hello phpdbg :)\"" CR
+"    Will set $variable in the current scope" CR CR
+
+"Note: **eval** will evaluate in the lowest (that is the executing) frame, unless this has first "
+"been explicitly changed by issuing a **frame** command. " CR CR
+
+"Note: **eval** will always show the result; do not prefix the code with **return**"
+}, 
+
+{"exec", 
+"The **exec** command sets the execution context, that is the script to be executed." CR
+
+"The execution context must be defined either by executing the **exec** command or by using the "
+"**-e** command line option before the script can be compiled or run." CR CR
+
+"Note that the **exec** command also can be used to replace a previously defined execution "
+"context." CR CR 
+
+"**Examples**" CR CR
+
+"    $P exec /tmp/script.php" CR
+"    $P e /tmp/script.php" CR
+"    Set the execution context to **/tmp/script.php**"
+}, 
+
+//*********** Does F skip any breakpoints lower stack frames or only the current??
+{"finish", 
+"The **finish** command causes control to be passed back to the vm, continuing execution.  Any "
+"breakpoints that are encountered within the current stack frame will be skipped.  Execution "
+"will then continue until the next breakpoint after leaving the stack frame or unitil "
+"completion of the script" CR CR
+
+"Note **finish** will trigger a \"not executing\" error if not executing."
+}, 
+
+{"frame", 
+"The **frame** takes an optional integer argument. If omitted, then the current frame is displayed "
+"If specified then the current scope is set to the corresponding frame listed in a **back** trace. " "This can be used to allowing access to the variables in a higher stack frame than that currently "
+"being executed." CR CR
+
+"**Examples**" CR CR
+"    $P frame 2" CR
+"    $P E $count" CR
+"    Go to frame 2 and print out variable **$count** in that frame" CR CR
+
+"Note that this frame scope is discarded when execution continues, with the execution frame "
+"then reset to the lowest executiong frame."
+}, 
+
+{"info", 
+"**info** commands provide quick access to various types of information about the PHP environment" CR
+"Specific info commands are show below:" CR CR
+
+"  **Target**   **Alias**  **Purpose**" CR
+"  **break**    **b**      show current breakpoints" CR
+"  **files**    **F**      show included files" CR
+"  **classes**  **c**      show loaded classes" CR
+"  **funcs**    **f**      show loaded classes" CR
+"  **error**    **e**      show last error" CR
+"  **vars**     **v**      show active variables" CR
+"  **literal**  **l**      show active literal constants" CR
+"  **memory**   **m**      show memory manager stats"
+},
+
+// ******** same issue about breakpoints in called frames
+{"leave", 
+"The **leave** command causes control to be passed back to the vm, continuing execution.  Any "
+"breakpoints that are encountered within the current stack frame will be skipped.  In effect a " 
+"temporary breakpoint is associated with any return opcode, so that a break in execution occurs "
+"before leaving the current stack frame. This allows inspection / modification of any frame "
+"variables including the return value before it is returned" CR CR
+
+"**Examples**" CR CR
+
+"    $P leave" CR
+"    $P L" CR CR
+}, 
+
+{"list", 
+"The list command displays source code for the given argument.  The target type is specficied by "
+"a second subcommand keyword:" CR CR
+
+"  **Type**     **Alias**  **Purpose**" CR
+"  **lines**    **l**      List N lines from the current execution point" CR
+"  **func**     **f**      List the complete source for a specified function" CR
+"  **method**   **m**      List the complete source for a specified class::method" CR
+"  **class**    **c**      List the complete source for a specified class" CR CR
+
+"Note that the context of **lines**, **func** and **method** can be determined by parsing the "
+"argument, so these subcommands are optional.  However, you must specify the **class** keyword "
+"to list off a class." CR CR
+
+"**Examples**" CR CR
+"    $P list 2" CR
+"    $P l l 2" CR
+"    List the next 2 lines from the current file" CR CR
+
+"    $P list my_function" CR
+"    $P l f my_function" CR
+"    List the source of the function **my_function**" CR CR
+
+//************ ????
+"    $P list func .mine" CR
+"    $P l f .mine" CR
+"    List the source of the method **mine** from the active class in scope" CR CR
+
+"    $P list m my::method" CR
+"    $P l my::method" CR
+"    List the source of **my::method**" CR CR
+
+"    $P list c myClass" CR
+"    $P l c myClass" CR
+"    List the source of **myClass**" CR CR
+
+"Note that functions and classes can only be listed if the corresponding classes and functions "
+"table in the Zend executor has a corresponding entry.  You can use the compile command to "
+"populate these tables for a given execution context."
+},
+
+//*********** what is the difference between n and s ???
+{"next", 
+"The **next** command causes control to be passed back to the vm, continuing execution.  The next "
+"opline will be executed if **step 1** is set.  Otherwise execution will continue to the next "
+"breakpoint or script completion" CR CR
+
+"Note **next** will trigger a \"not running\" error if not executing."
+}, 
+
+{"print",
+"By default, print will show information about the current execution context." CR
+"Other printing commands give access to instruction information." CR
+"Specific printers loaded are show below:" CR CR
+
+"  **Type**    **Alias**  **Purpose**" CR
+"  **exec**    **e**      print out the instructions in the execution context" CR
+"  **opline**  **o**      print out the instruction in the current opline" CR
+"  **class**   **c**      print out the instructions in the specified class" CR
+"  **method**  **m**      print out the instructions in the specified method" CR
+"  **func**    **f**      print out the instructions in the specified function" CR
+"  **stack**   **s**      print out the instructions in the current stack" CR CR
+
+"**Examples**" CR CR
+"    $P print class \\\\my\\\\class" CR
+"    $P p c \\\\my\\\\class" CR
+"    Print the instructions for the methods in \\\\my\\\\class" CR CR
+
+"    $P print method \\\\my\\\\class::method" CR
+"    $P p m \\\\my\\\\class::method" CR
+"    Print the instructions for \\\\my\\\\class::method" CR CR
+
+"    $P print func .getSomething" CR
+"    $P p f .getSomething" CR
+//************* Check this local method scope
+"    Print the instructions for ::getSomething in the active scope" CR CR
+
+"    $P print func my_function" CR
+"    $P p f my_function" CR
+"    Print the instructions for the global function my_function" CR CR
+
+"    $P print opline" CR
+"    $P p o" CR
+"    Print the instruction for the current opline" CR CR
+
+"    $P print exec" CR
+"    $P p e" CR
+"    Print the instructions for the execution context" CR CR
+
+"    $P print stack" CR
+"    $P p s" CR
+"    Print the instructions for the current stack"
+},
+
+{"quiet", 
+"Setting quietness on will stop the OPLINE output during execution" CR CR
+
+"**Examples**" CR CR
+"    $P quiet 1" CR
+"    $P Q 1" CR
+"    Will silence OPLINE output, while" CR CR
+
+"    $P quiet 0" CR
+"    $P Q 0" CR
+"    Will enable OPLINE output again" CR CR
+
+"Note: Quietness is disabled automatically while stepping"
+},
+
+{"register", 
+//******* Needs a general explanation of the how registered functions work
+"Register any global function for use as a command in phpdbg console" CR CR
+
+"**Examples**" CR CR
+"    $P register scandir" CR
+"    $P R scandir" CR
+"    Will register the scandir function for use in phpdbg" CR CR
+
+"Note: arguments passed as strings, return (if present) print_r'd on console"
+},
+
+{"run", 
+"Enter the vm, startinging execution. Execution will then continue until the next breakpoint "
+"or completion of the script"
+"**Examples**" CR CR
+"    $P run" CR
+"    $P r" CR
+"    Will cause execution of the context, if it is set." CR CR
+
+"Note that the execution context must be set. If not previously compiled, then the script will "
+"be compiled before execution." CR CR
+
+"Note that attempting to run a script that is already executing will result in an \"execution "
+"in progress\" error."
+},
+
+{"set", 
+"The **set** command is used to configure how phpdbg looks and behaves.  Specific set commands "
+"are as follows:" CR CR
+
+"   **Type**  **Alias**    **Purpose**" CR
+"   **prompt**   **p**     set the prompt  " CR
+"   **color**    **c**     set color  <element> <color>" CR
+"   **colors**   **C**     set colors on or off" CR
+"   **oplog**    **O**     set oplog output" CR
+"   **break**    **b**     set break **id** <on|off>" CR CR
+
+"Valid colors are **none**, **white**, **red**, **green**, **yellow**, **blue**, **purple**, "
+"**cyan** and **black**.  All colours except **none** can be followed by an optional "
+"**-bold** or **-underline** qualifier." CR CR
+
+"Color elements can be one of **prompt**, **notice**, or **error**." CR CR
+
+"**Examples**" CR CR
+"     $P s C on" CR
+"     Set colors on" CR CR
+
+"     $P set p >" CR
+"     $P set color prompt white-bold" CR
+"     Set the prompt to a bold >" CR CR
+
+"     $P s c error red-bold" CR
+"     Use red bold for errors" CR
+"     " CR
+"     $P s b 4 off" CR
+"     Temporarily disable breakpoint 4.  This can be subsequently reenabled by a **s b 4 on**." CR
+//*********** check oplog syntax
+}, 
+
+{"shell", 
+//************ Check ! notation
+"Direct access to shell commands saves having to switch windows/consoles" CR CR
+
+"**Examples**" CR CR
+"    $P shell ls /usr/src/php-src" CR
+"    $P - ls /usr/src/php-src" CR
+"    Will execute ls /usr/src/php-src, displaying the output in the console"
+//*********** what does this mean????Note: read only commands please!
+}, 
+
+{"source", 
+"Sourcing a **phpdbginit** script during your debugging session might save some time." CR CR
+
+"The source command can also be used to export breakpoints to a phpdbginit file." CR CR
+
+"**Examples**" CR CR
+
+"    $P source /my/init" CR
+"    $P . /my/init" CR
+"    Will execute the phpdbginit file at /my/init" CR CR
+
+"    $P source export /my/init" CR
+"    $P . export /my/init" CR
+"    Will export breakpoints to /my/init in phpdbginit file format"
+},
+
+{"step",
+"You can enable and disable **stepping** mode at the phpdbg prompt during execution.  When "
+"stepping mode is enabled, execution will be step through opcode by opcode." CR CR
+
+"**Examples**" CR CR
+"    $P step 1" CR
+"    $P s 1" CR
+"    Will enable stepping" CR CR
+
+"While stepping is enabled you are presented with an interactive prompt after the execution of each opcode"
+},
+
+{"until", 
+//******* More explanation needed -- how does until play with step 1 ??
+"The **until** command causes control to be passed back to the vm, continuing execution.  Any "
+"breakpoints that are encountered before the the next source line will be skipped.  Execution "
+"will then continue until the next breakpoint or completion of the script" CR CR
+
+"Note **until** will trigger a \"not executing\" error if not executing."
+
+},
+{"|", NULL /* end of table marker */}
+};  /* }}} */
index 319142cb5b200a03c8771fc71aedefc189f502db..16a1e771e3719b519638656c42e32b4429179932 100644 (file)
 /**
  * Helper Forward Declarations
  */
-PHPDBG_HELP(exec);
-PHPDBG_HELP(compile);
-PHPDBG_HELP(step);
-PHPDBG_HELP(next);
-PHPDBG_HELP(run);
-PHPDBG_HELP(eval);
-PHPDBG_HELP(until);
-PHPDBG_HELP(finish);
-PHPDBG_HELP(leave);
-PHPDBG_HELP(print);
-PHPDBG_HELP(break);
-PHPDBG_HELP(clean);
-PHPDBG_HELP(clear);
-PHPDBG_HELP(info);
-PHPDBG_HELP(back);
-PHPDBG_HELP(frame);
-PHPDBG_HELP(quiet);
-PHPDBG_HELP(list);
-PHPDBG_HELP(set);
-PHPDBG_HELP(register);
-PHPDBG_HELP(options);
-PHPDBG_HELP(source);
-PHPDBG_HELP(shell);
+PHPDBG_HELP(aliases);
 
-/**
- * Commands
- */
-static const phpdbg_command_t phpdbg_help_commands[] = {
-       PHPDBG_COMMAND_D_EX(exec,     "the execution context should be a valid path",                                    'e', help_exec,    NULL, 0),
-       PHPDBG_COMMAND_D_EX(compile,  "allow inspection of code before execution",                                       'c', help_compile, NULL, 0),
-       PHPDBG_COMMAND_D_EX(step,     "step through execution to break at every opcode",                                 's', help_step,    NULL, 0),
-       PHPDBG_COMMAND_D_EX(next,     "continue executing while stepping or after breaking",                             'n', help_next,    NULL, 0),
-       PHPDBG_COMMAND_D_EX(run,      "execute inside the phpdbg vm",                                                    'r', help_run,     NULL, 0),
-       PHPDBG_COMMAND_D_EX(eval,     "access to eval() allows affecting the environment",                               'E', help_eval,    NULL, 0),
-       PHPDBG_COMMAND_D_EX(until,    "continue until the current line is executed",                                     'u', help_until,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(finish,   "continue until the current function has returned",                                'F', help_finish,  NULL, 0),
-       PHPDBG_COMMAND_D_EX(leave,    "continue until the current function is returning",                                'L', help_leave,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(print,    "print context information or instructions",                                       'p', help_print,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(break,    "breakpoints allow execution interruption",                                        'b', help_break,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(clean,    "resetting the environment is useful while debugging",                             'X', help_clean,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(clear,    "reset breakpoints to execute without interruption",                               'c', help_clear,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(info,     "quick access to useful information on the console",                               'i', help_info,    NULL, 0),
-       PHPDBG_COMMAND_D_EX(back,     "show debug backtrace information during execution",                               't', help_back,    NULL, 0),
-       PHPDBG_COMMAND_D_EX(frame,    "switch to a frame in the current stack for inspection",                           'f', help_frame,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(quiet,    "be quiet during execution",                                                       'Q', help_quiet,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(list,     "list code gives you quick access to code",                                        'l', help_list,    NULL, 0),
-       PHPDBG_COMMAND_D_EX(set,      "configure how phpdbg looks and behaves",                                          'S', help_set,     NULL, 0),
-       PHPDBG_COMMAND_D_EX(register, "register a function for use as a command",                                        'R', help_register,NULL, 0),
-       PHPDBG_COMMAND_D_EX(options,  "show information about command line options",                                     'o', help_options, NULL, 0),
-       PHPDBG_COMMAND_D_EX(source,   "load a phpdbginit file at the console",                                           '.', help_source,  NULL, 0),
-       PHPDBG_COMMAND_D_EX(shell,    "execute system commands with direct shell access",                                '-', help_shell,   NULL, 0),
-       PHPDBG_END_COMMAND
-};
+extern const phpdbg_command_t phpdbg_help_commands[];
 
 #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);
 
+typedef struct _phpdbg_help_text_t {
+       char *key;
+       char *text;
+} phpdbg_help_text_t;
+
+extern phpdbg_help_text_t phpdbg_help_text[];
 #endif /* PHPDBG_HELP_H */
index 0f4233bf30c7bff03ff93cf7f2482f4395e56748..b559b75835f16cb141b4402e42e4660e56fd70f7 100644 (file)
 
 ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
 
+const phpdbg_command_t phpdbg_info_commands[] = {
+       PHPDBG_COMMAND_D_EX(break,    "show breakpoints",              'b', info_break,   NULL, 0),
+       PHPDBG_COMMAND_D_EX(files,    "show included files",           'F', info_files,   NULL, 0),
+       PHPDBG_COMMAND_D_EX(classes,  "show loaded classes",           'c', info_classes, NULL, 0),
+       PHPDBG_COMMAND_D_EX(funcs,    "show loaded classes",           'f', info_funcs,   NULL, 0),
+       PHPDBG_COMMAND_D_EX(error,    "show last error",               'e', info_error,   NULL, 0),
+       PHPDBG_COMMAND_D_EX(vars,     "show active variables",         'v', info_vars,    NULL, 0),
+       PHPDBG_COMMAND_D_EX(literal,  "show active literal constants", 'l', info_literal, NULL, 0),
+       PHPDBG_COMMAND_D_EX(memory,   "show memory manager stats",     'm', info_memory,  NULL, 0),
+       PHPDBG_END_COMMAND
+};
+
 PHPDBG_INFO(break) /* {{{ */
 {
        phpdbg_print_breakpoints(PHPDBG_BREAK_FILE TSRMLS_CC);
index a6b4e3719febd2e5e66598064737d6970a4d26e8..c36e6bebd65f6996260334abee2f9755efc3493d 100644 (file)
@@ -34,16 +34,6 @@ PHPDBG_INFO(vars);
 PHPDBG_INFO(literal);
 PHPDBG_INFO(memory);
 
-static const phpdbg_command_t phpdbg_info_commands[] = {
-       PHPDBG_COMMAND_D_EX(break,    "show breakpoints",              'b', info_break,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(files,    "show included files",           'F', info_files,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(classes,  "show loaded classes",           'c', info_classes, NULL, 0),
-       PHPDBG_COMMAND_D_EX(funcs,    "show loaded classes",           'f', info_funcs,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(error,    "show last error",               'e', info_error,   NULL, 0),
-       PHPDBG_COMMAND_D_EX(vars,     "show active variables",         'v', info_vars,    NULL, 0),
-       PHPDBG_COMMAND_D_EX(literal,  "show active literal constants", 'l', info_literal, NULL, 0),
-       PHPDBG_COMMAND_D_EX(memory,   "show memory manager stats",     'm', info_memory,  NULL, 0),
-       PHPDBG_END_COMMAND
-};
+extern const phpdbg_command_t phpdbg_info_commands[];
 
 #endif /* PHPDBG_INFO_H */
index eb1091550b018d47208bca2772866a560b3c6f9d..7177def8d62f0d2a1e2b50ed991ee786de28973e 100644 (file)
 
 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_END_COMMAND
+};
+
 PHPDBG_LIST(lines) /* {{{ */
 {
        if (!PHPDBG_G(exec) && !zend_is_executing(TSRMLS_C)) {
index f9d1885eaf242c0ba1dd1c141e1707501b1bb479..14905f65673b7123fa9ef1d2c33710ec127d0976 100644 (file)
@@ -36,12 +36,6 @@ 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, int TSRMLS_DC);
 
-static 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_END_COMMAND
-};
+extern const phpdbg_command_t phpdbg_list_commands[];
 
 #endif /* PHPDBG_LIST_H */
index c4925fe5fd78984c82c3d429b6ececf812aa1351..5e3129ad7fb9c52e2d7afd24173458503195639b 100644 (file)
 
 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(stack,      "print out the instructions in the current stack",      's', print_stack,  NULL, 0),
+       PHPDBG_END_COMMAND
+};
+
 PHPDBG_PRINT(opline) /* {{{ */
 {
        if (EG(in_execution) && EG(current_execute_data)) {
index 80010d5e7cc8ef5ff2f160b8eedb0d468c9ffd28..ed85e965c1b428278d5281fd36850e82f24eea59 100644 (file)
@@ -35,17 +35,6 @@ PHPDBG_PRINT(method);
 PHPDBG_PRINT(func);
 PHPDBG_PRINT(stack);
 
-/**
- * Commands
- */
-static 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(stack,      "print out the instructions in the current stack",      's', print_stack,  NULL, 0),
-       PHPDBG_END_COMMAND
-};
+extern const phpdbg_command_t phpdbg_print_commands[];
 
 #endif /* PHPDBG_PRINT_H */
index 529ab04194d4b7f29d539efb608b99ada6f8e818..447d40896bde4aacf4eee2af477eff91c6161145 100644 (file)
@@ -57,7 +57,6 @@ const phpdbg_command_t phpdbg_prompt_commands[] = {
        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(aliases, "show alias list",                          'a', NULL, 0),
        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),
@@ -908,76 +907,6 @@ PHPDBG_COMMAND(clear) /* {{{ */
        return SUCCESS;
 } /* }}} */
 
-PHPDBG_COMMAND(aliases) /* {{{ */
-{
-       const phpdbg_command_t *prompt_command = phpdbg_prompt_commands;
-
-       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) {
-                       if (prompt_command->subs) {
-                               const phpdbg_command_t *sub_command = prompt_command->subs;
-                               phpdbg_writeln(EMPTY);
-                               phpdbg_writeln(" %c -> %9s", prompt_command->alias, prompt_command->name);
-                               while (sub_command && sub_command->name) {
-                                       if (sub_command->alias) {
-                                               phpdbg_writeln(" |-------- %c -> %15s\t%s", sub_command->alias,
-                                                       sub_command->name, sub_command->tip);
-                                       }
-                                       ++sub_command;
-                               }
-                               phpdbg_writeln(EMPTY);
-                       } else {
-                               phpdbg_writeln(" %c -> %9s\t\t\t%s", prompt_command->alias,
-                                       prompt_command->name, prompt_command->tip);
-                       }
-               }
-
-               ++prompt_command;
-       }
-       phpdbg_help_footer();
-
-       return SUCCESS;
-} /* }}} */
-
-PHPDBG_COMMAND(help) /* {{{ */
-{
-       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_help_header();
-                       phpdbg_writeln("To get help regarding a specific command type \"help command\"");
-
-                       phpdbg_notice("Commands");
-
-                       while (prompt_command && prompt_command->name) {
-                               phpdbg_writeln(
-                                       " %10s\t%s", prompt_command->name, prompt_command->tip);
-                               ++prompt_command;
-                       }
-
-                       phpdbg_notice("Help Commands");
-
-                       while (help_command && help_command->name) {
-                               phpdbg_writeln(" %10s\t%s", help_command->name, help_command->tip);
-                               ++help_command;
-                       }
-
-                       phpdbg_help_footer();
-               } break;
-
-               default: {
-                       phpdbg_error(
-                               "No help can be found for the subject \"%s\"", param->str);
-               }
-       }
-
-       return SUCCESS;
-} /* }}} */
-
 PHPDBG_COMMAND(quiet) /* {{{ */
 {
        switch (param->type) {
index 6807d88f41d1659935c008c62e36fe5e2f5bc139..e66ea16dce31d4feb46e1bfadbcc98698b539ad7 100644 (file)
@@ -48,7 +48,6 @@ PHPDBG_COMMAND(clean);
 PHPDBG_COMMAND(clear);
 PHPDBG_COMMAND(help);
 PHPDBG_COMMAND(quiet);
-PHPDBG_COMMAND(aliases);
 PHPDBG_COMMAND(shell);
 PHPDBG_COMMAND(set);
 PHPDBG_COMMAND(source);
index 7c4da12a46e8c066f92c95193aa894f48052395e..50c07b66d85eb922c0c7e15826f1b62f70cc2ecd 100644 (file)
 
 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),
+#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),
+#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_END_COMMAND
+};
+
 PHPDBG_SET(prompt) /* {{{ */
 {
        switch (param->type) {
index 120aeb34f4e210ac9f1181219dc06837fe317198..ddc3876f5dce29682e890c1f0b96e314df88fa0c 100644 (file)
@@ -33,15 +33,6 @@ PHPDBG_SET(colors);
 PHPDBG_SET(oplog);
 PHPDBG_SET(break);
 
-static const phpdbg_command_t phpdbg_set_commands[] = {
-       PHPDBG_COMMAND_D_EX(prompt,       "usage: set prompt <string>",          'p', set_prompt,       NULL, 0),
-#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),
-#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_END_COMMAND
-};
+extern const phpdbg_command_t phpdbg_set_commands[];
 
 #endif /* PHPDBG_SET_H */
index 1effcfccaf93f7c90bc9a357efeb3297ccc9703e..4bb671247ed91e35224981614e922dc4bd1e708f 100644 (file)
@@ -30,6 +30,8 @@
 
 #ifdef _WIN32
 #      include "win32/time.h"
+#elif defined(HAVE_SYS_IOCTL_H) 
+#   include "sys/ioctl.h"
 #endif
 
 ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
@@ -385,3 +387,22 @@ PHPDBG_API const char *phpdbg_get_prompt(TSRMLS_D) /* {{{ */
 
        return PHPDBG_G(prompt)[1];
 } /* }}} */
+
+PHPDBG_API int phpdbg_get_terminal_width(TSRMLS_D) /* {{{ */
+{
+       int columns;    
+#ifdef _win32
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+       GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
+       columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
+#elif defined(HAVE_SYS_IOCTL_H) 
+       struct winsize w;
+
+       columns = ioctl(fileno(stdout), TIOCGWINSZ, &w) == 0 ? w.ws_col : 100;
+#else
+       columns = 100;
+#endif
+       return columns;
+} /* }}} */
+
index c5164c3ac31490859fa6c368ce6d3a40ca3df784..ee7ff3f5bd19bd50947134fd0318ce79c845b1dc 100644 (file)
@@ -107,4 +107,7 @@ PHPDBG_API const phpdbg_color_t* phpdbg_get_colors(TSRMLS_D); /* }}} */
 PHPDBG_API void phpdbg_set_prompt(const char* TSRMLS_DC);
 PHPDBG_API const char *phpdbg_get_prompt(TSRMLS_D); /* }}} */
 
+/* {{{ Console Width */
+PHPDBG_API int phpdbg_get_terminal_width(TSRMLS_D); /* }}} */
+
 #endif /* PHPDBG_UTILS_H */