diff --git a/src/cs_bcode.hh b/src/cs_bcode.hh index 457e413..44a1f7c 100644 --- a/src/cs_bcode.hh +++ b/src/cs_bcode.hh @@ -163,9 +163,9 @@ enum { BC_INST_ALIAS, /* pop 2 values off the stack; top is value to set, below is alias name */ BC_INST_ALIAS_U, - /* call alias with index D[5..] and arg count D[0..5], pop the arguments - * off the stack (top being last); if unknown, raise error, store result - * in R according to M + /* call alias with index D and arg count following the instruction, pop + * the arguments off the stack (top being last); if unknown, raise error, + * store result in R according to M */ BC_INST_CALL, /* given argument count D, pop the arguments off the stack (top being last) @@ -178,12 +178,12 @@ enum { * last argument being topmost; result of the call goes in R according to M */ BC_INST_COM, - /* call builtin command with index D[5..] and number of arguments D[0..5] - * arguments are popped off the stack and passed as is + /* call builtin command with index D and arg count following the + * instruction, arguments are popped off the stack and passed as is */ BC_INST_COM_V, - /* call builtin command with index D[5..] and number of arguments D[0..5] - * arguments are popped off the stack and concatenated together + /* call builtin command with index D and arg count following the + * instruction, arguments are popped off the stack and concatenated */ BC_INST_COM_C, diff --git a/src/cs_gen.cc b/src/cs_gen.cc index ddde6f3..8b4ce1f 100644 --- a/src/cs_gen.cc +++ b/src/cs_gen.cc @@ -308,7 +308,7 @@ lookupid: } goto done; case ident_type::COMMAND: { - int comtype = BC_INST_COM, numargs = 0; + std::uint32_t comtype = BC_INST_COM, numargs = 0; auto fmt = static_cast(id)->get_args(); for (char c: fmt) { switch (c) { @@ -375,9 +375,9 @@ lookupid: goto done; compilecomv: gs.code.push_back( - comtype | ret_code(ltype) | (numargs << 8) | - (id->get_index() << 13) + comtype | ret_code(ltype) | (id->get_index() << 8) ); + gs.code.push_back(numargs); gs.code.push_back( BC_INST_RESULT_ARG | ret_code(ltype) ); @@ -802,7 +802,7 @@ static bool compilearg( static void compile_cmd( codegen_state &gs, command_impl *id, bool &more, int rettype ) { - int comtype = BC_INST_COM, numargs = 0, fakeargs = 0; + std::uint32_t comtype = BC_INST_COM, numargs = 0, fakeargs = 0; bool rep = false; auto fmt = id->get_args(); for (auto it = fmt.begin(); it != fmt.end(); ++it) { @@ -819,11 +819,7 @@ static void compile_cmd( fakeargs++; } else if ((it + 1) == fmt.end()) { int numconc = 1; - while ((numargs + numconc) < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_STRING); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_STRING))) { numconc++; } if (numconc > 1) { @@ -947,11 +943,7 @@ static void compile_cmd( case 'C': /* concatenated string */ comtype = BC_INST_COM_C; if (more) { - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_ANY); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_ANY))) { numargs++; } } @@ -959,11 +951,7 @@ static void compile_cmd( case 'V': /* varargs */ comtype = BC_INST_COM_V; if (more) { - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_ANY); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_ANY))) { numargs++; } } @@ -972,15 +960,10 @@ static void compile_cmd( case '2': case '3': case '4': - if (more && (numargs < MAX_ARGUMENTS)) { + if (more) { int numrep = *it - '0' + 1; it -= numrep; rep = true; - } else { - while (numargs > MAX_ARGUMENTS) { - gs.code.push_back(BC_INST_POP); - --numargs; - } } break; } @@ -989,38 +972,29 @@ static void compile_cmd( return; compilecomv: gs.code.push_back( - comtype | ret_code(rettype) | (numargs << 8) | (id->get_index() << 13) + comtype | ret_code(rettype) | (id->get_index() << 8) ); + gs.code.push_back(numargs); } static void compile_alias(codegen_state &gs, alias *id, bool &more) { - int numargs = 0; - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_ANY); - if (!more) { - break; - } + std::uint32_t numargs = 0; + while ((more = compilearg(gs, VAL_ANY))) { ++numargs; } gs.code.push_back( - BC_INST_CALL | (numargs << 8) | (id->get_index() << 13) + BC_INST_CALL | (id->get_index() << 8) ); + gs.code.push_back(numargs); } static void compile_local(codegen_state &gs, bool &more) { - int numargs = 0; + std::uint32_t numargs = 0; if (more) { - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_IDENT); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_IDENT))) { numargs++; } } - if (more) { - while ((more = compilearg(gs, VAL_POP))); - } gs.code.push_back(BC_INST_LOCAL | (numargs << 8)); } @@ -1100,7 +1074,7 @@ static void compile_if( static void compile_and_or( codegen_state &gs, ident *id, bool &more, int rettype ) { - int numargs = 0; + std::uint32_t numargs = 0; if (more) { more = compilearg(gs, VAL_COND); } @@ -1112,11 +1086,7 @@ static void compile_and_or( } else { numargs++; int start = gs.code.size(), end = start; - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_COND); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_COND))) { numargs++; if ((gs.code[end] & ~BC_INST_RET_MASK) != ( BC_INST_BLOCK | (uint32_t(gs.code.size() - (end + 1)) << 8) @@ -1126,17 +1096,13 @@ static void compile_and_or( end = gs.code.size(); } if (more) { - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_COND); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_COND))) { numargs++; } gs.code.push_back( - BC_INST_COM_V | ret_code(rettype) | - (numargs << 8) | (id->get_index() << 13) + BC_INST_COM_V | ret_code(rettype) | (id->get_index() << 8) ); + gs.code.push_back(numargs); } else { uint32_t op = (id->get_raw_type() == ID_AND) ? (BC_INST_JUMP_RESULT | BC_INST_FLAG_FALSE) @@ -1240,12 +1206,8 @@ static void compilestatements(codegen_state &gs, int rettype, int brak) { } if (idname.empty()) { noid: - int numargs = 0; - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_ANY); - if (!more) { - break; - } + std::uint32_t numargs = 0; + while ((more = compilearg(gs, VAL_ANY))) { ++numargs; } gs.code.push_back(BC_INST_CALL_U | (numargs << 8)); @@ -1351,12 +1313,10 @@ noid: if (!(more = compilearg(gs, VAL_STRING))) { gs.code.push_back(BC_INST_PRINT | (id->get_index() << 8)); } else { - int numargs = 0; + std::uint32_t numargs = 0; do { ++numargs; - } while (numargs < MAX_ARGUMENTS && ( - more = compilearg(gs, VAL_ANY) - )); + } while ((more = compilearg(gs, VAL_ANY))); if (numargs > 1) { gs.code.push_back( BC_INST_CONC | BC_RET_STRING | (numargs << 8) diff --git a/src/cs_ident.hh b/src/cs_ident.hh index 27b7555..259e91f 100644 --- a/src/cs_ident.hh +++ b/src/cs_ident.hh @@ -7,7 +7,7 @@ namespace cubescript { -static constexpr int MAX_ARGUMENTS = 32; +static constexpr std::size_t MAX_ARGUMENTS = 32; using argset = std::bitset; enum { diff --git a/src/cs_state.cc b/src/cs_state.cc index a01e8c3..c60f9df 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -73,9 +73,9 @@ state::state(alloc_func func, void *data) { p_tstate->istate = statep; p_tstate->owner = true; - for (int i = 0; i < MAX_ARGUMENTS; ++i) { - char buf[32]; - snprintf(buf, sizeof(buf), "arg%d", i + 1); + for (std::size_t i = 0; i < MAX_ARGUMENTS; ++i) { + char buf[16]; + snprintf(buf, sizeof(buf), "arg%zu", i + 1); new_ident(static_cast(buf), IDENT_FLAG_ARG); } @@ -419,15 +419,14 @@ LIBCUBESCRIPT_EXPORT command *state::new_command( case 'e': case 'r': case '$': - if (nargs < MAX_ARGUMENTS) { - ++nargs; - } + ++nargs; break; case '1': case '2': case '3': - case '4': - if (nargs < (*fmt - '0')) { + case '4': { + int nrep = (*fmt - '0'); + if (nargs < nrep) { return nullptr; } if ((args.end() - fmt) != 2) { @@ -436,10 +435,9 @@ LIBCUBESCRIPT_EXPORT command *state::new_command( if ((fmt[1] != 'C') && (fmt[1] != 'V')) { return nullptr; } - if (nargs < MAX_ARGUMENTS) { - fmt -= *fmt - '0' + 1; - } + nargs -= nrep; break; + } case 'C': case 'V': if ((fmt + 1) != args.end()) { diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 4bd2f19..e148ac4 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -202,6 +202,8 @@ void exec_alias( std::size_t callargs, std::size_t &nargs, std::size_t offset, std::size_t skip, std::uint32_t op ) { + /* excess arguments get ignored (make error maybe?) */ + callargs = std::min(callargs, MAX_ARGUMENTS); integer_var *anargs = static_cast( ts.istate->identmap[ID_IDX_NUMARGS] ); @@ -1062,8 +1064,8 @@ std::uint32_t *vm_exec( case BC_INST_CALL | BC_RET_FLOAT: case BC_INST_CALL | BC_RET_INT: { result.force_none(); - ident *id = ts.istate->identmap[op >> 13]; - std::size_t callargs = (op >> 8) & 0x1F; + ident *id = ts.istate->identmap[op >> 8]; + std::size_t callargs = *code++; std::size_t nnargs = args.size(); std::size_t offset = nnargs - callargs; auto flags = id->get_flags(); @@ -1232,9 +1234,9 @@ noid: case BC_INST_COM_V | BC_RET_FLOAT: case BC_INST_COM_V | BC_RET_INT: { command_impl *id = static_cast( - ts.istate->identmap[op >> 13] + ts.istate->identmap[op >> 8] ); - std::size_t callargs = (op >> 8) & 0x1F; + std::size_t callargs = *code++; std::size_t offset = args.size() - callargs; result.force_none(); id->call(cs, std::span{&args[offset], callargs}, result); @@ -1247,10 +1249,10 @@ noid: case BC_INST_COM_C | BC_RET_FLOAT: case BC_INST_COM_C | BC_RET_INT: { command_impl *id = static_cast( - ts.istate->identmap[op >> 13] + ts.istate->identmap[op >> 8] ); - std::size_t callargs = (op >> 8) & 0x1F, - offset = args.size() - callargs; + std::size_t callargs = *code++; + std::size_t offset = args.size() - callargs; result.force_none(); { any_value tv{cs};