2016-08-12 16:38:43 +00:00
|
|
|
#include "cubescript.hh"
|
|
|
|
#include "cs_vm.hh"
|
2016-08-15 01:19:59 +00:00
|
|
|
#include "cs_util.hh"
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-12 23:26:16 +00:00
|
|
|
#include <ostd/memory.hh>
|
|
|
|
|
2016-08-12 16:38:43 +00:00
|
|
|
namespace cscript {
|
|
|
|
|
2016-08-17 21:04:43 +00:00
|
|
|
static inline bool cs_has_cmd_cb(Ident *id) {
|
|
|
|
if ((id->type != ID_COMMAND) && (id->type < ID_LOCAL)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Command *cb = static_cast<Command *>(id);
|
|
|
|
return !!cb->cb_cftv;
|
|
|
|
}
|
|
|
|
|
2016-08-17 22:06:39 +00:00
|
|
|
static inline void cs_push_alias(Ident *id, IdentStack &st) {
|
|
|
|
if ((id->type == ID_ALIAS) && (id->index >= MaxArguments)) {
|
|
|
|
static_cast<Alias *>(id)->push_arg(null_value, st);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void cs_pop_alias(Ident *id) {
|
|
|
|
if ((id->type == ID_ALIAS) && (id->index >= MaxArguments)) {
|
|
|
|
static_cast<Alias *>(id)->pop_arg();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
ostd::ConstCharRange cs_debug_line(
|
|
|
|
CsState &cs, ostd::ConstCharRange p, ostd::ConstCharRange fmt,
|
|
|
|
ostd::CharRange buf
|
|
|
|
) {
|
|
|
|
if (cs.src_str.empty()) {
|
|
|
|
return fmt;
|
|
|
|
}
|
2016-08-14 15:02:46 +00:00
|
|
|
ostd::Size num = 1;
|
|
|
|
ostd::ConstCharRange line(cs.src_str);
|
|
|
|
for (;;) {
|
|
|
|
ostd::ConstCharRange end = ostd::find(line, '\n');
|
2016-08-17 02:57:53 +00:00
|
|
|
if (!end.empty()) {
|
2016-08-14 15:02:46 +00:00
|
|
|
line = ostd::slice_until(line, end);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
2016-08-14 15:02:46 +00:00
|
|
|
if (&p[0] >= &line[0] && &p[0] <= &line[line.size()]) {
|
|
|
|
ostd::CharRange r(buf);
|
2016-08-17 02:57:53 +00:00
|
|
|
if (!cs.src_file.empty()) {
|
2016-08-14 15:02:46 +00:00
|
|
|
ostd::format(r, "%s:%d: %s", cs.src_file, num, fmt);
|
2016-08-17 02:57:53 +00:00
|
|
|
} else {
|
2016-08-14 15:02:46 +00:00
|
|
|
ostd::format(r, "%d: %s", num, fmt);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
2016-08-14 15:02:46 +00:00
|
|
|
r.put('\0');
|
|
|
|
return buf;
|
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
if (end.empty()) {
|
|
|
|
break;
|
|
|
|
}
|
2016-08-14 15:02:46 +00:00
|
|
|
line = end;
|
|
|
|
line.pop_front();
|
|
|
|
++num;
|
|
|
|
}
|
|
|
|
return fmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cs_debug_alias(CsState &cs) {
|
2016-08-17 02:57:53 +00:00
|
|
|
if (!cs.dbgalias) {
|
|
|
|
return;
|
|
|
|
}
|
2016-08-14 15:02:46 +00:00
|
|
|
int total = 0, depth = 0;
|
2016-08-17 02:57:53 +00:00
|
|
|
for (IdentLink *l = cs.stack; l != &cs.noalias; l = l->next) {
|
|
|
|
total++;
|
|
|
|
}
|
2016-08-14 15:02:46 +00:00
|
|
|
for (IdentLink *l = cs.stack; l != &cs.noalias; l = l->next) {
|
|
|
|
Ident *id = l->id;
|
|
|
|
++depth;
|
2016-08-17 02:57:53 +00:00
|
|
|
if (depth < cs.dbgalias) {
|
2016-08-14 15:02:46 +00:00
|
|
|
ostd::err.writefln(" %d) %s", total - depth + 1, id->name);
|
2016-08-17 02:57:53 +00:00
|
|
|
} else if (l->next == &cs.noalias) {
|
|
|
|
ostd::err.writefln(
|
|
|
|
depth == cs.dbgalias ? " %d) %s" : " ..%d) %s",
|
|
|
|
total - depth + 1, id->name
|
|
|
|
);
|
|
|
|
}
|
2016-08-14 15:02:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-14 15:05:55 +00:00
|
|
|
static void bcode_ref(ostd::Uint32 *code) {
|
2016-08-17 02:57:53 +00:00
|
|
|
if (!code) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((*code & CODE_OP_MASK) == CODE_START) {
|
2016-08-14 15:05:55 +00:00
|
|
|
bcode_incr(code);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (code[-1]&CODE_OP_MASK) {
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_START:
|
|
|
|
bcode_incr(&code[-1]);
|
|
|
|
break;
|
|
|
|
case CODE_OFFSET:
|
|
|
|
code -= ostd::Ptrdiff(code[-1] >> 8);
|
|
|
|
bcode_incr(code);
|
|
|
|
break;
|
2016-08-14 15:05:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bcode_unref(ostd::Uint32 *code) {
|
2016-08-17 02:57:53 +00:00
|
|
|
if (!code) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((*code & CODE_OP_MASK) == CODE_START) {
|
2016-08-14 15:05:55 +00:00
|
|
|
bcode_decr(code);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (code[-1]&CODE_OP_MASK) {
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_START:
|
|
|
|
bcode_decr(&code[-1]);
|
|
|
|
break;
|
|
|
|
case CODE_OFFSET:
|
|
|
|
code -= ostd::Ptrdiff(code[-1] >> 8);
|
|
|
|
bcode_decr(code);
|
|
|
|
break;
|
2016-08-14 15:05:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BytecodeRef::BytecodeRef(Bytecode *v): p_code(v) {
|
|
|
|
bcode_ref(reinterpret_cast<ostd::Uint32 *>(p_code));
|
|
|
|
}
|
|
|
|
BytecodeRef::BytecodeRef(BytecodeRef const &v): p_code(v.p_code) {
|
|
|
|
bcode_ref(reinterpret_cast<ostd::Uint32 *>(p_code));
|
|
|
|
}
|
|
|
|
|
|
|
|
BytecodeRef::~BytecodeRef() {
|
|
|
|
bcode_unref(reinterpret_cast<ostd::Uint32 *>(p_code));
|
|
|
|
}
|
|
|
|
|
|
|
|
BytecodeRef &BytecodeRef::operator=(BytecodeRef const &v) {
|
|
|
|
bcode_unref(reinterpret_cast<ostd::Uint32 *>(p_code));
|
|
|
|
p_code = v.p_code;
|
|
|
|
bcode_ref(reinterpret_cast<ostd::Uint32 *>(p_code));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
BytecodeRef &BytecodeRef::operator=(BytecodeRef &&v) {
|
|
|
|
bcode_unref(reinterpret_cast<ostd::Uint32 *>(p_code));
|
|
|
|
p_code = v.p_code;
|
|
|
|
v.p_code = nullptr;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-08-12 17:31:34 +00:00
|
|
|
static inline ostd::Uint32 const *forcecode(CsState &cs, TaggedValue &v) {
|
|
|
|
if (v.get_type() != VAL_CODE) {
|
|
|
|
GenState gs(cs);
|
|
|
|
gs.code.reserve(64);
|
|
|
|
gs.gen_main(v.get_str());
|
|
|
|
v.cleanup();
|
|
|
|
v.set_code(reinterpret_cast<Bytecode *>(gs.code.disown() + 1));
|
|
|
|
}
|
|
|
|
return reinterpret_cast<ostd::Uint32 const *>(v.code);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void forcecond(CsState &cs, TaggedValue &v) {
|
|
|
|
switch (v.get_type()) {
|
2016-08-17 02:57:53 +00:00
|
|
|
case VAL_STR:
|
|
|
|
case VAL_MACRO:
|
|
|
|
case VAL_CSTR:
|
|
|
|
if (v.s[0]) {
|
|
|
|
forcecode(cs, v);
|
|
|
|
} else {
|
|
|
|
v.set_int(0);
|
|
|
|
}
|
|
|
|
break;
|
2016-08-12 17:31:34 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
|
|
|
|
static ostd::Uint32 emptyblock[VAL_ANY][2] = {
|
|
|
|
{ CODE_START + 0x100, CODE_EXIT | RET_NULL },
|
|
|
|
{ CODE_START + 0x100, CODE_EXIT | RET_INT },
|
|
|
|
{ CODE_START + 0x100, CODE_EXIT | RET_FLOAT },
|
|
|
|
{ CODE_START + 0x100, CODE_EXIT | RET_STR }
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline void force_arg(TaggedValue &v, int type) {
|
|
|
|
switch (type) {
|
2016-08-17 02:57:53 +00:00
|
|
|
case RET_STR:
|
|
|
|
if (v.get_type() != VAL_STR) {
|
|
|
|
v.force_str();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case RET_INT:
|
|
|
|
if (v.get_type() != VAL_INT) {
|
|
|
|
v.force_int();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case RET_FLOAT:
|
|
|
|
if (v.get_type() != VAL_FLOAT) {
|
|
|
|
v.force_float();
|
|
|
|
}
|
|
|
|
break;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void free_args(TaggedValue *args, int &oldnum, int newnum) {
|
2016-08-17 02:57:53 +00:00
|
|
|
for (int i = newnum; i < oldnum; i++) {
|
|
|
|
args[i].cleanup();
|
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
oldnum = newnum;
|
|
|
|
}
|
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
static ostd::Uint32 const *skipcode(
|
|
|
|
ostd::Uint32 const *code, TaggedValue *result = nullptr
|
|
|
|
) {
|
2016-08-12 16:38:43 +00:00
|
|
|
int depth = 0;
|
|
|
|
for (;;) {
|
|
|
|
ostd::Uint32 op = *code++;
|
|
|
|
switch (op & 0xFF) {
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_MACRO:
|
|
|
|
case CODE_VAL | RET_STR: {
|
|
|
|
ostd::Uint32 len = op >> 8;
|
|
|
|
code += len / sizeof(ostd::Uint32) + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_BLOCK:
|
|
|
|
case CODE_JUMP:
|
|
|
|
case CODE_JUMP_TRUE:
|
|
|
|
case CODE_JUMP_FALSE:
|
|
|
|
case CODE_JUMP_RESULT_TRUE:
|
|
|
|
case CODE_JUMP_RESULT_FALSE: {
|
|
|
|
ostd::Uint32 len = op >> 8;
|
|
|
|
code += len;
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_ENTER:
|
|
|
|
case CODE_ENTER_RESULT:
|
|
|
|
++depth;
|
|
|
|
continue;
|
|
|
|
case CODE_EXIT | RET_NULL:
|
|
|
|
case CODE_EXIT | RET_STR:
|
|
|
|
case CODE_EXIT | RET_INT:
|
|
|
|
case CODE_EXIT | RET_FLOAT:
|
|
|
|
if (depth <= 0) {
|
|
|
|
if (result) {
|
|
|
|
force_arg(*result, op & CODE_RET_MASK);
|
|
|
|
}
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
--depth;
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TaggedValue::copy_arg(TaggedValue &r) const {
|
|
|
|
r.cleanup();
|
|
|
|
switch (get_type()) {
|
|
|
|
case VAL_INT:
|
|
|
|
case VAL_FLOAT:
|
|
|
|
case VAL_IDENT:
|
|
|
|
r = *this;
|
|
|
|
break;
|
|
|
|
case VAL_STR:
|
|
|
|
case VAL_CSTR:
|
|
|
|
case VAL_MACRO:
|
|
|
|
r.set_str(ostd::ConstCharRange(s, len));
|
|
|
|
break;
|
|
|
|
case VAL_CODE: {
|
|
|
|
ostd::Uint32 const *bcode = reinterpret_cast<ostd::Uint32 const *>(code);
|
|
|
|
ostd::Uint32 const *end = skipcode(bcode);
|
|
|
|
ostd::Uint32 *dst = new ostd::Uint32[end - bcode + 1];
|
|
|
|
*dst++ = CODE_START;
|
|
|
|
memcpy(dst, bcode, (end - bcode) * sizeof(ostd::Uint32));
|
|
|
|
r.set_code(reinterpret_cast<Bytecode const *>(dst));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
r.set_null();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
static inline void callcommand(
|
2016-08-17 21:04:43 +00:00
|
|
|
CsState &cs, Command *id, TaggedValue *args, TaggedValue &res, int numargs,
|
2016-08-17 02:57:53 +00:00
|
|
|
bool lookup = false
|
|
|
|
) {
|
2016-08-12 16:38:43 +00:00
|
|
|
int i = -1, fakeargs = 0;
|
|
|
|
bool rep = false;
|
2016-08-17 02:57:53 +00:00
|
|
|
for (char const *fmt = id->cargs; *fmt; fmt++) {
|
|
|
|
switch (*fmt) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
args[i].set_int(CsIntMin);
|
|
|
|
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("");
|
|
|
|
fakeargs++;
|
|
|
|
} else {
|
|
|
|
args[i].force_str();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
if (++i >= numargs) {
|
|
|
|
if (rep) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
args[i].set_cstr("");
|
|
|
|
fakeargs++;
|
|
|
|
} else {
|
|
|
|
args[i].force_str();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'T':
|
|
|
|
case 't':
|
|
|
|
if (++i >= numargs) {
|
|
|
|
if (rep) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
args[i].set_null();
|
|
|
|
fakeargs++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'E':
|
|
|
|
if (++i >= numargs) {
|
|
|
|
if (rep) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
args[i].set_null();
|
|
|
|
fakeargs++;
|
|
|
|
} else {
|
|
|
|
forcecond(cs, args[i]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
if (++i >= numargs) {
|
|
|
|
if (rep) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
args[i].set_code(
|
|
|
|
reinterpret_cast<Bytecode *>(emptyblock[VAL_NULL] + 1)
|
|
|
|
);
|
|
|
|
fakeargs++;
|
|
|
|
} else {
|
|
|
|
forcecode(cs, args[i]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
if (++i >= numargs) {
|
|
|
|
if (rep) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
args[i].set_ident(cs.dummy);
|
|
|
|
fakeargs++;
|
|
|
|
} else {
|
|
|
|
cs.force_ident(args[i]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '$':
|
|
|
|
if (++i < numargs) {
|
|
|
|
args[i].cleanup();
|
|
|
|
}
|
|
|
|
args[i].set_ident(id);
|
|
|
|
break;
|
|
|
|
case 'N':
|
|
|
|
if (++i < numargs) {
|
|
|
|
args[i].cleanup();
|
|
|
|
}
|
|
|
|
args[i].set_int(CsInt(lookup ? -1 : i - fakeargs));
|
|
|
|
break;
|
|
|
|
case 'C': {
|
|
|
|
i = ostd::max(i + 1, numargs);
|
|
|
|
auto buf = ostd::appender<ostd::String>();
|
|
|
|
cscript::util::tvals_concat(buf, ostd::iter(args, i), " ");
|
|
|
|
TaggedValue tv;
|
|
|
|
tv.set_mstr(buf.get().iter());
|
|
|
|
id->cb_cftv(TvalRange(&tv, 1), res);
|
|
|
|
goto cleanup;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
case 'V':
|
|
|
|
i = ostd::max(i + 1, numargs);
|
|
|
|
id->cb_cftv(ostd::iter(args, i), res);
|
|
|
|
goto cleanup;
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
if (i + 1 < numargs) {
|
|
|
|
fmt -= *fmt - '0' + 1;
|
|
|
|
rep = true;
|
|
|
|
}
|
|
|
|
break;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
++i;
|
|
|
|
id->cb_cftv(TvalRange(args, i), res);
|
|
|
|
cleanup:
|
2016-08-17 02:57:53 +00:00
|
|
|
for (ostd::Size k = 0; k < ostd::Size(i); ++k) {
|
|
|
|
args[k].cleanup();
|
|
|
|
}
|
|
|
|
for (; i < numargs; i++) {
|
|
|
|
args[i].cleanup();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static ostd::Uint32 const *runcode(
|
|
|
|
CsState &cs, ostd::Uint32 const *code, TaggedValue &result
|
|
|
|
);
|
|
|
|
|
|
|
|
static inline void cs_call_alias(
|
2016-08-17 22:06:39 +00:00
|
|
|
CsState &cs, Alias *a, TaggedValue *args, TaggedValue &result,
|
2016-08-17 02:57:53 +00:00
|
|
|
int callargs, int &nargs, int offset, int skip, ostd::Uint32 op
|
|
|
|
) {
|
|
|
|
IdentStack argstack[MaxArguments];
|
|
|
|
for(int i = 0; i < callargs; i++) {
|
2016-08-17 22:06:39 +00:00
|
|
|
static_cast<Alias *>(cs.identmap[i])->push_arg(
|
|
|
|
args[offset + i], argstack[i], false
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
int oldargs = cs.numargs;
|
|
|
|
cs.numargs = callargs;
|
|
|
|
int oldflags = cs.identflags;
|
2016-08-17 22:06:39 +00:00
|
|
|
cs.identflags |= a->flags&IDF_OVERRIDDEN;
|
2016-08-17 02:57:53 +00:00
|
|
|
IdentLink aliaslink = {
|
2016-08-17 22:06:39 +00:00
|
|
|
a, cs.stack, (1<<callargs)-1, argstack
|
2016-08-17 02:57:53 +00:00
|
|
|
};
|
|
|
|
cs.stack = &aliaslink;
|
2016-08-17 22:06:39 +00:00
|
|
|
if (!a->code) {
|
|
|
|
a->code = reinterpret_cast<Bytecode *>(compilecode(cs, a->get_str()));
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
2016-08-17 22:06:39 +00:00
|
|
|
ostd::Uint32 *codep = reinterpret_cast<ostd::Uint32 *>(a->code);
|
2016-08-17 02:57:53 +00:00
|
|
|
bcode_incr(codep);
|
|
|
|
runcode(cs, codep+1, (result));
|
|
|
|
bcode_decr(codep);
|
|
|
|
cs.stack = aliaslink.next;
|
|
|
|
cs.identflags = oldflags;
|
|
|
|
for (int i = 0; i < callargs; i++) {
|
2016-08-17 22:06:39 +00:00
|
|
|
static_cast<Alias *>(cs.identmap[i])->pop_arg();
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
int argmask = aliaslink.usedargs & (~0 << callargs);
|
|
|
|
for (; argmask; ++callargs) {
|
|
|
|
if (argmask & (1 << callargs)) {
|
2016-08-17 22:06:39 +00:00
|
|
|
static_cast<Alias *>(cs.identmap[callargs])->pop_arg();
|
2016-08-17 02:57:53 +00:00
|
|
|
argmask &= ~(1 << callargs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
cs.numargs = oldargs;
|
|
|
|
nargs = offset - skip;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static constexpr int MaxRunDepth = 255;
|
|
|
|
static thread_local int rundepth = 0;
|
|
|
|
|
2016-08-17 22:18:36 +00:00
|
|
|
static inline Alias *cs_get_lookup_id(CsState &cs, ostd::Uint32 op) {
|
2016-08-17 02:57:53 +00:00
|
|
|
Ident *id = cs.identmap[op >> 8];
|
|
|
|
if (id->flags & IDF_UNKNOWN) {
|
|
|
|
cs_debug_code(cs, "unknown alias lookup: %s", id->name);
|
|
|
|
}
|
2016-08-17 22:18:36 +00:00
|
|
|
return static_cast<Alias *>(id);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
|
2016-08-17 22:18:36 +00:00
|
|
|
static inline Alias *cs_get_lookuparg_id(CsState &cs, ostd::Uint32 op) {
|
2016-08-17 02:57:53 +00:00
|
|
|
Ident *id = cs.identmap[op >> 8];
|
|
|
|
if (!(cs.stack->usedargs&(1<<id->index))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2016-08-17 22:18:36 +00:00
|
|
|
return static_cast<Alias *>(id);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline int cs_get_lookupu_type(
|
|
|
|
CsState &cs, TaggedValue &arg, Ident *&id, ostd::Uint32 op
|
|
|
|
) {
|
|
|
|
if (
|
|
|
|
arg.get_type() != VAL_STR &&
|
|
|
|
arg.get_type() != VAL_MACRO &&
|
|
|
|
arg.get_type() != VAL_CSTR
|
|
|
|
) {
|
|
|
|
return -2; /* default case */
|
|
|
|
}
|
2016-08-17 20:03:11 +00:00
|
|
|
id = cs.get_ident(arg.s);
|
2016-08-17 02:57:53 +00:00
|
|
|
if (id) {
|
|
|
|
switch(id->type) {
|
|
|
|
case ID_ALIAS:
|
|
|
|
if (id->flags & IDF_UNKNOWN) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
arg.cleanup();
|
|
|
|
if (
|
|
|
|
(id->index < MaxArguments) &&
|
|
|
|
!(cs.stack->usedargs & (1 << id->index))
|
|
|
|
) {
|
|
|
|
return ID_UNKNOWN;
|
|
|
|
}
|
|
|
|
return ID_ALIAS;
|
|
|
|
case ID_SVAR:
|
|
|
|
arg.cleanup();
|
|
|
|
return ID_SVAR;
|
|
|
|
case ID_IVAR:
|
|
|
|
arg.cleanup();
|
|
|
|
return ID_IVAR;
|
|
|
|
case ID_FVAR:
|
|
|
|
arg.cleanup();
|
|
|
|
return ID_FVAR;
|
|
|
|
case ID_COMMAND: {
|
|
|
|
arg.cleanup();
|
|
|
|
arg.set_null();
|
|
|
|
TaggedValue buf[MaxArguments];
|
2016-08-17 21:04:43 +00:00
|
|
|
callcommand(cs, static_cast<Command *>(id), buf, arg, 0, true);
|
2016-08-17 02:57:53 +00:00
|
|
|
force_arg(arg, op & CODE_RET_MASK);
|
|
|
|
return -2; /* ignore */
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
arg.cleanup();
|
|
|
|
return ID_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cs_debug_code(cs, "unknown alias lookup: %s", arg.s);
|
|
|
|
arg.cleanup();
|
|
|
|
return ID_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ostd::Uint32 const *runcode(
|
|
|
|
CsState &cs, ostd::Uint32 const *code, TaggedValue &result
|
|
|
|
) {
|
2016-08-12 16:38:43 +00:00
|
|
|
result.set_null();
|
|
|
|
if (rundepth >= MaxRunDepth) {
|
|
|
|
cs_debug_code(cs, "exceeded recursion limit");
|
2016-08-12 17:20:33 +00:00
|
|
|
return skipcode(code, &result);
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
|
|
|
++rundepth;
|
|
|
|
int numargs = 0;
|
|
|
|
TaggedValue args[MaxArguments + MaxResults];
|
|
|
|
for (;;) {
|
|
|
|
ostd::Uint32 op = *code++;
|
|
|
|
switch (op & 0xFF) {
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_START:
|
|
|
|
case CODE_OFFSET:
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_NULL | RET_NULL:
|
|
|
|
result.cleanup();
|
|
|
|
result.set_null();
|
|
|
|
continue;
|
|
|
|
case CODE_NULL | RET_STR:
|
|
|
|
result.cleanup();
|
|
|
|
result.set_str("");
|
|
|
|
continue;
|
|
|
|
case CODE_NULL | RET_INT:
|
|
|
|
result.cleanup();
|
|
|
|
result.set_int(0);
|
|
|
|
continue;
|
|
|
|
case CODE_NULL | RET_FLOAT:
|
|
|
|
result.cleanup();
|
|
|
|
result.set_float(0.0f);
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_FALSE | RET_STR:
|
|
|
|
result.cleanup();
|
|
|
|
result.set_str("0");
|
|
|
|
continue;
|
|
|
|
case CODE_FALSE | RET_NULL:
|
|
|
|
case CODE_FALSE | RET_INT:
|
|
|
|
result.cleanup();
|
|
|
|
result.set_int(0);
|
|
|
|
continue;
|
|
|
|
case CODE_FALSE | RET_FLOAT:
|
|
|
|
result.cleanup();
|
|
|
|
result.set_float(0.0f);
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_TRUE | RET_STR:
|
|
|
|
result.cleanup();
|
|
|
|
result.set_str("1");
|
|
|
|
continue;
|
|
|
|
case CODE_TRUE | RET_NULL:
|
|
|
|
case CODE_TRUE | RET_INT:
|
|
|
|
result.cleanup();
|
|
|
|
result.set_int(1);
|
|
|
|
continue;
|
|
|
|
case CODE_TRUE | RET_FLOAT:
|
|
|
|
result.cleanup();
|
|
|
|
result.set_float(1.0f);
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_NOT | RET_STR:
|
|
|
|
result.cleanup();
|
|
|
|
--numargs;
|
|
|
|
result.set_str(args[numargs].get_bool() ? "0" : "1");
|
|
|
|
args[numargs].cleanup();
|
|
|
|
continue;
|
|
|
|
case CODE_NOT | RET_NULL:
|
|
|
|
case CODE_NOT | RET_INT:
|
|
|
|
result.cleanup();
|
|
|
|
--numargs;
|
|
|
|
result.set_int(!args[numargs].get_bool());
|
|
|
|
args[numargs].cleanup();
|
|
|
|
continue;
|
|
|
|
case CODE_NOT | RET_FLOAT:
|
|
|
|
result.cleanup();
|
|
|
|
--numargs;
|
|
|
|
result.set_float(CsFloat(!args[numargs].get_bool()));
|
|
|
|
args[numargs].cleanup();
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_POP:
|
|
|
|
args[--numargs].cleanup();
|
|
|
|
continue;
|
|
|
|
case CODE_ENTER:
|
|
|
|
code = runcode(cs, code, args[numargs++]);
|
|
|
|
continue;
|
|
|
|
case CODE_ENTER_RESULT:
|
|
|
|
result.cleanup();
|
|
|
|
code = runcode(cs, code, result);
|
|
|
|
continue;
|
|
|
|
case CODE_EXIT | RET_STR:
|
|
|
|
case CODE_EXIT | RET_INT:
|
|
|
|
case CODE_EXIT | RET_FLOAT:
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
/* fallthrough */
|
|
|
|
case CODE_EXIT | RET_NULL:
|
|
|
|
goto exit;
|
|
|
|
case CODE_RESULT_ARG | RET_STR:
|
|
|
|
case CODE_RESULT_ARG | RET_INT:
|
|
|
|
case CODE_RESULT_ARG | RET_FLOAT:
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
/* fallthrough */
|
|
|
|
case CODE_RESULT_ARG | RET_NULL:
|
|
|
|
args[numargs++] = result;
|
|
|
|
result.set_null();
|
|
|
|
continue;
|
|
|
|
case CODE_PRINT:
|
2016-08-17 21:29:31 +00:00
|
|
|
cs.print_var(static_cast<Var *>(cs.identmap[op >> 8]));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_LOCAL: {
|
|
|
|
result.cleanup();
|
|
|
|
int numlocals = op >> 8, offset = numargs - numlocals;
|
|
|
|
IdentStack locals[MaxArguments];
|
|
|
|
for (int i = 0; i < numlocals; ++i) {
|
2016-08-17 22:06:39 +00:00
|
|
|
cs_push_alias(args[offset + i].id, locals[i]);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
code = runcode(cs, code, result);
|
|
|
|
for (int i = offset; i < numargs; i++) {
|
2016-08-17 22:06:39 +00:00
|
|
|
cs_pop_alias(args[i].id);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_DOARGS | RET_NULL:
|
|
|
|
case CODE_DOARGS | RET_STR:
|
|
|
|
case CODE_DOARGS | RET_INT:
|
|
|
|
case CODE_DOARGS | RET_FLOAT:
|
|
|
|
if (cs.stack != &cs.noalias) {
|
|
|
|
cs_do_args(cs, [&]() {
|
|
|
|
result.cleanup();
|
|
|
|
cs.run_ret(args[--numargs].code, result);
|
|
|
|
args[numargs].cleanup();
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
});
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* fallthrough */
|
|
|
|
case CODE_DO | RET_NULL:
|
|
|
|
case CODE_DO | RET_STR:
|
|
|
|
case CODE_DO | RET_INT:
|
|
|
|
case CODE_DO | RET_FLOAT:
|
|
|
|
result.cleanup();
|
|
|
|
cs.run_ret(args[--numargs].code, result);
|
|
|
|
args[numargs].cleanup();
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_JUMP: {
|
|
|
|
ostd::Uint32 len = op >> 8;
|
|
|
|
code += len;
|
2016-08-12 16:38:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_JUMP_TRUE: {
|
|
|
|
ostd::Uint32 len = op >> 8;
|
|
|
|
if (args[--numargs].get_bool()) {
|
|
|
|
code += len;
|
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
args[numargs].cleanup();
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_JUMP_FALSE: {
|
|
|
|
ostd::Uint32 len = op >> 8;
|
|
|
|
if (!args[--numargs].get_bool()) {
|
|
|
|
code += len;
|
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
args[numargs].cleanup();
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_JUMP_RESULT_TRUE: {
|
|
|
|
ostd::Uint32 len = op >> 8;
|
|
|
|
result.cleanup();
|
|
|
|
--numargs;
|
|
|
|
if (args[numargs].get_type() == VAL_CODE) {
|
|
|
|
cs.run_ret(args[numargs].code, result);
|
|
|
|
args[numargs].cleanup();
|
|
|
|
} else {
|
|
|
|
result = args[numargs];
|
|
|
|
}
|
|
|
|
if (result.get_bool()) {
|
|
|
|
code += len;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_JUMP_RESULT_FALSE: {
|
|
|
|
ostd::Uint32 len = op >> 8;
|
|
|
|
result.cleanup();
|
|
|
|
--numargs;
|
|
|
|
if (args[numargs].get_type() == VAL_CODE) {
|
|
|
|
cs.run_ret(args[numargs].code, result);
|
|
|
|
args[numargs].cleanup();
|
|
|
|
} else {
|
|
|
|
result = args[numargs];
|
|
|
|
}
|
|
|
|
if (!result.get_bool()) {
|
|
|
|
code += len;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_MACRO: {
|
|
|
|
ostd::Uint32 len = op >> 8;
|
|
|
|
args[numargs++].set_macro(
|
|
|
|
reinterpret_cast<Bytecode const *>(code), len
|
|
|
|
);
|
|
|
|
code += len / sizeof(ostd::Uint32) + 1;
|
|
|
|
continue;
|
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_VAL | RET_STR: {
|
|
|
|
ostd::Uint32 len = op >> 8;
|
|
|
|
args[numargs++].set_str(ostd::ConstCharRange(
|
|
|
|
reinterpret_cast<char const *>(code), len
|
|
|
|
));
|
|
|
|
code += len / sizeof(ostd::Uint32) + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_VALI | RET_STR: {
|
|
|
|
char s[4] = {
|
|
|
|
char((op >> 8) & 0xFF),
|
|
|
|
char((op >> 16) & 0xFF),
|
|
|
|
char((op >> 24) & 0xFF), '\0'
|
|
|
|
};
|
|
|
|
args[numargs++].set_str(s);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_VAL | RET_NULL:
|
|
|
|
case CODE_VALI | RET_NULL:
|
|
|
|
args[numargs++].set_null();
|
|
|
|
continue;
|
|
|
|
case CODE_VAL | RET_INT:
|
|
|
|
args[numargs++].set_int(CsInt(*code++));
|
|
|
|
continue;
|
|
|
|
case CODE_VALI | RET_INT:
|
|
|
|
args[numargs++].set_int(CsInt(op) >> 8);
|
|
|
|
continue;
|
|
|
|
case CODE_VAL | RET_FLOAT:
|
|
|
|
args[numargs++].set_float(
|
|
|
|
*reinterpret_cast<CsFloat const *>(code++)
|
|
|
|
);
|
|
|
|
continue;
|
|
|
|
case CODE_VALI | RET_FLOAT:
|
|
|
|
args[numargs++].set_float(CsFloat(CsInt(op) >> 8));
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CODE_DUP | RET_NULL:
|
|
|
|
args[numargs - 1].get_val(args[numargs]);
|
|
|
|
numargs++;
|
|
|
|
continue;
|
|
|
|
case CODE_DUP | RET_INT:
|
|
|
|
args[numargs].set_int(args[numargs - 1].get_int());
|
|
|
|
numargs++;
|
|
|
|
continue;
|
|
|
|
case CODE_DUP | RET_FLOAT:
|
|
|
|
args[numargs].set_float(args[numargs - 1].get_float());
|
|
|
|
numargs++;
|
|
|
|
continue;
|
|
|
|
case CODE_DUP | RET_STR:
|
|
|
|
args[numargs].set_str(ostd::move(args[numargs - 1].get_str()));
|
|
|
|
numargs++;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CODE_FORCE | RET_STR:
|
|
|
|
args[numargs - 1].force_str();
|
|
|
|
continue;
|
|
|
|
case CODE_FORCE | RET_INT:
|
|
|
|
args[numargs - 1].force_int();
|
|
|
|
continue;
|
|
|
|
case CODE_FORCE | RET_FLOAT:
|
|
|
|
args[numargs - 1].force_float();
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CODE_RESULT | RET_NULL:
|
|
|
|
result.cleanup();
|
|
|
|
result = args[--numargs];
|
|
|
|
continue;
|
|
|
|
case CODE_RESULT | RET_STR:
|
|
|
|
case CODE_RESULT | RET_INT:
|
|
|
|
case CODE_RESULT | RET_FLOAT:
|
|
|
|
result.cleanup();
|
|
|
|
result = args[--numargs];
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CODE_EMPTY | RET_NULL:
|
|
|
|
args[numargs++].set_code(
|
|
|
|
reinterpret_cast<Bytecode *>(emptyblock[VAL_NULL] + 1)
|
|
|
|
);
|
2016-08-12 16:38:43 +00:00
|
|
|
break;
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_EMPTY | RET_STR:
|
|
|
|
args[numargs++].set_code(
|
|
|
|
reinterpret_cast<Bytecode *>(emptyblock[VAL_STR] + 1)
|
|
|
|
);
|
2016-08-12 16:38:43 +00:00
|
|
|
break;
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_EMPTY | RET_INT:
|
|
|
|
args[numargs++].set_code(
|
|
|
|
reinterpret_cast<Bytecode *>(emptyblock[VAL_INT] + 1)
|
|
|
|
);
|
2016-08-12 16:38:43 +00:00
|
|
|
break;
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_EMPTY | RET_FLOAT:
|
|
|
|
args[numargs++].set_code(
|
|
|
|
reinterpret_cast<Bytecode *>(emptyblock[VAL_FLOAT] + 1)
|
|
|
|
);
|
2016-08-12 16:38:43 +00:00
|
|
|
break;
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_BLOCK: {
|
|
|
|
ostd::Uint32 len = op >> 8;
|
|
|
|
args[numargs++].set_code(
|
|
|
|
reinterpret_cast<Bytecode const *>(code + 1)
|
|
|
|
);
|
|
|
|
code += len;
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_COMPILE: {
|
|
|
|
TaggedValue &arg = args[numargs - 1];
|
|
|
|
GenState gs(cs);
|
|
|
|
switch (arg.get_type()) {
|
|
|
|
case VAL_INT:
|
|
|
|
gs.code.reserve(8);
|
|
|
|
gs.code.push(CODE_START);
|
|
|
|
gs.gen_int(arg.i);
|
|
|
|
gs.code.push(CODE_RESULT);
|
|
|
|
gs.code.push(CODE_EXIT);
|
|
|
|
break;
|
|
|
|
case VAL_FLOAT:
|
|
|
|
gs.code.reserve(8);
|
|
|
|
gs.code.push(CODE_START);
|
|
|
|
gs.gen_float(arg.f);
|
|
|
|
gs.code.push(CODE_RESULT);
|
|
|
|
gs.code.push(CODE_EXIT);
|
|
|
|
break;
|
|
|
|
case VAL_STR:
|
|
|
|
case VAL_MACRO:
|
|
|
|
case VAL_CSTR:
|
|
|
|
gs.code.reserve(64);
|
|
|
|
gs.gen_main(arg.s);
|
|
|
|
arg.cleanup();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
gs.code.reserve(8);
|
|
|
|
gs.code.push(CODE_START);
|
|
|
|
gs.gen_null();
|
|
|
|
gs.code.push(CODE_RESULT);
|
|
|
|
gs.code.push(CODE_EXIT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
arg.set_code(
|
|
|
|
reinterpret_cast<Bytecode const *>(gs.code.disown() + 1)
|
|
|
|
);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_COND: {
|
|
|
|
TaggedValue &arg = args[numargs - 1];
|
|
|
|
switch (arg.get_type()) {
|
|
|
|
case VAL_STR:
|
|
|
|
case VAL_MACRO:
|
|
|
|
case VAL_CSTR:
|
|
|
|
if (arg.s[0]) {
|
|
|
|
GenState gs(cs);
|
|
|
|
gs.code.reserve(64);
|
|
|
|
gs.gen_main(arg.s);
|
|
|
|
arg.cleanup();
|
|
|
|
arg.set_code(reinterpret_cast<Bytecode const *>(
|
|
|
|
gs.code.disown() + 1
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
arg.force_null();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_IDENT:
|
|
|
|
args[numargs++].set_ident(cs.identmap[op >> 8]);
|
|
|
|
continue;
|
|
|
|
case CODE_IDENTARG: {
|
2016-08-17 22:06:39 +00:00
|
|
|
Alias *a = static_cast<Alias *>(cs.identmap[op >> 8]);
|
|
|
|
if (!(cs.stack->usedargs & (1 << a->index))) {
|
|
|
|
a->push_arg(null_value, cs.stack->argstack[a->index], false);
|
|
|
|
cs.stack->usedargs |= 1 << a->index;
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
2016-08-17 22:06:39 +00:00
|
|
|
args[numargs++].set_ident(a);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_IDENTU: {
|
|
|
|
TaggedValue &arg = args[numargs - 1];
|
|
|
|
Ident *id = cs.dummy;
|
|
|
|
if (
|
|
|
|
arg.get_type() == VAL_STR ||
|
|
|
|
arg.get_type() == VAL_MACRO ||
|
|
|
|
arg.get_type() == VAL_CSTR
|
|
|
|
) {
|
|
|
|
id = cs.new_ident(ostd::ConstCharRange(arg.cstr, arg.len));
|
|
|
|
}
|
|
|
|
if (id->index < MaxArguments && !(cs.stack->usedargs & (1 << id->index))) {
|
2016-08-17 22:06:39 +00:00
|
|
|
static_cast<Alias *>(id)->push_arg(
|
|
|
|
null_value, cs.stack->argstack[id->index], false
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
cs.stack->usedargs |= 1 << id->index;
|
|
|
|
}
|
|
|
|
arg.cleanup();
|
|
|
|
arg.set_ident(id);
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_LOOKUPU | RET_STR: {
|
|
|
|
Ident *id = nullptr;
|
|
|
|
TaggedValue &arg = args[numargs - 1];
|
|
|
|
switch (cs_get_lookupu_type(cs, arg, id, op)) {
|
|
|
|
case ID_ALIAS:
|
2016-08-17 22:18:36 +00:00
|
|
|
arg.set_str(ostd::move(
|
|
|
|
static_cast<Alias *>(id)->get_str()
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_SVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_str(*static_cast<Svar *>(id)->storage);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_IVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_str(ostd::move(
|
|
|
|
intstr(*static_cast<Ivar *>(id)->storage)
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_FVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_str(ostd::move(
|
|
|
|
floatstr(*static_cast<Fvar *>(id)->storage)
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_UNKNOWN:
|
|
|
|
arg.set_str("");
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case CODE_LOOKUP | RET_STR:
|
|
|
|
args[numargs++].set_str(
|
|
|
|
ostd::move(cs_get_lookup_id(cs, op)->get_str())
|
|
|
|
);
|
|
|
|
continue;
|
|
|
|
case CODE_LOOKUPARG | RET_STR: {
|
2016-08-17 22:18:36 +00:00
|
|
|
Alias *a = cs_get_lookuparg_id(cs, op);
|
|
|
|
if (!a) {
|
2016-08-17 02:57:53 +00:00
|
|
|
args[numargs++].set_str("");
|
|
|
|
} else {
|
2016-08-17 22:18:36 +00:00
|
|
|
args[numargs++].set_str(ostd::move(a->get_str()));
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_LOOKUPU | RET_INT: {
|
|
|
|
Ident *id = nullptr;
|
|
|
|
TaggedValue &arg = args[numargs - 1];
|
|
|
|
switch (cs_get_lookupu_type(cs, arg, id, op)) {
|
|
|
|
case ID_ALIAS:
|
2016-08-17 22:18:36 +00:00
|
|
|
arg.set_int(static_cast<Alias *>(id)->get_int());
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_SVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_int(cs_parse_int(
|
|
|
|
*static_cast<Svar *>(id)->storage
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_IVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_int(*static_cast<Ivar *>(id)->storage);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_FVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_int(CsInt(*static_cast<Fvar *>(id)->storage));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_UNKNOWN:
|
|
|
|
arg.set_int(0);
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
case CODE_LOOKUP | RET_INT:
|
|
|
|
args[numargs++].set_int(
|
|
|
|
cs_get_lookup_id(cs, op)->get_int()
|
|
|
|
);
|
|
|
|
continue;
|
|
|
|
case CODE_LOOKUPARG | RET_INT: {
|
2016-08-17 22:18:36 +00:00
|
|
|
Alias *a = cs_get_lookuparg_id(cs, op);
|
|
|
|
if (!a) {
|
2016-08-17 02:57:53 +00:00
|
|
|
args[numargs++].set_int(0);
|
|
|
|
} else {
|
2016-08-17 22:18:36 +00:00
|
|
|
args[numargs++].set_int(a->get_int());
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_LOOKUPU | RET_FLOAT: {
|
|
|
|
Ident *id = nullptr;
|
|
|
|
TaggedValue &arg = args[numargs - 1];
|
|
|
|
switch (cs_get_lookupu_type(cs, arg, id, op)) {
|
|
|
|
case ID_ALIAS:
|
2016-08-17 22:18:36 +00:00
|
|
|
arg.set_float(static_cast<Alias *>(id)->get_float());
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_SVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_float(cs_parse_float(
|
|
|
|
*static_cast<Svar *>(id)->storage
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_IVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_float(CsFloat(
|
|
|
|
*static_cast<Ivar *>(id)->storage
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_FVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_float(*static_cast<Fvar *>(id)->storage);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_UNKNOWN:
|
|
|
|
arg.set_float(CsFloat(0));
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
case CODE_LOOKUP | RET_FLOAT:
|
|
|
|
args[numargs++].set_float(
|
|
|
|
cs_get_lookup_id(cs, op)->get_float()
|
|
|
|
);
|
|
|
|
continue;
|
|
|
|
case CODE_LOOKUPARG | RET_FLOAT: {
|
2016-08-17 22:18:36 +00:00
|
|
|
Alias *a = cs_get_lookuparg_id(cs, op);
|
|
|
|
if (!a) {
|
2016-08-17 02:57:53 +00:00
|
|
|
args[numargs++].set_float(CsFloat(0));
|
|
|
|
} else {
|
2016-08-17 22:18:36 +00:00
|
|
|
args[numargs++].set_float(a->get_float());
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_LOOKUPU | RET_NULL: {
|
|
|
|
Ident *id = nullptr;
|
|
|
|
TaggedValue &arg = args[numargs - 1];
|
|
|
|
switch (cs_get_lookupu_type(cs, arg, id, op)) {
|
|
|
|
case ID_ALIAS:
|
2016-08-17 22:18:36 +00:00
|
|
|
static_cast<Alias *>(id)->get_val(arg);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_SVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_str(*static_cast<Svar *>(id)->storage);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_IVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_int(*static_cast<Ivar *>(id)->storage);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_FVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_float(*static_cast<Fvar *>(id)->storage);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_UNKNOWN:
|
|
|
|
arg.set_null();
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case CODE_LOOKUP | RET_NULL:
|
|
|
|
cs_get_lookup_id(cs, op)->get_val(args[numargs++]);
|
|
|
|
continue;
|
|
|
|
case CODE_LOOKUPARG | RET_NULL: {
|
2016-08-17 22:18:36 +00:00
|
|
|
Alias *a = cs_get_lookuparg_id(cs, op);
|
|
|
|
if (!a) {
|
2016-08-17 02:57:53 +00:00
|
|
|
args[numargs++].set_null();
|
|
|
|
} else {
|
2016-08-17 22:18:36 +00:00
|
|
|
a->get_val(args[numargs++]);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_LOOKUPMU | RET_STR: {
|
|
|
|
Ident *id = nullptr;
|
|
|
|
TaggedValue &arg = args[numargs - 1];
|
|
|
|
switch (cs_get_lookupu_type(cs, arg, id, op)) {
|
|
|
|
case ID_ALIAS:
|
2016-08-17 22:18:36 +00:00
|
|
|
static_cast<Alias *>(id)->get_cstr(arg);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_SVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_cstr(*static_cast<Svar *>(id)->storage);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_IVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_str(ostd::move(
|
|
|
|
intstr(*static_cast<Ivar *>(id)->storage)
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_FVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_str(ostd::move(
|
|
|
|
floatstr(*static_cast<Fvar *>(id)->storage)
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_UNKNOWN:
|
|
|
|
arg.set_cstr("");
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case CODE_LOOKUPM | RET_STR:
|
|
|
|
cs_get_lookup_id(cs, op)->get_cstr(args[numargs++]);
|
|
|
|
continue;
|
|
|
|
case CODE_LOOKUPMARG | RET_STR: {
|
2016-08-17 22:18:36 +00:00
|
|
|
Alias *a = cs_get_lookuparg_id(cs, op);
|
|
|
|
if (!a) {
|
2016-08-17 02:57:53 +00:00
|
|
|
args[numargs++].set_cstr("");
|
|
|
|
} else {
|
2016-08-17 22:18:36 +00:00
|
|
|
a->get_cstr(args[numargs++]);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
case CODE_LOOKUPMU | RET_NULL: {
|
|
|
|
Ident *id = nullptr;
|
|
|
|
TaggedValue &arg = args[numargs - 1];
|
|
|
|
switch (cs_get_lookupu_type(cs, arg, id, op)) {
|
|
|
|
case ID_ALIAS:
|
2016-08-17 22:18:36 +00:00
|
|
|
static_cast<Alias *>(id)->get_cval(arg);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_SVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_cstr(*static_cast<Svar *>(id)->storage);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_IVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_int(*static_cast<Ivar *>(id)->storage);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_FVAR:
|
2016-08-17 22:36:37 +00:00
|
|
|
arg.set_float(*static_cast<Fvar *>(id)->storage);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case ID_UNKNOWN:
|
|
|
|
arg.set_null();
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case CODE_LOOKUPM | RET_NULL:
|
|
|
|
cs_get_lookup_id(cs, op)->get_cval(args[numargs++]);
|
|
|
|
continue;
|
|
|
|
case CODE_LOOKUPMARG | RET_NULL: {
|
2016-08-17 22:18:36 +00:00
|
|
|
Alias *a = cs_get_lookuparg_id(cs, op);
|
|
|
|
if (!a) {
|
2016-08-17 02:57:53 +00:00
|
|
|
args[numargs++].set_null();
|
|
|
|
} else {
|
2016-08-17 22:18:36 +00:00
|
|
|
a->get_cval(args[numargs++]);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_SVAR | RET_STR:
|
|
|
|
case CODE_SVAR | RET_NULL:
|
2016-08-17 22:36:37 +00:00
|
|
|
args[numargs++].set_str(
|
|
|
|
*static_cast<Svar *>(cs.identmap[op >> 8])->storage
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_SVAR | RET_INT:
|
|
|
|
args[numargs++].set_int(cs_parse_int(
|
2016-08-17 22:36:37 +00:00
|
|
|
*static_cast<Svar *>(cs.identmap[op >> 8])->storage
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_SVAR | RET_FLOAT:
|
2016-08-17 22:36:37 +00:00
|
|
|
args[numargs++].set_float(cs_parse_float(
|
|
|
|
*static_cast<Svar *>(cs.identmap[op >> 8])->storage
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_SVARM:
|
2016-08-17 22:36:37 +00:00
|
|
|
args[numargs++].set_cstr(
|
|
|
|
*static_cast<Svar *>(cs.identmap[op >> 8])->storage
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_SVAR1:
|
2016-08-17 21:29:31 +00:00
|
|
|
cs.set_var_str_checked(
|
|
|
|
static_cast<Svar *>(cs.identmap[op >> 8]), args[--numargs].s
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
args[numargs].cleanup();
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_IVAR | RET_INT:
|
|
|
|
case CODE_IVAR | RET_NULL:
|
2016-08-17 22:36:37 +00:00
|
|
|
args[numargs++].set_int(
|
|
|
|
*static_cast<Ivar *>(cs.identmap[op >> 8])->storage
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_IVAR | RET_STR:
|
2016-08-17 22:36:37 +00:00
|
|
|
args[numargs++].set_str(ostd::move(intstr(
|
|
|
|
*static_cast<Ivar *>(cs.identmap[op >> 8])->storage
|
|
|
|
)));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_IVAR | RET_FLOAT:
|
2016-08-17 22:36:37 +00:00
|
|
|
args[numargs++].set_float(CsFloat(
|
|
|
|
*static_cast<Ivar *>(cs.identmap[op >> 8])->storage
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_IVAR1:
|
2016-08-17 21:29:31 +00:00
|
|
|
cs.set_var_int_checked(
|
|
|
|
static_cast<Ivar *>(cs.identmap[op >> 8]), args[--numargs].i
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_IVAR2:
|
|
|
|
numargs -= 2;
|
|
|
|
cs.set_var_int_checked(
|
2016-08-17 21:29:31 +00:00
|
|
|
static_cast<Ivar *>(cs.identmap[op >> 8]),
|
2016-08-17 02:57:53 +00:00
|
|
|
(args[numargs].i << 16) | (args[numargs + 1].i << 8));
|
|
|
|
continue;
|
|
|
|
case CODE_IVAR3:
|
|
|
|
numargs -= 3;
|
|
|
|
cs.set_var_int_checked(
|
2016-08-17 21:29:31 +00:00
|
|
|
static_cast<Ivar *>(cs.identmap[op >> 8]),
|
2016-08-17 02:57:53 +00:00
|
|
|
(args[numargs].i << 16)
|
|
|
|
| (args[numargs + 1].i << 8)
|
|
|
|
| args[numargs + 2].i);
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_FVAR | RET_FLOAT:
|
|
|
|
case CODE_FVAR | RET_NULL:
|
2016-08-17 22:36:37 +00:00
|
|
|
args[numargs++].set_float(
|
|
|
|
*static_cast<Fvar *>(cs.identmap[op >> 8])->storage
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_FVAR | RET_STR:
|
2016-08-17 22:36:37 +00:00
|
|
|
args[numargs++].set_str(ostd::move(floatstr(
|
|
|
|
*static_cast<Fvar *>(cs.identmap[op >> 8])->storage
|
|
|
|
)));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_FVAR | RET_INT:
|
2016-08-17 22:36:37 +00:00
|
|
|
args[numargs++].set_int(int(
|
|
|
|
*static_cast<Fvar *>(cs.identmap[op >> 8])->storage
|
|
|
|
));
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_FVAR1:
|
2016-08-17 21:29:31 +00:00
|
|
|
cs.set_var_float_checked(
|
|
|
|
static_cast<Fvar *>(cs.identmap[op >> 8]), args[--numargs].f
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
case CODE_COM | RET_NULL:
|
|
|
|
case CODE_COM | RET_STR:
|
|
|
|
case CODE_COM | RET_FLOAT:
|
|
|
|
case CODE_COM | RET_INT: {
|
2016-08-17 21:04:43 +00:00
|
|
|
Command *id = static_cast<Command *>(cs.identmap[op >> 8]);
|
2016-08-17 02:57:53 +00:00
|
|
|
int offset = numargs - id->numargs;
|
|
|
|
result.force_null();
|
|
|
|
id->cb_cftv(TvalRange(args + offset, id->numargs), result);
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
free_args(args, numargs, offset);
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
|
|
|
|
case CODE_COMV | RET_NULL:
|
|
|
|
case CODE_COMV | RET_STR:
|
|
|
|
case CODE_COMV | RET_FLOAT:
|
|
|
|
case CODE_COMV | RET_INT: {
|
2016-08-17 21:04:43 +00:00
|
|
|
Command *id = static_cast<Command *>(cs.identmap[op >> 13]);
|
2016-08-17 02:57:53 +00:00
|
|
|
int callargs = (op >> 8) & 0x1F, offset = numargs - callargs;
|
|
|
|
result.force_null();
|
|
|
|
id->cb_cftv(ostd::iter(&args[offset], callargs), result);
|
2016-08-12 16:38:43 +00:00
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
2016-08-17 02:57:53 +00:00
|
|
|
free_args(args, numargs, offset);
|
2016-08-12 16:38:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_COMC | RET_NULL:
|
|
|
|
case CODE_COMC | RET_STR:
|
|
|
|
case CODE_COMC | RET_FLOAT:
|
|
|
|
case CODE_COMC | RET_INT: {
|
2016-08-17 21:04:43 +00:00
|
|
|
Command *id = static_cast<Command *>(cs.identmap[op >> 13]);
|
2016-08-17 02:57:53 +00:00
|
|
|
int callargs = (op >> 8) & 0x1F, offset = numargs - callargs;
|
2016-08-12 16:38:43 +00:00
|
|
|
result.force_null();
|
2016-08-17 02:57:53 +00:00
|
|
|
{
|
|
|
|
auto buf = ostd::appender<ostd::String>();
|
|
|
|
cscript::util::tvals_concat(
|
|
|
|
buf, ostd::iter(&args[offset], callargs), " "
|
|
|
|
);
|
|
|
|
TaggedValue tv;
|
|
|
|
tv.set_mstr(buf.get().iter());
|
|
|
|
id->cb_cftv(TvalRange(&tv, 1), result);
|
|
|
|
}
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
free_args(args, numargs, offset);
|
|
|
|
continue;
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
|
|
|
|
case CODE_CONC | RET_NULL:
|
|
|
|
case CODE_CONC | RET_STR:
|
|
|
|
case CODE_CONC | RET_FLOAT:
|
|
|
|
case CODE_CONC | RET_INT:
|
|
|
|
case CODE_CONCW | RET_NULL:
|
|
|
|
case CODE_CONCW | RET_STR:
|
|
|
|
case CODE_CONCW | RET_FLOAT:
|
|
|
|
case CODE_CONCW | RET_INT: {
|
|
|
|
int numconc = op >> 8;
|
|
|
|
auto buf = ostd::appender<ostd::String>();
|
|
|
|
cscript::util::tvals_concat(
|
|
|
|
buf, ostd::iter(&args[numargs - numconc], numconc),
|
|
|
|
((op & CODE_OP_MASK) == CODE_CONC) ? " " : ""
|
|
|
|
);
|
|
|
|
free_args(args, numargs, numargs - numconc);
|
|
|
|
args[numargs].set_mstr(buf.get().iter());
|
|
|
|
buf.get().disown();
|
|
|
|
force_arg(args[numargs], op & CODE_RET_MASK);
|
|
|
|
numargs++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
case CODE_CONCM | RET_NULL:
|
|
|
|
case CODE_CONCM | RET_STR:
|
|
|
|
case CODE_CONCM | RET_FLOAT:
|
|
|
|
case CODE_CONCM | RET_INT: {
|
|
|
|
int numconc = op >> 8;
|
|
|
|
auto buf = ostd::appender<ostd::String>();
|
|
|
|
cscript::util::tvals_concat(
|
|
|
|
buf, ostd::iter(&args[numargs - numconc], numconc)
|
|
|
|
);
|
|
|
|
free_args(args, numargs, numargs - numconc);
|
|
|
|
result.set_mstr(buf.get().iter());
|
|
|
|
buf.get().disown();
|
2016-08-12 16:38:43 +00:00
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
|
|
|
|
case CODE_ALIAS:
|
2016-08-17 22:06:39 +00:00
|
|
|
static_cast<Alias *>(cs.identmap[op >> 8])->set_alias(
|
|
|
|
cs, args[--numargs]
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_ALIASARG:
|
2016-08-17 22:06:39 +00:00
|
|
|
static_cast<Alias *>(cs.identmap[op >> 8])->set_arg(
|
|
|
|
cs, args[--numargs]
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
continue;
|
|
|
|
case CODE_ALIASU:
|
|
|
|
numargs -= 2;
|
|
|
|
cs.set_alias(args[numargs].get_str(), args[numargs + 1]);
|
|
|
|
args[numargs].cleanup();
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CODE_CALL | RET_NULL:
|
|
|
|
case CODE_CALL | RET_STR:
|
|
|
|
case CODE_CALL | RET_FLOAT:
|
|
|
|
case CODE_CALL | RET_INT: {
|
|
|
|
result.force_null();
|
|
|
|
Ident *id = cs.identmap[op >> 13];
|
|
|
|
int callargs = (op >> 8) & 0x1F, offset = numargs - callargs;
|
|
|
|
if (id->flags & IDF_UNKNOWN) {
|
|
|
|
cs_debug_code(cs, "unknown command: %s", id->name);
|
|
|
|
free_args(args, numargs, offset);
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cs_call_alias(
|
2016-08-17 22:06:39 +00:00
|
|
|
cs, static_cast<Alias *>(id), args, result, callargs,
|
|
|
|
numargs, offset, 0, op
|
2016-08-17 02:57:53 +00:00
|
|
|
);
|
2016-08-12 16:38:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
case CODE_CALLARG | RET_NULL:
|
|
|
|
case CODE_CALLARG | RET_STR:
|
|
|
|
case CODE_CALLARG | RET_FLOAT:
|
|
|
|
case CODE_CALLARG | RET_INT: {
|
|
|
|
result.force_null();
|
|
|
|
Ident *id = cs.identmap[op >> 13];
|
|
|
|
int callargs = (op >> 8) & 0x1F, offset = numargs - callargs;
|
|
|
|
if (!(cs.stack->usedargs & (1 << id->index))) {
|
|
|
|
free_args(args, numargs, offset);
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cs_call_alias(
|
2016-08-17 22:06:39 +00:00
|
|
|
cs, static_cast<Alias *>(id), args, result, callargs,
|
|
|
|
numargs, offset, 0, op
|
2016-08-17 02:57:53 +00:00
|
|
|
);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
case CODE_CALLU | RET_NULL:
|
|
|
|
case CODE_CALLU | RET_STR:
|
|
|
|
case CODE_CALLU | RET_FLOAT:
|
|
|
|
case CODE_CALLU | RET_INT: {
|
|
|
|
int callargs = op >> 8, offset = numargs - callargs;
|
|
|
|
TaggedValue &idarg = args[offset - 1];
|
|
|
|
if (
|
|
|
|
idarg.get_type() != VAL_STR &&
|
|
|
|
idarg.get_type() != VAL_MACRO &&
|
|
|
|
idarg.get_type() != VAL_CSTR
|
|
|
|
) {
|
|
|
|
litval:
|
|
|
|
result.cleanup();
|
|
|
|
result = idarg;
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
while (--numargs >= offset) {
|
|
|
|
args[numargs].cleanup();
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2016-08-17 20:03:11 +00:00
|
|
|
Ident *id = cs.get_ident(idarg.s);
|
2016-08-17 02:57:53 +00:00
|
|
|
if (!id) {
|
|
|
|
noid:
|
|
|
|
if (cs_check_num(idarg.s)) {
|
|
|
|
goto litval;
|
|
|
|
}
|
|
|
|
cs_debug_code(cs, "unknown command: %s", idarg.s);
|
|
|
|
result.force_null();
|
|
|
|
free_args(args, numargs, offset - 1);
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
result.force_null();
|
|
|
|
switch (id->type) {
|
|
|
|
default:
|
2016-08-17 21:04:43 +00:00
|
|
|
if (!cs_has_cmd_cb(id)) {
|
2016-08-17 02:57:53 +00:00
|
|
|
free_args(args, numargs, offset - 1);
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* fallthrough */
|
|
|
|
case ID_COMMAND:
|
|
|
|
idarg.cleanup();
|
2016-08-17 21:04:43 +00:00
|
|
|
callcommand(
|
|
|
|
cs, static_cast<Command *>(id), &args[offset],
|
|
|
|
result, callargs
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
numargs = offset - 1;
|
|
|
|
continue;
|
|
|
|
case ID_LOCAL: {
|
|
|
|
IdentStack locals[MaxArguments];
|
|
|
|
idarg.cleanup();
|
|
|
|
for (ostd::Size j = 0; j < ostd::Size(callargs); ++j) {
|
2016-08-17 22:06:39 +00:00
|
|
|
cs_push_alias(cs.force_ident(
|
2016-08-17 02:57:53 +00:00
|
|
|
args[offset + j]
|
2016-08-17 22:06:39 +00:00
|
|
|
), locals[j]);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
code = runcode(cs, code, result);
|
|
|
|
for (ostd::Size j = 0; j < ostd::Size(callargs); ++j) {
|
2016-08-17 22:06:39 +00:00
|
|
|
cs_pop_alias(args[offset + j].id);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
case ID_IVAR:
|
|
|
|
if (callargs <= 0) {
|
2016-08-17 21:29:31 +00:00
|
|
|
cs.print_var(static_cast<Ivar *>(id));
|
2016-08-17 02:57:53 +00:00
|
|
|
} else {
|
|
|
|
cs.set_var_int_checked(
|
2016-08-17 21:29:31 +00:00
|
|
|
static_cast<Ivar *>(id),
|
|
|
|
ostd::iter(&args[offset], callargs)
|
2016-08-17 02:57:53 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
free_args(args, numargs, offset - 1);
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
|
|
|
case ID_FVAR:
|
|
|
|
if (callargs <= 0) {
|
2016-08-17 21:29:31 +00:00
|
|
|
cs.print_var(static_cast<Fvar *>(id));
|
2016-08-17 02:57:53 +00:00
|
|
|
} else {
|
|
|
|
cs.set_var_float_checked(
|
2016-08-17 21:29:31 +00:00
|
|
|
static_cast<Fvar *>(id),
|
|
|
|
args[offset].force_float()
|
2016-08-17 02:57:53 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
free_args(args, numargs, offset - 1);
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
|
|
|
case ID_SVAR:
|
|
|
|
if (callargs <= 0) {
|
2016-08-17 21:29:31 +00:00
|
|
|
cs.print_var(static_cast<Svar *>(id));
|
2016-08-17 02:57:53 +00:00
|
|
|
} else {
|
2016-08-17 21:29:31 +00:00
|
|
|
cs.set_var_str_checked(
|
|
|
|
static_cast<Svar *>(id),
|
|
|
|
args[offset].force_str()
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
free_args(args, numargs, offset - 1);
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
2016-08-17 22:06:39 +00:00
|
|
|
case ID_ALIAS: {
|
|
|
|
Alias *a = static_cast<Alias *>(id);
|
2016-08-17 02:57:53 +00:00
|
|
|
if (
|
2016-08-17 22:06:39 +00:00
|
|
|
a->index < MaxArguments &&
|
|
|
|
!(cs.stack->usedargs & (1 << a->index))
|
2016-08-17 02:57:53 +00:00
|
|
|
) {
|
|
|
|
free_args(args, numargs, offset - 1);
|
|
|
|
force_arg(result, op & CODE_RET_MASK);
|
|
|
|
continue;
|
|
|
|
}
|
2016-08-17 22:06:39 +00:00
|
|
|
if (a->get_valtype() == VAL_NULL) {
|
2016-08-17 02:57:53 +00:00
|
|
|
goto noid;
|
|
|
|
}
|
|
|
|
idarg.cleanup();
|
|
|
|
cs_call_alias(
|
2016-08-17 22:06:39 +00:00
|
|
|
cs, a, args, result, callargs, numargs,
|
2016-08-17 02:57:53 +00:00
|
|
|
offset, 1, op
|
|
|
|
);
|
|
|
|
continue;
|
2016-08-17 22:06:39 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
exit:
|
|
|
|
--rundepth;
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CsState::run_ret(Bytecode const *code, TaggedValue &ret) {
|
|
|
|
runcode(*this, reinterpret_cast<ostd::Uint32 const *>(code), ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CsState::run_ret(ostd::ConstCharRange code, TaggedValue &ret) {
|
|
|
|
GenState gs(*this);
|
|
|
|
gs.code.reserve(64);
|
|
|
|
/* FIXME range */
|
|
|
|
gs.gen_main(code.data(), VAL_ANY);
|
|
|
|
runcode(*this, gs.code.data() + 1, ret);
|
2016-08-17 02:57:53 +00:00
|
|
|
if (int(gs.code[0]) >= 0x100) {
|
2016-08-12 16:38:43 +00:00
|
|
|
gs.code.disown();
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO */
|
|
|
|
void CsState::run_ret(Ident *id, TvalRange args, TaggedValue &ret) {
|
|
|
|
int nargs = int(args.size());
|
|
|
|
ret.set_null();
|
|
|
|
++rundepth;
|
2016-08-17 02:57:53 +00:00
|
|
|
if (rundepth > MaxRunDepth) {
|
|
|
|
cs_debug_code(*this, "exceeded recursion limit");
|
|
|
|
} else if (id) {
|
|
|
|
switch (id->type) {
|
|
|
|
default:
|
2016-08-17 21:04:43 +00:00
|
|
|
if (!cs_has_cmd_cb(id)) {
|
2016-08-17 02:57:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fallthrough */
|
|
|
|
case ID_COMMAND:
|
2016-08-17 21:04:43 +00:00
|
|
|
if (nargs < static_cast<Command *>(id)->numargs) {
|
2016-08-17 02:57:53 +00:00
|
|
|
TaggedValue buf[MaxArguments];
|
|
|
|
memcpy(buf, args.data(), args.size() * sizeof(TaggedValue));
|
2016-08-17 21:04:43 +00:00
|
|
|
callcommand(
|
|
|
|
*this, static_cast<Command *>(id), buf, ret,
|
|
|
|
nargs, false
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
} else {
|
2016-08-17 21:04:43 +00:00
|
|
|
callcommand(
|
|
|
|
*this, static_cast<Command *>(id), args.data(),
|
|
|
|
ret, nargs, false
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
nargs = 0;
|
|
|
|
break;
|
|
|
|
case ID_IVAR:
|
|
|
|
if (args.empty()) {
|
2016-08-17 21:29:31 +00:00
|
|
|
print_var(static_cast<Ivar *>(id));
|
2016-08-17 02:57:53 +00:00
|
|
|
} else {
|
2016-08-17 21:29:31 +00:00
|
|
|
set_var_int_checked(static_cast<Ivar *>(id), args);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ID_FVAR:
|
|
|
|
if (args.empty()) {
|
2016-08-17 21:29:31 +00:00
|
|
|
print_var(static_cast<Fvar *>(id));
|
2016-08-17 02:57:53 +00:00
|
|
|
} else {
|
2016-08-17 21:29:31 +00:00
|
|
|
set_var_float_checked(
|
|
|
|
static_cast<Fvar *>(id), args[0].force_float()
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ID_SVAR:
|
|
|
|
if (args.empty()) {
|
2016-08-17 21:29:31 +00:00
|
|
|
print_var(static_cast<Svar *>(id));
|
2016-08-17 02:57:53 +00:00
|
|
|
} else {
|
2016-08-17 21:29:31 +00:00
|
|
|
set_var_str_checked(
|
|
|
|
static_cast<Svar *>(id), args[0].force_str()
|
|
|
|
);
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
|
|
|
break;
|
2016-08-17 22:06:39 +00:00
|
|
|
case ID_ALIAS: {
|
|
|
|
Alias *a = static_cast<Alias *>(id);
|
|
|
|
if (a->index < MaxArguments) {
|
|
|
|
if (!(stack->usedargs & (1 << a->index))) {
|
2016-08-17 02:57:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-08-17 22:06:39 +00:00
|
|
|
if (a->get_valtype() == VAL_NULL) {
|
2016-08-17 02:57:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
cs_call_alias(
|
2016-08-17 22:06:39 +00:00
|
|
|
*this, a, args.data(), ret, nargs, nargs, 0, 0, RET_NULL
|
2016-08-17 02:57:53 +00:00
|
|
|
);
|
|
|
|
break;
|
2016-08-17 22:06:39 +00:00
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
}
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
free_args(args.data(), nargs, 0);
|
|
|
|
--rundepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
ostd::String CsState::run_str(Bytecode const *code) {
|
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(code, ret);
|
|
|
|
ostd::String s = ret.get_str();
|
|
|
|
ret.cleanup();
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
ostd::String CsState::run_str(ostd::ConstCharRange code) {
|
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(code, ret);
|
|
|
|
ostd::String s = ret.get_str();
|
|
|
|
ret.cleanup();
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
ostd::String CsState::run_str(Ident *id, TvalRange args) {
|
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(id, args, ret);
|
|
|
|
ostd::String s = ret.get_str();
|
|
|
|
ret.cleanup();
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt CsState::run_int(Bytecode const *code) {
|
2016-08-12 16:38:43 +00:00
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(code, ret);
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt i = ret.get_int();
|
2016-08-12 16:38:43 +00:00
|
|
|
ret.cleanup();
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt CsState::run_int(ostd::ConstCharRange code) {
|
2016-08-12 16:38:43 +00:00
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(code, ret);
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt i = ret.get_int();
|
2016-08-12 16:38:43 +00:00
|
|
|
ret.cleanup();
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt CsState::run_int(Ident *id, TvalRange args) {
|
2016-08-12 16:38:43 +00:00
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(id, args, ret);
|
2016-08-14 16:35:38 +00:00
|
|
|
CsInt i = ret.get_int();
|
2016-08-12 16:38:43 +00:00
|
|
|
ret.cleanup();
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2016-08-14 16:35:38 +00:00
|
|
|
CsFloat CsState::run_float(Bytecode const *code) {
|
2016-08-12 16:38:43 +00:00
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(code, ret);
|
2016-08-14 16:35:38 +00:00
|
|
|
CsFloat f = ret.get_float();
|
2016-08-12 16:38:43 +00:00
|
|
|
ret.cleanup();
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2016-08-14 16:35:38 +00:00
|
|
|
CsFloat CsState::run_float(ostd::ConstCharRange code) {
|
2016-08-12 16:38:43 +00:00
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(code, ret);
|
2016-08-14 16:35:38 +00:00
|
|
|
CsFloat f = ret.get_float();
|
2016-08-12 16:38:43 +00:00
|
|
|
ret.cleanup();
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2016-08-14 16:35:38 +00:00
|
|
|
CsFloat CsState::run_float(Ident *id, TvalRange args) {
|
2016-08-12 16:38:43 +00:00
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(id, args, ret);
|
2016-08-14 16:35:38 +00:00
|
|
|
CsFloat f = ret.get_float();
|
2016-08-12 16:38:43 +00:00
|
|
|
ret.cleanup();
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CsState::run_bool(Bytecode const *code) {
|
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(code, ret);
|
|
|
|
bool b = ret.get_bool();
|
|
|
|
ret.cleanup();
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CsState::run_bool(ostd::ConstCharRange code) {
|
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(code, ret);
|
|
|
|
bool b = ret.get_bool();
|
|
|
|
ret.cleanup();
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CsState::run_bool(Ident *id, TvalRange args) {
|
|
|
|
TaggedValue ret;
|
|
|
|
run_ret(id, args, ret);
|
|
|
|
bool b = ret.get_bool();
|
|
|
|
ret.cleanup();
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CsState::run_file(ostd::ConstCharRange fname) {
|
|
|
|
ostd::ConstCharRange oldsrcfile = src_file, oldsrcstr = src_str;
|
2016-08-12 23:26:16 +00:00
|
|
|
ostd::Box<char[]> buf;
|
2016-08-12 16:38:43 +00:00
|
|
|
ostd::Size len;
|
|
|
|
|
|
|
|
ostd::FileStream f(fname, ostd::StreamMode::read);
|
2016-08-17 02:57:53 +00:00
|
|
|
if (!f.is_open()) {
|
2016-08-12 16:38:43 +00:00
|
|
|
return false;
|
2016-08-17 02:57:53 +00:00
|
|
|
}
|
2016-08-12 16:38:43 +00:00
|
|
|
|
|
|
|
len = f.size();
|
2016-08-12 23:26:16 +00:00
|
|
|
buf = ostd::make_box<char[]>(len + 1);
|
|
|
|
if (!buf || f.get(buf.get(), len) != len) {
|
2016-08-12 16:38:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
buf[len] = '\0';
|
|
|
|
|
|
|
|
src_file = fname;
|
2016-08-12 23:26:16 +00:00
|
|
|
src_str = ostd::ConstCharRange(buf.get(), len);
|
|
|
|
run_int(src_str);
|
2016-08-12 16:38:43 +00:00
|
|
|
src_file = oldsrcfile;
|
|
|
|
src_str = oldsrcstr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace cscript */
|