diff --git a/src/interpret.c b/src/interpret.c index b8c13ee2b0a53414f9d402b3072bc87bf23c9b26..3e2f2a679a0e6c9bd64a768dc83cfac1bc8d8d32 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -25,17 +25,41 @@ #include "lpc_signal.h" #define TRACE_LEN (100 + t_flag * 10) -struct svalue evaluator_stack[EVALUATOR_STACK_SIZE]; -struct svalue *mark_stack[EVALUATOR_STACK_SIZE]; -struct frame *fp; /* frame pointer */ + /* sp points to first unused value on stack * (much simpler than letting it point at the last used value.) */ -struct svalue *sp=evaluator_stack; +struct svalue *sp; /* mark stack, used to store markers into the normal stack */ -struct svalue **mark_sp=mark_stack; +struct svalue **mark_sp; + +struct frame *fp; /* frame pointer */ + +struct svalue evaluator_stack[EVALUATOR_STACK_SIZE]; +struct svalue *mark_stack[EVALUATOR_STACK_SIZE]; + +void init_interpreter() +{ + sp=evaluator_stack; + mark_sp=mark_stack; +} + +void exit_interpreter() {} + +void check_stack(INT32 size) +{ + if(sp - evaluator_stack + size >= EVALUATOR_STACK_SIZE) + error("Stack overflow.\n"); +} + +void check_mark_stack(INT32 size) +{ + if(mark_sp - mark_stack + size >= EVALUATOR_STACK_SIZE) + error("Stack overflow.\n"); +} + static void eval_instruction(unsigned char *pc); @@ -191,7 +215,7 @@ void print_return_value() void pop_n_elems(INT32 x) { #ifdef DEBUG - if(sp - &(evaluator_stack[0]) < x) + if(sp - evaluator_stack < x) fatal("Popping out of stack.\n"); if(x < 0) fatal("Popping negative number of args....\n"); @@ -364,6 +388,9 @@ static void eval_instruction(unsigned char *pc) if(sp<evaluator_stack || mark_sp < mark_stack || fp->locals>sp) fatal("Stack error.\n"); + if(sp > evaluator_stack+EVALUATOR_STACK_SIZE) + fatal("Stack error (overflow).\n"); + if(fp->fun>=0 && fp->current_object->prog && fp->locals+fp->num_locals > sp) fatal("Stack error.\n"); @@ -691,7 +718,6 @@ static void eval_instruction(unsigned char *pc) break; CASE(F_BRANCH_WHEN_ZERO); - check_destructed(sp-1); if(!IS_ZERO(sp-1)) { pc+=sizeof(INT32); @@ -703,7 +729,6 @@ static void eval_instruction(unsigned char *pc) break; CASE(F_BRANCH_WHEN_NON_ZERO); - check_destructed(sp-1); if(IS_ZERO(sp-1)) { pc+=sizeof(INT32); @@ -722,7 +747,6 @@ static void eval_instruction(unsigned char *pc) CJUMP(F_BRANCH_WHEN_GE,!is_lt); CASE(F_LAND); - check_destructed(sp-1); if(!IS_ZERO(sp-1)) { pc+=sizeof(INT32); @@ -734,7 +758,6 @@ static void eval_instruction(unsigned char *pc) break; CASE(F_LOR); - check_destructed(sp-1); if(IS_ZERO(sp-1)) { pc+=sizeof(INT32); @@ -812,14 +835,11 @@ static void eval_instruction(unsigned char *pc) { sp[-1].u.float_number =- sp[-1].u.float_number; }else{ - error("Bad argument to unary minus.\n"); + o_negate(); } break; - CASE(F_COMPL); - if(sp[-1].type != T_INT) error("Bad argument to ~.\n"); - sp[-1].u.integer = ~ sp[-1].u.integer; - break; + CASE(F_COMPL); o_compl(); break; CASE(F_NOT); switch(sp[-1].type) @@ -830,12 +850,15 @@ static void eval_instruction(unsigned char *pc) case T_FUNCTION: case T_OBJECT: - check_destructed(sp-1); - if(sp[-1].type == T_INT) + if(IS_ZERO(sp-1)) { - sp[-1].u.integer=1; - break; + pop_stack(); + push_int(1); + }else{ + pop_stack(); + push_int(0); } + break; default: free_svalue(sp-1); @@ -845,17 +868,25 @@ static void eval_instruction(unsigned char *pc) break; CASE(F_LSH); - if(sp[-2].type != T_INT) error("Bad argument 1 to <<\n"); - if(sp[-1].type != T_INT) error("Bad argument 2 to <<\n"); - sp--; - sp[-1].u.integer = sp[-1].u.integer << sp->u.integer; + if(sp[-2].type != T_INT) + { + o_lsh(); + }else{ + if(sp[-1].type != T_INT) error("Bad argument 2 to <<\n"); + sp--; + sp[-1].u.integer = sp[-1].u.integer << sp->u.integer; + } break; CASE(F_RSH); - if(sp[-2].type != T_INT) error("Bad argument 1 to >>\n"); - if(sp[-1].type != T_INT) error("Bad argument 2 to >>\n"); - sp--; - sp[-1].u.integer = sp[-1].u.integer >> sp->u.integer; + if(sp[-2].type != T_INT) + { + o_rsh(); + }else{ + if(sp[-1].type != T_INT) error("Bad argument 2 to >>\n"); + sp--; + sp[-1].u.integer = sp[-1].u.integer >> sp->u.integer; + } break; COMPARISMENT(F_EQ, is_eq(sp-2,sp-1)); @@ -889,11 +920,12 @@ static void eval_instruction(unsigned char *pc) CASE(F_RANGE); o_range(); break; CASE(F_COPY_VALUE); - copy_svalues_recursively_no_free(sp,sp-1,1,0); - sp++; - free_svalue(sp-2); - sp[-2]=sp[-1]; - sp--; + { + struct svalue tmp; + copy_svalues_recursively_no_free(&tmp,sp-1,1,0); + free_svalue(sp-1); + sp[-1]=tmp; + } break; CASE(F_SSCANF); f_sscanf(GET_ARG()); break; @@ -964,7 +996,6 @@ void apply_low(struct object *o, int fun, int args) struct frame new_frame; struct identifier *function; - check_signals(); if(fun<0) { pop_n_elems(args); @@ -972,8 +1003,9 @@ void apply_low(struct object *o, int fun, int args) return; } - if(evaluator_stack+EVALUATOR_STACK_SIZE-sp < 256) - error("Stack overflow.\n"); + check_signals(); + check_stack(256); + check_mark_stack(256); p=o->prog; if(!p) @@ -1172,13 +1204,12 @@ void safe_apply_low(struct object *o,int fun,int args) sp->type = T_INT; sp++; }else{ - struct svalue *expected_sp; - expected_sp=sp+1; + INT32 expected_stack = sp - evaluator_stack + 1; sp+=args; apply_low(o,fun,args); - if(sp > expected_sp) - pop_n_elems(sp-expected_sp); - if(sp < expected_sp) + if(sp - evaluator_stack > expected_stack) + pop_n_elems(sp - evaluator_stack - expected_stack); + if(sp - evaluator_stack < expected_stack) { sp->u.integer = 0; sp->subtype=NUMBER_NUMBER; @@ -1198,37 +1229,28 @@ void safe_apply(struct object *o, char *fun ,INT32 args) safe_apply_low(o, find_identifier(fun, o->prog), args); } +void apply_lfun(struct object *o, int fun, int args) +{ +#ifdef DEBUG + if(fun < 0 || fun >= NUM_LFUNS) + fatal("Apply lfun on illegal value!\n"); +#endif + if(!o->prog) + error("Apply on destructed object.\n"); + + apply_low(o, o->prog->lfuns[fun], args); +} + void apply_shared(struct object *o, struct lpc_string *fun, int args) { - int fun_number; - fun_number = find_shared_string_identifier(fun, o->prog); - if(fun_number < 0) - { - pop_n_elems(args); - sp++; - sp->u.integer=0; - sp->type=T_INT; - }else{ - apply_low(o, fun_number, args); - } + apply_low(o, find_shared_string_identifier(fun, o->prog), args); } void apply(struct object *o, char *fun, int args) { - int fun_number; - - fun_number = find_identifier(fun, o->prog); - if(fun_number < 0) - { - pop_n_elems(args); - sp->u.integer=0; - sp->type=T_INT; - sp++; - }else{ - apply_low(o, fun_number, args); - } + apply_low(o, find_identifier(fun, o->prog), args); } void strict_apply_svalue(struct svalue *s, INT32 args) @@ -1333,18 +1355,20 @@ void apply_svalue(struct svalue *s, INT32 args) pop_n_elems(args); push_int(0); }else{ - struct svalue *expected_sp=sp-args+1; + INT32 expected_stack=sp-args+1 - evaluator_stack; + strict_apply_svalue(s,args); - if(sp > expected_sp) + if(sp > (expected_stack + evaluator_stack)) { - pop_n_elems(sp-expected_sp); + pop_n_elems(sp-(expected_stack + evaluator_stack)); } - else if(sp < expected_sp) + else if(sp < (expected_stack + evaluator_stack)) { push_int(0); } #ifdef DEBUG - if(sp < expected_sp) fatal("Stack underflow!\n"); + if(sp < (expected_stack + evaluator_stack)) + fatal("Stack underflow!\n"); #endif } } @@ -1355,15 +1379,15 @@ void slow_check_stack() struct svalue *s,**m; struct frame *f; - check_stack(); + debug_check_stack(); if(sp > &(evaluator_stack[EVALUATOR_STACK_SIZE])) fatal("Stack overflow\n"); - if(mark_sp < mark_stack) - fatal("Mark stack underflow.\n"); - if(mark_sp > &(mark_stack[EVALUATOR_STACK_SIZE])) + fatal("Mark stack overflow.\n"); + + if(mark_sp < mark_stack) fatal("Mark stack underflow.\n"); for(s=evaluator_stack;s<sp;s++) check_svalue(s); diff --git a/src/interpret.h b/src/interpret.h index 358ecdb218a87af9b998db4ab6e533c5ed2eb592..754fdf5cad432faae6d2f110dc2225a33be61adb 100644 --- a/src/interpret.h +++ b/src/interpret.h @@ -26,11 +26,12 @@ struct frame }; #ifdef DEBUG -#define check_stack() do{if(sp<evaluator_stack)fatal("Stack error.\n");}while(0) +#define debug_check_stack() do{if(sp<evaluator_stack)fatal("Stack error.\n");}while(0) #else -#define check_stack() +#define debug_check_stack() #endif -#define pop_stack() do{ free_svalue(--sp); check_stack(); }while(0) + +#define pop_stack() do{ free_svalue(--sp); debug_check_stack(); }while(0) #define push_program(P) sp->u.program=(P),sp++->type=T_PROGRAM #define push_int(I) sp->u.integer=(I),sp->type=T_INT,sp++->subtype=NUMBER_NUMBER #define push_mapping(M) sp->u.mapping=(M),sp++->type=T_MAPPING @@ -66,9 +67,14 @@ do{ \ }while(0) /* Prototypes begin here */ +void init_interpreter(); +void exit_interpreter(); +void check_stack(INT32 size); +void check_mark_stack(INT32 size); void lvalue_to_svalue_no_free(struct svalue *to,struct svalue *lval); void assign_lvalue(struct svalue *lval,struct svalue *from); union anything *get_pointer_if_this_type(struct svalue *lval, TYPE_T t); +void print_return_value(); void pop_n_elems(INT32 x); void reset_evaluator(); void f_catch(unsigned char *pc); @@ -91,6 +97,7 @@ void cleanup_interpret(); extern struct svalue *sp; extern struct svalue **mark_sp; extern struct svalue evaluator_stack[EVALUATOR_STACK_SIZE]; +extern struct svalue *mark_stack[EVALUATOR_STACK_SIZE]; extern struct frame *fp; /* frame pointer */ #endif