diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-09-16 12:10:02 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-09-16 12:10:02 +0000 |
commit | 99c453be5795d76e10b0a9cf1a2558367e538a1c (patch) | |
tree | 7810d5bed75fe0e6e24a647d754c187a714e9819 /mfd/prog.c | |
parent | d6f4adec375f9f50186248462f2774d9dc6ae59e (diff) | |
download | mailfromd-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.c | 40 |
1 files changed, 37 insertions, 3 deletions
@@ -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)); |