diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-09-08 21:20:39 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-09-08 21:20:39 +0000 |
commit | 4cd3031ed36e207ce341c0854636c9047cd35d24 (patch) | |
tree | 6e9274a96c5fdb0984a6822e351eb7230d3319ef | |
parent | da3381a039b1ab4878baa9e5fc9be39284a154f2 (diff) | |
download | mailfromd-release_4_4_patches.tar.gz mailfromd-release_4_4_patches.tar.bz2 |
* src/snarf.m4, src/bi_sprintf.m4, src/prog.h, src/bi_sieve.m4,release_4_4_patches
Ported r1655 from trunk.
* src/prog.c: Ported r1655 and r1660 from trunk.
* NEWS: Update, set version number 4.4.1.
* configure.ac: set version number 4.4.1.
git-svn-id: file:///svnroot/mailfromd/branches/release_4_4_patches@1661 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/bi_sieve.m4 | 0 | ||||
-rw-r--r-- | src/bi_sprintf.m4 | 19 | ||||
-rw-r--r-- | src/prog.c | 272 | ||||
-rw-r--r-- | src/prog.h | 4 | ||||
-rw-r--r-- | src/snarf.m4 | 70 |
8 files changed, 267 insertions, 117 deletions
@@ -1,6 +1,16 @@ +2008-09-08 Sergey Poznyakoff <gray@gnu.org.ua> + + * src/snarf.m4, src/bi_sprintf.m4, src/prog.h, src/bi_sieve.m4, + Ported r1655 from trunk. + + * src/prog.c: Ported r1655 and r1660 from trunk. + + * NEWS: Update, set version number 4.4.1. + * configure.ac: set version number 4.4.1. + 2008-03-10 Sergey Poznyakoff <gray@gnu.org.ua> * doc/mailfromd.texi: Spell check. Add missing acknowledgments. 2008-03-10 Sergey Poznyakoff <gray@gnu.org.ua> @@ -1,13 +1,18 @@ -Mailfromd NEWS -- history of user-visible changes. 2008-03-10 +Mailfromd NEWS -- history of user-visible changes. 2008-09-09 Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff See the end of file for copying conditions. Please send mailfromd bug reports to <bug-mailfromd@gnu.org.ua> +Version 4.4.1 + +* Fix stack reallocation. + + Version 4.4, 2008-03-10 * The --domain option is withdrawn. This option was declared as deprecated in version 4.0. Now it is withdrawn and its short version (-D) is reused for another purpose diff --git a/configure.ac b/configure.ac index 5a146171..5a6e224c 100644 --- a/configure.ac +++ b/configure.ac @@ -14,13 +14,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. AC_PREREQ(2.59) m4_define([MF_VERSION_MAJOR], 4) m4_define([MF_VERSION_MINOR], 4) -dnl m4_define([MF_VERSION_PATCH], 0) +m4_define([MF_VERSION_PATCH], 1) AC_INIT([mailfromd], MF_VERSION_MAJOR.MF_VERSION_MINOR[]m4_ifdef([MF_VERSION_PATCH],.MF_VERSION_PATCH), [bug-mailfromd@gnu.org.ua]) AC_CONFIG_SRCDIR([src/main.c]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) diff --git a/src/bi_sieve.m4 b/src/bi_sieve.m4 index 04ae8f95..0c5af274 100644 --- a/src/bi_sieve.m4 +++ b/src/bi_sieve.m4 diff --git a/src/bi_sprintf.m4 b/src/bi_sprintf.m4 index afd63d32..051d2dc4 100644 --- a/src/bi_sprintf.m4 +++ b/src/bi_sprintf.m4 @@ -147,24 +147,23 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) case fmts_width_arg: /* Expect width argument position -- %2$#*_1$ */ state = fmts_prec; if (isdigit(*p)) { char *q = get_num(p, &n); if (*q == '$') { - num = (unsigned) MF_VA_ARG(n-1, - NUMBER); + MF_VA_ARG(n-1, NUMBER, num); p = q + 1; if (num < 0) { flags |= FMT_SPACEPFX; num = - num; } width = (unsigned) num; break; } } - num = MF_VA_ARG(i, NUMBER); + MF_VA_ARG(i, NUMBER, num); i++; if (num < 0) { /* A negative field width is taken as a `-' flag followed by a positive field width. */ flags |= FMT_SPACEPFX; num = - num; @@ -190,31 +189,31 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) /* Expect precision argument position -- %2$#*1$.*_3$ */ state = fmts_conv; if (isdigit(*p)) { char *q = get_num(p, &n); if (*q == '$') { - num = MF_VA_ARG(n-1, NUMBER); + MF_VA_ARG(n-1, NUMBER, num); if (num > 0) prec = (unsigned) num; p = q + 1; break; } } - num = MF_VA_ARG(i, NUMBER); + MF_VA_ARG(i, NUMBER, num); i++; if (num > 0) prec = (unsigned) num; break; case fmts_conv: /* Expect conversion specifier */ if (!(flags & FMT_ALTPOS)) argnum = i++; switch (*p) { case 's': - str = MF_VA_ARG(argnum,STRING); + MF_VA_ARG(argnum, STRING, str); n = strlen(str); if (prec && prec < n) n = prec; if (width) { char *q, *s; if (n > width) @@ -232,13 +231,13 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) } MF_OBSTACK_GROW(str, n); break; case 'i': case 'd': - num = MF_VA_ARG(argnum,NUMBER); + MF_VA_ARG(argnum, NUMBER, num); if (num < 0) { negative = 1; num = - num; } else negative = 0; /* If a precision is given with a @@ -287,13 +286,13 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) } } else MF_OBSTACK_GROW(str, n); break; case 'u': - num = MF_VA_ARG(argnum,NUMBER); + MF_VA_ARG(argnum, NUMBER, num); /* If a precision is given with a numeric conversion, the 0 flag is ignored. */ /* A - overrides a 0 if both are given.*/ if (prec || (flags & FMT_ADJUST_LEFT)) flags &= ~FMT_PADZERO; @@ -320,13 +319,13 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) } else MF_OBSTACK_GROW(str, n); break; case 'x': case 'X': - num = MF_VA_ARG(argnum,NUMBER); + MF_VA_ARG(argnum, NUMBER, num); /* If a precision is given with a numeric conversion, the 0 flag is ignored. */ /* A - overrides a 0 if both are given.*/ if (prec || (flags & FMT_ADJUST_LEFT)) flags &= ~FMT_PADZERO; @@ -366,13 +365,13 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) } } else MF_OBSTACK_GROW(str, n); break; case 'o': - num = MF_VA_ARG(argnum,NUMBER); + MF_VA_ARG(argnum, NUMBER, num); /* If a precision is given with a numeric conversion, the 0 flag is ignored. */ /* A - overrides a 0 if both are given.*/ if (prec || (flags & FMT_ADJUST_LEFT)) flags &= ~FMT_PADZERO; @@ -232,12 +232,16 @@ disable_prog_trace(const char *modlist) Jacek Kaczmarski. "Upadek Ikara" ======================================================================== */ /* Run-time evaluation */ +/* 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 { prog_counter_t pc; /* Program counter */ prog_counter_t tos; /* Top of stack: toh <= tos <= datasize + stack_size */ prog_counter_t toh; /* Top of heap: @@ -251,12 +255,16 @@ struct eval_environ { struct locus locus; /* Program locus corresponding to PC */ /* Temporary heap space */ size_t temp_start; 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. */ + /* Sendmail interaction data: */ SMFICTX *ctx; /* Milter Context */ void *data; /* MTA symbol table */ /* methods to access the latter */ char *(*getsym)(void *data, char *str); int (*setreply)(void *data, char *code, char *xcode, char *message); @@ -325,37 +333,79 @@ env_get_locus(eval_environ_t env) mu_stream_t env_get_stream(eval_environ_t env) { return env->stream; } + +/* 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 static int 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) * STACK_EXPAND_BLOCK; newds = realloc(env->dataseg, (env->stack_size + datasize + count) * sizeof env->dataseg[0]); if (!newds) { if (errtext) runtime_error(env, errtext); else return 1; } + offset = (char*)newds - (char*)env->dataseg; env->dataseg = newds; env->stack_size += count; env->tos += count; env->base += count; memmove(newds + env->tos, newds + env->tos - count, (datasize + env->stack_size - env->tos) * sizeof newds[0]); + env_fixup_autos(env, offset); mu_error(_("Warning: stack segment expanded, new size=%lu"), (unsigned long) env->stack_size); return 0; } @@ -459,43 +509,50 @@ runtime_error(eval_environ_t env, const char *fmt, ...) void * get_immediate(eval_environ_t env, unsigned n) { return prog[env->pc + n + 1]; } -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); } STKVAL get_arg(eval_environ_t env, unsigned n) { return env->dataseg[env->tos + n + 1]; } -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); } void push(eval_environ_t env, STKVAL val) { if (env->tos < env->toh) runtime_error(env, "INTERNAL ERROR at %s:%d, please report", __FILE__, __LINE__); - if (env->tos == env->toh) { debug2(100, "tos=%lu, toh=%lu", (unsigned long) env->tos, (unsigned long) env->toh); expand_dataseg(env, 1, _("Out of stack space; increase #pragma stacksize")); @@ -588,14 +645,14 @@ pushs(eval_environ_t env, char *s) /* Auxiliary instructions */ void 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) prog_trace(env, "LOCUS"); advance_pc(env, 2); } void @@ -684,12 +741,20 @@ instr_deref(eval_environ_t env) void instr_stkalloc(eval_environ_t env) { unsigned n = (unsigned) get_immediate(env, 0); if (PROG_TRACE_ENGINE) 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; advance_pc(env, 1); } void dump_stkalloc(prog_counter_t i) @@ -740,15 +805,18 @@ dump_backref(prog_counter_t i) } /* Type conversion instructions */ void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "STON %s", s); if (*p) env_throw(env, mfe_ston_conv, @@ -758,13 +826,13 @@ instr_ston(eval_environ_t env) push(env, (STKVAL) v); } void 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]; adjust_stack(env, 1); if (PROG_TRACE_ENGINE) prog_trace(env, "NTOS %ld", v); @@ -773,25 +841,27 @@ instr_ntos(eval_environ_t env) } /* Evaluation instructions */ void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "CMP %ld %ld", l, r); push(env, (STKVAL) (l == r)); } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "SYMBOL %s", symbol); if (!s) env_throw(env, mfe_macroundef, _("Macro not defined: %s"), symbol); @@ -812,146 +882,157 @@ dump_symbol(prog_counter_t i) } /* Comparation instructions */ void 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) prog_trace(env, "EQN %ld %ld", a, b); adjust_stack(env, 2); push(env, (STKVAL) (a == b)); } void 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) prog_trace(env, "EQS %s %s", a, b); adjust_stack(env, 2); push(env, (STKVAL) (strcmp(a, b) == 0)); } void 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) prog_trace(env, "NEN %ld %ld", a, b); adjust_stack(env, 2); push(env, (STKVAL) (a != b)); } void 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) prog_trace(env, "NES %s %s", a, b); adjust_stack(env, 2); push(env, (STKVAL) strcmp(a, b)); } void 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) prog_trace(env, "LTN %ld %ld", a, b); adjust_stack(env, 2); push(env, (STKVAL) (a < b)); } void 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) prog_trace(env, "LTS %s %s", a, b); adjust_stack(env, 2); push(env, (STKVAL) (strcmp(a, b) < 0)); } void 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) prog_trace(env, "LEN %ld %ld", a, b); adjust_stack(env, 2); push(env, (STKVAL) (a <= b)); } void 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) prog_trace(env, "LES %s %s", a, b); adjust_stack(env, 2); push(env, (STKVAL) (strcmp(a, b) <= 0)); } void 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) prog_trace(env, "GTN %ld %ld", a, b); adjust_stack(env, 2); push(env, (STKVAL) (a > b)); } void 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) prog_trace(env, "GTS %s %s", a, b); adjust_stack(env, 2); push(env, (STKVAL) (strcmp(a, b) > 0)); } void 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) prog_trace(env, "GEN %ld %ld", a, b); adjust_stack(env, 2); push(env, (STKVAL) (a >= b)); } void 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) prog_trace(env, "GES %s %s", a, b); adjust_stack(env, 2); push(env, (STKVAL) (strcmp(a, b) >= 0)); } /* Jump instructions */ void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "BZ %ld (%ld)", off, v); adjust_stack(env, 1); if (v == 0) @@ -965,13 +1046,13 @@ dump_branch (prog_counter_t i) printf("%ld (%ld)", (long) prog[i], i + (long) prog[i] + 1); } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "BNZ %ld (%ld)", off, v); adjust_stack(env, 1); if (v != 0) @@ -989,115 +1070,115 @@ instr_jmp(eval_environ_t env) } /* Boolean instructions */ void 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) prog_trace(env, "NOT %ld", v); adjust_stack(env, 1); push(env, (STKVAL) !v); } /* Bitwise arithmetics */ void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "LOGAND %lu %lu", a, b); push(env, (STKVAL) (a & b)); } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "LOGOR %lu %lu", a, b); push(env, (STKVAL) (a | b)); } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "LOGXOR %lu %lu", a, b); push(env, (STKVAL) (a ^ b)); } void 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) prog_trace(env, "LOGNOT %ld", v); adjust_stack(env, 1); push(env, (STKVAL) ~v); } /* Arithmetic instructions */ void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "ADD %ld %ld", a, b); push(env, (STKVAL) (a + b)); } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "SUB %ld %ld", a, b); push(env, (STKVAL) (a - b)); } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "MUL %ld %ld", a, b); push(env, (STKVAL) (a * b)); } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "DIV %ld %ld", a, b); if (b == 0) env_throw(env, mfe_divzero, "Division by zero at %08lx", (unsigned long)env->pc); push(env, (STKVAL) (a / b)); } void 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) prog_trace(env, "NEG %ld", v); adjust_stack(env, 1); push(env, (STKVAL) -v); } @@ -1132,15 +1213,17 @@ dump_regex(prog_counter_t i) } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "REGMATCH %s %s", env_data_ref(env, regtab[index].expr), string); @@ -1164,16 +1247,18 @@ instr_regmatch(eval_environ_t env) void instr_regcomp(eval_environ_t env) { int v; char buffer[REGEX_STRING_BUFSIZE]; 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); + advance_pc(env, 1); adjust_stack(env, 1); if (PROG_TRACE_ENGINE) prog_trace(env, "REGCOMP %s %s", regex_flags_to_string(rtx->regflags, @@ -1208,14 +1293,16 @@ dump_regcomp(prog_counter_t i) buffer, sizeof buffer)); } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "FNMATCH %s %s", string, pattern); push(env, (STKVAL) (fnmatch (pattern, string, 0) == 0)); } @@ -1255,14 +1342,16 @@ fn_matcher(const char *string, void *data) return fnmatch (data, string, 0) == 0; } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "FNMATCH,MX %s %s", string, pattern); push(env, (STKVAL) mx_match(env, string, fn_matcher, pattern)); } @@ -1274,15 +1363,17 @@ regex_matcher(const char *string, void *data) } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "REGMATCH,MX %s %s", regtab[index].expr, string); @@ -1304,15 +1395,18 @@ instr_next(eval_environ_t env) } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "RESULT %d %s %s %s", status, SP(code), SP(xcode), @@ -1347,16 +1441,18 @@ dump_result(prog_counter_t i) } void 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); adjust_stack(env, 1); if (PROG_TRACE_ENGINE) prog_trace(env, "HEADER %d %s %s", @@ -1379,15 +1475,16 @@ dump_header(prog_counter_t i) (char*)(dataseg + (size_t)prog[i+1])); } void 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) prog_trace(env, "BUILTIN %s", name); advance_pc(env, 2); handler(env); } @@ -1397,16 +1494,20 @@ dump_builtin(prog_counter_t i) printf("%s ", (char*)(dataseg + (size_t) prog[i])); } void 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); 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) off); @@ -1419,13 +1520,13 @@ dump_adjust(prog_counter_t i) } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "ASGN %lu=%lu", (unsigned long) dest, (unsigned long) val); env->dataseg[dest] = val; @@ -1573,14 +1674,15 @@ instr_pushreg(eval_environ_t env) push(env, env->reg); } void 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); if (PROG_TRACE_ENGINE) prog_trace(env, "FUNCALL %s (%lu)", name, (unsigned long)pc); env_make_frame(env); env->pc = pc-1; } @@ -1757,12 +1859,14 @@ env_init(eval_environ_t env) env->matches = NULL; env->matchsize = 0; env->matchcount = 0; env->string = NULL; + env->numautos = 0; + /* Initialize catch functions */ memcpy (env->catch, env->defcatch, sizeof env->catch); env_final_gc(env); } @@ -1803,14 +1907,16 @@ eval_environment(eval_environ_t env, prog_counter_t start) for (env->pc = start; ; env->pc++) { if (env->pc >= pc) runtime_error(env, _("pc out of range")); if (!prog[env->pc]) break; - if (setjmp(env->catch_jmp) == 0) + if (setjmp(env->catch_jmp) == 0) { (*(prog[env->pc]))(env); + env_unregister_autos(env); + } } return 0; } static void env_vsprintf_error(const char *fmt, va_list ap) @@ -28,14 +28,14 @@ struct eval_environ; #define B2STACK(s) (s + sizeof(STKVAL) - 1) / sizeof(STKVAL) void runtime_warning(eval_environ_t env, const char *fmt, ...); void runtime_error(eval_environ_t env, const char *fmt, ...) ATTRIBUTE_NORETURN; STKVAL get_arg(eval_environ_t env, unsigned n); -char *get_string_arg(eval_environ_t env, unsigned n); -size_t get_numeric_arg(eval_environ_t env, unsigned n); +void get_string_arg(eval_environ_t env, unsigned n, char **ptr); +void get_numeric_arg(eval_environ_t env, unsigned n, long *np); void push(eval_environ_t env, STKVAL val); STKVAL pop(eval_environ_t env); 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); diff --git a/src/snarf.m4 b/src/snarf.m4 index 6d419326..7ceb4af1 100644 --- a/src/snarf.m4 +++ b/src/snarf.m4 @@ -76,55 +76,85 @@ m4_define([<__mf_c_type>],m4_dnl * TYPE */ m4_define([<__mf_c_getarg>],m4_dnl [<m4_ifelse($1,STRING,get_string_arg,$1,NUMBER,get_numeric_arg, ERROR )>]) /* mf_c_argdcl(TYPE NAME) -- translate Mailfromd declaration "TYPE NAME" - * into the corresponding C one, followed by an equals sign, a typecast, - * and the name of corresponding ge |