simple error handling mechanism (will be used extensively later once it improves)
parent
5674375614
commit
bb72c27d2d
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue