/* interpret.h */ /* It is usually better to include "lpc_incl.h" instead of including this directly */ #ifndef INTERPRET_H #define INTERPRET_H #define PUSH_STRING (0 << 6) #define PUSH_NUMBER (1 << 6) #define PUSH_GLOBAL (2 << 6) #define PUSH_LOCAL (3 << 6) #define PUSH_WHAT (3 << 6) #define PUSH_MASK (0xff ^ (PUSH_WHAT)) #define SWITCH_CASE_SIZE ((int)(2 + sizeof(char *))) /* Trace defines */ #ifdef TRACE # define TRACE_CALL 1 # define TRACE_CALL_OTHER 2 # define TRACE_RETURN 4 # define TRACE_ARGS 8 # define TRACE_EXEC 16 # define TRACE_HEART_BEAT 32 # define TRACE_APPLY 64 # define TRACE_OBJNAME 128 # ifdef LPC_TO_C # define TRACE_COMPILED 256 # define TRACE_LPC_EXEC 512 # endif # define TRACETST(b) (command_giver->interactive->trace_level & (b)) # define TRACEP(b) \ (command_giver && command_giver->interactive && TRACETST(b) && \ (command_giver->interactive->trace_prefix == 0 || \ (current_object && strpref(command_giver->interactive->trace_prefix, \ current_object->name))) ) # define TRACEHB (current_heart_beat == 0 || (command_giver->interactive->trace_level & TRACE_HEART_BEAT)) #endif #define EXTRACT_UCHAR(p) (*(unsigned char *)(p)) /* * Control stack element. * 'prog' is usually same as 'ob->prog' (current_object), except when * when the current function is defined by inheritance. * The pointer, csp, will point to the values that will be used at return. */ #define FRAME_FUNCTION 0 #define FRAME_FUNP 1 #define FRAME_CATCH 2 #define FRAME_FAKE 3 #define FRAME_MASK 3 #define FRAME_OB_CHANGE 4 #define FRAME_EXTERNAL 8 #define FRAME_RETURNED_FROM_CATCH 16 typedef struct control_stack_s { #ifdef PROFILE_FUNCTIONS unsigned long entry_secs, entry_usecs; #endif short framekind; union { int table_index; funptr_t *funp; } fr; object_t *ob; /* Current object */ object_t *prev_ob; /* Save previous object */ program_t *prog; /* Current program */ int num_local_variables; /* Local + arguments */ char *pc; svalue_t *fp; int function_index_offset; /* Used when executing functions in inherited * programs */ int variable_index_offset; /* Same */ short caller_type; /* was this a locally called function? */ } control_stack_t; typedef struct { object_t *ob; union { funptr_t *fp; char *str; } f; int narg; svalue_t *args; } function_to_call_t; typedef struct error_context_s { jmp_buf context; control_stack_t *save_csp; svalue_t *save_sp; object_t **save_cgsp; struct error_context_s *save_context; } error_context_t; typedef struct { function_t *func; int index; } function_lookup_info_t; #define IS_ZERO(x) (!(x) || (((x)->type == T_NUMBER) && ((x)->u.number == 0))) #define IS_UNDEFINED(x) (!(x) || (((x)->type == T_NUMBER) && \ ((x)->subtype == T_UNDEFINED) && ((x)->u.number == 0))) #define CHECK_TYPES(val, t, arg, inst) \ if (!((val)->type & (t))) bad_argument(val, t, arg, inst); /* Beek - add some sanity to joining strings */ /* add to an svalue */ #define EXTEND_SVALUE_STRING(x, y, z) \ SAFE( char *ess_res; \ int ess_len; \ int ess_r; \ ess_len = (ess_r = SVALUE_STRLEN(x)) + strlen(y); \ if (ess_len > MAX_STRING_LENGTH) \ error("Maximum string length exceeded in concatenation.\n"); \ if ((x)->subtype == STRING_MALLOC && MSTR_REF((x)->u.string) == 1) { \ ess_res = (char *) extend_string((x)->u.string, ess_len); \ if (!ess_res) fatal("Out of memory!\n"); \ strcpy(ess_res + ess_r, (y)); \ } else { \ ess_res = new_string(ess_len, z); \ strcpy(ess_res, (x)->u.string); \ strcpy(ess_res + ess_r, (y)); \ free_string_svalue(x); \ (x)->subtype = STRING_MALLOC; \ } \ (x)->u.string = ess_res; \ ) /* <something that needs no free> + string svalue */ #define SVALUE_STRING_ADD_LEFT(y, z) \ SAFE( char *pss_res; int pss_r; int pss_len; \ pss_len = SVALUE_STRLEN(sp) + (pss_r = strlen(y)); \ if (pss_len > MAX_STRING_LENGTH) \ error("Maximum string length exceeded in concatenation.\n"); \ pss_res = new_string(pss_len, z); \ strcpy(pss_res, y); \ strcpy(pss_res + pss_r, sp->u.string); \ free_string_svalue(sp--); \ sp->type = T_STRING; \ sp->u.string = pss_res; \ sp->subtype = STRING_MALLOC; \ ) /* basically, string + string; faster than using extend b/c of SVALUE_STRLEN */ #define SVALUE_STRING_JOIN(x, y, z) \ SAFE( char *ssj_res; int ssj_r; int ssj_len; \ ssj_r = SVALUE_STRLEN(x); \ ssj_len = ssj_r + SVALUE_STRLEN(y); \ if (ssj_len > MAX_STRING_LENGTH) \ error("Maximum string length exceeded in concatenation.\n"); \ if ((x)->subtype == STRING_MALLOC && MSTR_REF((x)->u.string) == 1) { \ ssj_res = (char *) extend_string((x)->u.string, ssj_len); \ if (!ssj_res) fatal("Out of memory!\n"); \ (void) strcpy(ssj_res + ssj_r, (y)->u.string); \ free_string_svalue(y); \ } else { \ ssj_res = (char *) new_string(ssj_len, z); \ strcpy(ssj_res, (x)->u.string); \ strcpy(ssj_res + ssj_r, (y)->u.string); \ free_string_svalue(y); \ free_string_svalue(x); \ (x)->subtype = STRING_MALLOC; \ } \ (x)->u.string = ssj_res; \ ) /* macro calls */ #ifndef LPC_TO_C #define call_program(prog, offset) \ eval_instruction(prog->program + offset) #endif #ifdef DEBUG #define free_svalue(x,y) int_free_svalue(x,y) #else #define free_svalue(x,y) int_free_svalue(x) #endif #define CHECK_STACK_OVERFLOW(x) if (sp + (x) >= end_of_stack) SAFE( too_deep_error = 1; error("stack overflow"); ) #define STACK_INC SAFE( CHECK_STACK_OVERFLOW(1); sp++; ) #define push_svalue(x) SAFE( \ STACK_INC;\ assign_svalue_no_free(sp, x);\ ) #define put_number(x) SAFE( \ sp->type = T_NUMBER;\ sp->subtype = 0;\ sp->u.number = (x);\ ) #define put_buffer(x) SAFE( \ sp->type = T_BUFFER;\ sp->u.buf = (x);\ ) #define put_undested_object(x) SAFE(\ sp->type = T_OBJECT;\ sp->u.ob = (x);\ ) #define put_object(x) SAFE(\ if (!(x) || (x)->flags & O_DESTRUCTED) *sp = const0u;\ else put_undested_object(x);\ ) #define put_unrefed_undested_object(x, y) SAFE(\ sp->type = T_OBJECT;\ sp->u.ob = (x);\ add_ref((x), y);\ ) #define put_unrefed_object(x,y) SAFE(\ if (!(x) || (x)->flags & O_DESTRUCTED) *sp = const0u;\ else put_unrefed_undested_object(x,y);\ ) /* see comments on push_constant_string */ #define put_constant_string(x) SAFE(\ sp->type = T_STRING;\ sp->subtype = STRING_SHARED;\ sp->u.string = make_shared_string(x);\ ) #define put_malloced_string(x) SAFE(\ sp->type = T_STRING;\ sp->subtype = STRING_MALLOC;\ sp->u.string = (x);\ ) #define put_array(x) SAFE(\ sp->type = T_ARRAY;\ sp->u.arr = (x);\ ) #define put_shared_string(x) SAFE(\ sp->type = T_STRING;\ sp->subtype = STRING_SHARED;\ sp->u.string = (x);\ ) #define FOREACH_LEFT_GLOBAL 1 #define FOREACH_RIGHT_GLOBAL 2 #define FOREACH_REF 4 #define FOREACH_MAPPING 8 extern program_t *current_prog; extern short caller_type; extern char *pc; extern svalue_t *sp; extern svalue_t *fp; extern svalue_t *end_of_stack; extern svalue_t catch_value; extern control_stack_t control_stack[CFG_MAX_CALL_DEPTH]; extern control_stack_t *csp; extern int too_deep_error; extern int max_eval_error; extern int function_index_offset; extern int variable_index_offset; extern unsigned int apply_low_call_others; extern unsigned int apply_low_cache_hits; extern unsigned int apply_low_slots_used; extern unsigned int apply_low_collisions; extern int function_index_offset; extern int simul_efun_is_loading; extern program_t fake_prog; extern svalue_t global_lvalue_byte; extern int num_varargs; extern int st_num_arg; extern svalue_t const0; extern svalue_t const1; extern svalue_t const0u; extern svalue_t apply_ret_value; extern ref_t *global_ref_list; extern int lv_owner_type; extern refed_t *lv_owner; void kill_ref PROT((ref_t *)); ref_t *make_ref PROT((void)); /* with LPC_TO_C off, these are defines using eval_instruction */ #ifdef LPC_TO_C void call_program PROT((program_t *, POINTER_INT)); #endif void init_interpreter PROT((void)); void call_direct PROT((object_t *, int, int, int)); void eval_instruction PROT((char *p)); INLINE void assign_svalue PROT((svalue_t *, svalue_t *)); INLINE void assign_svalue_no_free PROT((svalue_t *, svalue_t *)); INLINE void copy_some_svalues PROT((svalue_t *, svalue_t *, int)); INLINE void transfer_push_some_svalues PROT((svalue_t *, int)); INLINE void push_some_svalues PROT((svalue_t *, int)); #ifdef DEBUG INLINE void int_free_svalue PROT((svalue_t *, char *)); #else INLINE void int_free_svalue PROT((svalue_t *)); #endif INLINE void free_string_svalue PROT((svalue_t *)); INLINE void free_some_svalues PROT((svalue_t *, int)); INLINE void push_object PROT((object_t *)); INLINE void push_number PROT((int)); INLINE void push_real PROT((double)); INLINE void push_undefined PROT((void)); INLINE void copy_and_push_string PROT((char *)); INLINE void share_and_push_string PROT((char *)); INLINE void push_array PROT((array_t *)); INLINE void push_refed_array PROT((array_t *)); #ifndef NO_BUFFER_TYPE INLINE void push_buffer PROT((buffer_t *)); INLINE void push_refed_buffer PROT((buffer_t *)); #endif INLINE void push_mapping PROT((mapping_t *)); INLINE void push_refed_mapping PROT((mapping_t *)); INLINE void push_class PROT((array_t *)); INLINE void push_refed_class PROT((array_t *)); INLINE void push_malloced_string PROT((char *)); INLINE void push_shared_string PROT((char *)); INLINE void push_constant_string PROT((char *)); INLINE void pop_stack PROT((void)); INLINE void pop_n_elems PROT((int)); INLINE void pop_2_elems PROT((void)); INLINE void pop_3_elems PROT((void)); INLINE function_t *setup_inherited_frame PROT((int)); INLINE program_t *find_function_by_name PROT((object_t *, char *, int *, int *)); char *function_name PROT((program_t *, int)); void remove_object_from_stack PROT((object_t *)); void setup_fake_frame PROT((funptr_t *)); void remove_fake_frame PROT((void)); void push_indexed_lvalue PROT((int)); void setup_variables PROT((int, int, int)); void process_efun_callback PROT((int, function_to_call_t *, int)); svalue_t *call_efun_callback PROT((function_to_call_t *, int)); char *type_name PROT((int c)); void bad_arg PROT((int, int)); void bad_argument PROT((svalue_t *, int, int, int)); void check_for_destr PROT((array_t *)); int is_static PROT((char *, object_t *)); int apply_low PROT((char *, object_t *, int)); svalue_t *apply PROT((char *, object_t *, int, int)); svalue_t *call_function_pointer PROT((funptr_t *, int)); svalue_t *safe_call_function_pointer PROT((funptr_t *, int)); svalue_t *safe_apply PROT((char *, object_t *, int, int)); void call___INIT PROT((object_t *)); array_t *call_all_other PROT((array_t *, char *, int)); char *function_exists PROT((char *, object_t *, int)); void call_function PROT((program_t *, int)); void mark_apply_low_cache PROT((void)); void translate_absolute_line PROT((int, unsigned short *, int *, int *)); char *add_slash PROT((char *)); int strpref PROT((char *, char *)); array_t *get_svalue_trace PROT((void)); void do_trace PROT((char *, char *, char *)); char *dump_trace PROT((int)); void opcdump PROT((char *)); int inter_sscanf PROT((svalue_t *, svalue_t *, svalue_t *, int)); char * get_line_number_if_any PROT((void)); char *get_line_number PROT((char *, program_t *)); void get_line_number_info PROT((char **, int *)); void get_version PROT((char *)); void reset_machine PROT((int)); void unlink_string_svalue PROT((svalue_t *)); void copy_lvalue_range PROT((svalue_t *)); void assign_lvalue_range PROT((svalue_t *)); void debug_perror PROT((char *, char *)); #ifndef NO_SHADOWS int validate_shadowing PROT((object_t *)); #endif #if !defined(NO_RESETS) && defined(LAZY_RESETS) void try_reset PROT((object_t *)); #endif void pop_context PROT((error_context_t *)); void restore_context PROT((error_context_t *)); int save_context PROT((error_context_t *)); void pop_control_stack PROT((void)); INLINE function_t *setup_new_frame PROT((int)); INLINE void push_control_stack PROT((int)); void break_point PROT((void)); #ifdef DEBUGMALLOC_EXTENSIONS void mark_svalue PROT((svalue_t *)); void mark_stack PROT((void)); #endif #endif /* _INTERPRET_H */