diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-05-07 21:43:43 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-05-07 21:43:43 +0300 |
commit | 615b68377fcf7f7e70bfa0f31aea917fe1cf0903 (patch) | |
tree | b39a17a079580066bfc1f7eb67875f3eb7e77901 | |
parent | 2a963ce202911085c98dac7628150f4a56ee1295 (diff) | |
download | mailfromd-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.c | 19 | ||||
-rw-r--r-- | mfd/gram.y | 34 | ||||
-rw-r--r-- | mfd/prog.c | 62 |
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); } @@ -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: @@ -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; } |