putchar('\n');
}
+qc_program::qc_program(const char *name, uint16_t crc, size_t entfields)
+ : filename(name)
+ , crc16(crc)
+ , entityfields(entfields)
+{}
+
qc_program_t* prog_load(const char *filename, bool skipversion)
{
prog_header_t header;
return nullptr;
}
- prog = (qc_program_t*)mem_a(sizeof(qc_program_t));
- if (!prog) {
- fclose(file);
- fprintf(stderr, "failed to allocate program data\n");
- return nullptr;
- }
- memset(prog, 0, sizeof(*prog));
-
- prog->entityfields = header.entfield;
- prog->crc16 = header.crc16;
-
- prog->filename = util_strdup(filename);
- if (!prog->filename) {
- loaderror("failed to store program name");
- goto error;
- }
+ prog = new qc_program(filename, header.crc16, header.entfield);
#define read_data(hdrvar, progvar, reserved) \
if (fseek(file, header.hdrvar.offset, SEEK_SET) != 0) { \
fclose(file);
/* profile counters */
- memset(vec_add(prog->profile, prog->code.size()), 0, sizeof(prog->profile[0]) * prog->code.size());
+ prog->profile.resize(prog->code.size());
+ memset(&prog->profile[0], 0, sizeof(prog->profile[0]) * prog->profile.size());
/* Add tempstring area */
prog->tempstring_start = prog->strings.size();
prog->strings.resize(prog->strings.size() + 16*1024, '\0');
/* spawn the world entity */
- vec_push(prog->entitypool, true);
- memset(vec_add(prog->entitydata, prog->entityfields), 0, prog->entityfields * sizeof(prog->entitydata[0]));
+ prog->entitypool.emplace_back(true);
+ prog->entitydata.resize(prog->entityfields);
+ memset(prog->entitydata.data(), 0, sizeof(prog->entitydata[0]) * prog->entityfields);
prog->entities = 1;
/* cache some globals and fields from names */
return prog;
error:
- if (prog->filename)
- mem_d(prog->filename);
- vec_free(prog->entitydata);
- vec_free(prog->entitypool);
- mem_d(prog);
+ delete prog;
fclose(file);
return nullptr;
void prog_delete(qc_program_t *prog)
{
- if (prog->filename) mem_d(prog->filename);
- vec_free(prog->entitydata);
- vec_free(prog->entitypool);
- vec_free(prog->localstack);
- vec_free(prog->stack);
- vec_free(prog->profile);
- mem_d(prog);
+ delete prog;
}
/***********************************************************************
}
qcany_t* prog_getedict(qc_program_t *prog, qcint_t e) {
- if (e >= (qcint_t)vec_size(prog->entitypool)) {
+ if (e >= (qcint_t)prog->entitypool.size()) {
prog->vmerror++;
fprintf(stderr, "Accessing out of bounds edict %i\n", (int)e);
e = 0;
}
- return (qcany_t*)(prog->entitydata + (prog->entityfields * e));
+ return (qcany_t*)&prog->entitydata[prog->entityfields * e];
}
static qcint_t prog_spawn_entity(qc_program_t *prog) {
char *data;
qcint_t e;
- for (e = 0; e < (qcint_t)vec_size(prog->entitypool); ++e) {
+ for (e = 0; e < (qcint_t)prog->entitypool.size(); ++e) {
if (!prog->entitypool[e]) {
- data = (char*)(prog->entitydata + (prog->entityfields * e));
+ data = (char*)&prog->entitydata[prog->entityfields * e];
memset(data, 0, prog->entityfields * sizeof(qcint_t));
return e;
}
}
- vec_push(prog->entitypool, true);
+ prog->entitypool.emplace_back(true);
prog->entities++;
- data = (char*)vec_add(prog->entitydata, prog->entityfields);
- memset(data, 0, prog->entityfields * sizeof(qcint_t));
+ size_t sz = prog->entitydata.size();
+ prog->entitydata.resize(sz + prog->entityfields);
+ data = (char*)&prog->entitydata[sz];
+ memset(data, 0, sz * sizeof(qcint_t));
+
return e;
}
fprintf(stderr, "Trying to free world entity\n");
return;
}
- if (e >= (qcint_t)vec_size(prog->entitypool)) {
+ if (e >= (qcint_t)prog->entitypool.size()) {
prog->vmerror++;
fprintf(stderr, "Trying to free out of bounds entity\n");
return;
printf("<illegal instruction %d>\n", st->opcode);
return;
}
- if ((prog->xflags & VMXF_TRACE) && vec_size(prog->function_stack)) {
+ if ((prog->xflags & VMXF_TRACE) && !prog->function_stack.empty()) {
size_t i;
- for (i = 0; i < vec_size(prog->function_stack); ++i)
+ for (i = 0; i < prog->function_stack.size(); ++i)
printf("->");
- printf("%s:", vec_last(prog->function_stack));
+ printf("%s:", prog->function_stack.back());
}
printf(" <> %-12s", util_instr_str[st->opcode]);
if (st->opcode >= INSTR_IF &&
int32_t p;
/* back up locals */
- st.localsp = vec_size(prog->localstack);
+ st.localsp = prog->localstack.size();
st.stmt = prog->statement;
st.function = func;
if (prog->xflags & VMXF_TRACE) {
const char *str = prog_getstring(prog, func->name);
- vec_push(prog->function_stack, str);
+ prog->function_stack.emplace_back(str);
}
#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS
- if (vec_size(prog->stack))
+ if (prog->stack.size())
{
prog_section_function_t *cur;
- cur = prog->stack[vec_size(prog->stack)-1].function;
+ cur = prog->stack.back().function;
if (cur)
{
qcint_t *globals = &prog->globals[0] + cur->firstlocal;
- vec_append(prog->localstack, cur->locals, globals);
+ prog->localstack.insert(prog->localstack.end(), globals, globals + cur->locals);
}
}
#else
{
qcint_t *globals = &prog->globals[0] + func->firstlocal;
- vec_append(prog->localstack, func->locals, globals);
+ prog->localstack.insert(prog->localstack.end(), globals, globals + func->locals);
}
#endif
}
}
- vec_push(prog->stack, st);
+ prog->stack.emplace_back(st);
return func->entry;
}
prog_section_function_t *prev = nullptr;
size_t oldsp;
- qc_exec_stack_t st = vec_last(prog->stack);
+ qc_exec_stack_t st = prog->stack.back();
if (prog->xflags & VMXF_TRACE) {
- if (vec_size(prog->function_stack))
- vec_pop(prog->function_stack);
+ if (!prog->function_stack.empty())
+ prog->function_stack.pop_back();
}
#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS
- if (vec_size(prog->stack) > 1) {
- prev = prog->stack[vec_size(prog->stack)-2].function;
- oldsp = prog->stack[vec_size(prog->stack)-2].localsp;
+ if (prog->stack.size() > 1) {
+ prev = prog->stack[prog->stack.size()-2].function;
+ oldsp = prog->stack[prog->stack.size()-2].localsp;
}
#else
- prev = prog->stack[vec_size(prog->stack)-1].function;
- oldsp = prog->stack[vec_size(prog->stack)-1].localsp;
+ prev = prog->stack[prog->stack.size()-1].function;
+ oldsp = prog->stack[prog->stack.size()-1].localsp;
#endif
if (prev) {
qcint_t *globals = &prog->globals[0] + prev->firstlocal;
- memcpy(globals, prog->localstack + oldsp, prev->locals * sizeof(prog->localstack[0]));
- /* vec_remove(prog->localstack, oldsp, vec_size(prog->localstack)-oldsp); */
- vec_shrinkto(prog->localstack, oldsp);
+ memcpy(globals, &prog->localstack[oldsp], prev->locals * sizeof(prog->localstack[0]));
+ prog->localstack.resize(oldsp);
}
- vec_pop(prog->stack);
+ prog->stack.pop_back();
return st.stmt - 1; /* offset the ++st */
}
cleanup:
prog->xflags = oldxflags;
- vec_free(prog->localstack);
- vec_free(prog->stack);
+ prog->localstack.clear();
+ prog->stack.clear();
if (prog->vmerror)
return false;
return true;
const char *value;
};
-static qcvm_parameter *main_params = nullptr;
+static std::vector<qcvm_parameter> main_params;
#define CheckArgs(num) do { \
if (prog->argc != (num)) { \
size_t i;
qcany_t *arg;
- for (i = 0; i < vec_size(main_params); ++i) {
+ for (i = 0; i < main_params.size(); ++i) {
arg = GetGlobal(OFS_PARM0 + 3*i);
arg->vector[0] = 0;
arg->vector[1] = 0;
bool opts_info = false;
bool noexec = false;
const char *progsfile = nullptr;
- const char **dis_list = nullptr;
int opts_v = 0;
+ std::vector<const char*> dis_list;
arg0 = argv[0];
usage();
exit(EXIT_FAILURE);
}
- vec_push(dis_list, argv[1]);
+ dis_list.emplace_back(argv[1]);
--argc;
++argv;
noexec = true;
}
p.value = argv[1];
- vec_push(main_params, p);
+ main_params.emplace_back(p);
--argc;
++argv;
}
prog_delete(prog);
return 0;
}
- for (i = 0; i < vec_size(dis_list); ++i) {
+ for (i = 0; i < dis_list.size(); ++i) {
size_t k;
printf("Looking for `%s`\n", dis_list[i]);
for (k = 1; k < prog->functions.size(); ++k) {
switch (st->opcode)
{
default:
- qcvmerror(prog, "Illegal instruction in %s\n", prog->filename);
+ qcvmerror(prog, "Illegal instruction in %s\n", prog->filename.c_str());
goto cleanup;
case INSTR_DONE:
GLOBAL(OFS_RETURN)->ivector[2] = OPA->ivector[2];
st = &prog->code[0] + prog_leavefunction(prog);
- if (!vec_size(prog->stack))
+ if (prog->stack.empty())
goto cleanup;
break;
case INSTR_LOAD_ENT:
case INSTR_LOAD_FNC:
if (OPA->edict < 0 || OPA->edict >= prog->entities) {
- qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename);
+ qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename.c_str());
goto cleanup;
}
if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields)) {
qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
- prog->filename,
+ prog->filename.c_str(),
OPB->_int);
goto cleanup;
}
break;
case INSTR_LOAD_V:
if (OPA->edict < 0 || OPA->edict >= prog->entities) {
- qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename);
+ qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename.c_str());
goto cleanup;
}
if (OPB->_int < 0 || OPB->_int + 3 > (qcint_t)prog->entityfields)
{
qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
- prog->filename,
+ prog->filename.c_str(),
OPB->_int + 2);
goto cleanup;
}
case INSTR_ADDRESS:
if (OPA->edict < 0 || OPA->edict >= prog->entities) {
- qcvmerror(prog, "prog `%s` attempted to address an out of bounds entity %i", prog->filename, OPA->edict);
+ qcvmerror(prog, "prog `%s` attempted to address an out of bounds entity %i", prog->filename.c_str(), OPA->edict);
goto cleanup;
}
if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields))
{
qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)",
- prog->filename,
+ prog->filename.c_str(),
OPB->_int);
goto cleanup;
}
ed = prog_getedict(prog, OPA->edict);
- OPC->_int = ((qcint_t*)ed) - prog->entitydata + OPB->_int;
+ OPC->_int = ((qcint_t*)ed) - prog->entitydata.data() + OPB->_int;
break;
case INSTR_STORE_F:
case INSTR_STOREP_ENT:
case INSTR_STOREP_FLD:
case INSTR_STOREP_FNC:
- if (OPB->_int < 0 || OPB->_int >= (qcint_t)vec_size(prog->entitydata)) {
- qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
+ if (OPB->_int < 0 || OPB->_int >= (qcint_t)prog->entitydata.size()) {
+ qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename.c_str(), OPB->_int);
goto cleanup;
}
if (OPB->_int < (qcint_t)prog->entityfields && !prog->allowworldwrites)
qcvmerror(prog, "`%s` tried to assign to world.%s (field %i)\n",
- prog->filename,
+ prog->filename.c_str(),
prog_getstring(prog, prog_entfield(prog, OPB->_int)->name),
OPB->_int);
- ptr = (qcany_t*)(prog->entitydata + OPB->_int);
+ ptr = (qcany_t*)&prog->entitydata[OPB->_int];
ptr->_int = OPA->_int;
break;
case INSTR_STOREP_V:
- if (OPB->_int < 0 || OPB->_int + 2 >= (qcint_t)vec_size(prog->entitydata)) {
- qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
+ if (OPB->_int < 0 || OPB->_int + 2 >= (qcint_t)prog->entitydata.size()) {
+ qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename.c_str(), OPB->_int);
goto cleanup;
}
if (OPB->_int < (qcint_t)prog->entityfields && !prog->allowworldwrites)
qcvmerror(prog, "`%s` tried to assign to world.%s (field %i)\n",
- prog->filename,
+ prog->filename.c_str(),
prog_getstring(prog, prog_entfield(prog, OPB->_int)->name),
OPB->_int);
- ptr = (qcany_t*)(prog->entitydata + OPB->_int);
+ ptr = (qcany_t*)&prog->entitydata[OPB->_int];
ptr->ivector[0] = OPA->ivector[0];
ptr->ivector[1] = OPA->ivector[1];
ptr->ivector[2] = OPA->ivector[2];
{
st += st->o2.s1 - 1; /* offset the s++ */
if (++jumpcount >= maxjumps)
- qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
+ qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename.c_str(), jumpcount);
}
break;
case INSTR_IFNOT:
{
st += st->o2.s1 - 1; /* offset the s++ */
if (++jumpcount >= maxjumps)
- qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
+ qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename.c_str(), jumpcount);
}
break;
case INSTR_CALL8:
prog->argc = st->opcode - INSTR_CALL0;
if (!OPA->function)
- qcvmerror(prog, "nullptr function in `%s`", prog->filename);
+ qcvmerror(prog, "nullptr function in `%s`", prog->filename.c_str());
if(!OPA->function || OPA->function >= (qcint_t)prog->functions.size())
{
- qcvmerror(prog, "CALL outside the program in `%s`", prog->filename);
+ qcvmerror(prog, "CALL outside the program in `%s`", prog->filename.c_str());
goto cleanup;
}
prog->builtins[builtinnumber](prog);
else
qcvmerror(prog, "No such builtin #%i in %s! Try updating your gmqcc sources",
- builtinnumber, prog->filename);
+ builtinnumber, prog->filename.c_str());
}
else
st = &prog->code[0] + prog_enterfunction(prog, newf) - 1; /* offset st++ */
qcfloat_t *time;
qcfloat_t *frame;
if (!prog->supports_state) {
- qcvmerror(prog, "`%s` tried to execute a STATE operation but misses its defs!", prog->filename);
+ qcvmerror(prog, "`%s` tried to execute a STATE operation but misses its defs!", prog->filename.c_str());
goto cleanup;
}
ed = prog_getedict(prog, prog->globals[prog->cached_globals.self]);
case INSTR_GOTO:
st += st->o1.s1 - 1; /* offset the s++ */
if (++jumpcount == 10000000)
- qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename, jumpcount);
+ qcvmerror(prog, "`%s` hit the runaway loop counter limit of %li jumps", prog->filename.c_str(), jumpcount);
break;
case INSTR_AND: