/* This file is part of Mailfromd. Copyright (C) 2006-2020 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define MFL_DATASEG volatile typedef void *mft_ptr; typedef char *mft_str; typedef int mft_int; typedef unsigned int mft_uint; typedef long mft_long; typedef unsigned long mft_ulong; typedef size_t mft_size; typedef mft_str mft_string; typedef mft_long mft_number; union mf_stkval { mft_ptr v_ptr; mft_size v_size; mft_long v_long; mft_ulong v_ulong; mft_int v_int; mft_uint v_uint; mft_str v_str; }; typedef union mf_stkval STKVAL; #define mf_cat(a,b) a ## b #define mf_c_val(x,t) ((x).mf_cat(v_,t)) #define mf_c_cast(x,t) ((STKVAL)(mf_cat(mft_,t))(x)) typedef void (*instr_t) (eval_environ_t env); /* Instruction */ union mf_code_cell { instr_t c_instr; STKVAL c_value; }; typedef union mf_code_cell mf_code_cell_t; #define mf_cell_instr(p) ((p).c_instr) #define mf_cell_value(p) ((p).c_value) #define mf_cell_c_value(p,t) mf_c_val(mf_cell_value(p),t) struct optab { char *name; instr_t instr; void (*dump) (prog_counter_t i); unsigned length; }; /* Code generation and diagnostics functions */ void code_put_stkval(prog_counter_t pos, STKVAL val); #define code_put(p,v,t) code_put_stkval(p,mf_c_cast(v,t)) mf_code_cell_t code_peek(prog_counter_t pos); prog_counter_t code_reserve(size_t count); prog_counter_t code_immediate_stkval(STKVAL value); #define code_immediate(v,t) code_immediate_stkval(mf_c_cast(v,t)) prog_counter_t code_op(unsigned code); prog_counter_t code_instr(const instr_t ptr); prog_counter_t code_exmask(struct exmask *exmask); prog_counter_t code_get_counter(); void dump_code(prog_counter_t start, prog_counter_t end); void fixup_code(void); /* Runtime evaluation functions */ struct eval_environ; #define B2STACK(s) (s + sizeof(STKVAL) - 1) / sizeof(STKVAL) void runtime_warning(eval_environ_t env, const char *fmt, ...) MU_PRINTFLIKE(2, 3); void runtime_error(eval_environ_t env, const char *fmt, ...) MU_PRINTFLIKE(2, 3) ATTRIBUTE_NORETURN; STKVAL get_arg(eval_environ_t env, unsigned n); void get_pointer_arg(eval_environ_t env, unsigned n, void * MFL_DATASEG *p); void get_string_arg(eval_environ_t env, unsigned n, char *MFL_DATASEG *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); void heap_obstack_begin(eval_environ_t env); STKVAL heap_obstack_finish(eval_environ_t env); void heap_obstack_cancel(eval_environ_t env); void *heap_obstack_grow(eval_environ_t env, void *MFL_DATASEG ptr, size_t size); void *heap_obstack_base(eval_environ_t env); void pushs(eval_environ_t env, const char * MFL_DATASEG s); void advance_pc(eval_environ_t env, long cnt); void adjust_stack(eval_environ_t env, unsigned cnt); void unroll_stack(eval_environ_t env, unsigned cnt); void prog_trace(eval_environ_t env, const char *fmt, ...) MU_PRINTFLIKE(2, 3); void runtime_stack_trace(eval_environ_t env); void env_var_inc(eval_environ_t env, size_t off); void env_get_locus(eval_environ_t env, struct mu_locus_range *loc); STKVAL env_get_reg(eval_environ_t env); prog_counter_t env_register_read(eval_environ_t env, int what); char *env_vaptr(eval_environ_t env, size_t off); int expand_dataseg(eval_environ_t env, size_t count, const char *errtext); void *env_get_builtin_priv(eval_environ_t env, int id); int builtin_priv_register(void *(*init)(void), void (*destroy)(void*), void (*free_capture)); void env_free_captured(eval_environ_t env); void env_function_cleanup_add(eval_environ_t env, void *data, void (*func)(void *)); void env_function_cleanup_del(eval_environ_t env, void *data); void env_function_cleanup_flush(eval_environ_t env, void *ptr); void ensure_initialized_variable(const char *name, struct value *val); void scan_code(prog_counter_t start, prog_counter_t end, void (*fun)(prog_counter_t pc, struct optab *op, void *d), void *data); int within_loop(struct literal *lit); void enter_loop(struct literal *lit, prog_counter_t *begptr, prog_counter_t *endptr); void leave_loop(void); NODE *alloc_node(enum node_type type, const struct mu_locus_range *locus); NODE *create_node_variable(struct variable *var, const struct mu_locus_range *locus); NODE *create_node_argcount(const struct mu_locus_range *locus); NODE *create_node_arg(long num, const struct mu_locus_range *locus); NODE *create_node_symbol(struct literal *lit, const struct mu_locus_range *loc); NODE *create_node_backref(long num, const struct mu_locus_range *locus); NODE *cast_to(data_type_t type, NODE *node); void add_xref(struct variable *var, const struct mu_locus_range *locus); extern mf_code_cell_t *prog; extern unsigned error_count; extern unsigned long prog_trace_option; extern STKVAL *dataseg; extern size_t datasize; extern size_t dvarsize; #define EXTABIND (datasize - exception_count) extern size_t *dataseg_reloc; extern size_t dataseg_reloc_count; extern size_t exception_count; extern mu_stream_t mf_strecho;