diff options
author | Bob Weinand <bobwei9@hotmail.com> | 2016-10-12 20:19:10 +0200 |
---|---|---|
committer | Anatol Belski <ab@php.net> | 2016-10-14 01:48:03 +0200 |
commit | 11e7447e044fe0b719e38246babbed6e8d56ebf3 (patch) | |
tree | 6ad99f8b4c4c81713c46c48a4ffaf4de0e66e22e | |
parent | a8a11b669d86ee276e0942a5a9d5aa504cf49fd3 (diff) | |
download | php-git-11e7447e044fe0b719e38246babbed6e8d56ebf3.tar.gz |
Merge branch 'PHP-7.0' into PHP-7.1
(cherry picked from commit 37ae5f3931b60c55e5004b6da912c4a957bca274)
-rwxr-xr-x | run-tests.php | 2 | ||||
-rw-r--r-- | sapi/phpdbg/phpdbg.c | 80 | ||||
-rw-r--r-- | sapi/phpdbg/phpdbg_bp.c | 23 | ||||
-rw-r--r-- | sapi/phpdbg/phpdbg_bp.h | 2 | ||||
-rw-r--r-- | sapi/phpdbg/phpdbg_help.c | 24 | ||||
-rw-r--r-- | sapi/phpdbg/phpdbg_list.c | 34 | ||||
-rw-r--r-- | sapi/phpdbg/phpdbg_prompt.c | 123 | ||||
-rw-r--r-- | sapi/phpdbg/phpdbg_prompt.h | 2 | ||||
-rw-r--r-- | sapi/phpdbg/tests/include_once.phpt | 16 | ||||
-rw-r--r-- | sapi/phpdbg/tests/set_exception_handler.phpt | 19 | ||||
-rw-r--r-- | sapi/phpdbg/tests/stdin_001.phpt | 25 |
11 files changed, 304 insertions, 46 deletions
diff --git a/run-tests.php b/run-tests.php index 80757edd90..41a061666b 100755 --- a/run-tests.php +++ b/run-tests.php @@ -127,7 +127,7 @@ if (getenv('TEST_PHP_EXECUTABLE')) { $phpdbg = $cwd . '/sapi/phpdbg/phpdbg'; if (file_exists($phpdbg)) { - putenv("TEST_PHP_CGI_EXECUTABLE=$phpdbg"); + putenv("TEST_PHPDBG_EXECUTABLE=$phpdbg"); } else { $phpdbg = null; } diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index bda5b5619f..be50de8070 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -127,6 +127,7 @@ static void php_phpdbg_destroy_file_source(zval *data) /* {{{ */ if (source->buf) { efree(source->buf); } + efree(source->filename); efree(source); } /* }}} */ @@ -373,7 +374,7 @@ static PHP_FUNCTION(phpdbg_break_file) return; } - phpdbg_set_breakpoint_file(file, line); + phpdbg_set_breakpoint_file(file, 0, line); } /* }}} */ /* {{{ proto void phpdbg_break_method(string class, string method) */ @@ -1076,6 +1077,7 @@ const opt_struct OPTIONS[] = { /* {{{ */ {'r', 0, "run"}, {'e', 0, "generate ext_stmt opcodes"}, {'E', 0, "step-through-eval"}, + {'s', 1, "script from stdin"}, {'S', 1, "sapi-name"}, #ifndef _WIN32 {'l', 1, "listen"}, @@ -1374,6 +1376,8 @@ int main(int argc, char **argv) /* {{{ */ zend_bool ext_stmt = 0; zend_bool is_exit; int exit_status; + char *read_from_stdin = NULL; + zend_string *backup_phpdbg_compile = NULL; #ifndef _WIN32 struct sigaction sigio_struct; @@ -1482,6 +1486,12 @@ phpdbg_main: /* begin phpdbg options */ + case 's': { /* read script from stdin */ + if (settings == NULL) { + read_from_stdin = strdup(php_optarg); + } + } break; + case 'S': { /* set SAPI name */ sapi_name = strdup(php_optarg); } break; @@ -1593,8 +1603,10 @@ phpdbg_main: php_optarg = NULL; } + quit_immediately = phpdbg_startup_run > 1; + /* set exec if present on command line */ - if (argc > php_optind && (strcmp(argv[php_optind-1], "--") != SUCCESS)) { + if (!read_from_stdin && argc > php_optind && (strcmp(argv[php_optind-1], "--") != SUCCESS)) { if (!exec && strlen(argv[php_optind])) { exec = strdup(argv[php_optind]); } @@ -1849,13 +1861,6 @@ phpdbg_main: if (init_file) { phpdbg_init(init_file, init_file_len, init_file_default); } - if (bp_tmp) { - PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT; - phpdbg_string_init(bp_tmp); - free(bp_tmp); - bp_tmp = NULL; - PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT; - } } zend_end_try(); PHPDBG_G(flags) &= ~PHPDBG_IS_INITIALIZING; @@ -1865,18 +1870,55 @@ phpdbg_main: } /* auto compile */ - if (PHPDBG_G(exec)) { + if (read_from_stdin) { + if (!read_from_stdin[0]) { + if (!quit_immediately) { + phpdbg_error("error", "", "Impossible to not specify a stdin delimiter without -rr"); + PHPDBG_G(flags) |= PHPDBG_IS_QUITTING; + goto phpdbg_out; + } + } + if (show_banner || read_from_stdin[0]) { + phpdbg_notice("stdin", "delimiter=\"%s\"", "Reading input from stdin; put '%s' followed by a newline on an own line after code to end input", read_from_stdin); + } + + if (phpdbg_startup_run > 0) { + PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT; + } + + zend_try { + phpdbg_param_t cmd; + cmd.str = read_from_stdin; + cmd.len = strlen(read_from_stdin); + PHPDBG_COMMAND_HANDLER(stdin)(&cmd); + } zend_end_try(); + + PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT; + } else if (PHPDBG_G(exec)) { if (settings || phpdbg_startup_run > 0) { PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT; } zend_try { - phpdbg_compile(); + if (backup_phpdbg_compile) { + phpdbg_compile_stdin(backup_phpdbg_compile); + } else { + phpdbg_compile(); + } } zend_end_try(); + backup_phpdbg_compile = NULL; PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT; } + if (bp_tmp) { + PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT | PHPDBG_IS_INITIALIZING; + phpdbg_string_init(bp_tmp); + free(bp_tmp); + bp_tmp = NULL; + PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT & ~PHPDBG_IS_INITIALIZING; + } + if (settings == (void *) 0x1) { if (PHPDBG_G(ops)) { phpdbg_print_opcodes(print_opline_func); @@ -1898,7 +1940,6 @@ phpdbg_interact: do { zend_try { if (phpdbg_startup_run) { - quit_immediately = phpdbg_startup_run > 1; phpdbg_startup_run = 0; if (quit_immediately) { PHPDBG_G(flags) = (PHPDBG_G(flags) & ~PHPDBG_HAS_PAGINATION) | PHPDBG_IS_INTERACTIVE | PHPDBG_PREVENT_INTERACTIVE; @@ -2073,6 +2114,12 @@ phpdbg_out: wrapper->wops->stream_opener = PHPDBG_G(orig_url_wrap_php); } + if (PHPDBG_G(exec) && !memcmp("-", PHPDBG_G(exec), 2)) { /* i.e. execution context has been read from stdin - back it up */ + phpdbg_file_source *data = zend_hash_str_find_ptr(&PHPDBG_G(file_sources), PHPDBG_G(exec), PHPDBG_G(exec_len)); + backup_phpdbg_compile = zend_string_alloc(data->len + 2, 1); + sprintf(ZSTR_VAL(backup_phpdbg_compile), "?>%.*s", (int) data->len, data->buf); + } + zend_try { php_module_shutdown(); } zend_end_try(); @@ -2097,6 +2144,11 @@ phpdbg_out: free(sapi_name); } + if (read_from_stdin) { + free(read_from_stdin); + read_from_stdin = NULL; + } + #ifdef ZTS tsrm_shutdown(); #endif @@ -2108,6 +2160,10 @@ phpdbg_out: goto phpdbg_main; } + if (backup_phpdbg_compile) { + zend_string_free(backup_phpdbg_compile); + } + #ifndef _WIN32 if (address) { free(address); diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index 4cb1dae42c..da4c8f71bf 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -230,7 +230,7 @@ PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str) /* {{{ */ } } /* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num) /* {{{ */ +PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, size_t path_len, long line_num) /* {{{ */ { php_stream_statbuf ssb; char realpath[MAXPATHLEN]; @@ -240,10 +240,11 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num) /* { HashTable *broken, *file_breaks = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE]; phpdbg_breakfile_t new_break; - size_t path_len = 0L; - if (VCWD_REALPATH(path, realpath)) { - path = realpath; + if (!path_len) { + if (VCWD_REALPATH(path, realpath)) { + path = realpath; + } } path_len = strlen(path); @@ -886,21 +887,13 @@ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array *op_ { HashTable *breaks; phpdbg_breakbase_t *brake; - size_t path_len; - char realpath[MAXPATHLEN]; - const char *path = ZSTR_VAL(op_array->filename); - - if (VCWD_REALPATH(path, realpath)) { - path = realpath; - } - - path_len = strlen(path); #if 0 - phpdbg_debug("Op at: %.*s %d\n", path_len, path, (*EG(opline_ptr))->lineno); + phpdbg_debug("Op at: %.*s %d\n", ZSTR_LEN(op_array->filename), ZSTR_VAL(op_array->filename), (*EG(opline_ptr))->lineno); #endif - if (!(breaks = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], path, path_len))) { + /* NOTE: realpath resolution should have happened at compile time - no reason to do it here again */ + if (!(breaks = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], op_array->filename))) { return NULL; } diff --git a/sapi/phpdbg/phpdbg_bp.h b/sapi/phpdbg/phpdbg_bp.h index abbcc4d5df..7daafe48c1 100644 --- a/sapi/phpdbg/phpdbg_bp.h +++ b/sapi/phpdbg/phpdbg_bp.h @@ -125,7 +125,7 @@ PHPDBG_API HashTable *phpdbg_resolve_pending_file_break_ex(const char *file, uin PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file); /* }}} */ /* {{{ Breakpoint Creation API */ -PHPDBG_API void phpdbg_set_breakpoint_file(const char* filename, long lineno); +PHPDBG_API void phpdbg_set_breakpoint_file(const char* filename, size_t path_len, long lineno); PHPDBG_API void phpdbg_set_breakpoint_symbol(const char* func_name, size_t func_name_len); PHPDBG_API void phpdbg_set_breakpoint_method(const char* class_name, const char* func_name); PHPDBG_API void phpdbg_set_breakpoint_opcode(const char* opname, size_t opname_len); diff --git a/sapi/phpdbg/phpdbg_help.c b/sapi/phpdbg/phpdbg_help.c index a3bcbd10a1..0943a7ea2c 100644 --- a/sapi/phpdbg/phpdbg_help.c +++ b/sapi/phpdbg/phpdbg_help.c @@ -339,6 +339,7 @@ phpdbg_help_text_t phpdbg_help_text[] = { "**Starting and Stopping Execution**" CR " **exec** set execution context" CR +" **stdin** set executing script from stdin" CR " **run** attempt execution" CR " **step** continue execution until other line is reached" CR " **continue** continue execution" CR @@ -387,6 +388,7 @@ phpdbg_help_text_t phpdbg_help_text[] = { " **-rr** Run execution context and quit after execution (not respecting breakpoints)" CR " **-e** Generate extended information for debugger/profiler" CR " **-E** Enable step through eval, careful!" CR +" **-s** **-s=**, **-s**=foo Read code to execute from stdin with an optional delimiter" 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 @@ -397,6 +399,13 @@ phpdbg_help_text_t phpdbg_help_text[] = { " **--** **--** arg1 arg2 Use to delimit phpdbg arguments and php $argv; append any $argv " "argument after it" CR CR +"**Reading from stdin**" CR CR + +"The **-s** option allows inputting a script to execute directly from stdin. The given delimiter " +"(\"foo\" in the example) needs to be specified at the end of the input on its own line, followed by " +"a line break. If **-rr** has been specified, it is allowed to omit the delimiter (**-s=**) and " +"it will read until EOF. See also the help entry for the **stdin** command." CR CR + "**Remote Console Mode**" CR CR "This mode is enabled by specifying the **-a** option. Phpdbg will bind only to the loopback " @@ -635,6 +644,21 @@ phpdbg_help_text_t phpdbg_help_text[] = { " Set the execution context to **/tmp/script.php**" }, +{"stdin", +"The **stdin** command takes a string serving as delimiter. It will then read all the input from " +"stdin until encountering the given delimiter on a standalone line. It can also be passed at " +"startup using the **-s=** command line option (the delimiter then is optional if **-rr** is " +"also passed - in that case it will just read until EOF)." CR +"This input will be then compiled as PHP code and set as execution context." CR CR + +"**Example**" CR CR + +" $P stdin foo" CR +" <?php" CR +" echo \"Hello, world!\\n\";" CR +" foo" +}, + //*********** 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 " diff --git a/sapi/phpdbg/phpdbg_list.c b/sapi/phpdbg/phpdbg_list.c index 86a2132b74..4d5e7dd8f8 100644 --- a/sapi/phpdbg/phpdbg_list.c +++ b/sapi/phpdbg/phpdbg_list.c @@ -62,9 +62,15 @@ PHPDBG_LIST(lines) /* {{{ */ } break; case FILE_PARAM: { - zend_string *file = zend_string_init(param->file.name, strlen(param->file.name), 0); + zend_string *file; + char resolved_path_buf[MAXPATHLEN]; + const char *abspath = param->file.name; + if (VCWD_REALPATH(abspath, resolved_path_buf)) { + abspath = resolved_path_buf; + } + file = zend_string_init(abspath, strlen(abspath), 0); phpdbg_list_file(file, param->file.line, 0, 0); - efree(file); + zend_string_release(file); } break; phpdbg_default_switch_case(); @@ -127,16 +133,8 @@ void phpdbg_list_file(zend_string *filename, uint count, int offset, uint highli { uint line, lastline; phpdbg_file_source *data; - char resolved_path_buf[MAXPATHLEN]; - const char *abspath; - - if (VCWD_REALPATH(ZSTR_VAL(filename), resolved_path_buf)) { - abspath = resolved_path_buf; - } else { - abspath = ZSTR_VAL(filename); - } - if (!(data = zend_hash_str_find_ptr(&PHPDBG_G(file_sources), abspath, strlen(abspath)))) { + if (!(data = zend_hash_find_ptr(&PHPDBG_G(file_sources), filename))) { phpdbg_error("list", "type=\"unknownfile\"", "Could not find information about included file..."); return; } @@ -288,6 +286,7 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) { return NULL; } + dataptr->filename = estrdup(dataptr->filename); dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line); zend_hash_str_add_ptr(&PHPDBG_G(file_sources), filename, strlen(filename), dataptr); phpdbg_resolve_pending_file_break(filename); @@ -306,6 +305,17 @@ zend_op_array *phpdbg_init_compile_file(zend_file_handle *file, int type) { if (VCWD_REALPATH(filename, resolved_path_buf)) { filename = resolved_path_buf; + + if (file->opened_path) { + zend_string_release(file->opened_path); + file->opened_path = zend_string_init(filename, strlen(filename), 0); + } else { + if (file->free_filename) { + efree((char *) file->filename); + } + file->free_filename = 1; + file->filename = estrdup(filename); + } } op_array = PHPDBG_G(init_compile_file)(file, type); @@ -356,7 +366,7 @@ zend_op_array *phpdbg_compile_string(zval *source_string, char *filename) { return NULL; } - fake_name = strpprintf(0, "%s\0%p", filename, op_array->opcodes); + fake_name = strpprintf(0, "%s%c%p", filename, 0, op_array->opcodes); dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line); zend_hash_add_ptr(&PHPDBG_G(file_sources), fake_name, dataptr); diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index de81450eac..367d7ef93d 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -26,7 +26,9 @@ #include "zend_vm.h" #include "zend_generators.h" #include "zend_interfaces.h" +#include "zend_smart_str.h" #include "phpdbg.h" +#include "phpdbg_io.h" #include "phpdbg_help.h" #include "phpdbg_print.h" @@ -68,6 +70,7 @@ extern int phpdbg_startup_run; /* {{{ command declarations */ const phpdbg_command_t phpdbg_prompt_commands[] = { PHPDBG_COMMAND_D(exec, "set execution context", 'e', NULL, "s", 0), + PHPDBG_COMMAND_D(stdin, "read script from stdin", 0 , NULL, "s", 0), PHPDBG_COMMAND_D(step, "step through execution", 's', NULL, 0, PHPDBG_ASYNC_SAFE), PHPDBG_COMMAND_D(continue, "continue execution", 'c', NULL, 0, PHPDBG_ASYNC_SAFE), PHPDBG_COMMAND_D(run, "attempt execution", 'r', NULL, "|s", 0), @@ -459,6 +462,111 @@ PHPDBG_COMMAND(exec) /* {{{ */ return SUCCESS; } /* }}} */ +PHPDBG_COMMAND(stdin) +{ + smart_str code = {0}; + char *buf; + char *sep = param->str; + int seplen = param->len; + int bytes = 0; + + smart_str_appends(&code, "?>"); + + do { + PHPDBG_G(input_buflen) += bytes; + if (PHPDBG_G(input_buflen) <= 0) { + continue; + } + + if (sep && seplen) { + char *nl = buf = PHPDBG_G(input_buffer); + do { + if (buf == nl + seplen) { + if (!memcmp(sep, nl, seplen) && (*buf == '\n' || (*buf == '\r' && buf[1] == '\n'))) { + smart_str_appendl(&code, PHPDBG_G(input_buffer), nl - PHPDBG_G(input_buffer)); + memmove(PHPDBG_G(input_buffer), ++buf, --PHPDBG_G(input_buflen)); + goto exec_code; + } + } + if (*buf == '\n') { + nl = buf + 1; + } + buf++; + } while (--PHPDBG_G(input_buflen)); + if (buf != nl && buf <= nl + seplen) { + smart_str_appendl(&code, PHPDBG_G(input_buffer), nl - PHPDBG_G(input_buffer)); + PHPDBG_G(input_buflen) = buf - nl; + memmove(PHPDBG_G(input_buffer), nl, PHPDBG_G(input_buflen)); + } else { + PHPDBG_G(input_buflen) = 0; + smart_str_appendl(&code, PHPDBG_G(input_buffer), buf - PHPDBG_G(input_buffer)); + } + } else { + smart_str_appendl(&code, PHPDBG_G(input_buffer), PHPDBG_G(input_buflen)); + PHPDBG_G(input_buflen) = 0; + } + } while ((bytes = phpdbg_mixed_read(PHPDBG_G(io)[PHPDBG_STDIN].fd, PHPDBG_G(input_buffer) + PHPDBG_G(input_buflen), PHPDBG_MAX_CMD - PHPDBG_G(input_buflen), -1)) > 0); + + if (bytes < 0) { + PHPDBG_G(flags) |= PHPDBG_IS_QUITTING | PHPDBG_IS_DISCONNECTED; + zend_bailout(); + } + +exec_code: + smart_str_0(&code); + + if (phpdbg_compile_stdin(code.s) == FAILURE) { + zend_exception_error(EG(exception), E_ERROR); + zend_bailout(); + } + + return SUCCESS; +} /* }}} */ + +int phpdbg_compile_stdin(zend_string *code) { + zval zv; + + ZVAL_STR(&zv, code); + + PHPDBG_G(ops) = zend_compile_string(&zv, "-"); + + zend_string_release(code); + + if (EG(exception)) { + return FAILURE; + } + + if (PHPDBG_G(exec)) { + efree(PHPDBG_G(exec)); + } + PHPDBG_G(exec) = estrdup("-"); + PHPDBG_G(exec_len) = 1; + { /* remove leading ?> from source */ + int i; + zend_string *source_path = zend_strpprintf(0, "-%c%p", 0, PHPDBG_G(ops)->opcodes); + phpdbg_file_source *data = zend_hash_find_ptr(&PHPDBG_G(file_sources), source_path); + dtor_func_t dtor = PHPDBG_G(file_sources).pDestructor; + PHPDBG_G(file_sources).pDestructor = NULL; + zend_hash_del(&PHPDBG_G(file_sources), source_path); + PHPDBG_G(file_sources).pDestructor = dtor; + zend_hash_str_update_ptr(&PHPDBG_G(file_sources), "-", 1, data); + zend_string_release(source_path); + + efree(data->filename); + data->filename = estrdup("-"); + + for (i = 1; i <= data->lines; i++) { + data->line[i] -= 2; + } + data->len -= 2; + memmove(data->buf, data->buf + 2, data->len); + } + + phpdbg_notice("compile", "context=\"-\"", "Successful compilation of stdin input"); + + return SUCCESS; +} + int phpdbg_compile(void) /* {{{ */ { zend_file_handle fh; @@ -1066,16 +1174,21 @@ PHPDBG_COMMAND(set) /* {{{ */ PHPDBG_COMMAND(break) /* {{{ */ { if (!param) { - phpdbg_set_breakpoint_file( - zend_get_executed_filename(), - zend_get_executed_lineno()); + if (PHPDBG_G(exec)) { + phpdbg_set_breakpoint_file( + zend_get_executed_filename(), + strlen(zend_get_executed_filename()), + zend_get_executed_lineno()); + } else { + phpdbg_error("inactive", "type=\"noexec\"", "Execution context not set!"); + } } else switch (param->type) { case ADDR_PARAM: phpdbg_set_breakpoint_opline(param->addr); break; case NUMERIC_PARAM: if (PHPDBG_G(exec)) { - phpdbg_set_breakpoint_file(phpdbg_current_file(), param->num); + phpdbg_set_breakpoint_file(phpdbg_current_file(), strlen(phpdbg_current_file()), param->num); } else { phpdbg_error("inactive", "type=\"noexec\"", "Execution context not set!"); } @@ -1090,7 +1203,7 @@ PHPDBG_COMMAND(break) /* {{{ */ phpdbg_set_breakpoint_function_opline(param->str, param->num); break; case FILE_PARAM: - phpdbg_set_breakpoint_file(param->file.name, param->file.line); + phpdbg_set_breakpoint_file(param->file.name, 0, param->file.line); break; case NUMERIC_FILE_PARAM: phpdbg_set_breakpoint_file_opline(param->file.name, param->file.line); diff --git a/sapi/phpdbg/phpdbg_prompt.h b/sapi/phpdbg/phpdbg_prompt.h index e5a0286af1..e9df703715 100644 --- a/sapi/phpdbg/phpdbg_prompt.h +++ b/sapi/phpdbg/phpdbg_prompt.h @@ -27,11 +27,13 @@ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default); void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init); int phpdbg_interactive(zend_bool allow_async_unsafe, char *input); int phpdbg_compile(void); +int phpdbg_compile_stdin(zend_string *code); void phpdbg_force_interruption(void); /* }}} */ /* {{{ phpdbg command handlers */ PHPDBG_COMMAND(exec); +PHPDBG_COMMAND(stdin); PHPDBG_COMMAND(step); PHPDBG_COMMAND(continue); PHPDBG_COMMAND(run); diff --git a/sapi/phpdbg/tests/include_once.phpt b/sapi/phpdbg/tests/include_once.phpt new file mode 100644 index 0000000000..0a00e04cde --- /dev/null +++ b/sapi/phpdbg/tests/include_once.phpt @@ -0,0 +1,16 @@ +--TEST-- +include_once must include only once +--PHPDBG-- +r +q +--EXPECTF-- +[Successful compilation of %s] +prompt> 1 +[Script ended normally] +prompt> +--FILE-- +<?php + +include_once __DIR__.'/include.inc'; +include_once __DIR__.'/include.inc'; + diff --git a/sapi/phpdbg/tests/set_exception_handler.phpt b/sapi/phpdbg/tests/set_exception_handler.phpt new file mode 100644 index 0000000000..7d4d4faca0 --- /dev/null +++ b/sapi/phpdbg/tests/set_exception_handler.phpt @@ -0,0 +1,19 @@ +--TEST-- +set_exception_handler() in phpdbg +--PHPDBG-- +r +c +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Uncaught Exception in %s on line 4: test] +>00004: throw new Exception("test"); + 00005: +prompt> EX +[Script ended normally] +prompt> +--FILE-- +<?php + +set_exception_handler(function () { print "EX\n"; }); +throw new Exception("test"); diff --git a/sapi/phpdbg/tests/stdin_001.phpt b/sapi/phpdbg/tests/stdin_001.phpt new file mode 100644 index 0000000000..0bc940caef --- /dev/null +++ b/sapi/phpdbg/tests/stdin_001.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test stdin input with breakpoints +--PHPDBG-- +stdin foo +<?php + +echo "Hello, world!\n"; +foo +b 3 +r +c +r +q +--EXPECTF-- +prompt> [Successful compilation of stdin input] +prompt> [Breakpoint #0 added at -:3] +prompt> [Breakpoint #0 at -:3, hits: 1] +>00003: echo "Hello, world!\n"; + 00004: +prompt> Hello, world! +[Script ended normally] +prompt> [Breakpoint #0 at -:3, hits: 1] +>00003: echo "Hello, world!\n"; + 00004: +prompt>
\ No newline at end of file |