aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-09-08 21:20:39 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2008-09-08 21:20:39 +0000
commit4cd3031ed36e207ce341c0854636c9047cd35d24 (patch)
tree6e9274a96c5fdb0984a6822e351eb7230d3319ef
parentda3381a039b1ab4878baa9e5fc9be39284a154f2 (diff)
downloadmailfromd-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--ChangeLog10
-rw-r--r--NEWS7
-rw-r--r--configure.ac2
-rw-r--r--src/bi_sieve.m40
-rw-r--r--src/bi_sprintf.m419
-rw-r--r--src/prog.c272
-rw-r--r--src/prog.h4
-rw-r--r--src/snarf.m470
8 files changed, 267 insertions, 117 deletions
diff --git a/ChangeLog b/ChangeLog
index 3602649b..5ab79460 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
diff --git a/NEWS b/NEWS
index 674dbae4..a212fcc2 100644
--- a/NEWS
+++ b/NEWS
@@ -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;
diff --git a/src/prog.c b/src/prog.c
index 26621102..9dc17daa 100644
--- a/src/prog.c
+++ b/src/prog.c
@@ -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 = &regtab[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 = &regtab[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 = &regtab[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)
diff --git a/src/prog.h b/src/prog.h
index c18ab87c..ef972826 100644
--- a/src/prog.h
+++ b/src/prog.h
@@ -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