diff options
| author | Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> | 2025-08-25 08:31:12 +0300 |
|---|---|---|
| committer | Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> | 2025-08-25 08:31:12 +0300 |
| commit | 4d2f5585900c608bb651337b6e5f0f6c2c9d874f (patch) | |
| tree | c1aaa2bd02cc383d636e9ef3c353d516b8b41b78 /scm | |
| parent | c27ba5e6688194e0a635a57cd2ce0a37f213eb92 (diff) | |
scm: clean up scm running
Split run_script / run_repl more clearly; update callers.
Diffstat (limited to 'scm')
| -rw-r--r-- | scm/mu-scm.cc | 119 | ||||
| -rw-r--r-- | scm/mu-scm.hh | 33 |
2 files changed, 76 insertions, 76 deletions
diff --git a/scm/mu-scm.cc b/scm/mu-scm.cc index 40718c2..63cb404 100644 --- a/scm/mu-scm.cc +++ b/scm/mu-scm.cc @@ -133,7 +133,7 @@ std::thread scm_worker; } static Result<void> -prepare_run(const Mu::Options& opts) +prepare_run(const Mu::Options& opts, StrVec& args) { // do a checks _before_ entering guile, so we get a bit more civilized // error message. @@ -147,38 +147,12 @@ prepare_run(const Mu::Options& opts) else return Err(path.error()); - if (opts.scm.script_path) { - const auto path{opts.scm.script_path->c_str()}; - if (const auto res = ::access(path, R_OK); res != 0) { - return Err(Error::Code::InvalidArgument, - "cannot read '{}': {}", path, ::strerror(errno)); - } - } + args = {"mu", "-l", mu_scm_path}; return Ok(); } static void -prepare_script(const Options& opts, StrVec& args) -{ - static std::string cmd; // keep alive - - // XXX: couldn't get another combination of -l/-s/-e/-c to work - // a) invokes `main' with arguments, and - // b) exits (rather than drop to a shell) - // but, what works is to manually specify (main ....) - cmd = "(main " + quote(*opts.scm.script_path); - for (const auto& scriptarg : opts.scm.params) - cmd += " " + quote(scriptarg); - cmd += ")"; - - args.emplace_back("-l"); - args.emplace_back(*opts.scm.script_path); - args.emplace_back("-c"); - args.emplace_back(cmd); -} - -static void maybe_remove_socket_path() { struct stat statbuf{}; @@ -197,25 +171,6 @@ maybe_remove_socket_path() } } -static void -prepare_shell(const Options& opts, StrVec& args) -{ - // drop us into an interactive shell/repl or start listening on a domain socket. - if (opts.scm.listen && opts.scm.socket_path) { - mu_scm_socket_path = *opts.scm.socket_path; - g_setenv(SOCKET_PATH_ENV, mu_scm_socket_path.c_str(), 1); - mu_info("setting up socket-path {}", mu_scm_socket_path); - ::atexit(maybe_remove_socket_path); //opportunistic cleanup - } - else - g_unsetenv(SOCKET_PATH_ENV); - - args.emplace_back("--no-auto-compile"); - args.emplace_back("-l"); - args.emplace_back(mu_scm_repl_path); -} - - struct ModMuData { const Mu::Store& store; const Mu::Options& opts; }; static void @@ -253,36 +208,69 @@ run_scm(const Mu::Store& store, const Mu::Options& opts) } Result<void> -Mu::Scm::run(const Mu::Store& store, const Mu::Options& opts, bool blocking) +Mu::Scm::run_repl(const Mu::Store& store, const Mu::Options& opts, + const std::string& socket_path) { - if (const auto res = prepare_run(opts); !res) + if (const auto res = prepare_run(opts, scm_args); !res) return Err(res.error()); - scm_args = {"mu", "-l", mu_scm_path}; + scm_args.emplace_back("--no-auto-compile"); + scm_args.emplace_back("-l"); + scm_args.emplace_back(mu_scm_repl_path); - // do env stuff _before_ starting guile / threads. - if (opts.scm.script_path) - prepare_script(opts, scm_args); - else - prepare_shell(opts, scm_args); + if (!socket_path.empty()) { + mu_scm_socket_path = socket_path; + g_setenv(SOCKET_PATH_ENV, mu_scm_socket_path.c_str(), 1); + mu_info("setting up socket-path {}", mu_scm_socket_path); + ::atexit(maybe_remove_socket_path); //opportunistic cleanup - // in the non-blocking case, we start guile in a - // background thread; otherwise it will block. - if (!blocking) { + // if a socket-path is provided, run in a background thread + // and offer a REPL on a Unix domain socket on said socket_path auto worker = std::thread([&](){ -#ifdef HAVE_PTHREAD_SETNAME_NP - pthread_setname_np(pthread_self(), "mu-scm"); -#endif /*HAVE_PTHREAD_SETNAME_NP*/ + set_thread_name("mu-scm"); run_scm(store, opts); }); worker.detach(); - } else + } else { // otherwise, a normal, interactive shell + g_unsetenv(SOCKET_PATH_ENV); run_scm(store, opts); + } return Ok(); - } +Result<void> +Mu::Scm::run_script(const Mu::Store& store, const Mu::Options& opts, + const std::string& script_path) +{ + if (script_path.empty()) + return Err(Error::Code::InvalidArgument, "missing script path"); + + if (const auto res = ::access(script_path.c_str(), R_OK); res != 0) + return Err(Error::Code::InvalidArgument, + "cannot read '{}': {}", script_path, ::strerror(errno)); + + if (const auto res = prepare_run(opts, scm_args); !res) + return Err(res.error()); + + // XXX: couldn't get another combination of -l/-s/-e/-c to work + // a) invokes `main' with arguments, and + // b) exits (rather than drop to a shell) + // but, what works is to manually specify (main ....) + std::string cmd = "(main " + quote(script_path); + for (const auto& scriptarg : opts.scm.params) + cmd += " " + quote(scriptarg); + cmd += ")"; + + scm_args.emplace_back("-l"); + scm_args.emplace_back(script_path); + scm_args.emplace_back("-c"); + scm_args.emplace_back(cmd); + + run_scm(store, opts); + + return Ok(); +} #ifdef BUILD_TESTS @@ -325,10 +313,9 @@ test_scm_script() } Mu::Options opts{}; - opts.scm.script_path = join_paths(MU_SCM_SRCDIR, "mu-scm-test.scm"); - { - const auto res = Mu::Scm::run(*store, opts, false /*blocks*/); + const auto script_path{join_paths(MU_SCM_SRCDIR, "mu-scm-test.scm")}; + const auto res = Mu::Scm::run_script(*store, opts, script_path); assert_valid_result(res); } } diff --git a/scm/mu-scm.hh b/scm/mu-scm.hh index 840a76b..e213331 100644 --- a/scm/mu-scm.hh +++ b/scm/mu-scm.hh @@ -40,23 +40,36 @@ */ namespace Mu::Scm { /** - * Start a guile REPL or program + * Start a Guile/SCM REPL * - * Initialize the Scm sub-system, then start a REPL or run a script, - * based on the configuration. + * Initialize the Scm sub-system, then start a REPL, based on the + * configuration. + * + * @param store a Store object + * @param opts options; opts.scm.script_path must be Nothing + * @param socket_path if non-empty, run in the background on the + * socket path (Unix domain socket); otherwise, run an + * interactive shell in blocking mode. + * + * @return Ok() or some error + */ + Result<void> run_repl(const Store& store, const Options& opts, + const std::string& socket_path = {}); + + /** + * Run a Guile/SCM script * - * Unless 'blocking' is false or there is some pre-guile error, this - * method never returns. If blocking is false, it runs in the - * background. + * Initialize the Scm sub-system, then start run a script, + * based on the configuration. * * @param store a Store object - * @param opts options - * @param blocking whether to block (or run in the background) + * @param opts options; opts.scm.script_path must set * * @return Ok() or some error */ - Result<void> run(const Store& store, const Options& opts, - bool blocking=true); + Result<void> run_script(const Store& store, const Options& opts, + const std::string& script_path); + /** * Helpers |
