diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-03-31 20:31:40 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-03-31 20:31:40 +0000 |
commit | 86be9fa5494be9417f90f16f87eca6ab2a28631d (patch) | |
tree | a3bd15dc99defd2413d1a0af10e946c6b6d0c01b | |
parent | 5633a8204a428a28582225810f215b23445037d5 (diff) | |
download | mailfromd-86be9fa5494be9417f90f16f87eca6ab2a28631d.tar.gz mailfromd-86be9fa5494be9417f90f16f87eca6ab2a28631d.tar.bz2 |
Switch to flat address space model. Data space (and stack) contain
only references to objects within the data space (virtual
addresses), no actual pointers are passed.
* src/snarf.m4 (MF_ALLOC_HEAP, MF_COPY_STRING): Take two arguments
(MF_BEGIN_TEMP_SPACE): Use env_data_ref
(MF_VAR_SET_STRING): New macro
* src/bi_poll.m4, src/bi_string.m4, src/bi_dns.m4, src/bi_spf.m4,
src/bi_sa.m4, src/bi_vars.m4, src/bi_db.m4: Use new heap
allocation macros.
* src/drivers.c (code_memref, code_type_string): Use opcode_push
(code_type_variable): Remove opcode_svalidate. This time for good
* src/mailfromd.h (env_throw_0): Change signature
* src/prog.c (struct eval_environ.stack): Remove. Use plain
addressing model. All references updated.
(env_reference,env_var_ref): Remove
(heap_reserve_words, heap_reserve): Return offset into the data
space instead of the pointer. All uses updated.
(env_data_ref): New function
* src/opcodes (MEMEXT,MEM,SVALIDATE): Remove
* src/prog.h (env_data_ref): New function
(heap_reserve_words): New function
(heap_reserve): Return size_t
* TODO: Update
git-svn-id: file:///svnroot/mailfromd/trunk@1331 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | src/bi_db.m4 | 5 | ||||
-rw-r--r-- | src/bi_dns.m4 | 7 | ||||
-rw-r--r-- | src/bi_poll.m4 | 13 | ||||
-rw-r--r-- | src/bi_sa.m4 | 4 | ||||
-rw-r--r-- | src/bi_spf.m4 | 6 | ||||
-rw-r--r-- | src/bi_string.m4 | 30 | ||||
-rw-r--r-- | src/bi_vars.m4 | 2 | ||||
-rw-r--r-- | src/drivers.c | 6 | ||||
-rw-r--r-- | src/mailfromd.h | 2 | ||||
-rw-r--r-- | src/opcodes | 3 | ||||
-rw-r--r-- | src/prog.c | 256 | ||||
-rw-r--r-- | src/prog.h | 5 | ||||
-rw-r--r-- | src/snarf.m4 | 23 |
14 files changed, 155 insertions, 209 deletions
@@ -8,6 +8,8 @@ Mailfromd TODO list. * Various items by Jan (ref <Pine.LNX.4.58.0610112345080.2162@cedric.unob.cz>) +* gsub(regex, repl, string) + ** Implement still more string functions * If an optional numeric argument to a built-in function has value 0 it is diff --git a/src/bi_db.m4 b/src/bi_db.m4 index 816ecc58..fecc0eb8 100644 --- a/src/bi_db.m4 +++ b/src/bi_db.m4 @@ -53,11 +53,12 @@ dbmap_lookup(eval_environ_t env, char *dbname, const char *keystr, else push(env, 0); } else if (((char*)MU_DATUM_PTR(contents))[MU_DATUM_SIZE(contents)-1]) { + size_t off; size_t len = MU_DATUM_SIZE(contents); - char *s = MF_ALLOC_HEAP(len + 1); + char *s = MF_ALLOC_HEAP(off, len + 1); memcpy(s, MU_DATUM_PTR(contents), len); s[len] = 0; - push(env, (STKVAL) s); + push(env, (STKVAL) off); } else pushs(env, MU_DATUM_PTR(contents)); } diff --git a/src/bi_dns.m4 b/src/bi_dns.m4 index 021f2d08..a7d8b214 100644 --- a/src/bi_dns.m4 +++ b/src/bi_dns.m4 @@ -189,7 +189,7 @@ END MF_DEFUN(domainpart, STRING, STRING str) { char *p = strchr(str, '@'); - MF_RETURN(p ? p+1 : str); + MF_RETURN_STRING(p ? p+1 : str); } END @@ -198,11 +198,12 @@ MF_DEFUN(localpart, STRING, STRING str) char *p = strchr(str, '@'); if (p) { + size_t off; size_t size = p - str; - char *string_space = MF_ALLOC_HEAP(size + 1); + char *string_space = MF_ALLOC_HEAP(off, size + 1); memcpy(string_space, str, size); string_space[size] = 0; - MF_RETURN(string_space); + MF_RETURN(off); } else MF_RETURN_STRING(str); } diff --git a/src/bi_poll.m4 b/src/bi_poll.m4 index c61605ab..d9f1eeeb 100644 --- a/src/bi_poll.m4 +++ b/src/bi_poll.m4 @@ -26,14 +26,11 @@ set_last_poll_result(eval_environ_t env, const char *host_addr, const char *send, const char *recv) { - char *s; - - s = host_addr ? MF_COPY_STRING(host_addr) : NULL; - MF_VAR_REF(last_poll_host, s); - s = send ? MF_COPY_STRING(send) : NULL; - MF_VAR_REF(last_poll_send, s); - s = recv ? MF_COPY_STRING(recv) : NULL; - MF_VAR_REF(last_poll_recv, s); + size_t s; + + MF_VAR_SET_STRING(last_poll_host, host_addr); + MF_VAR_SET_STRING(last_poll_send, send); + MF_VAR_SET_STRING(last_poll_recv, recv); } void diff --git a/src/bi_sa.m4 b/src/bi_sa.m4 index bd66b79d..c3734fe4 100644 --- a/src/bi_sa.m4 +++ b/src/bi_sa.m4 @@ -403,7 +403,7 @@ MF_DEFUN(sa, NUMBER, STRING urlstr, NUMBER prec) MF_VAR_REF(sa_score, score); MF_VAR_REF(sa_threshold, threshold); - MF_VAR_REF(sa_keywords, MF_COPY_STRING(buffer)); + MF_VAR_SET_STRING(sa_keywords, buffer); while (spamd_read_line(ostr, buffer, sizeof buffer, &size) == 0 && size > 0) @@ -485,7 +485,7 @@ MF_DEFUN(clamav, NUMBER, STRING urlstr) s = buffer; else s++; - MF_VAR_REF(clamav_virus_name, MF_COPY_STRING(s)); + MF_VAR_SET_STRING(clamav_virus_name, s); debug2(2, "%sclamav found %s", diff --git a/src/bi_spf.m4 b/src/bi_spf.m4 index ad4b7407..a09a7bce 100644 --- a/src/bi_spf.m4 +++ b/src/bi_spf.m4 @@ -26,10 +26,8 @@ MF_VAR(spf_explanation_prefix, STRING); static void update_spf_vars(eval_environ_t env, spf_answer_t *ans) { - char *s = ans->exp_text ? MF_COPY_STRING(ans->exp_text) : NULL; - MF_VAR_REF(spf_explanation, s); - s = ans->mech ? MF_COPY_STRING(ans->mech) : NULL; - MF_VAR_REF(spf_mechanism, s); + MF_VAR_SET_STRING(spf_explanation, ans->exp_text); + MF_VAR_SET_STRING(spf_mechanism, ans->mech); MF_VAR_REF(spf_ttl, ans->ttl); } diff --git a/src/bi_string.m4 b/src/bi_string.m4 index 874b783f..2326aead 100644 --- a/src/bi_string.m4 +++ b/src/bi_string.m4 @@ -18,21 +18,23 @@ MF_DEFUN(toupper, STRING, STRING string) { - char *s = MF_COPY_STRING(string); + size_t off; + char *s = MF_COPY_STRING(off, string); char *p; for (p = s; *p; p++) *p = toupper(*p); - MF_RETURN(s); + MF_RETURN(off); } END MF_DEFUN(tolower, STRING, STRING string) { - char *s = MF_COPY_STRING(string); + size_t off; + char *s = MF_COPY_STRING(off, string); char *p; for (p = s; *p; p++) *p = tolower(*p); - MF_RETURN(s); + MF_RETURN(off); } END @@ -44,6 +46,7 @@ END MF_DEFUN(substring, STRING, STRING string, NUMBER start, NUMBER end) { + size_t off; long len = strlen(string); char *s; @@ -59,16 +62,17 @@ MF_DEFUN(substring, STRING, STRING string, NUMBER start, NUMBER end) "argument out of range"); len = end - start + 1; - s = MF_ALLOC_HEAP(len + 1); + s = MF_ALLOC_HEAP(off, len + 1); memcpy(s, string + start, len); s[len] = 0; - MF_RETURN(s); + MF_RETURN(off); } END MF_DEFUN(substr, STRING, STRING string, NUMBER start, OPTIONAL, NUMBER nbytes) { + size_t off; long len = strlen(string); char *s; @@ -76,11 +80,11 @@ MF_DEFUN(substr, STRING, STRING string, NUMBER start, OPTIONAL, NUMBER nbytes) if (nbytes == 0) nbytes = len - start; - s = MF_ALLOC_HEAP(nbytes + 1); + s = MF_ALLOC_HEAP(off, nbytes + 1); memcpy(s, string + start, nbytes); s[nbytes] = 0; - MF_RETURN(s); + MF_RETURN(off); } END @@ -127,12 +131,13 @@ MF_DEFUN(revstr, STRING, STRING str) { int len = strlen(str); char *p; - char *s = MF_ALLOC_HEAP(len + 1); + size_t off; + char *s = MF_ALLOC_HEAP(off, len + 1); s[len] = 0; for (p = s + len - 1; p >= s; p--, str++) *p = *str; - MF_RETURN(s); + MF_RETURN(off); } END @@ -167,9 +172,10 @@ END MF_DEFUN(unfold, STRING, STRING text) { - char *s = MF_COPY_STRING(text); + size_t off; + char *s = MF_COPY_STRING(off, text); mu_string_unfold(s, NULL); - pushs(env, s); + MF_RETURN(off); } END diff --git a/src/bi_vars.m4 b/src/bi_vars.m4 index 156daf91..aca795b4 100644 --- a/src/bi_vars.m4 +++ b/src/bi_vars.m4 @@ -24,7 +24,7 @@ MF_VAR(mailfrom_address, STRING); unsigned long get_rcpt_count(eval_environ_t env) { - return (long) MF_VAR_REF(rcpt_count); + return (long) MF_VAR_REF(rcpt_count); } void diff --git a/src/drivers.c b/src/drivers.c index e66cf5b8..2e9c7c01 100644 --- a/src/drivers.c +++ b/src/drivers.c @@ -32,7 +32,7 @@ code_memref(NODE *node) { switch (node->v.var_ref.variable->storage_class) { case storage_extern: - code_op(opcode_memext); + code_op(opcode_push); code_immediate((void*)node->v.var_ref.variable->off); break; @@ -76,7 +76,7 @@ void code_type_string(NODE *node, struct locus **old_locus) { MARK_LOCUS(); - code_op(opcode_memext); + code_op(opcode_push); code_immediate((const void*)node->v.literal->off); } @@ -1148,8 +1148,6 @@ code_type_variable(NODE *node, struct locus **old_locus) MARK_LOCUS(); code_memref(node); code_op(opcode_deref); - if (node->v.var_ref.variable->type == dtype_string) - code_op(opcode_svalidate); } diff --git a/src/mailfromd.h b/src/mailfromd.h index 390c9f37..a292a743 100644 --- a/src/mailfromd.h +++ b/src/mailfromd.h @@ -759,7 +759,7 @@ void env_init(eval_environ_t env); void env_throw(eval_environ_t env, mf_status status, const char *fmt, ...) ATTRIBUTE_NORETURN; void env_throw_0(eval_environ_t env, mf_status status, - const char *text) ATTRIBUTE_NORETURN; + size_t text_off) ATTRIBUTE_NORETURN; void env_push_string(eval_environ_t env, char *arg); void env_push_number(eval_environ_t env, long arg); diff --git a/src/opcodes b/src/opcodes index cd0aaf2a..69637006 100644 --- a/src/opcodes +++ b/src/opcodes @@ -76,12 +76,9 @@ LOGNOT NULL 0 CONCAT NULL 0 MEMSTK dump_memstk 2 -MEMEXT dump_memext 1 -MEM NULL 0 DEREF NULL 0 ASGN NULL 0 BUILTIN dump_builtin 2 -SVALIDATE NULL 0 CATCH dump_catch 3 THROW dump_throw 1 @@ -230,9 +230,9 @@ disable_prog_trace(const char *modlist) struct eval_environ { prog_counter_t pc; /* Program counter */ - STKVAL *stack; /* Stack space */ - prog_counter_t tos; /* Top of stack: 0 <= tos <= toh */ - prog_counter_t toh; /* Top of heap: tos <= toh <= stack_size */ + prog_counter_t tos; /* Top of stack: datasize <= tos <= toh */ + prog_counter_t toh; /* Top of heap: + tos <= toh <= datasize + stack_size */ prog_counter_t base; /* Base pointer */ STKVAL reg; /* General purpose register */ STKVAL *dataseg; /* Data space */ @@ -285,34 +285,14 @@ env_base(eval_environ_t env, size_t frame) { size_t base = env->base; for (; frame; frame--) - base = (size_t) env->stack[base-1]; + base = (size_t) env->dataseg[base-1]; return base; } -STKVAL * -env_reference(eval_environ_t env, storage_class_t sc, size_t n, size_t frame) -{ - switch (sc) { - case storage_extern: - return &env->dataseg[n]; - case storage_auto: - return &env->stack[env_base(env, frame) + n]; - case storage_param: - return &env->stack[env_base(env, frame) - 2 - n]; - } - abort(); -} - -STKVAL * -env_var_ref(eval_environ_t env, size_t off) -{ - return env_reference(env, storage_extern, off, 0); -} - void env_var_inc(eval_environ_t env, size_t off) { - ++*env_var_ref(env, off); + ++*env_data_ref(env, off); } const struct locus * @@ -390,19 +370,19 @@ get_literal(eval_environ_t env, unsigned n) STKVAL get_arg(eval_environ_t env, unsigned n) { - return env->stack[env->tos - n - 1]; + return env->dataseg[env->tos - n - 1]; } char * get_string_arg(eval_environ_t env, unsigned n) { - return (char*) get_arg(env, n); + return (char*) (env->dataseg + (size_t) get_arg(env, n)); } size_t get_numeric_arg(eval_environ_t env, unsigned n) { - return get_arg(env, n); + return (size_t) get_arg(env, n); } void @@ -415,7 +395,7 @@ push(eval_environ_t env, STKVAL val) runtime_error(env, "Out of stack space; increase #pragma stacksize"); } - env->stack[env->tos++] = val; + env->dataseg[env->tos++] = val; } STKVAL @@ -423,14 +403,12 @@ pop(eval_environ_t env) { if (env->tos == 0) runtime_error(env, "Stack underflow"); - return env->stack[--env->tos]; + return env->dataseg[--env->tos]; } -STKVAL -heap_reserve(eval_environ_t env, size_t size) +size_t +heap_reserve_words(eval_environ_t env, size_t words) { - size_t words = B2STACK(size); - if (env->toh - words <= env->tos) { /* Heap overrun: */ /* gc(); */ @@ -439,7 +417,13 @@ heap_reserve(eval_environ_t env, size_t size) "Heap overrun; increase #pragma stacksize"); } env->toh -= words; - return env->stack + env->toh--; + return env->toh--; +} + +size_t +heap_reserve(eval_environ_t env, size_t size) +{ + return heap_reserve_words(env, B2STACK(size)); } STKVAL @@ -454,15 +438,15 @@ heap_tempspace(eval_environ_t env, size_t size) runtime_error(env, "Heap overrun; increase #pragma stacksize"); } - return env->stack + env->toh - words; + return env->dataseg + env->toh - words; } STKVAL heap_max_tempspace(eval_environ_t env, size_t *size) { - *size = (env->toh - env->tos - 1) * sizeof env->stack[0]; - return env->stack + env->tos + 1; + *size = (env->toh - env->tos - 1) * sizeof env->dataseg[0]; + return env->dataseg + env->tos + 1; } STKVAL @@ -475,14 +459,22 @@ heap_fix_tempspace(eval_environ_t env, size_t size) "INTERNAL ERROR: memory chunk too big " "to fit into heap"); env->toh -= words; - memmove(env->stack + env->toh, env->stack + env->tos + 1, size); - return env->stack + env->toh--; + memmove(env->dataseg + env->toh, env->dataseg + env->tos + 1, size); + return env->dataseg + env->toh--; +} + +STKVAL * +env_data_ref(eval_environ_t env, size_t off) +{ + return env->dataseg + off; } void pushs(eval_environ_t env, char *s) { - push(env, (STKVAL) strcpy(heap_reserve(env, strlen(s) + 1), s)); + size_t off = heap_reserve(env, strlen(s) + 1); + strcpy((char*) env_data_ref(env, off), s); + push(env, (STKVAL) off); } /* Auxiliary instructions */ @@ -509,9 +501,9 @@ void instr_xchg(eval_environ_t env) { prog_counter_t p = env->tos - 1; - STKVAL tmp = env->stack[p]; - env->stack[p] = env->stack[p - 1]; - env->stack[p - 1] = tmp; + STKVAL tmp = env->dataseg[p]; + env->dataseg[p] = env->dataseg[p - 1]; + env->dataseg[p - 1] = tmp; if (PROG_TRACE_ENGINE) prog_trace(env, "XCHG"); } @@ -552,13 +544,13 @@ instr_memstk(eval_environ_t env) { size_t frame = (size_t) get_immediate(env, 0); long off = (long) get_immediate(env, 1); - STKVAL val = (STKVAL) &env->stack[env_base(env, frame) + off]; + size_t val = env_base(env, frame) + off; advance_pc(env, 2); if (PROG_TRACE_ENGINE) - prog_trace(env, "MEMSTK %lu(%ld)=%08x", + prog_trace(env, "MEMSTK %lu(%ld)=%lu", (unsigned long) frame, off, - val); - push(env, val); + (unsigned long) val); + push(env, (STKVAL) val); } void @@ -568,70 +560,16 @@ dump_memstk(prog_counter_t i) } void -instr_memext(eval_environ_t env) -{ - size_t off = (size_t) get_immediate(env, 0); - STKVAL val = (STKVAL) &env->dataseg[off]; - advance_pc(env, 1); - if (PROG_TRACE_ENGINE) - prog_trace(env, "MEMEXT %08x=%08x", - (unsigned long) off, - val); - push(env, val); -} - -void -dump_memext(prog_counter_t i) -{ - printf("%08x", (unsigned long) prog[i]); -} - -void -instr_mem(eval_environ_t env) -{ - size_t frame = (size_t) get_numeric_arg(env, 2); - size_t off = (size_t) get_numeric_arg(env, 1); - storage_class_t class = (storage_class_t) get_numeric_arg(env, 0); - adjust_stack(env, 3); - - if (PROG_TRACE_ENGINE) - prog_trace(env, "LOC %s %lu(%lu)", - storage_class_str(class), - (unsigned long) frame, - (unsigned long) off); - push(env, (STKVAL) env_reference(env, class, off, frame)); -} - -void instr_deref(eval_environ_t env) { - STKVAL *p = (STKVAL*) get_arg(env, 0); + size_t off = (size_t) get_arg(env, 0); + STKVAL val = env->dataseg[off]; adjust_stack(env, 1); if (PROG_TRACE_ENGINE) - prog_trace(env, "DEREF %p=%p", p, *p); - push(env, *p); -} - - -void -instr_push_literal(eval_environ_t env) -{ - size_t s = (size_t) get_immediate(env, 0); - char *p = (char*) (env->dataseg + s); - if (PROG_TRACE_ENGINE) - prog_trace(env, "PUSH_LITERAL %08lx %s", - (unsigned long) s, p); - push(env, p); - advance_pc(env, 1); -} - -void -dump_push_literal(prog_counter_t i) -{ - size_t s = (size_t) prog[i]; - char *p = (char*) (dataseg + s); - - printf("%08lx %s", (unsigned long) s, p); + prog_trace(env, "DEREF %lu=%lu (%p)", + (unsigned long) off, + (unsigned long) val, val); + push(env, val); } void @@ -654,7 +592,6 @@ void instr_backref(eval_environ_t env) { unsigned n = (unsigned) get_immediate(env, 0); - char *s; size_t matchlen; if (PROG_TRACE_ENGINE) @@ -673,13 +610,17 @@ instr_backref(eval_environ_t env) } if (env->matches[n].rm_so == -1) { - push(env, env->dataseg); + push(env, 0); } else { + char *s; + size_t off; + matchlen = env->matches[n].rm_eo - env->matches[n].rm_so; - s = heap_reserve(env, matchlen + 1); + off = heap_reserve(env, matchlen + 1); + s = (char*) env_data_ref(env, off); memcpy(s, env->string + env->matches[n].rm_so, matchlen); s[matchlen] = 0; - push(env, (STKVAL) s); + push(env, (STKVAL) off); } } @@ -693,10 +634,11 @@ dump_backref(prog_counter_t i) void instr_ston(eval_environ_t env) { - char *s = pop(env); + char *s = get_string_arg(env, 0); char *p; long v = strtol(s, &p, 0); + adjust_stack(env, 1); if (PROG_TRACE_ENGINE) prog_trace(env, "STON %s", s); if (*p) @@ -713,9 +655,9 @@ instr_ntos(eval_environ_t env) long v = (long) get_numeric_arg(env, 0); char buf[NUMERIC_BUFSIZE_BOUND]; + adjust_stack(env, 1); if (PROG_TRACE_ENGINE) prog_trace(env, "NTOS %ld", v); - adjust_stack(env, 1); snprintf(buf, sizeof buf, "%ld", v); pushs(env, buf); @@ -738,6 +680,7 @@ instr_symbol(eval_environ_t env) { char *symbol = (char *) get_literal(env, 0); char *s = env->getsym(env->data, symbol); + if (PROG_TRACE_ENGINE) prog_trace(env, "SYMBOL %s", symbol); if (!s) { @@ -751,8 +694,9 @@ instr_symbol(eval_environ_t env) if (PROG_TRACE_ENGINE) prog_trace(env, "%s dereferenced to %s", symbol, s); - pushs(env, (STKVAL) s); advance_pc(env, 1); + + pushs(env, s); } void @@ -1067,8 +1011,7 @@ instr_regex(eval_environ_t env) regex_flags_to_string(regtab[index].regflags, buffer, sizeof buffer), - env_reference(env, storage_extern, - regtab[index].expr, 0)); + (char*) env_data_ref(env, regtab[index].expr)); push(env, (STKVAL) index); } @@ -1350,13 +1293,14 @@ instr_concat(eval_environ_t env) { char *left = get_string_arg(env, 1); char *right = get_string_arg(env, 0); - char *res = heap_reserve(env, strlen(left) + strlen(right) + 1); + size_t off = heap_reserve(env, strlen(left) + strlen(right) + 1); + char *res = (char*) env_data_ref(env, off); strcat(strcpy(res, left), right); adjust_stack(env, 2); if (PROG_TRACE_ENGINE) prog_trace(env, "CONCAT ('%s','%s')='%s'", left, right, res); - push(env, (STKVAL) res); + push(env, (STKVAL) off); } void @@ -1369,26 +1313,16 @@ void instr_asgn(eval_environ_t env) { STKVAL val = get_arg(env, 1); - STKVAL *dest = (STKVAL*)get_arg(env, 0); + size_t dest = get_numeric_arg(env, 0); adjust_stack(env, 2); if (PROG_TRACE_ENGINE) - prog_trace(env, "ASGN %p=%p", - dest, - val); - *dest = val; + prog_trace(env, "ASGN %lu=%lu", + (unsigned long) dest, + (unsigned long) val); + env->dataseg[dest] = val; } void -instr_svalidate(eval_environ_t env) -{ - STKVAL val = get_arg(env, 0); - if (PROG_TRACE_ENGINE) - prog_trace(env, "SVALIDATE %p", val); - if (val == 0) - env->stack[env->tos - 1] = env->dataseg; -} - -void instr_catch(eval_environ_t env) { long off = (long) get_immediate(env, 0); @@ -1427,12 +1361,12 @@ void instr_throw(eval_environ_t env) { unsigned long n = (unsigned long) get_immediate(env, 0); - char *str = get_string_arg(env, 0); + size_t off = (size_t) get_arg(env, 0); advance_pc(env, 1); adjust_stack(env, 1); if (n > mf_status_count) runtime_error(env, "Invalid exception number: %lu", n); - env_throw_0(env, (mf_status) n, str); + env_throw_0(env, (mf_status) n, off); } void @@ -1492,12 +1426,12 @@ dump_saveex(prog_counter_t i) void instr_restex(eval_environ_t env) { - unsigned exmask = (unsigned)env->stack[env->base]; + unsigned exmask = (unsigned)env->dataseg[env->base]; int i; for (i = 0; i < mf_status_count; i++) { if (EXMASK(i) & exmask) env->catch[i] = (prog_counter_t) - env->stack[env->base+i+1]; + env->dataseg[env->base+i+1]; } } @@ -1584,7 +1518,7 @@ instr_xlats(eval_environ_t env) unsigned long count = (unsigned long) get_immediate(env, 0); size_t off = (size_t) get_immediate(env, 1); STKVAL *tab = (STKVAL *) (env->dataseg + off); - char *str = (char*) env->reg; + char *str = (char*) env_data_ref(env, (size_t) env->reg); if (PROG_TRACE_ENGINE) prog_trace(env, "XLATS %lu %lu", count, (unsigned long) off); @@ -1707,7 +1641,7 @@ env_init(eval_environ_t env) /* Initialize status and registers */ env->status = SMFIS_CONTINUE; - env->tos = 0; + env->tos = datasize; env->base = 0; env->reg = 0; @@ -1798,20 +1732,21 @@ eval_environment(eval_environ_t env, prog_counter_t start) return 0; } -char * +size_t env_vsprintf(eval_environ_t env, const char *fmt, va_list ap) { size_t size, n; char *p; char *s = heap_max_tempspace(env, &size); + size_t off; n = vsnprintf(s, size, fmt, ap); - p = heap_reserve(env, n+1); + p = (char*) env_data_ref(env, off = heap_reserve(env, n + 1)); memmove(p, s, n + 1); - return p; + return off; } void -env_throw_0(eval_environ_t env, mf_status status, const char *str) +env_throw_0(eval_environ_t env, mf_status status, size_t off) { prog_counter_t pc = env->catch[status]; if (pc) { @@ -1824,23 +1759,23 @@ env_throw_0(eval_environ_t env, mf_status status, const char *str) /* Fixup the program counter */ env->pc = pc - 1; /* Generate normal entry frame */ - push(env, (STKVAL) str); /* Pass the pointer */ + push(env, (STKVAL) off); env_push_number(env, status); env_make_frame(env); longjmp(env->catch_jmp, 1); } - runtime_error(env, "%s", str); + runtime_error(env, "%s", (char*) env_data_ref(env, off)); } void env_throw(eval_environ_t env, mf_status status, const char *fmt, ...) { va_list ap; - char *str; + size_t off; va_start(ap, fmt); - str = env_vsprintf(env, fmt, ap); + off = env_vsprintf(env, fmt, ap); va_end(ap); - env_throw_0(env, status, str); + env_throw_0(env, status, off); } sfsistat @@ -2083,8 +2018,6 @@ init_dataseg(STKVAL *dseg) { size_t i; memcpy(dseg, dataseg, datasize * sizeof dataseg[0]); - for (i = 0; i < dataseg_reloc_count; i++) - dseg[dataseg_reloc[i]] = dseg + (size_t)dseg[dataseg_reloc[i]]; } eval_environ_t @@ -2102,13 +2035,12 @@ create_environment(SMFICTX *ctx, exit(1); } - env->dataseg = calloc(stack_size + datasize, sizeof env->stack[0]); + env->dataseg = calloc(stack_size + datasize, sizeof env->dataseg[0]); if (!env->dataseg) { mu_error("Not enough memory"); exit(1); } - env->stack = env->dataseg + datasize; init_dataseg(env->dataseg); env->ctx = ctx; @@ -2122,7 +2054,7 @@ create_environment(SMFICTX *ctx, in env_init. The top of heap should be retained across calls to handlers, since we store string variables there. This raises stack size requirements. */ - env->toh = stack_size - 1; + env->toh = datasize + stack_size - 1; env->bi_priv_array = NULL; @@ -2290,28 +2222,30 @@ void env_final_gc(eval_environ_t env) { size_t i; - char *top = (char*)(env->stack + env->toh); - char *bot = (char*)(env->stack + stack_size); + size_t top = env->toh; + size_t bot = datasize + stack_size; genv = env; /* Prepare s_off/s_count: remove any variables that are not in heap */ s_off = xcalloc(dataseg_reloc_count, sizeof s_off[0]); for (i = 0, s_cnt = 0; i < dataseg_reloc_count; i++) { - char *p = (char*) env->dataseg[dataseg_reloc[i]]; + size_t p = (size_t) env->dataseg[dataseg_reloc[i]]; if (top < p && p < bot) s_off[s_cnt++] = dataseg_reloc[i]; } qsort(s_off, s_cnt, sizeof s_off[0], s_off_cmp); /* Compact the variables */ - env->toh = stack_size - 1; + env->toh = datasize + stack_size - 1; for (i = 0; i < s_cnt; i++) { size_t off = s_off[i]; - char *p = (char*) env->dataseg[off]; + char *p = (char*) env_data_ref(env, + (size_t) env->dataseg[off]); size_t len = strlen(p) + 1; - char *q = (char*)(env->dataseg[off] = heap_reserve(env, len)); - memmove(q, p, len); + size_t q = heap_reserve(env, len); + memmove(env_data_ref(env, q), p, len); + env->dataseg[off] = (STKVAL) q; } free(s_off); } @@ -37,7 +37,9 @@ char *get_string_arg(eval_environ_t env, unsigned n); size_t get_numeric_arg(eval_environ_t env, unsigned n); void push(eval_environ_t env, STKVAL val); STKVAL pop(eval_environ_t env); -STKVAL heap_reserve(eval_environ_t env, size_t size); +STKVAL *env_data_ref(eval_environ_t env, size_t off); +size_t heap_reserve(eval_environ_t env, size_t size); +size_t heap_reserve_words(eval_environ_t env, size_t size); STKVAL heap_tempspace(eval_environ_t env, size_t size); STKVAL heap_max_tempspace(eval_environ_t env, size_t *size); STKVAL heap_fix_tempspace(eval_environ_t env, size_t size); @@ -45,7 +47,6 @@ void pushs(eval_environ_t env, char *s); void advance_pc(eval_environ_t env, unsigned cnt); void adjust_stack(eval_environ_t env, unsigned cnt); void prog_trace(eval_environ_t env, const char *fmt, ...); -STKVAL *env_var_ref(eval_environ_t env, size_t off); void env_var_inc(eval_environ_t env, size_t off); char *env_dict_getsym(eval_environ_t env, char *string); char *env_dict_install(eval_environ_t env, char *key, char *value); diff --git a/src/snarf.m4 b/src/snarf.m4 index 7d58163c..064e4e7c 100644 --- a/src/snarf.m4 +++ b/src/snarf.m4 @@ -237,19 +237,20 @@ pushs(env, $1); return; } while (0)>]) -dnl MF_ALLOC_HEAP(len) - Allocate LEN bytes from the heap +dnl MF_ALLOC_HEAP(off, len) - Allocate LEN bytes from the heap dnl -define([<MF_ALLOC_HEAP>],[<heap_reserve(env, $1)>]) +define([<MF_ALLOC_HEAP>],[<dnl +(char*) env_data_ref(env, ([<$1>] = heap_reserve(env, $2)))>]) dnl MF_ALLOC_HEAP_TEMP(len) - Temporarly allocate LEN bytes from the heap. dnl define([<MF_ALLOC_HEAP_TEMP>],[<heap_tempspace(env, $1)>]) -dnl MF_COPY_STRING(string) - Copy STRING to the heap. Return the pointer to -dnl the copy. +dnl MF_COPY_STRING(off, string) - Copy STRING to the heap. Return the +dnl pointer to the copy. dnl define([<MF_COPY_STRING>],[<dnl -strcpy(heap_reserve(env, strlen($1) + 1), $1)>]) +strcpy((char*)env_data_ref(env, $1 = heap_reserve(env, strlen($2) + 1)), $2)>]) dnl MF_BEGIN_TEMP_SPACE(ptr,size) - Begin temporary space manipulations dnl On return PTR will point to the temporary heap space capable of holding @@ -288,7 +289,17 @@ dnl In one-argument form, return its value. In two-arguments form, assign dnl the VALUE to it. dnl define([<MF_VAR_REF>],[<dnl -*env_var_ref(env, $1_loc) ifelse($2,,,= (STKVAL) ($2))>]) +*env_data_ref(env, $1_loc) ifelse($2,,,= (STKVAL) ($2))>]) + +dnl MF_VAR_SET_STRING(name, value) - Set variable NAME to the string VALUE +define([<MF_VAR_SET_STRING>],[< +{ size_t off; + if ($2) + MF_COPY_STRING(off, $2); + else + off = 0; + MF_VAR_REF($1, off); } +>]) dnl MF_VAR_INC(name) - Increment the value of the global variable NAME dnl |