libcubescript/src/cs_vm.cc

1724 lines
61 KiB
C++
Raw Normal View History

2017-06-20 21:21:39 +02:00
#include <cubescript/cubescript.hh>
2016-08-12 18:38:43 +02:00
#include "cs_vm.hh"
#include "cs_util.hh"
2016-08-12 18:38:43 +02:00
2021-03-20 06:52:10 +01:00
#include <cstdio>
2017-02-09 20:59:14 +01:00
#include <limits>
2016-08-13 01:26:16 +02:00
2016-08-12 18:38:43 +02:00
namespace cscript {
2017-02-13 18:10:40 +01:00
struct cs_cmd_internal {
static void call(
2021-03-20 05:41:25 +01:00
cs_state &cs, cs_command *c, std::span<cs_value> args, cs_value &ret
) {
c->p_cb_cftv(cs, args, ret);
2016-08-17 23:04:43 +02:00
}
2016-09-02 22:49:05 +02:00
2017-02-13 18:10:40 +01:00
static bool has_cb(cs_ident *id) {
2016-09-02 22:49:05 +02:00
if (!id->is_command() && !id->is_special()) {
return false;
}
2017-02-13 18:10:40 +01:00
cs_command *cb = static_cast<cs_command *>(id);
2016-09-02 22:49:05 +02:00
return !!cb->p_cb_cftv;
}
};
2016-08-17 23:04:43 +02:00
static inline void cs_push_alias(cs_state &cs, cs_ident *id, cs_ident_stack &st) {
2016-08-18 03:53:51 +02:00
if (id->is_alias() && (id->get_index() >= MaxArguments)) {
cs_value nv{cs};
2018-04-27 23:53:55 +02:00
cs_alias_internal::push_arg(static_cast<cs_alias *>(id), nv, st);
2016-08-18 00:06:39 +02:00
}
}
2017-02-13 18:10:40 +01:00
static inline void cs_pop_alias(cs_ident *id) {
2016-08-18 03:53:51 +02:00
if (id->is_alias() && (id->get_index() >= MaxArguments)) {
2018-04-27 23:53:55 +02:00
cs_alias_internal::pop_arg(static_cast<cs_alias *>(id));
2016-08-18 00:06:39 +02:00
}
}
2017-02-13 18:10:40 +01:00
cs_stack_state::cs_stack_state(cs_state &cs, cs_stack_state_node *nd, bool gap):
2016-09-14 21:46:47 +02:00
p_state(cs), p_node(nd), p_gap(gap)
2016-09-09 19:19:50 +02:00
{}
2017-02-13 18:10:40 +01:00
cs_stack_state::cs_stack_state(cs_stack_state &&st):
2016-09-14 21:46:47 +02:00
p_state(st.p_state), p_node(st.p_node), p_gap(st.p_gap)
2016-09-09 19:19:50 +02:00
{
st.p_node = nullptr;
st.p_gap = false;
}
2017-02-13 18:10:40 +01:00
cs_stack_state::~cs_stack_state() {
2017-01-25 02:09:50 +01:00
size_t len = 0;
2017-02-13 18:10:40 +01:00
for (cs_stack_state_node const *nd = p_node; nd; nd = nd->next) {
2016-09-14 21:46:47 +02:00
++len;
}
p_state.p_state->destroy_array(p_node, len);
2016-09-09 19:19:50 +02:00
}
2017-02-13 18:10:40 +01:00
cs_stack_state &cs_stack_state::operator=(cs_stack_state &&st) {
2016-09-09 19:19:50 +02:00
p_node = st.p_node;
p_gap = st.p_gap;
st.p_node = nullptr;
st.p_gap = false;
return *this;
}
2017-02-13 18:10:40 +01:00
cs_stack_state_node const *cs_stack_state::get() const {
2016-09-09 19:19:50 +02:00
return p_node;
}
2017-02-13 18:10:40 +01:00
bool cs_stack_state::gap() const {
2016-09-09 19:19:50 +02:00
return p_gap;
}
2017-02-13 18:10:40 +01:00
cs_stack_state cs_error::save_stack(cs_state &cs) {
cs_ivar *dalias = static_cast<cs_ivar *>(cs.p_state->identmap[DbgaliasIdx]);
2016-09-09 19:19:50 +02:00
if (!dalias->get_value()) {
2017-02-13 18:10:40 +01:00
return cs_stack_state(cs, nullptr, !!cs.p_callstack);
2016-09-09 19:19:50 +02:00
}
int total = 0, depth = 0;
2021-03-18 20:55:14 +01:00
for (cs_ident_link *l = cs.p_callstack; l; l = l->next) {
2016-09-09 19:19:50 +02:00
total++;
}
2016-09-10 15:01:49 +02:00
if (!total) {
2017-02-13 18:10:40 +01:00
return cs_stack_state(cs, nullptr, false);
2016-09-10 15:01:49 +02:00
}
2017-02-13 18:10:40 +01:00
cs_stack_state_node *st = cs.p_state->create_array<cs_stack_state_node>(
2017-02-18 17:49:01 +01:00
std::min(total, dalias->get_value())
2016-09-14 21:46:47 +02:00
);
2017-02-13 18:10:40 +01:00
cs_stack_state_node *ret = st, *nd = st;
2016-09-09 19:19:50 +02:00
++st;
2021-03-18 20:55:14 +01:00
for (cs_ident_link *l = cs.p_callstack; l; l = l->next) {
2016-09-09 19:19:50 +02:00
++depth;
if (depth < dalias->get_value()) {
nd->id = l->id;
nd->index = total - depth + 1;
2016-09-10 19:54:55 +02:00
if (!l->next) {
2016-09-09 19:19:50 +02:00
nd->next = nullptr;
} else {
nd->next = st;
}
nd = st++;
2016-09-10 19:54:55 +02:00
} else if (!l->next) {
2016-09-09 19:19:50 +02:00
nd->id = l->id;
nd->index = 1;
2016-09-10 19:54:55 +02:00
nd->next = nullptr;
2016-09-09 19:19:50 +02:00
}
}
2017-02-13 18:10:40 +01:00
return cs_stack_state(cs, ret, total > dalias->get_value());
2016-09-09 19:19:50 +02:00
}
std::string_view cs_error::save_msg(
cs_state &cs, std::string_view msg
2016-09-14 00:14:21 +02:00
) {
if (msg.size() > sizeof(cs.p_errbuf)) {
msg = msg.substr(0, sizeof(cs.p_errbuf));
2016-09-14 00:14:21 +02:00
}
2017-02-13 18:10:40 +01:00
cs_gen_state *gs = cs.p_pstate;
if (gs) {
/* we can attach line number */
2021-03-20 06:52:10 +01:00
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) {
strncpy(cs.p_errbuf, "format error", sizeof(cs.p_errbuf));
sz = strlen(cs.p_errbuf);
}
2021-03-20 06:52:10 +01:00
return std::string_view{cs.p_errbuf, std::size_t(sz)};
}
2016-09-14 00:14:21 +02:00
memcpy(cs.p_errbuf, msg.data(), msg.size());
return std::string_view{cs.p_errbuf, msg.size()};
2016-09-14 00:14:21 +02:00
}
2017-01-25 02:10:17 +01:00
static void bcode_ref(uint32_t *code) {
2016-08-17 04:57:53 +02:00
if (!code) {
return;
}
2021-03-18 20:55:14 +01:00
if ((*code & CS_CODE_OP_MASK) == CS_CODE_START) {
2016-08-14 17:05:55 +02:00
bcode_incr(code);
return;
}
2021-03-18 20:55:14 +01:00
switch (code[-1]&CS_CODE_OP_MASK) {
case CS_CODE_START:
2016-08-17 04:57:53 +02:00
bcode_incr(&code[-1]);
break;
2021-03-18 20:55:14 +01:00
case CS_CODE_OFFSET:
2017-01-30 19:38:11 +01:00
code -= std::ptrdiff_t(code[-1] >> 8);
2016-08-17 04:57:53 +02:00
bcode_incr(code);
break;
2016-08-14 17:05:55 +02:00
}
}
2017-01-25 02:10:17 +01:00
static void bcode_unref(uint32_t *code) {
2016-08-17 04:57:53 +02:00
if (!code) {
return;
}
2021-03-18 20:55:14 +01:00
if ((*code & CS_CODE_OP_MASK) == CS_CODE_START) {
2016-08-14 17:05:55 +02:00
bcode_decr(code);
return;
}
2021-03-18 20:55:14 +01:00
switch (code[-1]&CS_CODE_OP_MASK) {
case CS_CODE_START:
2016-08-17 04:57:53 +02:00
bcode_decr(&code[-1]);
break;
2021-03-18 20:55:14 +01:00
case CS_CODE_OFFSET:
2017-01-30 19:38:11 +01:00
code -= std::ptrdiff_t(code[-1] >> 8);
2016-08-17 04:57:53 +02:00
bcode_decr(code);
break;
2016-08-14 17:05:55 +02:00
}
}
2017-02-13 18:10:40 +01:00
cs_bcode_ref::cs_bcode_ref(cs_bcode *v): p_code(v) {
2017-01-25 02:10:17 +01:00
bcode_ref(reinterpret_cast<uint32_t *>(p_code));
2016-08-14 17:05:55 +02:00
}
2017-02-13 18:10:40 +01:00
cs_bcode_ref::cs_bcode_ref(cs_bcode_ref const &v): p_code(v.p_code) {
2017-01-25 02:10:17 +01:00
bcode_ref(reinterpret_cast<uint32_t *>(p_code));
2016-08-14 17:05:55 +02:00
}
2017-02-13 18:10:40 +01:00
cs_bcode_ref::~cs_bcode_ref() {
2017-01-25 02:10:17 +01:00
bcode_unref(reinterpret_cast<uint32_t *>(p_code));
2016-08-14 17:05:55 +02:00
}
2017-02-13 18:10:40 +01:00
cs_bcode_ref &cs_bcode_ref::operator=(cs_bcode_ref const &v) {
2017-01-25 02:10:17 +01:00
bcode_unref(reinterpret_cast<uint32_t *>(p_code));
2016-08-14 17:05:55 +02:00
p_code = v.p_code;
2017-01-25 02:10:17 +01:00
bcode_ref(reinterpret_cast<uint32_t *>(p_code));
2016-08-14 17:05:55 +02:00
return *this;
}
2017-02-13 18:10:40 +01:00
cs_bcode_ref &cs_bcode_ref::operator=(cs_bcode_ref &&v) {
2017-01-25 02:10:17 +01:00
bcode_unref(reinterpret_cast<uint32_t *>(p_code));
2016-08-14 17:05:55 +02:00
p_code = v.p_code;
v.p_code = nullptr;
return *this;
}
2017-02-13 18:10:40 +01:00
static inline uint32_t *forcecode(cs_state &cs, cs_value &v) {
2017-01-25 02:10:17 +01:00
uint32_t *code = reinterpret_cast<uint32_t *>(v.get_code());
2016-08-30 22:29:09 +02:00
if (!code) {
2017-02-13 18:10:40 +01:00
cs_gen_state gs(cs);
2016-08-12 19:31:34 +02:00
gs.code.reserve(64);
gs.gen_main(v.get_str());
gs.done();
2017-01-25 01:18:29 +01:00
uint32_t *cbuf = new uint32_t[gs.code.size()];
memcpy(cbuf, gs.code.data(), gs.code.size() * sizeof(uint32_t));
2017-02-13 18:10:40 +01:00
v.set_code(reinterpret_cast<cs_bcode *>(cbuf + 1));
2017-01-25 02:10:17 +01:00
code = reinterpret_cast<uint32_t *>(v.get_code());
2016-08-12 19:31:34 +02:00
}
2016-08-30 22:29:09 +02:00
return code;
2016-08-12 19:31:34 +02:00
}
2017-02-13 18:10:40 +01:00
static inline void forcecond(cs_state &cs, cs_value &v) {
2016-08-12 19:31:34 +02:00
switch (v.get_type()) {
2021-03-18 20:55:14 +01:00
case cs_value_type::STRING:
if (!std::string_view{v.get_str()}.empty()) {
2016-08-17 04:57:53 +02:00
forcecode(cs, v);
} else {
v.set_int(0);
}
break;
default:
break;
2016-08-12 19:31:34 +02:00
}
}
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
static uint32_t emptyblock[CS_VAL_ANY][2] = {
{ CS_CODE_START + 0x100, CS_CODE_EXIT | CS_RET_NULL },
{ CS_CODE_START + 0x100, CS_CODE_EXIT | CS_RET_INT },
{ CS_CODE_START + 0x100, CS_CODE_EXIT | CS_RET_FLOAT },
{ CS_CODE_START + 0x100, CS_CODE_EXIT | CS_RET_STRING }
2016-08-12 18:38:43 +02:00
};
2017-02-13 18:10:40 +01:00
static inline void force_arg(cs_value &v, int type) {
2016-08-12 18:38:43 +02:00
switch (type) {
2021-03-18 20:55:14 +01:00
case CS_RET_STRING:
if (v.get_type() != cs_value_type::STRING) {
2016-08-17 04:57:53 +02:00
v.force_str();
}
break;
2021-03-18 20:55:14 +01:00
case CS_RET_INT:
if (v.get_type() != cs_value_type::INT) {
2016-08-17 04:57:53 +02:00
v.force_int();
}
break;
2021-03-18 20:55:14 +01:00
case CS_RET_FLOAT:
if (v.get_type() != cs_value_type::FLOAT) {
2016-08-17 04:57:53 +02:00
v.force_float();
}
break;
2016-08-12 18:38:43 +02:00
}
}
2017-01-25 02:10:17 +01:00
static uint32_t *skipcode(uint32_t *code) {
2016-08-12 18:38:43 +02:00
int depth = 0;
for (;;) {
2017-01-25 02:10:17 +01:00
uint32_t op = *code++;
2016-08-12 18:38:43 +02:00
switch (op & 0xFF) {
2021-03-18 20:55:14 +01:00
case CS_CODE_VAL | CS_RET_STRING: {
2017-01-25 02:10:17 +01:00
uint32_t len = op >> 8;
code += len / sizeof(uint32_t) + 1;
2016-08-17 04:57:53 +02:00
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_BLOCK:
case CS_CODE_JUMP:
case CS_CODE_JUMP_B | CS_CODE_FLAG_TRUE:
case CS_CODE_JUMP_B | CS_CODE_FLAG_FALSE:
case CS_CODE_JUMP_RESULT | CS_CODE_FLAG_TRUE:
case CS_CODE_JUMP_RESULT | CS_CODE_FLAG_FALSE: {
2017-01-25 02:10:17 +01:00
uint32_t len = op >> 8;
2016-08-17 04:57:53 +02:00
code += len;
continue;
2016-08-12 18:38:43 +02:00
}
2021-03-18 20:55:14 +01:00
case CS_CODE_ENTER:
case CS_CODE_ENTER_RESULT:
2016-08-17 04:57:53 +02:00
++depth;
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_EXIT | CS_RET_NULL:
case CS_CODE_EXIT | CS_RET_STRING:
case CS_CODE_EXIT | CS_RET_INT:
case CS_CODE_EXIT | CS_RET_FLOAT:
2016-08-17 04:57:53 +02:00
if (depth <= 0) {
return code;
}
--depth;
continue;
2016-08-12 18:38:43 +02:00
}
}
}
2017-02-13 18:10:40 +01:00
cs_bcode *cs_copy_code(cs_bcode *c) {
2017-01-25 02:10:17 +01:00
uint32_t *bcode = reinterpret_cast<uint32_t *>(c);
uint32_t *end = skipcode(bcode);
uint32_t *dst = new uint32_t[end - bcode + 1];
2021-03-18 20:55:14 +01:00
*dst++ = CS_CODE_START;
2017-01-25 02:10:17 +01:00
memcpy(dst, bcode, (end - bcode) * sizeof(uint32_t));
2017-02-13 18:10:40 +01:00
return reinterpret_cast<cs_bcode *>(dst);
2016-08-12 18:38:43 +02:00
}
2016-08-17 04:57:53 +02:00
static inline void callcommand(
2017-02-13 18:10:40 +01:00
cs_state &cs, cs_command *id, cs_value *args, cs_value &res, int numargs,
2016-08-17 04:57:53 +02:00
bool lookup = false
) {
2016-08-12 18:38:43 +02:00
int i = -1, fakeargs = 0;
bool rep = false;
auto fmt = id->get_args();
for (auto it = fmt.begin(); it != fmt.end(); ++it) {
switch (*it) {
2016-08-17 04:57:53 +02:00
case 'i':
if (++i >= numargs) {
if (rep) {
break;
}
args[i].set_int(0);
fakeargs++;
} else {
args[i].force_int();
}
break;
case 'b':
if (++i >= numargs) {
if (rep) {
break;
}
2017-02-13 18:10:40 +01:00
args[i].set_int(std::numeric_limits<cs_int>::min());
2016-08-17 04:57:53 +02:00
fakeargs++;
} else {
args[i].force_int();
}
break;
case 'f':
if (++i >= numargs) {
if (rep) {
break;
}
args[i].set_float(0.0f);
fakeargs++;
} else {
args[i].force_float();
}
break;
case 'F':
if (++i >= numargs) {
if (rep) {
break;
}
args[i].set_float(args[i - 1].get_float());
fakeargs++;
} else {
args[i].force_float();
}
break;
case 's':
if (++i >= numargs) {
if (rep) {
break;
}
args[i].set_str("");
2016-08-17 04:57:53 +02:00
fakeargs++;
} else {
args[i].force_str();
}
break;
case 'T':
case 't':
if (++i >= numargs) {
if (rep) {
break;
}
2021-03-18 20:55:14 +01:00
args[i].set_none();
2016-08-17 04:57:53 +02:00
fakeargs++;
}
break;
case 'E':
if (++i >= numargs) {
if (rep) {
break;
}
2021-03-18 20:55:14 +01:00
args[i].set_none();
2016-08-17 04:57:53 +02:00
fakeargs++;
} else {
forcecond(cs, args[i]);
}
break;
case 'e':
if (++i >= numargs) {
if (rep) {
break;
}
args[i].set_code(
2021-03-18 20:55:14 +01:00
reinterpret_cast<cs_bcode *>(emptyblock[CS_VAL_NULL] + 1)
2016-08-17 04:57:53 +02:00
);
fakeargs++;
} else {
forcecode(cs, args[i]);
}
break;
case 'r':
if (++i >= numargs) {
if (rep) {
break;
}
args[i].set_ident(cs.p_state->identmap[DummyIdx]);
2016-08-17 04:57:53 +02:00
fakeargs++;
} else {
cs.force_ident(args[i]);
}
break;
case '$':
2016-09-06 20:48:24 +02:00
i += 1;
2016-08-17 04:57:53 +02:00
args[i].set_ident(id);
break;
case 'N':
2016-09-06 20:48:24 +02:00
i += 1;
2017-02-13 18:10:40 +01:00
args[i].set_int(cs_int(lookup ? -1 : i - fakeargs));
2016-08-17 04:57:53 +02:00
break;
case 'C': {
2017-02-18 17:49:01 +01:00
i = std::max(i + 1, numargs);
cs_value tv{cs};
2021-03-20 05:41:25 +01:00
tv.set_str(value_list_concat(
cs, std::span{args, std::size_t(i)}, " "
));
cs_cmd_internal::call(
cs, id, std::span<cs_value>(&tv, &tv + 1), res
);
return;
2016-08-12 18:38:43 +02:00
}
2016-08-17 04:57:53 +02:00
case 'V':
2017-02-18 17:49:01 +01:00
i = std::max(i + 1, numargs);
2021-03-20 05:41:25 +01:00
cs_cmd_internal::call(
cs, id, std::span{args, std::size_t(i)}, res
);
return;
2016-08-17 04:57:53 +02:00
case '1':
case '2':
case '3':
case '4':
if (i + 1 < numargs) {
it -= *it - '0' + 1;
2016-08-17 04:57:53 +02:00
rep = true;
}
break;
2016-08-12 18:38:43 +02:00
}
2016-08-17 04:57:53 +02:00
}
2016-08-12 18:38:43 +02:00
++i;
2021-03-20 05:41:25 +01:00
cs_cmd_internal::call(
cs, id, std::span<cs_value>{args, std::size_t(i)}, res
);
2016-08-17 04:57:53 +02:00
}
2017-02-13 18:10:40 +01:00
static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result);
2016-08-17 04:57:53 +02:00
static inline void cs_call_alias(
2017-02-13 18:10:40 +01:00
cs_state &cs, cs_alias *a, cs_value *args, cs_value &result,
2017-01-25 02:10:17 +01:00
int callargs, int &nargs, int offset, int skip, uint32_t op
2016-08-17 04:57:53 +02:00
) {
2017-02-13 18:10:40 +01:00
cs_ivar *anargs = static_cast<cs_ivar *>(cs.p_state->identmap[NumargsIdx]);
cs_valarray<cs_ident_stack, MaxArguments> argstack{cs};
2016-08-17 04:57:53 +02:00
for(int i = 0; i < callargs; i++) {
2018-04-27 23:53:55 +02:00
cs_alias_internal::push_arg(
2017-02-13 18:10:40 +01:00
static_cast<cs_alias *>(cs.p_state->identmap[i]),
2016-08-18 00:06:39 +02:00
args[offset + i], argstack[i], false
);
2016-08-17 04:57:53 +02:00
}
int oldargs = anargs->get_value();
anargs->set_value(callargs);
2016-08-17 04:57:53 +02:00
int oldflags = cs.identflags;
2017-02-13 18:10:40 +01:00
cs.identflags |= a->get_flags()&CS_IDF_OVERRIDDEN;
2021-03-18 20:55:14 +01:00
cs_ident_link aliaslink = {
a, cs.p_callstack, (1<<callargs)-1, &argstack[0]
2016-08-17 04:57:53 +02:00
};
cs.p_callstack = &aliaslink;
2017-01-25 02:10:17 +01:00
uint32_t *codep = reinterpret_cast<uint32_t *>(
2018-04-27 23:53:55 +02:00
cs_alias_internal::compile_code(a, cs)
);
2016-08-17 04:57:53 +02:00
bcode_incr(codep);
cs_do_and_cleanup([&]() {
runcode(cs, codep+1, result);
}, [&]() {
bcode_decr(codep);
cs.p_callstack = aliaslink.next;
cs.identflags = oldflags;
for (int i = 0; i < callargs; i++) {
2018-04-27 23:53:55 +02:00
cs_alias_internal::pop_arg(
2017-02-13 18:10:40 +01:00
static_cast<cs_alias *>(cs.p_state->identmap[i])
);
2016-08-17 04:57:53 +02:00
}
2017-11-06 01:07:53 +01:00
int argmask = aliaslink.usedargs & int(~0U << callargs);
for (; argmask; ++callargs) {
if (argmask & (1 << callargs)) {
2018-04-27 23:53:55 +02:00
cs_alias_internal::pop_arg(static_cast<cs_alias *>(
cs.p_state->identmap[callargs])
);
argmask &= ~(1 << callargs);
}
}
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
anargs->set_value(oldargs);
nargs = offset - skip;
});
2016-08-12 18:38:43 +02:00
}
static constexpr int MaxRunDepth = 255;
static thread_local int rundepth = 0;
2016-09-23 21:04:52 +02:00
struct RunDepthRef {
RunDepthRef() = delete;
2017-02-13 18:10:40 +01:00
RunDepthRef(cs_state &cs) {
2016-09-23 21:04:52 +02:00
if (rundepth >= MaxRunDepth) {
2017-02-13 18:10:40 +01:00
throw cs_error(cs, "exceeded recursion limit");
2016-09-23 21:04:52 +02:00
}
++rundepth;
}
RunDepthRef(RunDepthRef const &) = delete;
RunDepthRef(RunDepthRef &&) = delete;
~RunDepthRef() { --rundepth; }
};
2017-02-13 18:10:40 +01:00
static inline cs_alias *cs_get_lookup_id(cs_state &cs, uint32_t op) {
cs_ident *id = cs.p_state->identmap[op >> 8];
if (id->get_flags() & CS_IDF_UNKNOWN) {
throw cs_error(cs, "unknown alias lookup: %s", id->get_name());
2016-08-17 04:57:53 +02:00
}
2017-02-13 18:10:40 +01:00
return static_cast<cs_alias *>(id);
2016-08-17 04:57:53 +02:00
}
2017-02-13 18:10:40 +01:00
static inline cs_alias *cs_get_lookuparg_id(cs_state &cs, uint32_t op) {
cs_ident *id = cs.p_state->identmap[op >> 8];
2016-09-10 19:54:55 +02:00
if (!cs_is_arg_used(cs, id)) {
2016-08-17 04:57:53 +02:00
return nullptr;
}
2017-02-13 18:10:40 +01:00
return static_cast<cs_alias *>(id);
2016-08-17 04:57:53 +02:00
}
static inline int cs_get_lookupu_type(
2017-02-13 18:10:40 +01:00
cs_state &cs, cs_value &arg, cs_ident *&id, uint32_t op
2016-08-17 04:57:53 +02:00
) {
2021-03-18 20:55:14 +01:00
if (arg.get_type() != cs_value_type::STRING) {
2016-08-17 04:57:53 +02:00
return -2; /* default case */
}
2021-03-17 21:57:47 +01:00
id = cs.get_ident(arg.get_str());
2016-08-17 04:57:53 +02:00
if (id) {
2016-08-18 03:53:51 +02:00
switch(id->get_type()) {
2021-03-18 20:55:14 +01:00
case cs_ident_type::ALIAS:
2017-02-13 18:10:40 +01:00
if (id->get_flags() & CS_IDF_UNKNOWN) {
2016-08-17 04:57:53 +02:00
break;
}
2016-09-10 19:54:55 +02:00
if ((id->get_index() < MaxArguments) && !cs_is_arg_used(cs, id)) {
2016-09-07 20:20:36 +02:00
return CsIdUnknown;
2016-08-17 04:57:53 +02:00
}
2016-09-07 20:20:36 +02:00
return CsIdAlias;
2021-03-18 20:55:14 +01:00
case cs_ident_type::SVAR:
2016-09-07 20:20:36 +02:00
return CsIdSvar;
2021-03-18 20:55:14 +01:00
case cs_ident_type::IVAR:
2016-09-07 20:20:36 +02:00
return CsIdIvar;
2021-03-18 20:55:14 +01:00
case cs_ident_type::FVAR:
2016-09-07 20:20:36 +02:00
return CsIdFvar;
2021-03-18 20:55:14 +01:00
case cs_ident_type::COMMAND: {
arg.set_none();
cs_valarray<cs_value, MaxArguments> buf{cs};
callcommand(cs, static_cast<cs_command *>(id), &buf[0], arg, 0, true);
2021-03-18 20:55:14 +01:00
force_arg(arg, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
return -2; /* ignore */
}
default:
2016-09-07 20:20:36 +02:00
return CsIdUnknown;
2016-08-17 04:57:53 +02:00
}
}
2021-03-17 21:57:47 +01:00
throw cs_error(cs, "unknown alias lookup: %s", arg.get_str());
2016-08-17 04:57:53 +02:00
}
2017-02-13 18:10:40 +01:00
static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) {
2021-03-18 20:55:14 +01:00
result.set_none();
2016-09-23 21:04:52 +02:00
RunDepthRef level{cs}; /* incr and decr on scope exit */
2016-08-12 18:38:43 +02:00
int numargs = 0;
cs_valarray<cs_value, MaxArguments + MaxResults> args{cs};
auto &chook = cs.get_call_hook();
if (chook) {
chook(cs);
}
2016-08-12 18:38:43 +02:00
for (;;) {
2017-01-25 02:10:17 +01:00
uint32_t op = *code++;
2016-08-12 18:38:43 +02:00
switch (op & 0xFF) {
2021-03-18 20:55:14 +01:00
case CS_CODE_START:
case CS_CODE_OFFSET:
2016-08-17 04:57:53 +02:00
continue;
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_NULL | CS_RET_NULL:
result.set_none();
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_NULL | CS_RET_STRING:
2016-08-17 04:57:53 +02:00
result.set_str("");
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_NULL | CS_RET_INT:
2016-08-17 04:57:53 +02:00
result.set_int(0);
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_NULL | CS_RET_FLOAT:
2016-08-17 04:57:53 +02:00
result.set_float(0.0f);
continue;
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_FALSE | CS_RET_STRING:
2016-08-17 04:57:53 +02:00
result.set_str("0");
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_FALSE | CS_RET_NULL:
case CS_CODE_FALSE | CS_RET_INT:
2016-08-17 04:57:53 +02:00
result.set_int(0);
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_FALSE | CS_RET_FLOAT:
2016-08-17 04:57:53 +02:00
result.set_float(0.0f);
continue;
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_TRUE | CS_RET_STRING:
2016-08-17 04:57:53 +02:00
result.set_str("1");
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_TRUE | CS_RET_NULL:
case CS_CODE_TRUE | CS_RET_INT:
2016-08-17 04:57:53 +02:00
result.set_int(1);
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_TRUE | CS_RET_FLOAT:
2016-08-17 04:57:53 +02:00
result.set_float(1.0f);
continue;
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_NOT | CS_RET_STRING:
2016-08-17 04:57:53 +02:00
--numargs;
result.set_str(args[numargs].get_bool() ? "0" : "1");
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_NOT | CS_RET_NULL:
case CS_CODE_NOT | CS_RET_INT:
2016-08-17 04:57:53 +02:00
--numargs;
result.set_int(!args[numargs].get_bool());
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_NOT | CS_RET_FLOAT:
2016-08-17 04:57:53 +02:00
--numargs;
2017-02-13 18:10:40 +01:00
result.set_float(cs_float(!args[numargs].get_bool()));
2016-08-17 04:57:53 +02:00
continue;
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_POP:
numargs -= 1;
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_ENTER:
2016-08-17 04:57:53 +02:00
code = runcode(cs, code, args[numargs++]);
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_ENTER_RESULT:
2016-08-17 04:57:53 +02:00
code = runcode(cs, code, result);
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_EXIT | CS_RET_STRING:
case CS_CODE_EXIT | CS_RET_INT:
case CS_CODE_EXIT | CS_RET_FLOAT:
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
/* fallthrough */
2021-03-18 20:55:14 +01:00
case CS_CODE_EXIT | CS_RET_NULL:
2016-09-23 21:06:44 +02:00
return code;
2021-03-18 20:55:14 +01:00
case CS_CODE_RESULT_ARG | CS_RET_STRING:
case CS_CODE_RESULT_ARG | CS_RET_INT:
case CS_CODE_RESULT_ARG | CS_RET_FLOAT:
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
/* fallthrough */
2021-03-18 20:55:14 +01:00
case CS_CODE_RESULT_ARG | CS_RET_NULL:
2017-01-25 01:57:33 +01:00
args[numargs++] = std::move(result);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_PRINT:
2021-03-18 00:03:30 +01:00
cs.print_var(*static_cast<cs_var *>(cs.p_state->identmap[op >> 8]));
2016-08-17 04:57:53 +02:00
continue;
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_LOCAL: {
2016-08-17 04:57:53 +02:00
int numlocals = op >> 8, offset = numargs - numlocals;
cs_valarray<cs_ident_stack, MaxArguments> locals{cs};
2016-08-17 04:57:53 +02:00
for (int i = 0; i < numlocals; ++i) {
cs_push_alias(cs, args[offset + i].get_ident(), locals[i]);
2016-08-17 04:57:53 +02:00
}
cs_do_and_cleanup([&]() {
code = runcode(cs, code, result);
}, [&]() {
for (int i = offset; i < numargs; i++) {
cs_pop_alias(args[i].get_ident());
}
});
2016-09-23 21:06:44 +02:00
return code;
2016-08-17 04:57:53 +02:00
}
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_DO_ARGS | CS_RET_NULL:
case CS_CODE_DO_ARGS | CS_RET_STRING:
case CS_CODE_DO_ARGS | CS_RET_INT:
case CS_CODE_DO_ARGS | CS_RET_FLOAT:
2016-09-10 19:54:55 +02:00
cs_do_args(cs, [&]() {
cs.run(args[--numargs].get_code(), result);
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-09-10 19:54:55 +02:00
});
continue;
2016-08-17 04:57:53 +02:00
/* fallthrough */
2021-03-18 20:55:14 +01:00
case CS_CODE_DO | CS_RET_NULL:
case CS_CODE_DO | CS_RET_STRING:
case CS_CODE_DO | CS_RET_INT:
case CS_CODE_DO | CS_RET_FLOAT:
cs.run(args[--numargs].get_code(), result);
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
continue;
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_JUMP: {
2017-01-25 02:10:17 +01:00
uint32_t len = op >> 8;
2016-08-17 04:57:53 +02:00
code += len;
2016-08-12 18:38:43 +02:00
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_JUMP_B | CS_CODE_FLAG_TRUE: {
2017-01-25 02:10:17 +01:00
uint32_t len = op >> 8;
2016-08-17 04:57:53 +02:00
if (args[--numargs].get_bool()) {
code += len;
}
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_JUMP_B | CS_CODE_FLAG_FALSE: {
2017-01-25 02:10:17 +01:00
uint32_t len = op >> 8;
2016-08-17 04:57:53 +02:00
if (!args[--numargs].get_bool()) {
code += len;
}
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_JUMP_RESULT | CS_CODE_FLAG_TRUE: {
2017-01-25 02:10:17 +01:00
uint32_t len = op >> 8;
2016-08-17 04:57:53 +02:00
--numargs;
2021-03-18 20:55:14 +01:00
if (args[numargs].get_type() == cs_value_type::CODE) {
cs.run(args[numargs].get_code(), result);
2016-08-17 04:57:53 +02:00
} else {
2017-01-25 01:57:33 +01:00
result = std::move(args[numargs]);
2016-08-17 04:57:53 +02:00
}
if (result.get_bool()) {
code += len;
}
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_JUMP_RESULT | CS_CODE_FLAG_FALSE: {
2017-01-25 02:10:17 +01:00
uint32_t len = op >> 8;
2016-08-17 04:57:53 +02:00
--numargs;
2021-03-18 20:55:14 +01:00
if (args[numargs].get_type() == cs_value_type::CODE) {
cs.run(args[numargs].get_code(), result);
2016-08-17 04:57:53 +02:00
} else {
2017-01-25 01:57:33 +01:00
result = std::move(args[numargs]);
2016-08-17 04:57:53 +02:00
}
if (!result.get_bool()) {
code += len;
}
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_BREAK | CS_CODE_FLAG_FALSE:
2016-09-15 02:12:22 +02:00
if (cs.is_in_loop()) {
throw CsBreakException();
} else {
2017-02-13 18:10:40 +01:00
throw cs_error(cs, "no loop to break");
2016-09-15 02:12:22 +02:00
}
break;
2021-03-18 20:55:14 +01:00
case CS_CODE_BREAK | CS_CODE_FLAG_TRUE:
2016-09-15 02:12:22 +02:00
if (cs.is_in_loop()) {
throw CsContinueException();
} else {
2017-02-13 18:10:40 +01:00
throw cs_error(cs, "no loop to continue");
2016-09-15 02:12:22 +02:00
}
break;
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_VAL | CS_RET_STRING: {
2017-01-25 02:10:17 +01:00
uint32_t len = op >> 8;
args[numargs++].set_str(std::string_view{
reinterpret_cast<char const *>(code), len
2017-01-30 01:18:55 +01:00
});
2017-01-25 02:10:17 +01:00
code += len / sizeof(uint32_t) + 1;
2016-08-17 04:57:53 +02:00
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_VAL_INT | CS_RET_STRING: {
2016-08-17 04:57:53 +02:00
char s[4] = {
char((op >> 8) & 0xFF),
char((op >> 16) & 0xFF),
char((op >> 24) & 0xFF), '\0'
};
/* gotta cast or r.size() == potentially 3 */
args[numargs++].set_str(static_cast<char const *>(s));
2016-08-17 04:57:53 +02:00
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_VAL | CS_RET_NULL:
case CS_CODE_VAL_INT | CS_RET_NULL:
args[numargs++].set_none();
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_VAL | CS_RET_INT:
args[numargs++].set_int(
2017-02-13 18:10:40 +01:00
*reinterpret_cast<cs_int const *>(code)
);
2017-02-13 18:10:40 +01:00
code += CsTypeStorageSize<cs_int>;
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_VAL_INT | CS_RET_INT:
2017-02-13 18:10:40 +01:00
args[numargs++].set_int(cs_int(op) >> 8);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_VAL | CS_RET_FLOAT:
2016-08-17 04:57:53 +02:00
args[numargs++].set_float(
2017-02-13 18:10:40 +01:00
*reinterpret_cast<cs_float const *>(code)
2016-08-17 04:57:53 +02:00
);
2017-02-13 18:10:40 +01:00
code += CsTypeStorageSize<cs_float>;
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_VAL_INT | CS_RET_FLOAT:
2017-02-13 18:10:40 +01:00
args[numargs++].set_float(cs_float(cs_int(op) >> 8));
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_DUP | CS_RET_NULL:
2016-08-17 04:57:53 +02:00
args[numargs - 1].get_val(args[numargs]);
numargs++;
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_DUP | CS_RET_INT:
2016-08-17 04:57:53 +02:00
args[numargs].set_int(args[numargs - 1].get_int());
numargs++;
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_DUP | CS_RET_FLOAT:
2016-08-17 04:57:53 +02:00
args[numargs].set_float(args[numargs - 1].get_float());
numargs++;
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_DUP | CS_RET_STRING:
args[numargs] = args[numargs - 1];
args[numargs].force_str();
2016-08-17 04:57:53 +02:00
numargs++;
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_FORCE | CS_RET_STRING:
2016-08-17 04:57:53 +02:00
args[numargs - 1].force_str();
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_FORCE | CS_RET_INT:
2016-08-17 04:57:53 +02:00
args[numargs - 1].force_int();
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_FORCE | CS_RET_FLOAT:
2016-08-17 04:57:53 +02:00
args[numargs - 1].force_float();
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_RESULT | CS_RET_NULL:
2017-01-25 01:57:33 +01:00
result = std::move(args[--numargs]);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_RESULT | CS_RET_STRING:
case CS_CODE_RESULT | CS_RET_INT:
case CS_CODE_RESULT | CS_RET_FLOAT:
2017-01-25 01:57:33 +01:00
result = std::move(args[--numargs]);
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_EMPTY | CS_RET_NULL:
2016-08-17 04:57:53 +02:00
args[numargs++].set_code(
2021-03-18 20:55:14 +01:00
reinterpret_cast<cs_bcode *>(emptyblock[CS_VAL_NULL] + 1)
2016-08-17 04:57:53 +02:00
);
2016-08-12 18:38:43 +02:00
break;
2021-03-18 20:55:14 +01:00
case CS_CODE_EMPTY | CS_RET_STRING:
2016-08-17 04:57:53 +02:00
args[numargs++].set_code(
2021-03-18 20:55:14 +01:00
reinterpret_cast<cs_bcode *>(emptyblock[CS_VAL_STRING] + 1)
2016-08-17 04:57:53 +02:00
);
2016-08-12 18:38:43 +02:00
break;
2021-03-18 20:55:14 +01:00
case CS_CODE_EMPTY | CS_RET_INT:
2016-08-17 04:57:53 +02:00
args[numargs++].set_code(
2021-03-18 20:55:14 +01:00
reinterpret_cast<cs_bcode *>(emptyblock[CS_VAL_INT] + 1)
2016-08-17 04:57:53 +02:00
);
2016-08-12 18:38:43 +02:00
break;
2021-03-18 20:55:14 +01:00
case CS_CODE_EMPTY | CS_RET_FLOAT:
2016-08-17 04:57:53 +02:00
args[numargs++].set_code(
2021-03-18 20:55:14 +01:00
reinterpret_cast<cs_bcode *>(emptyblock[CS_VAL_FLOAT] + 1)
2016-08-17 04:57:53 +02:00
);
2016-08-12 18:38:43 +02:00
break;
2021-03-18 20:55:14 +01:00
case CS_CODE_BLOCK: {
2017-01-25 02:10:17 +01:00
uint32_t len = op >> 8;
2016-08-17 04:57:53 +02:00
args[numargs++].set_code(
2017-02-13 18:10:40 +01:00
reinterpret_cast<cs_bcode *>(code + 1)
2016-08-17 04:57:53 +02:00
);
code += len;
continue;
2016-08-12 18:38:43 +02:00
}
2021-03-18 20:55:14 +01:00
case CS_CODE_COMPILE: {
2017-02-13 18:10:40 +01:00
cs_value &arg = args[numargs - 1];
cs_gen_state gs(cs);
2016-08-17 04:57:53 +02:00
switch (arg.get_type()) {
2021-03-18 20:55:14 +01:00
case cs_value_type::INT:
2016-08-17 04:57:53 +02:00
gs.code.reserve(8);
2021-03-18 20:55:14 +01:00
gs.code.push_back(CS_CODE_START);
2016-08-30 22:55:35 +02:00
gs.gen_int(arg.get_int());
2021-03-18 20:55:14 +01:00
gs.code.push_back(CS_CODE_RESULT);
gs.code.push_back(CS_CODE_EXIT);
2016-08-17 04:57:53 +02:00
break;
2021-03-18 20:55:14 +01:00
case cs_value_type::FLOAT:
2016-08-17 04:57:53 +02:00
gs.code.reserve(8);
2021-03-18 20:55:14 +01:00
gs.code.push_back(CS_CODE_START);
2016-08-30 22:55:35 +02:00
gs.gen_float(arg.get_float());
2021-03-18 20:55:14 +01:00
gs.code.push_back(CS_CODE_RESULT);
gs.code.push_back(CS_CODE_EXIT);
2016-08-17 04:57:53 +02:00
break;
2021-03-18 20:55:14 +01:00
case cs_value_type::STRING:
2016-08-17 04:57:53 +02:00
gs.code.reserve(64);
2021-03-17 21:57:47 +01:00
gs.gen_main(arg.get_str());
2016-08-17 04:57:53 +02:00
break;
default:
gs.code.reserve(8);
2021-03-18 20:55:14 +01:00
gs.code.push_back(CS_CODE_START);
2016-08-17 04:57:53 +02:00
gs.gen_null();
2021-03-18 20:55:14 +01:00
gs.code.push_back(CS_CODE_RESULT);
gs.code.push_back(CS_CODE_EXIT);
2016-08-17 04:57:53 +02:00
break;
}
gs.done();
2017-01-25 01:18:29 +01:00
uint32_t *cbuf = new uint32_t[gs.code.size()];
memcpy(cbuf, gs.code.data(), gs.code.size() * sizeof(uint32_t));
2016-08-17 04:57:53 +02:00
arg.set_code(
2017-02-13 18:10:40 +01:00
reinterpret_cast<cs_bcode *>(cbuf + 1)
2016-08-17 04:57:53 +02:00
);
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_COND: {
2017-02-13 18:10:40 +01:00
cs_value &arg = args[numargs - 1];
2016-08-17 04:57:53 +02:00
switch (arg.get_type()) {
2021-03-18 20:55:14 +01:00
case cs_value_type::STRING: {
std::string_view s = arg.get_str();
2016-08-30 22:55:35 +02:00
if (!s.empty()) {
2017-02-13 18:10:40 +01:00
cs_gen_state gs(cs);
2016-08-17 04:57:53 +02:00
gs.code.reserve(64);
2016-08-30 22:55:35 +02:00
gs.gen_main(s);
gs.done();
2017-01-25 01:18:29 +01:00
uint32_t *cbuf = new uint32_t[gs.code.size()];
memcpy(
cbuf, gs.code.data(),
gs.code.size() * sizeof(uint32_t)
);
2017-02-13 18:10:40 +01:00
arg.set_code(reinterpret_cast<cs_bcode *>(cbuf + 1));
2016-08-17 04:57:53 +02:00
} else {
2021-03-18 20:55:14 +01:00
arg.force_none();
2016-08-17 04:57:53 +02:00
}
break;
2016-08-30 22:55:35 +02:00
}
default:
break;
2016-08-17 04:57:53 +02:00
}
continue;
2016-08-12 18:38:43 +02:00
}
2021-03-18 20:55:14 +01:00
case CS_CODE_IDENT:
args[numargs++].set_ident(cs.p_state->identmap[op >> 8]);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_IDENT_ARG: {
2017-02-13 18:10:40 +01:00
cs_alias *a = static_cast<cs_alias *>(
cs.p_state->identmap[op >> 8]
);
2016-09-10 19:54:55 +02:00
if (!cs_is_arg_used(cs, a)) {
cs_value nv{cs};
2018-04-27 23:53:55 +02:00
cs_alias_internal::push_arg(
a, nv, cs.p_callstack->argstack[a->get_index()], false
2016-08-18 03:53:51 +02:00
);
cs.p_callstack->usedargs |= 1 << a->get_index();
2016-08-17 04:57:53 +02:00
}
2016-08-18 00:06:39 +02:00
args[numargs++].set_ident(a);
2016-08-17 04:57:53 +02:00
continue;
2016-08-12 18:38:43 +02:00
}
2021-03-18 20:55:14 +01:00
case CS_CODE_IDENT_U: {
2017-02-13 18:10:40 +01:00
cs_value &arg = args[numargs - 1];
cs_ident *id = cs.p_state->identmap[DummyIdx];
2021-03-18 20:55:14 +01:00
if (arg.get_type() == cs_value_type::STRING) {
2021-03-17 21:57:47 +01:00
id = cs.new_ident(arg.get_str());
2016-08-17 04:57:53 +02:00
}
2016-09-10 19:54:55 +02:00
if ((id->get_index() < MaxArguments) && !cs_is_arg_used(cs, id)) {
cs_value nv{cs};
2018-04-27 23:53:55 +02:00
cs_alias_internal::push_arg(
2017-02-13 18:10:40 +01:00
static_cast<cs_alias *>(id), nv,
cs.p_callstack->argstack[id->get_index()], false
2016-08-18 00:06:39 +02:00
);
cs.p_callstack->usedargs |= 1 << id->get_index();
2016-08-17 04:57:53 +02:00
}
arg.set_ident(id);
continue;
2016-08-12 18:38:43 +02:00
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_U | CS_RET_STRING: {
2017-02-13 18:10:40 +01:00
cs_ident *id = nullptr;
cs_value &arg = args[numargs - 1];
2016-08-17 04:57:53 +02:00
switch (cs_get_lookupu_type(cs, arg, id, op)) {
2016-09-07 20:20:36 +02:00
case CsIdAlias:
arg = static_cast<cs_alias *>(id)->get_value();
arg.force_str();
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdSvar:
arg.set_str(static_cast<cs_svar *>(id)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdIvar:
arg.set_int(static_cast<cs_ivar *>(id)->get_value());
arg.force_str();
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdFvar:
arg.set_float(static_cast<cs_fvar *>(id)->get_value());
arg.force_str();
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdUnknown:
2016-08-17 04:57:53 +02:00
arg.set_str("");
continue;
default:
continue;
}
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP | CS_RET_STRING:
args[numargs] = cs_get_lookup_id(cs, op)->get_value();
args[numargs++].force_str();
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_ARG | CS_RET_STRING: {
2017-02-13 18:10:40 +01:00
cs_alias *a = cs_get_lookuparg_id(cs, op);
2016-08-18 00:18:36 +02:00
if (!a) {
2016-08-17 04:57:53 +02:00
args[numargs++].set_str("");
} else {
args[numargs] = a->get_value();
args[numargs++].force_str();
2016-08-17 04:57:53 +02:00
}
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_U | CS_RET_INT: {
2017-02-13 18:10:40 +01:00
cs_ident *id = nullptr;
cs_value &arg = args[numargs - 1];
2016-08-17 04:57:53 +02:00
switch (cs_get_lookupu_type(cs, arg, id, op)) {
2016-09-07 20:20:36 +02:00
case CsIdAlias:
2016-08-31 20:18:53 +02:00
arg.set_int(
2017-02-13 18:10:40 +01:00
static_cast<cs_alias *>(id)->get_value().get_int()
2016-08-31 20:18:53 +02:00
);
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdSvar:
arg.set_int(cs_parse_int(
2017-02-13 18:10:40 +01:00
static_cast<cs_svar *>(id)->get_value()
));
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdIvar:
2017-02-13 18:10:40 +01:00
arg.set_int(static_cast<cs_ivar *>(id)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdFvar:
2016-08-18 04:14:55 +02:00
arg.set_int(
2017-02-13 18:10:40 +01:00
cs_int(static_cast<cs_fvar *>(id)->get_value())
2016-08-18 04:14:55 +02:00
);
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdUnknown:
2016-08-17 04:57:53 +02:00
arg.set_int(0);
continue;
default:
continue;
2016-08-12 18:38:43 +02:00
}
2016-08-17 04:57:53 +02:00
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP | CS_RET_INT:
2016-08-17 04:57:53 +02:00
args[numargs++].set_int(
2016-08-31 20:18:53 +02:00
cs_get_lookup_id(cs, op)->get_value().get_int()
2016-08-17 04:57:53 +02:00
);
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_ARG | CS_RET_INT: {
2017-02-13 18:10:40 +01:00
cs_alias *a = cs_get_lookuparg_id(cs, op);
2016-08-18 00:18:36 +02:00
if (!a) {
2016-08-17 04:57:53 +02:00
args[numargs++].set_int(0);
} else {
2016-08-31 20:18:53 +02:00
args[numargs++].set_int(a->get_value().get_int());
2016-08-12 18:38:43 +02:00
}
2016-08-17 04:57:53 +02:00
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_U | CS_RET_FLOAT: {
2017-02-13 18:10:40 +01:00
cs_ident *id = nullptr;
cs_value &arg = args[numargs - 1];
2016-08-17 04:57:53 +02:00
switch (cs_get_lookupu_type(cs, arg, id, op)) {
2016-09-07 20:20:36 +02:00
case CsIdAlias:
arg.set_float(
2017-02-13 18:10:40 +01:00
static_cast<cs_alias *>(id)->get_value().get_float()
);
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdSvar:
arg.set_float(cs_parse_float(
2017-02-13 18:10:40 +01:00
static_cast<cs_svar *>(id)->get_value()
));
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdIvar:
2017-02-13 18:10:40 +01:00
arg.set_float(cs_float(
static_cast<cs_ivar *>(id)->get_value()
));
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdFvar:
2016-08-18 04:14:55 +02:00
arg.set_float(
2017-02-13 18:10:40 +01:00
static_cast<cs_fvar *>(id)->get_value()
2016-08-18 04:14:55 +02:00
);
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdUnknown:
2017-02-13 18:10:40 +01:00
arg.set_float(cs_float(0));
2016-08-17 04:57:53 +02:00
continue;
default:
continue;
2016-08-12 18:38:43 +02:00
}
2016-08-17 04:57:53 +02:00
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP | CS_RET_FLOAT:
2016-08-17 04:57:53 +02:00
args[numargs++].set_float(
2016-08-31 20:18:53 +02:00
cs_get_lookup_id(cs, op)->get_value().get_float()
2016-08-17 04:57:53 +02:00
);
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_ARG | CS_RET_FLOAT: {
2017-02-13 18:10:40 +01:00
cs_alias *a = cs_get_lookuparg_id(cs, op);
2016-08-18 00:18:36 +02:00
if (!a) {
2017-02-13 18:10:40 +01:00
args[numargs++].set_float(cs_float(0));
2016-08-17 04:57:53 +02:00
} else {
2016-08-31 20:18:53 +02:00
args[numargs++].set_float(a->get_value().get_float());
2016-08-17 04:57:53 +02:00
}
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_U | CS_RET_NULL: {
2017-02-13 18:10:40 +01:00
cs_ident *id = nullptr;
cs_value &arg = args[numargs - 1];
2016-08-17 04:57:53 +02:00
switch (cs_get_lookupu_type(cs, arg, id, op)) {
2016-09-07 20:20:36 +02:00
case CsIdAlias:
2017-02-13 18:10:40 +01:00
static_cast<cs_alias *>(id)->get_value().get_val(arg);
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdSvar:
arg.set_str(static_cast<cs_svar *>(id)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdIvar:
2017-02-13 18:10:40 +01:00
arg.set_int(static_cast<cs_ivar *>(id)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdFvar:
2016-08-18 04:14:55 +02:00
arg.set_float(
2017-02-13 18:10:40 +01:00
static_cast<cs_fvar *>(id)->get_value()
2016-08-18 04:14:55 +02:00
);
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdUnknown:
2021-03-18 20:55:14 +01:00
arg.set_none();
2016-08-17 04:57:53 +02:00
continue;
default:
continue;
}
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP | CS_RET_NULL:
2016-08-31 20:18:53 +02:00
cs_get_lookup_id(cs, op)->get_value().get_val(args[numargs++]);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_ARG | CS_RET_NULL: {
2017-02-13 18:10:40 +01:00
cs_alias *a = cs_get_lookuparg_id(cs, op);
2016-08-18 00:18:36 +02:00
if (!a) {
2021-03-18 20:55:14 +01:00
args[numargs++].set_none();
2016-08-17 04:57:53 +02:00
} else {
2016-08-31 20:18:53 +02:00
a->get_value().get_val(args[numargs++]);
2016-08-17 04:57:53 +02:00
}
continue;
2016-08-12 18:38:43 +02:00
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_MU | CS_RET_STRING: {
2017-02-13 18:10:40 +01:00
cs_ident *id = nullptr;
cs_value &arg = args[numargs - 1];
2016-08-17 04:57:53 +02:00
switch (cs_get_lookupu_type(cs, arg, id, op)) {
2016-09-07 20:20:36 +02:00
case CsIdAlias:
arg = static_cast<cs_alias *>(id)->get_value();
arg.force_str();
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdSvar:
arg.set_str(static_cast<cs_svar *>(id)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdIvar:
arg.set_int(static_cast<cs_ivar *>(id)->get_value());
arg.force_str();
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdFvar:
arg.set_float(static_cast<cs_fvar *>(id)->get_value());
arg.force_str();
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdUnknown:
arg.set_str("");
2016-08-17 04:57:53 +02:00
continue;
default:
continue;
}
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_M | CS_RET_STRING:
args[numargs] = cs_get_lookup_id(cs, op)->get_value();
args[numargs++].force_str();
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_MARG | CS_RET_STRING: {
2017-02-13 18:10:40 +01:00
cs_alias *a = cs_get_lookuparg_id(cs, op);
2016-08-18 00:18:36 +02:00
if (!a) {
args[numargs++].set_str("");
2016-08-17 04:57:53 +02:00
} else {
args[numargs] = a->get_value();
args[numargs++].force_str();
2016-08-17 04:57:53 +02:00
}
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_MU | CS_RET_NULL: {
2017-02-13 18:10:40 +01:00
cs_ident *id = nullptr;
cs_value &arg = args[numargs - 1];
2016-08-17 04:57:53 +02:00
switch (cs_get_lookupu_type(cs, arg, id, op)) {
2016-09-07 20:20:36 +02:00
case CsIdAlias:
2017-02-13 18:10:40 +01:00
static_cast<cs_alias *>(id)->get_cval(arg);
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdSvar:
arg.set_str(static_cast<cs_svar *>(id)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdIvar:
2017-02-13 18:10:40 +01:00
arg.set_int(static_cast<cs_ivar *>(id)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdFvar:
2017-02-13 18:10:40 +01:00
arg.set_float(static_cast<cs_fvar *>(id)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdUnknown:
2021-03-18 20:55:14 +01:00
arg.set_none();
2016-08-17 04:57:53 +02:00
continue;
default:
continue;
}
}
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_M | CS_RET_NULL:
2016-08-17 04:57:53 +02:00
cs_get_lookup_id(cs, op)->get_cval(args[numargs++]);
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_LOOKUP_MARG | CS_RET_NULL: {
2017-02-13 18:10:40 +01:00
cs_alias *a = cs_get_lookuparg_id(cs, op);
2016-08-18 00:18:36 +02:00
if (!a) {
2021-03-18 20:55:14 +01:00
args[numargs++].set_none();
2016-08-17 04:57:53 +02:00
} else {
2016-08-18 00:18:36 +02:00
a->get_cval(args[numargs++]);
2016-08-17 04:57:53 +02:00
}
continue;
2016-08-12 18:38:43 +02:00
}
2021-03-18 20:55:14 +01:00
case CS_CODE_SVAR | CS_RET_STRING:
case CS_CODE_SVAR | CS_RET_NULL:
args[numargs++].set_str(static_cast<cs_svar *>(
cs.p_state->identmap[op >> 8]
)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_SVAR | CS_RET_INT:
2017-02-13 18:10:40 +01:00
args[numargs++].set_int(cs_parse_int(static_cast<cs_svar *>(
cs.p_state->identmap[op >> 8]
)->get_value()));
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_SVAR | CS_RET_FLOAT:
2017-02-13 18:10:40 +01:00
args[numargs++].set_float(cs_parse_float(static_cast<cs_svar *>(
cs.p_state->identmap[op >> 8]
)->get_value()));
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_SVAR1:
2016-08-17 23:29:31 +02:00
cs.set_var_str_checked(
2017-02-13 18:10:40 +01:00
static_cast<cs_svar *>(cs.p_state->identmap[op >> 8]),
2021-03-17 21:57:47 +01:00
args[--numargs].get_str()
2016-08-17 23:29:31 +02:00
);
2016-08-17 04:57:53 +02:00
continue;
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_IVAR | CS_RET_INT:
case CS_CODE_IVAR | CS_RET_NULL:
2017-02-13 18:10:40 +01:00
args[numargs++].set_int(static_cast<cs_ivar *>(
cs.p_state->identmap[op >> 8]
)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_IVAR | CS_RET_STRING:
args[numargs].set_int(static_cast<cs_ivar *>(
cs.p_state->identmap[op >> 8]
)->get_value());
args[numargs++].force_str();
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_IVAR | CS_RET_FLOAT:
2017-02-13 18:10:40 +01:00
args[numargs++].set_float(cs_float(static_cast<cs_ivar *>(
cs.p_state->identmap[op >> 8]
)->get_value()));
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_IVAR1:
2016-08-17 23:29:31 +02:00
cs.set_var_int_checked(
2017-02-13 18:10:40 +01:00
static_cast<cs_ivar *>(cs.p_state->identmap[op >> 8]),
2016-08-30 22:55:35 +02:00
args[--numargs].get_int()
2016-08-17 23:29:31 +02:00
);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_IVAR2:
2016-08-17 04:57:53 +02:00
numargs -= 2;
cs.set_var_int_checked(
2017-02-13 18:10:40 +01:00
static_cast<cs_ivar *>(cs.p_state->identmap[op >> 8]),
2016-08-30 22:55:35 +02:00
(args[numargs].get_int() << 16)
| (args[numargs + 1].get_int() << 8)
);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_IVAR3:
2016-08-17 04:57:53 +02:00
numargs -= 3;
cs.set_var_int_checked(
2017-02-13 18:10:40 +01:00
static_cast<cs_ivar *>(cs.p_state->identmap[op >> 8]),
2016-08-30 22:55:35 +02:00
(args[numargs].get_int() << 16)
| (args[numargs + 1].get_int() << 8)
| (args[numargs + 2].get_int()));
2016-08-17 04:57:53 +02:00
continue;
2016-08-12 18:38:43 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_FVAR | CS_RET_FLOAT:
case CS_CODE_FVAR | CS_RET_NULL:
2017-02-13 18:10:40 +01:00
args[numargs++].set_float(static_cast<cs_fvar *>(
cs.p_state->identmap[op >> 8]
)->get_value());
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_FVAR | CS_RET_STRING:
args[numargs].set_int(static_cast<cs_fvar *>(
cs.p_state->identmap[op >> 8]
)->get_value());
args[numargs++].force_str();
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_FVAR | CS_RET_INT:
2017-02-13 18:10:40 +01:00
args[numargs++].set_int(int(static_cast<cs_fvar *>(
cs.p_state->identmap[op >> 8]
)->get_value()));
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_FVAR1:
2016-08-17 23:29:31 +02:00
cs.set_var_float_checked(
2017-02-13 18:10:40 +01:00
static_cast<cs_fvar *>(cs.p_state->identmap[op >> 8]),
2016-08-30 22:55:35 +02:00
args[--numargs].get_float()
2016-08-17 23:29:31 +02:00
);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_COM | CS_RET_NULL:
case CS_CODE_COM | CS_RET_STRING:
case CS_CODE_COM | CS_RET_FLOAT:
case CS_CODE_COM | CS_RET_INT: {
2017-02-13 18:10:40 +01:00
cs_command *id = static_cast<cs_command *>(
cs.p_state->identmap[op >> 8]
);
int offset = numargs - id->get_num_args();
2021-03-18 20:55:14 +01:00
result.force_none();
2021-03-20 05:41:25 +01:00
cs_cmd_internal::call(cs, id, std::span<cs_value>{
&args[0] + offset, std::size_t(id->get_num_args())
}, result);
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
numargs = offset;
2016-08-17 04:57:53 +02:00
continue;
2016-08-12 18:38:43 +02:00
}
2016-08-17 04:57:53 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_COM_V | CS_RET_NULL:
case CS_CODE_COM_V | CS_RET_STRING:
case CS_CODE_COM_V | CS_RET_FLOAT:
case CS_CODE_COM_V | CS_RET_INT: {
2017-02-13 18:10:40 +01:00
cs_command *id = static_cast<cs_command *>(
cs.p_state->identmap[op >> 13]
);
2021-03-20 05:41:25 +01:00
std::size_t callargs = (op >> 8) & 0x1F,
offset = numargs - callargs;
2021-03-18 20:55:14 +01:00
result.force_none();
2021-03-20 05:41:25 +01:00
cs_cmd_internal::call(
cs, id, std::span{&args[offset], callargs}, result
);
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
numargs = offset;
2016-08-12 18:38:43 +02:00
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_COM_C | CS_RET_NULL:
case CS_CODE_COM_C | CS_RET_STRING:
case CS_CODE_COM_C | CS_RET_FLOAT:
case CS_CODE_COM_C | CS_RET_INT: {
2017-02-13 18:10:40 +01:00
cs_command *id = static_cast<cs_command *>(
cs.p_state->identmap[op >> 13]
);
2021-03-20 05:41:25 +01:00
std::size_t callargs = (op >> 8) & 0x1F,
offset = numargs - callargs;
2021-03-18 20:55:14 +01:00
result.force_none();
2016-08-17 04:57:53 +02:00
{
cs_value tv{cs};
2021-03-20 05:41:25 +01:00
tv.set_str(value_list_concat(cs, std::span{
&args[offset], callargs
}, " "));
cs_cmd_internal::call(
cs, id, std::span<cs_value>{&tv, 1}, result
);
2016-08-17 04:57:53 +02:00
}
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
numargs = offset;
2016-08-17 04:57:53 +02:00
continue;
2016-08-12 18:38:43 +02:00
}
2016-08-17 04:57:53 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_CONC | CS_RET_NULL:
case CS_CODE_CONC | CS_RET_STRING:
case CS_CODE_CONC | CS_RET_FLOAT:
case CS_CODE_CONC | CS_RET_INT:
case CS_CODE_CONC_W | CS_RET_NULL:
case CS_CODE_CONC_W | CS_RET_STRING:
case CS_CODE_CONC_W | CS_RET_FLOAT:
case CS_CODE_CONC_W | CS_RET_INT: {
2021-03-20 05:41:25 +01:00
std::size_t numconc = op >> 8;
auto buf = value_list_concat(
2021-03-20 05:41:25 +01:00
cs, std::span{&args[numargs - numconc], numconc},
2021-03-18 20:55:14 +01:00
((op & CS_CODE_OP_MASK) == CS_CODE_CONC) ? " " : ""
2016-08-17 04:57:53 +02:00
);
numargs = numargs - numconc;
args[numargs].set_str(buf);
2021-03-18 20:55:14 +01:00
force_arg(args[numargs], op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
numargs++;
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_CONC_M | CS_RET_NULL:
case CS_CODE_CONC_M | CS_RET_STRING:
case CS_CODE_CONC_M | CS_RET_FLOAT:
case CS_CODE_CONC_M | CS_RET_INT: {
2021-03-20 05:41:25 +01:00
std::size_t numconc = op >> 8;
auto buf = value_list_concat(
2021-03-20 05:41:25 +01:00
cs, std::span{&args[numargs - numconc], numconc}
2016-08-17 04:57:53 +02:00
);
numargs = numargs - numconc;
result.set_str(buf);
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-12 18:38:43 +02:00
continue;
}
2016-08-17 04:57:53 +02:00
2021-03-18 20:55:14 +01:00
case CS_CODE_ALIAS:
2018-04-27 23:53:55 +02:00
cs_alias_internal::set_alias(
2017-02-13 18:10:40 +01:00
static_cast<cs_alias *>(cs.p_state->identmap[op >> 8]),
2016-08-18 00:06:39 +02:00
cs, args[--numargs]
);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_ALIAS_ARG:
2018-04-27 23:53:55 +02:00
cs_alias_internal::set_arg(
2017-02-13 18:10:40 +01:00
static_cast<cs_alias *>(cs.p_state->identmap[op >> 8]),
2016-08-18 00:06:39 +02:00
cs, args[--numargs]
);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_ALIAS_U:
2016-08-17 04:57:53 +02:00
numargs -= 2;
2016-09-06 22:57:10 +02:00
cs.set_alias(
2017-01-25 01:57:33 +01:00
args[numargs].get_str(), std::move(args[numargs + 1])
2016-09-06 22:57:10 +02:00
);
2016-08-17 04:57:53 +02:00
continue;
2021-03-18 20:55:14 +01:00
case CS_CODE_CALL | CS_RET_NULL:
case CS_CODE_CALL | CS_RET_STRING:
case CS_CODE_CALL | CS_RET_FLOAT:
case CS_CODE_CALL | CS_RET_INT: {
result.force_none();
2017-02-13 18:10:40 +01:00
cs_ident *id = cs.p_state->identmap[op >> 13];
2016-08-17 04:57:53 +02:00
int callargs = (op >> 8) & 0x1F, offset = numargs - callargs;
2017-02-13 18:10:40 +01:00
if (id->get_flags() & CS_IDF_UNKNOWN) {
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2017-02-13 18:10:40 +01:00
throw cs_error(
2016-09-15 20:55:58 +02:00
cs, "unknown command: %s", id->get_name()
);
2016-08-17 04:57:53 +02:00
}
cs_call_alias(
cs, static_cast<cs_alias *>(id), &args[0], result, callargs,
2016-08-18 00:06:39 +02:00
numargs, offset, 0, op
2016-08-17 04:57:53 +02:00
);
2016-08-12 18:38:43 +02:00
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_CALL_ARG | CS_RET_NULL:
case CS_CODE_CALL_ARG | CS_RET_STRING:
case CS_CODE_CALL_ARG | CS_RET_FLOAT:
case CS_CODE_CALL_ARG | CS_RET_INT: {
result.force_none();
2017-02-13 18:10:40 +01:00
cs_ident *id = cs.p_state->identmap[op >> 13];
2016-08-17 04:57:53 +02:00
int callargs = (op >> 8) & 0x1F, offset = numargs - callargs;
2016-09-10 19:54:55 +02:00
if (!cs_is_arg_used(cs, id)) {
numargs = offset;
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
continue;
}
cs_call_alias(
cs, static_cast<cs_alias *>(id), &args[0], result, callargs,
2016-08-18 00:06:39 +02:00
numargs, offset, 0, op
2016-08-17 04:57:53 +02:00
);
continue;
}
2021-03-18 20:55:14 +01:00
case CS_CODE_CALL_U | CS_RET_NULL:
case CS_CODE_CALL_U | CS_RET_STRING:
case CS_CODE_CALL_U | CS_RET_FLOAT:
case CS_CODE_CALL_U | CS_RET_INT: {
2016-08-17 04:57:53 +02:00
int callargs = op >> 8, offset = numargs - callargs;
2017-02-13 18:10:40 +01:00
cs_value &idarg = args[offset - 1];
2021-03-18 20:55:14 +01:00
if (idarg.get_type() != cs_value_type::STRING) {
2016-08-17 04:57:53 +02:00
litval:
2017-01-25 01:57:33 +01:00
result = std::move(idarg);
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
numargs = offset - 1;
2016-08-17 04:57:53 +02:00
continue;
}
2021-03-17 21:57:47 +01:00
auto idn = idarg.get_str();
cs_ident *id = cs.get_ident(idn);
2016-08-17 04:57:53 +02:00
if (!id) {
noid:
2021-03-17 21:57:47 +01:00
if (cs_check_num(idn)) {
2016-08-17 04:57:53 +02:00
goto litval;
}
2021-03-18 20:55:14 +01:00
result.force_none();
force_arg(result, op & CS_CODE_RET_MASK);
2017-02-13 18:10:40 +01:00
throw cs_error(
cs, "unknown command: %s", std::string_view{idn}
2016-09-15 20:55:58 +02:00
);
2016-08-17 04:57:53 +02:00
}
2021-03-18 20:55:14 +01:00
result.force_none();
2016-08-18 03:53:51 +02:00
switch (id->get_type_raw()) {
2016-08-17 04:57:53 +02:00
default:
2017-02-13 18:10:40 +01:00
if (!cs_cmd_internal::has_cb(id)) {
numargs = offset - 1;
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
continue;
}
/* fallthrough */
2016-09-07 20:20:36 +02:00
case CsIdCommand:
2016-08-17 23:04:43 +02:00
callcommand(
2017-02-13 18:10:40 +01:00
cs, static_cast<cs_command *>(id), &args[offset],
2016-08-17 23:04:43 +02:00
result, callargs
);
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
numargs = offset - 1;
continue;
2016-09-07 20:20:36 +02:00
case CsIdLocal: {
cs_valarray<cs_ident_stack, MaxArguments> locals{cs};
2017-01-25 02:09:50 +01:00
for (size_t j = 0; j < size_t(callargs); ++j) {
cs_push_alias(cs, cs.force_ident(
2016-08-17 04:57:53 +02:00
args[offset + j]
2016-08-18 00:06:39 +02:00
), locals[j]);
2016-08-17 04:57:53 +02:00
}
cs_do_and_cleanup([&]() {
code = runcode(cs, code, result);
}, [&]() {
2017-01-25 02:09:50 +01:00
for (size_t j = 0; j < size_t(callargs); ++j) {
cs_pop_alias(args[offset + j].get_ident());
}
});
2016-09-23 21:06:44 +02:00
return code;
2016-08-17 04:57:53 +02:00
}
2016-09-07 20:20:36 +02:00
case CsIdIvar:
2016-08-17 04:57:53 +02:00
if (callargs <= 0) {
2021-03-18 00:03:30 +01:00
cs.print_var(*static_cast<cs_var *>(id));
2016-08-17 04:57:53 +02:00
} else {
cs.set_var_int_checked(
2017-02-13 18:10:40 +01:00
static_cast<cs_ivar *>(id),
2021-03-20 05:41:25 +01:00
std::span{&args[offset], std::size_t(callargs)}
2016-08-17 04:57:53 +02:00
);
}
numargs = offset - 1;
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdFvar:
2016-08-17 04:57:53 +02:00
if (callargs <= 0) {
2021-03-18 00:03:30 +01:00
cs.print_var(*static_cast<cs_var *>(id));
2016-08-17 04:57:53 +02:00
} else {
cs.set_var_float_checked(
2017-02-13 18:10:40 +01:00
static_cast<cs_fvar *>(id),
2016-08-17 23:29:31 +02:00
args[offset].force_float()
2016-08-17 04:57:53 +02:00
);
}
numargs = offset - 1;
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdSvar:
2016-08-17 04:57:53 +02:00
if (callargs <= 0) {
2021-03-18 00:03:30 +01:00
cs.print_var(*static_cast<cs_var *>(id));
2016-08-17 04:57:53 +02:00
} else {
2016-08-17 23:29:31 +02:00
cs.set_var_str_checked(
2017-02-13 18:10:40 +01:00
static_cast<cs_svar *>(id),
2016-08-17 23:29:31 +02:00
args[offset].force_str()
);
2016-08-17 04:57:53 +02:00
}
numargs = offset - 1;
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
continue;
2016-09-07 20:20:36 +02:00
case CsIdAlias: {
2017-02-13 18:10:40 +01:00
cs_alias *a = static_cast<cs_alias *>(id);
2016-08-17 04:57:53 +02:00
if (
2016-09-10 19:54:55 +02:00
(a->get_index() < MaxArguments) &&
!cs_is_arg_used(cs, a)
2016-08-17 04:57:53 +02:00
) {
numargs = offset - 1;
2021-03-18 20:55:14 +01:00
force_arg(result, op & CS_CODE_RET_MASK);
2016-08-17 04:57:53 +02:00
continue;
}
2021-03-18 20:55:14 +01:00
if (a->get_value().get_type() == cs_value_type::NONE) {
2016-08-17 04:57:53 +02:00
goto noid;
}
cs_call_alias(
cs, a, &args[0], result, callargs, numargs,
2016-08-17 04:57:53 +02:00
offset, 1, op
);
continue;
2016-08-18 00:06:39 +02:00
}
2016-08-17 04:57:53 +02:00
}
}
2016-08-12 18:38:43 +02:00
}
}
return code;
}
2017-02-13 18:10:40 +01:00
void cs_state::run(cs_bcode *code, cs_value &ret) {
2017-01-25 02:10:17 +01:00
runcode(*this, reinterpret_cast<uint32_t *>(code), ret);
2016-08-12 18:38:43 +02:00
}
static void cs_run(
cs_state &cs, std::string_view file, std::string_view code,
2017-02-13 18:10:40 +01:00
cs_value &ret
) {
2017-02-13 18:10:40 +01:00
cs_gen_state gs(cs);
2016-09-22 01:44:35 +02:00
gs.src_name = file;
2016-08-12 18:38:43 +02:00
gs.code.reserve(64);
2021-03-18 20:55:14 +01:00
gs.gen_main(code, CS_VAL_ANY);
gs.done();
2017-01-25 01:18:29 +01:00
uint32_t *cbuf = new uint32_t[gs.code.size()];
memcpy(cbuf, gs.code.data(), gs.code.size() * sizeof(uint32_t));
runcode(cs, cbuf + 1, ret);
if (int(cbuf[0]) < 0x100) {
delete[] cbuf;
2016-08-17 04:57:53 +02:00
}
2016-08-12 18:38:43 +02:00
}
void cs_state::run(std::string_view code, cs_value &ret) {
cs_run(*this, std::string_view{}, code, ret);
}
void cs_state::run(
std::string_view code, cs_value &ret, std::string_view source
) {
cs_run(*this, source, code, ret);
}
2021-03-20 05:41:25 +01:00
void cs_state::run(cs_ident *id, std::span<cs_value> args, cs_value &ret) {
2016-08-12 18:38:43 +02:00
int nargs = int(args.size());
2021-03-18 20:55:14 +01:00
ret.set_none();
2016-09-23 21:04:52 +02:00
RunDepthRef level{*this}; /* incr and decr on scope exit */
if (id) {
2016-08-18 03:53:51 +02:00
switch (id->get_type()) {
2016-08-17 04:57:53 +02:00
default:
2017-02-13 18:10:40 +01:00
if (!cs_cmd_internal::has_cb(id)) {
2016-08-17 04:57:53 +02:00
break;
}
/* fallthrough */
2021-03-18 20:55:14 +01:00
case cs_ident_type::COMMAND:
2017-02-13 18:10:40 +01:00
if (nargs < static_cast<cs_command *>(id)->get_num_args()) {
cs_valarray<cs_value, MaxArguments> buf{*this};
for (std::size_t i = 0; i < args.size(); ++i) {
buf[i] = args[i];
}
2016-08-17 23:04:43 +02:00
callcommand(
*this, static_cast<cs_command *>(id), &buf[0], ret,
2016-08-17 23:04:43 +02:00
nargs, false
);
2016-08-17 04:57:53 +02:00
} else {
2016-08-17 23:04:43 +02:00
callcommand(
2017-02-14 17:41:15 +01:00
*this, static_cast<cs_command *>(id), &args[0],
2016-08-17 23:04:43 +02:00
ret, nargs, false
);
2016-08-17 04:57:53 +02:00
}
nargs = 0;
break;
2021-03-18 20:55:14 +01:00
case cs_ident_type::IVAR:
2016-08-17 04:57:53 +02:00
if (args.empty()) {
2021-03-18 00:03:30 +01:00
print_var(*static_cast<cs_var *>(id));
2016-08-17 04:57:53 +02:00
} else {
2017-02-13 18:10:40 +01:00
set_var_int_checked(static_cast<cs_ivar *>(id), args);
2016-08-17 04:57:53 +02:00
}
break;
2021-03-18 20:55:14 +01:00
case cs_ident_type::FVAR:
2016-08-17 04:57:53 +02:00
if (args.empty()) {
2021-03-18 00:03:30 +01:00
print_var(*static_cast<cs_var *>(id));
2016-08-17 04:57:53 +02:00
} else {
2016-08-17 23:29:31 +02:00
set_var_float_checked(
2017-02-13 18:10:40 +01:00
static_cast<cs_fvar *>(id), args[0].force_float()
2016-08-17 23:29:31 +02:00
);
2016-08-17 04:57:53 +02:00
}
break;
2021-03-18 20:55:14 +01:00
case cs_ident_type::SVAR:
2016-08-17 04:57:53 +02:00
if (args.empty()) {
2021-03-18 00:03:30 +01:00
print_var(*static_cast<cs_var *>(id));
2016-08-17 04:57:53 +02:00
} else {
2016-08-17 23:29:31 +02:00
set_var_str_checked(
2017-02-13 18:10:40 +01:00
static_cast<cs_svar *>(id), args[0].force_str()
2016-08-17 23:29:31 +02:00
);
2016-08-17 04:57:53 +02:00
}
break;
2021-03-18 20:55:14 +01:00
case cs_ident_type::ALIAS: {
2017-02-13 18:10:40 +01:00
cs_alias *a = static_cast<cs_alias *>(id);
2016-09-10 19:54:55 +02:00
if (
(a->get_index() < MaxArguments) && !cs_is_arg_used(*this, a)
) {
break;
2016-08-17 04:57:53 +02:00
}
2021-03-18 20:55:14 +01:00
if (a->get_value().get_type() == cs_value_type::NONE) {
2016-08-17 04:57:53 +02:00
break;
}
cs_call_alias(
2021-03-18 20:55:14 +01:00
*this, a, &args[0], ret, nargs, nargs, 0, 0, CS_RET_NULL
2016-08-17 04:57:53 +02:00
);
break;
2016-08-18 00:06:39 +02:00
}
2016-08-12 18:38:43 +02:00
}
2016-08-17 04:57:53 +02:00
}
2016-08-12 18:38:43 +02:00
}
cs_value cs_state::run(cs_bcode *code) {
cs_value ret{*this};
run(code, ret);
return ret;
2016-08-18 20:34:24 +02:00
}
cs_value cs_state::run(std::string_view code) {
cs_value ret{*this};
run(code, ret);
return ret;
}
cs_value cs_state::run(std::string_view code, std::string_view source) {
cs_value ret{*this};
run(code, ret, source);
return ret;
2016-08-18 20:34:24 +02:00
}
2021-03-20 05:41:25 +01:00
cs_value cs_state::run(cs_ident *id, std::span<cs_value> args) {
cs_value ret{*this};
run(id, args, ret);
return ret;
2016-08-18 20:34:24 +02:00
}
2021-03-18 20:55:14 +01:00
cs_loop_state cs_state::run_loop(cs_bcode *code, cs_value &ret) {
2016-09-14 23:24:13 +02:00
++p_inloop;
try {
run(code, ret);
} catch (CsBreakException) {
--p_inloop;
2021-03-18 20:55:14 +01:00
return cs_loop_state::BREAK;
2016-09-14 23:24:13 +02:00
} catch (CsContinueException) {
--p_inloop;
2021-03-18 20:55:14 +01:00
return cs_loop_state::CONTINUE;
2016-09-14 23:24:13 +02:00
} catch (...) {
--p_inloop;
throw;
}
2021-03-18 20:55:14 +01:00
return cs_loop_state::NORMAL;
2016-09-14 23:24:13 +02:00
}
2021-03-18 20:55:14 +01:00
cs_loop_state cs_state::run_loop(cs_bcode *code) {
cs_value ret{*this};
2016-09-14 23:24:13 +02:00
return run_loop(code, ret);
}
2016-08-12 18:38:43 +02:00
} /* namespace cscript */