throw error for {exit}

This commit is contained in:
Kelvin Sherlock 2016-02-02 16:19:13 -05:00
parent 6f482d73df
commit 6d9e5dc78c
5 changed files with 129 additions and 77 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}
}
*/

View File

@ -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

17
error.h Normal file
View File

@ -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