throw error for {exit}
This commit is contained in:
parent
6f482d73df
commit
6d9e5dc78c
117
command.cpp
117
command.cpp
|
@ -113,18 +113,18 @@ command::~command()
|
|||
* echo and error should respect the active fdmask.
|
||||
*/
|
||||
|
||||
int simple_command::execute(Environment &env, const fdmask &fds) {
|
||||
int simple_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
||||
std::string s = expand_vars(text, env);
|
||||
|
||||
if (env.echo()) fprintf(stderr, " %s\n", s.c_str());
|
||||
env.echo("%s", s.c_str());
|
||||
|
||||
process p;
|
||||
try {
|
||||
auto tokens = tokenize(s, false);
|
||||
parse_tokens(std::move(tokens), p);
|
||||
} catch(std::exception &e) {
|
||||
fprintf(stderr, "%s", e.what());
|
||||
return env.status(-4);
|
||||
fprintf(stderr, "%s\n", e.what());
|
||||
return env.status(-4, throwup);
|
||||
}
|
||||
|
||||
if (p.arguments.empty()) return 0;
|
||||
|
@ -137,7 +137,7 @@ int simple_command::execute(Environment &env, const fdmask &fds) {
|
|||
auto iter = builtins.find(name);
|
||||
if (iter != builtins.end()) {
|
||||
int status = iter->second(env, p.arguments, newfds);
|
||||
return env.status(status);
|
||||
return env.status(status, throwup);
|
||||
}
|
||||
|
||||
if (env.test()) return env.status(0);
|
||||
|
@ -148,54 +148,56 @@ int simple_command::execute(Environment &env, const fdmask &fds) {
|
|||
|
||||
int status = execute_external(env, p.arguments, newfds);
|
||||
|
||||
return env.status(status);
|
||||
return env.status(status, throwup);
|
||||
}
|
||||
|
||||
int evaluate_command::execute(Environment &env, const fdmask &fds) {
|
||||
int evaluate_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
||||
|
||||
std::string s = expand_vars(text, env);
|
||||
|
||||
if (env.echo()) fprintf(stderr, " %s\n", s.c_str());
|
||||
env.echo("%s", s.c_str());
|
||||
|
||||
auto tokens = tokenize(s, true);
|
||||
if (tokens.empty()) return 0;
|
||||
try {
|
||||
auto tokens = tokenize(s, true);
|
||||
if (tokens.empty()) return 0;
|
||||
|
||||
int status = builtin_evaluate(env, std::move(tokens), fds);
|
||||
int status = builtin_evaluate(env, std::move(tokens), fds);
|
||||
|
||||
return env.status(status);
|
||||
return env.status(status, throwup);
|
||||
} catch (std::exception &e) {
|
||||
fprintf(stderr, "%s\n", e.what());
|
||||
return env.status(1, throwup);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int or_command::execute(Environment &e, const fdmask &fds) {
|
||||
int or_command::execute(Environment &e, const fdmask &fds, bool throwup) {
|
||||
|
||||
int rv = 0;
|
||||
bool pv = e.and_or(true);
|
||||
|
||||
for (auto &c : children) {
|
||||
rv = c->execute(e, fds);
|
||||
if (!c) continue;
|
||||
rv = c->execute(e, fds, false);
|
||||
if (rv == 0) return rv;
|
||||
}
|
||||
e.and_or(pv);
|
||||
|
||||
return e.status(rv);
|
||||
}
|
||||
|
||||
int and_command::execute(Environment &e, const fdmask &fds) {
|
||||
int and_command::execute(Environment &e, const fdmask &fds, bool throwup) {
|
||||
|
||||
int rv = 0;
|
||||
bool pv = e.and_or(true);
|
||||
|
||||
for (auto &c : children) {
|
||||
rv = c->execute(e, fds);
|
||||
if (!c) continue;
|
||||
c->execute(e, fds, false);
|
||||
if (rv != 0) return rv;
|
||||
}
|
||||
e.and_or(pv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
int vector_command::execute(Environment &e, const fdmask &fds) {
|
||||
int vector_command::execute(Environment &e, const fdmask &fds, bool throwup) {
|
||||
|
||||
int rv = 0;
|
||||
for (auto &c : children) {
|
||||
|
@ -206,10 +208,10 @@ int vector_command::execute(Environment &e, const fdmask &fds) {
|
|||
return e.status(rv);
|
||||
}
|
||||
|
||||
int error_command::execute(Environment &e, const fdmask &fds) {
|
||||
int error_command::execute(Environment &e, const fdmask &fds, bool throwup) {
|
||||
std::string s = expand_vars(text, e);
|
||||
|
||||
if (e.echo()) fprintf(stderr, " %s\n", s.c_str());
|
||||
e.echo("%s", s.c_str());
|
||||
|
||||
switch(type) {
|
||||
case END:
|
||||
|
@ -249,14 +251,14 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
int begin_command::execute(Environment &env, const fdmask &fds) {
|
||||
int begin_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
||||
// todo -- parse end for redirection.
|
||||
|
||||
std::string b = expand_vars(begin, env);
|
||||
std::string e = expand_vars(end, env);
|
||||
|
||||
// echo!
|
||||
if (env.echo()) fprintf(stderr, " %s ... %s\n",
|
||||
env.echo("%s ... %s",
|
||||
b.c_str(),
|
||||
e.c_str()
|
||||
);
|
||||
|
@ -276,8 +278,13 @@ int begin_command::execute(Environment &env, const fdmask &fds) {
|
|||
newfds |= fds;
|
||||
if (status) return env.status(status);
|
||||
|
||||
int rv = vector_command::execute(env, newfds);
|
||||
if (env.echo()) fprintf(stderr, " %s\n", type == BEGIN ? "end" : ")");
|
||||
int rv;
|
||||
{
|
||||
indent_helper indent(env);
|
||||
rv = vector_command::execute(env, newfds);
|
||||
}
|
||||
|
||||
env.echo("%s", type == BEGIN ? "end" : ")");
|
||||
|
||||
return env.status(rv);
|
||||
}
|
||||
|
@ -286,7 +293,7 @@ namespace {
|
|||
|
||||
|
||||
|
||||
bool evaluate(int type, const std::string &s, Environment &env) {
|
||||
int evaluate(int type, const std::string &s, Environment &env) {
|
||||
|
||||
auto tokens = tokenize(s, true);
|
||||
std::reverse(tokens.begin(), tokens.end());
|
||||
|
@ -305,8 +312,7 @@ namespace {
|
|||
}
|
||||
catch (std::exception &ex) {
|
||||
fprintf(stderr, "%s\n", ex.what());
|
||||
env.status(-5);
|
||||
e = 0;
|
||||
return -5;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -315,15 +321,18 @@ namespace {
|
|||
if (tokens.size() > 1) {
|
||||
fprintf(stderr, "### Else - Missing if keyword.\n");
|
||||
fprintf(stderr, "# Usage - Else [if expression...]\n");
|
||||
env.status(-3);
|
||||
e = 0;
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
return !!e;
|
||||
}
|
||||
}
|
||||
|
||||
int if_command::execute(Environment &env, const fdmask &fds) {
|
||||
/*
|
||||
* the entire command prints even if there is an error with the expression.
|
||||
*
|
||||
*/
|
||||
int if_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
||||
|
||||
int rv = 0;
|
||||
bool ok = false;
|
||||
|
@ -334,37 +343,29 @@ int if_command::execute(Environment &env, const fdmask &fds) {
|
|||
fdmask newfds;
|
||||
int status = check_ends(e, newfds);
|
||||
newfds |= fds;
|
||||
if (status) return env.status(status);
|
||||
if (status) {
|
||||
rv = status;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
for (auto &c : clauses) {
|
||||
std::string s = expand_vars(c->clause, env);
|
||||
|
||||
if (env.echo()) {
|
||||
if (c->type == IF) { // special.
|
||||
fprintf(stderr, " %s ... %s\n",
|
||||
s.c_str(), e.c_str());
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, " %s\n", s.c_str());
|
||||
}
|
||||
}
|
||||
if (c->type == IF)
|
||||
env.echo("%s ... %s", s.c_str(), e.c_str());
|
||||
else
|
||||
env.echo("%s", s.c_str());
|
||||
|
||||
if (ok) continue;
|
||||
ok = evaluate(c->type, s, env);
|
||||
if (!ok) continue;
|
||||
rv = c->execute(env, newfds);
|
||||
{
|
||||
indent_helper indent(env);
|
||||
int tmp = evaluate(c->type, s, env);
|
||||
if (tmp < 0) { ok = true; rv = tmp; }
|
||||
else rv = c->execute(env, newfds);
|
||||
}
|
||||
}
|
||||
|
||||
if (env.echo()) fprintf(stderr, " end\n");
|
||||
env.echo("end");
|
||||
return env.status(rv);
|
||||
}
|
||||
|
||||
/*
|
||||
int if_else_clause::execute() {
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
bool if_else_clause::evaluate(const Environment &e) {
|
||||
return false;
|
||||
}
|
||||
|
|
29
command.h
29
command.h
|
@ -1,6 +1,7 @@
|
|||
#ifndef __command_h__
|
||||
#define __command_h__
|
||||
|
||||
#include <new>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
@ -20,9 +21,13 @@ struct command {
|
|||
command(int t = 0) : type(t)
|
||||
{}
|
||||
|
||||
virtual bool terminal() const noexcept {
|
||||
return type == EVALUATE || type == COMMAND;
|
||||
}
|
||||
|
||||
int type = 0;
|
||||
virtual ~command();
|
||||
virtual int execute(Environment &e, const fdmask &fds) = 0;
|
||||
virtual int execute(Environment &e, const fdmask &fds, bool throwup = true) = 0;
|
||||
};
|
||||
|
||||
struct error_command : public command {
|
||||
|
@ -32,7 +37,7 @@ struct error_command : public command {
|
|||
{}
|
||||
|
||||
std::string text;
|
||||
virtual int execute(Environment &e, const fdmask &fds) override final;
|
||||
virtual int execute(Environment &e, const fdmask &fds, bool throwup = true) override final;
|
||||
};
|
||||
|
||||
struct simple_command : public command {
|
||||
|
@ -42,7 +47,7 @@ struct simple_command : public command {
|
|||
|
||||
std::string text;
|
||||
|
||||
virtual int execute(Environment &e, const fdmask &fds) final override;
|
||||
virtual int execute(Environment &e, const fdmask &fds, bool throwup = true) final override;
|
||||
};
|
||||
|
||||
struct evaluate_command : public command {
|
||||
|
@ -52,7 +57,7 @@ struct evaluate_command : public command {
|
|||
|
||||
std::string text;
|
||||
|
||||
virtual int execute(Environment &e, const fdmask &fds) final override;
|
||||
virtual int execute(Environment &e, const fdmask &fds, bool throwup = true) final override;
|
||||
};
|
||||
|
||||
struct binary_command : public command {
|
||||
|
@ -63,6 +68,10 @@ struct binary_command : public command {
|
|||
|
||||
command_ptr_pair children;
|
||||
|
||||
virtual bool terminal() const noexcept final override {
|
||||
return children[0]->terminal() && children[1]->terminal();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct or_command : public binary_command {
|
||||
|
@ -70,7 +79,7 @@ struct or_command : public binary_command {
|
|||
binary_command(PIPE_PIPE, std::move(a), std::move(b))
|
||||
{}
|
||||
|
||||
virtual int execute(Environment &e, const fdmask &fds) final override;
|
||||
virtual int execute(Environment &e, const fdmask &fds, bool throwup) final override;
|
||||
};
|
||||
|
||||
struct and_command : public binary_command {
|
||||
|
@ -78,7 +87,7 @@ struct and_command : public binary_command {
|
|||
binary_command(AMP_AMP, std::move(a), std::move(b))
|
||||
{}
|
||||
|
||||
virtual int execute(Environment &e, const fdmask &fds) final override;
|
||||
virtual int execute(Environment &e, const fdmask &fds, bool throwup) final override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -98,7 +107,7 @@ struct vector_command : public command {
|
|||
{}
|
||||
|
||||
command_ptr_vector children;
|
||||
virtual int execute(Environment &e, const fdmask &fds) override;
|
||||
virtual int execute(Environment &e, const fdmask &fds, bool throwup = true) override;
|
||||
};
|
||||
|
||||
struct begin_command : public vector_command {
|
||||
|
@ -110,7 +119,7 @@ struct begin_command : public vector_command {
|
|||
std::string begin;
|
||||
std::string end;
|
||||
|
||||
virtual int execute(Environment &e, const fdmask &fds) final override;
|
||||
virtual int execute(Environment &e, const fdmask &fds, bool throwup) final override;
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<struct if_else_clause> if_else_clause_ptr;
|
||||
|
@ -127,7 +136,7 @@ struct if_command : public command {
|
|||
clause_vector_type clauses;
|
||||
std::string end;
|
||||
|
||||
virtual int execute(Environment &e, const fdmask &fds) final override;
|
||||
virtual int execute(Environment &e, const fdmask &fds, bool throwup) final override;
|
||||
};
|
||||
|
||||
struct if_else_clause : public vector_command {
|
||||
|
@ -139,7 +148,7 @@ struct if_else_clause : public vector_command {
|
|||
|
||||
std::string clause;
|
||||
|
||||
bool evaluate(const Environment &e);
|
||||
//bool evaluate(const Environment &e);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -2,6 +2,8 @@
|
|||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "error.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
|
@ -73,7 +75,7 @@ namespace {
|
|||
}
|
||||
|
||||
|
||||
int Environment::status(int i) {
|
||||
int Environment::status(int i, const std::nothrow_t &) {
|
||||
|
||||
if (_status == i) return i;
|
||||
|
||||
|
@ -82,21 +84,27 @@ namespace {
|
|||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
int Environment::status(int i) {
|
||||
int Environment::status(int i, bool throwup) {
|
||||
status(i, std::nothrow);
|
||||
if (_exit) {
|
||||
throw std::runtime_error("Execution of input terminated.");
|
||||
|
||||
if (throwup && _exit && i) {
|
||||
throw execution_of_input_terminated(i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void Environment::echo(const char *fmt, ...) {
|
||||
if (_echo) {}
|
||||
if (_echo && !_startup) {
|
||||
for (unsigned i = 0; i < _indent; ++i) {
|
||||
fputc(' ', stderr);
|
||||
fputc(' ', stderr);
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
va_end(ap);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <new>
|
||||
|
||||
|
||||
|
||||
// environment has a bool which indicates if exported.
|
||||
struct EnvironmentEntry {
|
||||
|
@ -58,7 +61,8 @@ public:
|
|||
|
||||
bool and_or(bool v) { std::swap(v, _and_or); return v; }
|
||||
|
||||
int status(int i);
|
||||
int status(int i, bool throw_up = true);
|
||||
int status(int i, const std::nothrow_t &);
|
||||
|
||||
constexpr bool startup() const noexcept { return _startup; }
|
||||
constexpr void startup(bool tf) noexcept { _startup = tf; }
|
||||
|
@ -88,6 +92,10 @@ public:
|
|||
private:
|
||||
// magic variables.
|
||||
|
||||
friend class indent_helper;
|
||||
|
||||
int _indent = 0;
|
||||
|
||||
bool _exit = false;
|
||||
bool _test = false;
|
||||
|
||||
|
@ -95,12 +103,21 @@ private:
|
|||
|
||||
bool _echo = false;
|
||||
int _status = 0;
|
||||
int _indent = 0;
|
||||
bool _startup = false;
|
||||
bool _passthrough = false;
|
||||
|
||||
std::unordered_map<std::string, EnvironmentEntry> _table;
|
||||
};
|
||||
|
||||
class indent_helper {
|
||||
public:
|
||||
indent_helper(Environment &e) : env(e) { env._indent++; }
|
||||
void release() { if (active) { active = false; env._indent--; }}
|
||||
~indent_helper() { if (active) env._indent--; }
|
||||
private:
|
||||
Environment &env;
|
||||
bool active = true;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef __mpw_error_h__
|
||||
#define __mpw_error_h__
|
||||
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
|
||||
class execution_of_input_terminated : public std::runtime_error {
|
||||
public:
|
||||
execution_of_input_terminated(int status) :
|
||||
std::runtime_error("MPW Shell - Execution of input Terminated."), _status(status)
|
||||
{}
|
||||
constexpr int status() const noexcept { return _status; }
|
||||
private:
|
||||
int _status;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue