summaryrefslogtreecommitdiff
path: root/scm
diff options
context:
space:
mode:
authorDirk-Jan C. Binnema <djcb@djcbsoftware.nl>2025-08-25 08:31:12 +0300
committerDirk-Jan C. Binnema <djcb@djcbsoftware.nl>2025-08-25 08:31:12 +0300
commit4d2f5585900c608bb651337b6e5f0f6c2c9d874f (patch)
treec1aaa2bd02cc383d636e9ef3c353d516b8b41b78 /scm
parentc27ba5e6688194e0a635a57cd2ce0a37f213eb92 (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.cc119
-rw-r--r--scm/mu-scm.hh33
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