#ifndef INTERPRET_H #define INTERPRET_H union u { char *string; p_int number; struct object *ob; struct vector *vec; struct mapping *map; struct lambda *lambda; p_int mantissa; struct svalue *lvalue; struct protected_lvalue *protected_lvalue; struct protected_char_lvalue *protected_char_lvalue; struct protected_range_lvalue *protected_range_lvalue; void (*error_handler) PROT((struct svalue *)); struct const_list_svalue *const_list; }; /* * The value stack element. * If it is a string, then the way that the string has been allocated differ, * wich will affect how it should be freed. */ struct svalue { ph_int type; union { ph_int string_type; ph_int exponent; ph_int closure_type; ph_int quotes; ph_int num_arg; /* for call_out.c */ ph_int generic; } x; union u u; }; #define SVALUE_FULLTYPE(svp) ((p_int *)(svp)) #define T_INVALID 0x0 #define T_LVALUE 0x1 #define T_NUMBER 0x2 #define T_STRING 0x3 #define T_POINTER 0x4 #define T_OBJECT 0x5 #define T_MAPPING 0x6 #define T_FLOAT 0x7 #define T_CLOSURE 0x8 #define T_SYMBOL 0x9 #define T_QUOTED_ARRAY 0xa #define T_CHAR_LVALUE 0xb #define T_STRING_RANGE_LVALUE 0xc #define T_POINTER_RANGE_LVALUE 0xd #define T_PROTECTED_CHAR_LVALUE 0x0e #define T_PROTECTED_STRING_RANGE_LVALUE 0x0f #define T_PROTECTED_POINTER_RANGE_LVALUE 0x10 #define T_PROTECTED_LVALUE 0x11 #define T_PROTECTOR_MAPPING 0x12 #define T_ERROR_HANDLER 0x13 #define STRING_MALLOC 0 /* Allocated by malloc() */ #define STRING_VOLATILE 1 /* Do not has to be freed at all */ #define STRING_CONSTANT 1 /* Old, but misleading name */ #define STRING_SHARED 2 /* Allocated by the shared string library */ #define CLOSURE_OPERATOR (-0x1800) #define CLOSURE_EFUN (-0x1000) #define CLOSURE_SIMUL_EFUN (-0x0800) #define CLOSURE_MALLOCED(c) ((c) >= 0) #define CLOSURE_LFUN 0 #define CLOSURE_IDENTIFIER 1 #define CLOSURE_PRELIMINARY 2 #define CLOSURE_REFERENCES_CODE(c) ((c) > 2) #define CLOSURE_BOUND_LAMBDA 3 #define CLOSURE_HAS_CODE(c) ((c) > 3) #define CLOSURE_LAMBDA 4 #define CLOSURE_UNBOUND_LAMBDA 5 #define CLOSURE_IDENTIFIER_OFFS 0xe800 #define CLOSURE_OPERATOR_OFFS (CLOSURE_OPERATOR & 0xffff) #define CLOSURE_EFUN_OFFS (CLOSURE_EFUN & 0xffff) #define CLOSURE_SIMUL_EFUN_OFFS (CLOSURE_SIMUL_EFUN & 0xffff) struct vector { ph_int size; ph_int ref; #ifdef DEBUG p_int extra_ref; #endif struct wiz_list *user; /* Save who made the vector */ struct svalue item[1]; }; struct mapping { p_int ref; struct hash_mapping *hash; struct condensed_mapping *condensed; struct wiz_list *user; int num_values; /* number of values per key */ }; struct hash_mapping { p_int mask; p_int used; p_int condensed_deleted; p_int ref; struct map_chain *deleted; struct mapping *next_dirty; struct map_chain *chains[1]; }; struct condensed_mapping { /* values for misc keys go above */ #define CM_MISC(m) ((struct svalue *)(m)) /* struct svalue misc[0]; */ p_int misc_size; p_int string_size; #define CM_STRING(m) ((char **)((m)+1)) /* char *string[0]; */ /* values for string keys go below */ }; struct lambda { p_int ref; struct object *ob; union { unsigned short index; /* lfun closures */ char code[1]; /* lambda closures */ struct lambda *lambda; } function; }; struct map_chain { struct map_chain *next; struct svalue key; struct svalue data[1]; /* data == &key+1 is used in some places */ }; #define MAP_CHAIN_SIZE(n) (\ (sizeof(struct map_chain) - sizeof(struct svalue) ) +\ sizeof(struct svalue)*(n) ) #define ALLOC_VECTOR(nelem) \ (struct vector *)xalloc(sizeof (struct vector) + \ sizeof(struct svalue) * (nelem - 1)) void free_vector PROT((struct vector *)), free_all_values(); /* * 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. */ struct control_stack { struct object *ob; /* Current object */ struct object *prev_ob; /* Save previous object */ struct program *prog; /* Current program */ char *pc; struct svalue *fp; char *funstart; int num_local_variables; /* Local + arguments */ int function_index_offset; /* Used when executing functions in inherited programs */ struct svalue *current_variables; /* Same */ short extern_call; /* Flag if evaluator should return */ short dummy; short *break_sp; struct object *pretend_to_be; }; #include <setjmp.h> extern struct error_recovery_info { struct error_recovery_info *last; int type; jmp_buf context; } *error_recovery_pointer; #define ERROR_RECOVERY_NONE 0 #define ERROR_RECOVERY_BACKEND 1 #define ERROR_RECOVERY_APPLY 2 #define ERROR_RECOVERY_CATCH 3 #define LI_MAXOFFSET 0x3c #define LI_INCLUDE 0x3d #define LI_INCLUDE_END 0x3e #define LI_L_RELOCATED 0x3f #define LI_RELOCATED 0xc0 #define LI_SMALL_REL 0x20 #define LI_MAXEMPTY 0x20 #if defined(atarist) || (defined(AMIGA) && defined(_DCC)) /* Faster routines, using inline and knowlegde about double format. * the exponent isn't actually in 'exponent', but that doesn't really matter * as long as the accesses are consistent. * the DICE compiler for the amiga lacks the ldexp() and frexp() functions, * therefore these funcions here are more than a speedup there... */ #define FLOAT_FORMAT_1 /* STORE_DOUBLE doesn't do any rounding, but truncates off the least * significant bits of the mantissa that won't fit together with the exponent * into 48 bits. To compensate for this, we initialise the unknown bits of * the mantissa with 0x7fff in READ_DOUBLE . This keeps the maximum precision * loss of a store/read pair to the same value as rounding, while being faster * and being more stable. */ static #ifdef atarist inline #endif double READ_DOUBLE(struct svalue *svalue_pnt) { double tmp; (*(long*)&tmp) = svalue_pnt->u.mantissa; ((short*)&tmp)[2] = svalue_pnt->x.exponent; ((short*)&tmp)[3] = 0x7fff; return tmp; } #define SPLIT_DOUBLE(double_value, int_pnt) (\ (*(int_pnt) = ((short*)&double_value)[2]),\ *((long*)&double_value)\ ) #define STORE_DOUBLE_USED #define STORE_DOUBLE(dest, double_value) (\ (dest)->u.mantissa = *((long*)&double_value),\ (dest)->x.exponent = ((short*)&double_value)[2]\ ) #endif #ifndef STORE_DOUBLE #define FLOAT_FORMAT_0 #define READ_DOUBLE(svalue_pnt) ( ldexp( (double)((svalue_pnt)->u.mantissa) , \ (svalue_pnt)->x.exponent-31 ) ) /* if your machine doesn't use the exponent to designate powers of two, the use of ldexp in SPLIT_DOUBLE won't work; you'll have to mulitply with 32768. in this case */ #define SPLIT_DOUBLE(double_value, int_pnt) \ ( (long)ldexp( frexp( (double_value), (int_pnt) ), 31) ) #define STORE_DOUBLE_USED int __store_double_int_; #define STORE_DOUBLE(dest, double_value) (\ ((dest)->u.mantissa = SPLIT_DOUBLE((double_value), &__store_double_int_)),\ (dest)->x.exponent = __store_double_int_\ ) #endif #endif /* INTERPRET_H */