67bdb52000-04-18Henrik Grubbström (Grubba) /*
2cd8ca2000-07-28Fredrik Hübinette (Hubbe)  * $Id: interpret_functions.h,v 1.27 2000/07/29 06:31:06 hubbe Exp $
67bdb52000-04-18Henrik Grubbström (Grubba)  * * Opcode definitions for the interpreter. */
87c7592000-04-18Fredrik Hübinette (Hubbe)  OPCODE0(F_UNDEFINED,"push UNDEFINED") push_int(0); Pike_sp[-1].subtype=NUMBER_UNDEFINED; BREAK; OPCODE0(F_CONST0, "push 0") push_int(0); BREAK; OPCODE0(F_CONST1, "push 1") push_int(1); BREAK; OPCODE0(F_CONST_1,"push -1") push_int(-1); BREAK; OPCODE0(F_BIGNUM, "push 0x7fffffff") push_int(0x7fffffff); BREAK; OPCODE1(F_NUMBER, "push int") push_int(arg1); BREAK; OPCODE1(F_NEG_NUMBER,"push -int") push_int(-arg1); BREAK; OPCODE1(F_CONSTANT,"constant") assign_svalue_no_free(Pike_sp++,& Pike_fp->context.prog->constants[arg1].sval); print_return_value(); BREAK; /* The rest of the basic 'push value' instructions */ OPCODE1_TAIL(F_MARK_AND_STRING,"mark & string") *(Pike_mark_sp++)=Pike_sp; OPCODE1(F_STRING,"string") copy_shared_string(Pike_sp->u.string,Pike_fp->context.prog->strings[arg1]); Pike_sp->type=PIKE_T_STRING; Pike_sp->subtype=0; Pike_sp++; print_return_value(); BREAK; OPCODE1(F_ARROW_STRING,"->string") copy_shared_string(Pike_sp->u.string,Pike_fp->context.prog->strings[arg1]); Pike_sp->type=PIKE_T_STRING; Pike_sp->subtype=1; /* Magic */ Pike_sp++; print_return_value(); BREAK; OPCODE0(F_FLOAT,"push float") /* FIXME, this opcode uses 'pc' which is not allowed.. */ Pike_sp->type=PIKE_T_FLOAT; MEMCPY((void *)&Pike_sp->u.float_number, pc, sizeof(FLOAT_TYPE)); pc+=sizeof(FLOAT_TYPE); Pike_sp++; BREAK; OPCODE1(F_LFUN, "local function") Pike_sp->u.object=Pike_fp->current_object; add_ref(Pike_fp->current_object); Pike_sp->subtype=arg1+Pike_fp->context.identifier_level; Pike_sp->type=PIKE_T_FUNCTION; Pike_sp++; print_return_value(); BREAK; OPCODE1(F_TRAMPOLINE, "trampoline") { struct object *o=low_clone(pike_trampoline_program); add_ref( ((struct pike_trampoline *)(o->storage))->frame=Pike_fp ); ((struct pike_trampoline *)(o->storage))->func=arg1+Pike_fp->context.identifier_level; push_object(o); /* Make it look like a function. */ Pike_sp[-1].subtype = pike_trampoline_program->lfuns[LFUN_CALL]; Pike_sp[-1].type = T_FUNCTION; print_return_value(); } BREAK; /* The not so basic 'push value' instructions */ OPCODE1(F_GLOBAL,"global") low_object_index_no_free(Pike_sp, Pike_fp->current_object, arg1 + Pike_fp->context.identifier_level); Pike_sp++; print_return_value(); BREAK;
a96ce92000-04-19Fredrik Hübinette (Hubbe) OPCODE2(F_EXTERNAL,"external")
87c7592000-04-18Fredrik Hübinette (Hubbe) { struct inherit *inherit; struct program *p; struct object *o; INT32 i; inherit=&Pike_fp->context; o=Pike_fp->current_object; if(!o) error("Current object is destructed\n"); while(1) { if(inherit->parent_offset) { #ifdef PIKE_DEBUG if(t_flag>4) { sprintf(trace_buffer,"- Following o->parent (accumulator+=%d)\n",inherit->parent_offset-1); write_to_stderr(trace_buffer,strlen(trace_buffer)); } #endif i=o->parent_identifier; o=o->parent;
a96ce92000-04-19Fredrik Hübinette (Hubbe)  arg2+=inherit->parent_offset-1;
87c7592000-04-18Fredrik Hübinette (Hubbe)  }else{ #ifdef PIKE_DEBUG if(t_flag>4) { sprintf(trace_buffer,"- Following inherit->parent (accumulator+=%d)\n",inherit->parent_offset-1); write_to_stderr(trace_buffer,strlen(trace_buffer)); } #endif i=inherit->parent_identifier; o=inherit->parent; } if(!o) error("Parent was lost during cloning.\n"); if(!(p=o->prog)) error("Attempting to access variable in destructed object\n"); #ifdef DEBUG_MALLOC if (o->refs == 0x55555555) { fprintf(stderr, "The object %p has been zapped!\n", o); describe(p); fatal("Object zapping detected.\n"); } if (p->refs == 0x55555555) { fprintf(stderr, "The program %p has been zapped!\n", p); describe(p); fprintf(stderr, "Which taken from the object %p\n", o); describe(o); fatal("Looks like the program %p has been zapped!\n", p); } #endif /* DEBUG_MALLOC */ #ifdef PIKE_DEBUG if(i < 0 || i > p->num_identifier_references) fatal("Identifier out of range!\n"); #endif inherit=INHERIT_FROM_INT(p, i); #ifdef DEBUG_MALLOC if (inherit->storage_offset == 0x55555555) { fprintf(stderr, "The inherit %p has been zapped!\n", inherit); debug_malloc_dump_references(inherit,0,2,0); fprintf(stderr, "It was extracted from the program %p %d\n", p, i); describe(p); fprintf(stderr, "Which was in turn taken from the object %p\n", o); describe(o); fatal("Looks like the program %p has been zapped!\n", p); } #endif /* DEBUG_MALLOC */
a96ce92000-04-19Fredrik Hübinette (Hubbe)  if(!arg2) break; --arg2;
87c7592000-04-18Fredrik Hübinette (Hubbe)  } low_object_index_no_free(Pike_sp, o, arg1 + inherit->identifier_level); Pike_sp++; print_return_value(); } BREAK;
a96ce92000-04-19Fredrik Hübinette (Hubbe) OPCODE2(F_EXTERNAL_LVALUE,"& external") { struct inherit *inherit; struct program *p; struct object *o; INT32 i,id=arg1; inherit=&Pike_fp->context; o=Pike_fp->current_object; if(!o)
c870472000-07-12Henrik Grubbström (Grubba)  error("Parent was lost during cloning.\n"); if(!(o->prog)) error("Attempting to access variable in destructed object\n");
a96ce92000-04-19Fredrik Hübinette (Hubbe)  while(1) { if(inherit->parent_offset) { i=o->parent_identifier; o=o->parent; arg2+=inherit->parent_offset-1; }else{ i=inherit->parent_identifier; o=inherit->parent; } if(!o) error("Parent no longer exists\n"); if(!(p=o->prog)) error("Attempting to access variable in destructed object\n"); inherit=INHERIT_FROM_INT(p, i); if(!arg2) break; arg2--; } ref_push_object(o); Pike_sp->type=T_LVALUE; Pike_sp->u.integer=id + inherit->identifier_level; Pike_sp++; } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f853ac2000-04-20Henrik Grubbström (Grubba) OPCODE1(F_MARK_AND_LOCAL, "mark & local") *(Pike_mark_sp++) = Pike_sp; assign_svalue_no_free(Pike_sp++, Pike_fp->locals + arg1); print_return_value(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f853ac2000-04-20Henrik Grubbström (Grubba) OPCODE1(F_LOCAL, "local") assign_svalue_no_free(Pike_sp++, Pike_fp->locals + arg1); print_return_value(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE2(F_2_LOCALS, "2 locals") assign_svalue_no_free(Pike_sp++, Pike_fp->locals + arg1); print_return_value(); assign_svalue_no_free(Pike_sp++, Pike_fp->locals + arg2); print_return_value(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
a96ce92000-04-19Fredrik Hübinette (Hubbe) OPCODE2(F_LOCAL_2_LOCAL, "local = local")
1986622000-04-20Henrik Grubbström (Grubba)  assign_svalue(Pike_fp->locals + arg1, Pike_fp->locals + arg2);
f102d22000-04-19Henrik Grubbström (Grubba) BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
1986622000-04-20Henrik Grubbström (Grubba) OPCODE2(F_LOCAL_2_GLOBAL, "global = local")
f102d22000-04-19Henrik Grubbström (Grubba) { INT32 tmp = arg1 + Pike_fp->context.identifier_level; struct identifier *i;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba)  if(!Pike_fp->current_object->prog) error("Cannot access global variables in destructed object.\n");
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba)  i = ID_FROM_INT(Pike_fp->current_object->prog, tmp); if(!IDENTIFIER_IS_VARIABLE(i->identifier_flags)) error("Cannot assign functions or constants.\n");
2cd8ca2000-07-28Fredrik Hübinette (Hubbe)  if(i->run_time_type == PIKE_T_MIXED)
f102d22000-04-19Henrik Grubbström (Grubba)  { assign_svalue((struct svalue *)GLOBAL_FROM_INT(tmp), Pike_fp->locals + arg2); }else{ assign_to_short_svalue((union anything *)GLOBAL_FROM_INT(tmp), i->run_time_type, Pike_fp->locals + arg2); } } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
1986622000-04-20Henrik Grubbström (Grubba) OPCODE2(F_GLOBAL_2_LOCAL,"local = global")
f102d22000-04-19Henrik Grubbström (Grubba) {
1986622000-04-20Henrik Grubbström (Grubba)  INT32 tmp = arg1 + Pike_fp->context.identifier_level;
a96ce92000-04-19Fredrik Hübinette (Hubbe)  free_svalue(Pike_fp->locals + arg2); low_object_index_no_free(Pike_fp->locals + arg2,
f102d22000-04-19Henrik Grubbström (Grubba)  Pike_fp->current_object, tmp); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE1(F_LOCAL_LVALUE, "& local") Pike_sp[0].type = T_LVALUE; Pike_sp[0].u.lval = Pike_fp->locals + arg1; Pike_sp[1].type = T_VOID; Pike_sp += 2; BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
a96ce92000-04-19Fredrik Hübinette (Hubbe) OPCODE2(F_LEXICAL_LOCAL,"lexical local")
f102d22000-04-19Henrik Grubbström (Grubba) {
a96ce92000-04-19Fredrik Hübinette (Hubbe)  struct pike_frame *f=Pike_fp; while(arg2--)
f102d22000-04-19Henrik Grubbström (Grubba)  { f=f->scope; if(!f) error("Lexical scope error.\n"); } push_svalue(f->locals + arg1); print_return_value(); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
a96ce92000-04-19Fredrik Hübinette (Hubbe) OPCODE2(F_LEXICAL_LOCAL_LVALUE,"&lexical local")
f102d22000-04-19Henrik Grubbström (Grubba) {
a96ce92000-04-19Fredrik Hübinette (Hubbe)  struct pike_frame *f=Pike_fp; while(arg2--)
f102d22000-04-19Henrik Grubbström (Grubba)  {
a96ce92000-04-19Fredrik Hübinette (Hubbe)  f=f->scope;
f102d22000-04-19Henrik Grubbström (Grubba)  if(!f) error("Lexical scope error.\n"); }
a96ce92000-04-19Fredrik Hübinette (Hubbe)  Pike_sp[0].type=T_LVALUE; Pike_sp[0].u.lval=f->locals+arg1; Pike_sp[1].type=T_VOID; Pike_sp+=2;
f102d22000-04-19Henrik Grubbström (Grubba) } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE1(F_ARRAY_LVALUE, "[ lvalues ]") f_aggregate(arg1*2); Pike_sp[-1].u.array->flags |= ARRAY_LVALUE; Pike_sp[-1].u.array->type_field |= BIT_UNFINISHED | BIT_MIXED; /* FIXME: Shouldn't a ref be added here? */ Pike_sp[0] = Pike_sp[-1]; Pike_sp[-1].type = T_ARRAY_LVALUE;
2026c22000-04-20Henrik Grubbström (Grubba)  dmalloc_touch_svalue(Pike_sp);
f102d22000-04-19Henrik Grubbström (Grubba)  Pike_sp++; BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE1(F_CLEAR_2_LOCAL, "clear 2 local")
7951942000-04-20Fredrik Hübinette (Hubbe)  free_svalues(Pike_fp->locals + arg1, 2, -1); Pike_fp->locals[arg1].type = PIKE_T_INT; Pike_fp->locals[arg1].subtype = 0; Pike_fp->locals[arg1].u.integer = 0; Pike_fp->locals[arg1+1].type = PIKE_T_INT; Pike_fp->locals[arg1+1].subtype = 0; Pike_fp->locals[arg1+1].u.integer = 0;
f102d22000-04-19Henrik Grubbström (Grubba) BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE1(F_CLEAR_4_LOCAL, "clear 4 local") { int e;
7951942000-04-20Fredrik Hübinette (Hubbe)  free_svalues(Pike_fp->locals + arg1, 4, -1);
f102d22000-04-19Henrik Grubbström (Grubba)  for(e = 0; e < 4; e++) {
7951942000-04-20Fredrik Hübinette (Hubbe)  Pike_fp->locals[arg1+e].type = PIKE_T_INT; Pike_fp->locals[arg1+e].subtype = 0; Pike_fp->locals[arg1+e].u.integer = 0;
f102d22000-04-19Henrik Grubbström (Grubba)  } } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE1(F_CLEAR_LOCAL, "clear local")
7951942000-04-20Fredrik Hübinette (Hubbe)  free_svalue(Pike_fp->locals + arg1); Pike_fp->locals[arg1].type = PIKE_T_INT; Pike_fp->locals[arg1].subtype = 0; Pike_fp->locals[arg1].u.integer = 0;
f102d22000-04-19Henrik Grubbström (Grubba) BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE1(F_INC_LOCAL, "++local")
7951942000-04-20Fredrik Hübinette (Hubbe)  if( (Pike_fp->locals[arg1].type == PIKE_T_INT)
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
7951942000-04-20Fredrik Hübinette (Hubbe)  && (!INT_TYPE_ADD_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1))
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif /* AUTO_BIGNUM */
f102d22000-04-19Henrik Grubbström (Grubba)  ) {
7951942000-04-20Fredrik Hübinette (Hubbe)  Pike_fp->locals[arg1].u.integer++; assign_svalue_no_free(Pike_sp++,Pike_fp->locals+arg1);
f102d22000-04-19Henrik Grubbström (Grubba)  } else {
7951942000-04-20Fredrik Hübinette (Hubbe)  assign_svalue_no_free(Pike_sp++,Pike_fp->locals+arg1);
f102d22000-04-19Henrik Grubbström (Grubba)  push_int(1); f_add(2);
7951942000-04-20Fredrik Hübinette (Hubbe)  assign_svalue(Pike_fp->locals+arg1,Pike_sp-1);
f102d22000-04-19Henrik Grubbström (Grubba)  } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
cc75b62000-04-21Henrik Grubbström (Grubba) OPCODE1(F_POST_INC_LOCAL, "local++") assign_svalue_no_free(Pike_sp++, Pike_fp->locals + arg1); if( (Pike_fp->locals[arg1].type == PIKE_T_INT) #ifdef AUTO_BIGNUM && (!INT_TYPE_ADD_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1)) #endif /* AUTO_BIGNUM */ ) { Pike_fp->locals[arg1].u.integer++; } else { assign_svalue_no_free(Pike_sp++, Pike_fp->locals + arg1); push_int(1); f_add(2); assign_svalue(Pike_fp->locals + arg1, Pike_sp-1); pop_stack(); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
cc75b62000-04-21Henrik Grubbström (Grubba) OPCODE1(F_INC_LOCAL_AND_POP, "++local and pop") if( (Pike_fp->locals[arg1].type == PIKE_T_INT)
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
cc75b62000-04-21Henrik Grubbström (Grubba)  && (!INT_TYPE_ADD_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1))
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif /* AUTO_BIGNUM */
cc75b62000-04-21Henrik Grubbström (Grubba)  ) { Pike_fp->locals[arg1].u.integer++; } else { assign_svalue_no_free(Pike_sp++, Pike_fp->locals + arg1); push_int(1); f_add(2); assign_svalue(Pike_fp->locals + arg1, Pike_sp-1); pop_stack(); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE1(F_DEC_LOCAL, "--local")
7951942000-04-20Fredrik Hübinette (Hubbe)  if( (Pike_fp->locals[arg1].type == PIKE_T_INT)
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
7951942000-04-20Fredrik Hübinette (Hubbe)  && (!INT_TYPE_SUB_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1))
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif /* AUTO_BIGNUM */
f102d22000-04-19Henrik Grubbström (Grubba)  ) {
7951942000-04-20Fredrik Hübinette (Hubbe)  Pike_fp->locals[arg1].u.integer--; assign_svalue_no_free(Pike_sp++,Pike_fp->locals+arg1);
f102d22000-04-19Henrik Grubbström (Grubba)  } else {
7951942000-04-20Fredrik Hübinette (Hubbe)  assign_svalue_no_free(Pike_sp++,Pike_fp->locals+arg1);
f102d22000-04-19Henrik Grubbström (Grubba)  push_int(1); o_subtract();
7951942000-04-20Fredrik Hübinette (Hubbe)  assign_svalue(Pike_fp->locals+arg1,Pike_sp-1);
f102d22000-04-19Henrik Grubbström (Grubba)  } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
cc75b62000-04-21Henrik Grubbström (Grubba) OPCODE1(F_POST_DEC_LOCAL, "local--") assign_svalue_no_free(Pike_sp++, Pike_fp->locals + arg1); if( (Pike_fp->locals[arg1].type == PIKE_T_INT) #ifdef AUTO_BIGNUM && (!INT_TYPE_SUB_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1)) #endif /* AUTO_BIGNUM */ ) { Pike_fp->locals[arg1].u.integer--; } else { assign_svalue_no_free(Pike_sp++, Pike_fp->locals + arg1); push_int(1); o_subtract(); assign_svalue(Pike_fp->locals + arg1, Pike_sp-1); pop_stack(); } /* Pike_fp->locals[instr].u.integer--; */ BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
cc75b62000-04-21Henrik Grubbström (Grubba) OPCODE1(F_DEC_LOCAL_AND_POP, "--local and pop") if( (Pike_fp->locals[arg1].type == PIKE_T_INT)
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
cc75b62000-04-21Henrik Grubbström (Grubba)  && (!INT_TYPE_SUB_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1))
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif /* AUTO_BIGNUM */
cc75b62000-04-21Henrik Grubbström (Grubba)  ) { Pike_fp->locals[arg1].u.integer--; } else { assign_svalue_no_free(Pike_sp++, Pike_fp->locals + arg1); push_int(1); o_subtract(); assign_svalue(Pike_fp->locals + arg1, Pike_sp-1); pop_stack(); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE0(F_LTOSVAL, "lvalue to svalue") lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++; BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE0(F_LTOSVAL2, "ltosval2") Pike_sp[0] = Pike_sp[-1]; Pike_sp[-1].type = PIKE_T_INT; Pike_sp++; lvalue_to_svalue_no_free(Pike_sp-2, Pike_sp-4); /* this is so that foo+=bar (and similar things) will be faster, this * is done by freeing the old reference to foo after it has been pushed * on the stack. That way foo can have only 1 reference if we are lucky, * and then the low array/multiset/mapping manipulation routines can be * destructive if they like */ if( (1 << Pike_sp[-2].type) & (BIT_ARRAY | BIT_MULTISET | BIT_MAPPING | BIT_STRING) ) { struct svalue s; s.type = PIKE_T_INT; s.subtype = 0; s.u.integer = 0; assign_lvalue(Pike_sp-4, &s); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE0(F_ADD_TO_AND_POP, "+= and pop") Pike_sp[0]=Pike_sp[-1]; Pike_sp[-1].type=PIKE_T_INT; Pike_sp++; lvalue_to_svalue_no_free(Pike_sp-2,Pike_sp-4); /* this is so that foo+=bar (and similar things) will be faster, this * is done by freeing the old reference to foo after it has been pushed * on the stack. That way foo can have only 1 reference if we are lucky, * and then the low array/multiset/mapping manipulation routines can be * destructive if they like */ if( (1 << Pike_sp[-2].type) & (BIT_ARRAY | BIT_MULTISET | BIT_MAPPING | BIT_STRING) ) { struct svalue s; s.type=PIKE_T_INT; s.subtype=0; s.u.integer=0; assign_lvalue(Pike_sp-4,&s); } f_add(2); assign_lvalue(Pike_sp-3,Pike_sp-1); pop_n_elems(3); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba) OPCODE1(F_GLOBAL_LVALUE, "& global") { struct identifier *i; INT32 tmp=arg1 + Pike_fp->context.identifier_level; if(!Pike_fp->current_object->prog) error("Cannot access global variables in destructed object.\n"); i=ID_FROM_INT(Pike_fp->current_object->prog, tmp);
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f102d22000-04-19Henrik Grubbström (Grubba)  if(!IDENTIFIER_IS_VARIABLE(i->identifier_flags)) error("Cannot re-assign functions or constants.\n");
87c7592000-04-18Fredrik Hübinette (Hubbe) 
2cd8ca2000-07-28Fredrik Hübinette (Hubbe)  if(i->run_time_type == PIKE_T_MIXED)
f102d22000-04-19Henrik Grubbström (Grubba)  { Pike_sp[0].type=T_LVALUE; Pike_sp[0].u.lval=(struct svalue *)GLOBAL_FROM_INT(tmp); }else{ Pike_sp[0].type=T_SHORT_LVALUE; Pike_sp[0].u.short_lval= (union anything *)GLOBAL_FROM_INT(tmp); Pike_sp[0].subtype=i->run_time_type; } Pike_sp[1].type=T_VOID; Pike_sp+=2; } BREAK;
a96ce92000-04-19Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_INC, "++x") { union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT); if(u
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
bac71b2000-04-19Henrik Grubbström (Grubba)  && !INT_TYPE_ADD_OVERFLOW(u->integer, 1)
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif
bac71b2000-04-19Henrik Grubbström (Grubba)  ) { instr=++ u->integer; pop_n_elems(2); push_int(u->integer); } else { lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++; push_int(1); f_add(2); assign_lvalue(Pike_sp-3, Pike_sp-1); assign_svalue(Pike_sp-3, Pike_sp-1); pop_n_elems(2); } } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_DEC, "--x") { union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT); if(u
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
bac71b2000-04-19Henrik Grubbström (Grubba)  && !INT_TYPE_SUB_OVERFLOW(u->integer, 1)
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif
bac71b2000-04-19Henrik Grubbström (Grubba)  ) { instr=-- u->integer; pop_n_elems(2); push_int(u->integer); } else { lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++; push_int(1); o_subtract(); assign_lvalue(Pike_sp-3, Pike_sp-1); assign_svalue(Pike_sp-3, Pike_sp-1); pop_n_elems(2); } } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_DEC_AND_POP, "x-- and pop") { union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT); if(u
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
bac71b2000-04-19Henrik Grubbström (Grubba)  && !INT_TYPE_SUB_OVERFLOW(u->integer, 1)
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif )
bac71b2000-04-19Henrik Grubbström (Grubba)  { instr=-- u->integer; pop_n_elems(2); }else{ lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++; push_int(1); o_subtract(); assign_lvalue(Pike_sp-3, Pike_sp-1); pop_n_elems(3); } } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_INC_AND_POP, "x++ and pop") { union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT); if(u
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
bac71b2000-04-19Henrik Grubbström (Grubba)  && !INT_TYPE_ADD_OVERFLOW(u->integer, 1)
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif
bac71b2000-04-19Henrik Grubbström (Grubba)  ) { instr=++ u->integer; pop_n_elems(2); } else { lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++; push_int(1); f_add(2); assign_lvalue(Pike_sp-3, Pike_sp-1); pop_n_elems(3); } } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_POST_INC, "x++") { union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT); if(u
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
bac71b2000-04-19Henrik Grubbström (Grubba)  && !INT_TYPE_ADD_OVERFLOW(u->integer, 1)
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif
bac71b2000-04-19Henrik Grubbström (Grubba)  ) { instr=u->integer ++; pop_n_elems(2); push_int(instr); } else { lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++; assign_svalue_no_free(Pike_sp,Pike_sp-1); Pike_sp++; push_int(1); f_add(2); assign_lvalue(Pike_sp-4, Pike_sp-1); assign_svalue(Pike_sp-4, Pike_sp-2); pop_n_elems(3); } } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_POST_DEC, "x--") { union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT); if(u
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
bac71b2000-04-19Henrik Grubbström (Grubba)  && !INT_TYPE_SUB_OVERFLOW(u->integer, 1)
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif
bac71b2000-04-19Henrik Grubbström (Grubba)  ) { instr=u->integer --; pop_n_elems(2); push_int(instr); } else { lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++; assign_svalue_no_free(Pike_sp,Pike_sp-1); Pike_sp++; push_int(1); o_subtract(); assign_lvalue(Pike_sp-4, Pike_sp-1); assign_svalue(Pike_sp-4, Pike_sp-2); pop_n_elems(3); } } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
a96ce92000-04-19Fredrik Hübinette (Hubbe) OPCODE1(F_ASSIGN_LOCAL,"assign local") assign_svalue(Pike_fp->locals+arg1,Pike_sp-1); BREAK;
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_ASSIGN, "assign") assign_lvalue(Pike_sp-3,Pike_sp-1); free_svalue(Pike_sp-3); free_svalue(Pike_sp-2); Pike_sp[-3]=Pike_sp[-1]; Pike_sp-=2; BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
a96ce92000-04-19Fredrik Hübinette (Hubbe) OPCODE2(F_APPLY_ASSIGN_LOCAL_AND_POP,"apply, assign local and pop") strict_apply_svalue(Pike_fp->context.prog->constants + arg1, Pike_sp - *--Pike_mark_sp ); free_svalue(Pike_fp->locals+arg2); Pike_fp->locals[arg2]=Pike_sp[-1]; Pike_sp--; BREAK; OPCODE2(F_APPLY_ASSIGN_LOCAL,"apply, assign local") strict_apply_svalue(Pike_fp->context.prog->constants + arg1, Pike_sp - *--Pike_mark_sp ); assign_svalue(Pike_fp->locals+arg2,Pike_sp-1); BREAK;
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_ASSIGN_AND_POP, "assign and pop") assign_lvalue(Pike_sp-3, Pike_sp-1); pop_n_elems(3); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f853ac2000-04-20Henrik Grubbström (Grubba) OPCODE1(F_ASSIGN_LOCAL_AND_POP, "assign local and pop") free_svalue(Pike_fp->locals + arg1); Pike_fp->locals[arg1] = Pike_sp[-1]; Pike_sp--; BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE1(F_ASSIGN_GLOBAL, "assign global") { struct identifier *i; INT32 tmp=arg1 + Pike_fp->context.identifier_level; if(!Pike_fp->current_object->prog) error("Cannot access global variables in destructed object.\n"); i=ID_FROM_INT(Pike_fp->current_object->prog, tmp); if(!IDENTIFIER_IS_VARIABLE(i->identifier_flags)) error("Cannot assign functions or constants.\n");
2cd8ca2000-07-28Fredrik Hübinette (Hubbe)  if(i->run_time_type == PIKE_T_MIXED)
bac71b2000-04-19Henrik Grubbström (Grubba)  { assign_svalue((struct svalue *)GLOBAL_FROM_INT(tmp), Pike_sp-1); }else{ assign_to_short_svalue((union anything *)GLOBAL_FROM_INT(tmp), i->run_time_type, Pike_sp-1); } } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE1(F_ASSIGN_GLOBAL_AND_POP, "assign global and pop") { struct identifier *i; INT32 tmp=arg1 + Pike_fp->context.identifier_level; if(!Pike_fp->current_object->prog) error("Cannot access global variables in destructed object.\n");
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba)  i=ID_FROM_INT(Pike_fp->current_object->prog, tmp); if(!IDENTIFIER_IS_VARIABLE(i->identifier_flags)) error("Cannot assign functions or constants.\n");
87c7592000-04-18Fredrik Hübinette (Hubbe) 
2cd8ca2000-07-28Fredrik Hübinette (Hubbe)  if(i->run_time_type == PIKE_T_MIXED)
bac71b2000-04-19Henrik Grubbström (Grubba)  { struct svalue *s=(struct svalue *)GLOBAL_FROM_INT(tmp); free_svalue(s); Pike_sp--; *s=*Pike_sp; }else{ assign_to_short_svalue((union anything *)GLOBAL_FROM_INT(tmp), i->run_time_type, Pike_sp-1); pop_stack(); } } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
a96ce92000-04-19Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) /* Stack machine stuff */ OPCODE0(F_POP_VALUE, "pop") pop_stack(); BREAK; OPCODE1(F_POP_N_ELEMS, "pop_n_elems") pop_n_elems(arg1); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
7951942000-04-20Fredrik Hübinette (Hubbe) OPCODE0_TAIL(F_MARK2,"mark mark") *(Pike_mark_sp++)=Pike_sp; OPCODE0(F_MARK,"mark") *(Pike_mark_sp++)=Pike_sp; BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
17f08c2000-07-06Fredrik Hübinette (Hubbe) OPCODE1(F_MARK_X, "mark Pike_sp-X")
bac71b2000-04-19Henrik Grubbström (Grubba)  *(Pike_mark_sp++)=Pike_sp-arg1; BREAK; OPCODE0(F_POP_MARK, "pop mark") --Pike_mark_sp; BREAK; OPCODE0(F_CLEAR_STRING_SUBTYPE, "clear string subtype") if(Pike_sp[-1].type==PIKE_T_STRING) Pike_sp[-1].subtype=0; BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe)  /* Jumps */
7951942000-04-20Fredrik Hübinette (Hubbe) OPCODE0_JUMP(F_BRANCH,"branch") DOJUMP(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
7951942000-04-20Fredrik Hübinette (Hubbe) OPCODE2(F_BRANCH_IF_NOT_LOCAL_ARROW,"branch if !local->x") { struct svalue tmp; tmp.type=PIKE_T_STRING; tmp.u.string=Pike_fp->context.prog->strings[arg1]; tmp.subtype=1; Pike_sp->type=PIKE_T_INT; Pike_sp++; index_no_free(Pike_sp-1,Pike_fp->locals+arg2, &tmp); print_return_value(); }
87c7592000-04-18Fredrik Hübinette (Hubbe)  /* Fall through */
7951942000-04-20Fredrik Hübinette (Hubbe) OPCODE0_TAILJUMP(F_BRANCH_WHEN_ZERO,"branch if zero") if(!IS_ZERO(Pike_sp-1)) { SKIPJUMP(); }else{ DOJUMP(); } pop_stack(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
7951942000-04-20Fredrik Hübinette (Hubbe) OPCODE0_JUMP(F_BRANCH_WHEN_NON_ZERO,"branch if not zero") if(IS_ZERO(Pike_sp-1)) { SKIPJUMP(); }else{ DOJUMP(); } pop_stack(); BREAK
87c7592000-04-18Fredrik Hübinette (Hubbe) 
7951942000-04-20Fredrik Hübinette (Hubbe) OPCODE1_JUMP(F_BRANCH_IF_LOCAL,"branch if local") if(IS_ZERO(Pike_fp->locals + arg1)) { SKIPJUMP(); }else{ DOJUMP(); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe)  CASE(F_BRANCH_IF_NOT_LOCAL); instr=GET_ARG(); if(!IS_ZERO(Pike_fp->locals + instr)) {
7951942000-04-20Fredrik Hübinette (Hubbe)  SKIPJUMP();
87c7592000-04-18Fredrik Hübinette (Hubbe)  }else{ DOJUMP(); } break; CJUMP(F_BRANCH_WHEN_EQ, is_eq); CJUMP(F_BRANCH_WHEN_NE,!is_eq); CJUMP(F_BRANCH_WHEN_LT, is_lt); CJUMP(F_BRANCH_WHEN_LE,!is_gt); CJUMP(F_BRANCH_WHEN_GT, is_gt); CJUMP(F_BRANCH_WHEN_GE,!is_lt); CASE(F_BRANCH_AND_POP_WHEN_ZERO); if(!IS_ZERO(Pike_sp-1)) {
7951942000-04-20Fredrik Hübinette (Hubbe)  SKIPJUMP();
87c7592000-04-18Fredrik Hübinette (Hubbe)  }else{ DOJUMP(); pop_stack(); } break; CASE(F_BRANCH_AND_POP_WHEN_NON_ZERO); if(IS_ZERO(Pike_sp-1)) {
7951942000-04-20Fredrik Hübinette (Hubbe)  SKIPJUMP();
87c7592000-04-18Fredrik Hübinette (Hubbe)  }else{ DOJUMP(); pop_stack(); } break; CASE(F_LAND); if(!IS_ZERO(Pike_sp-1)) {
7951942000-04-20Fredrik Hübinette (Hubbe)  SKIPJUMP();
87c7592000-04-18Fredrik Hübinette (Hubbe)  pop_stack(); }else{ DOJUMP(); } break; CASE(F_LOR); if(IS_ZERO(Pike_sp-1)) {
7951942000-04-20Fredrik Hübinette (Hubbe)  SKIPJUMP();
87c7592000-04-18Fredrik Hübinette (Hubbe)  pop_stack(); }else{ DOJUMP(); } break; CASE(F_EQ_OR); if(!is_eq(Pike_sp-2,Pike_sp-1)) { pop_n_elems(2);
7951942000-04-20Fredrik Hübinette (Hubbe)  SKIPJUMP();
87c7592000-04-18Fredrik Hübinette (Hubbe)  }else{ pop_n_elems(2); push_int(1); DOJUMP(); } break; CASE(F_EQ_AND); if(is_eq(Pike_sp-2,Pike_sp-1)) { pop_n_elems(2);
7951942000-04-20Fredrik Hübinette (Hubbe)  SKIPJUMP();
87c7592000-04-18Fredrik Hübinette (Hubbe)  }else{ pop_n_elems(2); push_int(0); DOJUMP(); } break; CASE(F_CATCH); if(o_catch(pc+sizeof(INT32))) return -1; /* There was a return inside the evaluated code */ else pc+=EXTRACT_INT(pc); break;
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_THROW_ZERO, "throw(0)") push_int(0); f_throw(1); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE1(F_SWITCH, "switch") { INT32 tmp; tmp=switch_lookup(Pike_fp->context.prog-> constants[arg1].sval.u.array,Pike_sp-1); pc=(unsigned char *)DO_ALIGN(pc,sizeof(INT32)); pc+=(tmp>=0 ? 1+tmp*2 : 2*~tmp) * sizeof(INT32); if(*(INT32*)pc < 0) fast_check_threads_etc(7); pc+=*(INT32*)pc; pop_stack(); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe)  /* FIXME: Does this need bignum tests? /Fixed - Hubbe */ LOOP(F_INC_LOOP, 1, <, is_lt); LOOP(F_DEC_LOOP, -1, >, is_gt); LOOP(F_INC_NEQ_LOOP, 1, !=, !is_eq); LOOP(F_DEC_NEQ_LOOP, -1, !=, !is_eq); CASE(F_FOREACH) /* array, lvalue, X, i */ { if(Pike_sp[-4].type != PIKE_T_ARRAY) PIKE_ERROR("foreach", "Bad argument 1.\n", Pike_sp-3, 1); if(Pike_sp[-1].u.integer < Pike_sp[-4].u.array->size) { fast_check_threads_etc(10); index_no_free(Pike_sp,Pike_sp-4,Pike_sp-1); Pike_sp++; assign_lvalue(Pike_sp-4, Pike_sp-1); free_svalue(Pike_sp-1); Pike_sp--; pc+=EXTRACT_INT(pc); Pike_sp[-1].u.integer++; }else{
7951942000-04-20Fredrik Hübinette (Hubbe)  SKIPJUMP();
87c7592000-04-18Fredrik Hübinette (Hubbe)  } break; } CASE(F_APPLY_AND_RETURN); { INT32 args=Pike_sp - *--Pike_mark_sp; /* fprintf(stderr,"%p >= %p\n",Pike_fp->expendible,Pike_sp-args); */ if(Pike_fp->expendible >= Pike_sp-args) { /* fprintf(stderr,"NOT EXPENDIBLE!\n"); */ MEMMOVE(Pike_sp-args+1,Pike_sp-args,args*sizeof(struct svalue)); Pike_sp++; Pike_sp[-args-1].type=PIKE_T_INT; } /* We sabotage the stack here */ assign_svalue(Pike_sp-args-1,&Pike_fp->context.prog->constants[GET_ARG()].sval); return args+1; }
6fd5172000-04-25Fredrik Hübinette (Hubbe) OPCODE1(F_CALL_LFUN_AND_RETURN,"call lfun & return") {
17f08c2000-07-06Fredrik Hübinette (Hubbe)  INT32 args=Pike_sp - *--Pike_mark_sp;
6fd5172000-04-25Fredrik Hübinette (Hubbe)  if(Pike_fp->expendible >= Pike_sp-args) { MEMMOVE(Pike_sp-args+1,Pike_sp-args,args*sizeof(struct svalue)); Pike_sp++; Pike_sp[-args-1].type=PIKE_T_INT; }else{ free_svalue(Pike_sp-args-1); } /* More stack sabotage */ Pike_sp[-args-1].u.object=Pike_fp->current_object; Pike_sp[-args-1].subtype=arg1+Pike_fp->context.identifier_level;
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
6fd5172000-04-25Fredrik Hübinette (Hubbe)  if(t_flag > 9) fprintf(stderr,"- IDENTIFIER_LEVEL: %d\n",Pike_fp->context.identifier_level);
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif
6fd5172000-04-25Fredrik Hübinette (Hubbe)  Pike_sp[-args-1].type=PIKE_T_FUNCTION; add_ref(Pike_fp->current_object); return args+1; } BREAK
87c7592000-04-18Fredrik Hübinette (Hubbe)  CASE(F_RETURN_LOCAL); instr=GET_ARG();
931b532000-06-20Fredrik Hübinette (Hubbe) #if defined(PIKE_DEBUG) && defined(GC2)
17f08c2000-07-06Fredrik Hübinette (Hubbe)  /* special case! Pike_interpreter.mark_stack may be invalid at the time we
931b532000-06-20Fredrik Hübinette (Hubbe)  * call return -1, so we must call the callbacks here to * prevent false alarms! /Hubbe */ if(d_flag>3) do_gc(); if(d_flag>4) do_debug(); check_threads_etc(); #endif
87c7592000-04-18Fredrik Hübinette (Hubbe)  if(Pike_fp->expendible <= Pike_fp->locals+instr) { pop_n_elems(Pike_sp-1 - (Pike_fp->locals+instr)); }else{ push_svalue(Pike_fp->locals+instr); } print_return_value();
931b532000-06-20Fredrik Hübinette (Hubbe)  return -1;
87c7592000-04-18Fredrik Hübinette (Hubbe)  CASE(F_RETURN_IF_TRUE);
931b532000-06-20Fredrik Hübinette (Hubbe)  if(!IS_ZERO(Pike_sp-1)) goto do_return;
87c7592000-04-18Fredrik Hübinette (Hubbe)  pop_stack(); break; CASE(F_RETURN_1); push_int(1); goto do_return; CASE(F_RETURN_0); push_int(0); goto do_return; CASE(F_RETURN); do_return: #if defined(PIKE_DEBUG) && defined(GC2) if(d_flag>3) do_gc(); if(d_flag>4) do_debug(); check_threads_etc(); #endif /* fall through */ CASE(F_DUMB_RETURN); return -1;
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_NEGATE, "unary minus") if(Pike_sp[-1].type == PIKE_T_INT) {
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
bac71b2000-04-19Henrik Grubbström (Grubba)  if(INT_TYPE_NEG_OVERFLOW(Pike_sp[-1].u.integer)) { convert_stack_top_to_bignum(); o_negate(); } else
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif /* AUTO_BIGNUM */
bac71b2000-04-19Henrik Grubbström (Grubba)  Pike_sp[-1].u.integer =- Pike_sp[-1].u.integer; } else if(Pike_sp[-1].type == PIKE_T_FLOAT) { Pike_sp[-1].u.float_number =- Pike_sp[-1].u.float_number; }else{ o_negate(); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_COMPL, "~") o_compl(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_NOT, "!") switch(Pike_sp[-1].type) { case PIKE_T_INT: Pike_sp[-1].u.integer =! Pike_sp[-1].u.integer; break;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba)  case PIKE_T_FUNCTION: case PIKE_T_OBJECT: if(IS_ZERO(Pike_sp-1)) { pop_stack(); push_int(1); }else{ pop_stack(); push_int(0); } break;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba)  default: free_svalue(Pike_sp-1); Pike_sp[-1].type=PIKE_T_INT; Pike_sp[-1].u.integer=0; } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_LSH, "<<") o_lsh(); BREAK; OPCODE0(F_RSH, ">>") o_rsh(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe)  COMPARISMENT(F_EQ, is_eq(Pike_sp-2,Pike_sp-1)); COMPARISMENT(F_NE,!is_eq(Pike_sp-2,Pike_sp-1)); COMPARISMENT(F_GT, is_gt(Pike_sp-2,Pike_sp-1)); COMPARISMENT(F_GE,!is_lt(Pike_sp-2,Pike_sp-1)); COMPARISMENT(F_LT, is_lt(Pike_sp-2,Pike_sp-1)); COMPARISMENT(F_LE,!is_gt(Pike_sp-2,Pike_sp-1));
f853ac2000-04-20Henrik Grubbström (Grubba) OPCODE0(F_ADD, "+") f_add(2); BREAK;
a2b70a2000-04-30Fredrik Hübinette (Hubbe) OPCODE0(F_ADD_INTS, "int+int")
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp[-1].type == T_INT && Pike_sp[-2].type == T_INT
a2b70a2000-04-30Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
17f08c2000-07-06Fredrik Hübinette (Hubbe)  && (!INT_TYPE_ADD_OVERFLOW(Pike_sp[-1].u.integer, Pike_sp[-2].u.integer))
a2b70a2000-04-30Fredrik Hübinette (Hubbe) #endif ) {
17f08c2000-07-06Fredrik Hübinette (Hubbe)  Pike_sp[-2].u.integer+=Pike_sp[-1].u.integer; Pike_sp--;
a2b70a2000-04-30Fredrik Hübinette (Hubbe)  }else{ f_add(2); } BREAK; OPCODE0(F_ADD_FLOATS, "float+float")
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp[-1].type == T_FLOAT && Pike_sp[-2].type == T_FLOAT)
a2b70a2000-04-30Fredrik Hübinette (Hubbe)  {
17f08c2000-07-06Fredrik Hübinette (Hubbe)  Pike_sp[-2].u.float_number+=Pike_sp[-1].u.float_number; Pike_sp--;
a2b70a2000-04-30Fredrik Hübinette (Hubbe)  }else{ f_add(2); } BREAK;
f853ac2000-04-20Henrik Grubbström (Grubba) OPCODE0(F_SUBTRACT, "-") o_subtract(); BREAK; OPCODE0(F_AND, "&") o_and(); BREAK; OPCODE0(F_OR, "|") o_or(); BREAK; OPCODE0(F_XOR, "^") o_xor(); BREAK; OPCODE0(F_MULTIPLY, "*") o_multiply(); BREAK; OPCODE0(F_DIVIDE, "/") o_divide(); BREAK; OPCODE0(F_MOD, "%") o_mod(); BREAK; OPCODE1(F_ADD_INT, "add integer")
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp[-1].type == T_INT
6fd5172000-04-25Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
17f08c2000-07-06Fredrik Hübinette (Hubbe)  && (!INT_TYPE_ADD_OVERFLOW(Pike_sp[-1].u.integer, arg1))
6fd5172000-04-25Fredrik Hübinette (Hubbe) #endif ) {
17f08c2000-07-06Fredrik Hübinette (Hubbe)  Pike_sp[-1].u.integer+=arg1;
6fd5172000-04-25Fredrik Hübinette (Hubbe)  }else{ push_int(arg1); f_add(2); }
f853ac2000-04-20Henrik Grubbström (Grubba) BREAK; OPCODE1(F_ADD_NEG_INT, "add -integer")
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp[-1].type == T_INT
6fd5172000-04-25Fredrik Hübinette (Hubbe) #ifdef AUTO_BIGNUM
17f08c2000-07-06Fredrik Hübinette (Hubbe)  && (!INT_TYPE_ADD_OVERFLOW(Pike_sp[-1].u.integer, -arg1))
6fd5172000-04-25Fredrik Hübinette (Hubbe) #endif ) {
17f08c2000-07-06Fredrik Hübinette (Hubbe)  Pike_sp[-1].u.integer-=arg1;
6fd5172000-04-25Fredrik Hübinette (Hubbe)  }else{ push_int(-arg1); f_add(2); }
f853ac2000-04-20Henrik Grubbström (Grubba) BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
9b22582000-04-18Henrik Grubbström (Grubba) OPCODE0(F_PUSH_ARRAY, "@") switch(Pike_sp[-1].type) { default: PIKE_ERROR("@", "Bad argument.\n", Pike_sp, 1); case PIKE_T_OBJECT: if(!Pike_sp[-1].u.object->prog || FIND_LFUN(Pike_sp[-1].u.object->prog,LFUN__VALUES) == -1) PIKE_ERROR("@", "Bad argument.\n", Pike_sp, 1); apply_lfun(Pike_sp[-1].u.object, LFUN__VALUES, 0); if(Pike_sp[-1].type != PIKE_T_ARRAY) error("Bad return type from o->_values() in @\n"); free_svalue(Pike_sp-2); Pike_sp[-2]=Pike_sp[-1]; Pike_sp--; break; case PIKE_T_ARRAY: break; } Pike_sp--; push_array_items(Pike_sp->u.array); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
50d1d62000-04-30Fredrik Hübinette (Hubbe) OPCODE2(F_LOCAL_LOCAL_INDEX, "local[local]")
9b22582000-04-18Henrik Grubbström (Grubba) { struct svalue *s=Pike_fp->locals+arg1; if(s->type == PIKE_T_STRING) s->subtype=0; Pike_sp++->type=PIKE_T_INT; index_no_free(Pike_sp-1,Pike_fp->locals+arg2,s); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
9b22582000-04-18Henrik Grubbström (Grubba) OPCODE1(F_LOCAL_INDEX, "local index") {
13cfa82000-04-18Henrik Grubbström (Grubba)  struct svalue tmp,*s=Pike_fp->locals+arg1;
9b22582000-04-18Henrik Grubbström (Grubba)  if(s->type == PIKE_T_STRING) s->subtype=0; index_no_free(&tmp,Pike_sp-1,s); free_svalue(Pike_sp-1); Pike_sp[-1]=tmp; } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
9b22582000-04-18Henrik Grubbström (Grubba) OPCODE2(F_GLOBAL_LOCAL_INDEX, "global[local]") { struct svalue tmp,*s; low_object_index_no_free(Pike_sp, Pike_fp->current_object, arg1 + Pike_fp->context.identifier_level); Pike_sp++; s=Pike_fp->locals+arg2; if(s->type == PIKE_T_STRING) s->subtype=0; index_no_free(&tmp,Pike_sp-1,s); free_svalue(Pike_sp-1); Pike_sp[-1]=tmp; } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
9b22582000-04-18Henrik Grubbström (Grubba) OPCODE2(F_LOCAL_ARROW, "local->x") { struct svalue tmp; tmp.type=PIKE_T_STRING; tmp.u.string=Pike_fp->context.prog->strings[arg1]; tmp.subtype=1; Pike_sp->type=PIKE_T_INT; Pike_sp++; index_no_free(Pike_sp-1,Pike_fp->locals+arg2, &tmp); print_return_value(); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
9b22582000-04-18Henrik Grubbström (Grubba) OPCODE1(F_ARROW, "->x") { struct svalue tmp,tmp2; tmp.type=PIKE_T_STRING; tmp.u.string=Pike_fp->context.prog->strings[arg1]; tmp.subtype=1; index_no_free(&tmp2, Pike_sp-1, &tmp); free_svalue(Pike_sp-1); Pike_sp[-1]=tmp2; print_return_value(); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
372a652000-04-18Henrik Grubbström (Grubba) OPCODE1(F_STRING_INDEX, "string index") { struct svalue tmp,tmp2; tmp.type=PIKE_T_STRING; tmp.u.string=Pike_fp->context.prog->strings[arg1]; tmp.subtype=0; index_no_free(&tmp2, Pike_sp-1, &tmp); free_svalue(Pike_sp-1); Pike_sp[-1]=tmp2; print_return_value(); } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe)  CASE(F_POS_INT_INDEX); push_int(GET_ARG()); print_return_value(); goto do_index; CASE(F_NEG_INT_INDEX); push_int(-GET_ARG()); print_return_value(); CASE(F_INDEX); do_index: { struct svalue s; index_no_free(&s,Pike_sp-2,Pike_sp-1); pop_n_elems(2); *Pike_sp=s; Pike_sp++; } print_return_value(); break;
a96ce92000-04-19Fredrik Hübinette (Hubbe) OPCODE2(F_MAGIC_INDEX, "::`[]") push_magic_index(magic_index_program, arg2, arg1);
372a652000-04-18Henrik Grubbström (Grubba) BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
a96ce92000-04-19Fredrik Hübinette (Hubbe) OPCODE2(F_MAGIC_SET_INDEX, "::`[]=") push_magic_index(magic_set_index_program, arg2, arg1);
372a652000-04-18Henrik Grubbström (Grubba) BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
372a652000-04-18Henrik Grubbström (Grubba) OPCODE0(F_CAST, "cast") f_cast(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba) OPCODE0(F_SOFT_CAST, "soft cast") /* Stack: type_string, value */
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
bac71b2000-04-19Henrik Grubbström (Grubba)  if (Pike_sp[-2].type != T_STRING) { /* FIXME: The type should really be T_TYPE... */ fatal("Argument 1 to soft_cast isn't a string!\n"); }
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif /* PIKE_DEBUG */
bac71b2000-04-19Henrik Grubbström (Grubba)  if (runtime_options & RUNTIME_CHECK_TYPES) { struct pike_string *sval_type = get_type_of_svalue(Pike_sp-1); if (!pike_types_le(sval_type, Pike_sp[-2].u.string)) { /* get_type_from_svalue() doesn't return a fully specified type * for array, mapping and multiset, so we perform a more lenient * check for them. */ if (!pike_types_le(sval_type, weak_type_string) || !match_types(sval_type, Pike_sp[-2].u.string)) { struct pike_string *t1; struct pike_string *t2; char *fname = "__soft-cast"; ONERROR tmp1; ONERROR tmp2; if (Pike_fp->current_object && Pike_fp->context.prog && Pike_fp->current_object->prog) { /* Look up the function-name */ struct pike_string *name = ID_FROM_INT(Pike_fp->current_object->prog, Pike_fp->fun)->name; if ((!name->size_shift) && (name->len < 100)) fname = name->str; } t1 = describe_type(Pike_sp[-2].u.string); SET_ONERROR(tmp1, do_free_string, t1);
87c7592000-04-18Fredrik Hübinette (Hubbe) 
bac71b2000-04-19Henrik Grubbström (Grubba)  t2 = describe_type(sval_type); SET_ONERROR(tmp2, do_free_string, t2);
87c7592000-04-18Fredrik Hübinette (Hubbe)  free_string(sval_type);
bac71b2000-04-19Henrik Grubbström (Grubba)  bad_arg_error(NULL, Pike_sp-1, 1, 1, t1->str, Pike_sp-1, "%s(): Soft cast failed. Expected %s, got %s\n", fname, t1->str, t2->str); /* NOT_REACHED */ UNSET_ONERROR(tmp2); UNSET_ONERROR(tmp1); free_string(t2); free_string(t1); } } free_string(sval_type);
87c7592000-04-18Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
bac71b2000-04-19Henrik Grubbström (Grubba)  if (d_flag > 2) { struct pike_string *t = describe_type(Pike_sp[-2].u.string); fprintf(stderr, "Soft cast to %s\n", t->str); free_string(t); }
87c7592000-04-18Fredrik Hübinette (Hubbe) #endif /* PIKE_DEBUG */
bac71b2000-04-19Henrik Grubbström (Grubba)  } stack_swap(); pop_stack(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
372a652000-04-18Henrik Grubbström (Grubba) OPCODE0(F_RANGE, "range") o_range(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
372a652000-04-18Henrik Grubbström (Grubba) OPCODE0(F_COPY_VALUE, "copy_value") { struct svalue tmp; copy_svalues_recursively_no_free(&tmp,Pike_sp-1,1,0); free_svalue(Pike_sp-1); Pike_sp[-1]=tmp; } BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
372a652000-04-18Henrik Grubbström (Grubba) OPCODE0(F_INDIRECT, "indirect") { struct svalue s; lvalue_to_svalue_no_free(&s,Pike_sp-2); if(s.type != PIKE_T_STRING) { pop_n_elems(2); *Pike_sp=s; Pike_sp++; }else{ struct object *o; o=low_clone(string_assignment_program); ((struct string_assignment_storage *)o->storage)->lval[0]=Pike_sp[-2]; ((struct string_assignment_storage *)o->storage)->lval[1]=Pike_sp[-1]; ((struct string_assignment_storage *)o->storage)->s=s.u.string; Pike_sp-=2; push_object(o); } } print_return_value(); BREAK; OPCODE0(F_SIZEOF, "sizeof") instr=pike_sizeof(Pike_sp-1); pop_stack(); push_int(instr); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
372a652000-04-18Henrik Grubbström (Grubba) OPCODE1(F_SIZEOF_LOCAL, "sizeof local") push_int(pike_sizeof(Pike_fp->locals+arg1)); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
372a652000-04-18Henrik Grubbström (Grubba) OPCODE1(F_SSCANF, "sscanf") o_sscanf(arg1); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
873ceb2000-04-30Fredrik Hübinette (Hubbe) OPCODE1(F_CALL_LFUN,"call lfun") apply_low(Pike_fp->current_object, arg1+Pike_fp->context.identifier_level, Pike_sp - *--Pike_mark_sp); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
873ceb2000-04-30Fredrik Hübinette (Hubbe) OPCODE1(F_CALL_LFUN_AND_POP,"call lfun & pop") apply_low(Pike_fp->current_object, arg1+Pike_fp->context.identifier_level, Pike_sp - *--Pike_mark_sp); pop_stack(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
873ceb2000-04-30Fredrik Hübinette (Hubbe) OPCODE1(F_MARK_APPLY,"mark apply") strict_apply_svalue(Pike_fp->context.prog->constants + arg1, 0); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe) 
873ceb2000-04-30Fredrik Hübinette (Hubbe) OPCODE1(F_MARK_APPLY_POP,"mark, apply & pop") strict_apply_svalue(Pike_fp->context.prog->constants + arg1, 0); pop_stack(); BREAK;
87c7592000-04-18Fredrik Hübinette (Hubbe)  CASE(F_APPLY); strict_apply_svalue(Pike_fp->context.prog->constants + GET_ARG(), Pike_sp - *--Pike_mark_sp ); break; CASE(F_APPLY_AND_POP); strict_apply_svalue(Pike_fp->context.prog->constants + GET_ARG(), Pike_sp - *--Pike_mark_sp ); pop_stack(); break; CASE(F_CALL_FUNCTION); mega_apply(APPLY_STACK,Pike_sp - *--Pike_mark_sp,0,0); break; CASE(F_CALL_FUNCTION_AND_RETURN); { INT32 args=Pike_sp - *--Pike_mark_sp; if(!args) PIKE_ERROR("`()", "Too few arguments.\n", Pike_sp, 0); switch(Pike_sp[-args].type) { case PIKE_T_INT: if (!Pike_sp[-args].u.integer) { PIKE_ERROR("`()", "Attempt to call the NULL-value\n", Pike_sp, args); } case PIKE_T_STRING: case PIKE_T_FLOAT: case PIKE_T_MAPPING: case PIKE_T_MULTISET: PIKE_ERROR("`()", "Attempt to call a non-function value.\n", Pike_sp, args); } return args; }
6fd5172000-04-25Fredrik Hübinette (Hubbe)  /* Assume that the number of arguments is correct */ OPCODE0_JUMP(F_RECUR,"recur") { int x,num_locals,args; char *addr;
17f08c2000-07-06Fredrik Hübinette (Hubbe)  struct svalue *expendible=Pike_fp->expendible; struct svalue *locals=Pike_fp->locals;
9106a42000-04-26Fredrik Hübinette (Hubbe)  struct svalue *save_sp, **save_mark_sp;
6fd5172000-04-25Fredrik Hübinette (Hubbe)  fast_check_threads_etc(6); check_c_stack(8192); check_stack(256);
17f08c2000-07-06Fredrik Hübinette (Hubbe)  save_sp=Pike_fp->expendible=Pike_fp->locals=*--Pike_mark_sp; args=Pike_sp-Pike_fp->locals; save_mark_sp=Pike_mark_sp;
6fd5172000-04-25Fredrik Hübinette (Hubbe)  addr=pc+EXTRACT_INT(pc);
873ceb2000-04-30Fredrik Hübinette (Hubbe)  num_locals=EXTRACT_UCHAR(addr-2);
6fd5172000-04-25Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG
873ceb2000-04-30Fredrik Hübinette (Hubbe)  if(args != EXTRACT_UCHAR(addr-1)) fatal("Wrong number of arguments in F_RECUR %d!=%d\n",args,EXTRACT_UCHAR(addr-1));
6fd5172000-04-25Fredrik Hübinette (Hubbe) #endif
17f08c2000-07-06Fredrik Hübinette (Hubbe)  clear_svalues(Pike_sp, num_locals - args); Pike_sp += num_locals - args;
6fd5172000-04-25Fredrik Hübinette (Hubbe)  x=eval_instruction(addr);
cfa1db2000-05-01Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_mark_sp < save_mark_sp) fatal("mark Pike_sp underflow in F_RECUR.\n");
cfa1db2000-05-01Fredrik Hübinette (Hubbe) #endif
17f08c2000-07-06Fredrik Hübinette (Hubbe)  Pike_mark_sp=save_mark_sp;
6fd5172000-04-25Fredrik Hübinette (Hubbe)  if(x!=-1) mega_apply(APPLY_STACK, x, 0,0); pc+=sizeof(INT32);
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(save_sp+1 < Pike_sp)
6fd5172000-04-25Fredrik Hübinette (Hubbe)  {
17f08c2000-07-06Fredrik Hübinette (Hubbe)  assign_svalue(save_sp,Pike_sp-1); pop_n_elems(Pike_sp-save_sp-1);
6fd5172000-04-25Fredrik Hübinette (Hubbe)  }
17f08c2000-07-06Fredrik Hübinette (Hubbe)  Pike_fp->expendible=expendible; Pike_fp->locals=locals;
6fd5172000-04-25Fredrik Hübinette (Hubbe)  print_return_value(); #ifdef PIKE_DEBUG
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp != save_sp+1) fatal("Stack whack in F_RECUR Pike_sp=%p, expected=%p\n",Pike_sp,save_sp+1);
6fd5172000-04-25Fredrik Hübinette (Hubbe) #endif } BREAK
873ceb2000-04-30Fredrik Hübinette (Hubbe) /* Assume that the number of arguments is correct */ OPCODE1_JUMP(F_COND_RECUR,"recur if not overloaded") { int x,num_locals,args; char *addr;
17f08c2000-07-06Fredrik Hübinette (Hubbe)  struct svalue *expendible=Pike_fp->expendible; struct svalue *locals=Pike_fp->locals;
873ceb2000-04-30Fredrik Hübinette (Hubbe)  struct svalue *save_sp, **save_mark_sp;
c313ac2000-05-01Fredrik Hübinette (Hubbe)  /* FIXME: * this test should actually test if this function is * overloaded or not. Currently it only tests if * this context is inherited or not. */
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_fp->current_object->prog != Pike_fp->context.prog)
873ceb2000-04-30Fredrik Hübinette (Hubbe)  { apply_low(Pike_fp->current_object, arg1+Pike_fp->context.identifier_level, Pike_sp - *--Pike_mark_sp);
6d73d82000-05-01Fredrik Hübinette (Hubbe)  pc+=sizeof(INT32);
873ceb2000-04-30Fredrik Hübinette (Hubbe)  }else{ fast_check_threads_etc(6); check_c_stack(8192); check_stack(256);
17f08c2000-07-06Fredrik Hübinette (Hubbe)  save_sp=Pike_fp->expendible=Pike_fp->locals=*--Pike_mark_sp; args=Pike_sp-Pike_fp->locals; save_mark_sp=Pike_mark_sp;
873ceb2000-04-30Fredrik Hübinette (Hubbe)  addr=pc+EXTRACT_INT(pc); num_locals=EXTRACT_UCHAR(addr-2); #ifdef PIKE_DEBUG if(args != EXTRACT_UCHAR(addr-1)) fatal("Wrong number of arguments in F_RECUR %d!=%d\n",args,EXTRACT_UCHAR(addr-1)); #endif
17f08c2000-07-06Fredrik Hübinette (Hubbe)  clear_svalues(Pike_sp, num_locals - args); Pike_sp += num_locals - args;
873ceb2000-04-30Fredrik Hübinette (Hubbe)  x=eval_instruction(addr);
cfa1db2000-05-01Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_mark_sp < save_mark_sp) fatal("mark Pike_sp underflow in F_RECUR.\n");
cfa1db2000-05-01Fredrik Hübinette (Hubbe) #endif
17f08c2000-07-06Fredrik Hübinette (Hubbe)  Pike_mark_sp=save_mark_sp;
873ceb2000-04-30Fredrik Hübinette (Hubbe)  if(x!=-1) mega_apply(APPLY_STACK, x, 0,0); pc+=sizeof(INT32);
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(save_sp+1 < Pike_sp)
873ceb2000-04-30Fredrik Hübinette (Hubbe)  {
17f08c2000-07-06Fredrik Hübinette (Hubbe)  assign_svalue(save_sp,Pike_sp-1); pop_n_elems(Pike_sp-save_sp-1);
873ceb2000-04-30Fredrik Hübinette (Hubbe)  }
17f08c2000-07-06Fredrik Hübinette (Hubbe)  Pike_fp->expendible=expendible; Pike_fp->locals=locals;
873ceb2000-04-30Fredrik Hübinette (Hubbe)  print_return_value(); #ifdef PIKE_DEBUG
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp != save_sp+1) fatal("Stack whack in F_RECUR Pike_sp=%p, expected=%p\n",Pike_sp,save_sp+1);
873ceb2000-04-30Fredrik Hübinette (Hubbe) #endif } } BREAK
6fd5172000-04-25Fredrik Hübinette (Hubbe) /* Assume that the number of arguments is correct */
17f08c2000-07-06Fredrik Hübinette (Hubbe) /* FIXME: adjust Pike_mark_sp */
6fd5172000-04-25Fredrik Hübinette (Hubbe) OPCODE0_JUMP(F_TAIL_RECUR,"tail recursion") { int x,num_locals; char *addr;
17f08c2000-07-06Fredrik Hübinette (Hubbe)  int args=Pike_sp - *--Pike_mark_sp;
6fd5172000-04-25Fredrik Hübinette (Hubbe)  fast_check_threads_etc(6); addr=pc+EXTRACT_INT(pc);
873ceb2000-04-30Fredrik Hübinette (Hubbe)  num_locals=EXTRACT_UCHAR(addr-2);
6fd5172000-04-25Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG
873ceb2000-04-30Fredrik Hübinette (Hubbe)  if(args != EXTRACT_UCHAR(addr-1)) fatal("Wrong number of arguments in F_TAIL_RECUR %d != %d\n",args,EXTRACT_UCHAR(addr-1));
6fd5172000-04-25Fredrik Hübinette (Hubbe) #endif
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp-args != Pike_fp->locals)
6fd5172000-04-25Fredrik Hübinette (Hubbe)  {
17f08c2000-07-06Fredrik Hübinette (Hubbe)  assign_svalues(Pike_fp->locals, Pike_sp-args, args, BIT_MIXED); pop_n_elems(Pike_sp - (Pike_fp->locals + args));
6fd5172000-04-25Fredrik Hübinette (Hubbe)  }
17f08c2000-07-06Fredrik Hübinette (Hubbe)  clear_svalues(Pike_sp, num_locals - args); Pike_sp += num_locals - args;
6fd5172000-04-25Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG
17f08c2000-07-06Fredrik Hübinette (Hubbe)  if(Pike_sp != Pike_fp->locals + Pike_fp->num_locals)
6fd5172000-04-25Fredrik Hübinette (Hubbe)  fatal("Sp whacked!\n"); #endif pc=addr; } BREAK