From 70314b3303f712a0277b80b23bc3613744e6178e Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 1 Jun 2020 19:51:17 +0300 Subject: Add builtin weight Also invent the notion of external builtin (builtin_info::function is NULL). --- libbutl/builtin.cxx | 29 +++++++++++++++-------------- libbutl/builtin.mxx | 27 +++++++++++++++++++++++---- libbutl/command.cxx | 20 ++++++++++---------- tests/builtin/driver.cxx | 12 +++++++++--- 4 files changed, 57 insertions(+), 31 deletions(-) diff --git a/libbutl/builtin.cxx b/libbutl/builtin.cxx index 9efa697..fe74b05 100644 --- a/libbutl/builtin.cxx +++ b/libbutl/builtin.cxx @@ -2109,19 +2109,20 @@ namespace butl const builtin_map builtins { - {"cat", &async_impl<&cat>}, - {"cp", &sync_impl<&cp>}, - {"echo", &async_impl<&echo>}, - {"false", &false_}, - {"ln", &sync_impl<&ln>}, - {"mkdir", &sync_impl<&mkdir>}, - {"mv", &sync_impl<&mv>}, - {"rm", &sync_impl<&rm>}, - {"rmdir", &sync_impl<&rmdir>}, - {"sed", &async_impl<&sed>}, - {"sleep", &sync_impl<&sleep>}, - {"test", &sync_impl<&test>}, - {"touch", &sync_impl<&touch>}, - {"true", &true_} + {"cat", {&async_impl<&cat>, 2}}, + {"cp", {&sync_impl<&cp>, 2}}, + {"diff", {nullptr, 2}}, + {"echo", {&async_impl<&echo>, 2}}, + {"false", {&false_, 0}}, + {"ln", {&sync_impl<&ln>, 2}}, + {"mkdir", {&sync_impl<&mkdir>, 2}}, + {"mv", {&sync_impl<&mv>, 2}}, + {"rm", {&sync_impl<&rm>, 1}}, + {"rmdir", {&sync_impl<&rmdir>, 1}}, + {"sed", {&async_impl<&sed>, 2}}, + {"sleep", {&sync_impl<&sleep>, 1}}, + {"test", {&sync_impl<&test>, 1}}, + {"touch", {&sync_impl<&touch>, 2}}, + {"true", {&true_, 0}} }; } diff --git a/libbutl/builtin.mxx b/libbutl/builtin.mxx index 2be2f90..e4dd4f8 100644 --- a/libbutl/builtin.mxx +++ b/libbutl/builtin.mxx @@ -153,19 +153,38 @@ LIBBUTL_MODEXPORT namespace butl const dir_path& cwd, const builtin_callbacks&); - class builtin_map: public std::map + // Builtin function and weight. + // + // The weight between 0 and 2 reflects the builtin's contribution to the + // containing script semantics with 0 being the lowest/ignore. Current + // mapping is as follows: + // + // 0 - non-contributing (true, false) + // 1 - non-creative (rm, rmdir, sleep, test) + // 2 - creative (any builtin that may produce output) + // + // If the function is NULL, then the builtin has an external implementation + // and should be executed by running the program with this name. + // + struct builtin_info + { + builtin_function* function; + uint8_t weight; + }; + + class builtin_map: public std::map { public: - using base = std::map; + using base = std::map; using base::base; // Return NULL if not a builtin. // - builtin_function* + const builtin_info* find (const std::string& n) const { auto i (base::find (n)); - return i != end () ? i->second : nullptr; + return i != end () ? &i->second : nullptr; } }; diff --git a/libbutl/command.cxx b/libbutl/command.cxx index bb5287c..fadd617 100644 --- a/libbutl/command.cxx +++ b/libbutl/command.cxx @@ -227,9 +227,9 @@ namespace butl msg.c_str ()); } - builtin_function* bf (builtins.find (prog)); + const builtin_info* bi (builtins.find (prog)); - if (bf != nullptr) // Execute the builtin. + if (bi != nullptr && bi->function != nullptr) // Execute the builtin. { if (callback) { @@ -259,17 +259,17 @@ namespace butl uint8_t r; // Storage. builtin_callbacks cb; - builtin b (bf (r, - args, - nullfd /* stdin */, - move (rd) /* stdout */, - nullfd /* stderr */, - cwd, - cb)); + builtin b (bi->function (r, + args, + nullfd /* stdin */, + move (rd) /* stdout */, + nullfd /* stderr */, + cwd, + cb)); return process_exit (b.wait ()); } - else // Execute the program. + else // Execute the program. { // Strip the potential leading `^`, indicating that this is an external // program rather than a builtin. Consider only simple paths and don't diff --git a/tests/builtin/driver.cxx b/tests/builtin/driver.cxx index 2583ba2..9fb6d6f 100644 --- a/tests/builtin/driver.cxx +++ b/tests/builtin/driver.cxx @@ -144,15 +144,21 @@ main (int argc, char* argv[]) // Execute the builtin. // - builtin_function* bf (builtins.find (name)); + const builtin_info* bi (builtins.find (name)); - if (bf == nullptr) + if (bi == nullptr) { cerr << "unknown builtin '" << name << "'" << endl; return 1; } + if (bi->function == nullptr) + { + cerr << "external builtin '" << name << "'" << endl; + return 1; + } + uint8_t r; // Storage. - builtin b (bf (r, args, nullfd, nullfd, nullfd, cwd, callbacks)); + builtin b (bi->function (r, args, nullfd, nullfd, nullfd, cwd, callbacks)); return b.wait (); } -- cgit v1.1