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

interpret_functions_fixed.h

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

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