rework allocator errors and error message storage buffer
parent
d7c93fa8b9
commit
be71d3a4b9
|
@ -386,14 +386,6 @@ enum class cs_loop_state {
|
|||
NORMAL = 0, BREAK, CONTINUE
|
||||
};
|
||||
|
||||
static inline void *cs_default_alloc(void *, void *p, size_t, size_t ns) {
|
||||
if (!ns) {
|
||||
delete[] static_cast<unsigned char *>(p);
|
||||
return nullptr;
|
||||
}
|
||||
return new unsigned char[ns];
|
||||
}
|
||||
|
||||
struct LIBCUBESCRIPT_EXPORT cs_state {
|
||||
friend struct cs_error;
|
||||
friend struct cs_strman;
|
||||
|
@ -407,7 +399,8 @@ struct LIBCUBESCRIPT_EXPORT cs_state {
|
|||
|
||||
int identflags = 0;
|
||||
|
||||
cs_state(cs_alloc_cb func = cs_default_alloc, void *data = nullptr);
|
||||
cs_state();
|
||||
cs_state(cs_alloc_cb func, void *data);
|
||||
virtual ~cs_state();
|
||||
|
||||
cs_state(cs_state const &) = delete;
|
||||
|
@ -536,11 +529,10 @@ private:
|
|||
LIBCUBESCRIPT_LOCAL void *alloc(void *ptr, size_t olds, size_t news);
|
||||
|
||||
cs_gen_state *p_pstate = nullptr;
|
||||
void *p_errbuf = nullptr;
|
||||
int p_inloop = 0;
|
||||
bool p_owner = false;
|
||||
|
||||
char p_errbuf[512];
|
||||
|
||||
cs_hook_cb p_callhook;
|
||||
};
|
||||
|
||||
|
@ -593,7 +585,11 @@ struct LIBCUBESCRIPT_EXPORT cs_error {
|
|||
cs_error(cs_state &cs, std::string_view msg):
|
||||
p_errmsg(), p_stack(cs)
|
||||
{
|
||||
p_errmsg = save_msg(cs, msg);
|
||||
char *sp;
|
||||
char *buf = request_buf(cs, msg.size(), sp);
|
||||
std::memcpy(buf, msg.data(), msg.size());
|
||||
buf[msg.size()] = '\0';
|
||||
p_errmsg = std::string_view{sp, buf + msg.size()};
|
||||
p_stack = save_stack(cs);
|
||||
}
|
||||
|
||||
|
@ -601,26 +597,25 @@ struct LIBCUBESCRIPT_EXPORT cs_error {
|
|||
cs_error(cs_state &cs, std::string_view msg, A const &...args):
|
||||
p_errmsg(), p_stack(cs)
|
||||
{
|
||||
char fbuf[512];
|
||||
int written = std::snprintf(
|
||||
fbuf, sizeof(fbuf), msg.data(), args...
|
||||
);
|
||||
if (written >= int(sizeof(fbuf))) {
|
||||
written = std::strlen(fbuf);
|
||||
} else if (written <= 0) {
|
||||
std::strncpy(fbuf, "format error", sizeof(fbuf));
|
||||
written = std::strlen(fbuf);
|
||||
std::size_t sz = msg.size() + 64;
|
||||
char *buf, *sp;
|
||||
for (;;) {
|
||||
buf = request_buf(cs, sz, sp);
|
||||
int written = std::snprintf(buf, sz, msg.data(), args...);
|
||||
if (written <= 0) {
|
||||
throw cs_internal_error{"format error"};
|
||||
} else if (std::size_t(written) <= sz) {
|
||||
break;
|
||||
}
|
||||
sz = std::size_t(written);
|
||||
}
|
||||
p_errmsg = save_msg(cs, std::string_view{
|
||||
static_cast<char const *>(fbuf),
|
||||
std::size_t(written)
|
||||
});
|
||||
p_errmsg = std::string_view{sp, buf + sz};
|
||||
p_stack = save_stack(cs);
|
||||
}
|
||||
|
||||
private:
|
||||
cs_stack_state save_stack(cs_state &cs);
|
||||
std::string_view save_msg(cs_state &cs, std::string_view v);
|
||||
char *request_buf(cs_state &cs, std::size_t bufs, char *&sp);
|
||||
|
||||
std::string_view p_errmsg;
|
||||
cs_stack_state p_stack;
|
||||
|
|
|
@ -151,7 +151,11 @@ struct cs_shared_state {
|
|||
{}
|
||||
|
||||
void *alloc(void *ptr, size_t os, size_t ns) {
|
||||
return allocf(aptr, ptr, os, ns);
|
||||
void *p = allocf(aptr, ptr, os, ns);
|
||||
if (!p && ns) {
|
||||
throw std::bad_alloc{};
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
template<typename T, typename ...A>
|
||||
|
|
70
src/cs_vm.cc
70
src/cs_vm.cc
|
@ -70,6 +70,43 @@ bool cs_stack_state::gap() const {
|
|||
return p_gap;
|
||||
}
|
||||
|
||||
char *cs_error::request_buf(cs_state &cs, std::size_t bufs, char *&sp) {
|
||||
cs_charbuf &cb = *static_cast<cs_charbuf *>(cs.p_errbuf);
|
||||
cs_gen_state *gs = cs.p_pstate;
|
||||
cb.clear();
|
||||
std::size_t sz = 0;
|
||||
if (gs) {
|
||||
/* we can attach line number */
|
||||
sz = gs->src_name.size() + 32;
|
||||
for (;;) {
|
||||
/* we are using so the buffer tracks the elements and therefore
|
||||
* does not wipe them when we attempt to reserve more capacity
|
||||
*/
|
||||
cb.resize(sz);
|
||||
int nsz;
|
||||
if (!gs->src_name.empty()) {
|
||||
nsz = std::snprintf(
|
||||
cb.data(), sz, "%.*s:%zu: ",
|
||||
int(gs->src_name.size()), gs->src_name.data(),
|
||||
gs->current_line
|
||||
);
|
||||
} else {
|
||||
nsz = std::snprintf(cb.data(), sz, "%zu: ", gs->current_line);
|
||||
}
|
||||
if (nsz <= 0) {
|
||||
throw cs_internal_error{"format error"};
|
||||
} else if (std::size_t(nsz) < sz) {
|
||||
sz = std::size_t(nsz);
|
||||
break;
|
||||
}
|
||||
sz = std::size_t(nsz + 1);
|
||||
}
|
||||
}
|
||||
cb.resize(sz + bufs + 1);
|
||||
sp = cb.data();
|
||||
return &cb[sz];
|
||||
}
|
||||
|
||||
cs_stack_state cs_error::save_stack(cs_state &cs) {
|
||||
cs_ivar *dalias = static_cast<cs_ivar *>(cs.p_state->identmap[DbgaliasIdx]);
|
||||
if (!dalias->get_value()) {
|
||||
|
@ -107,39 +144,6 @@ cs_stack_state cs_error::save_stack(cs_state &cs) {
|
|||
return cs_stack_state(cs, ret, total > dalias->get_value());
|
||||
}
|
||||
|
||||
std::string_view cs_error::save_msg(
|
||||
cs_state &cs, std::string_view msg
|
||||
) {
|
||||
if (msg.size() >= sizeof(cs.p_errbuf)) {
|
||||
msg = msg.substr(0, sizeof(cs.p_errbuf) - 1);
|
||||
}
|
||||
cs_gen_state *gs = cs.p_pstate;
|
||||
if (gs) {
|
||||
/* we can attach line number */
|
||||
int sz;
|
||||
if (!gs->src_name.empty()) {
|
||||
sz = snprintf(
|
||||
cs.p_errbuf, sizeof(cs.p_errbuf), "%.*s:%zu: %.*s",
|
||||
int(gs->src_name.size()), gs->src_name.data(),
|
||||
gs->current_line,
|
||||
int(msg.size()), msg.data()
|
||||
);
|
||||
} else {
|
||||
sz = snprintf(
|
||||
cs.p_errbuf, sizeof(cs.p_errbuf), "%zu: %.*s",
|
||||
gs->current_line, int(msg.size()), msg.data()
|
||||
);
|
||||
}
|
||||
if (sz <= 0) {
|
||||
throw cs_internal_error{"format error"};
|
||||
}
|
||||
return std::string_view{cs.p_errbuf, std::size_t(sz)};
|
||||
}
|
||||
memcpy(cs.p_errbuf, msg.data(), msg.size());
|
||||
cs.p_errbuf[msg.size()] = '\0';
|
||||
return std::string_view{cs.p_errbuf, msg.size()};
|
||||
}
|
||||
|
||||
static void bcode_ref(uint32_t *code) {
|
||||
if (!code) {
|
||||
return;
|
||||
|
|
|
@ -248,6 +248,16 @@ int cs_command::get_num_args() const {
|
|||
|
||||
void cs_init_lib_base(cs_state &cs);
|
||||
|
||||
static void *cs_default_alloc(void *, void *p, size_t, size_t ns) {
|
||||
if (!ns) {
|
||||
std::free(p);
|
||||
return nullptr;
|
||||
}
|
||||
return std::realloc(p, ns);
|
||||
}
|
||||
|
||||
cs_state::cs_state(): cs_state{cs_default_alloc, nullptr} {}
|
||||
|
||||
cs_state::cs_state(cs_alloc_cb func, void *data):
|
||||
p_state(nullptr), p_callhook()
|
||||
{
|
||||
|
@ -262,6 +272,9 @@ cs_state::cs_state(cs_alloc_cb func, void *data):
|
|||
new (p_state) cs_shared_state{func, data};
|
||||
p_owner = true;
|
||||
|
||||
/* will be used as message storage for errors */
|
||||
p_errbuf = p_state->create<cs_charbuf>(*this);
|
||||
|
||||
for (int i = 0; i < MaxArguments; ++i) {
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "arg%d", i + 1);
|
||||
|
@ -379,6 +392,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::destroy() {
|
|||
p_state->destroy(i);
|
||||
}
|
||||
p_state->destroy(p_state->strman);
|
||||
p_state->destroy(static_cast<cs_charbuf *>(p_errbuf));
|
||||
p_state->destroy(p_state);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue