diff options
Diffstat (limited to 'src/prog.c')
-rw-r--r-- | src/prog.c | 276 |
1 files changed, 191 insertions, 85 deletions
@@ -237,2 +237,6 @@ disable_prog_trace(const char *modlist) +/* Max. number of C locals to save in struct eval_environ for eventual fixups. + See comment to env_fixup_autos, below. */ +#define MAX_AUTO_PTR 128 + struct eval_environ { @@ -255,2 +259,6 @@ struct eval_environ { size_t temp_size; + + STKVAL *auto_ptr[MAX_AUTO_PTR]; /* Pointers to C automatic variables + referring to dataseg. */ + size_t numautos; /* Number of entries in auto_ptr. */ @@ -330,2 +338,40 @@ env_get_stream(eval_environ_t env) + +/* A call to expand_dataseg (see below) invalidates any C variables that + pointed to dataseg before the call. To avoid dereferencing invalid memory + pointers, the addresses of such C variables are stored in env->auto_ptr + using env_register_auto (it is done by get_string_arg). When + expand_dataseg is called, it calls env_fixup_autos and passes it the + offset of new dataseg from old one. env_fixup_autos adds this value to + every address in auto_ptr, thereby fixing them. + + The auto_ptr array is cleared (by calling env_unregister_autos) after + executing each instruction (see eval_environment). + */ +void +env_register_auto(eval_environ_t env, void *ptr) +{ + if (env->numautos == MAX_AUTO_PTR) + runtime_error(env, "INTERNAL ERROR at %s:%d, please report", + __FILE__, __LINE__); + env->auto_ptr[env->numautos++] = ptr; +} + +void +env_unregister_autos(eval_environ_t env) +{ + env->numautos = 0; +} + +void +env_fixup_autos(eval_environ_t env, ptrdiff_t offset) +{ + int i; + for (i = 0; i < env->numautos; i++) { + STKVAL *pptr = env->auto_ptr[i]; + *pptr += offset; + } +} + + #define STACK_EXPAND_BLOCK 64 @@ -336,2 +382,4 @@ expand_dataseg(eval_environ_t env, size_t count, const char *errtext) STKVAL *newds; + ptrdiff_t offset; + count = ((count + STACK_EXPAND_BLOCK - 1) / STACK_EXPAND_BLOCK) @@ -348,2 +396,3 @@ expand_dataseg(eval_environ_t env, size_t count, const char *errtext) + offset = (char*)newds - (char*)env->dataseg; env->dataseg = newds; @@ -355,2 +404,3 @@ expand_dataseg(eval_environ_t env, size_t count, const char *errtext) * sizeof newds[0]); + env_fixup_autos(env, offset); mu_error(_("Warning: stack segment expanded, new size=%lu"), @@ -464,6 +514,7 @@ get_immediate(eval_environ_t env, unsigned n) -const char * -get_literal(eval_environ_t env, unsigned n) +void +get_literal(eval_environ_t env, unsigned n, const char **p) { - return (char*)(env->dataseg + (size_t) get_immediate(env, n)); + *p = (char*)(env->dataseg + (size_t) get_immediate(env, n)); + env_register_auto(env, p); } @@ -476,12 +527,19 @@ get_arg(eval_environ_t env, unsigned n) -char * -get_string_arg(eval_environ_t env, unsigned n) +void +get_string_arg(eval_environ_t env, unsigned n, char **p) { - return (char*) (env->dataseg + (size_t) get_arg(env, n)); + *p = (char*) (env->dataseg + (size_t) get_arg(env, n)); + env_register_auto(env, p); } -size_t -get_numeric_arg(eval_environ_t env, unsigned n) +void +get_numeric_arg(eval_environ_t env, unsigned n, long *np) { - return (size_t) get_arg(env, n); + *np = (long) get_arg(env, n); +} + +void +get_pointer_arg(eval_environ_t env, unsigned n, void **p) +{ + *p = (void*) get_arg(env, n); } @@ -491,6 +549,5 @@ push(eval_environ_t env, STKVAL val) { - if (env->tos < env->toh) + if (env->tos < env->toh) runtime_error(env, "INTERNAL ERROR at %s:%d, please report", __FILE__, __LINE__); - if (env->tos == env->toh) { @@ -593,4 +650,4 @@ instr_locus(eval_environ_t env) { - env->locus.file = get_literal(env, 0); env->locus.line = (size_t) get_immediate(env, 1); + get_literal(env, 0, &env->locus.file); if (PROG_TRACE_ENGINE) @@ -689,2 +746,10 @@ instr_stkalloc(eval_environ_t env) prog_trace(env, "STKALLOC %p", n); + if (env->tos - n < env->toh) { + debug3(100, "tos=%lu, toh=%lu, delta=%u", + (unsigned long) env->tos, + (unsigned long) env->toh, + n); + expand_dataseg(env, env->toh - (env->tos - n), + _("Out of stack space; increase #pragma stacksize")); + } env->tos -= n; @@ -745,6 +810,9 @@ instr_ston(eval_environ_t env) { - char *s = get_string_arg(env, 0); + char *s; char *p; - long v = strtol(s, &p, 0); + long v; + get_string_arg(env, 0, &s); + v = strtol(s, &p, 0); + adjust_stack(env, 1); @@ -763,3 +831,3 @@ instr_ntos(eval_environ_t env) { - long v = (long) get_numeric_arg(env, 0); + long v = (long) get_arg(env, 0); char buf[NUMERIC_BUFSIZE_BOUND]; @@ -778,4 +846,4 @@ instr_cmp(eval_environ_t env) { - long l = (long) get_numeric_arg(env, 1); - long r = (long) get_numeric_arg(env, 0); + long l = (long) get_arg(env, 1); + long r = (long) get_arg(env, 0); adjust_stack(env, 2); @@ -789,4 +857,6 @@ instr_symbol(eval_environ_t env) { - char *symbol = (char *) get_literal(env, 0); - char *s = env->getsym(env->data, symbol); + char *symbol, *s; + + get_literal(env, 0, (const char **)&symbol); + s = env->getsym(env->data, symbol); @@ -817,4 +887,4 @@ instr_eqn(eval_environ_t env) { - long a = (long) get_numeric_arg(env, 1); - long b = (long) get_numeric_arg(env, 0); + long a = (long) get_arg(env, 1); + long b = (long) get_arg(env, 0); if (PROG_TRACE_ENGINE) @@ -828,4 +898,5 @@ instr_eqs(eval_environ_t env) { - char *a = get_string_arg(env, 1); - char *b = get_string_arg(env, 0); + char *a, *b; + get_string_arg(env, 1, &a); + get_string_arg(env, 0, &b); if (PROG_TRACE_ENGINE) @@ -839,4 +910,4 @@ instr_nen(eval_environ_t env) { - long a = (long) get_numeric_arg(env, 1); - long b = (long) get_numeric_arg(env, 0); + long a = (long) get_arg(env, 1); + long b = (long) get_arg(env, 0); if (PROG_TRACE_ENGINE) @@ -850,4 +921,6 @@ instr_nes(eval_environ_t env) { - char *a = get_string_arg(env, 1); - char *b = get_string_arg(env, 0); + char *a, *b; + + get_string_arg(env, 1, &a); + get_string_arg(env, 0, &b); if (PROG_TRACE_ENGINE) @@ -861,4 +934,4 @@ instr_ltn(eval_environ_t env) { - long a = (long) get_numeric_arg(env, 1); - long b = (long) get_numeric_arg(env, 0); + long a = (long) get_arg(env, 1); + long b = (long) get_arg(env, 0); if (PROG_TRACE_ENGINE) @@ -872,4 +945,6 @@ instr_lts(eval_environ_t env) { - char *a = get_string_arg(env, 1); - char *b = get_string_arg(env, 0); + char *a, *b; + + get_string_arg(env, 1, &a); + get_string_arg(env, 0, &b); if (PROG_TRACE_ENGINE) @@ -883,4 +958,4 @@ instr_len(eval_environ_t env) { - long a = (long) get_numeric_arg(env, 1); - long b = (long) get_numeric_arg(env, 0); + long a = (long) get_arg(env, 1); + long b = (long) get_arg(env, 0); if (PROG_TRACE_ENGINE) @@ -894,4 +969,6 @@ instr_les(eval_environ_t env) { - char *a = get_string_arg(env, 1); - char *b = get_string_arg(env, 0); + char *a, *b; + + get_string_arg(env, 1, &a); + get_string_arg(env, 0, &b); if (PROG_TRACE_ENGINE) @@ -905,4 +982,4 @@ instr_gtn(eval_environ_t env) { - long a = (long) get_numeric_arg(env, 1); - long b = (long) get_numeric_arg(env, 0); + long a = (long) get_arg(env, 1); + long b = (long) get_arg(env, 0); if (PROG_TRACE_ENGINE) @@ -916,4 +993,6 @@ instr_gts(eval_environ_t env) { - char *a = get_string_arg(env, 1); - char *b = get_string_arg(env, 0); + char *a, *b; + + get_string_arg(env, 1, &a); + get_string_arg(env, 0, &b); if (PROG_TRACE_ENGINE) @@ -927,4 +1006,4 @@ instr_gen(eval_environ_t env) { - long a = (long) get_numeric_arg(env, 1); - long b = (long) get_numeric_arg(env, 0); + long a = (long) get_arg(env, 1); + long b = (long) get_arg(env, 0); if (PROG_TRACE_ENGINE) @@ -938,4 +1017,6 @@ instr_ges(eval_environ_t env) { - char *a = get_string_arg(env, 1); - char *b = get_string_arg(env, 0); + char *a, *b; + + get_string_arg(env, 1, &a); + get_string_arg(env, 0, &b); if (PROG_TRACE_ENGINE) @@ -950,3 +1031,3 @@ instr_bz(eval_environ_t env) { - long v = (long) get_numeric_arg(env, 0); + long v = (long) get_arg(env, 0); long off = (long) get_immediate(env, 0); @@ -970,3 +1051,3 @@ instr_bnz(eval_environ_t env) { - long v = (long) get_numeric_arg(env, 0); + long v = (long) get_arg(env, 0); long off = (long) get_immediate(env, 0); @@ -994,3 +1075,3 @@ instr_not(eval_environ_t env) { - long v = (long) get_numeric_arg(env, 0); + long v = (long) get_arg(env, 0); if (PROG_TRACE_ENGINE) @@ -1005,4 +1086,4 @@ instr_logand(eval_environ_t env) { - unsigned long a = (unsigned long) get_numeric_arg(env, 1); - unsigned long b = (unsigned long) get_numeric_arg(env, 0); + unsigned long a = (unsigned long) get_arg(env, 1); + unsigned long b = (unsigned long) get_arg(env, 0); adjust_stack(env, 2); @@ -1016,4 +1097,4 @@ instr_logor(eval_environ_t env) { - unsigned long a = (unsigned long) get_numeric_arg(env, 1); - unsigned long b = (unsigned long) get_numeric_arg(env, 0); + unsigned long a = (unsigned long) get_arg(env, 1); + unsigned long b = (unsigned long) get_arg(env, 0); adjust_stack(env, 2); @@ -1027,4 +1108,4 @@ instr_logxor(eval_environ_t env) { - unsigned long a = (unsigned long) get_numeric_arg(env, 1); - unsigned long b = (unsigned long) get_numeric_arg(env, 0); + unsigned long a = (unsigned long) get_arg(env, 1); + unsigned long b = (unsigned long) get_arg(env, 0); adjust_stack(env, 2); @@ -1038,3 +1119,3 @@ instr_lognot(eval_environ_t env) { - unsigned long v = (unsigned long) get_numeric_arg(env, 0); + unsigned long v = (unsigned long) get_arg(env, 0); if (PROG_TRACE_ENGINE) @@ -1049,4 +1130,4 @@ instr_add(eval_environ_t env) { - long a = (long) get_numeric_arg(env, 1); - long b = (long) get_numeric_arg(env, 0); + long a = (long) get_arg(env, 1); + long b = (long) get_arg(env, 0); adjust_stack(env, 2); @@ -1060,4 +1141,4 @@ instr_sub(eval_environ_t env) { - long a = (long) get_numeric_arg(env, 1); - long b = (long) get_numeric_arg(env, 0); + long a = (long) get_arg(env, 1); + long b = (long) get_arg(env, 0); adjust_stack(env, 2); @@ -1071,4 +1152,4 @@ instr_mul(eval_environ_t env) { - long a = (long) get_numeric_arg(env, 1); - long b = (long) get_numeric_arg(env, 0); + long a = (long) get_arg(env, 1); + long b = (long) get_arg(env, 0); adjust_stack(env, 2); @@ -1082,4 +1163,4 @@ instr_div(eval_environ_t env) { - long a = (long) get_numeric_arg(env, 1); - long b = (long) get_numeric_arg(env, 0); + long a = (long) get_arg(env, 1); + long b = (long) get_arg(env, 0); adjust_stack(env, 2); @@ -1096,3 +1177,3 @@ instr_neg(eval_environ_t env) { - long v = (long) get_numeric_arg(env, 0); + long v = (long) get_arg(env, 0); if (PROG_TRACE_ENGINE) @@ -1137,5 +1218,7 @@ instr_regmatch(eval_environ_t env) int v; - size_t index = (size_t)get_numeric_arg(env, 0); + size_t index = (size_t)get_arg(env, 0); regex_t *re = ®tab[index].re; - char *string = get_string_arg(env, 1); + char *string; + + get_string_arg(env, 1, &string); adjust_stack(env, 2); @@ -1169,5 +1252,7 @@ instr_regcomp(eval_environ_t env) size_t expr_off = (size_t)get_arg(env, 0); - char *expr = get_string_arg(env, 0); + char *expr; size_t index = (size_t) get_immediate(env, 0); struct rt_regex *rtx = ®tab[index]; + + get_string_arg(env, 0, &expr); @@ -1213,4 +1298,6 @@ instr_fnmatch(eval_environ_t env) { - char *string = get_string_arg(env, 1); - char *pattern = get_string_arg(env, 0); + char *string, *pattern; + + get_string_arg(env, 1, &string); + get_string_arg(env, 0, &pattern); adjust_stack(env, 2); @@ -1260,4 +1347,6 @@ instr_fnmatch_mx(eval_environ_t env) { - char *string = get_string_arg(env, 1); - char *pattern = get_string_arg(env, 0); + char *string, *pattern; + + get_string_arg(env, 1, &string); + get_string_arg(env, 0, &pattern); adjust_stack(env, 2); @@ -1279,5 +1368,7 @@ instr_regmatch_mx(eval_environ_t env) int rc; - size_t index = (size_t)get_numeric_arg(env, 0); + size_t index = (size_t)get_arg(env, 0); regex_t *re = ®tab[index].re; - char *string = get_string_arg(env, 1); + char *string; + + get_string_arg(env, 1, &string); adjust_stack(env, 2); @@ -1309,5 +1400,8 @@ instr_result(eval_environ_t env) sfsistat status = (sfsistat) get_immediate(env, 0); - char *code = (char *) get_literal(env, 1); - char *xcode = (char *) get_literal(env, 2); - char *message = get_string_arg(env, 0); + char *code, *xcode; + char *message; + + get_string_arg(env, 0, &message); + get_literal(env, 1, (const char**)&code); + get_literal(env, 2, (const char**)&xcode); @@ -1352,7 +1446,9 @@ instr_header(eval_environ_t env) struct old_header_node *hdr = xmalloc (sizeof(*hdr)); + char *value; hdr->opcode = (enum header_opcode) get_immediate(env, 0); - hdr->name = get_literal(env, 1); - hdr->value = strdup(get_string_arg(env, 0)); - + get_literal(env, 1, &hdr->name); + get_string_arg(env, 0, &value); + hdr->value = strdup(value); + advance_pc(env, 2); @@ -1384,5 +1480,6 @@ instr_builtin(eval_environ_t env) { - const char *name = get_literal(env, 0); + const char *name; void (*handler)(eval_environ_t) = get_immediate(env, 1); + get_literal(env, 0, &name); if (PROG_TRACE_ENGINE) @@ -1402,6 +1499,10 @@ instr_concat(eval_environ_t env) { - char *left = get_string_arg(env, 1); - char *right = get_string_arg(env, 0); - size_t off = heap_reserve(env, strlen(left) + strlen(right) + 1); - char *res = (char*) env_data_ref(env, off); + char *left, *right; + size_t off; + char *res; + + get_string_arg(env, 1, &left); + get_string_arg(env, 0, &right); + off = heap_reserve(env, strlen(left) + strlen(right) + 1); + res = (char*) env_data_ref(env, off); @@ -1424,3 +1525,3 @@ instr_asgn(eval_environ_t env) STKVAL val = get_arg(env, 1); - size_t dest = get_numeric_arg(env, 0); + size_t dest = (size_t) get_arg(env, 0); adjust_stack(env, 2); @@ -1578,4 +1679,5 @@ instr_funcall(eval_environ_t env) { - const char *name = get_literal(env, 0); + const char *name; prog_counter_t pc = (prog_counter_t) get_immediate(env, 1); + get_literal(env, 0, &name); advance_pc(env, 2); @@ -1762,2 +1864,4 @@ env_init(eval_environ_t env) + env->numautos = 0; + /* Initialize catch functions */ @@ -1808,4 +1912,6 @@ eval_environment(eval_environ_t env, prog_counter_t start) break; - if (setjmp(env->catch_jmp) == 0) + if (setjmp(env->catch_jmp) == 0) { (*(prog[env->pc]))(env); + env_unregister_autos(env); + } } |