mirror of
https://github.com/ksherlock/mpw-shell.git
synced 2024-05-28 13:41:34 +00:00
shift builtin.
This commit is contained in:
parent
c8f1e370dc
commit
8a2b9ec3cd
75
builtins.cpp
75
builtins.cpp
|
@ -84,6 +84,81 @@ inline int fputc(int c, int fd) {
|
||||||
auto rv = write(fd, &tmp, 1); return rv < 0 ? EOF : c;
|
auto rv = write(fd, &tmp, 1); return rv < 0 ? EOF : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> load_argv(Environment &env) {
|
||||||
|
std::vector<std::string> rv;
|
||||||
|
int n = env.pound();
|
||||||
|
if ( n <= 0 ) return rv;
|
||||||
|
n = std::min(n, (int)255);
|
||||||
|
rv.reserve(n);
|
||||||
|
|
||||||
|
for (int i = 1; i <= n; ++i) {
|
||||||
|
rv.push_back(env.get(std::to_string(i)));
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int builtin_shift(Environment &env, const std::vector<std::string> &tokens, const fdmask &fds) {
|
||||||
|
|
||||||
|
int n = 1;
|
||||||
|
|
||||||
|
if (tokens.size() > 3) {
|
||||||
|
fputs("### Shift - Too many parameters were specified.\n", stderr);
|
||||||
|
fputs("# Usage - Shift [number]\n", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokens.size() == 2) {
|
||||||
|
|
||||||
|
value v(tokens[1]);
|
||||||
|
if (v.is_number() && v.number >= 0) n = v.number;
|
||||||
|
else {
|
||||||
|
fputs("### Shift - The parameter must be a positive number.\n", stderr);
|
||||||
|
fputs("# Usage - Shift [number]\n", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0) return 0;
|
||||||
|
|
||||||
|
auto argv = load_argv(env);
|
||||||
|
if (argv.empty()) return 0;
|
||||||
|
|
||||||
|
std::move(argv.begin() + n , argv.end(), argv.begin());
|
||||||
|
do {
|
||||||
|
env.unset(std::to_string(argv.size()));
|
||||||
|
argv.pop_back();
|
||||||
|
} while (--n);
|
||||||
|
|
||||||
|
env.set_argv(argv);
|
||||||
|
/*
|
||||||
|
for (unsigned i = 0; i < argv.size(); ++i) {
|
||||||
|
env.set(std::to_string(i+1), argv[i]);
|
||||||
|
}
|
||||||
|
env.set("#", argv.size());
|
||||||
|
|
||||||
|
// fix Parameters and "Parameters"
|
||||||
|
std::string p;
|
||||||
|
for (const auto &s : argv) {
|
||||||
|
p += quote(s);
|
||||||
|
p += " ";
|
||||||
|
}
|
||||||
|
p.pop_back();
|
||||||
|
env.set("\"Parameters\"", p);
|
||||||
|
|
||||||
|
p.clear();
|
||||||
|
|
||||||
|
for (const auto &s : argv) {
|
||||||
|
p += s;
|
||||||
|
p += " ";
|
||||||
|
}
|
||||||
|
p.pop_back();
|
||||||
|
env.set("Parameters", p);
|
||||||
|
*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int builtin_unset(Environment &env, const std::vector<std::string> &tokens, const fdmask &) {
|
int builtin_unset(Environment &env, const std::vector<std::string> &tokens, const fdmask &) {
|
||||||
for (auto iter = tokens.begin() + 1; iter != tokens.end(); ++iter) {
|
for (auto iter = tokens.begin() + 1; iter != tokens.end(); ++iter) {
|
||||||
|
|
|
@ -16,6 +16,7 @@ int builtin_export(Environment &e, const std::vector<std::string> &, const fdmas
|
||||||
int builtin_parameters(Environment &e, const std::vector<std::string> &, const fdmask &);
|
int builtin_parameters(Environment &e, const std::vector<std::string> &, const fdmask &);
|
||||||
int builtin_quote(Environment &e, const std::vector<std::string> &tokens, const fdmask &);
|
int builtin_quote(Environment &e, const std::vector<std::string> &tokens, const fdmask &);
|
||||||
int builtin_set(Environment &e, const std::vector<std::string> &, const fdmask &);
|
int builtin_set(Environment &e, const std::vector<std::string> &, const fdmask &);
|
||||||
|
int builtin_shift(Environment &e, const std::vector<std::string> &, const fdmask &);
|
||||||
int builtin_unexport(Environment &e, const std::vector<std::string> &, const fdmask &);
|
int builtin_unexport(Environment &e, const std::vector<std::string> &, const fdmask &);
|
||||||
int builtin_unset(Environment &e, const std::vector<std::string> &, const fdmask &);
|
int builtin_unset(Environment &e, const std::vector<std::string> &, const fdmask &);
|
||||||
int builtin_version(Environment &e, const std::vector<std::string> &, const fdmask &);
|
int builtin_version(Environment &e, const std::vector<std::string> &, const fdmask &);
|
||||||
|
|
|
@ -175,6 +175,7 @@ namespace {
|
||||||
{"parameters", builtin_parameters},
|
{"parameters", builtin_parameters},
|
||||||
{"quote", builtin_quote},
|
{"quote", builtin_quote},
|
||||||
{"set", builtin_set},
|
{"set", builtin_set},
|
||||||
|
{"shift", builtin_shift},
|
||||||
{"unexport", builtin_unexport},
|
{"unexport", builtin_unexport},
|
||||||
{"unset", builtin_unset},
|
{"unset", builtin_unset},
|
||||||
{"version", builtin_version},
|
{"version", builtin_version},
|
||||||
|
|
|
@ -18,6 +18,22 @@ namespace {
|
||||||
if (s.size() == 1 && s == "0") return false;
|
if (s.size() == 1 && s == "0") return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tf(long v) { return v; }
|
||||||
|
|
||||||
|
// used for #. base 10 only, extra chars ignored.
|
||||||
|
int to_pound_int(const std::string &s) {
|
||||||
|
if (s.empty()) return 0;
|
||||||
|
try {
|
||||||
|
int n = stoi(s);
|
||||||
|
return std::max(n, (int)0);
|
||||||
|
}
|
||||||
|
catch(std::exception e) {}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int to_pound_int(long n) { return std::max(n, (long)0); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Environment::get(const std::string & key) const {
|
std::string Environment::get(const std::string & key) const {
|
||||||
|
@ -38,6 +54,7 @@ namespace {
|
||||||
return _table.find(k);
|
return _table.find(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Environment::set(const std::string &key, const std::string &value, bool exported) {
|
void Environment::set(const std::string &key, const std::string &value, bool exported) {
|
||||||
std::string k(key);
|
std::string k(key);
|
||||||
lowercase(k);
|
lowercase(k);
|
||||||
|
@ -45,10 +62,65 @@ namespace {
|
||||||
if (k == "echo") _echo = tf(value);
|
if (k == "echo") _echo = tf(value);
|
||||||
if (k == "exit") _exit = tf(value);
|
if (k == "exit") _exit = tf(value);
|
||||||
if (k == "test") _test = tf(value);
|
if (k == "test") _test = tf(value);
|
||||||
|
if (k == "#") _pound = to_pound_int(value);
|
||||||
|
|
||||||
// don't need to check {status} because that will be clobbered
|
// don't need to check {status} because that will be clobbered
|
||||||
// by the return value.
|
// by the return value.
|
||||||
|
set_common(k, value, exported);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Environment::set(const std::string &key, long value, bool exported) {
|
||||||
|
std::string k(key);
|
||||||
|
lowercase(k);
|
||||||
|
|
||||||
|
if (k == "echo") _echo = tf(value);
|
||||||
|
if (k == "exit") _exit = tf(value);
|
||||||
|
if (k == "test") _test = tf(value);
|
||||||
|
if (k == "#") _pound = to_pound_int(value);
|
||||||
|
|
||||||
|
// don't need to check {status} because that will be clobbered
|
||||||
|
// by the return value.
|
||||||
|
set_common(k, std::to_string(value), exported);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Environment::set_argv(const std::string &argv0, const std::vector<std::string>& argv) {
|
||||||
|
set_common("0", argv0, false);
|
||||||
|
set_argv(argv);
|
||||||
|
}
|
||||||
|
void Environment::set_argv(const std::vector<std::string>& argv) {
|
||||||
|
_pound = argv.size();
|
||||||
|
set_common("#", std::to_string(argv.size()), false);
|
||||||
|
|
||||||
|
int n = 1;
|
||||||
|
for (const auto &s : argv) {
|
||||||
|
set_common(std::to_string(n++), s, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// parameters, "parameters" ...
|
||||||
|
std::string p;
|
||||||
|
for (const auto &s : argv) {
|
||||||
|
p.push_back('"');
|
||||||
|
p += s;
|
||||||
|
p.push_back('"');
|
||||||
|
p.push_back(' ');
|
||||||
|
}
|
||||||
|
p.pop_back();
|
||||||
|
set_common("\"parameters\"", p, false);
|
||||||
|
p.clear();
|
||||||
|
|
||||||
|
for (const auto &s : argv) {
|
||||||
|
p += s;
|
||||||
|
p.push_back(' ');
|
||||||
|
}
|
||||||
|
p.pop_back();
|
||||||
|
set_common("parameters", p, false);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Environment::set_common(const std::string &k, const std::string &value, bool exported)
|
||||||
|
{
|
||||||
EnvironmentEntry v(value, exported);
|
EnvironmentEntry v(value, exported);
|
||||||
|
|
||||||
auto iter = _table.find(k);
|
auto iter = _table.find(k);
|
||||||
|
@ -59,15 +131,20 @@ namespace {
|
||||||
// if previously exported, keep exported.
|
// if previously exported, keep exported.
|
||||||
if (iter->second) v = true;
|
if (iter->second) v = true;
|
||||||
iter->second = std::move(v);
|
iter->second = std::move(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Environment::unset(const std::string &key) {
|
void Environment::unset(const std::string &key) {
|
||||||
std::string k(key);
|
std::string k(key);
|
||||||
lowercase(k);
|
lowercase(k);
|
||||||
if (k == "echo") _echo = false;
|
if (k == "echo") _echo = false;
|
||||||
if (k == "exit") _exit = false;
|
if (k == "exit") _exit = false;
|
||||||
if (k == "test") _test = false;
|
if (k == "test") _test = false;
|
||||||
|
if (k == "#") _pound = 0;
|
||||||
_table.erase(k);
|
_table.erase(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +53,11 @@ public:
|
||||||
|
|
||||||
//const EnvironmentEntry & lookup(const std::string &s);
|
//const EnvironmentEntry & lookup(const std::string &s);
|
||||||
|
|
||||||
|
void set_argv(const std::string &argv0, const std::vector<std::string>& argv);
|
||||||
|
void set_argv(const std::vector<std::string>& argv);
|
||||||
|
|
||||||
void set(const std::string &k, const std::string &value, bool exported = false);
|
void set(const std::string &k, const std::string &value, bool exported = false);
|
||||||
|
void set(const std::string &k, long l, bool exported = false);
|
||||||
void unset(const std::string &k);
|
void unset(const std::string &k);
|
||||||
void unset();
|
void unset();
|
||||||
|
|
||||||
|
@ -62,6 +67,7 @@ public:
|
||||||
constexpr bool test() const noexcept { return _test; }
|
constexpr bool test() const noexcept { return _test; }
|
||||||
constexpr bool exit() const noexcept { return _exit; }
|
constexpr bool exit() const noexcept { return _exit; }
|
||||||
constexpr int status() const noexcept { return _status; }
|
constexpr int status() const noexcept { return _status; }
|
||||||
|
constexpr int pound() const noexcept { return _pound; }
|
||||||
|
|
||||||
int status(int i, bool throw_up = true);
|
int status(int i, bool throw_up = true);
|
||||||
int status(int i, const std::nothrow_t &);
|
int status(int i, const std::nothrow_t &);
|
||||||
|
@ -121,9 +127,12 @@ private:
|
||||||
|
|
||||||
bool _echo = false;
|
bool _echo = false;
|
||||||
int _status = 0;
|
int _status = 0;
|
||||||
|
int _pound = 0;
|
||||||
bool _startup = false;
|
bool _startup = false;
|
||||||
bool _passthrough = false;
|
bool _passthrough = false;
|
||||||
|
|
||||||
|
void set_common(const std::string &, const std::string &, bool);
|
||||||
|
|
||||||
std::unordered_map<std::string, EnvironmentEntry> _table;
|
std::unordered_map<std::string, EnvironmentEntry> _table;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user