aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-05-07 21:43:43 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2009-05-07 21:43:43 +0300
commit615b68377fcf7f7e70bfa0f31aea917fe1cf0903 (patch)
treeb39a17a079580066bfc1f7eb67875f3eb7e77901
parent2a963ce202911085c98dac7628150f4a56ee1295 (diff)
downloadmailfromd-615b68377fcf7f7e70bfa0f31aea917fe1cf0903.tar.gz
mailfromd-615b68377fcf7f7e70bfa0f31aea917fe1cf0903.tar.bz2
Fix exception handling code (saveex/restex).
* mfd/drivers.c (code_type_funcdecl): Exmask handling and jump fixups are handled within codegen. (code_type_progdecl): Update call to codegen. * mfd/gram.y (codegen): Take an extra argument specifying the exception mask to handle. Unless it is zero, code saveex/restex pair around the main code. This makes sure local allocations do not disturb exception handling code. Also, take care of jump fixup here. (mailfromd_test): Fix bug in numeric argument passing. * mfd/prog.c (instr_saveex): Provide additional debugging diagnostics (temporary). (dump_saveex): Fix retrieving of the exmask (seftover from earlier version). (instr_memstk, instr_xmemstk, instr_deref) (instr_ston, instr_ntos, instr_cmp) (instr_logand, instr_logor, instr_logxor) (instr_add, instr_sub, instr_mul) (instr_div, instr_regex, instr_regcomp) (instr_funcall): Make sure PC and stack adjustments occur after outputting trace info.
-rw-r--r--mfd/drivers.c19
-rw-r--r--mfd/gram.y34
-rw-r--r--mfd/prog.c62
3 files changed, 68 insertions, 47 deletions
diff --git a/mfd/drivers.c b/mfd/drivers.c
index bb6d9e09..d8dfb4b2 100644
--- a/mfd/drivers.c
+++ b/mfd/drivers.c
@@ -2310,21 +2310,8 @@ code_type_funcdecl(NODE *node, struct locus **old_locus)
handle recursive functions */
func->entry = code_get_counter();
- /* Entry code */
- if (func->exmask) {
- code_op(opcode_saveex);
- code_immediate((void*)func->exmask);
- }
-
- if (codegen(&pc, node->v.funcdecl.tree, 0,
- node->v.funcdecl.auto_count) == 0) {
- jump_fixup(jump_pc, code_get_counter());
-
- /* Exit code */
- if (func->exmask)
- code_op(opcode_restex);
- code_op(opcode_return);
- }
+ codegen(&pc, node->v.funcdecl.tree, func->exmask, 0,
+ node->v.funcdecl.auto_count);
}
@@ -2359,7 +2346,7 @@ code_type_progdecl(NODE *node, struct locus **old_locus)
root_node[tag] = node->v.progdecl.tree;
if (codegen(&entry_point[tag],
- node->v.progdecl.tree, 1,
+ node->v.progdecl.tree, 0, 1,
node->v.progdecl.auto_count) == 0)
milter_enable_state(tag);
}
diff --git a/mfd/gram.y b/mfd/gram.y
index 15a7f069..332a748a 100644
--- a/mfd/gram.y
+++ b/mfd/gram.y
@@ -33,8 +33,8 @@
static NODE *alloc_node(enum node_type type, const struct locus *locus);
static void free_node(NODE *node);
static void set_poll_arg(struct poll_data *poll, int kw, NODE *expr);
-static int codegen(prog_counter_t *pc, NODE *node, int finalize,
- size_t nautos);
+static int codegen(prog_counter_t *pc, NODE *node, unsigned exmask,
+ int finalize, size_t nautos);
static void mark(NODE *node);
static void dataseg_layout(void);
static void regex_layout(void);
@@ -2615,20 +2615,34 @@ mark(NODE *node)
static int
-codegen(prog_counter_t *pc, NODE *node, int finalize, size_t nautos)
+codegen(prog_counter_t *pc, NODE *node, unsigned exmask,
+ int finalize, size_t nautos)
{
- if (error_count == 0) {
+ if (error_count)
+ return 1;
+
*pc = code_get_counter();
jump_pc = 0;
if (nautos) {
code_op(opcode_stkalloc);
code_immediate((void*)nautos);
}
+ if (exmask) {
+ code_op(opcode_saveex);
+ code_immediate((void*) exmask);
+ }
traverse_tree(node);
+
+ jump_fixup(jump_pc, code_get_counter());
+ if (exmask)
+ code_op(opcode_restex);
+
if (finalize)
code_op(opcode_nil);
- }
- return error_count;
+ else
+ code_op(opcode_return);
+
+ return 0;
}
static void
@@ -3134,9 +3148,13 @@ mailfromd_test(int argc, char **argv)
env_push_string(env, args[i] ? args[i] : "");
break;
case dtype_number:
- n = strtol(p, &end, 0);
+ if (args[i]) {
+ n = strtol(args[i], &end, 0);
if (*end)
- mu_error(_("$%d is not a number"), i+1);
+ mu_error(_("$%d is not a number"),
+ i+1);
+ } else
+ n = 0;
env_push_number(env, n);
break;
default:
diff --git a/mfd/prog.c b/mfd/prog.c
index 1ec1217a..5ab7b110 100644
--- a/mfd/prog.c
+++ b/mfd/prog.c
@@ -754,11 +754,12 @@ instr_memstk(eval_environ_t env)
size_t frame = (size_t) get_immediate(env, 0);
long off = (long) get_immediate(env, 1);
size_t val = env_base(env, frame) + off;
- advance_pc(env, 2);
+
if (PROG_TRACE_ENGINE)
prog_trace(env, "MEMSTK %lu(%ld)=%lu",
(unsigned long) frame, off,
(unsigned long) val);
+ advance_pc(env, 2);
push(env, (STKVAL) val);
}
@@ -774,11 +775,12 @@ instr_xmemstk(eval_environ_t env)
size_t frame = (size_t) get_arg(env, 1);
long off = (long) get_arg(env, 0);
size_t val = env_base(env, frame) + off;
- adjust_stack(env, 2);
+
if (PROG_TRACE_ENGINE)
prog_trace(env, "XMEMSTK %lu(%ld)=%lu",
(unsigned long) frame, off,
(unsigned long) val);
+ adjust_stack(env, 2);
push(env, (STKVAL) val);
}
@@ -787,11 +789,12 @@ instr_deref(eval_environ_t env)
{
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 %lu=%lu (%p)",
(unsigned long) off,
(unsigned long) val, val);
+ adjust_stack(env, 1);
push(env, val);
}
@@ -872,9 +875,9 @@ instr_ston(eval_environ_t env)
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);
+ adjust_stack(env, 1);
if (*p)
env_throw(env, mfe_ston_conv,
"Cannot convert stack value to number (stopped at %8.8s)",
@@ -889,9 +892,9 @@ instr_ntos(eval_environ_t env)
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);
+ adjust_stack(env, 1);
snprintf(buf, sizeof buf, "%ld", v);
pushs(env, buf);
@@ -903,9 +906,10 @@ instr_cmp(eval_environ_t env)
{
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);
+ adjust_stack(env, 2);
push(env, (STKVAL) (l == r));
}
@@ -1144,9 +1148,9 @@ instr_logand(eval_environ_t env)
{
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);
+ adjust_stack(env, 2);
push(env, (STKVAL) (a & b));
}
@@ -1155,9 +1159,9 @@ instr_logor(eval_environ_t env)
{
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);
+ adjust_stack(env, 2);
push(env, (STKVAL) (a | b));
}
@@ -1166,9 +1170,9 @@ instr_logxor(eval_environ_t env)
{
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);
+ adjust_stack(env, 2);
push(env, (STKVAL) (a ^ b));
}
@@ -1188,9 +1192,9 @@ instr_add(eval_environ_t env)
{
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);
+ adjust_stack(env, 2);
push(env, (STKVAL) (a + b));
}
@@ -1199,9 +1203,9 @@ instr_sub(eval_environ_t env)
{
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);
+ adjust_stack(env, 2);
push(env, (STKVAL) (a - b));
}
@@ -1210,9 +1214,9 @@ instr_mul(eval_environ_t env)
{
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);
+ adjust_stack(env, 2);
push(env, (STKVAL) (a * b));
}
@@ -1221,9 +1225,9 @@ instr_div(eval_environ_t env)
{
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);
+ adjust_stack(env, 2);
if (b == 0)
env_throw(env, mfe_divzero,
"Division by zero at %08x", (unsigned int) env->pc);
@@ -1249,13 +1253,14 @@ instr_regex(eval_environ_t env)
{
char buffer[REGEX_STRING_BUFSIZE];
size_t index = (size_t) get_immediate(env, 0);
- advance_pc(env, 1);
+
if (PROG_TRACE_ENGINE)
prog_trace(env, "REGEX (%s) %s",
regex_flags_to_string(regtab[index].regflags,
buffer,
sizeof buffer),
(char*) env_data_ref(env, regtab[index].expr));
+ advance_pc(env, 1);
push(env, (STKVAL) index);
}
@@ -1314,14 +1319,15 @@ instr_regcomp(eval_environ_t env)
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,
buffer, sizeof buffer),
expr);
+
+ advance_pc(env, 1);
+ adjust_stack(env, 1);
+
if (rtx->compiled) {
regfree(&rtx->re);
rtx->compiled = 0;
@@ -1671,14 +1677,20 @@ instr_saveex(eval_environ_t env)
{
unsigned exmask = (unsigned) get_immediate(env, 0);
int i;
- advance_pc(env, 1);
+
if (PROG_TRACE_ENGINE)
prog_trace(env, "SAVEEX %x", exmask);
- push(env, (STKVAL) exmask);
+
+ advance_pc(env, 1);
for (i = 0; i < mf_exception_count; i++)
- if (EXMASK(i) & exmask)
+ if (EXMASK(i) & exmask) {
+ debug3(101, "Push Exception: %d %lu <- %lu",
+ i, (unsigned long) env->tos,
+ (unsigned long) env->catch[i]);
push(env, (STKVAL) env->catch[i]);
}
+ push(env, (STKVAL) exmask);
+}
void
dump_saveex(prog_counter_t i)
@@ -1689,14 +1701,18 @@ dump_saveex(prog_counter_t i)
void
instr_restex(eval_environ_t env)
{
- unsigned exmask = (unsigned)env->dataseg[env->base];
+ unsigned exmask = (unsigned) pop(env);
int i;
if (PROG_TRACE_ENGINE)
prog_trace(env, "RESTEX %x", exmask);
for (i = mf_exception_count-1; i >= 0; i--)
- if (EXMASK(i) & exmask)
+ if (EXMASK(i) & exmask) {
env->catch[i] = (prog_counter_t) pop(env);
+ debug3(102, "Pop Exception: %d %lu -> %lu",
+ i, (unsigned long) env->tos,
+ (unsigned long) env->catch[i]);
+ }
}
void
@@ -1731,9 +1747,9 @@ instr_funcall(eval_environ_t env)
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);
+ advance_pc(env, 2);
env_make_frame(env);
env->pc = pc-1;
}

Return to:

Send suggestions and report system problems to the System administrator.