Main Page | Class List | Directories | File List | Class Members | File Members

interpret_functions.h

Go to the documentation of this file.
00001 /*
00002 || This file is part of Pike. For copyright information see COPYRIGHT.
00003 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
00004 || for more information.
00005 || $Id: interpret_functions.h,v 1.186 2005/06/20 12:58:23 grubba Exp $
00006 */
00007 
00008 /*
00009  * Opcode definitions for the interpreter.
00010  */
00011 
00012 #include "global.h"
00013 
00014 #undef CJUMP
00015 #undef AUTO_BIGNUM_LOOP_TEST
00016 #undef LOOP
00017 #undef COMPARISON
00018 #undef MKAPPLY
00019 #undef DO_CALL_BUILTIN
00020 
00021 #undef DO_IF_BIGNUM
00022 #ifdef AUTO_BIGNUM
00023 #define DO_IF_BIGNUM(CODE)      CODE
00024 #else /* !AUTO_BIGNUM */
00025 #define DO_IF_BIGNUM(CODE)
00026 #endif /* AUTO_BIGNUM */
00027 
00028 #undef DO_IF_ELSE_COMPUTED_GOTO
00029 #ifdef HAVE_COMPUTED_GOTO
00030 #define DO_IF_ELSE_COMPUTED_GOTO(A, B)  (A)
00031 #else /* !HAVE_COMPUTED_GOTO */
00032 #define DO_IF_ELSE_COMPUTED_GOTO(A, B)  (B)
00033 #endif /* HAVE_COMPUTED_GOTO */
00034 
00035 #ifdef GEN_PROTOS
00036 /* Used to generate the interpret_protos.h file. */
00037 #define OPCODE0(A, B, F, C)             OPCODE0(A, B, F) --- C
00038 #define OPCODE1(A, B, F, C)             OPCODE1(A, B, F) --- C
00039 #define OPCODE2(A, B, F, C)             OPCODE2(A, B, F) --- C
00040 #define OPCODE0_TAIL(A, B, F, C)        OPCODE0_TAIL(A, B, F) --- C
00041 #define OPCODE1_TAIL(A, B, F, C)        OPCODE1_TAIL(A, B, F) --- C
00042 #define OPCODE2_TAIL(A, B, F, C)        OPCODE2_TAIL(A, B, F) --- C
00043 #define OPCODE0_JUMP(A, B, F, C)        OPCODE0_JUMP(A, B, F) --- C
00044 #define OPCODE1_JUMP(A, B, F, C)        OPCODE1_JUMP(A, B, F) --- C
00045 #define OPCODE2_JUMP(A, B, F, C)        OPCODE2_JUMP(A, B, F) --- C
00046 #define OPCODE0_TAILJUMP(A, B, F, C)    OPCODE0_TAILJUMP(A, B, F) --- C
00047 #define OPCODE1_TAILJUMP(A, B, F, C)    OPCODE1_TAILJUMP(A, B, F) --- C
00048 #define OPCODE2_TAILJUMP(A, B, F, C)    OPCODE2_TAILJUMP(A, B, F) --- C
00049 #define OPCODE0_PTRJUMP(A, B, F, C)     OPCODE0_PTRJUMP(A, B, F) --- C
00050 #define OPCODE1_PTRJUMP(A, B, F, C)     OPCODE1_PTRJUMP(A, B, F) --- C
00051 #define OPCODE2_PTRJUMP(A, B, F, C)     OPCODE2_PTRJUMP(A, B, F) --- C
00052 #define OPCODE0_TAILPTRJUMP(A, B, F, C) OPCODE0_TAILPTRJUMP(A, B, F) --- C
00053 #define OPCODE1_TAILPTRJUMP(A, B, F, C) OPCODE1_TAILPTRJUMP(A, B, F) --- C
00054 #define OPCODE2_TAILPTRJUMP(A, B, F, C) OPCODE2_TAILPTRJUMP(A, B, F) --- C
00055 #define OPCODE0_RETURN(A, B, F, C)      OPCODE0_RETURN(A, B, F) --- C
00056 #define OPCODE1_RETURN(A, B, F, C)      OPCODE1_RETURN(A, B, F) --- C
00057 #define OPCODE2_RETURN(A, B, F, C)      OPCODE2_RETURN(A, B, F) --- C
00058 #define OPCODE0_TAILRETURN(A, B, F, C)  OPCODE0_TAILRETURN(A, B, F) --- C
00059 #define OPCODE1_TAILRETURN(A, B, F, C)  OPCODE1_TAILRETURN(A, B, F) --- C
00060 #define OPCODE2_TAILRETURN(A, B, F, C)  OPCODE2_TAILRETURN(A, B, F) --- C
00061 #define OPCODE0_BRANCH(A, B, F, C)      OPCODE0_BRANCH(A, B, F) --- C
00062 #define OPCODE1_BRANCH(A, B, F, C)      OPCODE1_BRANCH(A, B, F) --- C
00063 #define OPCODE2_BRANCH(A, B, F, C)      OPCODE2_BRANCH(A, B, F) --- C
00064 #define OPCODE0_TAILBRANCH(A, B, F, C)  OPCODE0_TAILBRANCH(A, B, F) --- C
00065 #define OPCODE1_TAILBRANCH(A, B, F, C)  OPCODE1_TAILBRANCH(A, B, F) --- C
00066 #define OPCODE2_TAILBRANCH(A, B, F, C)  OPCODE2_TAILBRANCH(A, B, F) --- C
00067 #define OPCODE0_ALIAS(A, B, F, C)       OPCODE0_ALIAS(A, B, F, C) --- FOO
00068 #define OPCODE1_ALIAS(A, B, F, C)       OPCODE1_ALIAS(A, B, F, C) --- FOO
00069 #define OPCODE2_ALIAS(A, B, F, C)       OPCODE2_ALIAS(A, B, F, C) --- FOO
00070 #endif /* GEN_PROTOS */
00071 
00072 #ifndef OPCODE0_ALIAS
00073 #define OPCODE0_ALIAS(A,B,C,D)  OPCODE0(A,B,C,{D();})
00074 #endif /* !OPCODE0_ALIAS */
00075 #ifndef OPCODE1_ALIAS
00076 #define OPCODE1_ALIAS(A,B,C,D)  OPCODE1(A,B,C,{D();})
00077 #endif /* !OPCODE1_ALIAS */
00078 #ifndef OPCODE2_ALIAS
00079 #define OPCODE2_ALIAS(A,B,C,D)  OPCODE2(A,B,C,{D();})
00080 #endif /* !OPCODE2_ALIAS */
00081 
00082 
00083 /*
00084 #ifndef PROG_COUNTER
00085 #define PROG_COUNTER pc
00086 #endif
00087 */
00088 
00089 #ifndef INTER_ESCAPE_CATCH
00090 #define INTER_ESCAPE_CATCH return -2
00091 #endif
00092 
00093 #ifndef INTER_RETURN
00094 #define INTER_RETURN return -1
00095 #endif
00096 
00097 /* BRANCH opcodes use these two to indicate whether the
00098  * branch should be taken or not.
00099  */
00100 #ifndef DO_BRANCH
00101 #define DO_BRANCH       DOJUMP
00102 #endif
00103 #ifndef DONT_BRANCH
00104 #define DONT_BRANCH     SKIPJUMP
00105 #endif
00106 
00107 #ifndef LOCAL_VAR
00108 #define LOCAL_VAR(X)    X
00109 #endif
00110 
00111 #ifndef OVERRIDE_JUMPS
00112 
00113 #undef GET_JUMP
00114 #undef SKIPJUMP
00115 #undef DOJUMP
00116 
00117 #ifdef PIKE_DEBUG
00118 
00119 #define GET_JUMP() (backlog[backlogp].arg=(                     \
00120   (Pike_interpreter.trace_level>3 ?                             \
00121      sprintf(trace_buffer, "-    Target = %+ld\n",              \
00122              (long)LOW_GET_JUMP()),                             \
00123      write_to_stderr(trace_buffer,strlen(trace_buffer)) : 0),   \
00124   LOW_GET_JUMP()))
00125 
00126 #define SKIPJUMP() (GET_JUMP(), LOW_SKIPJUMP())
00127 
00128 #else /* !PIKE_DEBUG */
00129 
00130 #define GET_JUMP() (/*write_to_stderr("GET_JUMP\n", 9),*/ LOW_GET_JUMP())
00131 #define SKIPJUMP() (/*write_to_stderr("SKIPJUMP\n", 9),*/ LOW_SKIPJUMP())
00132 
00133 #endif /* PIKE_DEBUG */
00134 
00135 #define DOJUMP() do { \
00136     PIKE_OPCODE_T *addr;                                                \
00137     INT32 tmp; \
00138     JUMP_SET_TO_PC_AT_NEXT (addr);                                      \
00139     tmp = GET_JUMP(); \
00140     SET_PROG_COUNTER(addr + tmp); \
00141     FETCH; \
00142     if(tmp < 0) \
00143       fast_check_threads_etc(6); \
00144   } while(0)
00145 
00146 #endif /* OVERRIDE_JUMPS */
00147 
00148 
00149 /* WARNING:
00150  * The surgeon general has stated that define code blocks
00151  * without do{}while() can be hazardous to your health.
00152  * However, in these cases it is required to handle break
00153  * properly. -Hubbe
00154  */
00155 #undef DO_JUMP_TO
00156 #define DO_JUMP_TO(NEWPC)       {       \
00157   SET_PROG_COUNTER(NEWPC);              \
00158   FETCH;                                \
00159   JUMP_DONE;                            \
00160 }
00161 
00162 #undef DO_DUMB_RETURN
00163 #define DO_DUMB_RETURN {                                \
00164   if(Pike_fp -> flags & PIKE_FRAME_RETURN_INTERNAL)     \
00165   {                                                     \
00166     int f=Pike_fp->flags;                               \
00167     if(f & PIKE_FRAME_RETURN_POP)                       \
00168        low_return_pop();                                \
00169      else                                               \
00170        low_return();                                    \
00171                                                         \
00172     DO_IF_DEBUG(if (Pike_interpreter.trace_level > 5)   \
00173       fprintf(stderr, "Returning to 0x%p\n",            \
00174               Pike_fp->return_addr));                   \
00175     DO_JUMP_TO(Pike_fp->return_addr);                   \
00176   }                                                     \
00177   DO_IF_DEBUG(if (Pike_interpreter.trace_level > 5)     \
00178     fprintf(stderr, "Inter return\n"));                 \
00179   INTER_RETURN;                                         \
00180 }
00181 
00182 #undef DO_RETURN
00183 #ifndef PIKE_DEBUG
00184 #define DO_RETURN DO_DUMB_RETURN
00185 #else
00186 #define DO_RETURN {                             \
00187   if(d_flag>3) do_gc(NULL, 0);                  \
00188   if(d_flag>4) do_debug();                      \
00189   DO_DUMB_RETURN;                               \
00190 }
00191 #endif
00192 
00193 #ifdef OPCODE_RETURN_JUMPADDR
00194 #define DO_JUMP_TO_NEXT do {                                            \
00195     PIKE_OPCODE_T *next_addr;                                           \
00196     JUMP_SET_TO_PC_AT_NEXT (next_addr);                                 \
00197     SET_PROG_COUNTER (next_addr);                                       \
00198     FETCH;                                                              \
00199     JUMP_DONE;                                                          \
00200   } while (0)
00201 #else  /* !OPCODE_RETURN_JUMPADDR */
00202 #define JUMP_SET_TO_PC_AT_NEXT(PC) ((PC) = PROG_COUNTER)
00203 #define DO_JUMP_TO_NEXT JUMP_DONE
00204 #endif  /* !OPCODE_RETURN_JUMPADDR */
00205 
00206 #undef DO_INDEX
00207 #define DO_INDEX do {                           \
00208     LOCAL_VAR(struct svalue tmp);               \
00209     index_no_free(&tmp,Pike_sp-2,Pike_sp-1);    \
00210     pop_2_elems();                              \
00211     move_svalue (Pike_sp, &tmp);                \
00212     Pike_sp++;                                  \
00213     print_return_value();                       \
00214   }while(0)
00215 
00216 
00217 OPCODE0(F_UNDEFINED, "push UNDEFINED", I_UPDATE_SP, {
00218   push_int(0);
00219   Pike_sp[-1].subtype=NUMBER_UNDEFINED;
00220 });
00221 
00222 OPCODE0(F_CONST0, "push 0", I_UPDATE_SP, {
00223   push_int(0);
00224 });
00225 
00226 OPCODE0(F_CONST1, "push 1", I_UPDATE_SP, {
00227   push_int(1);
00228 });
00229 
00230 
00231 OPCODE0(F_MARK_AND_CONST0, "mark & 0", I_UPDATE_SP|I_UPDATE_M_SP, {
00232   *(Pike_mark_sp++)=Pike_sp;
00233   push_int(0);
00234 });
00235 
00236 OPCODE0(F_MARK_AND_CONST1, "mark & 1", I_UPDATE_SP|I_UPDATE_M_SP, {
00237   *(Pike_mark_sp++)=Pike_sp;
00238   push_int(1);
00239 });
00240 
00241 OPCODE0(F_CONST_1,"push -1", I_UPDATE_SP, {
00242   push_int(-1);
00243 });
00244 
00245 OPCODE0(F_BIGNUM, "push 0x7fffffff", I_UPDATE_SP, {
00246   push_int(0x7fffffff);
00247 });
00248 
00249 OPCODE1(F_NUMBER, "push int", I_UPDATE_SP, {
00250   push_int(arg1);
00251 });
00252 
00253 /* always need to declare this opcode to make working dists */
00254 #if SIZEOF_INT_TYPE > 4
00255 OPCODE2(F_NUMBER64, "push 64-bit int", I_UPDATE_SP, {
00256    push_int( (INT_TYPE)
00257              (( ((unsigned INT_TYPE)arg1) << 32) 
00258               | ((unsigned INT32)arg2)) );
00259 });
00260 #else
00261 OPCODE2(F_NUMBER64, "push 64-bit int", I_UPDATE_SP, {
00262   Pike_error("F_NUMBER64: this opcode should never be used in your system\n");
00263 });
00264 #endif
00265 
00266 OPCODE1(F_NEG_NUMBER, "push -int", I_UPDATE_SP, {
00267   push_int(-arg1);
00268 });
00269 
00270 OPCODE1(F_CONSTANT, "constant", I_UPDATE_SP, {
00271   push_svalue(& Pike_fp->context.prog->constants[arg1].sval);
00272   print_return_value();
00273 });
00274 
00275 
00276 /* Generic swap instruction:
00277  * swaps the arg1 top values with the arg2 values beneath
00278  */
00279 OPCODE2(F_REARRANGE,"rearrange",0,{
00280   check_stack(arg2);
00281   MEMCPY(Pike_sp,Pike_sp-arg1-arg2,sizeof(struct svalue)*arg2);
00282   MEMMOVE(Pike_sp-arg1-arg2,Pike_sp-arg1,sizeof(struct svalue)*arg1);
00283   MEMCPY(Pike_sp-arg2,Pike_sp,sizeof(struct svalue)*arg2);
00284 });
00285 
00286 /* The rest of the basic 'push value' instructions */   
00287 
00288 OPCODE1_TAIL(F_MARK_AND_STRING, "mark & string", I_UPDATE_SP|I_UPDATE_M_SP, {
00289   *(Pike_mark_sp++)=Pike_sp;
00290 
00291   OPCODE1(F_STRING, "string", I_UPDATE_SP, {
00292     copy_shared_string(Pike_sp->u.string,Pike_fp->context.prog->strings[arg1]);
00293     Pike_sp->type=PIKE_T_STRING;
00294     Pike_sp->subtype=0;
00295     Pike_sp++;
00296     print_return_value();
00297   });
00298 });
00299 
00300 
00301 OPCODE1(F_ARROW_STRING, "->string", I_UPDATE_SP, {
00302   copy_shared_string(Pike_sp->u.string,Pike_fp->context.prog->strings[arg1]);
00303   Pike_sp->type=PIKE_T_STRING;
00304   Pike_sp->subtype=1; /* Magic */
00305   Pike_sp++;
00306   print_return_value();
00307 });
00308 
00309 OPCODE1(F_LOOKUP_LFUN, "->lfun", 0, {
00310   LOCAL_VAR(struct object *o);
00311   LOCAL_VAR(struct svalue tmp);
00312   LOCAL_VAR(struct program *p);
00313 
00314   if ((Pike_sp[-1].type == T_OBJECT) &&
00315       (p = (o = Pike_sp[-1].u.object)->prog) &&
00316       (FIND_LFUN(p = o->prog->inherits[Pike_sp[-1].subtype].prog,
00317                  LFUN_ARROW) == -1)) {
00318     int id = FIND_LFUN(p, arg1);
00319     if ((id != -1) &&
00320         (!(p->identifier_references[id].id_flags &
00321            (ID_STATIC|ID_PRIVATE|ID_HIDDEN)))) {
00322       id += o->prog->inherits[Pike_sp[-1].subtype].identifier_level;
00323       low_object_index_no_free(&tmp, o, id);
00324     } else {
00325       /* Not found. */
00326       tmp.type = T_INT;
00327       tmp.subtype = NUMBER_UNDEFINED;
00328       tmp.u.integer = 0;
00329     }
00330   } else {
00331     LOCAL_VAR(struct svalue tmp2);
00332     tmp2.type = PIKE_T_STRING;
00333     tmp2.u.string = lfun_strings[arg1];
00334     tmp2.subtype = 1;
00335     index_no_free(&tmp, Pike_sp-1, &tmp2);
00336   }
00337   free_svalue(Pike_sp-1);
00338   move_svalue (Pike_sp - 1, &tmp);
00339   print_return_value();
00340 });
00341 
00342 OPCODE1(F_LFUN, "local function", I_UPDATE_SP, {
00343   ref_push_function (Pike_fp->current_object,
00344                      arg1+Pike_fp->context.identifier_level);
00345   print_return_value();
00346 });
00347 
00348 OPCODE2(F_TRAMPOLINE, "trampoline", I_UPDATE_SP, {
00349   struct pike_frame *f=Pike_fp;
00350   DO_IF_DEBUG(INT32 arg2_ = arg2;)
00351   LOCAL_VAR(struct object *o);
00352   o = low_clone(pike_trampoline_program);
00353 
00354   while(arg2--) {
00355     DO_IF_DEBUG({
00356       if (!f->scope) {
00357         Pike_fatal("F_TRAMPOLINE %d, %d: Missing %d levels of scope!\n", 
00358               arg1, arg2_, arg2+1);
00359       }
00360     });
00361     f=f->scope;
00362   }
00363   add_ref( ((struct pike_trampoline *)(o->storage))->frame=f );
00364   ((struct pike_trampoline *)(o->storage))->func=arg1+Pike_fp->context.identifier_level;
00365   push_function(o, pike_trampoline_program->lfuns[LFUN_CALL]);
00366   print_return_value();
00367 });
00368 
00369 /* The not so basic 'push value' instructions */
00370 
00371 OPCODE1_TAIL(F_MARK_AND_GLOBAL, "mark & global", I_UPDATE_SP|I_UPDATE_M_SP, {
00372   *(Pike_mark_sp++)=Pike_sp;
00373 
00374   OPCODE1(F_GLOBAL, "global", I_UPDATE_SP, {
00375     low_index_current_object_no_free(Pike_sp, arg1);
00376     Pike_sp++;
00377     print_return_value();
00378   });
00379 });
00380 
00381 OPCODE2_TAIL(F_MARK_AND_EXTERNAL, "mark & external", I_UPDATE_SP|I_UPDATE_M_SP, {
00382   *(Pike_mark_sp++)=Pike_sp;
00383 
00384   OPCODE2(F_EXTERNAL,"external", I_UPDATE_SP, {
00385     LOCAL_VAR(struct external_variable_context loc);
00386 
00387     loc.o=Pike_fp->current_object;
00388     loc.parent_identifier=Pike_fp->fun;
00389     if (loc.o->prog)
00390       loc.inherit=INHERIT_FROM_INT(loc.o->prog, loc.parent_identifier);
00391     find_external_context(&loc, arg2);
00392 
00393     DO_IF_DEBUG({
00394       TRACE((5,"-   Identifier=%d Offset=%d\n",
00395              arg1,
00396              loc.inherit->identifier_level));
00397     });
00398 
00399     if (arg1 == IDREF_MAGIC_THIS)
00400       /* Special treatment to allow doing Foo::this on destructed
00401        * parent objects. */
00402       ref_push_object (loc.o);
00403     else {
00404       low_object_index_no_free(Pike_sp,
00405                                loc.o,
00406                                arg1 + loc.inherit->identifier_level);
00407       Pike_sp++;
00408     }
00409     print_return_value();
00410   });
00411 });
00412 
00413 OPCODE2(F_EXTERNAL_LVALUE, "& external", I_UPDATE_SP, {
00414   LOCAL_VAR(struct external_variable_context loc);
00415 
00416   loc.o=Pike_fp->current_object;
00417   loc.parent_identifier=Pike_fp->fun;
00418   if (loc.o->prog)
00419     loc.inherit=INHERIT_FROM_INT(loc.o->prog, loc.parent_identifier);
00420   find_external_context(&loc, arg2);
00421 
00422   if (!loc.o->prog)
00423     Pike_error ("Cannot access variable in destructed parent object.\n");
00424 
00425   DO_IF_DEBUG({
00426     TRACE((5,"-   Identifier=%d Offset=%d\n",
00427            arg1,
00428            loc.inherit->identifier_level));
00429   });
00430 
00431   ref_push_object(loc.o);
00432   push_obj_index(arg1 + loc.inherit->identifier_level);
00433 });
00434 
00435 OPCODE1(F_MARK_AND_LOCAL, "mark & local", I_UPDATE_SP|I_UPDATE_M_SP, {
00436   *(Pike_mark_sp++) = Pike_sp;
00437   push_svalue( Pike_fp->locals + arg1);
00438   print_return_value();
00439 });
00440 
00441 OPCODE1(F_LOCAL, "local", I_UPDATE_SP, {
00442   push_svalue( Pike_fp->locals + arg1);
00443   print_return_value();
00444 });
00445 
00446 OPCODE2(F_2_LOCALS, "2 locals", I_UPDATE_SP, {
00447   push_svalue( Pike_fp->locals + arg1);
00448   print_return_value();
00449   push_svalue( Pike_fp->locals + arg2);
00450   print_return_value();
00451 });
00452 
00453 OPCODE2(F_LOCAL_2_LOCAL, "local = local", 0, {
00454   assign_svalue(Pike_fp->locals + arg1, Pike_fp->locals + arg2);
00455 });
00456 
00457 OPCODE2(F_LOCAL_2_GLOBAL, "global = local", 0, {
00458   object_low_set_index(Pike_fp->current_object,
00459                        arg1 + Pike_fp->context.identifier_level,
00460                        Pike_fp->locals + arg2);
00461 });
00462 
00463 OPCODE2(F_GLOBAL_2_LOCAL, "local = global", 0, {
00464   free_svalue(Pike_fp->locals + arg2);
00465   low_index_current_object_no_free(Pike_fp->locals + arg2, arg1);
00466 });
00467 
00468 OPCODE1(F_LOCAL_LVALUE, "& local", I_UPDATE_SP, {
00469   Pike_sp[0].type = T_SVALUE_PTR;
00470   Pike_sp[0].u.lval = Pike_fp->locals + arg1;
00471   Pike_sp[1].type = T_VOID;
00472   Pike_sp += 2;
00473 });
00474 
00475 OPCODE2(F_LEXICAL_LOCAL, "lexical local", I_UPDATE_SP, {
00476   struct pike_frame *f=Pike_fp;
00477   while(arg2--)
00478   {
00479     f=f->scope;
00480     if(!f) Pike_error("Lexical scope error.\n");
00481   }
00482   push_svalue(f->locals + arg1);
00483   print_return_value();
00484 });
00485 
00486 OPCODE2(F_LEXICAL_LOCAL_LVALUE, "&lexical local", I_UPDATE_SP, {
00487   struct pike_frame *f=Pike_fp;
00488   while(arg2--)
00489   {
00490     f=f->scope;
00491     if(!f) Pike_error("Lexical scope error.\n");
00492   }
00493   Pike_sp[0].type=T_SVALUE_PTR;
00494   Pike_sp[0].u.lval=f->locals+arg1;
00495   Pike_sp[1].type=T_VOID;
00496   Pike_sp+=2;
00497 });
00498 
00499 OPCODE1(F_ARRAY_LVALUE, "[ lvalues ]", I_UPDATE_SP, {
00500   f_aggregate(arg1*2);
00501   Pike_sp[-1].u.array->flags |= ARRAY_LVALUE;
00502   Pike_sp[-1].u.array->type_field |= BIT_UNFINISHED | BIT_MIXED;
00503   /* FIXME: Shouldn't a ref be added here? */
00504   move_svalue (Pike_sp, Pike_sp - 1);
00505   Pike_sp[-1].type = T_ARRAY_LVALUE;
00506   Pike_sp++;
00507 });
00508 
00509 OPCODE1(F_CLEAR_2_LOCAL, "clear 2 local", 0, {
00510   free_mixed_svalues(Pike_fp->locals + arg1, 2);
00511   Pike_fp->locals[arg1].type = PIKE_T_INT;
00512   Pike_fp->locals[arg1].subtype = NUMBER_NUMBER;
00513   Pike_fp->locals[arg1].u.integer = 0;
00514   Pike_fp->locals[arg1+1].type = PIKE_T_INT;
00515   Pike_fp->locals[arg1+1].subtype = NUMBER_NUMBER;
00516   Pike_fp->locals[arg1+1].u.integer = 0;
00517 });
00518 
00519 OPCODE1(F_CLEAR_4_LOCAL, "clear 4 local", 0, {
00520   int e;
00521   free_mixed_svalues(Pike_fp->locals + arg1, 4);
00522   for(e = 0; e < 4; e++)
00523   {
00524     Pike_fp->locals[arg1+e].type = PIKE_T_INT;
00525     Pike_fp->locals[arg1+e].subtype = NUMBER_NUMBER;
00526     Pike_fp->locals[arg1+e].u.integer = 0;
00527   }
00528 });
00529 
00530 OPCODE1(F_CLEAR_LOCAL, "clear local", 0, {
00531   free_svalue(Pike_fp->locals + arg1);
00532   Pike_fp->locals[arg1].type = PIKE_T_INT;
00533   Pike_fp->locals[arg1].subtype = NUMBER_NUMBER;
00534   Pike_fp->locals[arg1].u.integer = 0;
00535 });
00536 
00537 OPCODE1(F_INC_LOCAL, "++local", I_UPDATE_SP, {
00538   if( (Pike_fp->locals[arg1].type == PIKE_T_INT)
00539       DO_IF_BIGNUM(
00540       && (!INT_TYPE_ADD_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1))
00541       )
00542       )
00543   {
00544     push_int(++(Pike_fp->locals[arg1].u.integer));
00545     Pike_fp->locals[arg1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
00546   } else {
00547     push_svalue(Pike_fp->locals+arg1);
00548     push_int(1);
00549     f_add(2);
00550     assign_svalue(Pike_fp->locals+arg1,Pike_sp-1);
00551   }
00552 });
00553 
00554 OPCODE1(F_POST_INC_LOCAL, "local++", I_UPDATE_SP, {
00555   push_svalue( Pike_fp->locals + arg1);
00556 
00557   if( (Pike_fp->locals[arg1].type == PIKE_T_INT)
00558       DO_IF_BIGNUM(
00559       && (!INT_TYPE_ADD_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1))
00560       )
00561       )
00562   {
00563     Pike_fp->locals[arg1].u.integer++;
00564     Pike_fp->locals[arg1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
00565   } else {
00566     push_svalue(Pike_fp->locals + arg1);
00567     push_int(1);
00568     f_add(2);
00569     stack_pop_to(Pike_fp->locals + arg1);
00570   }
00571 });
00572 
00573 OPCODE1(F_INC_LOCAL_AND_POP, "++local and pop", 0, {
00574   if( (Pike_fp->locals[arg1].type == PIKE_T_INT)
00575       DO_IF_BIGNUM(
00576       && (!INT_TYPE_ADD_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1))
00577       )
00578       )
00579   {
00580     Pike_fp->locals[arg1].u.integer++;
00581     Pike_fp->locals[arg1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
00582   } else {
00583     push_svalue( Pike_fp->locals + arg1);
00584     push_int(1);
00585     f_add(2);
00586     stack_pop_to(Pike_fp->locals + arg1);
00587   }
00588 });
00589 
00590 OPCODE1(F_DEC_LOCAL, "--local", I_UPDATE_SP, {
00591   if( (Pike_fp->locals[arg1].type == PIKE_T_INT)
00592       DO_IF_BIGNUM(
00593       && (!INT_TYPE_SUB_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1))
00594       )
00595       )
00596   {
00597     push_int(--(Pike_fp->locals[arg1].u.integer));
00598     Pike_fp->locals[arg1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
00599   } else {
00600     push_svalue(Pike_fp->locals+arg1);
00601     push_int(1);
00602     o_subtract();
00603     assign_svalue(Pike_fp->locals+arg1,Pike_sp-1);
00604   }
00605 });
00606 
00607 OPCODE1(F_POST_DEC_LOCAL, "local--", I_UPDATE_SP, {
00608   push_svalue( Pike_fp->locals + arg1);
00609 
00610   if( (Pike_fp->locals[arg1].type == PIKE_T_INT)
00611       DO_IF_BIGNUM(
00612       && (!INT_TYPE_SUB_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1))
00613       )
00614       )
00615   {
00616     Pike_fp->locals[arg1].u.integer--;
00617     Pike_fp->locals[arg1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
00618   } else {
00619     push_svalue(Pike_fp->locals + arg1);
00620     push_int(1);
00621     o_subtract();
00622     stack_pop_to(Pike_fp->locals + arg1);
00623   }
00624 });
00625 
00626 OPCODE1(F_DEC_LOCAL_AND_POP, "--local and pop", 0, {
00627   if( (Pike_fp->locals[arg1].type == PIKE_T_INT)
00628       DO_IF_BIGNUM(
00629       && (!INT_TYPE_SUB_OVERFLOW(Pike_fp->locals[arg1].u.integer, 1))
00630       )
00631       )
00632   {
00633     Pike_fp->locals[arg1].u.integer--;
00634     Pike_fp->locals[arg1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
00635   } else {
00636     push_svalue(Pike_fp->locals + arg1);
00637     push_int(1);
00638     o_subtract();
00639     stack_pop_to(Pike_fp->locals + arg1);
00640   }
00641 });
00642 
00643 OPCODE0(F_LTOSVAL, "lvalue to svalue", I_UPDATE_SP, {
00644   dmalloc_touch_svalue(Pike_sp-2);
00645   dmalloc_touch_svalue(Pike_sp-1);
00646   lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2);
00647   Pike_sp++;
00648   print_return_value();
00649 });
00650 
00651 OPCODE0(F_LTOSVAL2, "ltosval2", I_UPDATE_SP, {
00652   dmalloc_touch_svalue(Pike_sp-3);
00653   dmalloc_touch_svalue(Pike_sp-2);
00654   dmalloc_touch_svalue(Pike_sp-1);
00655 
00656   move_svalue (Pike_sp, Pike_sp - 1);
00657   Pike_sp[-1].type = PIKE_T_INT;
00658   Pike_sp++;
00659   lvalue_to_svalue_no_free(Pike_sp-2, Pike_sp-4);
00660   /* This is so that foo+=bar (and similar things) will be faster.
00661    * It's done by freeing the old reference to foo after it has been
00662    * pushed on the stack. That way foo can have only 1 reference if we
00663    * are lucky, and then the low array/multiset/mapping manipulation
00664    * routines can be destructive if they like.
00665    */
00666   if( (1 << Pike_sp[-2].type) &
00667       (BIT_ARRAY | BIT_MULTISET | BIT_MAPPING | BIT_STRING) )
00668   {
00669     LOCAL_VAR(struct svalue tmp);
00670     tmp.type = PIKE_T_INT;
00671     tmp.subtype = NUMBER_NUMBER;
00672     tmp.u.integer = 0;
00673     assign_lvalue(Pike_sp-4, &tmp);
00674   }
00675 });
00676 
00677 OPCODE0(F_LTOSVAL3, "ltosval3", I_UPDATE_SP, {
00678   dmalloc_touch_svalue(Pike_sp-4);
00679   dmalloc_touch_svalue(Pike_sp-3);
00680   dmalloc_touch_svalue(Pike_sp-2);
00681   dmalloc_touch_svalue(Pike_sp-1);
00682 
00683   move_svalue (Pike_sp, Pike_sp - 1);
00684   move_svalue (Pike_sp - 1, Pike_sp - 2);
00685   Pike_sp[-2].type = PIKE_T_INT;
00686   Pike_sp++;
00687   lvalue_to_svalue_no_free(Pike_sp-3, Pike_sp-5);
00688 
00689   /* This is so that foo=foo[x..y] (and similar things) will be faster.
00690    * It's done by freeing the old reference to foo after it has been
00691    * pushed on the stack. That way foo can have only 1 reference if we
00692    * are lucky, and then the low array/multiset/mapping manipulation
00693    * routines can be destructive if they like.
00694    */
00695   if( (1 << Pike_sp[-3].type) &
00696       (BIT_ARRAY | BIT_MULTISET | BIT_MAPPING | BIT_STRING) )
00697   {
00698     LOCAL_VAR(struct svalue tmp);
00699     tmp.type = PIKE_T_INT;
00700     tmp.subtype = NUMBER_NUMBER;
00701     tmp.u.integer = 0;
00702     assign_lvalue(Pike_sp-5, &tmp);
00703   }
00704 });
00705 
00706 OPCODE0(F_LTOSVAL1, "ltosval1", I_UPDATE_SP, {
00707   dmalloc_touch_svalue(Pike_sp-2);
00708   dmalloc_touch_svalue(Pike_sp-1);
00709 
00710   lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2);
00711   Pike_sp++;
00712 
00713   /* See ltosval3. This opcode is used e.g. in foo = foo[..] where no
00714    * bound arguments are pushed on the stack. */
00715   if( (1 << Pike_sp[-1].type) &
00716       (BIT_ARRAY | BIT_MULTISET | BIT_MAPPING | BIT_STRING) )
00717   {
00718     LOCAL_VAR(struct svalue tmp);
00719     tmp.type = PIKE_T_INT;
00720     tmp.subtype = NUMBER_NUMBER;
00721     tmp.u.integer = 0;
00722     assign_lvalue(Pike_sp-3, &tmp);
00723   }
00724 });
00725 
00726 OPCODE0(F_ADD_TO, "+=", I_UPDATE_SP, {
00727   move_svalue (Pike_sp, Pike_sp - 1);
00728   Pike_sp[-1].type=PIKE_T_INT;
00729   Pike_sp++;
00730   lvalue_to_svalue_no_free(Pike_sp-2,Pike_sp-4);
00731 
00732   if( Pike_sp[-1].type == PIKE_T_INT &&
00733       Pike_sp[-2].type == PIKE_T_INT  )
00734   {
00735     DO_IF_BIGNUM(
00736     if(!INT_TYPE_ADD_OVERFLOW(Pike_sp[-1].u.integer, Pike_sp[-2].u.integer))
00737     )
00738     {
00739       /* Optimization for a rather common case. Makes it 30% faster. */
00740       INT_TYPE val = (Pike_sp[-1].u.integer += Pike_sp[-2].u.integer);
00741       Pike_sp[-1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
00742       assign_lvalue(Pike_sp-4,Pike_sp-1);
00743       Pike_sp-=2;
00744       pop_2_elems();
00745       push_int(val);
00746       goto add_to_done;
00747     }
00748   }
00749   /* This is so that foo+=bar (and similar things) will be faster.
00750    * It's done by freeing the old reference to foo after it has been
00751    * pushed on the stack. That way foo can have only 1 reference if we
00752    * are lucky, and then the low array/multiset/mapping manipulation
00753    * routines can be destructive if they like.
00754    */
00755   if( (1 << Pike_sp[-2].type) &
00756       (BIT_ARRAY | BIT_MULTISET | BIT_MAPPING | BIT_STRING) )
00757   {
00758     LOCAL_VAR(struct svalue tmp);
00759     tmp.type=PIKE_T_INT;
00760     tmp.subtype=NUMBER_NUMBER;
00761     tmp.u.integer=0;
00762     assign_lvalue(Pike_sp-4, &tmp);
00763   } else if (Pike_sp[-2].type == T_OBJECT) {
00764     /* One ref in the lvalue, and one on the stack. */
00765     int i;
00766     LOCAL_VAR(struct object *o);
00767     LOCAL_VAR(struct program *p);
00768     if((o = Pike_sp[-2].u.object)->refs <= 2 &&
00769        (p = o->prog) &&
00770        (i = FIND_LFUN(p->inherits[Pike_sp[-2].subtype].prog,
00771                       LFUN_ADD_EQ)) != -1)
00772     {
00773       apply_low(o, i + p->inherits[Pike_sp[-2].subtype].identifier_level, 1);
00774       /* NB: The lvalue already contains the object, so
00775        *     no need to reassign it.
00776        */
00777       pop_stack();
00778       stack_pop_2_elems_keep_top();
00779       goto add_to_done;
00780     }
00781   }
00782   f_add(2);
00783   assign_lvalue(Pike_sp-3,Pike_sp-1);
00784   stack_pop_2_elems_keep_top();
00785  add_to_done:
00786    ; /* make gcc happy */
00787 });
00788 
00789 OPCODE0(F_ADD_TO_AND_POP, "+= and pop", I_UPDATE_SP, {
00790   move_svalue (Pike_sp, Pike_sp - 1);
00791   Pike_sp[-1].type=PIKE_T_INT;
00792   Pike_sp++;
00793   lvalue_to_svalue_no_free(Pike_sp-2,Pike_sp-4);
00794 
00795   if( Pike_sp[-1].type == PIKE_T_INT &&
00796       Pike_sp[-2].type == PIKE_T_INT  )
00797   {
00798     DO_IF_BIGNUM(
00799     if(!INT_TYPE_ADD_OVERFLOW(Pike_sp[-1].u.integer, Pike_sp[-2].u.integer))
00800     )
00801     {
00802       /* Optimization for a rather common case. Makes it 30% faster. */
00803       Pike_sp[-1].u.integer += Pike_sp[-2].u.integer;
00804       Pike_sp[-1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
00805       assign_lvalue(Pike_sp-4,Pike_sp-1);
00806       Pike_sp-=2;
00807       pop_2_elems();
00808       goto add_to_and_pop_done;
00809     }
00810   }
00811   /* This is so that foo+=bar (and similar things) will be faster.
00812    * It's done by freeing the old reference to foo after it has been
00813    * pushed on the stack. That way foo can have only 1 reference if we
00814    * are lucky, and then the low array/multiset/mapping manipulation
00815    * routines can be destructive if they like.
00816    */
00817   if( (1 << Pike_sp[-2].type) &
00818       (BIT_ARRAY | BIT_MULTISET | BIT_MAPPING | BIT_STRING) )
00819   {
00820     LOCAL_VAR(struct svalue tmp);
00821     tmp.type=PIKE_T_INT;
00822     tmp.subtype=NUMBER_NUMBER;
00823     tmp.u.integer=0;
00824     assign_lvalue(Pike_sp-4, &tmp);
00825   } else if (Pike_sp[-2].type == PIKE_T_OBJECT) {
00826     /* One ref in the lvalue, and one on the stack. */
00827     int i;
00828     LOCAL_VAR(struct object *o);
00829     LOCAL_VAR(struct program *p);
00830     if((o = Pike_sp[-2].u.object)->refs <= 2 &&
00831        (p = o->prog) &&
00832        (i = FIND_LFUN(p->inherits[Pike_sp[-2].subtype].prog,
00833                       LFUN_ADD_EQ)) != -1)
00834     {
00835       apply_low(o, i + p->inherits[Pike_sp[-2].subtype].identifier_level, 1);
00836       /* NB: The lvalue already contains the object, so
00837        *     no need to reassign it.
00838        */
00839       pop_n_elems(4);
00840       goto add_to_and_pop_done;
00841     }
00842   }
00843   f_add(2);
00844   assign_lvalue(Pike_sp-3,Pike_sp-1);
00845   pop_n_elems(3);
00846  add_to_and_pop_done:
00847    ; /* make gcc happy */
00848 });
00849 
00850 OPCODE1(F_GLOBAL_LVALUE, "& global", I_UPDATE_SP, {
00851   ref_push_object(Pike_fp->current_object);
00852   push_obj_index(arg1 + Pike_fp->context.identifier_level);
00853 });
00854 
00855 OPCODE0(F_INC, "++x", I_UPDATE_SP, {
00856   union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT);
00857   if(u
00858      DO_IF_BIGNUM(
00859      && !INT_TYPE_ADD_OVERFLOW(u->integer, 1)
00860      )
00861      )
00862   {
00863     INT_TYPE val = ++u->integer;
00864     pop_2_elems();
00865     push_int(val);
00866   } else {
00867     lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++;
00868     push_int(1);
00869     f_add(2);
00870     assign_lvalue(Pike_sp-3, Pike_sp-1);
00871     stack_pop_2_elems_keep_top();
00872   }
00873 });
00874 
00875 OPCODE0(F_DEC, "--x", I_UPDATE_SP, {
00876   union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT);
00877   if(u
00878      DO_IF_BIGNUM(
00879      && !INT_TYPE_SUB_OVERFLOW(u->integer, 1)
00880      )
00881      )
00882   {
00883     INT_TYPE val = --u->integer;
00884     pop_2_elems();
00885     push_int(val);
00886   } else {
00887     lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++;
00888     push_int(1);
00889     o_subtract();
00890     assign_lvalue(Pike_sp-3, Pike_sp-1);
00891     stack_pop_2_elems_keep_top();
00892   }
00893 });
00894 
00895 OPCODE0(F_DEC_AND_POP, "x-- and pop", I_UPDATE_SP, {
00896   union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT);
00897   if(u
00898      DO_IF_BIGNUM(
00899      && !INT_TYPE_SUB_OVERFLOW(u->integer, 1)
00900      )
00901 )
00902   {
00903     --u->integer;
00904     pop_2_elems();
00905   }else{
00906     lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++;
00907     push_int(1);
00908     o_subtract();
00909     assign_lvalue(Pike_sp-3, Pike_sp-1);
00910     pop_n_elems(3);
00911   }
00912 });
00913 
00914 OPCODE0(F_INC_AND_POP, "x++ and pop", I_UPDATE_SP, {
00915   union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT);
00916   if(u
00917      DO_IF_BIGNUM(
00918      && !INT_TYPE_ADD_OVERFLOW(u->integer, 1)
00919      )
00920      )
00921   {
00922     ++u->integer;
00923     pop_2_elems();
00924   } else {
00925     lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++;
00926     push_int(1);
00927     f_add(2);
00928     assign_lvalue(Pike_sp-3, Pike_sp-1);
00929     pop_n_elems(3);
00930   }
00931 });
00932 
00933 OPCODE0(F_POST_INC, "x++", I_UPDATE_SP, {
00934   union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT);
00935   if(u
00936      DO_IF_BIGNUM(
00937      && !INT_TYPE_ADD_OVERFLOW(u->integer, 1)
00938      )
00939      )
00940   {
00941     INT_TYPE val = u->integer++;
00942     pop_2_elems();
00943     push_int(val);
00944   } else {
00945     lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++;
00946     stack_dup();
00947     push_int(1);
00948     f_add(2);
00949     assign_lvalue(Pike_sp-4, Pike_sp-1);
00950     pop_stack();
00951     stack_pop_2_elems_keep_top();
00952     print_return_value();
00953   }
00954 });
00955 
00956 OPCODE0(F_POST_DEC, "x--", I_UPDATE_SP, {
00957   union anything *u=get_pointer_if_this_type(Pike_sp-2, PIKE_T_INT);
00958   if(u
00959      DO_IF_BIGNUM(
00960      && !INT_TYPE_SUB_OVERFLOW(u->integer, 1)
00961      )
00962      )
00963   {
00964     INT_TYPE val = u->integer--;
00965     pop_2_elems();
00966     push_int(val);
00967   } else {
00968     lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2); Pike_sp++;
00969     stack_dup();
00970     push_int(1);
00971     o_subtract();
00972     assign_lvalue(Pike_sp-4, Pike_sp-1);
00973     pop_stack();
00974     stack_pop_2_elems_keep_top();
00975     print_return_value();
00976   }
00977 });
00978 
00979 OPCODE1(F_ASSIGN_LOCAL, "assign local", 0, {
00980   assign_svalue(Pike_fp->locals+arg1,Pike_sp-1);
00981 });
00982 
00983 OPCODE0(F_ASSIGN, "assign", I_UPDATE_SP, {
00984   assign_lvalue(Pike_sp-3,Pike_sp-1);
00985   free_svalue(Pike_sp-3);
00986   free_svalue(Pike_sp-2);
00987   move_svalue (Pike_sp - 3, Pike_sp - 1);
00988   Pike_sp-=2;
00989 });
00990 
00991 OPCODE2(F_APPLY_ASSIGN_LOCAL_AND_POP, "apply, assign local and pop", I_UPDATE_SP|I_UPDATE_M_SP, {
00992   apply_svalue(&((Pike_fp->context.prog->constants + arg1)->sval),
00993                DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp)));
00994   free_svalue(Pike_fp->locals+arg2);
00995   move_svalue (Pike_fp->locals + arg2, Pike_sp - 1);
00996   Pike_sp--;
00997 });
00998 
00999 OPCODE2(F_APPLY_ASSIGN_LOCAL, "apply, assign local", I_UPDATE_ALL, {
01000   apply_svalue(&((Pike_fp->context.prog->constants + arg1)->sval),
01001                DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp)));
01002   assign_svalue(Pike_fp->locals+arg2, Pike_sp-1);
01003 });
01004 
01005 OPCODE0(F_ASSIGN_AND_POP, "assign and pop", I_UPDATE_SP, {
01006   assign_lvalue(Pike_sp-3, Pike_sp-1);
01007   pop_n_elems(3);
01008 });
01009 
01010 OPCODE1(F_ASSIGN_LOCAL_AND_POP, "assign local and pop", I_UPDATE_SP, {
01011   free_svalue(Pike_fp->locals + arg1);
01012   move_svalue (Pike_fp->locals + arg1, Pike_sp - 1);
01013   Pike_sp--;
01014 });
01015 
01016 OPCODE1(F_ASSIGN_GLOBAL, "assign global", 0, {
01017   object_low_set_index(Pike_fp->current_object,
01018                        arg1 + Pike_fp->context.identifier_level,
01019                        Pike_sp-1);
01020 });
01021 
01022 OPCODE1(F_ASSIGN_GLOBAL_AND_POP, "assign global and pop", I_UPDATE_SP, {
01023   object_low_set_index(Pike_fp->current_object,
01024                        arg1 + Pike_fp->context.identifier_level,
01025                        Pike_sp-1);
01026   pop_stack();
01027 });
01028 
01029 
01030 /* Stack machine stuff */
01031 
01032 OPCODE0(F_POP_VALUE, "pop", I_UPDATE_SP, {
01033   pop_stack();
01034 });
01035 
01036 OPCODE1(F_POP_N_ELEMS, "pop_n_elems", I_UPDATE_SP, {
01037   pop_n_elems(arg1);
01038 });
01039 
01040 OPCODE0_TAIL(F_MARK2, "mark mark", I_UPDATE_M_SP, {
01041   *(Pike_mark_sp++)=Pike_sp;
01042 
01043 /* This opcode is only used when running with -d. Identical to F_MARK,
01044  * but with a different name to make the debug printouts more clear. */
01045   OPCODE0_TAIL(F_SYNCH_MARK, "synch mark", I_UPDATE_M_SP, {
01046 
01047     OPCODE0(F_MARK, "mark", I_UPDATE_M_SP, {
01048       *(Pike_mark_sp++)=Pike_sp;
01049     });
01050   });
01051 });
01052 
01053 OPCODE1(F_MARK_X, "mark Pike_sp-X", I_UPDATE_M_SP, {
01054   *(Pike_mark_sp++)=Pike_sp-arg1;
01055 });
01056 
01057 OPCODE0(F_POP_MARK, "pop mark", I_UPDATE_M_SP, {
01058   --Pike_mark_sp;
01059 });
01060 
01061 OPCODE0(F_POP_TO_MARK, "pop to mark", I_UPDATE_SP|I_UPDATE_M_SP, {
01062   pop_n_elems(Pike_sp - *--Pike_mark_sp);
01063 });
01064 
01065 /* These opcodes are only used when running with -d. The reason for
01066  * the two aliases is mainly to keep the indentation in asm debug
01067  * output. */
01068 OPCODE0_TAIL(F_CLEANUP_SYNCH_MARK, "cleanup synch mark", I_UPDATE_SP|I_UPDATE_M_SP, {
01069   OPCODE0(F_POP_SYNCH_MARK, "pop synch mark", I_UPDATE_SP|I_UPDATE_M_SP, {
01070     if (d_flag) {
01071       if (Pike_mark_sp <= Pike_interpreter.mark_stack) {
01072         Pike_fatal("Mark stack out of synch - %p <= %p.\n",
01073                    Pike_mark_sp, Pike_interpreter.mark_stack);
01074       } else if (*--Pike_mark_sp != Pike_sp) {
01075         ptrdiff_t should = *Pike_mark_sp - Pike_interpreter.evaluator_stack;
01076         ptrdiff_t is = Pike_sp - Pike_interpreter.evaluator_stack;
01077         if (Pike_sp - *Pike_mark_sp > 0) /* not always same as Pike_sp > *Pike_mark_sp */
01078         /* Some attempt to recover, just to be able to report the backtrace. */
01079           pop_n_elems(Pike_sp - *Pike_mark_sp);
01080         Pike_fatal("Stack out of synch - should be %ld, is %ld.\n",
01081               DO_NOT_WARN((long)should), DO_NOT_WARN((long)is));
01082       }
01083     }
01084   });
01085 });
01086 
01087 OPCODE0(F_CLEAR_STRING_SUBTYPE, "clear string subtype", 0, {
01088   if(Pike_sp[-1].type==PIKE_T_STRING) Pike_sp[-1].subtype=0;
01089 });
01090 
01091       /* Jumps */
01092 OPCODE0_BRANCH(F_BRANCH, "branch", 0, {
01093   DO_BRANCH();
01094 });
01095 
01096 OPCODE2_BRANCH(F_BRANCH_IF_NOT_LOCAL_ARROW, "branch if !local->x", 0, {
01097   LOCAL_VAR(struct svalue tmp);
01098   tmp.type=PIKE_T_STRING;
01099   tmp.u.string=Pike_fp->context.prog->strings[arg1];
01100   tmp.subtype=1;
01101   Pike_sp->type=PIKE_T_INT;     
01102   Pike_sp++;
01103   index_no_free(Pike_sp-1,Pike_fp->locals+arg2, &tmp);
01104   print_return_value();
01105 
01106   /* Fall through */
01107 
01108   OPCODE0_TAILBRANCH(F_BRANCH_WHEN_ZERO, "branch if zero", I_UPDATE_SP, {
01109     if(!UNSAFE_IS_ZERO(Pike_sp-1))
01110     {
01111       /* write_to_stderr("foreach\n", 8); */
01112       DONT_BRANCH();
01113     }else{
01114       DO_BRANCH();
01115     }
01116     pop_stack();
01117   });
01118 });
01119 
01120       
01121 OPCODE0_BRANCH(F_BRANCH_WHEN_NON_ZERO, "branch if not zero", I_UPDATE_SP, {
01122   if(UNSAFE_IS_ZERO(Pike_sp-1))
01123   {
01124     /* write_to_stderr("foreach\n", 8); */
01125     DONT_BRANCH();
01126   }else{
01127     DO_BRANCH();
01128   }
01129   pop_stack();
01130 });
01131 
01132 OPCODE1_BRANCH(F_BRANCH_IF_TYPE_IS_NOT, "branch if type is !=", I_UPDATE_SP, {
01133 /*  fprintf(stderr,"******BRANCH IF TYPE IS NOT***** %s\n",get_name_of_type(arg1)); */
01134   LOCAL_VAR(struct object *o);
01135   if(Pike_sp[-1].type == T_OBJECT &&
01136      (o = Pike_sp[-1].u.object)->prog)
01137   {
01138     int fun = FIND_LFUN(o->prog->inherits[Pike_sp[-1].subtype].prog,
01139                         LFUN__IS_TYPE);
01140     if(fun != -1)
01141     {
01142 /*      fprintf(stderr,"******OBJECT OVERLOAD IN TYPEP***** %s\n",get_name_of_type(arg1)); */
01143       push_text(get_name_of_type(arg1));
01144       apply_low(o, fun +
01145                 o->prog->inherits[Pike_sp[-2].subtype].identifier_level, 1);
01146       arg1=UNSAFE_IS_ZERO(Pike_sp-1) ? T_FLOAT : T_OBJECT ;
01147       pop_stack();
01148     }
01149   }
01150   if(Pike_sp[-1].type == arg1)
01151   {
01152     /* write_to_stderr("foreach\n", 8); */
01153     DONT_BRANCH();
01154   }else{
01155     DO_BRANCH();
01156   }
01157   pop_stack();
01158 });
01159 
01160 OPCODE1_BRANCH(F_BRANCH_IF_LOCAL, "branch if local", 0, {
01161   if(UNSAFE_IS_ZERO(Pike_fp->locals + arg1))
01162   {
01163     /* write_to_stderr("foreach\n", 8); */
01164     DONT_BRANCH();
01165   }else{
01166     DO_BRANCH();
01167   }
01168 });
01169 
01170 OPCODE1_BRANCH(F_BRANCH_IF_NOT_LOCAL, "branch if !local", 0, {
01171   if(!UNSAFE_IS_ZERO(Pike_fp->locals + arg1))
01172   {
01173     /* write_to_stderr("foreach\n", 8); */
01174     DONT_BRANCH();
01175   }else{
01176     DO_BRANCH();
01177   }
01178 });
01179 
01180 #define CJUMP(X, DESC, Y) \
01181   OPCODE0_BRANCH(X, DESC, I_UPDATE_SP, { \
01182     if(Y(Pike_sp-2,Pike_sp-1)) { \
01183       DO_BRANCH(); \
01184     }else{ \
01185       /* write_to_stderr("foreach\n", 8); */    \
01186       DONT_BRANCH(); \
01187     } \
01188     pop_2_elems(); \
01189   })
01190 
01191 CJUMP(F_BRANCH_WHEN_EQ, "branch if ==", is_eq);
01192 CJUMP(F_BRANCH_WHEN_NE, "branch if !=", !is_eq);
01193 CJUMP(F_BRANCH_WHEN_LT, "branch if <", is_lt);
01194 CJUMP(F_BRANCH_WHEN_LE, "branch if <=", is_le);
01195 CJUMP(F_BRANCH_WHEN_GT, "branch if >", is_gt);
01196 CJUMP(F_BRANCH_WHEN_GE, "branch if >=", is_ge);
01197 
01198 OPCODE0_BRANCH(F_BRANCH_AND_POP_WHEN_ZERO, "branch & pop if zero", 0, {
01199   if(!UNSAFE_IS_ZERO(Pike_sp-1))
01200   {
01201     /* write_to_stderr("foreach\n", 8); */
01202     DONT_BRANCH();
01203   }else{
01204     DO_BRANCH();
01205     pop_stack();
01206   }
01207 });
01208 
01209 OPCODE0_BRANCH(F_BRANCH_AND_POP_WHEN_NON_ZERO, "branch & pop if !zero", 0, {
01210   if(UNSAFE_IS_ZERO(Pike_sp-1))
01211   {
01212     /* write_to_stderr("foreach\n", 8); */
01213     DONT_BRANCH();
01214   }else{
01215     DO_BRANCH();
01216     pop_stack();
01217   }
01218 });
01219 
01220 OPCODE0_BRANCH(F_LAND, "&&", I_UPDATE_SP, {
01221   if(!UNSAFE_IS_ZERO(Pike_sp-1))
01222   {
01223     /* write_to_stderr("foreach\n", 8); */
01224     DONT_BRANCH();
01225     pop_stack();
01226   }else{
01227     DO_BRANCH();
01228     pop_stack();
01229     push_int(0);
01230   }
01231 });
01232 
01233 OPCODE0_BRANCH(F_LOR, "||", I_UPDATE_SP, {
01234   if(UNSAFE_IS_ZERO(Pike_sp-1))
01235   {
01236     /* write_to_stderr("foreach\n", 8); */
01237     DONT_BRANCH();
01238     pop_stack();
01239   }else{
01240     DO_BRANCH();
01241   }
01242 });
01243 
01244 OPCODE0_BRANCH(F_EQ_OR, "==||", I_UPDATE_SP, {
01245   if(!is_eq(Pike_sp-2,Pike_sp-1))
01246   {
01247     /* write_to_stderr("foreach\n", 8); */
01248     DONT_BRANCH();
01249     pop_2_elems();
01250   }else{
01251     DO_BRANCH();
01252     pop_2_elems();
01253     push_int(1);
01254   }
01255 });
01256 
01257 OPCODE0_BRANCH(F_EQ_AND, "==&&", I_UPDATE_SP, {
01258   if(is_eq(Pike_sp-2,Pike_sp-1))
01259   {
01260     /* write_to_stderr("foreach\n", 8); */
01261     DONT_BRANCH();
01262     pop_2_elems();
01263   }else{
01264     DO_BRANCH();
01265     pop_2_elems();
01266     push_int(0);
01267   }
01268 });
01269 
01270 /* This instruction can't currently be a branch, since
01271  * it has more than two continuation paths.
01272  */
01273 OPCODE0_PTRJUMP(F_CATCH, "catch", I_UPDATE_ALL, {
01274   PIKE_OPCODE_T *next_addr;
01275   JUMP_SET_TO_PC_AT_NEXT (next_addr);
01276   check_c_stack(8192);
01277   switch (o_catch((PIKE_OPCODE_T *)(((INT32 *)next_addr)+1)))
01278   {
01279   case 1:
01280     /* There was a return inside the evaluated code */
01281     DO_DUMB_RETURN;
01282   case 2:
01283     /* Escape catch, continue after the escape instruction. */
01284     DO_JUMP_TO(Pike_fp->return_addr);
01285     break;
01286   default:
01287     DOJUMP();
01288   }
01289   /* NOT_REACHED in byte-code and computed goto cases. */
01290 });
01291 
01292 OPCODE0_RETURN(F_ESCAPE_CATCH, "escape catch", 0, {
01293   JUMP_SET_TO_PC_AT_NEXT (Pike_fp->return_addr);
01294   INTER_ESCAPE_CATCH;
01295 });
01296 
01297 OPCODE0_RETURN(F_EXIT_CATCH, "exit catch", I_UPDATE_SP, {
01298   push_undefined();
01299   JUMP_SET_TO_PC_AT_NEXT (Pike_fp->return_addr);
01300   INTER_ESCAPE_CATCH;
01301 });
01302 
01303 OPCODE1_JUMP(F_SWITCH, "switch", I_UPDATE_ALL, {
01304   INT32 tmp;
01305   PIKE_OPCODE_T *addr;
01306   JUMP_SET_TO_PC_AT_NEXT (addr);
01307   tmp=switch_lookup(Pike_fp->context.prog->
01308                     constants[arg1].sval.u.array,Pike_sp-1);
01309   addr = DO_IF_ELSE_COMPUTED_GOTO(addr, (PIKE_OPCODE_T *)
01310                                   DO_ALIGN(PTR_TO_INT(addr),
01311                                            ((ptrdiff_t)sizeof(INT32))));
01312   addr = (PIKE_OPCODE_T *)(((INT32 *)addr) + (tmp>=0 ? 1+tmp*2 : 2*~tmp));
01313   if(*(INT32*)addr < 0) fast_check_threads_etc(7);
01314   pop_stack();
01315   DO_JUMP_TO(addr + *(INT32*)addr);
01316 });
01317 
01318 OPCODE1_JUMP(F_SWITCH_ON_INDEX, "switch on index", I_UPDATE_ALL, {
01319   INT32 tmp;
01320   PIKE_OPCODE_T *addr;
01321   LOCAL_VAR(struct svalue tmp2);
01322   JUMP_SET_TO_PC_AT_NEXT (addr);
01323   index_no_free(&tmp2, Pike_sp-2, Pike_sp-1);
01324   move_svalue (Pike_sp++, &tmp2);
01325 
01326   tmp=switch_lookup(Pike_fp->context.prog->
01327                     constants[arg1].sval.u.array,Pike_sp-1);
01328   pop_n_elems(3);
01329   addr = DO_IF_ELSE_COMPUTED_GOTO(addr, (PIKE_OPCODE_T *)
01330                                   DO_ALIGN(PTR_TO_INT(addr),
01331                                            ((ptrdiff_t)sizeof(INT32))));
01332   addr = (PIKE_OPCODE_T *)(((INT32 *)addr) + (tmp>=0 ? 1+tmp*2 : 2*~tmp));
01333   if(*(INT32*)addr < 0) fast_check_threads_etc(7);
01334   DO_JUMP_TO(addr + *(INT32*)addr);
01335 });
01336 
01337 OPCODE2_JUMP(F_SWITCH_ON_LOCAL, "switch on local", 0, {
01338   INT32 tmp;
01339   PIKE_OPCODE_T *addr;
01340   JUMP_SET_TO_PC_AT_NEXT (addr);
01341   tmp=switch_lookup(Pike_fp->context.prog->
01342                     constants[arg2].sval.u.array,Pike_fp->locals + arg1);
01343   addr = DO_IF_ELSE_COMPUTED_GOTO(addr, (PIKE_OPCODE_T *)
01344                                   DO_ALIGN(PTR_TO_INT(addr),
01345                                            ((ptrdiff_t)sizeof(INT32))));
01346   addr = (PIKE_OPCODE_T *)(((INT32 *)addr) + (tmp>=0 ? 1+tmp*2 : 2*~tmp));
01347   if(*(INT32*)addr < 0) fast_check_threads_etc(7);
01348   DO_JUMP_TO(addr + *(INT32*)addr);
01349 });
01350 
01351 
01352 #ifdef AUTO_BIGNUM
01353 #define AUTO_BIGNUM_LOOP_TEST(X,Y) INT_TYPE_ADD_OVERFLOW(X,Y)
01354 #else
01355 #define AUTO_BIGNUM_LOOP_TEST(X,Y) 0
01356 #endif
01357 
01358       /* FIXME: Does this need bignum tests? /Fixed - Hubbe */
01359       /* LOOP(OPCODE, INCREMENT, OPERATOR, IS_OPERATOR) */
01360 #define LOOP(ID, DESC, INC, OP2, OP4)                                   \
01361   OPCODE0_BRANCH(ID, DESC, 0, {                                         \
01362     union anything *i=get_pointer_if_this_type(Pike_sp-2, T_INT);       \
01363     if(i && !AUTO_BIGNUM_LOOP_TEST(i->integer,INC) &&                   \
01364        Pike_sp[-3].type == T_INT)                                       \
01365     {                                                                   \
01366       i->integer += INC;                                                \
01367       if(i->integer OP2 Pike_sp[-3].u.integer)                          \
01368       {                                                                 \
01369         DO_BRANCH();                                                    \
01370       }else{                                                            \
01371         /* write_to_stderr("loop\n", 8); */                             \
01372         DONT_BRANCH();                                                  \
01373       }                                                                 \
01374     }else{                                                              \
01375       lvalue_to_svalue_no_free(Pike_sp,Pike_sp-2); Pike_sp++;           \
01376       push_int(INC);                                                    \
01377       f_add(2);                                                         \
01378       assign_lvalue(Pike_sp-3,Pike_sp-1);                               \
01379       if(OP4 ( Pike_sp-1, Pike_sp-4 ))                                  \
01380       {                                                                 \
01381         DO_BRANCH();                                                    \
01382       }else{                                                            \
01383         /* write_to_stderr("loop\n", 8); */                             \
01384         DONT_BRANCH();                                                  \
01385       }                                                                 \
01386       pop_stack();                                                      \
01387     }                                                                   \
01388   })
01389 
01390 LOOP(F_INC_LOOP, "++Loop", 1, <, is_lt);
01391 LOOP(F_DEC_LOOP, "--Loop", -1, >, is_gt);
01392 LOOP(F_INC_NEQ_LOOP, "++Loop!=", 1, !=, !is_eq);
01393 LOOP(F_DEC_NEQ_LOOP, "--Loop!=", -1, !=, !is_eq);
01394 
01395 /* Use like:
01396  *
01397  * push(loopcnt)
01398  * branch(l2)
01399  * l1:
01400  *   sync_mark
01401  *     code
01402  *   pop_sync_mark
01403  * l2:
01404  * loop(l1)
01405  */
01406 OPCODE0_BRANCH(F_LOOP, "loop", I_UPDATE_SP, { /* loopcnt */
01407   /* Use >= and 1 to be able to reuse the 1 for the subtraction. */
01408   push_int(1);
01409   if (!is_lt(Pike_sp-2, Pike_sp-1)) {
01410     o_subtract();
01411     DO_BRANCH();
01412   } else {
01413     /* write_to_stderr("foreach\n", 8); */
01414     DONT_BRANCH();
01415     pop_2_elems();
01416   }
01417 });
01418 
01419 OPCODE0_BRANCH(F_FOREACH, "foreach", 0, { /* array, lvalue, i */
01420   if(Pike_sp[-4].type != PIKE_T_ARRAY)
01421     PIKE_ERROR("foreach", "Bad argument 1.\n", Pike_sp-3, 1);
01422   if(Pike_sp[-1].u.integer < Pike_sp[-4].u.array->size)
01423   {
01424     if(Pike_sp[-1].u.integer < 0)
01425       /* Isn't this an internal compiler error? /mast */
01426       Pike_error("Foreach loop variable is negative!\n");
01427     assign_lvalue(Pike_sp-3, Pike_sp[-4].u.array->item + Pike_sp[-1].u.integer);
01428     DO_BRANCH();
01429     Pike_sp[-1].u.integer++;
01430     DO_IF_DEBUG (
01431       if (Pike_sp[-1].subtype)
01432         Pike_fatal ("Got unexpected subtype in loop variable.\n");
01433     );
01434   }else{
01435     /* write_to_stderr("foreach\n", 8); */
01436     DONT_BRANCH();
01437   }
01438 });
01439 
01440 OPCODE0(F_MAKE_ITERATOR, "get_iterator", 0, {
01441   f_get_iterator(1);
01442 });
01443 
01444 /* Stack is: iterator, index lvalue, value lvalue. */
01445 OPCODE0_BRANCH (F_FOREACH_START, "foreach start", 0, {
01446   DO_IF_DEBUG (
01447     if(Pike_sp[-5].type != PIKE_T_OBJECT)
01448       Pike_fatal ("Iterator gone from stack.\n");
01449   );
01450   /* FIXME: object subtype. */
01451   if (foreach_iterate (Pike_sp[-5].u.object, 0))
01452     DONT_BRANCH();
01453   else {
01454     DO_BRANCH();
01455   }
01456 });
01457 
01458 /* Stack is: iterator, index lvalue, value lvalue. */
01459 OPCODE0_BRANCH(F_FOREACH_LOOP, "foreach loop", 0, {
01460   DO_IF_DEBUG (
01461     if(Pike_sp[-5].type != PIKE_T_OBJECT)
01462       Pike_fatal ("Iterator gone from stack.\n");
01463   );
01464   /* FIXME: object subtype. */
01465   if(foreach_iterate(Pike_sp[-5].u.object, 1))
01466   {
01467     DO_BRANCH();
01468   }else{
01469     DONT_BRANCH();
01470   }
01471 });
01472 
01473 
01474 OPCODE1_RETURN(F_RETURN_LOCAL,"return local", I_UPDATE_SP|I_UPDATE_FP, {
01475   DO_IF_DEBUG(
01476     /* special case! Pike_interpreter.mark_stack may be invalid at the time we
01477      * call return -1, so we must call the callbacks here to
01478      * prevent false alarms! /Hubbe
01479      */
01480     if(d_flag>3) do_gc(NULL, 0);
01481     if(d_flag>4) do_debug();
01482     );
01483   if(Pike_fp->expendible <= Pike_fp->locals + arg1)
01484   {
01485     pop_n_elems(Pike_sp-1 - (Pike_fp->locals + arg1));
01486   }else{
01487     push_svalue(Pike_fp->locals + arg1);
01488   }
01489   DO_DUMB_RETURN;
01490 });
01491 
01492 
01493 OPCODE0_RETURN(F_RETURN_IF_TRUE,"return if true", I_UPDATE_SP|I_UPDATE_FP, {
01494   if(!UNSAFE_IS_ZERO(Pike_sp-1)) DO_RETURN;
01495   pop_stack();
01496   DO_JUMP_TO_NEXT;
01497 });
01498 
01499 OPCODE0_RETURN(F_RETURN_1,"return 1", I_UPDATE_SP|I_UPDATE_FP, {
01500   push_int(1);
01501   DO_RETURN;
01502 });
01503 
01504 OPCODE0_RETURN(F_RETURN_0,"return 0", I_UPDATE_SP|I_UPDATE_FP, {
01505   push_int(0);
01506   DO_RETURN;
01507 });
01508 
01509 OPCODE0_RETURN(F_RETURN, "return", I_UPDATE_FP, {
01510   DO_RETURN;
01511 });
01512 
01513 OPCODE0_RETURN(F_DUMB_RETURN,"dumb return", I_UPDATE_FP, {
01514   DO_DUMB_RETURN;
01515 });
01516 
01517 OPCODE0(F_NEGATE, "unary minus", 0, {
01518   if(Pike_sp[-1].type == PIKE_T_INT)
01519   {
01520     DO_IF_BIGNUM(
01521       if(INT_TYPE_NEG_OVERFLOW(Pike_sp[-1].u.integer))
01522       {
01523         convert_stack_top_to_bignum();
01524         o_negate();
01525       }
01526       else
01527     )
01528     {
01529       Pike_sp[-1].u.integer =- Pike_sp[-1].u.integer;
01530       Pike_sp[-1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
01531     }
01532   }
01533   else if(Pike_sp[-1].type == PIKE_T_FLOAT)
01534   {
01535     Pike_sp[-1].u.float_number =- Pike_sp[-1].u.float_number;
01536   }else{
01537     o_negate();
01538   }
01539 });
01540 
01541 OPCODE0_ALIAS(F_COMPL, "~", 0, o_compl);
01542 
01543 OPCODE0(F_NOT, "!", 0, {
01544   switch(Pike_sp[-1].type)
01545   {
01546   case PIKE_T_INT:
01547     Pike_sp[-1].u.integer =! Pike_sp[-1].u.integer;
01548     Pike_sp[-1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
01549     break;
01550 
01551   case PIKE_T_FUNCTION:
01552   case PIKE_T_OBJECT:
01553     if(UNSAFE_IS_ZERO(Pike_sp-1))
01554     {
01555       pop_stack();
01556       push_int(1);
01557     }else{
01558       pop_stack();
01559       push_int(0);
01560     }
01561     break;
01562 
01563   default:
01564     free_svalue(Pike_sp-1);
01565     Pike_sp[-1].type=PIKE_T_INT;
01566     Pike_sp[-1].subtype = NUMBER_NUMBER;
01567     Pike_sp[-1].u.integer=0;
01568   }
01569 });
01570 
01571 OPCODE0_ALIAS(F_LSH, "<<", I_UPDATE_SP, o_lsh);
01572 OPCODE0_ALIAS(F_RSH, ">>", I_UPDATE_SP, o_rsh);
01573 
01574 #define COMPARISON(ID,DESC,EXPR)        \
01575   OPCODE0(ID, DESC, I_UPDATE_SP, {      \
01576     INT32 val = EXPR;                   \
01577     pop_2_elems();                      \
01578     push_int(val);                      \
01579   })
01580 
01581 COMPARISON(F_EQ, "==", is_eq(Pike_sp-2,Pike_sp-1));
01582 COMPARISON(F_NE, "!=", !is_eq(Pike_sp-2,Pike_sp-1));
01583 COMPARISON(F_GT, ">", is_gt(Pike_sp-2,Pike_sp-1));
01584 COMPARISON(F_GE, ">=", is_ge(Pike_sp-2,Pike_sp-1));
01585 COMPARISON(F_LT, "<", is_lt(Pike_sp-2,Pike_sp-1));
01586 COMPARISON(F_LE, "<=", is_le(Pike_sp-2,Pike_sp-1));
01587 
01588 OPCODE0(F_ADD, "+", I_UPDATE_SP, {
01589   f_add(2);
01590 });
01591 
01592 OPCODE0(F_ADD_INTS, "int+int", I_UPDATE_SP, {
01593   if(Pike_sp[-1].type == T_INT && Pike_sp[-2].type == T_INT 
01594      DO_IF_BIGNUM(
01595       && (!INT_TYPE_ADD_OVERFLOW(Pike_sp[-1].u.integer, Pike_sp[-2].u.integer))
01596       )
01597     )
01598   {
01599     Pike_sp[-2].u.integer+=Pike_sp[-1].u.integer;
01600     Pike_sp[-2].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
01601     dmalloc_touch_svalue(Pike_sp-1);
01602     Pike_sp--;
01603   }else{
01604     f_add(2);
01605   }
01606 });
01607 
01608 OPCODE0(F_ADD_FLOATS, "float+float", I_UPDATE_SP, {
01609   if(Pike_sp[-1].type == T_FLOAT && Pike_sp[-2].type == T_FLOAT)
01610   {
01611     Pike_sp[-2].u.float_number+=Pike_sp[-1].u.float_number;
01612     dmalloc_touch_svalue(Pike_sp-1);
01613     Pike_sp--;
01614   }else{
01615     f_add(2);
01616   }
01617 });
01618 
01619 OPCODE0_ALIAS(F_SUBTRACT, "-", I_UPDATE_SP, o_subtract);
01620 OPCODE0_ALIAS(F_AND, "&", I_UPDATE_SP, o_and);
01621 OPCODE0_ALIAS(F_OR, "|", I_UPDATE_SP, o_or);
01622 OPCODE0_ALIAS(F_XOR, "^", I_UPDATE_SP, o_xor);
01623 OPCODE0_ALIAS(F_MULTIPLY, "*", I_UPDATE_SP, o_multiply);
01624 OPCODE0_ALIAS(F_DIVIDE, "/", I_UPDATE_SP, o_divide);
01625 OPCODE0_ALIAS(F_MOD, "%", I_UPDATE_SP, o_mod);
01626 
01627 OPCODE1(F_ADD_INT, "add integer", 0, {
01628   if(Pike_sp[-1].type == T_INT
01629      DO_IF_BIGNUM(
01630       && (!INT_TYPE_ADD_OVERFLOW(Pike_sp[-1].u.integer, arg1))
01631       )
01632      )
01633   {
01634     Pike_sp[-1].u.integer+=arg1;
01635     Pike_sp[-1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
01636   }else{
01637     push_int(arg1);
01638     f_add(2);
01639   }
01640 });
01641 
01642 OPCODE1(F_ADD_NEG_INT, "add -integer", 0, {
01643   if(Pike_sp[-1].type == T_INT
01644      DO_IF_BIGNUM(
01645       && (!INT_TYPE_ADD_OVERFLOW(Pike_sp[-1].u.integer, -arg1))
01646       )
01647      )
01648   {
01649     Pike_sp[-1].u.integer-=arg1;
01650     Pike_sp[-1].subtype = NUMBER_NUMBER; /* Could have UNDEFINED there before. */
01651   }else{
01652     push_int(-arg1);
01653     f_add(2);
01654   }
01655 });
01656 
01657 OPCODE0(F_PUSH_ARRAY, "@", I_UPDATE_SP, {
01658   int i;
01659   LOCAL_VAR(struct object *o);
01660   LOCAL_VAR(struct program *p);
01661 
01662   switch(Pike_sp[-1].type)
01663   {
01664   default:
01665     PIKE_ERROR("@", "Bad argument.\n", Pike_sp, 1);
01666     
01667   case PIKE_T_OBJECT:
01668     if(!(p = (o = Pike_sp[-1].u.object)->prog) ||
01669        (i = FIND_LFUN(p->inherits[Pike_sp[-1].subtype].prog,
01670                       LFUN__VALUES)) == -1)
01671       PIKE_ERROR("@", "Bad argument.\n", Pike_sp, 1);
01672 
01673     apply_low(o, i + p->inherits[Pike_sp[-1].subtype].identifier_level, 0);
01674     if(Pike_sp[-1].type != PIKE_T_ARRAY)
01675       Pike_error("Bad return type from o->_values() in @\n");
01676     free_svalue(Pike_sp-2);
01677     move_svalue (Pike_sp - 2, Pike_sp - 1);
01678     Pike_sp--;
01679     break;
01680 
01681   case PIKE_T_ARRAY: break;
01682   }
01683   dmalloc_touch_svalue(Pike_sp-1);
01684   Pike_sp--;
01685   push_array_items(Pike_sp->u.array);
01686 });
01687 
01688 OPCODE2(F_LOCAL_LOCAL_INDEX, "local[local]", I_UPDATE_SP, {
01689   LOCAL_VAR(struct svalue *s);
01690   s = Pike_fp->locals + arg1;
01691   if(s->type == PIKE_T_STRING) s->subtype=0;
01692   Pike_sp++->type=PIKE_T_INT;
01693   index_no_free(Pike_sp-1,Pike_fp->locals+arg2,s);
01694 });
01695 
01696 OPCODE1(F_LOCAL_INDEX, "local index", 0, {
01697   LOCAL_VAR(struct svalue *s);
01698   LOCAL_VAR(struct svalue tmp);
01699   s = Pike_fp->locals + arg1;
01700   if(s->type == PIKE_T_STRING) s->subtype=0;
01701   index_no_free(&tmp,Pike_sp-1,s);
01702   free_svalue(Pike_sp-1);
01703   move_svalue (Pike_sp - 1, &tmp);
01704 });
01705 
01706 OPCODE2(F_GLOBAL_LOCAL_INDEX, "global[local]", I_UPDATE_SP, {
01707   LOCAL_VAR(struct svalue *s);
01708   LOCAL_VAR(struct svalue tmp);
01709   low_index_current_object_no_free(Pike_sp, arg1);
01710   Pike_sp++;
01711   s=Pike_fp->locals+arg2;
01712   if(s->type == PIKE_T_STRING) s->subtype=0;
01713   index_no_free(&tmp,Pike_sp-1,s);
01714   free_svalue(Pike_sp-1);
01715   move_svalue (Pike_sp - 1, &tmp);
01716 });
01717 
01718 OPCODE2(F_LOCAL_ARROW, "local->x", I_UPDATE_SP, {
01719   LOCAL_VAR(struct svalue tmp);
01720   tmp.type=PIKE_T_STRING;
01721   tmp.u.string=Pike_fp->context.prog->strings[arg1];
01722   tmp.subtype=1;
01723   Pike_sp->type=PIKE_T_INT;     
01724   Pike_sp++;
01725   index_no_free(Pike_sp-1,Pike_fp->locals+arg2, &tmp);
01726   print_return_value();
01727 });
01728 
01729 OPCODE1(F_ARROW, "->x", 0, {
01730   LOCAL_VAR(struct svalue tmp);
01731   LOCAL_VAR(struct svalue tmp2);
01732   tmp.type=PIKE_T_STRING;
01733   tmp.u.string=Pike_fp->context.prog->strings[arg1];
01734   tmp.subtype=1;
01735   index_no_free(&tmp2, Pike_sp-1, &tmp);
01736   free_svalue(Pike_sp-1);
01737   move_svalue (Pike_sp - 1, &tmp2);
01738   print_return_value();
01739 });
01740 
01741 OPCODE1(F_STRING_INDEX, "string index", 0, {
01742   LOCAL_VAR(struct svalue tmp);
01743   LOCAL_VAR(struct svalue tmp2);
01744   tmp.type=PIKE_T_STRING;
01745   tmp.u.string=Pike_fp->context.prog->strings[arg1];
01746   tmp.subtype=0;
01747   index_no_free(&tmp2, Pike_sp-1, &tmp);
01748   free_svalue(Pike_sp-1);
01749   move_svalue (Pike_sp - 1, &tmp2);
01750   print_return_value();
01751 });
01752 
01753 OPCODE1(F_POS_INT_INDEX, "int index", 0, {
01754   push_int(arg1);
01755   print_return_value();
01756   DO_INDEX;
01757 });
01758 
01759 OPCODE1(F_NEG_INT_INDEX, "-int index", 0, {
01760   push_int(-(ptrdiff_t)arg1);
01761   print_return_value();
01762   DO_INDEX;
01763 });
01764 
01765 OPCODE0(F_INDEX, "index", I_UPDATE_SP, {
01766   DO_INDEX;
01767 });
01768 
01769 OPCODE2(F_MAGIC_INDEX, "::`[]", I_UPDATE_SP, {
01770   push_magic_index(magic_index_program, arg2, arg1);
01771 });
01772 
01773 OPCODE2(F_MAGIC_SET_INDEX, "::`[]=", I_UPDATE_SP, {
01774   push_magic_index(magic_set_index_program, arg2, arg1);
01775 });
01776 
01777 OPCODE2(F_MAGIC_INDICES, "::_indices", I_UPDATE_SP, {
01778   push_magic_index(magic_indices_program, arg2, arg1);
01779 });
01780 
01781 OPCODE2(F_MAGIC_VALUES, "::_values", I_UPDATE_SP, {
01782   push_magic_index(magic_values_program, arg2, arg1);
01783 });
01784 
01785 OPCODE0_ALIAS(F_CAST, "cast", I_UPDATE_SP, f_cast);
01786 OPCODE0_ALIAS(F_CAST_TO_INT, "cast_to_int", 0, o_cast_to_int);
01787 OPCODE0_ALIAS(F_CAST_TO_STRING, "cast_to_string", 0, o_cast_to_string);
01788 
01789 OPCODE0(F_SOFT_CAST, "soft cast", I_UPDATE_SP, {
01790   /* Stack: type_string, value */
01791   DO_IF_DEBUG({
01792     if (Pike_sp[-2].type != T_TYPE) {
01793       Pike_fatal("Argument 1 to soft_cast isn't a type!\n");
01794     }
01795   });
01796   if (runtime_options & RUNTIME_CHECK_TYPES) {
01797     struct pike_type *sval_type = get_type_of_svalue(Pike_sp-1);
01798     if (!pike_types_le(sval_type, Pike_sp[-2].u.type)) {
01799       /* get_type_from_svalue() doesn't return a fully specified type
01800        * for array, mapping and multiset, so we perform a more lenient
01801        * check for them.
01802        */
01803       if (!pike_types_le(sval_type, weak_type_string) ||
01804           !match_types(sval_type, Pike_sp[-2].u.type)) {
01805         struct pike_string *t1;
01806         struct pike_string *t2;
01807         char *fname = "__soft-cast";
01808         ONERROR tmp1;
01809         ONERROR tmp2;
01810 
01811         if (Pike_fp->current_object && Pike_fp->context.prog &&
01812             Pike_fp->current_object->prog) {
01813           /* Look up the function-name */
01814           struct pike_string *name =
01815             ID_FROM_INT(Pike_fp->current_object->prog, Pike_fp->fun)->name;
01816           if ((!name->size_shift) && (name->len < 100))
01817             fname = name->str;
01818         }
01819 
01820         t1 = describe_type(Pike_sp[-2].u.type);
01821         SET_ONERROR(tmp1, do_free_string, t1);
01822           
01823         t2 = describe_type(sval_type);
01824         SET_ONERROR(tmp2, do_free_string, t2);
01825           
01826         free_type(sval_type);
01827 
01828         bad_arg_error(NULL, Pike_sp-1, 1, 1, t1->str, Pike_sp-1,
01829                       "%s(): Soft cast failed. Expected %s, got %s\n",
01830                       fname, t1->str, t2->str);
01831         /* NOT_REACHED */
01832         UNSET_ONERROR(tmp2);
01833         UNSET_ONERROR(tmp1);
01834         free_string(t2);
01835         free_string(t1);
01836       }
01837     }
01838     free_type(sval_type);
01839 
01840     DO_IF_DEBUG({
01841       if (d_flag > 2) {
01842         struct pike_string *t = describe_type(Pike_sp[-2].u.type);
01843         fprintf(stderr, "Soft cast to %s\n", t->str);
01844         free_string(t);
01845       }
01846     });
01847   }
01848   stack_swap();
01849   pop_stack();
01850 });
01851 
01852 OPCODE1_ALIAS(F_RANGE, "range", I_UPDATE_SP, o_range2);
01853 
01854 OPCODE0(F_COPY_VALUE, "copy_value", 0, {
01855   LOCAL_VAR(struct svalue tmp);
01856   copy_svalues_recursively_no_free(&tmp,Pike_sp-1,1,0);
01857   free_svalue(Pike_sp-1);
01858   move_svalue (Pike_sp - 1, &tmp);
01859   print_return_value();
01860 });
01861 
01862 OPCODE0(F_INDIRECT, "indirect", I_UPDATE_SP, {
01863   LOCAL_VAR(struct svalue tmp);
01864   lvalue_to_svalue_no_free(&tmp, Pike_sp-2);
01865   if(tmp.type != PIKE_T_STRING)
01866   {
01867     pop_2_elems();
01868     move_svalue (Pike_sp, &tmp);
01869     Pike_sp++;
01870   }else{
01871     struct string_assignment_storage *s;
01872     LOCAL_VAR(struct object *o);
01873     o=low_clone(string_assignment_program);
01874     s = (struct string_assignment_storage *)o->storage;
01875     move_svalue (s->lval, Pike_sp - 2);
01876     move_svalue (s->lval + 1, Pike_sp - 1);
01877     s->s=tmp.u.string;
01878     Pike_sp-=2;
01879     push_object(o);
01880   }
01881   print_return_value();
01882 });
01883       
01884 OPCODE0(F_SIZEOF, "sizeof", 0, {
01885   INT_TYPE val = pike_sizeof(Pike_sp-1);
01886   pop_stack();
01887   push_int(val);
01888 });
01889 
01890 OPCODE1(F_SIZEOF_LOCAL, "sizeof local", I_UPDATE_SP, {
01891   push_int(pike_sizeof(Pike_fp->locals+arg1));
01892 });
01893 
01894 OPCODE1_ALIAS(F_SSCANF, "sscanf", I_UPDATE_SP, o_sscanf);
01895 
01896 #define MKAPPLY(OP,OPCODE,NAME,TYPE,  ARG2, ARG3)                          \
01897   PIKE_CONCAT(OP,_JUMP)(PIKE_CONCAT(F_,OPCODE),NAME,                    \
01898                         I_UPDATE_ALL, {                                 \
01899 JUMP_SET_TO_PC_AT_NEXT (Pike_fp->return_addr);                          \
01900 if(low_mega_apply(TYPE,DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp)),    \
01901                   ARG2, ARG3))                                             \
01902 {                                                                          \
01903   Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL;                            \
01904   DO_JUMP_TO(Pike_fp->pc);                                                 \
01905 }                                                                          \
01906 else {                                                                  \
01907   DO_JUMP_TO_NEXT;                                                      \
01908 }                                                                       \
01909 });                                                                        \
01910                                                                            \
01911   PIKE_CONCAT(OP,_JUMP)(PIKE_CONCAT3(F_,OPCODE,_AND_POP),NAME " & pop", \
01912                         I_UPDATE_ALL, {                                 \
01913   JUMP_SET_TO_PC_AT_NEXT (Pike_fp->return_addr);                        \
01914   if(low_mega_apply(TYPE, DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp)), \
01915                     ARG2, ARG3))                                           \
01916   {                                                                        \
01917     Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL | PIKE_FRAME_RETURN_POP;  \
01918     DO_JUMP_TO(Pike_fp->pc);                                               \
01919   }else{                                                                   \
01920     pop_stack();                                                           \
01921     DO_JUMP_TO_NEXT;                                                    \
01922   }                                                                        \
01923 });                                                                        \
01924                                                                            \
01925 PIKE_CONCAT(OP,_RETURN)(PIKE_CONCAT3(F_,OPCODE,_AND_RETURN),               \
01926                         NAME " & return",                               \
01927                         I_UPDATE_ALL, { \
01928   if(low_mega_apply(TYPE,DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp)),  \
01929                     ARG2,ARG3))                                            \
01930   {                                                                        \
01931     PIKE_OPCODE_T *addr = Pike_fp->pc;                                     \
01932     DO_IF_DEBUG(Pike_fp->next->pc=0);                                      \
01933     unlink_previous_frame();                                               \
01934     DO_JUMP_TO(addr);                                                      \
01935   }else{                                                                   \
01936     DO_DUMB_RETURN;                                                        \
01937   }                                                                        \
01938 })
01939 
01940 
01941 #define MKAPPLY2(OP,OPCODE,NAME,TYPE,  ARG2, ARG3)                         \
01942                                                                            \
01943 MKAPPLY(OP,OPCODE,NAME,TYPE,  ARG2, ARG3);                                 \
01944                                                                            \
01945 PIKE_CONCAT(OP,_JUMP)(PIKE_CONCAT(F_MARK_,OPCODE),"mark, " NAME, \
01946                       I_UPDATE_ALL, {                                   \
01947   JUMP_SET_TO_PC_AT_NEXT (Pike_fp->return_addr);                        \
01948   if(low_mega_apply(TYPE, 0,                                               \
01949                     ARG2, ARG3))                                           \
01950   {                                                                        \
01951     Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL;                          \
01952     DO_JUMP_TO(Pike_fp->pc);                                               \
01953   }                                                                        \
01954   else {                                                                \
01955     DO_JUMP_TO_NEXT;                                                    \
01956   }                                                                     \
01957 });                                                                        \
01958                                                                            \
01959 PIKE_CONCAT(OP,_JUMP)(PIKE_CONCAT3(F_MARK_,OPCODE,_AND_POP),            \
01960                       "mark, " NAME " & pop",                           \
01961                       I_UPDATE_ALL, {                                   \
01962   JUMP_SET_TO_PC_AT_NEXT (Pike_fp->return_addr);                        \
01963   if(low_mega_apply(TYPE, 0,                                               \
01964                     ARG2, ARG3))                                           \
01965   {                                                                        \
01966     Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL | PIKE_FRAME_RETURN_POP;  \
01967     DO_JUMP_TO(Pike_fp->pc);                                               \
01968   }else{                                                                   \
01969     pop_stack();                                                           \
01970     DO_JUMP_TO_NEXT;                                                    \
01971   }                                                                        \
01972 });                                                                        \
01973                                                                            \
01974 PIKE_CONCAT(OP,_RETURN)(PIKE_CONCAT3(F_MARK_,OPCODE,_AND_RETURN),          \
01975                         "mark, " NAME " & return",                      \
01976                         I_UPDATE_ALL, {                 \
01977   if(low_mega_apply(TYPE, 0,                                               \
01978                     ARG2,ARG3))                                            \
01979   {                                                                        \
01980     PIKE_OPCODE_T *addr = Pike_fp->pc;                                     \
01981     DO_IF_DEBUG(Pike_fp->next->pc=0);                                      \
01982     unlink_previous_frame();                                               \
01983     DO_JUMP_TO(addr);                                                      \
01984   }else{                                                                   \
01985     DO_DUMB_RETURN;                                                        \
01986   }                                                                        \
01987 })
01988 
01989 
01990 MKAPPLY2(OPCODE1,CALL_LFUN,"call lfun",APPLY_LOW,
01991          Pike_fp->current_object,
01992          (void *)(ptrdiff_t)(arg1+Pike_fp->context.identifier_level));
01993 
01994 MKAPPLY2(OPCODE1,APPLY,"apply",APPLY_SVALUE_STRICT,
01995          &((Pike_fp->context.prog->constants + arg1)->sval),0);
01996 
01997 MKAPPLY(OPCODE0,CALL_FUNCTION,"call function",APPLY_STACK, 0,0);
01998 
01999 OPCODE1_JUMP(F_CALL_OTHER,"call other", I_UPDATE_ALL, {
02000   INT32 args=DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp));
02001   LOCAL_VAR(struct svalue *s);
02002   s = Pike_sp-args;
02003   JUMP_SET_TO_PC_AT_NEXT (Pike_fp->return_addr);
02004   if(s->type == T_OBJECT)
02005   {
02006     LOCAL_VAR(struct object *o);
02007     LOCAL_VAR(struct program *p);
02008     o = s->u.object;
02009     if((p=o->prog))
02010     {
02011       p = p->inherits[s->subtype].prog;
02012       if(FIND_LFUN(p, LFUN_ARROW) == -1)
02013       {
02014         int fun;
02015         fun=find_shared_string_identifier(Pike_fp->context.prog->strings[arg1],
02016                                           p);
02017         if(fun >= 0)
02018         {
02019           fun += o->prog->inherits[s->subtype].identifier_level;
02020           if(low_mega_apply(APPLY_LOW, args-1, o, (void *)(ptrdiff_t)fun))
02021           {
02022             Pike_fp->save_sp--;
02023             Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL;
02024             DO_JUMP_TO(Pike_fp->pc);
02025           }
02026           stack_pop_keep_top();
02027           DO_JUMP_TO_NEXT;
02028         }
02029       }
02030     }
02031   }
02032 
02033   {
02034     LOCAL_VAR(struct svalue tmp);
02035     LOCAL_VAR(struct svalue tmp2);
02036 
02037     tmp.type=PIKE_T_STRING;
02038     tmp.u.string=Pike_fp->context.prog->strings[arg1];
02039     tmp.subtype=1;
02040 
02041     index_no_free(&tmp2, s, &tmp);
02042     free_svalue(s);
02043     move_svalue (s, &tmp2);
02044     print_return_value();
02045 
02046     if(low_mega_apply(APPLY_STACK, args, 0, 0))
02047     {
02048       Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL;
02049       DO_JUMP_TO(Pike_fp->pc);
02050     }
02051     else {
02052       DO_JUMP_TO_NEXT;
02053     }
02054   }
02055 });
02056 
02057 OPCODE1_JUMP(F_CALL_OTHER_AND_POP,"call other & pop", I_UPDATE_ALL, {
02058   INT32 args=DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp));
02059   LOCAL_VAR(struct svalue *s);
02060   s = Pike_sp-args;
02061   JUMP_SET_TO_PC_AT_NEXT (Pike_fp->return_addr);
02062   if(s->type == T_OBJECT)
02063   {
02064     LOCAL_VAR(struct object *o);
02065     LOCAL_VAR(struct program *p);
02066     o = s->u.object;
02067     if((p=o->prog))
02068     {
02069       p = p->inherits[s->subtype].prog;
02070       if(FIND_LFUN(p, LFUN_ARROW) == -1)
02071       {
02072         int fun;
02073         fun=find_shared_string_identifier(Pike_fp->context.prog->strings[arg1],
02074                                           p);
02075         if(fun >= 0)
02076         {
02077           fun += o->prog->inherits[s->subtype].identifier_level;
02078           if(low_mega_apply(APPLY_LOW, args-1, o, (void *)(ptrdiff_t)fun))
02079           {
02080             Pike_fp->save_sp--;
02081             Pike_fp->flags |=
02082               PIKE_FRAME_RETURN_INTERNAL |
02083               PIKE_FRAME_RETURN_POP;
02084             DO_JUMP_TO(Pike_fp->pc);
02085           }
02086           pop_2_elems();
02087           DO_JUMP_TO_NEXT;
02088         }
02089       }
02090     }
02091   }
02092 
02093   {
02094     LOCAL_VAR(struct svalue tmp);
02095     LOCAL_VAR(struct svalue tmp2);
02096 
02097     tmp.type=PIKE_T_STRING;
02098     tmp.u.string=Pike_fp->context.prog->strings[arg1];
02099     tmp.subtype=1;
02100 
02101     index_no_free(&tmp2, s, &tmp);
02102     free_svalue(s);
02103     move_svalue (s, &tmp2);
02104     print_return_value();
02105 
02106     if(low_mega_apply(APPLY_STACK, args, 0, 0))
02107     {
02108       Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL | PIKE_FRAME_RETURN_POP;
02109       DO_JUMP_TO(Pike_fp->pc);
02110     }
02111     else {
02112       pop_stack();
02113       DO_JUMP_TO_NEXT;
02114     }
02115   }
02116 });
02117 
02118 OPCODE1_JUMP(F_CALL_OTHER_AND_RETURN,"call other & return", I_UPDATE_ALL, {
02119   INT32 args=DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp));
02120   LOCAL_VAR(struct svalue *s);
02121   s = Pike_sp - args;
02122   if(s->type == T_OBJECT)
02123   {
02124     LOCAL_VAR(struct object *o);
02125     LOCAL_VAR(struct program *p);
02126     o = s->u.object;
02127     if((p=o->prog))
02128     {
02129       p = p->inherits[s->subtype].prog;
02130       if(FIND_LFUN(p, LFUN_ARROW) == -1)
02131       {
02132         int fun;
02133         fun=find_shared_string_identifier(Pike_fp->context.prog->strings[arg1],
02134                                           p);
02135         if(fun >= 0)
02136         {
02137           fun += o->prog->inherits[s->subtype].identifier_level;
02138           if(low_mega_apply(APPLY_LOW, args-1, o, (void *)(ptrdiff_t)fun))
02139           {
02140             PIKE_OPCODE_T *addr = Pike_fp->pc;
02141             Pike_fp->save_sp--;
02142             DO_IF_DEBUG(Pike_fp->next->pc=0);
02143             unlink_previous_frame();
02144             DO_JUMP_TO(addr);
02145           }
02146           stack_pop_keep_top();
02147           DO_DUMB_RETURN;
02148         }
02149       }
02150     }
02151   }
02152 
02153   {
02154     LOCAL_VAR(struct svalue tmp);
02155     LOCAL_VAR(struct svalue tmp2);
02156 
02157     tmp.type=PIKE_T_STRING;
02158     tmp.u.string=Pike_fp->context.prog->strings[arg1];
02159     tmp.subtype=1;
02160 
02161     index_no_free(&tmp2, s, &tmp);
02162     free_svalue(s);
02163     move_svalue (s, &tmp2);
02164     print_return_value();
02165 
02166     if(low_mega_apply(APPLY_STACK, args, 0, 0))
02167     {
02168       PIKE_OPCODE_T *addr = Pike_fp->pc;
02169       DO_IF_DEBUG(Pike_fp->next->pc=0);
02170       unlink_previous_frame();
02171       DO_JUMP_TO(addr);
02172     }
02173     DO_DUMB_RETURN;
02174   }
02175 });
02176 
02177 #undef DO_CALL_BUILTIN
02178 #ifdef PIKE_DEBUG
02179 #define DO_CALL_BUILTIN(ARGS) do {                                       \
02180   int args=(ARGS);                                                       \
02181   struct svalue *expected_stack=Pike_sp-args;                            \
02182   LOCAL_VAR(struct svalue *s);                                           \
02183   s = &Pike_fp->context.prog->constants[arg1].sval;                      \
02184   if(Pike_interpreter.trace_level)                                       \
02185   {                                                                      \
02186     LOCAL_VAR(dynamic_buffer save_buf);                                  \
02187     init_buf(&save_buf);                                                 \
02188     if (s->u.efun->name->size_shift)                                     \
02189       my_strcat ("[widestring function name]");                          \
02190     else                                                                 \
02191       my_strcat (s->u.efun->name->str);                                  \
02192     do_trace_call(args, &save_buf);                                      \
02193   }                                                                      \
02194   (*(s->u.efun->function))(args);                                        \
02195   s->u.efun->runs++;                                                     \
02196   if(Pike_sp != expected_stack + !s->u.efun->may_return_void)            \
02197   {                                                                      \
02198     if(Pike_sp < expected_stack)                                         \
02199       Pike_fatal("Function popped too many arguments: %s\n",             \
02200             s->u.efun->name->str);                                       \
02201     if(Pike_sp>expected_stack+1)                                         \
02202       Pike_fatal("Function left %"PRINTPTRDIFFT"d droppings on stack: %s\n", \
02203            Pike_sp-(expected_stack+1),                                   \
02204             s->u.efun->name->str);                                       \
02205     if(Pike_sp == expected_stack && !s->u.efun->may_return_void)         \
02206       Pike_fatal("Non-void function returned without return value "      \
02207             "on stack: %s %d\n",                                         \
02208             s->u.efun->name->str,s->u.efun->may_return_void);            \
02209     if(Pike_sp==expected_stack+1 && s->u.efun->may_return_void)          \
02210       Pike_fatal("Void function returned with a value on the stack: %s %d\n", \
02211             s->u.efun->name->str, s->u.efun->may_return_void);           \
02212   }                                                                      \
02213   if(Pike_interpreter.trace_level>1) {                                   \
02214     LOCAL_VAR(dynamic_buffer save_buf);                                  \
02215     init_buf(&save_buf);                                                 \
02216     if (s->u.efun->name->size_shift)                                     \
02217       my_strcat ("[widestring function name]");                          \
02218     else                                                                 \
02219       my_strcat (s->u.efun->name->str);                                  \
02220     my_strcat ("() ");                                                   \
02221     do_trace_return (Pike_sp>expected_stack, &save_buf);                 \
02222   }                                                                      \
02223 }while(0)
02224 #else
02225 #define DO_CALL_BUILTIN(ARGS) \
02226 (*(Pike_fp->context.prog->constants[arg1].sval.u.efun->function))(ARGS)
02227 #endif
02228 
02229 OPCODE1(F_CALL_BUILTIN, "call builtin", I_UPDATE_ALL, {
02230   DO_CALL_BUILTIN(DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp)));
02231 });
02232 
02233 OPCODE1(F_CALL_BUILTIN_AND_POP,"call builtin & pop", I_UPDATE_ALL, {
02234   DO_CALL_BUILTIN(DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp)));
02235   pop_stack();
02236 });
02237 
02238 OPCODE1_RETURN(F_CALL_BUILTIN_AND_RETURN,"call builtin & return", I_UPDATE_ALL, {
02239   DO_CALL_BUILTIN(DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp)));
02240   DO_DUMB_RETURN;
02241 });
02242 
02243 
02244 OPCODE1(F_MARK_CALL_BUILTIN, "mark, call builtin", I_UPDATE_ALL, {
02245   DO_CALL_BUILTIN(0);
02246 });
02247 
02248 OPCODE1(F_MARK_CALL_BUILTIN_AND_POP, "mark, call builtin & pop", 0, {
02249   DO_CALL_BUILTIN(0);
02250   pop_stack();
02251 });
02252 
02253 OPCODE1_RETURN(F_MARK_CALL_BUILTIN_AND_RETURN, "mark, call builtin & return", I_UPDATE_ALL, {
02254   DO_CALL_BUILTIN(0);
02255   DO_DUMB_RETURN;
02256 });
02257 
02258 
02259 OPCODE1(F_CALL_BUILTIN1, "call builtin 1", I_UPDATE_ALL, {
02260   DO_CALL_BUILTIN(1);
02261 });
02262 
02263 OPCODE1(F_CALL_BUILTIN1_AND_POP, "call builtin1 & pop", I_UPDATE_ALL, {
02264   DO_CALL_BUILTIN(1);
02265   pop_stack();
02266 });
02267 
02268 #ifndef ENTRY_PROLOGUE_SIZE
02269 #define ENTRY_PROLOGUE_SIZE 0
02270 #endif /* !ENTRY_PROLOGUE_SIZE */
02271 
02272 #define DO_RECUR(XFLAGS) do{                                               \
02273   PIKE_OPCODE_T *addr;                                                     \
02274   register struct pike_frame *new_frame;                                   \
02275   ptrdiff_t args;                                                          \
02276                                                                            \
02277   DO_IF_SECURITY(CHECK_DATA_SECURITY_OR_ERROR(Pike_fp->current_object,     \
02278                                               SECURITY_BIT_CALL,           \
02279                                 ("Function call permission denied.\n")));  \
02280                                                                            \
02281   fast_check_threads_etc(6);                                               \
02282   check_stack(256);                                                        \
02283                                                                            \
02284   new_frame=alloc_pike_frame();                                            \
02285                                                                            \
02286   new_frame->refs=1;    /* FIXME: Is this needed? */                       \
02287   new_frame->next=Pike_fp;                                                 \
02288                                                                            \
02289   JUMP_SET_TO_PC_AT_NEXT (addr);                                        \
02290   Pike_fp->return_addr = (PIKE_OPCODE_T *)(((INT32 *) addr) + 1);       \
02291   addr += GET_JUMP();                                                   \
02292                                                                            \
02293   new_frame->num_locals = READ_INCR_BYTE(addr);                            \
02294   args = READ_INCR_BYTE(addr);                                             \
02295   addr += ENTRY_PROLOGUE_SIZE;                                             \
02296                                                                            \
02297   new_frame->num_args = new_frame->args = args;                            \
02298   new_frame->locals=new_frame->save_sp=new_frame->expendible=Pike_sp-args; \
02299   new_frame->save_mark_sp = new_frame->mark_sp_base = Pike_mark_sp;        \
02300                                                                            \
02301   push_zeroes(new_frame->num_locals - args);                               \
02302                                                                            \
02303   DO_IF_DEBUG({                                                            \
02304     if(Pike_interpreter.trace_level > 3)                                   \
02305       fprintf(stderr,"-    Allocating %d extra locals.\n",                 \
02306               new_frame->num_locals - new_frame->num_args);                \
02307     if (Pike_fp && (new_frame->locals < Pike_fp->locals)) {                \
02308       fatal("New locals below old locals: %p < %p\n",                      \
02309             new_frame->locals, Pike_fp->locals);                           \
02310     }                                                                      \
02311   });                                                                      \
02312                                                                            \
02313                                                                            \
02314   SET_PROG_COUNTER(addr);                                                  \
02315   new_frame->fun=Pike_fp->fun;                                             \
02316   DO_IF_PROFILING( new_frame->ident=Pike_fp->ident );                      \
02317   new_frame->current_storage=Pike_fp->current_storage;                     \
02318   if(Pike_fp->scope) add_ref(new_frame->scope=Pike_fp->scope);             \
02319   add_ref(new_frame->current_object=Pike_fp->current_object);              \
02320   new_frame->context=Pike_fp->context;                                     \
02321   add_ref(new_frame->context.prog);                                        \
02322   if(new_frame->context.parent)                                            \
02323     add_ref(new_frame->context.parent);                                    \
02324                                                                            \
02325   DO_IF_PROFILING({                                                        \
02326       new_frame->start_time =                                              \
02327         get_cpu_time() - Pike_interpreter.unlocked_time;                   \
02328       new_frame->ident = Pike_fp->ident;                                   \
02329       new_frame->children_base = Pike_interpreter.accounted_time;          \
02330       new_frame->context.prog->identifiers[new_frame->ident].num_calls++;  \
02331       DO_IF_PROFILING_DEBUG({                                              \
02332           fprintf(stderr, "%p{: Push at %" PRINT_CPU_TIME                  \
02333                   " %" PRINT_CPU_TIME "\n",                                \
02334                   Pike_interpreter.thread_state, new_frame->start_time,    \
02335                   new_frame->children_base);                               \
02336         });                                                                \
02337     });                                                                    \
02338                                                                            \
02339   Pike_fp=new_frame;                                                       \
02340   new_frame->flags=PIKE_FRAME_RETURN_INTERNAL | XFLAGS;                    \
02341                                                                            \
02342   DO_IF_SECURITY(if(!CHECK_DATA_SECURITY(Pike_fp->current_object,          \
02343                                          SECURITY_BIT_NOT_SETUID))         \
02344                    SET_CURRENT_CREDS(Pike_fp->current_object->prot));      \
02345                                                                            \
02346   FETCH;                                                                   \
02347   JUMP_DONE;                                                            \
02348 }while(0)
02349 
02350 /* Assume that the number of arguments is correct */
02351 OPCODE1_PTRJUMP(F_COND_RECUR, "recur if not overloaded", I_UPDATE_ALL, {
02352   PIKE_OPCODE_T *addr;
02353   LOCAL_VAR(struct program *p);
02354   p = Pike_fp->current_object->prog;
02355   JUMP_SET_TO_PC_AT_NEXT (addr);
02356   Pike_fp->return_addr = (PIKE_OPCODE_T *)(((INT32 *)addr) + 1);
02357 
02358   /* Test if the function is overloaded.
02359    *
02360    * Note: The second part of the test is sufficient, but
02361    *       the since first case is much simpler to test and
02362    *       is common, it should offer a speed improvement.
02363    *
02364    *    /grubba 2002-11-14
02365    *
02366    * Also test if the function uses scoping. DO_RECUR() doesn't
02367    * adjust fp->expendible which will make eg RETURN_LOCAL fail.
02368    *
02369    *    /grubba 2003-03-25
02370    */
02371   if(((p != Pike_fp->context.prog) &&
02372       (p->inherits[p->identifier_references[Pike_fp->context.identifier_level +
02373                                            arg1].inherit_offset].prog !=
02374        Pike_fp->context.prog)) ||
02375      (ID_FROM_INT(p, arg1+Pike_fp->context.identifier_level)->
02376       identifier_flags & IDENTIFIER_SCOPE_USED))
02377   {
02378     PIKE_OPCODE_T *faddr;
02379     ptrdiff_t num_locals;
02380     ptrdiff_t args;
02381 
02382     JUMP_SET_TO_PC_AT_NEXT (faddr);
02383     faddr += GET_JUMP();
02384     num_locals = READ_INCR_BYTE(faddr); /* ignored */
02385     args = READ_INCR_BYTE(faddr);
02386 
02387     if(low_mega_apply(APPLY_LOW,
02388                       args,
02389                       Pike_fp->current_object,
02390                       (void *)(ptrdiff_t)(arg1+
02391                                           Pike_fp->context.identifier_level)))
02392     {
02393       Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL;
02394       addr = Pike_fp->pc;
02395     }
02396     DO_JUMP_TO(addr);
02397   }
02398 
02399   /* FALL THROUGH */
02400 
02401   /* Assume that the number of arguments is correct */
02402 
02403   OPCODE0_TAILPTRJUMP(F_RECUR, "recur", I_UPDATE_ALL, {
02404     DO_RECUR(0);
02405   });
02406 });
02407 
02408 /* Ugly code duplication */
02409 OPCODE0_PTRJUMP(F_RECUR_AND_POP, "recur & pop", I_UPDATE_ALL, {
02410   DO_RECUR(PIKE_FRAME_RETURN_POP);
02411 });
02412 
02413 
02414 /* Assume that the number of arguments is correct */
02415 /* FIXME: adjust Pike_mark_sp */
02416 OPCODE0_PTRJUMP(F_TAIL_RECUR, "tail recursion", I_UPDATE_ALL, {
02417   INT32 num_locals;
02418   PIKE_OPCODE_T *addr;
02419   INT32 args;
02420 
02421   fast_check_threads_etc(6);
02422 
02423   JUMP_SET_TO_PC_AT_NEXT (addr);
02424   addr += GET_JUMP();
02425   num_locals = READ_INCR_BYTE(addr);
02426   args = READ_INCR_BYTE(addr);
02427   addr += ENTRY_PROLOGUE_SIZE;
02428   SET_PROG_COUNTER(addr);
02429 
02430   if(Pike_sp-args != Pike_fp->locals)
02431   {
02432     DO_IF_DEBUG({
02433       if (Pike_sp < Pike_fp->locals + args)
02434         Pike_fatal("Pike_sp (%p) < Pike_fp->locals (%p) + args (%d)\n",
02435               Pike_sp, Pike_fp->locals, args);
02436     });
02437     assign_svalues(Pike_fp->locals, Pike_sp-args, args, BIT_MIXED);
02438     pop_n_elems(Pike_sp - (Pike_fp->locals + args));
02439   }
02440 
02441   push_zeroes(num_locals - args);
02442 
02443   DO_IF_DEBUG({
02444     if(Pike_sp != Pike_fp->locals + Pike_fp->num_locals)
02445       Pike_fatal("Sp whacked!\n");
02446   });
02447 
02448   FETCH;
02449   JUMP_DONE;
02450 });
02451 
02452 #if 0
02453 /* This opcode needs mending if it is to work with machine code. */
02454 OPCODE0_JUMP(F_BREAKPOINT, "breakpoint", 0, {
02455   extern void o_breakpoint(void);
02456   o_breakpoint();
02457   DO_JUMP_TO(PROG_COUNTER-1);
02458 });
02459 #endif
02460 
02461 OPCODE1(F_THIS_OBJECT, "this_object", I_UPDATE_SP, {
02462     int level;
02463     LOCAL_VAR(struct object *o);
02464     o = Pike_fp->current_object;
02465     for (level = 0; level < arg1; level++) {
02466       LOCAL_VAR(struct program *p);
02467       p = o->prog;
02468       if (!p)
02469         Pike_error ("Object %d level(s) up is destructed - cannot get the parent.\n",
02470                     level);
02471       if (!(p->flags & PROGRAM_USES_PARENT))
02472         /* FIXME: Ought to write out the object here. */
02473         Pike_error ("Object %d level(s) up lacks parent reference.\n", level);
02474       o = PARENT_INFO(o)->parent;
02475     }
02476     ref_push_object(o);
02477   });
02478 
02479 OPCODE0(F_ZERO_TYPE, "zero_type", 0, {
02480   if(Pike_sp[-1].type != T_INT)
02481   {
02482     if((Pike_sp[-1].type==T_OBJECT || Pike_sp[-1].type==T_FUNCTION)
02483        && !Pike_sp[-1].u.object->prog)
02484     {
02485       pop_stack();
02486       push_int(NUMBER_DESTRUCTED);
02487     }else{
02488       pop_stack();
02489       push_int(0);
02490     }
02491   }else{
02492     Pike_sp[-1].u.integer=Pike_sp[-1].subtype;
02493     Pike_sp[-1].subtype=NUMBER_NUMBER;
02494   }
02495 });
02496 
02497 OPCODE0(F_SWAP,"swap",0,{
02498   stack_swap();
02499 });
02500 
02501 OPCODE0(F_DUP,"dup",I_UPDATE_SP,{
02502   stack_dup();
02503 });
02504 
02505 OPCODE2(F_THIS, "this", I_UPDATE_SP, {
02506     LOCAL_VAR(struct external_variable_context loc);
02507 
02508     loc.o = Pike_fp->current_object;
02509     loc.parent_identifier = Pike_fp->fun;
02510     if (loc.o->prog)
02511       loc.inherit = INHERIT_FROM_INT(loc.o->prog, loc.parent_identifier);
02512     find_external_context(&loc, arg1);
02513 
02514     DO_IF_DEBUG({
02515       TRACE((5,"-   Identifier=%d Offset=%d\n",
02516              arg1,
02517              loc.inherit->identifier_level));
02518     });
02519     if (loc.o->prog && arg2) {
02520       /* FIXME: Might want to be able refer to the non overloaded object
02521        *        (ie arg2 == 0) in the future.
02522        *        /grubba 2004-12-19
02523        */
02524       ref_push_object_inherit(loc.o,
02525                               (loc.inherit - loc.o->prog->inherits) + arg2);
02526     } else {
02527       /* Destructed or top-level. */
02528       ref_push_object(loc.o);
02529     }
02530     print_return_value();
02531 });
02532 
02533 /*
02534 #undef PROG_COUNTER
02535 */

Generated on Fri Jul 22 23:44:25 2005 for Pike by  doxygen 1.3.9.1