simple error handling mechanism (will be used extensively later once it improves)

master
Daniel Kolesa 2016-09-09 00:41:42 +02:00
parent 5674375614
commit bb72c27d2d
4 changed files with 89 additions and 10 deletions

View File

@ -316,6 +316,7 @@ enum {
};
using CsHookCb = ostd::Function<void()>;
using CsPanicCb = ostd::Function<void(CsString)>;
struct OSTD_EXPORT CsState {
CsMap<ostd::ConstCharRange, CsIdent *> idents;
@ -326,6 +327,7 @@ struct OSTD_EXPORT CsState {
int identflags = 0;
int nodebug = 0;
int protect = 0;
CsState();
virtual ~CsState();
@ -346,6 +348,19 @@ struct OSTD_EXPORT CsState {
void init_libs(int libs = CsLibAll);
CsPanicCb set_panic_func(CsPanicCb func);
CsPanicCb const &get_panic_func() const;
CsPanicCb &get_panic_func();
template<typename F>
bool pcall(F func, ostd::String *error) {
return ipcall([](void *data) {
(*static_cast<F *>(data))();
}, error, &func);
}
void error(CsString msg);
void clear_override(CsIdent &id);
void clear_overrides();
@ -461,8 +476,10 @@ struct OSTD_EXPORT CsState {
private:
CsIdent *add_ident(CsIdent *id);
bool ipcall(void (*f)(void *data), ostd::String *error, void *data);
CsHookCb p_callhook;
CsPanicCb p_panicfunc;
CsStream *p_out, *p_err;
};

View File

@ -82,6 +82,14 @@ enum {
CsRetFloat = CsValFloat << CsCodeRet,
};
struct CsErrorException {
CsString errmsg;
CsErrorException() = delete;
CsErrorException(CsErrorException const &) = delete;
CsErrorException(CsErrorException &&v): errmsg(ostd::move(v.errmsg)) {}
CsErrorException(CsString &&v): errmsg(ostd::move(v)) {}
};
ostd::ConstCharRange cs_debug_line(
ostd::ConstCharRange p, ostd::ConstCharRange fmt, ostd::CharRange buf
);

View File

@ -252,11 +252,21 @@ int CsCommand::get_num_args() const {
void cs_init_lib_base(CsState &cs);
CsState::CsState(): p_out(&ostd::out), p_err(&ostd::err) {
CsState::CsState():
p_callhook(), p_panicfunc(), p_out(&ostd::out), p_err(&ostd::err)
{
noalias.id = nullptr;
noalias.next = nullptr;
noalias.usedargs = (1 << MaxArguments) - 1;
noalias.argstack = nullptr;
/* default panic func */
p_panicfunc = [this](CsString v) {
get_err().writefln(
"PANIC: unprotected error in call to CubeScript (%s)", v
);
};
for (int i = 0; i < MaxArguments; ++i) {
char buf[32];
snprintf(buf, sizeof(buf), "arg%d", i + 1);
@ -394,6 +404,49 @@ void *CsState::alloc(void *ptr, ostd::Size, ostd::Size ns) {
return new ostd::byte[ns];
}
CsPanicCb CsState::set_panic_func(CsPanicCb func) {
auto hk = ostd::move(p_panicfunc);
p_panicfunc = ostd::move(func);
return hk;
}
CsPanicCb const &CsState::get_panic_func() const {
return p_panicfunc;
}
CsPanicCb &CsState::get_panic_func() {
return p_panicfunc;
}
bool CsState::ipcall(void (*f)(void *data), ostd::String *error, void *data) {
++protect;
try {
f(data);
} catch (CsErrorException const &v) {
--protect;
if (error) {
*error = ostd::move(v.errmsg);
}
return false;
} catch (...) {
--protect;
throw;
}
--protect;
return true;
}
void CsState::error(CsString msg) {
if (protect) {
throw CsErrorException(ostd::move(msg));
} else {
if (p_panicfunc) {
p_panicfunc(ostd::move(msg));
}
exit(EXIT_FAILURE);
}
}
void CsState::clear_override(CsIdent &id) {
if (!(id.get_flags() & CsIdfOverridden)) {
return;
@ -1223,8 +1276,11 @@ void cs_init_lib_base(CsState &cs) {
cs.new_command("nodebug", "e", [&cs](CsValueRange args, CsValue &res) {
++cs.nodebug;
cs.run(args[0].get_code(), res);
--cs.nodebug;
cs_do_and_cleanup([&]() {
cs.run(args[0].get_code(), res);
}, [&cs]() {
--cs.nodebug;
});
});
cs.new_command("push", "rTe", [&cs](CsValueRange args, CsValue &res) {

View File

@ -182,16 +182,13 @@ void print_version() {
ostd::writeln(version);
}
struct InterruptedException {
};
static void do_sigint(int n) {
/* in case another SIGINT happens, terminate normally */
signal(n, SIG_DFL);
if (gcs) {
gcs->set_call_hook([]() {
gcs->set_call_hook(nullptr);
throw InterruptedException{};
gcs->error("<execution interrupted>");
});
}
}
@ -199,7 +196,8 @@ static void do_sigint(int n) {
static void do_call(CsState &cs, ostd::ConstCharRange line, bool file = false) {
CsValue ret;
signal(SIGINT, do_sigint);
try {
ostd::String err;
if (!cs.pcall([&]() {
if (file) {
if (!cs.run_file(line, ret)) {
ostd::err.writeln("cannot read file: ", line);
@ -207,9 +205,9 @@ static void do_call(CsState &cs, ostd::ConstCharRange line, bool file = false) {
} else {
cs.run(line, ret);
}
} catch (InterruptedException) {
}, &err)) {
signal(SIGINT, SIG_DFL);
ostd::writeln("<execution interrupted>");
ostd::writeln(err);
return;
}
signal(SIGINT, SIG_DFL);