diff --git a/.gitignore b/.gitignore index 40cdca7..3c5d5dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .vscode -debug # build config.h @@ -22,8 +21,10 @@ build modules # debug +debug test.php header.php composer.json composer.lock vendor +.breakpoints_file.bp diff --git a/README.md b/README.md index 5924f87..b0ba522 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,8 @@ php -e test.php b absolute-file-path lineno ``` +This will also save the breakpoint information in the cache file -- `.breakpoints_file.bp` + ### run ```bash diff --git a/include/util.h b/include/util.h index 1e4d75a..73d01f8 100644 --- a/include/util.h +++ b/include/util.h @@ -38,5 +38,10 @@ class Util static const char *get_prev_executed_filename(); static int get_prev_executed_file_lineno(); static bool is_match(std::string sub_str, std::string target_str); + + static void reload_cache_breakpoint(); + static void clear_breakpoint_cache_file(); + static std::string get_breakpoint_cache_filename(); + static void cache_breakpoint(std::string filename, int lineno); }; } // namespace yasd diff --git a/php_yasd.h b/php_yasd.h index 4aa7a9f..aaa2f97 100644 --- a/php_yasd.h +++ b/php_yasd.h @@ -24,6 +24,14 @@ extern zend_module_entry yasd_module_entry; #define PHP_YASD_VERSION "0.1.0" +ZEND_BEGIN_MODULE_GLOBALS(yasd) + char *breakpoints_file; +ZEND_END_MODULE_GLOBALS(yasd) + +extern ZEND_DECLARE_MODULE_GLOBALS(yasd); + +#define YASD_G(v) (yasd_globals.v) + namespace yasd { namespace function { class ReturnValue { public: diff --git a/src/base.cc b/src/base.cc index 63661ff..74fb3a9 100644 --- a/src/base.cc +++ b/src/base.cc @@ -19,6 +19,8 @@ #include "include/global.h" #include "include/cmder.h" +#include "./php_yasd.h" + #include static void (*old_execute_ex)(zend_execute_data *execute_data); diff --git a/src/cmder.cc b/src/cmder.cc index 73bf32e..6d64151 100644 --- a/src/cmder.cc +++ b/src/cmder.cc @@ -87,6 +87,8 @@ int Cmder::parse_breakpoint_cmd() { global->breakpoints->insert(std::make_pair(filename, lineno_set)); } + yasd::Util::cache_breakpoint(filename, lineno); + yasd::Util::printf_info(yasd::Color::YASD_ECHO_GREEN, "set breakpoint at %s:%d", filename.c_str(), lineno); return RECV_CMD_AGAIN; @@ -132,11 +134,9 @@ int Cmder::parse_info_cmd() { yasd::Util::printf_info(YASD_ECHO_RED, "no found breakpoints!"); } for (auto i = global->breakpoints->begin(); i != global->breakpoints->end(); i++) { - std::cout << "filename: " << i->first << std::endl; for (auto j = i->second.begin(); j != i->second.end(); j++) { - std::cout << *j << ", "; + yasd::Util::printf_info(yasd::Color::YASD_ECHO_GREEN, "filename: %s:%d", i->first.c_str(), *j); } - std::cout << std::endl; } return RECV_CMD_AGAIN; diff --git a/src/util.cc b/src/util.cc index 55d1445..17c7657 100644 --- a/src/util.cc +++ b/src/util.cc @@ -15,11 +15,14 @@ */ #include "include/util.h" #include "include/common.h" +#include "include/global.h" BEGIN_EXTERN_C() #include "php/ext/standard/php_var.h" END_EXTERN_C() +#include "./php_yasd.h" + #include namespace yasd { @@ -187,4 +190,52 @@ bool Util::is_match(std::string sub_str, std::string target_str) { return true; } + +void Util::reload_cache_breakpoint() { + std::string content; + std::fstream file(yasd::Util::get_breakpoint_cache_filename()); + std::string filename; + int lineno; + + while (getline(file, content)) { + auto exploded_content = explode(content, ":"); + if (exploded_content.size() != 2) { + continue; + } + auto iter = global->breakpoints->find(filename); + + filename = exploded_content[0]; + lineno = atoi(exploded_content[1].c_str()); + + yasd::Util::printf_info(yasd::Color::YASD_ECHO_GREEN, "reload breakpoint at %s:%d", filename.c_str(), lineno); + + if (iter != global->breakpoints->end()) { + iter->second.insert(lineno); + } else { + std::set lineno_set; + lineno_set.insert(lineno); + global->breakpoints->insert(std::make_pair(filename, lineno_set)); + } + } +} + +void Util::clear_breakpoint_cache_file() { + // create file and clear file + std::ofstream file(yasd::Util::get_breakpoint_cache_filename()); + file.close(); +} + +std::string Util::get_breakpoint_cache_filename() { + return std::string(YASD_G(breakpoints_file)) + ".bp"; +} + +void Util::cache_breakpoint(std::string filename, int lineno) { + std::ofstream file; + std::string path = get_breakpoint_cache_filename(); + + file.open(path, std::ios_base::app); + file << filename + ":" + std::to_string(lineno) + "\n"; + file.close(); +} + } // namespace yasd diff --git a/yasd.cc b/yasd.cc index 7831071..5b4ac6f 100644 --- a/yasd.cc +++ b/yasd.cc @@ -40,8 +40,10 @@ #include "include/source_reader.h" #include "include/redirect_file_to_cin.h" +ZEND_DECLARE_MODULE_GLOBALS(yasd) + ZEND_BEGIN_ARG_INFO_EX(arginfo_yasd_redirectStdin, 0, 0, 1) - ZEND_ARG_INFO(0, data) +ZEND_ARG_INFO(0, data) ZEND_END_ARG_INFO() PHP_FUNCTION(redirectStdin) { @@ -55,6 +57,16 @@ PHP_FUNCTION(redirectStdin) { global->redirector = new yasd::RedirectFileToCin(file); } +// clang-format off +PHP_INI_BEGIN() +STD_PHP_INI_ENTRY("yasd.breakpoints_file", ".breakpoints_file", PHP_INI_ALL, OnUpdateString, + breakpoints_file, zend_yasd_globals, yasd_globals) +PHP_INI_END() +// clang-format on + +static void php_yasd_init_globals(zend_yasd_globals *yasd_globals) { +} + PHP_RINIT_FUNCTION(yasd) { if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) { return SUCCESS; @@ -72,6 +84,8 @@ PHP_RINIT_FUNCTION(yasd) { cmder->show_welcome_info(); + yasd::Util::reload_cache_breakpoint(); + do { cmd = cmder->get_next_cmd(); if (cmd == "") { @@ -85,6 +99,9 @@ PHP_RINIT_FUNCTION(yasd) { } PHP_MINIT_FUNCTION(yasd) { + ZEND_INIT_MODULE_GLOBALS(yasd, php_yasd_init_globals, nullptr); + REGISTER_INI_ENTRIES(); + return SUCCESS; } @@ -183,7 +200,7 @@ ZEND_DLEXPORT int yasd_zend_startup(zend_extension *extension) { // clang-format off static const zend_function_entry yasd_functions[] = { PHP_FE(redirectStdin, arginfo_yasd_redirectStdin) - PHP_FE_END /* Must be the last line in swoole_functions[] */ + PHP_FE_END /* Must be the last line in yasd_functions[] */ }; // clang-format off