mirror of
https://github.com/ksherlock/mpw-shell.git
synced 2025-01-15 03:30:00 +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;
|
||||
}
|
||||
|
||||
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 &) {
|
||||
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_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_shift(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_version(Environment &e, const std::vector<std::string> &, const fdmask &);
|
||||
|
@ -175,6 +175,7 @@ namespace {
|
||||
{"parameters", builtin_parameters},
|
||||
{"quote", builtin_quote},
|
||||
{"set", builtin_set},
|
||||
{"shift", builtin_shift},
|
||||
{"unexport", builtin_unexport},
|
||||
{"unset", builtin_unset},
|
||||
{"version", builtin_version},
|
||||
|
@ -18,6 +18,22 @@ namespace {
|
||||
if (s.size() == 1 && s == "0") return false;
|
||||
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 {
|
||||
@ -38,6 +54,7 @@ namespace {
|
||||
return _table.find(k);
|
||||
}
|
||||
|
||||
|
||||
void Environment::set(const std::string &key, const std::string &value, bool exported) {
|
||||
std::string k(key);
|
||||
lowercase(k);
|
||||
@ -45,10 +62,65 @@ namespace {
|
||||
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, 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);
|
||||
|
||||
auto iter = _table.find(k);
|
||||
@ -59,15 +131,20 @@ namespace {
|
||||
// if previously exported, keep exported.
|
||||
if (iter->second) v = true;
|
||||
iter->second = std::move(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Environment::unset(const std::string &key) {
|
||||
std::string k(key);
|
||||
lowercase(k);
|
||||
if (k == "echo") _echo = false;
|
||||
if (k == "exit") _exit = false;
|
||||
if (k == "test") _test = false;
|
||||
if (k == "#") _pound = 0;
|
||||
_table.erase(k);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
@ -52,7 +53,11 @@ public:
|
||||
|
||||
//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, long l, bool exported = false);
|
||||
void unset(const std::string &k);
|
||||
void unset();
|
||||
|
||||
@ -62,6 +67,7 @@ public:
|
||||
constexpr bool test() const noexcept { return _test; }
|
||||
constexpr bool exit() const noexcept { return _exit; }
|
||||
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, const std::nothrow_t &);
|
||||
@ -121,9 +127,12 @@ private:
|
||||
|
||||
bool _echo = false;
|
||||
int _status = 0;
|
||||
int _pound = 0;
|
||||
bool _startup = false;
|
||||
bool _passthrough = false;
|
||||
|
||||
void set_common(const std::string &, const std::string &, bool);
|
||||
|
||||
std::unordered_map<std::string, EnvironmentEntry> _table;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user