#include "phpdbg_list.h"
#include "phpdbg_utils.h"
+ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
+
+static inline void i_phpdbg_list_func(const char *str TSRMLS_DC)
+{
+ HashTable *func_table = EG(function_table);
+ zend_function* fbc;
+ const char *func_name = str;
+ size_t func_name_len = strlen(str);
+
+ /* search active scope if begins with period */
+ if (func_name[0] == '.') {
+ if (EG(scope)) {
+ func_name++;
+ func_name_len--;
+
+ func_table = &EG(scope)->function_table;
+ } else {
+ phpdbg_error("No active class");
+ return;
+ }
+ } else if (!EG(function_table)) {
+ phpdbg_error("No function table loaded");
+ return;
+ } else {
+ func_table = EG(function_table);
+ }
+
+ if (zend_hash_find(func_table, func_name, func_name_len+1,
+ (void**)&fbc) == SUCCESS) {
+ phpdbg_list_function(fbc TSRMLS_CC);
+ } else {
+ phpdbg_error("Function %s not found", func_name);
+ }
+}
+
+PHPDBG_LIST(lines) /* {{{ */
+{
+ phpdbg_param_t param;
+ int type = phpdbg_parse_param(
+ expr, expr_len, ¶m TSRMLS_CC);
+
+ switch (type) {
+ case NUMERIC_PARAM:
+ case EMPTY_PARAM: {
+ if (PHPDBG_G(exec) || zend_is_executing(TSRMLS_C)) {
+ if (type == EMPTY_PARAM) {
+ phpdbg_list_file(phpdbg_current_file(TSRMLS_C), 0, 0 TSRMLS_CC);
+ } else phpdbg_list_file(phpdbg_current_file(TSRMLS_C), param.num, 0 TSRMLS_CC);
+ } else phpdbg_error("Not executing, and execution context not set");
+ } break;
+
+ default:
+ phpdbg_error("Unsupported parameter type (%d) for command", type);
+ }
+
+ phpdbg_clear_param(type, ¶m TSRMLS_CC);
+
+ return SUCCESS;
+} /* }}} */
+
+PHPDBG_LIST(func) /* {{{ */
+{
+ phpdbg_param_t param;
+ int type = phpdbg_parse_param(
+ expr, expr_len, ¶m TSRMLS_CC);
+
+ if (type == STR_PARAM) {
+ i_phpdbg_list_func(
+ param.str TSRMLS_CC);
+ }
+
+ phpdbg_clear_param(type, ¶m TSRMLS_CC);
+
+ return SUCCESS;
+} /* }}} */
+
+void phpdbg_list_dispatch(int type, phpdbg_param_t *param TSRMLS_DC) /* {{{ */
+{
+ switch (type) {
+ case NUMERIC_PARAM:
+ case EMPTY_PARAM: {
+ if (PHPDBG_G(exec) || zend_is_executing(TSRMLS_C)) {
+ if (type == EMPTY_PARAM) {
+ phpdbg_list_file(phpdbg_current_file(TSRMLS_C), 0, 0 TSRMLS_CC);
+ } else phpdbg_list_file(phpdbg_current_file(TSRMLS_C), param->num, 0 TSRMLS_CC);
+ } else phpdbg_error("Not executing, and execution context not set");
+ } break;
+
+ case FILE_PARAM:
+ phpdbg_list_file(param->file.name, param->file.line, 0 TSRMLS_CC);
+ break;
+
+ case STR_PARAM: {
+ i_phpdbg_list_func(param->str TSRMLS_CC);
+ } break;
+
+ default:
+ phpdbg_error("Unsupported input type (%d) for command", type);
+ break;
+ }
+} /* }}} */
+
void phpdbg_list_file(const char *filename, long count, long offset TSRMLS_DC) /* {{{ */
{
unsigned char *mem, *pos, *last_pos, *end_pos;
#ifndef PHPDBG_LIST_H
#define PHPDBG_LIST_H
+#include "TSRM.h"
+#include "phpdbg_prompt.h"
+#include "phpdbg_utils.h"
+
+/**
+ * Command Declarators
+ */
+#define PHPDBG_LIST_D(name, tip) \
+ {PHPDBG_STRL(#name), tip, sizeof(tip)-1, 0, phpdbg_do_list_##name}
+#define PHPDBG_LIST_EX_D(name, tip, alias) \
+ {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_list_##name}
+#define PHPDBG_LIST(name) \
+ int phpdbg_do_list_##name(const char *expr, size_t expr_len TSRMLS_DC)
+
+PHPDBG_LIST(lines);
+PHPDBG_LIST(func);
+
void phpdbg_list_function(const zend_function* TSRMLS_DC);
void phpdbg_list_file(const char*, long, long TSRMLS_DC);
+void phpdbg_list_dispatch(int type, phpdbg_param_t *param TSRMLS_DC);
+
+static const phpdbg_command_t phpdbg_list_commands[] = {
+ PHPDBG_LIST_EX_D(lines, "lists the specified lines", 'l'),
+ PHPDBG_LIST_EX_D(func, "lists the specified function", 'f'),
+ {NULL, 0, 0}
+};
#endif /* PHPDBG_LIST_H */
static PHPDBG_COMMAND(break) /* {{{ */
{
phpdbg_param_t param;
- char *line_pos;
-
+ int type;
+
if (expr_len == 0) {
phpdbg_error("No expression found");
return FAILURE;
return SUCCESS;
}
- switch (phpdbg_parse_param(expr, expr_len, ¶m TSRMLS_CC)) {
+ switch ((type=phpdbg_parse_param(expr, expr_len, ¶m TSRMLS_CC))) {
case ADDR_PARAM:
phpdbg_set_breakpoint_opline(param.addr TSRMLS_CC);
break;
default:
break;
}
- phpdbg_clear_param(¶m);
+
+ phpdbg_clear_param(type, ¶m TSRMLS_CC);
return SUCCESS;
} /* }}} */
static PHPDBG_COMMAND(list) /* {{{ */
{
- if (phpdbg_is_empty(expr) || phpdbg_is_numeric(expr)) {
- long offset = 0, count = strtol(expr, NULL, 0);
- const char *filename = PHPDBG_G(exec);
-
- if (zend_is_executing(TSRMLS_C)) {
- filename = zend_get_executed_filename(TSRMLS_C);
- offset = zend_get_executed_lineno(TSRMLS_C);
- } else if (!filename) {
- phpdbg_error("No file to list");
- return SUCCESS;
- }
-
- phpdbg_list_file(filename, count, offset TSRMLS_CC);
- } else {
- HashTable *func_table = EG(function_table);
- zend_function* fbc;
- const char *func_name = expr;
- size_t func_name_len = expr_len;
-
- /* search active scope if begins with period */
- if (func_name[0] == '.') {
- if (EG(scope)) {
- func_name++;
- func_name_len--;
-
- func_table = &EG(scope)->function_table;
- } else {
- phpdbg_error("No active class");
- return FAILURE;
- }
- } else if (!EG(function_table)) {
- phpdbg_error("No function table loaded");
- return SUCCESS;
- } else {
- func_table = EG(function_table);
- }
-
- if (zend_hash_find(func_table, func_name, func_name_len+1,
- (void**)&fbc) == SUCCESS) {
- phpdbg_list_function(fbc TSRMLS_CC);
- } else {
- phpdbg_error("Function %s not found", func_name);
- }
+ phpdbg_param_t param;
+ int type = 0;
+
+ /* allow advanced listers to run */
+ if (phpdbg_do_cmd(phpdbg_list_commands, (char*)expr, expr_len TSRMLS_CC) == SUCCESS) {
+ return SUCCESS;
}
+ phpdbg_list_dispatch(
+ phpdbg_parse_param(expr, expr_len, ¶m TSRMLS_CC),
+ ¶m TSRMLS_CC);
+
+ phpdbg_clear_param(type, ¶m TSRMLS_CC);
+
return SUCCESS;
} /* }}} */
return STR_PARAM;
} /* }}} */
-void phpdbg_clear_param(int type, phpdbg_param_t *param) /* {{{ */
+void phpdbg_clear_param(int type, phpdbg_param_t *param TSRMLS_DC) /* {{{ */
{
switch (type) {
case FILE_PARAM:
} phpdbg_param_t;
int phpdbg_parse_param(const char*, size_t, phpdbg_param_t* TSRMLS_DC);
+void phpdbg_clear_param(int, phpdbg_param_t * TSRMLS_DC);
const char *phpdbg_current_file(TSRMLS_D);
char *phpdbg_resolve_path(const char* TSRMLS_DC);