/* // Full copyright information is available in the file ../doc/CREDITS */ #ifndef execute_h #define execute_h typedef struct frame Frame; typedef struct error_action_specifier Error_action_specifier; typedef struct handler_info Handler_info; typedef struct vmstate VMState; typedef struct vmstack VMStack; typedef struct task_s task_t; #include <sys/types.h> #include <stdarg.h> /* We use the MALLOC_DELTA defines to keep table sizes thirty-two bytes less * than a power of two, which is helpful on buddy systems. */ #define STACK_MALLOC_DELTA 4 #define ARG_STACK_MALLOC_DELTA 8 struct vmstack { cData * stack; Int stack_size, * arg_starts, arg_size; VMStack * next; }; struct vmstate { Frame * cur_frame; cData * stack; Int stack_pos, stack_size, * arg_starts, arg_pos, arg_size; Int task_id; Int preempted; #ifdef DRIVER_DEBUG cData debug; #endif Int limit_datasize; Int limit_fork; Int limit_calldepth; Int limit_recursion; Int limit_objswap; VMState * next; }; struct task_s { cObjnum objnum; Ident method; Int stack_start; Int arg_start; task_t * next; }; struct frame { Obj *object; cObjnum sender; cObjnum caller; cObjnum user; Method *method; Long *opcodes; Int pc; Int last_opcode; Int ticks; Int stack_start; Int var_start; Bool is_frob; Error_action_specifier *specifiers; Handler_info *handler_info; Frame *caller_frame; }; struct error_action_specifier { Int type; Int stack_pos; Int arg_pos; union { struct { Int end; } critical; struct { Int end; } propagate; struct { Int error_list; Int handler; } ccatch; } u; Error_action_specifier *next; }; struct handler_info { cList *traceback; Ident error; Handler_info *next; }; #define MF_NONE 0 /* No flags */ #define MF_NOOVER 1 /* not overridable */ #define MF_SYNC 2 /* synchronized */ #define MF_LOCK 4 /* locked */ #define MF_NATIVE 8 /* native */ #define MF_FORK 16 /* fork */ #define MF_UNDF2 32 /* undefined */ #define MF_UNDF3 64 /* undefined */ #define MF_UNDF4 128 /* undefined */ /* define these seperately, so we can switch the result of 'call_method' */ #define CALL_OK 0 #define CALL_NATIVE 1 #define CALL_FORK 2 #define CALL_ERROR 3 #define CALL_ERR_NONE 0 #define CALL_ERR_NUMARGS 1 #define CALL_ERR_MAXDEPTH 2 #define CALL_ERR_OBJNF 3 #define CALL_ERR_METHNF 4 #define CALL_ERR_PRIVATE 5 #define CALL_ERR_PROT 6 #define CALL_ERR_ROOT 7 #define CALL_ERR_DRIVER 8 extern Frame *cur_frame; extern cData *stack; extern Int stack_pos, stack_size; extern Int *arg_starts, arg_pos, arg_size; extern cStr *numargs_str; extern Long task_id; extern Long call_environ; extern Long tick; extern VMState * preempted; extern VMState * suspended; void init_execute(void); void task(cObjnum objnum, Long message, Int num_args, ...); void task_method(Obj *obj, Method *method); Int frame_start(Obj *obj, Method *method, cObjnum sender, cObjnum caller, cObjnum user, Int stack_start, Int arg_start, Bool is_frob); void pop_native_stack(Int start); void frame_return(void); void anticipate_assignment(void); Int pass_method(Int stack_start, Int arg_start); Int call_method(cObjnum objnum, Ident message, Int stack_start, Int arg_start, Bool is_frob); void pop(Int n); void check_stack(Int n); #define F_PUSH(_name_, _c_type_) \ void CAT(push_, _name_) (_c_type_ var) #define N_PUSH(_name_, _c_type_) \ void CAT(native_push_, _name_) (_c_type_ var) F_PUSH(int, cNum); F_PUSH(float, cFloat); F_PUSH(string, cStr *); F_PUSH(objnum, cObjnum); F_PUSH(list, cList *); F_PUSH(dict, cDict *); F_PUSH(symbol, Ident); F_PUSH(error, Ident); F_PUSH(buffer, cBuf *); N_PUSH(int, cNum); N_PUSH(float, cFloat); N_PUSH(string, cStr *); N_PUSH(objnum, cObjnum); N_PUSH(list, cList *); N_PUSH(dict, cDict *); N_PUSH(symbol, Ident); N_PUSH(error, Ident); N_PUSH(buffer, cBuf *); #undef F_PUSH #undef N_PUSH Int func_init_0(void); Int func_init_1(cData **args, Int type1); Int func_init_2(cData **args, Int type1, Int type2); Int func_init_3(cData **args, Int type1, Int type2, Int type3); Int func_init_0_or_1(cData **args, Int *num_args, Int type1); Int func_init_1_or_2(cData **args, Int *num_args, Int type1, Int type2); Int func_init_2_or_3(cData **args, Int *num_args, Int type1, Int type2, Int type3); Int func_init_3_or_4(cData **args, Int *num_args, Int type1, Int type2, Int type3, Int type4); Int func_init_1_to_3(cData **args, Int *num_args, Int type1, Int type2, Int type3); void func_num_error(Int num_args, char *required); void func_type_error(char *which, cData *wrong, char *required); /* void func_error(Ident id, char *fmt, ...); */ void cthrow(Long id, char *fmt, ...); void unignorable_error(Ident id, cStr *str); void interp_error(Ident error, cStr *str); void user_error(Ident error, cStr *str, cData *arg); void propagate_error(cList *traceback, Ident error); void pop_error_action_specifier(void); void pop_handler_info(void); void task_suspend(void); cList * task_info(Long tid); void task_resume(Long tid, cData *ret); void task_cancel(Long tid); void task_pause(void); VMState *task_lookup(Long tid); cList * task_list(void); cList * task_stack(void); void run_paused_tasks(void); void bind_opcode(Int opcode, cObjnum objnum); #ifdef DRIVER_DEBUG void init_debug(); void clear_debug(); void start_debug(); void start_full_debug(); void get_debug (cData *d); #endif #ifdef PROFILE_EXECUTE void dump_execute_profile(void); #endif #define INVALID_BINDING \ (op_table[cur_frame->last_opcode].binding != INV_OBJNUM && \ op_table[cur_frame->last_opcode].binding != \ cur_frame->method->object->objnum) #define FUNC_NAME() (op_table[cur_frame->last_opcode].name) #define FUNC_BINDING() (op_table[cur_frame->last_opcode].binding) #include "macros.h" #endif