aboutsummaryrefslogtreecommitdiff
path: root/mfd/prog.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-09-16 12:10:02 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2008-09-16 12:10:02 +0000
commit99c453be5795d76e10b0a9cf1a2558367e538a1c (patch)
tree7810d5bed75fe0e6e24a647d754c187a714e9819 /mfd/prog.c
parentd6f4adec375f9f50186248462f2774d9dc6ae59e (diff)
downloadmailfromd-99c453be5795d76e10b0a9cf1a2558367e538a1c.tar.gz
mailfromd-99c453be5795d76e10b0a9cf1a2558367e538a1c.tar.bz2
Implement functions with variable number of arguments and 'run' mode.
* mfd/symtab.c (function_install): Take additional argument. * mfd/lex.l: New tokens `vaptr', `...' and ARGX. * mfd/snarf.m4 (MF_VASTRING): New define. * mfd/gram.y: Handle functions with variable number of arguments, $(expr), and vaptr() expressions. This raises shift/reduce expectation to 29 conflicts. (parmtype_function): Return dtype_string for arguments from vararg list. (FUNC_HIDDEN_ARGS): Return 1 if f->varargs is set. (type_to_string): Handle pointer argument. (function_call): Handle function->varargs. (node_type): Handle node_type_argx, and node_type_vaptr. (cast_arg_list): Handle variable number of arguments. (cast_to): Handle dtype_pointer as dtype_number. * mfd/drivers.c (argx, vaptr): New node types. (code_type_call): Handle variable number of arguments. (code_cast): Handle dtype_pointer as dtype_number. * mfd/mailfromd.h (MAILFROMD_RUN): New define. (struct argx_node): New type. (struct node): Add argx_node. (struct function): New member `varargs'. (function_install): Add varargs. (mailfromd_run): New prototype. * mfd/prog.c (env_vaptr, env_get_reg): New functions. (env_make_frame0): New function. (instr_xmemstk): New instruction handler. * mfd/opcodes (XMEMSTK): New opcode. * mfd/prog.h (env_get_reg, env_vaptr): New protos. * mfd/main.c (options): New option `--run'. (main): Handle `run' mode. * mfd/Makefile.am (M4_FILES): Add bi_getopt.m4. * NEWS: Update. git-svn-id: file:///svnroot/mailfromd/trunk@1669 7a8a7f39-df28-0410-adc6-e0d955640f24
Diffstat (limited to 'mfd/prog.c')
-rw-r--r--mfd/prog.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/mfd/prog.c b/mfd/prog.c
index 6624f415..8420a918 100644
--- a/mfd/prog.c
+++ b/mfd/prog.c
@@ -241,7 +241,7 @@ struct eval_environ {
prog_counter_t pc; /* Program counter */
prog_counter_t tos; /* Top of stack:
- toh <= tos <= datasize + stack_size */
+ toh <= tos < datasize + stack_size */
prog_counter_t toh; /* Top of heap:
datasize <= toh <= tos */
@@ -316,6 +316,12 @@ env_base(eval_environ_t env, size_t frame)
return base;
}
+char *
+env_vaptr(eval_environ_t env, size_t off)
+{
+ return env->dataseg + (size_t) env->dataseg[off];
+}
+
void
env_var_inc(eval_environ_t env, size_t off)
{
@@ -334,14 +340,20 @@ env_get_stream(eval_environ_t env)
return env->stream;
}
+STKVAL
+env_get_reg(eval_environ_t env)
+{
+ return env->reg;
+}
+
/* A call to expand_dataseg (see below) invalidates any C variables that
pointed to the dataseg before the call. To avoid dereferencing invalid
memory pointers, 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.
+ offset of the new dataseg from the 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).
@@ -724,6 +736,20 @@ dump_memstk(prog_counter_t i)
}
void
+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);
+ push(env, (STKVAL) val);
+}
+
+void
instr_deref(eval_environ_t env)
{
size_t off = (size_t) get_arg(env, 0);
@@ -1865,6 +1891,14 @@ env_init(eval_environ_t env)
}
void
+env_make_frame0(eval_environ_t env)
+{
+ push(env, (STKVAL) 0);
+ push(env, (STKVAL) (env->base - env->tos));
+ env->base = env->tos;
+}
+
+void
env_make_frame(eval_environ_t env)
{
push(env, (STKVAL) (env->pc + 1));

Return to:

Send suggestions and report system problems to the System administrator.