1 /*---------------------------------------------------------------------------
2  * Gamedriver: Bytecode Interpreter
3  *
4  *---------------------------------------------------------------------------
5  * This module implements the bytecode interpreter for the compiled LPC
6  * programs. The machine is implemented as a stackmachine with separate
7  * stacks for values and control.
8  *
9  * See also 'exec.h' for the details of program storage, and 'svalue.h'
10  * for the details of value storage.
11  *
12  * --- Evaluator Stack ---
13  *
14  *    The evaluation stack is an array of 'svalue_t's (see datatypes.h
15  *    for information about this type) with EVALUATOR_SIZE<<1 elements.
16  *    <inter_sp> resp. <sp> points to the last (that is topmost) valid
17  *    entry in the stack, the framepointer <inter_fp> resp. <fp> points
18  *    to the bottom of the frame of one function. Single values in the
19  *    frame are then accessed by indexing the frame pointer.
20  *    A typical stack layout looks like this:
21  *
22  *                    ^
23  *    (inter_)sp   -> |  Top stack value
24  *                    |  ...
25  *                    |  Temporary stack values
26  *                    |  Break addresses for switch instructions
27  *    break_sp     -> |   (forming a sub-stack growing _down_).
28  *                    |  ...
29  *                    |  Local variable number 1
30  *                    |  Local variable number 0
31  *                    |  ...
32  *                    |  Argument number 1
33  *    (inter_)fp   -> |  Argument number 0
34  *                    |
35  *                    |
36  *    VALUE_STACK     -----
37  *
38  *    The interpreter assumes that there are no destructed objects
39  *    on the stack - to aid in this, the functions remove_object_from_stack()
40  *    and (in array.c) check_for_destr() replace destructed objects by
41  *    value 0.
42  *
43  *
44 #ifdef USE_NEW_INLINES
45  * --- Context Variables ---
46  *
47  *    In order to implement 'real' inline closures, lfun closure carry with
48  *    them a set of svalue_t's, called the 'context'. When such a closure
49  *    is created, the context is filled with values from selected local
50  *    function variables.
51  *
52  *    The interpreter keeps the pointer <inter_context> pointed to the
53  *    currently value context, if there is one, or NULL if there is no
54  *    context. The context variables are accessed with a set of instructions
55  *    mirroring those to access object variables.
56  *
57  *    TODO: In fact, these contexts could be implemented as light-weight
58  *    TODO:: objects, removing the need for special cases.
59  *
60  *
61 #endif
62  * --- Control Stack ---
63  *
64  *    During nested function calls, the return information to the higher
65  *    functions are stored on the control stack.
66  *
67  *    One particularity about the current implementation is that every
68  *    inter-object call (ie. every 'extern_call') and every catch()
69  *    constitutes in a recursive call to eval_instruction().
70  *
71  *
72  * --- Error Recovery Stack --- (implemented in backend.c)
73  *
74  *    Error recovery in general is implemented using setjmp()/longjmp().
75  *    The error recovery stack holds the (possibly nested) longjmp() contexts
76  *    together with an indication where the jump will lead. Currently these
77  *    context types are defined:
78  *      ERROR_RECOVERY_NONE:     No error recovery available
79  *                               (used by the top entry in the stack)
80  *      ERROR_RECOVERY_BACKEND:  Errors fall back to the backend,
81  *                               e.g. process_objects(), call_heart_beat()
82  *                               and others.
83  *      ERROR_RECOVERY_APPLY:    Errors fall back into the secure_apply()
84  *                               function used for sensitive applies.
85  *      ERROR_RECOVERY_CATCH:    Errors are caught by the catch() construct.
86  *
87  *    The _CATCH contexts differs from the others in that it allows the
88  *    continuing execution after the error. In order to achieve this, the
89  *    stack entry holds the necessary additional information to re-init
90  *    the interpreter.
91  *    TODO: Elaborate on the details.
92  *
93  *
94  * --- Bytecode ---
95  *
96  *    The machine instructions are stored as unsigned characters and read
97  *    sequentially. A single machine instruction consists of one or two
98  *    bytes defining the instruction, optionally followed by more bytes
99  *    with parameters (e.g. number of arguments on the stack, branch offsets,
100  *    etc).
101  *
102  *    Apart from the usual machine instructions (branches, stack
103  *    manipulation, summarily called 'codes'), the machine implements every
104  *    efun by its own instruction code. Since this leads to more than
105  *    256 instructions, the most of the efuns are encoded using prefix
106  *    bytes. The unprefixed opcodes in the range 0..255 are used for the
107  *    internal machine instructions and LPC operators, and for the small
108  *    and/or often used efuns. The prefix byte for the other efun
109  *    instructions reflects the type of the efun:
110  *
111  *      F_EFUN0: efuns taking no argument
112  *      F_EFUN1: efuns taking one argument
113  *      F_EFUN2: efuns taking two arguments
114  *      F_EFUN3: efuns taking three arguments
115  *      F_EFUN4: efuns taking four arguments
116  *      F_EFUNV: efuns taking more than four or a variable number of arguments
117  *
118  *    The implementation is such that the unprefixed instructions are
119  *    implemented directly in the interpreter loop in a big switch()
120  *    statement, whereas the prefixed instructions are implemented
121  *    in separate functions and called via the lookup tables efun_table[]
122  *    and vefun_table[].
123  *
124  *    Every machine instruction, efun or else, is assigned a unique number
125  *    and a preprocessor symbol F_<name>. The exact translation into
126  *    the prefix/opcode bytecodes depends on the number of instructions
127  *    in the various classes, but is linear and holds the following
128  *    conditions:
129  *
130  *       - all non-efun instructions do not need a prefix byte and start
131  *         at instruction code 0.
132  *       - selected efuns also don't need a prefix byte and directly follow
133  *         the non-efun instructions.
134  *       - the instruction codes for all tabled efuns are consecutive.
135  *       - the instruction codes for all tabled varargs efuns are consecutive.
136  *
137  *    All existing machine instructions are defined in the file func_spec,
138  *    which during the compilation of the driver is evaluated by make_func.y
139  *    to create the LPC compiler lang.y from prolang.y, the symbolic
140  *    instruction names and numbers in instrs.h, and the definition of the
141  *    tables efuns in efun_defs.c .
142  *
143  *
144  * --- Calling Convention ---
145  *
146  *    All arguments for a function are evaluated and pushed to the value
147  *    stack. The last argument is the last pushed. It is important that
148  *    the called function gets exactly as many arguments as it wants; for
149  *    LPC functions ('lfuns') this means that the actual function call will
150  *    remove excessive arguments or push '0's for missing arguments. The
151  *    number of arguments will be stored in the control stack, so that
152  *    the return instruction not needs to know it explicitely.
153  *
154  *    If the function called is an lfun (inherited or not), the number
155  *    of arguments passed to the call is encoded in the bytecode stream,
156  *    and the number of arguments expected can be determined from the
157  *    functions 'struct function' entry.
158  *
159  *    Efuns, operators and internal bytecode usually operate on a fixed
160  *    number of arguments and the compiler makes sure that the right
161  *    number is given. If an efun takes a variable number of arguments,
162  *    the actual number is stored in the byte following the efun's opcode.
163  *
164  *    The called function must ensure that exactly one value remains on the
165  *    stack when returning. The caller is responsible of deallocating the
166  *    returned value. This includes 'void' lfuns, which just push the
167  *    value 0 as return value.
168  *
169  *    When a LPC function returns, it will use the instruction F_RETURN, which
170  *    will deallocate all arguments and local variables, and only let the
171  *    top of stack entry remain. The number of arguments and local variables
172  *    are stored in the control stack, so that the evaluator knows how much
173  *    to deallocate.
174  *
175  *    If flag 'extern_call' is set, then the evaluator should return from
176  *    eval_instruction(). Otherwise, the evaluator will continue to execute
177  *    the instruction at the returned address. In the current implementation,
178  *    every inter-object call (call_other) receives its own (recursive)
179  *    call to eval_instruction().
180  *
181  *---------------------------------------------------------------------------
182  * TODO: The virtual machine should be reconsidered, using the DGD and MudOS
183  * TODO:: machines for inspiration. This applies to implementation as well
184  * TODO:: as to the instruction set.
185  * TODO: Let all assign_ and transfer_ functions check for destruct objects.
186  * TODO:: The speed difference to assign_checked_ and transfer_checked_ is
187  * TODO:: not big enough to justify the extra set of functions.
188  */
189 
190 /*-------------------------------------------------------------------------*/
191 
192 #include "driver.h"
193 #include "typedefs.h"
194 
195 #include "my-alloca.h"
196 #include <stdarg.h>
197 #include <stddef.h>
198 #include <stdio.h>
199 #include <setjmp.h>
200 #include <ctype.h>
201 #ifdef HAVE_SYS_TIME_H
202 #include <sys/time.h>
203 #endif
204 #include <time.h>
205 #include <sys/types.h>
206 #include <sys/stat.h>
207 #ifdef MARK
208 #include "profile.h"
209 #endif
210 
211 #include "interpret.h"
212 
213 #include "actions.h"
214 #include "array.h"
215 #include "backend.h"
216 #include "call_out.h"
217 #include "closure.h"
218 #include "comm.h"
219 #include "efuns.h"
220 #include "exec.h"
221 #include "filestat.h"
222 #include "gcollect.h"
223 #include "heartbeat.h"
224 #include "instrs.h"
225 #include "lex.h"
226 #include "mapping.h"
227 #include "mstrings.h"
228 #include "object.h"
229 #include "otable.h"
230 #include "parse.h"
231 #include "prolang.h"
232 #include "simulate.h"
233 #include "simul_efun.h"
234 #include "stdstrings.h"
235 #ifdef USE_STRUCTS
236 #include "structs.h"
237 #endif /* USE_STRUCTS */
238 #include "svalue.h"
239 #include "swap.h"
240 #include "switch.h"
241 #include "wiz_list.h"
242 #include "xalloc.h"
243 
244 #include "i-eval_cost.h"
245 
246 #include "../mudlib/sys/driver_hook.h"
247 #include "../mudlib/sys/debug_info.h"
248 #include "../mudlib/sys/trace.h"
249 
250 /*-------------------------------------------------------------------------*/
251 /* Types */
252 
253 /* --- struct catch_context: error_recovery subclass for catch() ---
254  *
255  * This extension of the struct error_recovery_info (see backend.h)
256  * stores the additional information needed to reinitialize the global
257  * variables when bailing out of a catch(). The type is always
258  * ERROR_RECOVERY_CATCH.
259  *
260  * It is handled by the functions push_, pop_ and pull_error_context().
261  */
262 
263 struct catch_context
264 {
265     struct error_recovery_info recovery_info;
266       /* The subclassed recovery info.
267        */
268     struct control_stack * save_csp;
269     object_t             * save_command_giver;
270     svalue_t             * save_sp;
271       /* The saved global values
272        */
273 
274     svalue_t catch_value;
275       /* Holds the value throw()n from within a catch() while the throw
276        * is executed.
277        */
278 };
279 
280 /* --- struct cache: one entry of the apply cache
281  *
282  * Every entry in the apply cache holds information about a function
283  * call, both for functions found and not found.
284  */
285 
286 struct cache
287 {
288     string_t *name;
289       /* The name of the cached function, shared for existing functions,
290        * allocated if the object does not have the function.
291        * This pointer counts as reference.
292        */
293     program_t *progp;
294       /* The pointer to the program code of the function, or NULL if the
295        * object does not implement the function.
296        */
297     int32 id;
298       /* The id_number of the program. */
299 
300     funflag_t flags;
301       /* Copy of the _MOD_STATIC and _MOD_PROTECTED flags of the function.
302        */
303     fun_hdr_p funstart;
304       /* Pointer to the function.
305        */
306     int function_index_offset;
307     int variable_index_offset;
308       /* Function and variable index offset.
309        */
310 };
311 
312 /*-------------------------------------------------------------------------*/
313 /* Macros */
314 
315 #define ERRORF(s) do{inter_pc = pc; inter_sp = sp; errorf s ;}while(0)
316 #define ERROR(s) ERRORF((s))
317   /* ERRORF((...)) acts like errorf(...), except that first the local pc and sp
318    * are copied into the global variables.
319    * ERROR() is an easier to type form of ERRORF() when your error message
320    * is just one string. It will be redefined below for the tabled
321    * efuns.
322    */
323 
324 #define WARNF(s) do{inter_pc = pc; inter_sp = sp; warnf s ;}while(0)
325 #define WARN(s) WARNF((s))
326 #define FATALF(s) do{inter_pc = pc; inter_sp = sp; fatal s ;}while(0)
327 #define FATAL(s) FATALF((s))
328   /* Analogue.
329    */
330 
331 #if APPLY_CACHE_BITS < 1
332 #    error APPLY_CACHE_BITS must be at least 1.
333 #else
334 #    define CACHE_SIZE (1 << APPLY_CACHE_BITS)
335 #endif
336   /* Number of entries in the apply cache.
337    */
338 #if CACHE_SIZE > INT_MAX
339 #error CACHE_SIZE is > INT_MAX.
340 #endif
341   /* sanity check - some function rely that CACHE_SIZE fits into int */
342 
343 /*-------------------------------------------------------------------------*/
344 /* Tracing */
345 
346 #if TOTAL_TRACE_LENGTH > INT_MAX
347 #error TOTAL_TRACE_LENGTH is > INT_MAX.
348 #endif
349 /* sanity check - some function rely that TOTAL_TRACE_LENGTH fits into int */
350 
351 int tracedepth;
352   /* Current depth of traced functions.
353    */
354 
355 int trace_level;
356   /* Current set of active trace options.
357    * This set can be different from interactive->trace_level if several
358    * nested trace() calls occur.
359    */
360 
361 static int traceing_recursion = -1;
362   /* Kind of mutex, used to turn off tracing while doing trace output.
363    * Necessary because output with add_message() might result result
364    * in further code to be executed.
365    */
366 
367 static Bool trace_exec_active = MY_FALSE;
368   /* TRUE whenever TRACE_EXEC is not just requested, but actually
369    * active. This distinction is necessary as tracing might be limited
370    * to one object only, and testing the object name for every instruction
371    * would be too expensive. Hence, the tracing condition is checked
372    * only on object changes and this variable is updated accordingly.
373    * See macros SET_TRACE_EXEC and TRACE_EXEC_P.
374    */
375 
376 #ifdef TRACE_CODE
377 /* The buffers for the traced code:
378  */
379 
380 static int              previous_instruction[TOTAL_TRACE_LENGTH];
381 static ptrdiff_t        stack_size[TOTAL_TRACE_LENGTH];
382 static ptrdiff_t        abs_stack_size[TOTAL_TRACE_LENGTH];
383 static bytecode_p       previous_pc[TOTAL_TRACE_LENGTH];
384 static program_t * previous_programs[TOTAL_TRACE_LENGTH];
385 static object_t  * previous_objects[TOTAL_TRACE_LENGTH];
386   /* These arrays, organized as ring buffers, hold the vitals of the
387    * last TOTAL_TRACE_LENGTH instructions executed. Yet unused entries
388    * are 0 resp. NULL.
389    */
390 
391 static int              last = TOTAL_TRACE_LENGTH - 1;
392   /* Index to the last used entry in the ringbuffers above.
393    */
394 
395 #endif
396 
397 /* --- Macros --- */
398 
399 #define TRACE_IS_INTERACTIVE() (command_giver && O_IS_INTERACTIVE(command_giver))
400 
401   /* Return TRUE if the current command_giver is interactive.
402    * TODO: Instead of disabling all traceoutput whenever the command_giver
403    * TODO:: turns non-interactive, output should be redirected (with a
404    * TODO:: special mark) to the current_interactive.
405    */
406 
407 #define TRACETST(b) (TRACE_IS_INTERACTIVE() && (O_GET_INTERACTIVE(command_giver)->trace_level & (b)))
408 
409   /* Return TRUE if the any of the tracing options <b> are requested
410    * by the interactive user.
411    */
412 
413 #define TRACEP(b) (trace_level & (b) && trace_test(b))
414   /* Return TRUE if tracing options <b> are both active in trace_level
415    * and requested by the interactive user.
416    */
417 
418 #define TRACEHB \
419   ( current_heart_beat == NULL || TRACETST(TRACE_HEART_BEAT))
420 
421   /* Return TRUE if either the current execution is not caused
422    * by a heart beat call, or if heartbeat tracing is allowed.
423    */
424 
425 #define SET_TRACE_EXEC MACRO( \
426                               if (trace_level & TRACE_EXEC) \
427                                   trace_exec_active = MY_TRUE;\
428                             )
429 
430   /* If TRACE_EXEC is requested, (re)activate it.
431    * See trace_exec_active for the background.
432    */
433 
434 #define TRACE_EXEC_P (   TRACEP(TRACE_EXEC) \
435                       || (trace_exec_active = MY_FALSE, MY_FALSE))
436 
437   /* If TRACE_EXEC is still requested, return TRUE, otherwise deactivate
438    * it and return FALSE.
439    * See trace_exec_active for the background.
440    */
441 
442 /*-------------------------------------------------------------------------*/
443 /* The names for the svalue types */
444 
445 static const char * svalue_typename[]
446  = { /* T_INVALID */  "invalid"
447    , /* T_LVALUE  */  "lvalue"
448    , /* T_NUMBER  */  "number"
449    , /* T_STRING  */  "string"
450    , /* T_POINTER */  "array"
451    , /* T_OBJECT  */  "object"
452    , /* T_MAPPING */  "mapping"
453    , /* T_FLOAT   */  "float"
454    , /* T_CLOSURE */  "closure"
455    , /* T_SYMBOL  */  "symbol"
456    , /* T_QUOTED_ARRAY */  "quoted-array"
457    , /* T_STRUCT */  "struct"
458    , /* T_CHAR_LVALUE */           "char-lvalue"
459    , /* T_STRING_RANGE_LVALUE */   "string-range-lvalue"
460    , /* T_POINTER_RANGE_LVALUE */  "array-range-lvalue"
461    , /* T_PROTECTED_CHAR_LVALUE */           "prot-char-lvalue"
462    , /* T_PROTECTED_STRING_RANGE_LVALUE */   "prot-string-range-lvalue"
463    , /* T_PROTECTED_POINTER_RANGE_LVALUE */  "prot-array-range-lvalue"
464    , /* T_PROTECTED_LVALUE  */               "prot-lvalue"
465    , /* T_PROTECTOR_MAPPING  */              "protector-mapping"
466    , /* T_CALLBACK */       "callback-mapping"
467    , /* T_ERROR_HANDLER */  "error-handler"
468    , /* T_NULL */  "null"
469    };
470 
471 /*-------------------------------------------------------------------------*/
472 /* Variables */
473 
474 /* The virtual machine's registers.
475  *
476  * While the interpreter is in eval_instruction(), some of the values are
477  * kept in local variables for greater speed, with the globals being updated
478  * only when necessary.
479  * The affected variables are: inter_pc, inter_sp, TODO: which else?
480  */
481 
482 svalue_t *inter_sp;
483   /* Points to last valid value on the value stack.
484    */
485 bytecode_p inter_pc;
486   /* Next bytecode to interpret.
487    */
488 
489 static svalue_t *inter_fp;
490   /* Framepointer: pointer to first argument.
491    */
492 
493 #ifdef USE_NEW_INLINES
494 static svalue_t *inter_context;
495   /* Contextpointer: pointer to first context variable.
496    * May be NULL if no context is available.
497    */
498 #endif /* USE_NEW_INLINES */
499 
500 static bytecode_p *break_sp;
501   /* Points to address to branch to at next F_BREAK from within a switch().
502    * This is actually a stack of addresses with break_sp pointing to the
503    * bottom with the most recent entry. This break stack is stored on
504    * the evaluator stack, one address per svalue_t (which incidentally
505    * stored in the u.string field), between the functions temporary values
506    * and its local variables.
507    * TODO: Since this stores an opcode* in a svalue, it should get its
508    * TODO:: own union type, and break_sp should be an svalue_t *.
509    */
510 
511 program_t *current_prog;
512   /* The current program. This is usually current_object->prog, but can
513    * differ when executing an inherited program.
514    */
515 
516 static svalue_t current_lambda;
517   /* If the VM is executing a lambda, this variable holds a counted
518    * reference to it to make sure that it isn't destructed while it is
519    * still executing.
520    */
521 
522 static string_t **current_strings;
523   /* Pointer to the string literal block of the current program for
524    * faster access.
525    */
526 
527 int function_index_offset;
528   /* Index of current program's function block within the functions of
529    * the current objects program (needed for inheritance).
530    */
531 
532 static int variable_index_offset;
533   /* Index of current program's variable block within the variables
534    * of the current object (needed for inheritance).
535    */
536 
537 svalue_t *current_variables;
538   /* Pointer to begin of the current variable block.
539    * This is current_object->variables + variable_index_offset for
540    * faster access.
541    */
542 
543 
544 /* Other Variables */
545 
546 int32 eval_cost;
547   /* The amount of eval cost used in the current execution thread.
548    */
549 
550 int32 assigned_eval_cost;
551   /* Auxiliary variable used to account eval costs to single objects and
552    * their user's wizlist entry.
553    * Whenver the execution thread enters a different object,
554    * assigned_eval_cost is set to the current value of eval_cost. When the
555    * thread leaves the object again, the difference between the actual
556    * eval_cost value and the older assigned_eval_cost is accounted to
557    * the current object.
558    * The implementation combines both actions in one function
559    * assign_eval_cost().
560    */
561 
562 svalue_t apply_return_value = { T_NUMBER };
563   /* This variable holds the result from a call to apply(), transferred
564    * properly from the interpreter stack where the called function
565    * left it.
566    * push_ and pop_apply_value() handle this particular transfer.
567    * Note: The process_string() helper function process_value() takes
568    * direct advantage of this variable.
569    */
570 
571 #define SIZEOF_STACK (EVALUATOR_STACK_SIZE<<1)
572 #if SIZEOF_STACK > INT_MAX
573 #error SIZEOF_STACK is > INT_MAX.
574 #endif
575 /* sanity check - some function rely that SIZEOF_STACK fits into int */
576 
577 static svalue_t value_stack_array[SIZEOF_STACK+1];
578 #define VALUE_STACK (value_stack_array+1)
579 
580   /* The evaluator stack, sized with (hopefully) enough fudge to handle
581    * function arguments and overflows.
582    * The stack grows upwards, and <inter_sp> points to last valid entry.
583    *
584    * The first entry of value_stack_array[] is not used and serves as
585    * dummy so that underflows can be detected in a portable way
586    * (Standard C disallows indexing before an array). Instead, VALUE_STACK
587    * is the real bottom of the stack.
588    */
589 
590 #if MAX_TRACE > INT_MAX
591 #error MAX_TRACE is > INT_MAX.
592 #endif
593 #if MAX_USER_TRACE >= MAX_TRACE
594 #error MAX_USER_TRACE value must be smaller than MAX_TRACE!
595 #endif
596   /* Sanity check for the control stack definition.
597    */
598 
599 static struct control_stack control_stack_array[MAX_TRACE+2];
600 #define CONTROL_STACK (control_stack_array+2)
601 struct control_stack *csp;
602   /* The control stack holds copies of the machine registers for previous
603    * function call levels, with <csp> pointing to the last valid
604    * entry, describing the last context.
605    * This also means that CONTROL_STACK[0] (== control_stack_array[2]) will
606    * have almost no interesting values as it will terminate execution.
607    * Especially CONTROL_STACK[0].prog is NULL to mark the bottom.
608    *
609    * The first two entries of control_stack_array[] are not used and
610    * serve as dummies so that underflows can be detected in a portable
611    * way (Standard C disallows indexing before an array).
612    */
613 
614 static Bool runtime_no_warn_deprecated = MY_FALSE;
615   /* Set to TRUE if the current instruction is not to warn about usage
616    * of deprecated features; reset at the end of the instruction.
617    * This flag is set by the NO_WARN_DEPRECATED instruction, generated
618    * by the bytecode compiler in response to the warn-deprecated pragma.
619    */
620 
621 static Bool runtime_array_range_check = MY_FALSE;
622   /* Set to TRUE if the current instruction is to warn about using
623    * an illegal range.
624    * This flag is set by the ARRAY_RANGE_CHECK instruction, generated
625    * by the bytecode compiler in response to the range-check pragma.
626    */
627 
628 #ifdef APPLY_CACHE_STAT
629 p_uint apply_cache_hit  = 0;
630 p_uint apply_cache_miss = 0;
631   /* Number of hits and misses in the apply cache.
632    */
633 #endif
634 
635 static struct cache cache[CACHE_SIZE];
636   /* The apply cache.
637    */
638 
639 static struct
640   {
641     svalue_t v;
642       /* The target value:
643        *   .v.type: T_CHAR_LVALUE
644        *   .v.u.charp: the char to modify
645        * or
646        *   .v.type: T_{POINTER,STRING}_RANGE_LVALUE
647        *   .v.u.{vec,string}: the target value holding the range
648        *   .index1, .index2, .size: see below
649        */
650     mp_int index1;  /* First index of the range */
651     mp_int index2;  /* Last index of the range plus 1 */
652     mp_int size;    /* Current(?) size of the value */
653   }
654 special_lvalue;
655   /* When assigning to vector and string ranges or elements, the
656    * target information is stored in this structure.
657    * TODO: Having one global structure counts as 'ugly'.
658    * Used knowingly by: (r)index_lvalue(), transfer_pointer_range(),
659    *                    assign_string_range().
660    * Used unknowingly by: assign_svalue(), transfer_svalue(),
661    *                    add_number_to_lvalue(), F_VOID_ASSIGN.
662    */
663 
664 static svalue_t indexing_quickfix = { T_NUMBER };
665   /* When indexing arrays and mappings with just one ref, especially
666    * for the purpose of getting a lvalue, the indexed item is copied
667    * into this variable and indexed from here.
668    * Used by operators: push_(r)indexed_lvalue, push_indexed_map_lvalue.
669    * TODO: Rename this variable, or better: devise a nice solution.
670    * TODO:: Use the protected_lvalues instead?
671    * TODO:: To quote Marion:
672    * TODO::     marion says: but this is crude too
673    * TODO::     marion blushes.
674    * TODO: Is it made sure that this var will be vacated before the
675    * TODO:: next use? Otoh, if not it's no problem as the value is
676    * TODO:: by definition volatile.
677    */
678 
679 svalue_t last_indexing_protector = { T_NUMBER };
680   /* When indexing a protected non-string-lvalue, this variable receives
681    * the protecting svalue for the duration of the operation (actually
682    * until the next indexing operation (TODO: not nice)).
683    * This is necessary because the indexing operation necessarily destroys
684    * the protector structure, even though the protection is still needed.
685    * Used by: protected_index_lvalue().
686    */
687 
688 #ifdef OPCPROF
689 
690 #define MAXOPC (LAST_INSTRUCTION_CODE)
691   /* Number of different instructions to trace.
692    */
693 
694 static int opcount[MAXOPC];
695   /* Counter array for instruction profiling: each entry counts the
696    * usages of one instruction. The full instruction code (not the
697    * opcode) is used as index.
698    */
699 
700 #endif
701 
702 #ifdef DEBUG
703 
704 static program_t *check_a_lot_ref_counts_search_prog;
705   /* Program you developer are especially interested in.
706    */
707 
708 static struct pointer_table *ptable;
709   /* check_a_lot_of_ref_counts: the table of structures already
710    * visited.
711    */
712 
713 #endif
714 
715 p_uint eval_number;
716   /* evaluation number. (may overflow)
717    */
718 
719 unsigned long total_evalcost;
720 static struct timeval eval_begin;
721   /* Current total evalcost counter, and start of the evaluation.
722    */
723 
724 unsigned long last_total_evalcost = 0;
725 struct timeval last_eval_duration = { 0 };
726   /* Last total evaluation cost and duration.
727    */
728 
729 statistic_t stat_total_evalcost = { 0 };
730 statistic_t stat_eval_duration = { 0 };
731   /* Weighted statistics of evaluation cost and duration.
732    */
733 
734 /*-------------------------------------------------------------------------*/
735 /* Forward declarations */
736 
737 enum { APPLY_NOT_FOUND = 0, APPLY_FOUND, APPLY_DEFAULT_FOUND };
738 static int int_apply(string_t *, object_t *, int, Bool, Bool);
739 static void call_simul_efun(unsigned int code, object_t *ob, int num_arg);
740 #ifdef DEBUG
741 static void check_extra_ref_in_vector(svalue_t *svp, size_t num);
742 #endif
743 
744 /*-------------------------------------------------------------------------*/
745 
746 /* Assign the evaluation cost elapsed since the last call to the
747  * current_object and it's user's wizlist entry. Then set assigned_eval_cost
748  * to the current eval_cost so that later calls can do the same.
749  *
750  * This function must be called at least whenever the execution leaves
751  * one object for another one.
752  *
753  * assign_eval_cost_inl() is the inlinable version used here,
754  * assign_eval_cost() is used by other compilation units.
755  */
756 
757 static INLINE void
assign_eval_cost_inl(void)758 assign_eval_cost_inl(void)
759 {
760     unsigned long carry;
761     if (current_object->user)
762     {
763         current_object->user->cost += eval_cost - assigned_eval_cost;
764         carry = current_object->user->cost / 1000000000;
765         if (carry)
766         {
767             current_object->user->gigacost += carry;
768             current_object->user->cost %= 1000000000;
769         }
770         current_object->user->total_cost += eval_cost - assigned_eval_cost;
771         carry = current_object->user->total_cost / 1000000000;
772         if (carry)
773         {
774             current_object->user->total_gigacost += carry;
775             current_object->user->total_cost %= 1000000000;
776         }
777     }
778     current_object->ticks += eval_cost - assigned_eval_cost;
779     {
780         carry = current_object->ticks / 1000000000;
781         if (carry)
782         {
783             current_object->gigaticks += carry;
784             current_object->ticks %= 1000000000;
785         }
786     }
787     assigned_eval_cost = eval_cost;
788 }
789 
assign_eval_cost(void)790 void assign_eval_cost(void) { assign_eval_cost_inl(); }
791 
792 /*-------------------------------------------------------------------------*/
793 void
mark_start_evaluation(void)794 mark_start_evaluation (void)
795 
796 /* Called before a new evaluation; resets the current evaluation statistics.
797  */
798 
799 {
800     total_evalcost = 0;
801     eval_number++;
802     if (gettimeofday(&eval_begin, NULL))
803     {
804         eval_begin.tv_sec = eval_begin.tv_usec = 0;
805     }
806 } /* mark_start_evaluation() */
807 
808 /*-------------------------------------------------------------------------*/
809 void
mark_end_evaluation(void)810 mark_end_evaluation (void)
811 
812 /* Called after an evaluation; updates the evaluation statistics.
813  */
814 
815 {
816     if (total_evalcost == 0)
817         return;
818 
819     last_total_evalcost = total_evalcost;
820 
821     if (eval_begin.tv_sec == 0
822      || gettimeofday(&last_eval_duration, NULL))
823     {
824         last_eval_duration.tv_sec = last_eval_duration.tv_usec = 0;
825     }
826     else
827     {
828         last_eval_duration.tv_sec -= eval_begin.tv_sec;
829         last_eval_duration.tv_usec -= eval_begin.tv_usec;
830 
831         if (last_eval_duration.tv_usec < 0)
832         {
833             last_eval_duration.tv_sec--;
834             last_eval_duration.tv_usec += 1000000;
835         }
836 
837         update_statistic_avg( &stat_eval_duration
838                             , last_eval_duration.tv_sec * 1000000L
839                               + last_eval_duration.tv_usec
840                             );
841     }
842 
843     update_statistic_avg(&stat_total_evalcost, last_total_evalcost);
844 } /* mark_end_evaluation() */
845 
846 /*-------------------------------------------------------------------------*/
847 void
init_interpret(void)848 init_interpret (void)
849 
850 /* Initialize the interpreter data structures, especially the apply cache.
851  */
852 
853 {
854     struct cache invalid_entry;
855     int i;
856 
857     /* The cache is inited to hold entries for 'functions' in a non-existing
858      * program (id 0). The first real apply calls will thus see a (virtual)
859      * collision with 'older' cache entries.
860      */
861 
862     invalid_entry.id = 0;
863     invalid_entry.progp = (program_t *)1;
864     invalid_entry.name = NULL;
865 
866     /* To silence the compiler: */
867     invalid_entry.variable_index_offset = 0;
868     invalid_entry.function_index_offset = 0;
869     invalid_entry.funstart = 0;
870     invalid_entry.flags = 0;
871 
872     for (i = 0; i < CACHE_SIZE; i++)
873         cache[i] = invalid_entry;
874 } /* init_interpret()*/
875 
876 /*-------------------------------------------------------------------------*/
877 static INLINE Bool
is_sto_context(void)878 is_sto_context (void)
879 
880 /* Return TRUE if the current call context has a set_this_object()
881  * in effect.
882  */
883 
884 {
885     struct control_stack *p;
886 
887     for (p = csp; !p->extern_call; p--) NOOP;
888 
889     return (p->extern_call & CS_PRETEND) != 0;
890 } /* is_sto_context() */
891 
892 /*=========================================================================*/
893 
894 /*                         S V A L U E S                                   */
895 
896 /*-------------------------------------------------------------------------*/
897 /* The following functions handle svalues, ie. the data referenced
898  * by the svalue_ts. 'Freeing' in this context therefore never means
899  * a svalue_t, only the data referenced by it.
900  *
901  * destructed_object_ref(v): test if <v> references a destructed object.
902  * object_ref(v,o):          test if <v> references object <o>
903  * free_string_svalue(v): free string svalue <v>.
904  * free_object_svalue(v): free object svalue <v>.
905  * zero_object_svalue(v): replace the object in svalue <v> by number 0.
906  * free_svalue(v):        free the svalue <v>.
907  * assign_svalue_no_free(to,from): put a copy of <from> into <to>; <to>
908  *                        is considered empty.
909  * copy_svalue_no_free(to,from): put a shallow value copy of <from> into <to>;
910  *                        <to> is considered empty.
911  * assign_checked_svalue_no_free(to,from): put a copy of <from> into <to>;
912  *                        <to> is considered empty, <from> may be destructed
913  *                        object.
914  * assign_local_svalue_no_free(to,from): put a copy of local var <from>
915  *                        into <to>; <to> is considered empty, <from> may
916  *                        be destructed object.
917  * static assign_lrvalue_no_free(to,from): like assign_svalue_no_free(),
918  *                        but lvalues and strings are handled differently.
919  * assign_svalue(dest,v): assign <v> to <dest>, freeing <dest> first.
920  *                        Also handles assigns to lvalues.
921  * transfer_svalue_no_free(dest,v): move <v> into <dest>; <dest> is
922  *                        considered empty.
923  * transfer_svalue(dest,v): move <v> into <dest>; freeing <dest> first.
924  *                        Also handles transfers to lvalues.
925  * static add_number_to_lvalue(dest,i,pre,post): add <i> to lvalue <dest>.
926  *
927  * In addition there are some helper functions.
928  *
929  * TODO: All these functions and vars should go into a separate module.
930  */
931 
932 /*-------------------------------------------------------------------------*/
933 
934 /* --- Protector structures ---
935  *
936  * Whenever an assignment is made to a single value, or to a range in
937  * a string, vector or mapping, the interpreter generates protector
938  * structures in place of the usual LVALUE-svalues, which hold:
939  *  - a svalue structure referring to the svalue into which the assignment
940  *    is done (this structure is always first so that the protector
941  *    structures can be used instead of normal svalues),
942  *  - the necessary information to store the assigned svalue into its
943  *    place in the target holding the value,
944  *  - a protective reference to the holding value.
945  *
946  * All this just to keep LPC statements like 'a = ({ 1 }); a[0] = (a = 0);'
947  * from crashing.
948  *
949  * TODO: A simpler way would be to compute the lhs of an assignment
950  * TODO:: after evaluating the rhs - not vice versa as it is now.
951  * TODO:: However, passing lvalues and ranges as ref-parameters to functions
952  * TODO:: would still be a potential problem.
953  */
954 
955 /* --- struct protected_lvalue: protect a single value
956  */
957 struct protected_lvalue
958 {
959     svalue_t v;
960       /* .v.type: T_PROTECTED_LVALUE
961        * .v.u.lvalue: the protected value
962        */
963     svalue_t protector;
964       /* additional reference .v.u.lvalue (or its holder) as means of
965        * protection
966        */
967 };
968 
969 /* --- struct protected_char_lvalue: protect a char in a string
970  */
971 struct protected_char_lvalue
972 {
973     svalue_t v;
974       /* .v.type: T_PROTECTED_CHAR_LVALUE
975        * .v.u.charp: points to the char to access
976        */
977     svalue_t protector; /* protects .lvalue */
978     svalue_t *lvalue;   /* the string containing the char */
979     char *start;
980       /* must be == get_txt(lvalue->u.str), otherwise the string has been
981        * changed and this lvalue is invalid
982        */
983 };
984 
985 /* --- struct protected_range_lvalue: protect a range in a string or vector
986  */
987 struct protected_range_lvalue {
988     svalue_t v;
989       /* .v.type: T_PROTECTED_{POINTER,STRING}_RANGE_LVALUE
990        * .v.u.{str,vec}: the target value holding the range
991        */
992     svalue_t protector;  /* protects .lvalue */
993     svalue_t *lvalue;    /* the original svalue holding the range */
994     int index1, index2;  /* first and last index of the range in .lvalue */
995     int size;            /* original size of .lvalue */
996 
997     /* On creation, .v.u.{vec,str} == .lvalue->u.{vec,str}.
998      * If that condition no longer holds, the target in .v has been changed
999      * and the range information (index, size) is no longer valid.
1000      */
1001 };
1002 
1003 /*-------------------------------------------------------------------------*/
1004 /* Forward declarations */
1005 
1006 static void transfer_pointer_range(svalue_t *source);
1007 static void transfer_protected_pointer_range(
1008     struct protected_range_lvalue *dest, svalue_t *source);
1009 static void assign_string_range(svalue_t *source, Bool do_free);
1010 static void assign_protected_string_range(
1011     struct protected_range_lvalue *dest,svalue_t *source, Bool do_free);
1012 
1013 /*-------------------------------------------------------------------------*/
1014 void
free_string_svalue(svalue_t * v)1015 free_string_svalue (svalue_t *v)
1016 
1017 /* Free the string svalue <v>; <v> must be of type T_STRING.
1018  */
1019 
1020 {
1021 #ifdef DEBUG
1022     if (v->type != T_STRING)
1023     {
1024         fatal("free_string_svalue(): Expected string, "
1025               "received svalue type (%d:%hd)\n"
1026             , v->type, v->x.generic);
1027         /* NOTREACHED */
1028         return;
1029     }
1030 #endif
1031 
1032     free_mstring(v->u.str);
1033 }
1034 
1035 #define free_string_svalue(v) free_mstring((v)->u.str)
1036 
1037 /*-------------------------------------------------------------------------*/
1038 void
free_object_svalue(svalue_t * v)1039 free_object_svalue (svalue_t *v)
1040 
1041 /* Free the object svalue <v>; <v> must be of type T_OBJECT.
1042  */
1043 
1044 {
1045     object_t *ob = v->u.ob;
1046 
1047 #ifdef DEBUG
1048     if (v->type != T_OBJECT)
1049     {
1050         fatal("free_object_svalue(): Expected object, "
1051               "received svalue type (%d:%hd)\n"
1052             , v->type, v->x.generic);
1053         /* NOTREACHED */
1054         return;
1055     }
1056 #endif
1057 
1058     free_object(ob, "free_object_svalue");
1059 }
1060 
1061 /*-------------------------------------------------------------------------*/
1062 void
zero_object_svalue(svalue_t * v)1063 zero_object_svalue (svalue_t *v)
1064 
1065 /* Change <v> from an object svalue to the svalue-number 0.
1066  */
1067 
1068 {
1069     object_t *ob = v->u.ob;
1070 
1071     free_object(ob, "zero_object_svalue");
1072     put_number(v, 0);
1073 }
1074 
1075 /*-------------------------------------------------------------------------*/
1076 static void
free_protector_svalue(svalue_t * v)1077 free_protector_svalue (svalue_t *v)
1078 
1079 /* Free the svalue <v> which contains a protective reference to a vector
1080  * or to a mapping.
1081  */
1082 
1083 {
1084     switch (v->type)
1085     {
1086 #ifdef USE_STRUCTS
1087       case T_STRUCT:
1088         free_struct(v->u.strct);
1089         break;
1090 #endif /* USE_STRUCTS */
1091       case T_POINTER:
1092         free_array(v->u.vec);
1093         break;
1094       case T_MAPPING:
1095         free_mapping(v->u.map);
1096         break;
1097       case T_PROTECTOR_MAPPING:
1098         free_protector_mapping(v->u.map);
1099         break;
1100     }
1101 }
1102 
1103 /*-------------------------------------------------------------------------*/
1104 static void
int_free_svalue(svalue_t * v)1105 int_free_svalue (svalue_t *v)
1106 
1107 /* Free the svalue <v>, which may be of any type.
1108  * Afterwards, the content of <v> is undefined.
1109  */
1110 
1111 {
1112     ph_int type = v->type;
1113 
1114     v->type = T_INVALID;
1115       /* If freeing the value throws an error, it is most likely that
1116        * we ran out of stack. To avoid the error handling running
1117        * out of stack on the same value again, we mask it before we free
1118        * it - at the risk of leaking memory.
1119        */
1120 
1121     assert_stack_gap();
1122 
1123     switch (type)
1124     {
1125     default:
1126         fatal("(free_svalue) Illegal svalue %p type %d\n", v, type);
1127         /* NOTREACHED */
1128         break;
1129 
1130     case T_INVALID:
1131     case T_NUMBER:
1132     case T_FLOAT:
1133         NOOP;
1134         break;
1135 
1136     case T_STRING:
1137       {
1138         string_t *str = v->u.str;
1139         free_mstring(str);
1140         break;
1141       }
1142 
1143     case T_OBJECT:
1144       {
1145         object_t *ob = v->u.ob;
1146         free_object(ob, "free_svalue");
1147         break;
1148       }
1149 
1150     case T_QUOTED_ARRAY:
1151     case T_POINTER:
1152         free_array(v->u.vec);
1153         break;
1154 
1155 #ifdef USE_STRUCTS
1156     case T_STRUCT:
1157         free_struct(v->u.strct);
1158         break;
1159 #endif /* USE_STRUCTS */
1160 
1161     case T_MAPPING:
1162         free_mapping(v->u.map);
1163         break;
1164 
1165     case T_SYMBOL:
1166         free_mstring(v->u.str);
1167         break;
1168 
1169     case T_CLOSURE:
1170         free_closure(v);
1171         break;
1172 
1173     case T_CALLBACK:
1174         free_callback(v->u.cb);
1175         break;
1176 
1177     case T_LVALUE:
1178         switch (v->u.lvalue->type)
1179         {
1180         case T_PROTECTED_LVALUE:
1181           {
1182               struct protected_lvalue *p;
1183 
1184               p = v->u.protected_lvalue;
1185               free_protector_svalue(&p->protector);
1186               xfree(p);
1187               break;
1188           }
1189 
1190         case T_PROTECTED_CHAR_LVALUE:
1191           {
1192               struct protected_char_lvalue *p;
1193 
1194               p = v->u.protected_char_lvalue;
1195               if (p->v.type == T_STRING)
1196               {
1197                   free_mstring(p->v.u.str);
1198               }
1199               free_protector_svalue(&p->protector);
1200               xfree(p);
1201               break;
1202           }
1203 
1204         case T_PROTECTED_STRING_RANGE_LVALUE:
1205           {
1206               struct protected_range_lvalue *p;
1207 
1208               p = v->u.protected_range_lvalue;
1209               free_mstring(p->v.u.str);
1210               free_protector_svalue(&p->protector);
1211               xfree(p);
1212               break;
1213           }
1214 
1215         case T_PROTECTED_POINTER_RANGE_LVALUE:
1216           {
1217               struct protected_range_lvalue *p;
1218 
1219               p = v->u.protected_range_lvalue;
1220               free_array(p->v.u.vec);
1221               free_protector_svalue(&p->protector);
1222               xfree(p);
1223               break;
1224           }
1225 
1226         case T_ERROR_HANDLER:
1227           {
1228               svalue_t *p;
1229 
1230               p = v->u.lvalue;
1231               (*p->u.error_handler)(p);
1232               break;
1233           }
1234         } /* switch (v->u.lvalue->type) */
1235         break; /* case T_LVALUE */
1236 
1237     }
1238 } /* int_free_svalue() */
1239 
1240 /*-------------------------------------------------------------------------*/
1241 
1242 /* Queue element to deserialize the freeing of complex svalues. */
1243 struct fs_queue_s {
1244     struct fs_queue_s * next;
1245     svalue_t                   value;
1246 };
1247 
1248 typedef struct fs_queue_s fs_queue_t;
1249 
1250 static fs_queue_t fs_queue_base;
1251   /* Static fs_queue_t variable to avoid xallocs for the simple cases.
1252    */
1253 
1254 static fs_queue_t * fs_queue_head = NULL;
1255 static fs_queue_t * fs_queue_tail = NULL;
1256   /* Double-ended list of deserialized svalues to free.
1257    */
1258 
1259 void
free_svalue(svalue_t * v)1260 free_svalue (svalue_t *v)
1261 
1262 /* Free the svalue <v>, which may be of any type, while making sure that
1263  * complex nested structures are deserialized (to avoid stack overflows).
1264  * Afterwards, the content of <v> is undefined.
1265  */
1266 
1267 {
1268     Bool needs_deserializing = MY_FALSE;
1269 
1270     switch (v->type)
1271     {
1272     case T_QUOTED_ARRAY:
1273     case T_POINTER:
1274         needs_deserializing = (v->u.vec->ref == 1);
1275         break;
1276 
1277 #ifdef USE_STRUCTS
1278     case T_STRUCT:
1279         needs_deserializing = (struct_ref(v->u.strct) == 1);
1280         break;
1281 #endif /* USE_STRUCTS */
1282 
1283     case T_MAPPING:
1284         needs_deserializing = (v->u.map->ref == 1);
1285         break;
1286     }
1287 
1288     /* If the value doesn't need de-serializing, it can be
1289      * be freed immediately.
1290      */
1291     if (!needs_deserializing)
1292     {
1293         int_free_svalue(v);
1294         return;
1295     }
1296 
1297     /* If there are elements in the queue, we are inside the freeing of a
1298      * complex structure, and this element just needs to be queued up.
1299      * When out of memory, however, just free it.
1300      */
1301     if (fs_queue_head != NULL)
1302     {
1303         fs_queue_t * tmp = xalloc(sizeof(*tmp));
1304 
1305         if (NULL == tmp)
1306         {
1307             int_free_svalue(v);
1308             return;
1309         }
1310 
1311         /* Copy the value over, invalidating this one. */
1312         tmp->next = NULL;
1313         tmp->value = *v;
1314         v->type = T_INVALID;
1315 
1316         /* Insert the element into the queue. */
1317         fs_queue_tail->next = tmp;
1318         fs_queue_tail = tmp;
1319 
1320         return;
1321     }
1322 
1323     /* This is the first complex value to be freed - start the queue.
1324      */
1325     fs_queue_base.next = NULL;
1326     fs_queue_base.value = *v;
1327     v->type = T_INVALID;
1328 
1329     fs_queue_head = fs_queue_tail = &fs_queue_base;
1330 
1331     /* Now loop over the queue, successively freeing the values.
1332      * If one of the values freed contains complex freeable structures
1333      * itself, they will be added to the end of the queue and eventually
1334      * picked up by this loop.
1335      */
1336     while (fs_queue_head != NULL)
1337     {
1338         fs_queue_t * current = fs_queue_head;
1339 
1340         int_free_svalue(&(fs_queue_head->value));
1341 
1342         fs_queue_head = fs_queue_head->next;
1343         if (fs_queue_head == NULL)
1344             fs_queue_tail = NULL;
1345 
1346         if (current != &fs_queue_base)
1347             xfree(current);
1348     }
1349 } /* free_svalue() */
1350 
1351 /*-------------------------------------------------------------------------*/
1352 static INLINE Bool
_destructed_object_ref(svalue_t * svp)1353 _destructed_object_ref (svalue_t *svp)
1354 
1355 /* Return TRUE if the svalue in <svp> references a destructed object.
1356  */
1357 
1358 {
1359     lambda_t *l;
1360     int type;
1361 
1362     if (svp->type != T_OBJECT && svp->type != T_CLOSURE)
1363         return MY_FALSE;
1364 
1365     if (svp->type == T_OBJECT || !CLOSURE_MALLOCED(type = svp->x.closure_type))
1366         return (svp->u.ob->flags & O_DESTRUCTED) ? MY_TRUE : MY_FALSE;
1367 
1368     /* Lambda closure */
1369 
1370     l = svp->u.lambda;
1371 
1372     if (CLOSURE_HAS_CODE(type) && type == CLOSURE_UNBOUND_LAMBDA)
1373         return MY_FALSE;
1374 
1375     if (type == CLOSURE_LFUN
1376      && (l->function.lfun.ob->flags & O_DESTRUCTED))
1377         return MY_TRUE;
1378 
1379     return (l->ob->flags & O_DESTRUCTED) ? MY_TRUE : MY_FALSE;
1380 
1381 } /* _destructed_object_ref() */
1382 
destructed_object_ref(svalue_t * v)1383 Bool destructed_object_ref (svalue_t *v) { return _destructed_object_ref(v); }
1384 
1385 #define destructed_object_ref(v) _destructed_object_ref(v)
1386 
1387 /*-------------------------------------------------------------------------*/
1388 static INLINE Bool
int_object_ref(svalue_t * svp,object_t * obj)1389 int_object_ref (svalue_t *svp, object_t *obj)
1390 
1391 /* Return TRUE if <svp> references object <obj> (destructed or alive),
1392  * return FALSE if it doesn't.
1393  */
1394 
1395 {
1396     lambda_t *l;
1397     int type;
1398 
1399     if (svp->type != T_OBJECT && svp->type != T_CLOSURE)
1400         return MY_FALSE;
1401 
1402     if (svp->type == T_OBJECT || !CLOSURE_MALLOCED(type = svp->x.closure_type))
1403         return svp->u.ob == obj;
1404 
1405     /* Lambda closure */
1406 
1407     l = svp->u.lambda;
1408 
1409     if (CLOSURE_HAS_CODE(type) && type == CLOSURE_UNBOUND_LAMBDA)
1410         return MY_FALSE;
1411 
1412     if (type == CLOSURE_LFUN && l->function.lfun.ob == obj)
1413         return MY_TRUE;
1414 
1415     return l->ob == obj;
1416 
1417 } /* int_object_ref() */
1418 
1419 #define object_ref(v,o) int_object_ref(v,o)
1420 
1421 /*-------------------------------------------------------------------------*/
1422 static INLINE void
check_for_ref_loop(svalue_t * dest)1423 check_for_ref_loop (svalue_t * dest)
1424 
1425 /* <dest> has just been assigned to - check if this created a reference loop.
1426  * If yes, free <dest> and throw an error.
1427  */
1428 
1429 {
1430     if (dest->type == T_LVALUE || dest->type == T_PROTECTED_LVALUE)
1431     {
1432         /* rover1 will scan the lvalue chain in two-steps, rover2 will
1433          * scan it step by step. If there is a loop, the two will eventually
1434          * meet again.
1435          */
1436         svalue_t * rover1, * rover2;
1437 
1438         rover1 = rover2 = dest;
1439         do {
1440             if (rover1->type == T_LVALUE || rover1->type == T_PROTECTED_LVALUE)
1441                 rover1 = rover1->u.lvalue;
1442             else
1443                 break;
1444             if (rover1->type == T_LVALUE || rover1->type == T_PROTECTED_LVALUE)
1445                 rover1 = rover1->u.lvalue;
1446             else
1447                 break;
1448             if (rover2->type == T_LVALUE || rover2->type == T_PROTECTED_LVALUE)
1449                 rover2 = rover2->u.lvalue;
1450             else
1451                 break;
1452             if (rover1 == rover2)
1453             {
1454                 free_svalue(dest);
1455                 errorf("Assignment would create reference loop.\n");
1456             }
1457         } while (rover1
1458              && (rover1->type == T_LVALUE || rover1->type == T_PROTECTED_LVALUE)
1459              && rover2
1460              && (rover2->type == T_LVALUE || rover2->type == T_PROTECTED_LVALUE)
1461                 );
1462     }
1463 
1464 } /* check_for_ref_loop() */
1465 
1466 /*-------------------------------------------------------------------------*/
1467 static INLINE void
inl_assign_svalue_no_free(svalue_t * to,svalue_t * from)1468 inl_assign_svalue_no_free (svalue_t *to, svalue_t *from)
1469 
1470 /* Put a duplicate of svalue <from> into svalue <to>, meaning that the original
1471  * value is either copied when appropriate, or its refcount is increased.
1472  * <to> is considered empty at the time of call.
1473  *
1474  * If <from> is a destructed object, <to> is set to the number 0 but
1475  * <from> is left unchanged.
1476  */
1477 
1478 {
1479 #ifdef DEBUG
1480     if (from == 0)
1481         fatal("Null pointer to assign_svalue().\n");
1482 #endif
1483 
1484     /* Copy all the data */
1485     *to = *from;
1486 
1487     /* Now create duplicates resp. increment refcounts where necessary */
1488 
1489     switch(from->type)
1490     {
1491     case T_STRING:
1492         (void)ref_mstring(from->u.str);
1493         break;
1494 
1495     case T_OBJECT:
1496         {
1497           object_t *ob = to->u.ob;
1498           if ( !(ob->flags & O_DESTRUCTED) )
1499               (void)ref_object(ob, "ass to var");
1500           else
1501               put_number(to, 0);
1502 
1503           break;
1504         }
1505         break;
1506 
1507     case T_QUOTED_ARRAY:
1508     case T_POINTER:
1509         (void)ref_array(to->u.vec);
1510         break;
1511 
1512 #ifdef USE_STRUCTS
1513     case T_STRUCT:
1514         (void)ref_struct(to->u.strct);
1515         break;
1516 #endif /* USE_STRUCTS */
1517 
1518     case T_SYMBOL:
1519         (void)ref_mstring(to->u.str);
1520         break;
1521 
1522     case T_CLOSURE:
1523         addref_closure(to, "ass to var");
1524         break;
1525 
1526     case T_MAPPING:
1527         (void)ref_mapping(to->u.map);
1528         break;
1529     }
1530 
1531     /* Protection against endless reference loops */
1532     if (to->type == T_LVALUE || to->type == T_PROTECTED_LVALUE)
1533     {
1534         check_for_ref_loop(to);
1535     }
1536 } /* inl_assign_svalue_no_free() */
1537 
assign_svalue_no_free(svalue_t * to,svalue_t * from)1538 void assign_svalue_no_free (svalue_t *to, svalue_t *from)
1539 { inl_assign_svalue_no_free(to,from); }
1540 
1541 #define assign_svalue_no_free(to,from) inl_assign_svalue_no_free(to,from)
1542 
1543 /*-------------------------------------------------------------------------*/
1544 static INLINE void
inl_copy_svalue_no_free(svalue_t * to,svalue_t * from)1545 inl_copy_svalue_no_free (svalue_t *to, svalue_t *from)
1546 
1547 /* Put a duplicate of svalue <from> into svalue <to>, meaning that the original
1548  * value is either copied when appropriate, or its refcount is increased.
1549  * In particular, if <from> is a mapping (which must not contain destructed
1550  * objects!) or array, a shallow copy is created.
1551  * <to> is considered empty at the time of call.
1552  *
1553  * If <from> is a destructed object, <to> is set to the number 0 but
1554  * <from> is left unchanged.
1555  */
1556 
1557 {
1558     assign_svalue_no_free(to, from);
1559 
1560     /* For arrays and mappings, create a shallow copy */
1561     if (from->type == T_MAPPING)
1562     {
1563         mapping_t *old, *new;
1564 
1565         old = to->u.map;
1566         if (old->ref != 1)
1567         {
1568             DYN_MAPPING_COST(MAP_SIZE(old));
1569             new = copy_mapping(old);
1570             if (!new)
1571                 errorf("Out of memory: mapping[%"PRIdPINT"] for copy.\n"
1572                      , MAP_SIZE(old));
1573             free_mapping(old);
1574             to->u.map = new;
1575         }
1576     }
1577     else if (from->type == T_POINTER
1578           || from->type == T_QUOTED_ARRAY)
1579     {
1580         vector_t *old, *new;
1581         size_t size, i;
1582 
1583         old = to->u.vec;
1584         size = VEC_SIZE(old);
1585         if (old->ref != 1 && old != &null_vector)
1586         {
1587             DYN_ARRAY_COST(size);
1588             new = allocate_uninit_array((int)size);
1589             if (!new)
1590                 errorf("Out of memory: array[%zu] for copy.\n"
1591                      , size);
1592             for (i = 0; i < size; i++)
1593                 assign_svalue_no_free( &new->item[i]
1594                                      , &old->item[i]);
1595             free_array(old);
1596             to->u.vec = new;
1597         }
1598     }
1599 } /* inl_copy_svalue_no_free() */
1600 
copy_svalue_no_free(svalue_t * to,svalue_t * from)1601 void copy_svalue_no_free (svalue_t *to, svalue_t *from)
1602 { inl_copy_svalue_no_free(to,from); }
1603 
1604 #define copy_svalue_no_free(to,from) inl_copy_svalue_no_free(to,from)
1605 
1606 /*-------------------------------------------------------------------------*/
1607 static INLINE void
assign_checked_svalue_no_free(svalue_t * to,svalue_t * from)1608 assign_checked_svalue_no_free (svalue_t *to, svalue_t *from)
1609 
1610 /* Put a duplicate of svalue <from> into svalue <to>, meaning that the original
1611  * value is either copied when appropriate, or its refcount is increased.
1612  * <to> is considered empty at the time of call.
1613  * <from> may point to a variable or vector element, so it might contain
1614  * a destructed object. In that case, <from> and <to> are set to
1615  * svalue-number 0.
1616  */
1617 
1618 {
1619     switch (from->type)
1620     {
1621     case T_STRING:
1622         (void)ref_mstring(from->u.str);
1623         break;
1624 
1625     case T_OBJECT:
1626       {
1627         object_t *ob = from->u.ob;
1628         if ( !(ob->flags & O_DESTRUCTED) ) {
1629             ref_object(ob, "ass to var");
1630             break;
1631         }
1632         zero_object_svalue(from);
1633         break;
1634       }
1635 
1636     case T_QUOTED_ARRAY:
1637     case T_POINTER:
1638         (void)ref_array(from->u.vec);
1639         break;
1640 
1641 #ifdef USE_STRUCTS
1642     case T_STRUCT:
1643         (void)ref_struct(from->u.strct);
1644         break;
1645 #endif /* USE_STRUCTS */
1646 
1647     case T_SYMBOL:
1648         (void)ref_mstring(from->u.str);
1649         break;
1650 
1651     case T_CLOSURE:
1652         if (!destructed_object_ref(from))
1653             addref_closure(from, "ass to var");
1654         else
1655             assign_svalue(from, &const0);
1656         break;
1657 
1658     case T_MAPPING:
1659         (void)ref_mapping(from->u.map);
1660         break;
1661     }
1662     *to = *from;
1663 
1664     /* Protection against endless reference loops */
1665     if (to->type == T_LVALUE || to->type == T_PROTECTED_LVALUE)
1666     {
1667         check_for_ref_loop(to);
1668     }
1669 } /* assign_checked_svalue_no_free() */
1670 
1671 /*-------------------------------------------------------------------------*/
1672 static INLINE void
assign_local_svalue_no_free(svalue_t * to,svalue_t * from)1673 assign_local_svalue_no_free ( svalue_t *to, svalue_t *from )
1674 
1675 /* Put a duplicate of svalue <from> into svalue <to>, meaning that the original
1676  * value is either copied when appropriate, or its refcount is increased.
1677  * <to> is considered empty at the time of call.
1678  *
1679  * <from> is meant to point to a local variable, which might be an arg
1680  * to the current lfun.
1681  * If <from> is a lvalue, the chain is unraveled and the final non-lvalue
1682  * is assigned. If that value is a destructed object, 0 is assigned.
1683  */
1684 
1685 {
1686 assign_from_lvalue:
1687     switch (from->type)
1688     {
1689       case T_STRING:
1690         (void)ref_mstring(from->u.str);
1691         break;
1692       case T_OBJECT:
1693         (void)ref_object(from->u.ob, "assign_local_lvalue_no_free");
1694         break;
1695       case T_QUOTED_ARRAY:
1696       case T_POINTER:
1697         (void)ref_array(from->u.vec);
1698         break;
1699 #ifdef USE_STRUCTS
1700       case T_STRUCT:
1701         (void)ref_struct(from->u.strct);
1702         break;
1703 #endif /* USE_STRUCTS */
1704       case T_SYMBOL:
1705         (void)ref_mstring(from->u.str);
1706         break;
1707       case T_CLOSURE:
1708         addref_closure(from, "ass to var");
1709         break;
1710       case T_MAPPING:
1711         (void)ref_mapping(from->u.map);
1712         break;
1713       case T_LVALUE:
1714       case T_PROTECTED_LVALUE:
1715         from = from->u.lvalue;
1716         if (destructed_object_ref(from)) {
1717             assign_svalue(from, &const0);
1718             break;
1719         }
1720         goto assign_from_lvalue;
1721       case T_PROTECTED_CHAR_LVALUE:
1722         put_number(to, *from->u.charp);
1723         return;
1724     }
1725     *to = *from;
1726 
1727     /* Protection against endless reference loops */
1728     if (to->type == T_LVALUE || to->type == T_PROTECTED_LVALUE)
1729     {
1730         check_for_ref_loop(to);
1731     }
1732 } /* assign_local_svalue_no_free() */
1733 
1734 /*-------------------------------------------------------------------------*/
1735 static INLINE
assign_lrvalue_no_free(svalue_t * to,svalue_t * from)1736 void assign_lrvalue_no_free (svalue_t *to, svalue_t *from)
1737 
1738 /* Put a duplicate of svalue <from> into svalue <to>, meaning that the original
1739  * value is either copied when appropriate, or its refcount is increased.
1740  * <to> is considered empty at the time of call.
1741  *
1742  * This function differs from assign_svalue_no_free() in the handling of
1743  * two types:
1744  *  - if <from> is an unshared string, the string is made shared and
1745  *    both <to> and <from> are changed to use the shared string.
1746  *  - if <from> is a lvalue, <to>.u.lvalue is set to point to <from>.
1747  *    This is necessary when pushing references onto the stack - if
1748  *    assign_svalue_no_free() were used, the first free_svalue() would undo
1749  *    the whole lvalue indirection, even though there were still other lvalue
1750  *    entries in the stack for the same svalue.
1751  *    TODO: An alternative would be use a special struct lvalue {} with a
1752  *    refcount.
1753  */
1754 
1755 {
1756 #ifdef DEBUG
1757     if (from == 0)
1758         fatal("Null pointer to assign_lrvalue_no_free().\n");
1759 #endif
1760 
1761     /* Copy the data */
1762     *to = *from;
1763 
1764     /* Now adapt the refcounts or similar */
1765 
1766     switch(from->type)
1767     {
1768     case T_STRING:
1769         (void)ref_mstring(to->u.str);
1770         break;
1771 
1772     case T_OBJECT:
1773         (void)ref_object(to->u.ob, "ass to var");
1774         break;
1775 
1776     case T_QUOTED_ARRAY:
1777     case T_POINTER:
1778         (void)ref_array(to->u.vec);
1779         break;
1780 
1781 #ifdef USE_STRUCTS
1782     case T_STRUCT:
1783         (void)ref_struct(to->u.strct);
1784         break;
1785 #endif /* USE_STRUCTS */
1786 
1787     case T_SYMBOL:
1788         (void)ref_mstring(to->u.str);
1789         break;
1790 
1791     case T_CLOSURE:
1792         if (!destructed_object_ref(to))
1793             addref_closure(to, "ass to var");
1794         else
1795             put_number(to, 0);
1796         break;
1797 
1798     case T_MAPPING:
1799         (void)ref_mapping(to->u.map);
1800         break;
1801 
1802     case T_LVALUE:
1803         to->u.lvalue = from;
1804         break;
1805     }
1806 
1807     /* Protection against endless reference loops */
1808     if (to->type == T_LVALUE || to->type == T_PROTECTED_LVALUE)
1809     {
1810         check_for_ref_loop(to);
1811     }
1812 } /* assign_lrvalue_no_free() */
1813 
1814 /*-------------------------------------------------------------------------*/
1815 void
assign_svalue(svalue_t * dest,svalue_t * v)1816 assign_svalue (svalue_t *dest, svalue_t *v)
1817 
1818 /* Put a duplicate of svalue <v> into svalue <dest>, meaning that the
1819  * original value is either copied when appropriate, or its refcount is
1820  * increased.
1821  *
1822  * <dest> is considered a valid svalue and therefore freed before the
1823  * assignment. Structured values will necessiate doing the assignment before
1824  * the actual deallocation, otherwise recursive structures could cause crashs.
1825  * One nasty example is
1826  *    a = ( ({((a=({0})),(a[0]=a)),(a=0)})[0] = query_verb() );
1827  * which used to corrupt the shared string table, namely the entry for
1828  * the verb in variable a if its length uses a memory block of
1829  * the same length as an array of size 2.
1830  *
1831  * If <dest> is a lvalue, <v> will be assigned to the svalue referenced
1832  * to by <dest>.
1833  */
1834 
1835 {
1836     /* Free the <dest> svalue.
1837      * If <dest> is a (protected) lvalue, the loop will traverse the lvalue
1838      * chain until the actual svalue is found.
1839      * If a T_xxx_LVALUE is found, the assignment will be done here
1840      * immediately.
1841      */
1842 
1843     for (;;) {
1844         switch(dest->type)
1845         {
1846         case T_LVALUE:
1847         case T_PROTECTED_LVALUE:
1848             dest = dest->u.lvalue;
1849             continue;
1850 
1851         case T_STRING:
1852             free_mstring(dest->u.str);
1853             break;
1854 
1855         case T_OBJECT:
1856           {
1857             object_t *ob = dest->u.ob;
1858             free_object(ob, "assign_svalue");
1859             break;
1860           }
1861 
1862         case T_QUOTED_ARRAY:
1863         case T_POINTER:
1864           {
1865             vector_t *vec = dest->u.vec;
1866             assign_svalue_no_free(dest, v);
1867               /* TODO: leaks vec if out of memory */
1868             free_array(vec);
1869             return;
1870           }
1871 
1872 #ifdef USE_STRUCTS
1873         case T_STRUCT:
1874           {
1875             struct_t *strct = dest->u.strct;
1876             assign_svalue_no_free(dest, v);
1877               /* TODO: leaks strct if out of memory */
1878             free_struct(strct);
1879             return;
1880           }
1881 #endif /* USE_STRUCTS */
1882 
1883         case T_MAPPING:
1884           {
1885             mapping_t *map = dest->u.map;
1886             assign_svalue_no_free(dest, v); /* leaks map if out of memory */
1887             free_mapping(map);
1888             return;
1889           }
1890 
1891         case T_SYMBOL:
1892             free_mstring(dest->u.str);
1893             break;
1894 
1895         case T_CLOSURE:
1896             free_closure(dest);
1897             break;
1898 
1899         /* If the final svalue in dest is one of these lvalues,
1900          * the assignment is done right here and now.
1901          * Note that 'dest' in some cases points to a protector structure.
1902          */
1903 
1904         case T_CHAR_LVALUE:
1905             if (v->type == T_NUMBER)
1906                 *dest->u.charp = (char)v->u.number;
1907             return;
1908 
1909         case T_PROTECTED_CHAR_LVALUE:
1910           {
1911             struct protected_char_lvalue *p;
1912 
1913             p = (struct protected_char_lvalue *)dest;
1914             if (p->lvalue->type == T_STRING
1915              && get_txt(p->lvalue->u.str) == p->start)
1916             {
1917                 if (v->type == T_NUMBER)
1918                     *p->v.u.charp = (char)v->u.number;
1919             }
1920             return;
1921           }
1922 
1923         case T_POINTER_RANGE_LVALUE:
1924             if (v->type == T_POINTER)
1925             {
1926                 (void)ref_array(v->u.vec); /* transfer_...() will free it once */
1927                 transfer_pointer_range(v);
1928             }
1929             return;
1930 
1931         case T_PROTECTED_POINTER_RANGE_LVALUE:
1932             if (v->type == T_POINTER)
1933             {
1934                 (void)ref_array(v->u.vec); /* transfer_...() will free it once */
1935                 transfer_protected_pointer_range(
1936                   (struct protected_range_lvalue *)dest, v
1937                 );
1938             }
1939             return;
1940 
1941         case T_STRING_RANGE_LVALUE:
1942             assign_string_range(v, MY_FALSE);
1943             return;
1944 
1945         case T_PROTECTED_STRING_RANGE_LVALUE:
1946             assign_protected_string_range(
1947                   (struct protected_range_lvalue *)dest, v, MY_FALSE
1948             );
1949             return;
1950 
1951         } /* switch() */
1952 
1953         /* No more lvalues to follow, old value freed: do the assign next */
1954         break;
1955     } /* end for */
1956 
1957     /* Now assign the value to the now-invalid <dest> */
1958     assign_svalue_no_free(dest, v);
1959 } /* assign_svalue() */
1960 
1961 /*-------------------------------------------------------------------------*/
1962 static INLINE void
inl_transfer_svalue_no_free(svalue_t * dest,svalue_t * v)1963 inl_transfer_svalue_no_free (svalue_t *dest, svalue_t *v)
1964 
1965 /* Move the value <v> into <dest>.
1966  *
1967  * <dest> is assumed to be invalid before the call, <v> is invalid after.
1968  */
1969 
1970 {
1971     /* Copy the data */
1972     *dest = *v;
1973 
1974     /* Protection against endless reference loops */
1975     if (dest->type == T_LVALUE || dest->type == T_PROTECTED_LVALUE)
1976     {
1977         v->type = T_INVALID;
1978         check_for_ref_loop(dest);
1979     }
1980 } /* inl_transfer_svalue_no_free() */
1981 
transfer_svalue_no_free(svalue_t * dest,svalue_t * v)1982 void transfer_svalue_no_free (svalue_t *dest, svalue_t *v)
1983 {  inl_transfer_svalue_no_free(dest,v); }
1984 
1985 #define transfer_svalue_no_free(dest,v) inl_transfer_svalue_no_free(dest,v)
1986 
1987 /*-------------------------------------------------------------------------*/
1988 static INLINE void
inl_transfer_svalue(svalue_t * dest,svalue_t * v)1989 inl_transfer_svalue (svalue_t *dest, svalue_t *v)
1990 
1991 /* Move svalue <v> into svalue <dest>.
1992  *
1993  * <dest> is considered a valid svalue and therefore freed before the
1994  * assignment. <v> will be invalid after the call.
1995  *
1996  * If <dest> is a lvalue, <v> will be moved into the svalue referenced
1997  * to by <dest>.
1998  *
1999  * TODO: Test if copying this function into F_VOID_ASSIGN case speeds up
2000  * TODO:: the interpreter.
2001  */
2002 
2003 {
2004     /* Unravel the T_LVALUE chain, if any. */
2005     while (dest->type == T_LVALUE || dest->type == T_PROTECTED_LVALUE)
2006         dest = dest->u.lvalue;
2007 
2008     /* Free the <dest> svalue.
2009      * If a T_xxx_LVALUE is found, the transfer will be done here
2010      * immediately.
2011      */
2012 
2013     for(;;)
2014     {
2015         switch (dest->type)
2016         {
2017         case T_STRING:
2018             free_mstring(dest->u.str);
2019             break;
2020 
2021         case T_OBJECT:
2022           {
2023             object_t *ob = dest->u.ob;
2024             free_object(ob, "transfer_svalue");
2025             break;
2026           }
2027 
2028         case T_QUOTED_ARRAY:
2029         case T_POINTER:
2030             free_array(dest->u.vec);
2031             break;
2032 
2033 #ifdef USE_STRUCTS
2034         case T_STRUCT:
2035             free_struct(dest->u.strct);
2036             break;
2037 #endif /* USE_STRUCTS */
2038 
2039         case T_SYMBOL:
2040             free_mstring(dest->u.str);
2041             break;
2042 
2043         case T_CLOSURE:
2044             free_closure(dest);
2045             break;
2046 
2047         case T_MAPPING:
2048             free_mapping(dest->u.map);
2049             break;
2050 
2051         /* If the final svalue in dest is one of these lvalues,
2052          * the assignment is done right here and now.
2053          * Note that 'dest' in some cases points to a protector structure.
2054          */
2055 
2056         case T_CHAR_LVALUE:
2057             if (v->type == T_NUMBER)
2058             {
2059                 *dest->u.charp = (char)v->u.number;
2060             }
2061             else
2062                 free_svalue(v);
2063             return;
2064 
2065         case T_PROTECTED_CHAR_LVALUE:
2066           {
2067             struct protected_char_lvalue *p;
2068 
2069             p = (struct protected_char_lvalue *)dest;
2070             if (p->lvalue->type == T_STRING
2071              && get_txt(p->lvalue->u.str) == p->start)
2072             {
2073                 if (v->type == T_NUMBER)
2074                 {
2075                     *p->v.u.charp = (char)v->u.number;
2076                     return;
2077                 }
2078             }
2079             free_svalue(v);
2080             return;
2081           }
2082 
2083         case T_POINTER_RANGE_LVALUE:
2084             transfer_pointer_range(v);
2085             return;
2086 
2087         case T_PROTECTED_POINTER_RANGE_LVALUE:
2088             transfer_protected_pointer_range(
2089               (struct protected_range_lvalue *)dest, v
2090             );
2091             return;
2092 
2093         case T_STRING_RANGE_LVALUE:
2094             assign_string_range(v, MY_TRUE);
2095             return;
2096 
2097         case T_PROTECTED_STRING_RANGE_LVALUE:
2098             assign_protected_string_range(
2099               (struct protected_range_lvalue *)dest, v, MY_TRUE
2100             );
2101             return;
2102         } /* end switch */
2103 
2104         /* No more lvalues to follow, old value freed: do the assign next */
2105         break;
2106     } /* end for */
2107 
2108     /* Transfer the value */
2109     *dest = *v;
2110 
2111     /* Protection against endless reference loops */
2112     if (dest->type == T_LVALUE || dest->type == T_PROTECTED_LVALUE)
2113     {
2114         v->type = T_INVALID;
2115         check_for_ref_loop(dest);
2116     }
2117 
2118 } /* inl_transfer_svalue() */
2119 
transfer_svalue(svalue_t * dest,svalue_t * v)2120 void transfer_svalue (svalue_t *dest, svalue_t *v)
2121 {  inl_transfer_svalue(dest,v); }
2122 
2123 #define transfer_svalue(dest,v) inl_transfer_svalue(dest,v)
2124 
2125 /*-------------------------------------------------------------------------*/
2126 static void
transfer_pointer_range(svalue_t * source)2127 transfer_pointer_range (svalue_t *source)
2128 
2129 /* Transfer the vector <source> to the vector range defined by
2130  * <special_lvalue>, modifying the target vector in special_lvalue
2131  * accordingly. <source> is freed once in the call.
2132  *
2133  * If <source> is not a vector, it is just freed.
2134  */
2135 
2136 {
2137     if (source->type == T_POINTER)
2138     {
2139         vector_t *sv;      /* Source vector (from source) */
2140         vector_t *dv;      /* Destination vector (from special_lvalue) */
2141         vector_t *rv;      /* Result vector */
2142         mp_int dsize;           /* Size of destination vector */
2143         mp_int ssize;           /* Size of source vector */
2144         mp_int index1, index2;  /* First and last index of destination range */
2145         mp_int i;
2146 
2147         /* Setup the variables */
2148         dsize = special_lvalue.size;
2149         index1 = special_lvalue.index1;
2150         index2 = special_lvalue.index2;
2151         dv = special_lvalue.v.u.lvalue->u.vec;
2152         sv = source->u.vec;
2153         ssize = (mp_int)VEC_SIZE(sv);
2154 
2155 #ifdef NO_NEGATIVE_RANGES
2156         if (index1 > index2)
2157             errorf("Illegal range [%"PRIdMPINT"..%"PRIdMPINT
2158                    "] for assignment.\n", index1, index2-1
2159                  );
2160 #endif /* NO_NEGATIVE_RANGES */
2161 
2162         if (ssize + index1 - index2 == 0)
2163         {
2164             /* <source> fits exactly into the target range */
2165 
2166             svalue_t *s, *d;  /* Copy source and destination */
2167 
2168             s = sv->item;
2169             d = dv->item + index1;
2170 
2171             ref_array(dv); /* protect against recursive refs during the copy */
2172 
2173             /* If there is just one ref to the source, use the faster
2174              * transfer instead of the slow assign for the copy.
2175              */
2176             if (sv->ref == 1)
2177             {
2178                 for (i = ssize; --i >= 0; )
2179                 {
2180                     transfer_svalue(d++, s++);
2181                 }
2182                 free_empty_vector(sv);
2183             }
2184             else /* sv->ref > 1 */
2185             {
2186                 for (i = ssize; --i >= 0; )
2187                 {
2188                     assign_svalue(d++, s++);
2189                 }
2190 
2191                 free_array(sv);
2192                   /* deref_array() is not enough, because in situations
2193                    * where one d == sv, eg
2194                    *    arr = ({ ({ 1 }) });
2195                    *    arr[0..0] = arr[0];
2196                    * sv would be left behind with 0 refs but unfreed.
2197                    */
2198             }
2199 
2200             free_array(dv); /* Undo the ref_array() above */
2201         }
2202         else
2203         {
2204             /* Create a new vector */
2205 
2206             svalue_t *s, *d; /* Copy source and destination */
2207 
2208             rv = allocate_array(dsize + ssize + index1 - index2);
2209             special_lvalue.v.u.lvalue->u.vec = rv;
2210             s = dv->item;
2211             d = rv->item;
2212 
2213             for (i = index1; --i >= 0; )
2214             {
2215                 assign_svalue_no_free(d++, s++);
2216             }
2217 
2218             s = sv->item;
2219             for (i = ssize; --i >= 0; )
2220             {
2221                 assign_svalue_no_free(d++, s++);
2222             }
2223             free_array(sv);
2224 
2225             s = dv->item + index2;
2226             for (i = dsize - index2; --i >= 0; )
2227             {
2228                 assign_svalue_no_free(d++, s++);
2229             }
2230 
2231             free_array(dv); /* this can make the lvalue invalid to use */
2232         }
2233     }
2234     else
2235         /* Not a pointer: just free it */
2236         free_svalue(source);
2237 
2238 } /* transfer_pointer_range() */
2239 
2240 /*-------------------------------------------------------------------------*/
2241 static void
transfer_protected_pointer_range(struct protected_range_lvalue * dest,svalue_t * source)2242 transfer_protected_pointer_range ( struct protected_range_lvalue *dest
2243                                  , svalue_t *source)
2244 
2245 /* Transfer the vector <source> to the vector range defined by
2246  * <dest>, modifying the target vector in <dest>
2247  * accordingly. <source> is freed once in the call.
2248  *
2249  * If <source> is not a vector, it is just freed.
2250  */
2251 
2252 {
2253     if (source->type == T_POINTER && dest->v.u.vec == dest->lvalue->u.vec)
2254     {
2255         vector_t *sv;      /* Source vector (from source) */
2256         vector_t *dv;      /* Dest vector (from dest) */
2257         vector_t *rv;      /* Result vector */
2258         mp_int dsize;           /* Size of the dest vector */
2259         mp_int ssize;           /* Size of the source vector */
2260         mp_int index1, index2;  /* Target range indices */
2261         mp_int i;
2262 
2263         /* Setup the variables */
2264         dsize = dest->size;
2265         index1 = dest->index1;
2266         index2 = dest->index2;
2267         dv = dest->v.u.vec;
2268         sv = source->u.vec;
2269         ssize = (mp_int)VEC_SIZE(sv);
2270 
2271 #ifdef NO_NEGATIVE_RANGES
2272         if (index1 > index2)
2273             errorf("Illegal range [%"PRIdMPINT"..%"PRIdMPINT
2274                    "] for assignment.\n", index1, index2-1
2275                  );
2276 #endif /* NO_NEGATIVE_RANGES */
2277 
2278         if (ssize + index1 - index2 == 0)
2279         {
2280             /* <source> fits exactly into the target range */
2281 
2282             svalue_t *s, *d; /* Copy source and destination */
2283 
2284             s = sv->item;
2285             d = dv->item + index1;
2286 
2287             /* If there is just one ref to the source, use the faster
2288              * transfer instead of the slow assign for the copy.
2289              */
2290             if (sv->ref == 1)
2291             {
2292                 for (i = ssize; --i >= 0; )
2293                 {
2294                     transfer_svalue(d++, s++);
2295                 }
2296                 free_empty_vector(sv);
2297             }
2298             else /* sv->ref > 1 */
2299             {
2300                 for (i = ssize; --i >= 0; )
2301                 {
2302                     assign_svalue(d++, s++);
2303                 }
2304 
2305                 deref_array(sv);
2306                 /* The if() above effectively did the 'free_svalue(source)' */
2307             }
2308         }
2309         else
2310         {
2311             /* Create a new vector */
2312 
2313             svalue_t *s, *d;  /* Copy source and destination */
2314 
2315             rv = allocate_array(dsize + ssize + index1 - index2);
2316             dest->lvalue->u.vec = rv;
2317 
2318             s = dv->item;
2319             d = rv->item;
2320             for (i = index1; --i >= 0; )
2321             {
2322                 assign_svalue_no_free(d++, s++);
2323             }
2324 
2325             s = sv->item;
2326             for (i = ssize; --i >= 0; )
2327             {
2328                 assign_svalue_no_free(d++, s++);
2329             }
2330             free_array(sv);
2331 
2332             s = dv->item + index2;
2333             for (i = dsize - index2; --i >= 0; )
2334             {
2335                 assign_svalue_no_free(d++, s++);
2336             }
2337 
2338             free_array(dv); /* this can make the lvalue invalid to use */
2339         }
2340     }
2341     else
2342     {
2343         /* Not a pointer, or the protected range has changed in size before:
2344          * just free it
2345          */
2346         free_svalue(source);
2347     }
2348 
2349 } /* transfer_protected_pointer_range() */
2350 
2351 /*-------------------------------------------------------------------------*/
2352 static void
assign_string_range(svalue_t * source,Bool do_free)2353 assign_string_range (svalue_t *source, Bool do_free)
2354 
2355 /* Transfer the string <source> to the string range defined by
2356  * <special_lvalue>, modifying the target string in special_lvalue
2357  * accordingly. If <do_free> is TRUE, <source> is freed once in the call.
2358  *
2359  * If <source> is not a string, it is just freed resp. ignored.
2360  */
2361 
2362 {
2363     if (source->type == T_STRING)
2364     {
2365         svalue_t *dsvp;     /* destination svalue (from special_lvalue) */
2366         string_t *ds;            /* destination string (from dsvp) */
2367         string_t *ss;            /* source string (from source) */
2368         string_t *rs;            /* result string */
2369         mp_int dsize;            /* size of destination string */
2370         mp_int ssize;            /* size of source string */
2371         mp_int index1, index2;   /* range indices */
2372 
2373         /* Set variables */
2374         dsize = special_lvalue.size;
2375         index1 = special_lvalue.index1;
2376         index2 = special_lvalue.index2;
2377         dsvp = special_lvalue.v.u.lvalue;
2378         ds = dsvp->u.str;
2379         ss = source->u.str;
2380         ssize = (mp_int)mstrsize(ss);
2381 
2382 #ifdef NO_NEGATIVE_RANGES
2383         if (index1 > index2)
2384             errorf("Illegal range [%"PRIdMPINT"..%"PRIdMPINT
2385                    "] for assignment.\n", index1, index2-1
2386                  );
2387 #endif /* NO_NEGATIVE_RANGES */
2388 
2389         /* Create the new string */
2390         rs = alloc_mstring((size_t)(dsize + ssize + index1 - index2));
2391         if (!rs)
2392         {
2393             /* We don't pop the stack here --> don't free source */
2394             outofmem((dsize + ssize + index1 - index2), "new string");
2395         }
2396 
2397         if (index1)
2398             memcpy(get_txt(rs), get_txt(ds), (size_t)index1);
2399         if (ssize)
2400             memcpy(get_txt(rs) + index1, get_txt(ss), (size_t)ssize);
2401         if (dsize > index2)
2402             memcpy( get_txt(rs) + index1 + ssize, get_txt(ds) + index2
2403                   , (size_t)(dsize - index2));
2404 
2405         /* Assign the new string in place of the old */
2406         free_string_svalue(dsvp);
2407         dsvp->u.str = rs;
2408 
2409         if (do_free)
2410             free_string_svalue(source);
2411     }
2412     else
2413     {
2414         /* Not a string: just free it */
2415         if (do_free)
2416             free_svalue(source);
2417     }
2418 } /* assign_string_range() */
2419 
2420 /*-------------------------------------------------------------------------*/
2421 static void
assign_protected_string_range(struct protected_range_lvalue * dest,svalue_t * source,Bool do_free)2422 assign_protected_string_range ( struct protected_range_lvalue *dest
2423                               , svalue_t *source
2424                               , Bool do_free
2425                               )
2426 
2427 /* Transfer the string <source> to the string range defined by
2428  * <dest>, modifying the target string in dest
2429  * accordingly.
2430  *
2431  * If <do_free> is TRUE, <source> and the protector <dest> are freed once
2432  * in the call.
2433  *
2434  * If <source> is not a string, it is just freed resp. ignored.
2435  */
2436 
2437 {
2438     if (source->type == T_STRING)
2439     {
2440         svalue_t *dsvp;     /* destination value (from dest) */
2441         string_t *ds;            /* destination string (from dsvp) */
2442         string_t *ss;            /* source string (from source) */
2443         string_t *rs;            /* result string */
2444         mp_int dsize;            /* size of destination string */
2445         mp_int ssize;            /* size of source string */
2446         mp_int rsize;            /* size of result string */
2447         mp_int index1, index2;   /* range indices */
2448 
2449         /* Set variables */
2450         dsize = dest->size;
2451         index1 = dest->index1;
2452         index2 = dest->index2;
2453         dsvp = dest->lvalue;
2454         ds = dest->v.u.str;
2455 
2456 #ifdef NO_NEGATIVE_RANGES
2457         if (index1 > index2)
2458             errorf("Illegal range [%"PRIdMPINT"..%"PRIdMPINT
2459                    "] for assignment.\n", index1, index2-1
2460                  );
2461 #endif /* NO_NEGATIVE_RANGES */
2462 
2463         /* If the lvalue is no longer valid, free it */
2464         if (dsvp->u.str != ds)
2465         {
2466             if (do_free)
2467                 free_svalue(source);
2468             return;
2469         }
2470 
2471         /* Create a new string */
2472         ss = source->u.str;
2473         ssize = (mp_int)mstrsize(ss);
2474         rsize = dsize + ssize + index1 - index2;
2475         rs = alloc_mstring((size_t)rsize);
2476         if (!rs)
2477         {
2478             outofmem((dsize + ssize + index1 - index2), "new string");
2479         }
2480 
2481         if (index1)
2482             memcpy(get_txt(rs), get_txt(ds), (size_t)index1);
2483         if (ssize)
2484             memcpy(get_txt(rs) + index1, get_txt(ss), (size_t)ssize);
2485         dest->index2 = (int)(index1 + ssize);
2486         if (dsize > index2)
2487             memcpy( get_txt(rs) + dest->index2, get_txt(ds) + index2
2488                   , (size_t)(dsize - index2));
2489         dest->size = rsize;
2490         free_mstring(ds);
2491         free_mstring(ds);
2492         /* we will have two references to rs */
2493         ref_mstring(rs);
2494         dest->v.u.str = dsvp->u.str = rs;
2495 
2496         if (do_free)
2497             free_string_svalue(source);
2498     }
2499     else
2500     {
2501         /* Not a string: just free it */
2502         if (do_free)
2503             free_svalue(source);
2504     }
2505 } /* transfer_protected_string_range() */
2506 
2507 /*-------------------------------------------------------------------------*/
2508 static void
add_number_to_lvalue(svalue_t * dest,int i,svalue_t * pre,svalue_t * post)2509 add_number_to_lvalue (svalue_t *dest, int i, svalue_t *pre, svalue_t *post)
2510 
2511 /* Add the number <i> to the (PROTECTED_)LVALUE <dest>.
2512  * If <pre> is not null, the <dest> value before the addition is copied
2513  * into it.
2514  * If <post> is not null, the <dest> value after the addition is copied
2515  * into it.
2516  * Both <pre> and <post> are supposed to be empty svalues when given.
2517  *
2518  * If <dest> is of the wrong type, an error is generated.
2519  */
2520 
2521 {
2522     /* Deref the T_(PROTECTED_)LVALUES */
2523     do
2524         dest = dest->u.lvalue;
2525     while (dest->type == T_LVALUE || dest->type == T_PROTECTED_LVALUE);
2526 
2527     /* Now increment the non-LVALUE */
2528     switch (dest->type)
2529     {
2530     default:
2531         errorf("Reference to bad type %s to ++/--\n", typename(dest->type));
2532         break;
2533 
2534     case T_NUMBER:
2535         if (pre) put_number(pre, dest->u.number);
2536         dest->u.number += i;
2537         if (post) put_number(post, dest->u.number);
2538         break;
2539 
2540     case T_FLOAT:
2541       {
2542         STORE_DOUBLE_USED
2543         double d;
2544 
2545         d = READ_DOUBLE(dest);
2546 
2547         if (pre)
2548         {
2549             pre->type = T_FLOAT;
2550             STORE_DOUBLE(pre, d);
2551         }
2552 
2553         d += (double)i;
2554         STORE_DOUBLE(dest, d);
2555 
2556         if (post)
2557         {
2558             post->type = T_FLOAT;
2559             STORE_DOUBLE(post, d);
2560         }
2561         break;
2562       }
2563 
2564     case T_PROTECTED_LVALUE:
2565         add_number_to_lvalue(dest, i, pre, post);
2566         break;
2567 
2568     case T_CHAR_LVALUE:
2569         if (pre) put_number(pre, (unsigned char)*dest->u.charp);
2570         *(dest->u.charp) += i;
2571         if (post) put_number(post, (unsigned char)*dest->u.charp);
2572         break;
2573 
2574     case T_PROTECTED_CHAR_LVALUE:
2575       {
2576         struct protected_char_lvalue *p;
2577 
2578         p = (struct protected_char_lvalue *)dest;
2579         if (p->lvalue->type == T_STRING
2580          && get_txt(p->lvalue->u.str) == p->start)
2581         {
2582             if (pre) put_number(pre, (unsigned char)*(p->v.u.charp));
2583             i = (unsigned char)(*(p->v.u.charp) += i);
2584             if (post) put_number(post, i);
2585         }
2586         break;
2587       }
2588     } /* switch() */
2589 } /* add_number_to_lvalue() */
2590 
2591 /*-------------------------------------------------------------------------*/
2592 static vector_t *
inter_add_array(vector_t * q,vector_t ** vpp)2593 inter_add_array (vector_t *q, vector_t **vpp)
2594 
2595 /* Append array <q> to array *<vpp>. Both <q> and *<vpp> are freed,
2596  * the result vector (just one ref) is assigned to *<vpp> and also returned.
2597  *
2598  * <inter_sp> is supposed to point at the two vectors and will be decremented
2599  * by 2.
2600  */
2601 
2602 {
2603     vector_t *p;       /* The second summand vector */
2604     mp_int cnt;
2605     vector_t *r;       /* Result vector */
2606     svalue_t *s, *d;   /* Pointers for copying: src and dest */
2607     size_t p_size, q_size;  /* Sizes of p and q */
2608 
2609     p = *vpp;
2610 
2611     /* *vpp could be in the summands, thus don't free p / q before
2612      * assigning.
2613      * On the other hand, with an uninitialized array, we musn't assign
2614      * before the copying is done.
2615      */
2616 
2617     p_size = VEC_SIZE(p);
2618     q_size = VEC_SIZE(q);
2619     s = p->item;
2620 
2621     /* Check the result size for legality - this leaves the code below
2622      * to deal just with out of memory conditions.
2623      */
2624 
2625     if (max_array_size && p_size + q_size > max_array_size)
2626     {
2627         errorf("Illegal array size: %zu.\n", (p_size + q_size));
2628     }
2629 
2630     /* The optimized array-adding will transfer elements around, rendering
2631      * the arrays on the stack inconsistent. Thus any out-of-memory
2632      * error must not attempt to free them - leaking them is the lesser
2633      * evil in this situation.
2634      */
2635     inter_sp -= 2;
2636 
2637     /* Out of memory might result in some memory leaks. Better that freeing
2638      * arrays with 0 ref count, or indigestion in garbage_collection() .
2639      * It will simply give some more debugging output...
2640      */
2641 
2642     /* Allocate the result vector and copy p into it.
2643      */
2644     if (!(p->ref-1))
2645     {
2646         /* p will be deallocated completely - try to optimize a bit */
2647 
2648         /* We try to expand the existing memory for p (without moving)
2649          * instead of allocating a completely new vector.
2650          */
2651         d = malloc_increment_size(p, q_size * sizeof(svalue_t));
2652         if ( NULL != d)
2653         {
2654             /* We got the additional memory */
2655             r = p;
2656             r->ref = 1;
2657             r->size = p_size + q_size;
2658 
2659             r->user->size_array -= p_size;
2660             r->user = current_object->user;
2661             r->user->size_array += p_size + q_size;
2662         } else
2663         /* Just allocate a new vector and memcopy p into it. */
2664         {
2665             r = allocate_uninit_array((p_int)(p_size + q_size));
2666             deref_array(p);
2667             d = r->item;
2668             for (cnt = (mp_int)p_size; --cnt >= 0; )
2669             {
2670                 *d++ = *s++;
2671             }
2672         }
2673     }
2674     else
2675     {
2676         /* p must survive: allocate a new vector and assign the values
2677          * from p.
2678          */
2679         r = allocate_uninit_array((p_int)(p_size + q_size));
2680         deref_array(p);
2681         d = r->item;
2682         for (cnt = (mp_int)p_size; --cnt >= 0; ) {
2683             assign_checked_svalue_no_free (d++, s++);
2684         }
2685     }
2686 
2687     /* Here 'd' points to the first item to set */
2688 
2689     /* Add the values from q. Again, try to optimize */
2690     s = q->item;
2691     if (q->ref == 1)
2692     {
2693         for (cnt = (mp_int)q_size; --cnt >= 0; )
2694         {
2695             if (destructed_object_ref(s))
2696             {
2697                 assign_svalue(s, &const0);
2698             }
2699             *d++ = *s++;
2700         }
2701         *vpp = r;
2702         free_empty_vector(q);
2703     }
2704     else /* q->ref > 1 */
2705     {
2706         for (cnt = (mp_int)q_size; --cnt >= 0; ) {
2707             assign_checked_svalue_no_free (d++, s++);
2708         }
2709         *vpp = r;
2710 
2711         deref_array(q);
2712     }
2713 
2714     if (!p->ref && p != q)
2715         free_empty_vector(p);
2716 
2717     return r;
2718 } /* inter_add_array() */
2719 
2720 
2721 /*=========================================================================*/
2722 
2723 /*                           S T A C K                                     */
2724 
2725 /*-------------------------------------------------------------------------*/
2726 /* The following functions handle the pushing and popping of the
2727  * interpreter stack. Often functions appear in two versions: one version
2728  * using the global variable <inter_sp>, the other version receiving and
2729  * returning the old/new stack pointer as argument and result.
2730  *
2731  * Obviously, the former version can be easily called from outside the
2732  * interpreter, while the latter allows better optimization.
2733  *
2734  * To make things even more complicated, some of the 'slower' functions
2735  * are redefined with preprocessor macros to use the faster function - this
2736  * is meant to make the code in this module faster, but relies on certain
2737  * naming conventions (e.g. that 'sp' is always the local copy of the
2738  * stack pointer).
2739  *
2740  * TODO: Streamline the functions, given them macros as fast alternative
2741  * TODO:: publish them all in interpret.h and enforce their use.
2742  *-------------------------------------------------------------------------
2743  * The functions are:
2744  *
2745  * put_c_string (sp, p)
2746  *     Convert the C-String <p> into a mstring and put it into <sp>.
2747  * push_svalue(v), push_svalue_block(num,v):
2748  *     Push one or more svalues onto the stack.
2749  * pop_stack(), _drop_n_elems(n,sp):
2750  *     Pop (free) elements from the stack.
2751  * stack_overflow(sp,fp,pc):
2752  *     Handle a stack overflow.
2753  * push_referenced_mapping(m):
2754  *     Push a mapping onto the stack.
2755  * push_error_handler(h)
2756  *     Push an errorhandler entry onto the stack.
2757  */
2758 
2759 /*-------------------------------------------------------------------------*/
2760 void
put_c_string(svalue_t * sp,const char * p)2761 put_c_string (svalue_t *sp, const char *p)
2762 
2763 /* Put a copy of the C string *<p> into <sp>.
2764  */
2765 
2766 {
2767     string_t * str;
2768 
2769     memsafe(str = new_mstring(p), strlen(p), "string");
2770     put_string(sp, str);
2771 } /* put_c_string() */
2772 
2773 /*-------------------------------------------------------------------------*/
2774 void
put_c_n_string(svalue_t * sp,const char * p,size_t len)2775 put_c_n_string (svalue_t *sp, const char *p, size_t len)
2776 
2777 /* Put a copy of first <len> characters of the C string *<p> into <sp>.
2778  */
2779 
2780 {
2781     string_t * str;
2782 
2783     memsafe(str = new_n_mstring(p, len), len, "string");
2784     put_string(sp, str);
2785 } /* put_c_n_string() */
2786 
2787 /*-------------------------------------------------------------------------*/
2788 void
push_svalue(svalue_t * v)2789 push_svalue (svalue_t *v)
2790 
2791 /* Push the svalue <v> onto the stack as defined by <inter_sp>.
2792  * Same semantic as assign_svalue_no_free().
2793  */
2794 
2795 {
2796     assign_svalue_no_free(++inter_sp, v);
2797 }
2798 
2799 /*-------------------------------------------------------------------------*/
2800 void
push_svalue_block(int num,svalue_t * v)2801 push_svalue_block (int num, svalue_t *v)
2802 
2803 /* Push all <num> svalues starting at <v> onto the stack as defined by
2804  * <inter_sp>. Same semantic as assign_svalue_no_free().
2805  */
2806 
2807 {
2808     svalue_t *w;
2809 
2810     for (w = inter_sp; --num >= 0; v++)
2811     {
2812         w++;
2813         assign_lrvalue_no_free(w, v);
2814     }
2815     inter_sp = w;
2816 }
2817 
2818 /*-------------------------------------------------------------------------*/
2819 static INLINE void
_pop_stack(void)2820 _pop_stack (void)
2821 
2822 /* Pop the topmost element from the stack as defined by <inter_sp>,
2823  * using free_svalue().
2824  */
2825 
2826 {
2827 #ifdef DEBUG
2828     if (inter_sp < VALUE_STACK)
2829         fatal("VM Stack underflow: %"PRIdMPINT" too low.\n",
2830               (mp_int)(VALUE_STACK - inter_sp));
2831 #endif
2832     free_svalue(inter_sp--);
2833 }
2834 
pop_stack(void)2835 void pop_stack (void) { _pop_stack(); }
2836 
2837 /*-------------------------------------------------------------------------*/
2838 static INLINE svalue_t *
_pop_n_elems(int n,svalue_t * sp)2839 _pop_n_elems (int n, svalue_t *sp)
2840 
2841 /* Pop the <n> topmost elements from the stack, currently ending at <sp>,
2842  * and return the new stackpointer.
2843  * The elements are freed using free_svalue().
2844  */
2845 
2846 {
2847 #ifdef DEBUG
2848     if (n < 0)
2849         fatal("pop_n_elems: %d elements.\n", n);
2850 #endif
2851     for (; --n >= 0; )
2852     {
2853         free_svalue(sp--);
2854     }
2855     return sp;
2856 }
2857 
pop_n_elems(int n,svalue_t * sp)2858 svalue_t * pop_n_elems (int n, svalue_t *sp)
2859 { return _pop_n_elems(n, sp); }
2860 
2861 /*-------------------------------------------------------------------------*/
2862 static void stack_overflow (svalue_t *sp, svalue_t *fp, bytecode_p pc)
2863                               NORETURN;
2864 static void
stack_overflow(svalue_t * sp,svalue_t * fp,bytecode_p pc)2865 stack_overflow (svalue_t *sp, svalue_t *fp, bytecode_p pc)
2866 
2867 /* Recover from a stack overflow by popping all the elements between the
2868  * current stack end <sp> and the begin of the frame <fp>.
2869  * The function then assigns the new <sp> == <fp> and the <pc> to the
2870  * corresponding inter_xx variables and generates an error.
2871  */
2872 
2873 {
2874     if (sp >= &VALUE_STACK[SIZEOF_STACK])
2875         fatal("Fatal stack overflow: %"PRIdMPINT" too high.\n"
2876              , (mp_int)(sp - &VALUE_STACK[SIZEOF_STACK])
2877              );
2878     sp = _pop_n_elems(sp-fp, sp);
2879     ERROR("stack overflow\n");
2880 }
2881 
2882 /*-------------------------------------------------------------------------*/
2883 void
push_referenced_mapping(mapping_t * m)2884 push_referenced_mapping (mapping_t *m)
2885 
2886 /* Push mapping <m> onto the stack as defined by <inter_sp>.
2887  * The refs of <m> are _not_ incremented.
2888  */
2889 
2890 {
2891     inter_sp++;
2892     put_mapping(inter_sp, m);
2893 }
2894 
2895 /*-------------------------------------------------------------------------*/
2896 svalue_t *
push_error_handler(void (* errorhandler)(svalue_t *),svalue_t * arg)2897 push_error_handler(void (*errorhandler)(svalue_t *), svalue_t *arg)
2898 
2899 /* Push the <errorhandler>() with the argument <arg> as error handler
2900  * onto the stack.
2901  * This means that a new T_LVALUE is created on the stack, pointing
2902  * to <arg>. <arg> itself is setup to be a T_ERROR_HANDLER value.
2903  * Returns new inter_sp.
2904  */
2905 
2906 {
2907     arg->type = T_ERROR_HANDLER;
2908     arg->u.error_handler = errorhandler;
2909 
2910     inter_sp++;
2911     inter_sp->type = T_LVALUE;
2912     inter_sp->u.lvalue = arg;
2913     return inter_sp;
2914 } /* push_error_handler() */
2915 
2916 /*-------------------------------------------------------------------------*/
2917 /* Fast version of several functions, must come last so to not disturb
2918  * the actual definitions:
2919  */
2920 
2921 #define pop_stack()             free_svalue(sp--)
2922 #define pop_n_elems(n)          (sp = _pop_n_elems((n), sp))
2923 
2924 /*=========================================================================*/
2925 
2926 /*                          I N D E X I N G                                */
2927 
2928 /*-------------------------------------------------------------------------*/
2929 /* The following functions are concerned with the indexing of single
2930  * elements and ranges of strings, vectors and mappings, both as rvalue
2931  * and lvalue.
2932  *
2933  * Most of the functions are just the implementations of the corresponding
2934  * machine operators and are called just from the interpreter switch().
2935  * The actual arguments are pulled from the vm stack and the results pushed;
2936  * the functions receive the current stackpointer and programcounter as
2937  * function call parameters. The program counter is usally only used to
2938  * update <inter_pc> in case of errors. Result of the call is the new
2939  * stackpointer pointing to the result on the machine stack.
2940  *
2941  * Some typical layouts:
2942  *
2943  *     (LVALUE) -> indexed svalue from vector/mapping
2944  *                 (might be copied into indexing_quickfix)
2945  *
2946  *       by: push_(r)indexed_lvalue()
2947  *           (r)index_lvalue()
2948  *
2949  *
2950  *     (LVALUE) -> (CHAR_LVALUE)
2951  *                 special_lvalue.u.charp -> character in untabled string
2952  *
2953  *       by: (r)index_lvalue() on string lvalues
2954  *
2955  *
2956  *     (LVALUE) -> (PROTECTED_LVALUE) -> indexed svalue in vector/mapping
2957  *                 protector          -> vector/mapping
2958  *       by: push_protected_(r)indexed_lvalue()
2959  *           push_protected_indexed_map_lvalue()
2960  *           protected_(r)index_lvalue()
2961  *
2962  *
2963  *     (LVALUE) -> (PROTECTED_CHAR_LVALUE)
2964  *                    .lvalue -> untabled string svalue
2965  *                    .charp -> indexed character in untabled string
2966  *                    .start  -> first character of actual string text
2967  *                    .protector: T_INVALID or the string's .protector value
2968  *                                if the string itself is result of a protected
2969  *                                lvalue index.
2970  *
2971  *       by: protected_(r)index_lvalue() on string lvalue
2972  *
2973  *
2974  *     (LVALUE) -> (T_{STRING,POINTER}_RANGE_LVALUE)
2975  *                   special_lvalue.v   -> indexed-on string/vector
2976  *                   special_lvalue.size:  size of the string/vector
2977  *                                 .ind1:  lower index
2978  *                                 .ind2:  upper index
2979  *
2980  *       by: range_lvalue()
2981  *
2982  *
2983  *     (LVALUE) -> (T_PROTECTED_{STRING,POINTER}_RANGE_LVALUE)
2984  *                   .v   :   indexed-on string/vector
2985  *                   .lvalue -> svalue of indexed-on string/vector
2986  *                   .size:  size of the string/vector
2987  *                   .ind1:  lower index
2988  *                   .ind2:  upper index
2989  *                   .protector: the protector of the initial lvalue, if any.
2990  *
2991  *       by: protected_range_lvalue()
2992  *
2993  *
2994  * TODO: A lot of the functions differ only in minute details - test how
2995  * TODO:: much time merging the functions (and adding if()s for the
2996  * TODO:: differences) really costs.
2997  *-------------------------------------------------------------------------
2998  * The functions (in a LPCish notation) are:
2999  *
3000  *   push_indexed_lvalue(vector|mapping v, int|mixed i)
3001  *     Return &(v[i]), unprotected.
3002  *   push_rindexed_lvalue(vector v, int i)
3003  *     Return &(v[<i]), unprotected.
3004  *   push_aindexed_lvalue(vector v, int i)
3005  *     Return &(v[>i]), unprotected.
3006  *   push_protected_indexed_lvalue(vector|mapping v, int|mixed i)
3007  *     Return &(v[i]), protected.
3008  *   push_protected_rindexed_lvalue(vector v, int i)
3009  *     Return &(v[<i]), protected.
3010  *   push_protected_aindexed_lvalue(vector v, int i)
3011  *     Return &(v[>i]), protected.
3012  *   push_protected_indexed_map_lvalue(mapping m, mixed i, int j)
3013  *     Return &(m[i:j]), protected.
3014  *   index_lvalue(vector|mapping|string & v, int|mixed i)
3015  *     Return &(*v[i]), unprotected, using special_lvalue.
3016  *   rindex_lvalue(vector|string & v, int i)
3017  *     Return &(*v[<i]), unprotected, using special_lvalue.
3018  *   aindex_lvalue(vector|string & v, int i)
3019  *     Return &(*v[>i]), unprotected, using special_lvalue.
3020  *   protected_index_lvalue(vector|mapping|string & v, int|mixed i)
3021  *     Return &(*v[i]), protected.
3022  *   protected_rindex_lvalue(vector|string & v, int i)
3023  *     Return &(*v[<i]), protected.
3024  *   protected_aindex_lvalue(vector|string & v, int i)
3025  *     Return &(*v[>i]), protected.
3026  *   range_lvalue(vector|string & v, int i2, int i1)
3027  *     Return &(*v[i1..i2]), unprotected, using special_lvalue.
3028  *   protected_range_lvalue(vector|string & v, int i2, int i1)
3029  *     Return &(*v[i1..i2]), protected.
3030  *   push_indexed_value(string|vector|mapping|struct v, int|mixed i)
3031  *     Return v[i].
3032  *   push_rindexed_value(string|vector v, int i)
3033  *     Return v[<i].
3034  *   push_aindexed_value(string|vector v, int i)
3035  *     Return v[>i].
3036  */
3037 
3038 /*-------------------------------------------------------------------------*/
3039 static INLINE svalue_t *
get_vector_item(vector_t * vec,svalue_t * i,svalue_t * sp,bytecode_p pc)3040 get_vector_item (vector_t * vec, svalue_t * i, svalue_t *sp, bytecode_p pc)
3041 
3042 /* Index vector <vec> with index <i> and return the pointer to the
3043  * indexed item.
3044  * If the index is invalid, throw an error.
3045  */
3046 
3047 {
3048     p_int ind;
3049     svalue_t * item;
3050 
3051     if (i->type != T_NUMBER)
3052     {
3053         ERRORF(("Illegal index for []: got %s, expected number.\n"
3054                , typename(i->type)
3055                ));
3056         return NULL;
3057     }
3058     else
3059     {
3060         ind = i->u.number;
3061         if (ind < 0)
3062         {
3063             ERROR("Illegal index for []: not a positive number.\n");
3064             /* NOTREACHED */
3065             return NULL;
3066         }
3067         if (ind >= VEC_SIZE(vec))
3068         {
3069             ERRORF(("Index for [] out of bounds: %"PRIdPINT
3070                     ", vector size: %"PRIdPINT"\n"
3071                    , ind, VEC_SIZE(vec)));
3072             /* NOTREACHED */
3073             return NULL;
3074         }
3075     }
3076 
3077     /* Compute the indexed element */
3078     item = &vec->item[ind];
3079     if (destructed_object_ref(item))
3080     {
3081         free_svalue(item);
3082         put_number(item, 0);
3083     }
3084 
3085     return item;
3086 } /* get_vector_item() */
3087 
3088 /*-------------------------------------------------------------------------*/
3089 static INLINE svalue_t *
get_vector_r_item(vector_t * vec,svalue_t * i,svalue_t * sp,bytecode_p pc)3090 get_vector_r_item (vector_t * vec, svalue_t * i, svalue_t *sp, bytecode_p pc)
3091 
3092 /* Reverse-index vector <vec> with index <i> and return the pointer to the
3093  * indexed item.
3094  * If the index is invalid, throw an error.
3095  */
3096 
3097 {
3098     p_int ind;
3099     svalue_t * item;
3100 
3101     if (i->type != T_NUMBER)
3102     {
3103         ERRORF(("Illegal index for [<]: got %s, expected number.\n"
3104                , typename(i->type)
3105                ));
3106         return NULL;
3107     }
3108     if ((ind = i->u.number) < 0)
3109     {
3110         ERROR("Illegal index for [<]: not a positive number.\n");
3111         return NULL;
3112     }
3113     if ( (ind = VEC_SIZE(vec) - ind) < 0
3114      ||  ind >= VEC_SIZE(vec)
3115        )
3116     {
3117         ERRORF(("Index out of bounds for [<]: %"PRIdPINT", vector size: %"
3118                 PRIdPINT".\n", i->u.number, VEC_SIZE(vec)));
3119         return NULL;
3120     }
3121 
3122     /* Compute the indexed element */
3123     item = &vec->item[ind];
3124     if (destructed_object_ref(item))
3125     {
3126         free_svalue(item);
3127         put_number(item, 0);
3128     }
3129 
3130     return item;
3131 } /* get_vector_r_item() */
3132 
3133 /*-------------------------------------------------------------------------*/
3134 static INLINE svalue_t *
get_vector_a_item(vector_t * vec,svalue_t * i,svalue_t * sp,bytecode_p pc)3135 get_vector_a_item (vector_t * vec, svalue_t * i, svalue_t *sp, bytecode_p pc)
3136 
3137 /* Arithmetic-index vector <vec> with index <i> and return the pointer to the
3138  * indexed item.
3139  * If the index is invalid, throw an error.
3140  */
3141 
3142 {
3143     p_int ind;
3144     svalue_t * item;
3145 
3146     if (i->type != T_NUMBER)
3147     {
3148         ERRORF(("Illegal index for [>]: got %s, expected number.\n"
3149                , typename(i->type)
3150                ));
3151         return NULL;
3152     }
3153     if (0 > (ind = i->u.number))
3154         ind = VEC_SIZE(vec) + ind;
3155     if (ind < 0 || ind >= VEC_SIZE(vec))
3156     {
3157         ERRORF(("Index out of bounds for [>]: %"PRIdPINT", vector size: %"
3158                 PRIdPINT".\n"
3159                , i->u.number, VEC_SIZE(vec)));
3160         return NULL;
3161     }
3162 
3163     /* Compute the indexed element */
3164     item = &vec->item[ind];
3165     if (destructed_object_ref(item))
3166     {
3167         free_svalue(item);
3168         put_number(item, 0);
3169     }
3170 
3171     return item;
3172 } /* get_vector_a_item() */
3173 
3174 /*-------------------------------------------------------------------------*/
3175 static INLINE char *
get_string_item(svalue_t * svp,svalue_t * i,Bool make_singular,Bool allow_one_past,svalue_t * sp,bytecode_p pc)3176 get_string_item ( svalue_t * svp, svalue_t * i, Bool make_singular
3177                 , Bool allow_one_past
3178                 , svalue_t *sp, bytecode_p pc)
3179 
3180 /* Index string <svp> with index <i> and return the pointer to the
3181  * indexed item.
3182  * If <make_singular> is TRUE, <svp> is made an untabled string
3183  * with just one reference.
3184  * If <allow_one_past> is TRUE, indexing one past the official end
3185  * of the string for retrieval purposes is ok. TODO: Remove this.
3186  * If the index is invalid, throw an error.
3187  */
3188 
3189 {
3190     mp_int ind;
3191 
3192     if (i->type != T_NUMBER)
3193     {
3194         ERRORF(("Illegal index for []: got %s, expected number.\n"
3195                , typename(i->type)
3196                ));
3197         return NULL;
3198     }
3199     else
3200     {
3201         ind = i->u.number;
3202         if (ind < 0)
3203         {
3204             ERROR("Illegal index for []: not a positive number.\n");
3205             return NULL;
3206         }
3207 
3208         if (ind > (mp_int)mstrsize(svp->u.str) )
3209         {
3210             ERRORF(("Index out for [] of bounds: %"PRIdMPINT
3211                     ", string length: %zu.\n"
3212                    , ind, mstrsize(svp->u.str)));
3213             return NULL;
3214         }
3215 
3216         if (ind == (mp_int)mstrsize(svp->u.str))
3217         {
3218             if (!allow_one_past)
3219             {
3220                 ERRORF(("Index out of bounds for []: %"PRIdMPINT
3221                         ", string length: %zu.\n"
3222                        , ind, mstrsize(svp->u.str)));
3223                 return NULL;
3224             }
3225             else if (!runtime_no_warn_deprecated)
3226                 warnf( "Warning: Indexing past string end is deprecated: "
3227                        "index %"PRIdMPINT", string length: %zu.\n"
3228                      , ind, mstrsize(svp->u.str)
3229                      );
3230         }
3231     }
3232 
3233     /* The basic idea here was to to create a new copy of the string only
3234      * if the string is not singular (aka !mstr_singular(svp->u.str)).
3235      * Unfortunately local variable lvalues are pushed without counting
3236      * the additional reference, so we now have to play it safe and
3237      * duplicate the string whenever requested.
3238      */
3239     if (make_singular)
3240     {
3241         string_t *p;
3242 
3243         memsafe(p = unshare_mstring(svp->u.str), mstrsize(svp->u.str)
3244                , "modifiable string");
3245         svp->u.str = p;
3246     }
3247 
3248     return &(get_txt(svp->u.str)[ind]);
3249 } /* get_string_item() */
3250 
3251 /*-------------------------------------------------------------------------*/
3252 static INLINE char *
get_string_r_item(svalue_t * svp,svalue_t * i,Bool make_singular,Bool allow_one_past,svalue_t * sp,bytecode_p pc)3253 get_string_r_item (svalue_t * svp, svalue_t * i, Bool make_singular
3254                   , Bool allow_one_past
3255                   , svalue_t *sp, bytecode_p pc)
3256 
3257 /* Reverse-Index string <svp> with index <i> and return the pointer to the
3258  * indexed item.
3259  * If <allow_one_past> is TRUE, indexing one past the official end
3260  * of the string for retrieval purposes is ok. TODO: Remove this.
3261  * If <make_singular> is TRUE, <svp> is made an untabled string
3262  * with just one reference.
3263  * If the index is invalid, throw an error.
3264  */
3265 
3266 {
3267     mp_int ind;
3268 
3269     if (i->type != T_NUMBER)
3270     {
3271         ERRORF(("Illegal index for [<]: got %s, expected number.\n"
3272                , typename(i->type)
3273                ));
3274         return NULL;
3275     }
3276     else
3277     {
3278         ind = i->u.number;
3279         if ((ind = i->u.number) < 0)
3280         {
3281             ERROR("Illegal index for [<]: not a positive number.\n");
3282             return NULL;
3283         }
3284 
3285         /* Compute the real index. Allow ""[<1]. */
3286         ind = (mp_int)mstrsize(svp->u.str) - ind;
3287         if (!mstrsize(svp->u.str) && ind == -1)
3288             ind = 0;
3289 
3290         if ( ind < 0
3291          ||  ind > (mp_int)mstrsize(svp->u.str)
3292            )
3293         {
3294             ERRORF(("Index out of bounds for [<]: %"PRIdPINT
3295                     ", string length: %zu\n"
3296                    , i->u.number, mstrsize(svp->u.str)));
3297             return NULL;
3298         }
3299 
3300         if (ind == (mp_int)mstrsize(svp->u.str))
3301         {
3302             if (!allow_one_past)
3303             {
3304                 ERRORF(("Index out for [<] of bounds: %"PRIdMPINT
3305                         ", string length: %zu.\n"
3306                        , ind, mstrsize(svp->u.str)));
3307                 return NULL;
3308             }
3309             else if (!runtime_no_warn_deprecated)
3310                 warnf( "Warning: Indexing past string end is deprecated: "
3311                        "index %"PRIdMPINT", string length: %zu.\n"
3312                      , ind, mstrsize(svp->u.str)
3313                      );
3314         }
3315     }
3316 
3317     /* The basic idea here was to to create a new copy of the string only
3318      * if the string is not singular (aka !mstr_singular(svp->u.str)).
3319      * Unfortunately local variable lvalues are pushed without counting
3320      * the additional reference, so we now have to play it safe and
3321      * duplicate the string whenever requested.
3322      */
3323     if (make_singular)
3324     {
3325         string_t *p;
3326 
3327         memsafe(p = unshare_mstring(svp->u.str), mstrsize(svp->u.str)
3328                , "modifiable string");
3329         svp->u.str = p;
3330     }
3331 
3332     return &(get_txt(svp->u.str)[ind]);
3333 } /* get_string_r_item() */
3334 
3335 /*-------------------------------------------------------------------------*/
3336 static INLINE char *
get_string_a_item(svalue_t * svp,svalue_t * i,Bool make_singular,Bool allow_one_past,svalue_t * sp,bytecode_p pc)3337 get_string_a_item (svalue_t * svp, svalue_t * i, Bool make_singular
3338                   , Bool allow_one_past
3339                   , svalue_t *sp, bytecode_p pc)
3340 
3341 /* Arithmetic-Index string <svp> with index <i> and return the pointer to the
3342  * indexed item.
3343  * If <allow_one_past> is TRUE, indexing one past the official end
3344  * of the string for retrieval purposes is ok. TODO: Remove this.
3345  * If <make_singular> is TRUE, <svp> is made an untabled string
3346  * with just one reference.
3347  * If the index is invalid, throw an error.
3348  */
3349 
3350 {
3351     mp_int ind;
3352 
3353     if (i->type != T_NUMBER)
3354     {
3355         ERRORF(("Illegal index for [>]: got %s, expected number.\n"
3356                , typename(i->type)
3357                ));
3358         return NULL;
3359     }
3360     else
3361     {
3362         ind = i->u.number;
3363 
3364         if (0 > ind)
3365         {
3366             /* Compute the real index. Allow ""[<1]. */
3367             ind = (mp_int)mstrsize(svp->u.str) + ind;
3368             if (!mstrsize(svp->u.str) && ind == -1)
3369                 ind = 0;
3370         }
3371         if (ind < 0 || ind > (mp_int)mstrsize(svp->u.str))
3372         {
3373             ERRORF(("Index out of bounds for [>]: %"PRIdPINT
3374                     ", string length: %zu\n"
3375                    , i->u.number, mstrsize(svp->u.str)));
3376             return NULL;
3377         }
3378 
3379         if (ind == (mp_int)mstrsize(svp->u.str))
3380         {
3381             if (!allow_one_past)
3382             {
3383                 ERRORF(("Index out for [>] of bounds: %"PRIdMPINT
3384                         ", string length: %zu.\n"
3385                        , ind, mstrsize(svp->u.str)));
3386                 return NULL;
3387             }
3388             else if (!runtime_no_warn_deprecated)
3389                 warnf( "Warning: Indexing past string end is deprecated: "
3390                        "index %"PRIdMPINT", string length: %zu.\n"
3391                      , ind, mstrsize(svp->u.str)
3392                      );
3393         }
3394     }
3395 
3396     /* The basic idea here was to to create a new copy of the string only
3397      * if the string is not singular (aka !mstr_singular(svp->u.str)).
3398      * Unfortunately local variable lvalues are pushed without counting
3399      * the additional reference, so we now have to play it safe and
3400      * duplicate the string whenever requested.
3401      */
3402     if (make_singular)
3403     {
3404         string_t *p;
3405 
3406         memsafe(p = unshare_mstring(svp->u.str), mstrsize(svp->u.str)
3407                , "modifiable string");
3408         svp->u.str = p;
3409     }
3410 
3411     return &(get_txt(svp->u.str)[ind]);
3412 } /* get_string_a_item() */
3413 
3414 #ifdef USE_STRUCTS
3415 /*-------------------------------------------------------------------------*/
3416 static INLINE svalue_t *
check_struct_op(svalue_t * sp,int off_type,int off_value,bytecode_p pc)3417 check_struct_op (svalue_t * sp, int off_type, int off_value, bytecode_p pc)
3418 
3419 /* On the stack are the arguments for a struct indexing operation.
3420  * In particular: sp[<off_type>]:  the struct type index <idx>
3421  *               sp[<off_value>]:    <off_value> <= 0: the struct value to idx.
3422  *               sp[-<off_value>+1]: <off_value> >  0: the struct Lvalue to idx.
3423  *
3424  * Check the validity of the indexing operation and thrown an error
3425  * if invalid.
3426  *
3427  * <idx> gives the index of the expected struct type - the
3428  * operator accepts a struct of this type, or any of its children.
3429  * An negative <idx> accepts any struct.
3430  *
3431  * On success, the <idx> svalue is removed from the stack and the
3432  * new stack pointer is returned.
3433  */
3434 
3435 {
3436     short s_index;
3437     svalue_t * svp;
3438 
3439     /* These two errors can happen with careless funcall(#'->)s */
3440     if (sp[off_type].type != T_NUMBER)
3441         ERRORF(("Illegal struct type value: %s, expected a number.\n"
3442                , typename(sp[off_type].type)
3443               ));
3444     if (sp[off_type].u.number >= 0
3445      && sp[off_type].u.number >= current_prog->num_structs)
3446     {
3447         ERRORF(("Too big struct index: %"PRIdPINT", max %hu\n"
3448                , sp[off_type].u.number, current_prog->num_structs
3449               ));
3450     }
3451 
3452     /* Get the struct type index */
3453     s_index = (short)sp[off_type].u.number;
3454 
3455     if (off_value <= 0 && sp[off_value].type != T_STRUCT)
3456     {
3457         ERRORF(("Illegal type to struct->(): %s, expected struct.\n"
3458                , typename(sp[off_type].type)
3459               ));
3460         /* NOTREACHED */
3461     }
3462 
3463     /* Get the reference to struct svalue to index */
3464 
3465     if (off_value > 0)
3466     {
3467         svp = &sp[-off_value+1];
3468 
3469         if (svp->type != T_LVALUE && svp->type != T_PROTECTED_LVALUE)
3470         {
3471             ERRORF(("Illegal type to lvalue struct->(): %s value, "
3472                     "expected struct lvalue.\n"
3473                    , typename(svp->type)
3474                   ));
3475             /* NOTREACHED */
3476         }
3477 
3478         while (svp->type == T_LVALUE || svp->type == T_PROTECTED_LVALUE)
3479             svp = svp->u.lvalue;
3480         if (svp->type != T_STRUCT)
3481         {
3482             if (svp->type == T_NUMBER && !svp->u.number)
3483                 ERRORF(("Illegal type to lvalue struct->(): number 0, "
3484                         "expected struct.\n"
3485                       ));
3486             else
3487                 ERRORF(("Illegal type to lvalue struct->(): %s, "
3488                         "expected struct.\n"
3489                        , typename(svp->type)
3490                       ));
3491             /* NOTREACHED */
3492         }
3493     }
3494     else
3495         svp = &sp[off_value];
3496 
3497     /* Check if the struct on the stack is of the correct type */
3498     if (s_index >= 0)
3499     {
3500         struct_type_t * pExpected = current_prog->struct_defs[s_index].type;
3501         struct_type_t * pType = svp->u.strct->type;
3502 
3503         if (!struct_baseof(pExpected, pType))
3504         {
3505             string_t * got_name, * exp_name;
3506 
3507             got_name = struct_unique_name(svp->u.strct);
3508             if (!got_name)
3509                 got_name = struct_name(svp->u.strct);
3510 
3511             exp_name = struct_t_unique_name(pExpected);
3512             if (!exp_name)
3513                 exp_name = struct_t_name(pExpected);
3514 
3515             ERRORF(("Illegal type to%s struct->(): struct %s, "
3516                     "expected struct %s.\n"
3517                    , off_value > 0 ? " lvalue" : ""
3518                    , get_txt(got_name)
3519                    , get_txt(exp_name)
3520                   ));
3521         }
3522     }
3523 
3524     /* Remove the type index entry from the stack */
3525     if (off_type != 0)
3526     {
3527         for ( ; off_type < 0; off_type++)
3528             sp[off_type] = sp[off_type+1];
3529     }
3530 
3531     return sp-1;
3532 } /* check_struct_op() */
3533 
3534 /*-------------------------------------------------------------------------*/
3535 static INLINE svalue_t *
get_struct_item(struct_t * st,svalue_t * i,svalue_t * sp,bytecode_p pc)3536 get_struct_item (struct_t * st, svalue_t * i, svalue_t *sp, bytecode_p pc)
3537 
3538 /* Index struct <st> with index <i> and return the pointer to the
3539  * indexed item.
3540  * If the index is invalid, throw an error.
3541  */
3542 
3543 {
3544     p_int ind;
3545     svalue_t * item;
3546 
3547     if (i->type == T_SYMBOL || i->type == T_STRING)
3548     {
3549         ind = struct_find_member(st->type, i->u.str);
3550         if (ind < 0)
3551         {
3552             ERRORF(("Illegal struct '%s'->(): member '%s' not found.\n"
3553                    , get_txt(struct_name(st))
3554                    , get_txt(i->u.str)
3555                    ));
3556             /* NOTREACHED */
3557             return NULL;
3558         }
3559     }
3560     else if (i->type != T_NUMBER)
3561     {
3562         ERRORF(("Illegal struct '%s'->(): got %s, "
3563                 "expected number/string/symbol.\n"
3564                , get_txt(struct_name(st))
3565                , typename(i->type)
3566                ));
3567         return NULL;
3568     }
3569     else
3570     {
3571         ind = i->u.number;
3572         if (ind < 0)
3573         {
3574             ERRORF(("Illegal struct '%s'->(): not a positive number.\n"
3575                    , get_txt(struct_name(st))
3576                   ));
3577             /* NOTREACHED */
3578             return NULL;
3579         }
3580         if (ind >= struct_size(st))
3581         {
3582             ERRORF(("Illegal struct '%s'->: out of bounds: "
3583                     "%"PRIdPINT", struct sized: %lu.\n"
3584                    , get_txt(struct_name(st))
3585                    , ind
3586                    , (unsigned long)struct_size(st)
3587                   ));
3588             /* NOTREACHED */
3589             return NULL;
3590         }
3591     }
3592 
3593     /* Compute the indexed element */
3594     item = &st->member[ind];
3595     if (destructed_object_ref(item))
3596     {
3597         free_svalue(item);
3598         put_number(item, 0);
3599     }
3600 
3601     return item;
3602 } /* get_struct_item() */
3603 #endif /* USE_STRUCTS */
3604 
3605 /*-------------------------------------------------------------------------*/
3606 static INLINE svalue_t *
push_indexed_lvalue(svalue_t * sp,bytecode_p pc)3607 push_indexed_lvalue (svalue_t *sp, bytecode_p pc)
3608 
3609 /* Operator F_PUSH_INDEXED_LVALUE(vector  v=sp[-1], int   i=sp[0])
3610  * Operator F_PUSH_INDEXED_LVALUE(mapping v=sp[-1], mixed i=sp[0])
3611  * Operator F_PUSH_INDEXED_S_LVALUE(struct v=sp[-1], mixed i=sp[0])
3612  *
3613  * Compute the lvalue &(v[i]) and push it into the stack. If v has just
3614  * one ref left, the indexed item is stored in indexing_quickfix and the
3615  * lvalue refers to that variable.
3616  * TODO: indexing_quickfix could be implemented using protected lvalues.
3617  */
3618 
3619 {
3620     svalue_t *i;     /* the index value */
3621     svalue_t *vec;   /* the indexed vector or mapping */
3622 
3623     /* Get the arguments */
3624     i = sp;
3625     vec = sp - 1;
3626 
3627     /* Index a vector.
3628      */
3629     if (vec->type == T_POINTER)
3630     {
3631         svalue_t *item;
3632 
3633         item = get_vector_item(vec->u.vec, i, sp, pc);
3634 
3635         if (vec->u.vec->ref == 1)
3636         {
3637             /* Rescue the indexed item as vec will go away */
3638             assign_svalue (&indexing_quickfix, item);
3639             item = &indexing_quickfix;
3640         }
3641 
3642         /* Remove the arguments from the stack */
3643         sp = vec;
3644         free_array(vec->u.vec);
3645 
3646         /* Return the result */
3647         vec->type = T_LVALUE;
3648         vec->u.lvalue = item;
3649         return sp;
3650     }
3651 
3652 #ifdef USE_STRUCTS
3653     /* Index a struct.
3654      */
3655     if (vec->type == T_STRUCT)
3656     {
3657         struct_t * st = vec->u.strct;
3658         svalue_t * item;
3659 
3660         item = get_struct_item(st, i, sp, pc);
3661 
3662         if (st->ref == 1)
3663         {
3664             /* Rescue the indexed item as st will go away */
3665             assign_svalue (&indexing_quickfix, item);
3666             item = &indexing_quickfix;
3667         }
3668 
3669         /* Remove the arguments from the stack */
3670         free_svalue(sp); sp--;
3671         free_struct(st);
3672 
3673         /* Return the result */
3674         sp->type = T_LVALUE;
3675         sp->u.lvalue = item;
3676         return sp;
3677     }
3678 #endif /* USE_STRUCTS */
3679 
3680     /* Index a mapping
3681      */
3682     if (vec->type == T_MAPPING)
3683     {
3684         mapping_t *m;
3685         svalue_t *item;
3686 
3687         m = vec->u.map;
3688 
3689         if (!m->num_values)
3690         {
3691             ERROR("Indexing a mapping of width 0.\n");
3692             return NULL;
3693         }
3694 
3695         /* Compute the indexed element */
3696 
3697         item = get_map_lvalue(m, i);
3698         if (!item)
3699         {
3700             outofmemory("indexed lvalue");
3701             /* NOTREACHED */
3702             return NULL;
3703         }
3704 
3705         if (m->ref == 1)
3706         {
3707             /* Rescue the indexed item as vec will go away */
3708             assign_svalue (&indexing_quickfix, item);
3709             item = &indexing_quickfix;
3710         }
3711 
3712         /* Remove the arguments from the stack */
3713         free_svalue(sp--);
3714         free_mapping(m);
3715 
3716         /* Return the result */
3717         vec->type = T_LVALUE;
3718         vec->u.lvalue = item;
3719         return sp;
3720     }
3721 
3722     /* Illegal type to index */
3723     inter_sp = sp;
3724     inter_pc = pc;
3725     errorf("(lvalue1)Indexing on illegal type '%s'.\n", typename(vec->type));
3726     return sp;
3727 } /* push_indexed_lvalue() */
3728 
3729 /*-------------------------------------------------------------------------*/
3730 static INLINE svalue_t *
push_rindexed_lvalue(svalue_t * sp,bytecode_p pc)3731 push_rindexed_lvalue (svalue_t *sp, bytecode_p pc)
3732 
3733 /* Operator F_PUSH_RINDEXED_LVALUE(vector v=sp[-1], int i=sp[0])
3734  *
3735  * Compute the lvalue &(v[<i]) and push it into the stack. If v has just
3736  * one ref left, the indexed item is stored in indexing_quickfix and the
3737  * lvalue refers to that variable.
3738  */
3739 
3740 {
3741     svalue_t *i;     /* the index value */
3742     svalue_t *vec;   /* the vector */
3743 
3744     /* Get the arguments */
3745     i = sp;
3746     vec = sp - 1;
3747 
3748     /* Index a vector.
3749      */
3750     if (vec->type == T_POINTER)
3751     {
3752         svalue_t *item;
3753 
3754         item = get_vector_r_item(vec->u.vec, i, sp, pc);
3755 
3756         if (vec->u.vec->ref == 1)
3757         {
3758             /* Rescue the indexed item as vec will go away */
3759             assign_svalue (&indexing_quickfix, item);
3760             item = &indexing_quickfix;
3761         }
3762 
3763         /* Remove the arguments from the stack */
3764         sp = vec;
3765         free_array(vec->u.vec);
3766 
3767         /* Return the result */
3768         vec->type = T_LVALUE;
3769         vec->u.lvalue = item;
3770         return sp;
3771     }
3772 
3773     /* Indexing on illegal type */
3774     inter_sp = sp;
3775     inter_pc = pc;
3776     errorf("(lvalue2)Indexing on illegal type '%s'.\n", typename(vec->type));
3777     return NULL;
3778 } /* push_rindexed_lvalue() */
3779 
3780 /*-------------------------------------------------------------------------*/
3781 static INLINE svalue_t *
push_aindexed_lvalue(svalue_t * sp,bytecode_p pc)3782 push_aindexed_lvalue (svalue_t *sp, bytecode_p pc)
3783 
3784 /* Operator F_PUSH_AINDEXED_LVALUE(vector v=sp[-1], int i=sp[0])
3785  *
3786  * Compute the lvalue &(v[>i]) and push it into the stack. If v has just
3787  * one ref left, the indexed item is stored in indexing_quickfix and the
3788  * lvalue refers to that variable.
3789  */
3790 
3791 {
3792     svalue_t *i;     /* the index value */
3793     svalue_t *vec;   /* the vector */
3794 
3795     /* Get the arguments */
3796     i = sp;
3797     vec = sp - 1;
3798 
3799     /* Index a vector.
3800      */
3801     if (vec->type == T_POINTER)
3802     {
3803         svalue_t *item;
3804 
3805         item = get_vector_a_item(vec->u.vec, i, sp, pc);
3806 
3807         if (vec->u.vec->ref == 1)
3808         {
3809             /* Rescue the indexed item as vec will go away */
3810             assign_svalue (&indexing_quickfix, item);
3811             item = &indexing_quickfix;
3812         }
3813 
3814         /* Remove the arguments from the stack */
3815         sp = vec;
3816         free_array(vec->u.vec);
3817 
3818         /* Return the result */
3819         vec->type = T_LVALUE;
3820         vec->u.lvalue = item;
3821         return sp;
3822     }
3823 
3824     /* Indexing on illegal type */
3825     inter_sp = sp;
3826     inter_pc = pc;
3827     errorf("(lvalue3)Indexing on illegal type '%s'.\n", typename(vec->type));
3828     return NULL;
3829 } /* push_aindexed_lvalue() */
3830 
3831 /*-------------------------------------------------------------------------*/
3832 /* void BUILD_MAP_PROTECTOR(svalue_t *dest, mapping_t *m)
3833  *
3834  * Init svalue <dest> to protectively hold mapping <m> in which one entry
3835  * is about to be used as target for a lvalue.
3836  *
3837  * If mapping <m> is dirty, protect its hash_mapping part by incrementing
3838  * its refcount (and if this is the first call, also initialize the .deleted
3839  * entry), and by making the svalue a T_PROTECTOR_MAPPING.
3840  *
3841  * If <m> is not dirty, not protection is necessary.
3842  */
3843 #define BUILD_MAP_PROTECTOR(dest, m)     \
3844 {                                        \
3845     mapping_hash_t *hm;                  \
3846                                          \
3847     if ( NULL != (hm = (m)->hash) ) {    \
3848         if (!hm->ref++)                  \
3849             hm->deleted = NULL;          \
3850         dest.type = T_PROTECTOR_MAPPING; \
3851     } else {                             \
3852         dest.type = T_MAPPING;           \
3853     }                                    \
3854     dest.u.map = m;                      \
3855 }
3856 
3857 /*-------------------------------------------------------------------------*/
3858 static INLINE svalue_t *
push_protected_indexed_lvalue(svalue_t * sp,bytecode_p pc)3859 push_protected_indexed_lvalue (svalue_t *sp, bytecode_p pc)
3860 
3861 /* Op. F_PUSH_PROTECTED_INDEXED_LVALUE(vector  v=sp[-1], int   i=sp[0])
3862  * Op. F_PUSH_PROTECTED_INDEXED_LVALUE(mapping v=sp[-1], mixed i=sp[0])
3863  * Op. F_PUSH_PROTECTED_INDEXED_S_LVALUE(struct  v=sp[-1], mixed i=sp[0])
3864  *
3865  * Compute the lvalue &(v[i]), store it in a struct protected_lvalue, and
3866  * push the protector as PROTECTED_LVALUE into the stack.
3867  */
3868 
3869 {
3870     svalue_t           * i;       /* the index */
3871     svalue_t           * vec;     /* the vector */
3872 
3873     /* Get the arguments */
3874     i = sp;
3875     vec = sp - 1;
3876 
3877     /* Index a vector.
3878      */
3879     if (vec->type == T_POINTER)
3880     {
3881         svalue_t *item;
3882         struct protected_lvalue * lvalue;
3883 
3884         item = get_vector_item(vec->u.vec, i, sp, pc);
3885 
3886         /* Compute the indexed item and set up the protector */
3887 
3888         lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
3889         lvalue->v.type = T_PROTECTED_LVALUE;
3890         lvalue->v.u.lvalue = item;
3891         put_array(&(lvalue->protector), vec->u.vec);
3892           /* The one ref to vec is transferred from *vec */
3893 
3894         /* Remove the arguments and return the result */
3895         sp = vec;
3896         vec->type = T_LVALUE;
3897         vec->u.lvalue = &lvalue->v;
3898         return sp;
3899     }
3900 
3901 #ifdef USE_STRUCTS
3902     /* Index a struct.
3903      */
3904     if (vec->type == T_STRUCT)
3905     {
3906         struct_t * st = vec->u.strct;
3907         svalue_t * item;
3908         struct protected_lvalue * lvalue;
3909 
3910         item = get_struct_item(st, i, sp, pc);
3911 
3912         /* Item and set up the protector */
3913 
3914         lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
3915         lvalue->v.type = T_PROTECTED_LVALUE;
3916         lvalue->v.u.lvalue = item;
3917         put_struct(&(lvalue->protector), st);
3918           /* The one ref to st is transferred from *vec */
3919 
3920         /* Remove the arguments and return the result */
3921         free_svalue(i);
3922         sp = vec;
3923         sp->type = T_LVALUE;
3924         sp->u.lvalue = &lvalue->v;
3925         return sp;
3926     }
3927 #endif /* USE_STRUCTS */
3928 
3929     /* Index a mapping
3930      */
3931     if (vec->type == T_MAPPING)
3932     {
3933         mapping_t *m;
3934         svalue_t *item;
3935         struct protected_lvalue * lvalue;
3936 
3937         m = vec->u.map;
3938 
3939         if (!m->num_values)
3940         {
3941             ERROR("Indexing a mapping of width 0.\n");
3942             return NULL;
3943         }
3944 
3945         /* Compute the indexed item and set up the protector */
3946 
3947         item = get_map_lvalue(m, i);
3948         if (!item)
3949         {
3950             outofmemory("indexed lvalue");
3951             /* NOTREACHED */
3952             return NULL;
3953         }
3954 
3955         lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
3956         lvalue->v.type = T_PROTECTED_LVALUE;
3957         lvalue->v.u.lvalue = item;
3958         BUILD_MAP_PROTECTOR(lvalue->protector, m)
3959           /* The one ref is transferred from the stack */
3960 
3961         /* Remove the arguments and return the result */
3962         pop_stack();
3963         vec->type = T_LVALUE;
3964         vec->u.lvalue = &lvalue->v;
3965         return sp;
3966     }
3967 
3968     /* Indexing on illegal type. */
3969 
3970     inter_sp = sp;
3971     inter_pc = pc;
3972     errorf("(lvalue4)Indexing on illegal type '%s'.\n", typename(vec->type));
3973     return NULL;
3974 } /* push_protected_indexed_lvalue() */
3975 
3976 /*-------------------------------------------------------------------------*/
3977 static INLINE svalue_t *
push_protected_rindexed_lvalue(svalue_t * sp,bytecode_p pc)3978 push_protected_rindexed_lvalue (svalue_t *sp, bytecode_p pc)
3979 
3980 /* Op. F_PUSH_PROTECTED_RINDEXED_LVALUE(vector v=sp[-1], int i=sp[0])
3981  *
3982  * Compute the lvalue &(v[<i]), store it in a struct protected_lvalue, and
3983  * push the protector as PROTECTED_LVALUE into the stack.
3984  */
3985 
3986 {
3987     svalue_t           * i;       /* the index */
3988     svalue_t           * vec;     /* the vector */
3989     struct protected_lvalue * lvalue;  /* the protector */
3990 
3991     /* Get the arguments */
3992 
3993     i = sp;
3994     vec = sp - 1;
3995 
3996     /* Index a vector
3997      */
3998     if (vec->type == T_POINTER)
3999     {
4000         svalue_t *item;
4001 
4002         item = get_vector_r_item(vec->u.vec, i, sp, pc);
4003 
4004         /* Set up the protector */
4005 
4006         lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
4007         lvalue->v.type = T_PROTECTED_LVALUE;
4008         lvalue->v.u.lvalue = item;
4009         put_array(&(lvalue->protector), vec->u.vec);
4010           /* The one ref is transferred from the stack */
4011 
4012         /* Remove arguments and return result */
4013         sp = vec;
4014         vec->type = T_LVALUE;
4015         vec->u.lvalue = &lvalue->v;
4016         return sp;
4017     }
4018 
4019     /* Indexing in illegal type */
4020 
4021     inter_sp = sp;
4022     inter_pc = pc;
4023     errorf("(lvalue5)Indexing on illegal type '%s'.\n", typename(vec->type));
4024     return NULL;
4025 } /* push_protected_rindexed_lvalue() */
4026 
4027 /*-------------------------------------------------------------------------*/
4028 static INLINE svalue_t *
push_protected_aindexed_lvalue(svalue_t * sp,bytecode_p pc)4029 push_protected_aindexed_lvalue (svalue_t *sp, bytecode_p pc)
4030 
4031 /* Op. F_PUSH_PROTECTED_AINDEXED_LVALUE(vector v=sp[-1], int i=sp[0])
4032  *
4033  * Compute the lvalue &(v[>i]), store it in a struct protected_lvalue, and
4034  * push the protector as PROTECTED_LVALUE into the stack.
4035  */
4036 
4037 {
4038     svalue_t           * i;       /* the index */
4039     svalue_t           * vec;     /* the vector */
4040     struct protected_lvalue * lvalue;  /* the protector */
4041 
4042     /* Get the arguments */
4043 
4044     i = sp;
4045     vec = sp - 1;
4046 
4047     /* Index a vector
4048      */
4049     if (vec->type == T_POINTER)
4050     {
4051         svalue_t *item;
4052 
4053         item = get_vector_a_item(vec->u.vec, i, sp, pc);
4054 
4055         /* Setup the protector */
4056 
4057         lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
4058         lvalue->v.type = T_PROTECTED_LVALUE;
4059         lvalue->v.u.lvalue = item;
4060         put_array(&(lvalue->protector), vec->u.vec);
4061           /* The one ref is transferred from the stack */
4062 
4063         /* Remove arguments and return result */
4064         sp = vec;
4065         vec->type = T_LVALUE;
4066         vec->u.lvalue = &lvalue->v;
4067         return sp;
4068     }
4069 
4070     /* Indexing in illegal type */
4071 
4072     inter_sp = sp;
4073     inter_pc = pc;
4074     errorf("(lvalue6)Indexing on illegal type '%s'.\n", typename(vec->type));
4075     return NULL;
4076 } /* push_protected_aindexed_lvalue() */
4077 
4078 /*-------------------------------------------------------------------------*/
4079 static INLINE svalue_t *
push_protected_indexed_map_lvalue(svalue_t * sp,bytecode_p pc)4080 push_protected_indexed_map_lvalue (svalue_t *sp, bytecode_p pc)
4081 
4082 /* Op. F_PUSH_PROTECTED_INDEXED_MAP_LVALUE(mapping m=sp[-2], mixed i=sp[-1]
4083  *                                                         , int   j=sp[0])
4084  *
4085  * Compute the lvalue &(m[i:j]), store it in a struct protected_lvalue, and
4086  * push the protector as PROTECTED_LVALUE into the stack.
4087  */
4088 
4089 {
4090     svalue_t           * i;       /* the index */
4091     svalue_t           * vec;     /* the vector */
4092     svalue_t           * item;    /* the indexed element */
4093     struct protected_lvalue * lvalue;  /* the protector */
4094 
4095     /* Get the arguments */
4096     i = sp - 1;
4097     vec = sp - 2;
4098 
4099     /* Index a mapping.
4100      */
4101     if (vec->type == T_MAPPING)
4102     {
4103         mapping_t *m;
4104 
4105         m = vec->u.map;
4106         if (sp->type != T_NUMBER)
4107         {
4108             ERRORF(("Illegal subindex for []: got %s, expected number.\n"
4109                    , typename(sp->type)
4110                    ));
4111             return NULL;
4112         }
4113         if ((p_uint)sp->u.number >= (p_uint)m->num_values
4114             /* using uints automagically checks for negative indices */
4115            )
4116         {
4117             ERRORF(("Too big subindex for []: value %"PRIdPINT", width %"
4118                     PRIdPINT".\n", sp->u.number, m->num_values));
4119             return NULL;
4120         }
4121 
4122         /* Compute the indexed element and setup the protector */
4123 
4124         item = get_map_lvalue(m, i);
4125         if (!item)
4126         {
4127             outofmemory("indexed lvalue");
4128             /* NOTREACHED */
4129             return NULL;
4130         }
4131         item += sp->u.number;
4132 
4133         lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
4134         lvalue->v.type = T_PROTECTED_LVALUE;
4135         lvalue->v.u.lvalue = item;
4136         BUILD_MAP_PROTECTOR(lvalue->protector, m)
4137           /* The one ref is transferred from the stack */
4138 
4139         /* Remove the arguments and return the result */
4140         sp--;
4141         pop_stack();
4142         vec->type = T_LVALUE;
4143         vec->u.lvalue = &lvalue->v;
4144         return sp;
4145     }
4146 
4147     /* Indexing on illegal type */
4148 
4149     inter_sp = sp;
4150     inter_pc = pc;
4151     errorf("(lvalue7)Indexing on illegal type '%s'.\n", typename(vec->type));
4152     return NULL;
4153 } /* push_protected_indexed_map_lvalue() */
4154 
4155 /*-------------------------------------------------------------------------*/
4156 static INLINE svalue_t *
index_lvalue(svalue_t * sp,bytecode_p pc)4157 index_lvalue (svalue_t *sp, bytecode_p pc)
4158 
4159 /* Operator F_INDEX_LVALUE (string|vector &v=sp[0], int   i=sp[-1])
4160  *          F_INDEX_LVALUE (mapping       &v=sp[0], mixed i=sp[-1])
4161  *          F_INDEX_S_LVALUE (struct      &v=sp[0], mixed i=sp[-1])
4162  *
4163  * Compute the index &(v[i]) of lvalue <v> and push it into the stack. The
4164  * computed index is a lvalue itself.
4165  * If <v> is a string-lvalue, it is made a malloced string if necessary,
4166  * and the pushed result will be a lvalue pointing to a CHAR_LVALUE stored
4167  * in <special_lvalue>.
4168  */
4169 
4170 {
4171     svalue_t *vec;   /* the vector/mapping */
4172     svalue_t *i;     /* the index */
4173     short     type;  /* type of <vec> */
4174 
4175     /* get the arguments */
4176     vec = sp;
4177     i = sp -1;
4178 
4179     /* Dereference the initial (and possibly more) lvalue-indirection
4180      */
4181     do {
4182         vec = vec->u.lvalue;
4183         type = vec->type;
4184     } while (type == T_LVALUE || type == T_PROTECTED_LVALUE);
4185 
4186     /* Index a vector.
4187      */
4188     if (type == T_POINTER)
4189     {
4190         vector_t *v = vec->u.vec;
4191         svalue_t *item;
4192 
4193         item = get_vector_item(v, i, sp, pc);
4194 
4195         /* Remove the arguments and push the result */
4196 
4197         sp = i;
4198 
4199         sp->type = T_LVALUE;
4200         sp->u.lvalue = item;
4201         return sp;
4202     }
4203 
4204     /* Index a string.
4205      */
4206     if (type == T_STRING)
4207     {
4208         char * cp;
4209 
4210         cp = get_string_item(vec, i, /* make_singular: */ MY_TRUE
4211                             , /* allow_one_past: */ MY_FALSE
4212                             , sp, pc);
4213 
4214         /* Remove the arguments and create and push the result. */
4215 
4216         sp = i;
4217 
4218         sp->type = T_LVALUE;
4219         sp->u.lvalue = &special_lvalue.v;
4220         special_lvalue.v.type = T_CHAR_LVALUE;
4221         special_lvalue.v.u.charp = cp;
4222         return sp;
4223     }
4224 
4225 #ifdef USE_STRUCTS
4226     /* Index a struct.
4227      */
4228     if (type == T_STRUCT)
4229     {
4230         struct_t * st = vec->u.strct;
4231         svalue_t * item;
4232 
4233         item = get_struct_item(st, i, sp, pc);
4234 
4235         /* Remove the arguments and push the result */
4236 
4237         sp--; /* *sp is a T_LVALUE and can be dropped silently  */
4238         free_svalue(sp); /* This was 'i' */
4239 
4240         sp->type = T_LVALUE;
4241         sp->u.lvalue = item;
4242         return sp;
4243     }
4244 #endif /* USE_STRUCTS */
4245 
4246     /* Index a mapping.
4247      */
4248     if (type == T_MAPPING)
4249     {
4250         svalue_t *item;
4251         mapping_t *m;
4252 
4253         m = vec->u.map;
4254         if (!m->num_values)
4255         {
4256             ERROR("Indexing a mapping of width 0.\n");
4257             return NULL;
4258         }
4259 
4260         /* Compute the element */
4261         item = get_map_lvalue(m, i);
4262         if (!item)
4263         {
4264             outofmemory("indexed lvalue");
4265             /* NOTREACHED */
4266             return NULL;
4267         }
4268 
4269         /* Remove the arguments and push the result. */
4270 
4271         sp = i;
4272         free_svalue(i);
4273         sp->type = T_LVALUE;
4274         sp->u.lvalue = item;
4275         return sp;
4276     }
4277 
4278     /* Illegal type to index. */
4279 
4280     inter_sp = sp;
4281     inter_pc = pc;
4282     errorf("(lvalue8)Indexing on illegal type '%s'.\n", typename(type));
4283     return NULL;
4284 } /* index_lvalue() */
4285 
4286 /*-------------------------------------------------------------------------*/
4287 static INLINE svalue_t *
rindex_lvalue(svalue_t * sp,bytecode_p pc)4288 rindex_lvalue (svalue_t *sp, bytecode_p pc)
4289 
4290 /* Operator F_RINDEX_LVALUE (string|vector &v=sp[0], int   i=sp[-1])
4291  *
4292  * Compute the index &(v[<i]) of lvalue <v> and push it into the stack. The
4293  * computed index is a lvalue itself.
4294  * If <v> is a string-lvalue, it is made a malloced string if necessary,
4295  * and the pushed result will be a lvalue pointing to a CHAR_LVALUE stored
4296  * in <special_lvalue>.
4297  */
4298 
4299 {
4300     svalue_t *vec;   /* the vector/string */
4301     svalue_t *i;     /* the index */
4302     short     type;  /* type of <vec> */
4303 
4304     /* get the arguments */
4305     vec = sp;
4306     i = sp -1;
4307 
4308     /* Dereference the initial (and possibly more) lvalue-indirection
4309      */
4310     do {
4311         vec = vec->u.lvalue;
4312         type = vec->type;
4313     } while (type == T_LVALUE || type == T_PROTECTED_LVALUE);
4314 
4315     /* Index a vector
4316      */
4317     if (type == T_POINTER)
4318     {
4319         vector_t *v = vec->u.vec;
4320         svalue_t *item;
4321 
4322         item = get_vector_r_item(v, i, sp, pc);
4323 
4324         /* Remove the arguments and return the result */
4325 
4326         sp = i;
4327         sp->type = T_LVALUE;
4328         sp->u.lvalue = item;
4329         return sp;
4330     }
4331 
4332     /* Index a string
4333      */
4334     if (type == T_STRING)
4335     {
4336         char * cp;
4337 
4338         cp = get_string_r_item(vec, i, /* make_singular: */ MY_TRUE
4339                               , /* allow_one_past: */ MY_FALSE
4340                               , sp, pc);
4341 
4342         /* Remove the argument and return the result */
4343 
4344         sp = i;
4345         sp->type = T_LVALUE;
4346         sp->u.lvalue = &special_lvalue.v;
4347         special_lvalue.v.type = T_CHAR_LVALUE;
4348         special_lvalue.v.u.charp = cp;
4349         return sp;
4350     }
4351 
4352     /* Indexing on illegal type */
4353 
4354     inter_sp = sp;
4355     inter_pc = pc;
4356     errorf("(lvalue9)Indexing on illegal type '%s'.\n", typename(type));
4357     return NULL;
4358 } /* rindex_lvalue() */
4359 
4360 /*-------------------------------------------------------------------------*/
4361 static INLINE svalue_t *
aindex_lvalue(svalue_t * sp,bytecode_p pc)4362 aindex_lvalue (svalue_t *sp, bytecode_p pc)
4363 
4364 /* Operator F_AINDEX_LVALUE (string|vector &v=sp[0], int   i=sp[-1])
4365  *
4366  * Compute the index &(v[>i]) of lvalue <v> and push it into the stack. The
4367  * computed index is a lvalue itself.
4368  * If <v> is a string-lvalue, it is made a malloced string if necessary,
4369  * and the pushed result will be a lvalue pointing to a CHAR_LVALUE stored
4370  * in <special_lvalue>.
4371  */
4372 
4373 {
4374     svalue_t *vec;   /* the vector/string */
4375     svalue_t *i;     /* the index */
4376     short     type;  /* type of <vec> */
4377 
4378     /* get the arguments */
4379     vec = sp;
4380     i = sp -1;
4381 
4382     /* Dereference the initial (and possibly more) lvalue-indirection
4383      */
4384     do {
4385         vec = vec->u.lvalue;
4386         type = vec->type;
4387     } while (type == T_LVALUE || type == T_PROTECTED_LVALUE);
4388 
4389     /* Index a vector
4390      */
4391     if (type == T_POINTER)
4392     {
4393         vector_t *v = vec->u.vec;
4394         svalue_t *item;
4395 
4396         item = get_vector_a_item(v, i, sp, pc);
4397 
4398         /* Remove the arguments and return the result */
4399 
4400         sp = i;
4401         sp->type = T_LVALUE;
4402         sp->u.lvalue = item;
4403         return sp;
4404     }
4405 
4406     /* Index a string
4407      */
4408     if (type == T_STRING)
4409     {
4410         char * cp;
4411 
4412         cp = get_string_a_item(vec, i, /* make_singular: */ MY_TRUE
4413                               , /* allow_one_past: */ MY_FALSE
4414                               , sp, pc);
4415 
4416         /* Remove the argument and return the result */
4417 
4418         sp = i;
4419         sp->type = T_LVALUE;
4420         sp->u.lvalue = &special_lvalue.v;
4421         special_lvalue.v.type = T_CHAR_LVALUE;
4422         special_lvalue.v.u.charp = cp;
4423         return sp;
4424     }
4425 
4426     /* Indexing on illegal type */
4427 
4428     inter_sp = sp;
4429     inter_pc = pc;
4430     errorf("(lvalue10)Indexing on illegal type '%s'.\n", typename(type));
4431     return NULL;
4432 } /* aindex_lvalue() */
4433 
4434 /*-------------------------------------------------------------------------*/
4435 static svalue_t *
protected_index_lvalue(svalue_t * sp,bytecode_p pc)4436 protected_index_lvalue (svalue_t *sp, bytecode_p pc)
4437 
4438 /* Operator F_PROTECTED_INDEX_LVALUE (string|vector &v=sp[0], int   i=sp[-1])
4439  *          F_PROTECTED_INDEX_LVALUE (mapping       &v=sp[0], mixed i=sp[-1])
4440  *          F_PROTECTED_INDEX_S_LVALUE (struct      &v=sp[0], mixed i=sp[-1])
4441  *
4442  * Compute the index &(*v[i]) of lvalue <v>, wrap it into a protector, and push
4443  * the reference to the protector as PROTECTED_LVALUE onto the stack.
4444  *
4445  * If <v> is a protected non-string-lvalue, the protected_lvalue referenced
4446  * by <v>.u.lvalue will be deallocated, and the protector itself will be
4447  * stored in <last_indexing_protector> for the time being.
4448  *
4449  * If <v> is a string-lvalue, it is made a malloced string if necessary.
4450  */
4451 
4452 {
4453     svalue_t *vec;   /* the indexed value */
4454     svalue_t *i;     /* the index */
4455     short     type;  /* type of <vec> */
4456 
4457     /* Get arguments */
4458     vec = sp->u.lvalue;
4459     i = sp -1;
4460 
4461     /* The loop unravels the (possible) lvalue chain starting at vec.
4462      * When a non-lvalue is encountered, the indexing takes place
4463      * the function returns.
4464      */
4465     for (;;)
4466     {
4467         type = vec->type;
4468 
4469         /* Index a vector.
4470          */
4471         if (type == T_POINTER)
4472         {
4473             vector_t *v = vec->u.vec;
4474             struct protected_lvalue *lvalue;
4475             svalue_t *item;
4476 
4477             item = get_vector_item(v, i, sp, pc);
4478 
4479             /* Drop the arguments */
4480             sp = i;
4481 
4482             /* Compute and return the result */
4483 
4484             lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
4485             lvalue->v.type = T_PROTECTED_LVALUE;
4486             lvalue->v.u.lvalue = item;
4487             put_ref_array(&(lvalue->protector), v);
4488 
4489             sp->type = T_LVALUE;
4490             sp->u.lvalue = &lvalue->v;
4491 
4492             return sp;
4493         }
4494 
4495 #ifdef USE_STRUCTS
4496         /* Index a struct.
4497          */
4498         if (type == T_STRUCT)
4499         {
4500             struct_t * st = vec->u.strct;
4501             svalue_t * item;
4502             struct protected_lvalue *lvalue;
4503 
4504             item = get_struct_item(st, i, sp, pc);
4505 
4506             /* Drop the arguments */
4507             free_svalue(i);
4508             sp = i;
4509 
4510             /* Compute and return the result */
4511 
4512             lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
4513             lvalue->v.type = T_PROTECTED_LVALUE;
4514             lvalue->v.u.lvalue = item;
4515             put_ref_struct(&(lvalue->protector), st);
4516 
4517             sp->type = T_LVALUE;
4518             sp->u.lvalue = &lvalue->v;
4519 
4520             return sp;
4521         }
4522 #endif /* USE_STRUCTS */
4523 
4524         /* Index a string.
4525          */
4526         if (type == T_STRING)
4527         {
4528             struct protected_char_lvalue *val;
4529             char * cp;
4530 
4531             cp = get_string_item(vec, i, /* make_singular: */ MY_TRUE
4532                                 , /* allow_one_past: */ MY_FALSE
4533                                 , sp, pc);
4534 
4535             /* Add another reference to the string to keep it alive while
4536              * we use it.
4537              */
4538             (void)ref_mstring(vec->u.str);
4539 
4540             /* Drop the arguments */
4541             sp = i;
4542 
4543             /* Compute and return the result */
4544 
4545             val = (struct protected_char_lvalue *)xalloc(sizeof *val);
4546             val->v.type = T_PROTECTED_CHAR_LVALUE;
4547             val->v.u.charp = cp;
4548             val->lvalue = vec;
4549             val->start = get_txt(vec->u.str);
4550             val->protector.type = T_INVALID;
4551 
4552             sp->type = T_LVALUE;
4553             sp->u.protected_char_lvalue = val;
4554 
4555             return sp;
4556         }
4557 
4558         /* Index a mapping.
4559          */
4560         if (type == T_MAPPING)
4561         {
4562             svalue_t *item;
4563             struct protected_lvalue *lvalue;
4564             mapping_t *m;
4565 
4566             m = vec->u.map;
4567             if (!m->num_values)
4568             {
4569                 ERROR("Indexing a mapping of width 0.\n");
4570                 return NULL;
4571             }
4572 
4573             /* Compute the indexed element */
4574             item = get_map_lvalue(m, i);
4575             if (!item)
4576             {
4577                 outofmemory("indexed lvalue");
4578                 /* NOTREACHED */
4579                 return NULL;
4580             }
4581 
4582             /* Build the protector */
4583             ref_mapping(m);
4584             lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
4585             lvalue->v.type = T_PROTECTED_LVALUE;
4586             lvalue->v.u.lvalue = item;
4587             BUILD_MAP_PROTECTOR(lvalue->protector, m)
4588 
4589             /* Drop the arguments and return the result */
4590             sp = i;
4591             free_svalue(i);
4592 
4593             sp->type = T_LVALUE;
4594             sp->u.lvalue = &lvalue->v;
4595 
4596             return sp;
4597         }
4598 
4599         /* lvalues are just dereferenced.
4600          */
4601         if (type == T_LVALUE)
4602         {
4603             vec = vec->u.lvalue;
4604             continue;
4605         }
4606 
4607         /* Non-string protected lvalues are dereferenced, a protected
4608          * string lvalue is indexed immediately.
4609          */
4610         if (type == T_PROTECTED_LVALUE)
4611         {
4612             struct protected_lvalue *lvalue;
4613             struct protected_char_lvalue *val;
4614             char * cp;
4615 
4616             lvalue = (struct protected_lvalue *)vec;
4617 
4618             if (lvalue->v.u.lvalue->type != T_STRING)
4619             {
4620                 /* Deref a non-string protected lvalue.
4621                  * If this is the lvalue passed to the operator, also free
4622                  * the protector structure (since its stack space will be
4623                  * used for the result), but keep the protector itself
4624                  * in a global variable.
4625                  */
4626                 if (vec == sp->u.lvalue)
4627                 {
4628                     free_protector_svalue(&last_indexing_protector);
4629                     last_indexing_protector = lvalue->protector;
4630                     vec = lvalue->v.u.lvalue;
4631                     xfree(lvalue);
4632                     continue;
4633                 }
4634 
4635                 vec = lvalue->v.u.lvalue;
4636                 continue;
4637             }
4638 
4639             vec = lvalue->v.u.lvalue; /* it's a string... */
4640 
4641             cp = get_string_item(vec, i, /* make_singular: */ MY_TRUE
4642                                 , /* allow_one_past: */ MY_FALSE
4643                                 , sp, pc);
4644 
4645             /* Add another reference to the string to keep it alive while
4646              * we use it.
4647              */
4648             (void)ref_mstring(vec->u.str);
4649 
4650             /* Build the protector */
4651             val = (struct protected_char_lvalue *)xalloc(sizeof *val);
4652             val->v.type = T_PROTECTED_CHAR_LVALUE;
4653             val->v.u.charp = cp;
4654             val->lvalue = vec;
4655             val->start = get_txt(vec->u.str);
4656 
4657             /* Drop the arguments and return the result.
4658              * If this was the lvalue passed to the operator in the
4659              * first place, adopt the protecting value and free the old
4660              * operator structure. If not, just don't assign a protecting
4661              * value.
4662              */
4663             if (lvalue == sp->u.protected_lvalue)
4664             {
4665                 val->protector = lvalue->protector;
4666                 xfree(lvalue);
4667             }
4668             else
4669             {
4670                 val->protector.type = T_INVALID;
4671             }
4672 
4673             sp = i;
4674             sp->type = T_LVALUE;
4675             sp->u.protected_char_lvalue = val;
4676 
4677             return sp;
4678         }
4679 
4680         /* Indexing on illegal type */
4681         inter_sp = sp;
4682         inter_pc = pc;
4683         errorf("(lvalue11)Indexing on illegal type '%s'.\n", typename(type));
4684         return NULL;
4685     } /* for(ever) */
4686 
4687     /* NOTREACHED */
4688     return NULL;
4689 } /* protected_index_lvalue() */
4690 
4691 /*-------------------------------------------------------------------------*/
4692 static INLINE svalue_t *
protected_rindex_lvalue(svalue_t * sp,bytecode_p pc)4693 protected_rindex_lvalue (svalue_t *sp, bytecode_p pc)
4694 
4695 /* Operator F_PROTECTED_RINDEX_LVALUE (string|vector &v=sp[0], int   i=sp[-1])
4696  *
4697  * Compute the index &(*v[<i]) of lvalue <v>, wrap it into a protector, and
4698  * push the reference to the protector as PROTECTED_LVALUE onto the stack.
4699  *
4700  * If <v> is a protected non-string-lvalue, the protected_lvalue referenced
4701  * by <v>.u.lvalue will be deallocated, and the protector itself will be
4702  * stored in <last_indexing_protector> for the time being.
4703  *
4704  * If <v> is a string-lvalue, it is made a malloced string if necessary.
4705  */
4706 
4707 {
4708     svalue_t *vec;   /* the indexed value */
4709     svalue_t *i;     /* the index */
4710     short     type;  /* type of <vec> */
4711 
4712     /* Get arguments */
4713     vec = sp->u.lvalue;
4714     i = sp -1;
4715 
4716     /* The loop unravels the (possible) lvalue chain starting at vec.
4717      * When a non-lvalue is encountered, the indexing takes place
4718      * the function returns.
4719      */
4720     for (;;)
4721     {
4722         type = vec->type;
4723 
4724         /* Index a vector.
4725          */
4726         if (type == T_POINTER)
4727         {
4728             vector_t *v = vec->u.vec;
4729             struct protected_lvalue *lvalue;
4730             svalue_t *item;
4731 
4732             item = get_vector_r_item(v, i, sp, pc);
4733 
4734             /* Create the protector for the result */
4735 
4736             lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
4737             lvalue->v.type = T_PROTECTED_LVALUE;
4738             lvalue->v.u.lvalue = item;
4739             put_ref_array(&(lvalue->protector), v);
4740 
4741             /* Drop the arguments and return the result */
4742 
4743             sp = i;
4744 
4745             sp->type = T_LVALUE;
4746             sp->u.lvalue = &lvalue->v;
4747             return sp;
4748         }
4749 
4750         /* Index a string.
4751          */
4752         if (type == T_STRING)
4753         {
4754             struct protected_char_lvalue *val;
4755             char * cp;
4756 
4757             cp = get_string_r_item(vec, i, /* make_singular: */ MY_TRUE
4758                                   , /* allow_one_past: */ MY_FALSE
4759                                   , sp, pc);
4760 
4761             /* Add another reference to the string to keep it alive while
4762              * we use it.
4763              */
4764             (void)ref_mstring(vec->u.str);
4765 
4766             /* Build the protector */
4767             val = (struct protected_char_lvalue *)xalloc(sizeof *val);
4768             val->v.type = T_PROTECTED_CHAR_LVALUE;
4769             val->v.u.charp = cp;
4770             val->lvalue = vec;
4771             val->start = get_txt(vec->u.str);
4772             val->protector.type = T_INVALID;
4773 
4774             /* Drop the arguments and return the result */
4775             sp = i;
4776 
4777             sp->type = T_LVALUE;
4778             sp->u.protected_char_lvalue = val;
4779 
4780             return sp;
4781         }
4782 
4783         /* lvalues are just dereferenced.
4784          */
4785         if (type == T_LVALUE)
4786         {
4787             vec = vec->u.lvalue;
4788             continue;
4789         }
4790 
4791         /* Non-string protected lvalues are dereferenced, a protected
4792          * string lvalue is indexed immediately.
4793          */
4794         if (type == T_PROTECTED_LVALUE)
4795         {
4796             struct protected_lvalue *lvalue;
4797             struct protected_char_lvalue *val;
4798             char * cp;
4799 
4800             lvalue = (struct protected_lvalue *)vec;
4801 
4802             if (lvalue->v.u.lvalue->type != T_STRING)
4803             {
4804                 /* Deref a non-string protected lvalue.
4805                  * If this is the lvalue passed to the operator, also free
4806                  * the protector structure (since its stack space will be
4807                  * used for the result), but keep the protector itself
4808                  * in a global variable.
4809                  */
4810                 if (vec == sp->u.lvalue)
4811                 {
4812                     free_protector_svalue(&last_indexing_protector);
4813                     last_indexing_protector = lvalue->protector;
4814                     vec = lvalue->v.u.lvalue;
4815                     xfree(lvalue);
4816                     continue;
4817                 }
4818                 vec = lvalue->v.u.lvalue;
4819                 continue;
4820             }
4821 
4822             vec = lvalue->v.u.lvalue; /* it's a string... */
4823             cp = get_string_r_item(vec, i, /* make_singular: */ MY_TRUE
4824                                   , /* allow_one_past: */ MY_FALSE
4825                                   , sp, pc);
4826 
4827             /* Add another reference to the string to keep it alive while
4828              * we use it.
4829              */
4830             (void)ref_mstring(vec->u.str);
4831 
4832             /* Build the protector */
4833             val = (struct protected_char_lvalue *)xalloc(sizeof *val);
4834             val->v.type = T_PROTECTED_CHAR_LVALUE;
4835             val->v.u.charp = cp;
4836             val->lvalue = vec;
4837             val->start = get_txt(vec->u.str);
4838 
4839             /* Drop the arguments and return the result.
4840              * If this was the lvalue passed to the operator in the
4841              * first place, adopt the protecting value and free the old
4842              * operator structure. If not, just don't assign a protecting
4843              * value.
4844              */
4845             if (lvalue == sp->u.protected_lvalue)
4846             {
4847                 val->protector = lvalue->protector;
4848                 xfree(lvalue);
4849             }
4850             else
4851             {
4852                 val->protector.type = T_INVALID;
4853             }
4854 
4855             sp = i;
4856             sp->type = T_LVALUE;
4857             sp->u.protected_char_lvalue = val;
4858 
4859             return sp;
4860         }
4861 
4862         /* Indexing on illegal type */
4863         inter_sp = sp;
4864         inter_pc = pc;
4865         errorf("(lvalue12)Indexing on illegal type '%s'.\n", typename(type));
4866         return NULL;
4867     } /* for(ever) */
4868 
4869     /* NOTREACHED */
4870     return NULL;
4871 } /* protected_rindex_lvalue() */
4872 
4873 /*-------------------------------------------------------------------------*/
4874 static INLINE svalue_t *
protected_aindex_lvalue(svalue_t * sp,bytecode_p pc)4875 protected_aindex_lvalue (svalue_t *sp, bytecode_p pc)
4876 
4877 /* Operator F_PROTECTED_AINDEX_LVALUE (string|vector &v=sp[0], int   i=sp[-1])
4878  *
4879  * Compute the index &(*v[>i]) of lvalue <v>, wrap it into a protector, and
4880  * push the reference to the protector as PROTECTED_LVALUE onto the stack.
4881  *
4882  * If <v> is a protected non-string-lvalue, the protected_lvalue referenced
4883  * by <v>.u.lvalue will be deallocated, and the protector itself will be
4884  * stored in <last_indexing_protector> for the time being.
4885  *
4886  * If <v> is a string-lvalue, it is made a malloced string if necessary.
4887  */
4888 
4889 {
4890     svalue_t *vec;   /* the indexed value */
4891     svalue_t *i;     /* the index */
4892     short     type;  /* type of <vec> */
4893 
4894     /* Get arguments */
4895     vec = sp->u.lvalue;
4896     i = sp -1;
4897 
4898     /* The loop unravels the (possible) lvalue chain starting at vec.
4899      * When a non-lvalue is encountered, the indexing takes place
4900      * the function returns.
4901      */
4902     for (;;)
4903     {
4904         type = vec->type;
4905 
4906         /* Index a vector.
4907          */
4908         if (type == T_POINTER)
4909         {
4910             vector_t *v = vec->u.vec;
4911             struct protected_lvalue *lvalue;
4912             svalue_t *item;
4913 
4914             item = get_vector_a_item(v, i, sp, pc);
4915 
4916             /* Create the protector for the result */
4917 
4918             lvalue = (struct protected_lvalue *)xalloc(sizeof *lvalue);
4919             lvalue->v.type = T_PROTECTED_LVALUE;
4920             lvalue->v.u.lvalue = item;
4921             put_ref_array(&(lvalue->protector), v);
4922 
4923             /* Drop the arguments and return the result */
4924 
4925             sp = i;
4926 
4927             sp->type = T_LVALUE;
4928             sp->u.lvalue = &lvalue->v;
4929             return sp;
4930         }
4931 
4932         /* Index a string.
4933          */
4934         if (type == T_STRING)
4935         {
4936             struct protected_char_lvalue *val;
4937             char * cp;
4938 
4939             cp = get_string_a_item(vec, i, /* make_singular: */ MY_TRUE
4940                                   , /* allow_one_past: */ MY_FALSE
4941                                   , sp, pc);
4942 
4943             /* Add another reference to the string to keep it alive while
4944              * we use it.
4945              */
4946             (void)ref_mstring(vec->u.str);
4947 
4948             /* Build the protector */
4949             val = (struct protected_char_lvalue *)xalloc(sizeof *val);
4950             val->v.type = T_PROTECTED_CHAR_LVALUE;
4951             val->v.u.charp = cp;
4952             val->lvalue = vec;
4953             val->start = get_txt(vec->u.str);
4954             val->protector.type = T_INVALID;
4955 
4956             /* Drop the arguments and return the result */
4957             sp = i;
4958 
4959             sp->type = T_LVALUE;
4960             sp->u.protected_char_lvalue = val;
4961 
4962             return sp;
4963         }
4964 
4965         /* lvalues are just dereferenced.
4966          */
4967         if (type == T_LVALUE)
4968         {
4969             vec = vec->u.lvalue;
4970             continue;
4971         }
4972 
4973         /* Non-string protected lvalues are dereferenced, a protected
4974          * string lvalue is indexed immediately.
4975          */
4976         if (type == T_PROTECTED_LVALUE)
4977         {
4978             struct protected_lvalue *lvalue;
4979             struct protected_char_lvalue *val;
4980             char * cp;
4981 
4982             lvalue = (struct protected_lvalue *)vec;
4983 
4984             if (lvalue->v.u.lvalue->type != T_STRING)
4985             {
4986                 /* Deref a non-string protected lvalue.
4987                  * If this is the lvalue passed to the operator, also free
4988                  * the protector structure (since its stack space will be
4989                  * used for the result), but keep the protector itself
4990                  * in a global variable.
4991                  */
4992                 if (vec == sp->u.lvalue)
4993                 {
4994                     free_protector_svalue(&last_indexing_protector);
4995                     last_indexing_protector = lvalue->protector;
4996                     vec = lvalue->v.u.lvalue;
4997                     xfree(lvalue);
4998                     continue;
4999                 }
5000                 vec = lvalue->v.u.lvalue;
5001                 continue;
5002             }
5003 
5004             vec = lvalue->v.u.lvalue; /* it's a string... */
5005             cp = get_string_a_item(vec, i, /* make_singular: */ MY_TRUE
5006                                   , /* allow_one_past: */ MY_FALSE
5007                                   , sp, pc);
5008 
5009             /* Add another reference to the string to keep it alive while
5010              * we use it.
5011              */
5012             (void)ref_mstring(vec->u.str);
5013 
5014             /* Build the protector */
5015             val = (struct protected_char_lvalue *)xalloc(sizeof *val);
5016             val->v.type = T_PROTECTED_CHAR_LVALUE;
5017             val->v.u.charp = cp;
5018             val->lvalue = vec;
5019             val->start = get_txt(vec->u.str);
5020 
5021             /* Drop the arguments and return the result.
5022              * If this was the lvalue passed to the operator in the
5023              * first place, adopt the protecting value and free the old
5024              * operator structure. If not, just don't assign a protecting
5025              * value.
5026              */
5027             if (lvalue == sp->u.protected_lvalue)
5028             {
5029                 val->protector = lvalue->protector;
5030                 xfree(lvalue);
5031             }
5032             else
5033             {
5034                 val->protector.type = T_INVALID;
5035             }
5036 
5037             sp = i;
5038             sp->type = T_LVALUE;
5039             sp->u.protected_char_lvalue = val;
5040 
5041             return sp;
5042         }
5043 
5044         /* Indexing on illegal type */
5045         inter_sp = sp;
5046         inter_pc = pc;
5047         errorf("(lvalue13)Indexing on illegal type '%s'.\n", typename(type));
5048         return NULL;
5049     } /* for(ever) */
5050 
5051     /* NOTREACHED */
5052     return NULL;
5053 } /* protected_aindex_lvalue() */
5054 
5055 /*-------------------------------------------------------------------------*/
5056 
5057 /* Code values used by range_lvalue() and protected_range_lvalue()
5058  */
5059 
5060 #define NN_RANGE (0)
5061 #define RN_RANGE (1 << 0)
5062 #define AN_RANGE (2 << 0)
5063 #define NR_RANGE (1 << 2)
5064 #define NA_RANGE (2 << 2)
5065 
5066 #define RR_RANGE (RN_RANGE|NR_RANGE)
5067 #define RA_RANGE (RN_RANGE|NA_RANGE)
5068 #define AR_RANGE (AN_RANGE|NR_RANGE)
5069 #define AA_RANGE (AN_RANGE|NA_RANGE)
5070 
5071 #define NX_MASK (3)
5072 #define XN_MASK (3 << 2)
5073 
5074 static svalue_t *
range_lvalue(int code,svalue_t * sp)5075 range_lvalue (int code, svalue_t *sp)
5076 
5077 /* Operator F_RANGE_LVALUE (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
5078  * and the operators F_*_RANGE_LVALUE.
5079  *
5080  * Compute the range &(v[i1..i2]) of lvalue <v> and push it into the stack.
5081  * The value pushed is a lvalue pointing to <special_lvalue>. <special_lvalue>
5082  * then is the POINTER_RANGE_- resp. STRING_RANGE_LVALUE.
5083  *
5084  * <code> is a four-bit flag determining whether the indexes are counted
5085  * from the beginning ('[i1..' and '..i2]'), the end of the vector
5086  * or string ('[<i1..' and '..<i2]'), or depending on the sign of the
5087  * index either from the beginning or end ('[>i1..' and '..>i2]').
5088  * <code>&NX_MASK determines the mode for the lower index (NN_RANGE,
5089  * RN_RANGE or AN_RANGE), <code>&XN_MASK the upper index (NN_RANGE,
5090  * NR_RANGE or NA_RANGE).
5091  */
5092 
5093 {
5094     svalue_t *vec;         /* the indexed vector or string */
5095     svalue_t *i;           /* the index */
5096     int            ind1, ind2;  /* Lower and upper range index */
5097     short          type;        /* type of <vec> */
5098     mp_int         size;        /* size of <vec> in elements */
5099 
5100     /* Get the arguments */
5101     vec = sp;
5102     i = sp-1;
5103 
5104 #ifdef DEBUG
5105     if (sp->type != T_LVALUE) {
5106         inter_sp = sp;
5107         errorf("wrong type to range_lvalue: got %s, expected lvalue\n"
5108              , typename(sp->type));
5109         return NULL;
5110     }
5111 #endif
5112 
5113     /* Deref the initial, and possibly more, lvalues.
5114      */
5115     do {
5116         vec = vec->u.lvalue;
5117         type = vec->type;
5118     } while (type == T_LVALUE || type == T_PROTECTED_LVALUE);
5119 
5120     /* Determine the type of the result, and the input's size.
5121      */
5122     switch(type)
5123     {
5124     case T_POINTER:
5125         special_lvalue.v.type = T_POINTER_RANGE_LVALUE;
5126         size = (mp_int)VEC_SIZE(vec->u.vec);
5127         break;
5128     case T_STRING:
5129         special_lvalue.v.type = T_STRING_RANGE_LVALUE;
5130         size = (mp_int)mstrsize(vec->u.str);
5131         break;
5132     default:
5133         inter_sp = sp;
5134         errorf("(lvalue)Range index on illegal type '%s'.\n", typename(type));
5135         return NULL;
5136     }
5137 
5138     /* Get and check the upper bound i2 */
5139 
5140     if (i->type != T_NUMBER)
5141     {
5142         inter_sp = sp;
5143         errorf("Illegal upper range index: got '%s', expected 'number'.\n"
5144              , typename(i->type));
5145         return NULL;
5146     }
5147 
5148     if ((code & XN_MASK) == NR_RANGE)
5149     {
5150         ind2 = size - i->u.number;
5151     }
5152     else if ((code & XN_MASK) == NA_RANGE)
5153     {
5154         if (i->u.number < 0)
5155             ind2 = size + i->u.number;
5156         else
5157             ind2 = i->u.number;
5158     }
5159     else
5160     {
5161         ind2 = i->u.number;
5162     }
5163 
5164 
5165     if (++ind2 < 0 || ind2 > size+1)
5166     {
5167         inter_sp = sp;
5168         errorf("Upper range index out of bounds: %"PRIdPINT
5169                ", size: %"PRIdMPINT".\n"
5170              , i->u.number, size);
5171         return NULL;
5172     }
5173 
5174     /* Get and check the lower bound i1 */
5175 
5176     if ((--i)->type != T_NUMBER)
5177     {
5178         inter_sp = sp;
5179         errorf("Illegal lower range index: got %s, expected number.\n"
5180              , typename(i->type));
5181         return NULL;
5182     }
5183 
5184     if ((code & NX_MASK) == RN_RANGE)
5185     {
5186         ind1 = size - i->u.number;
5187     }
5188     else if ((code & NX_MASK) == AN_RANGE)
5189     {
5190         if (i->u.number < 0)
5191             ind1 = size + i->u.number;
5192         else
5193             ind1 = i->u.number;
5194     }
5195     else
5196     {
5197         ind1 = i->u.number;
5198     }
5199 
5200     if (ind1 < 0 || ind1 > size)
5201     {   /* Appending (ind1 == size) is allowed */
5202         inter_sp = sp;
5203         errorf("Lower range index out of bounds: %"PRIdPINT
5204                ", size: %"PRIdMPINT".\n"
5205              , i->u.number, size);
5206         return NULL;
5207     }
5208 
5209 
5210     /* Check the range for consistency */
5211 
5212     if (ind2 < ind1)
5213     {
5214         inter_sp = sp;
5215         errorf("Range of negative size given: %"PRIdPINT
5216                "..%"PRIdPINT" .\n"
5217              , i->u.number, (i+1)->u.number);
5218         return NULL;
5219     }
5220 
5221     if (ind1 == size) /* again allow appending */
5222         ind2 = ind1;
5223     else if (ind2 > size)
5224     {
5225         inter_sp = sp;
5226         errorf("Upper range index out of bounds: %"PRIdPINT
5227                ", size: %"PRIdMPINT".\n"
5228              , (i+1)->u.number, size);
5229         return NULL;
5230     }
5231 
5232     /* Finish the special_lvalue structure
5233      */
5234     special_lvalue.v.u.lvalue = vec;
5235     special_lvalue.size = size;
5236     special_lvalue.index1 = ind1;
5237     special_lvalue.index2 = ind2;
5238 
5239     /* Drop the arguments and return the result. */
5240 
5241     sp = i;
5242 
5243     sp->type = T_LVALUE;
5244     sp->u.lvalue = &special_lvalue.v;
5245 
5246     return sp;
5247 } /* range_lvalue() */
5248 
5249 /*-------------------------------------------------------------------------*/
5250 static svalue_t *
protected_range_lvalue(int code,svalue_t * sp)5251 protected_range_lvalue (int code, svalue_t *sp)
5252 
5253 /* Operator F_PROTECTED_RANGE_LVALUE
5254  *                       (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
5255  * and the x-operators F_PROTECTED_*_RANGE_LVALUE and
5256  * F_PROTECTED_LVALUE.
5257  *
5258  * Compute the range &(v[i1..i2]) of lvalue <v>, wrap it into a protector,
5259  * and push the reference to the protector onto the stack.
5260  *
5261  * If <v> is a protected lvalue itself, its protecting svalue will be used
5262  * in the result protector.
5263  *
5264  * If <v> is a string-lvalue, it is made a malloced string if necessary.
5265  *
5266  * <code> is a four-bit flag determining whether the indexes are counted
5267  * from the beginning ('[i1..' and '..i2]'), the end of the vector
5268  * or string ('[<i1..' and '..<i2]'), or depending on the sign of the
5269  * index either from the beginning or end ('[>i1..' and '..>i2]').
5270  * <code>&NX_MASK determines the mode for the lower index (NN_RANGE,
5271  * RN_RANGE or AN_RANGE), <code>&XN_MASK the upper index (NN_RANGE,
5272  * NR_RANGE or NA_RANGE).
5273  */
5274 
5275 {
5276     svalue_t *vec;         /* the indexed vector or string */
5277     svalue_t *i;           /* the index */
5278     int            ind1, ind2;  /* Lower and upper range index */
5279     short          type;        /* type of <vec> */
5280     mp_int         size;        /* size of <vec> in elements */
5281     short          lvalue_type; /* Result type */
5282     svalue_t  protector;   /* Protecting svalue saved from v */
5283     struct protected_range_lvalue *new_lvalue;
5284                                 /* Result protector structure */
5285 
5286 #ifdef DEBUG
5287     if (sp->type != T_LVALUE)
5288     {
5289         inter_sp = sp;
5290         errorf("wrong type to protected_range_lvalue: got %s, expected lvalue\n"
5291              , typename(sp->type));
5292         return NULL;
5293     }
5294 #endif
5295     /* Get the arguments, and also remember the protector in case v
5296      * is a protected lvalue.
5297      */
5298     vec = sp->u.lvalue; /* deref initial lvalue */
5299     i = sp - 1;
5300 
5301     type = vec->type;
5302 
5303     if (type != T_PROTECTED_LVALUE)
5304         protector.type = T_INVALID;
5305     else
5306         protector = ((struct protected_lvalue*)vec)->protector;
5307 
5308     /* Deref any possibly following lvalues
5309      */
5310     while (type == T_LVALUE || type == T_PROTECTED_LVALUE)
5311     {
5312         vec = vec->u.lvalue;
5313         type = vec->type;
5314     }
5315 
5316     /* Determine the type of the result, and the input's size.
5317      * Also massage the input value a bit.
5318      */
5319     switch(type)
5320     {
5321     case T_POINTER:
5322         (void)ref_array(vec->u.vec); /* Count the coming protector */
5323         lvalue_type = T_PROTECTED_POINTER_RANGE_LVALUE;
5324         size = (mp_int)VEC_SIZE(vec->u.vec);
5325         break;
5326 
5327     case T_STRING:
5328         /* If the string is tabled, i.e. not changeable, or has more than
5329          * one reference, allocate a new copy which can be changed safely.
5330          */
5331         if (!mstr_singular(vec->u.str))
5332         {
5333             string_t *p;
5334 
5335             memsafe(p = unshare_mstring(vec->u.str), mstrsize(vec->u.str)
5336                    , "modifiable string");
5337             vec->u.str = p;
5338         }
5339 
5340         /* Add another reference to the string to keep it alive while
5341          * we use it.
5342          */
5343         (void)ref_mstring(vec->u.str);
5344 
5345         lvalue_type = T_PROTECTED_STRING_RANGE_LVALUE;
5346         size = (mp_int)mstrsize(vec->u.str);
5347         break;
5348 
5349     default:
5350         inter_sp = sp;
5351         errorf("(lvalue)Range index on illegal type '%s'.\n", typename(type));
5352         return NULL;
5353     }
5354 
5355     /* Get and check the upper index i2 */
5356 
5357     if (i->type != T_NUMBER)
5358     {
5359         inter_sp = sp;
5360         errorf("Illegal upper range index: got '%s', expected 'number'.\n"
5361              , typename(i->type));
5362         return NULL;
5363     }
5364 
5365     if ((code & XN_MASK) == NR_RANGE)
5366     {
5367         ind2 = size - i->u.number;
5368     }
5369     else if ((code & XN_MASK) == NA_RANGE)
5370     {
5371         if (i->u.number < 0)
5372             ind2 = size + i->u.number;
5373         else
5374             ind2 = i->u.number;
5375     }
5376     else
5377     {
5378         ind2 = i->u.number;
5379     }
5380 
5381     if (++ind2 < 0 || ind2 > size) {
5382         inter_sp = sp;
5383         errorf("Upper range index out of bounds: %"PRIdPINT
5384                ", size: %"PRIdMPINT".\n"
5385              , i->u.number, size);
5386         return NULL;
5387     }
5388 
5389     /* Get and check the lower index i1 */
5390 
5391     if ((--i)->type != T_NUMBER)
5392     {
5393         inter_sp = sp;
5394         errorf("Illegal lower range index: got %s, expected number.\n"
5395              , typename(i->type));
5396         return NULL;
5397     }
5398 
5399     if ((code & NX_MASK) == RN_RANGE)
5400     {
5401         ind1 = size - i->u.number;
5402     }
5403     else if ((code & NX_MASK) == AN_RANGE)
5404     {
5405         if (i->u.number < 0)
5406             ind1 = size + i->u.number;
5407         else
5408             ind1 = i->u.number;
5409     }
5410     else
5411     {
5412         ind1 = i->u.number;
5413     }
5414 
5415     if (ind1 < 0 || ind1 > size)
5416     {
5417         /* Appending (ind1 == size) is allowed */
5418         inter_sp = sp;
5419         errorf("Lower range index out of bounds: %"PRIdPINT
5420                ", size: %"PRIdMPINT".\n"
5421              , i->u.number, size);
5422         return NULL;
5423     }
5424 
5425     /* Build the protector */
5426     new_lvalue = (struct protected_range_lvalue *)xalloc(sizeof *new_lvalue);
5427     new_lvalue->v.type = lvalue_type;
5428     new_lvalue->v.u = vec->u;
5429     new_lvalue->protector = protector;
5430     new_lvalue->lvalue = vec;
5431     new_lvalue->index2 = ind2;
5432     new_lvalue->index1 = ind1;
5433     new_lvalue->size = size;
5434 
5435     /* Drop the arguments and return the result */
5436 
5437     sp = i;
5438 
5439     sp->type = T_LVALUE;
5440     sp->u.protected_range_lvalue = new_lvalue;
5441 
5442     return sp;
5443 } /* protected_range_lvalue() */
5444 
5445 /*-------------------------------------------------------------------------*/
5446 static INLINE svalue_t *
push_indexed_value(svalue_t * sp,bytecode_p pc)5447 push_indexed_value (svalue_t *sp, bytecode_p pc)
5448 
5449 /* Operator F_INDEX (string|vector v=sp[-1], int   i=sp[0])
5450  *          F_INDEX (mapping       v=sp[-1], mixed i=sp[0])
5451  *          F_S_INDEX (struct      v=sp[-1], string|int i=sp[0])
5452  *
5453  * Compute the value (v[i]) and push it onto the stack.
5454  * If the value would be a destructed object, 0 is pushed onto the stack
5455  * and the ref to the object is removed from the vector/mapping.
5456  */
5457 
5458 {
5459     svalue_t *vec;  /* the indexed value */
5460     svalue_t *i;    /* the index */
5461 
5462     /* Get arguments */
5463     i = sp;
5464     vec = sp - 1;
5465 
5466     switch (vec->type)
5467     {
5468     case T_STRING:
5469       {
5470         int c;
5471 
5472         c = (unsigned char)
5473             *get_string_item(vec, i, /* make_singular: */ MY_FALSE
5474                             , /* allow_one_past: */ MY_TRUE
5475                             , sp, pc);
5476 
5477         /* Drop the args and return the result */
5478 
5479         free_string_svalue(vec);
5480 
5481         sp = vec; /* == sp-1 */
5482         put_number(sp, c);
5483 
5484         return sp;
5485       }
5486 
5487     case T_POINTER:
5488       {
5489         svalue_t *item;
5490 
5491         item = get_vector_item(vec->u.vec, i, sp, pc);
5492 
5493         /* Drop the arguments */
5494         sp = vec; /* == sp-1 */
5495 
5496         /* Assign the indexed element to the sp entry holding vec.
5497          * Decrement the vector ref manually to optimize the case that
5498          * this is the last ref to the vector.
5499          */
5500         if (vec->u.vec->ref == 1)
5501         {
5502             svalue_t tmp;
5503 
5504             /* Copy the indexed element into <tmp>
5505              */
5506             tmp = *item;
5507 
5508             /* Invalidate the old space of the result value and free
5509              * the vector.
5510              */
5511             item->type = T_INVALID;
5512             free_array(vec->u.vec);
5513 
5514             /* Return the result */
5515             *sp = tmp;
5516             return sp;
5517         }
5518 
5519         deref_array(vec->u.vec);
5520 
5521         /* The vector continues to live: keep the refcount as it is
5522          * and just assign the indexed element for the result.
5523          */
5524         assign_checked_svalue_no_free(sp, item);
5525         return sp;
5526       }
5527 
5528     case T_MAPPING:
5529       {
5530         svalue_t item;
5531         mapping_t *m;
5532 
5533         m = vec->u.map;
5534 
5535         if (!m->num_values)
5536         {
5537             inter_sp = sp;
5538             inter_pc = pc;
5539             errorf("(value)Indexing a mapping of width 0.\n");
5540             return NULL;
5541         }
5542 
5543         /* Get the item.
5544          * We are getting a copy in case the subsequent free() actions
5545          * free the mapping and all it's data.
5546          */
5547         assign_checked_svalue_no_free(&item, get_map_value(m, i));
5548 
5549         /* Drop the arguments */
5550 
5551         free_svalue(i);
5552         free_mapping(m);
5553 
5554         /* Return the result */
5555         sp = vec; /* == sp-1 */
5556         transfer_svalue_no_free(sp, &item);
5557         return sp;
5558       }
5559 
5560 #ifdef USE_STRUCTS
5561     case T_STRUCT:
5562       {
5563         struct_t * st = vec->u.strct;
5564         svalue_t * item;
5565 
5566         item = get_struct_item(st, i, sp, pc);
5567 
5568         /* Drop the 'i' argument */
5569         free_svalue(sp);
5570         sp--;
5571 
5572         /* Assign the value */
5573         assign_svalue_no_free(sp, item);
5574 
5575         /* Drop the struct reference */
5576         free_struct(st);
5577         return sp;
5578       }
5579 #endif /* USE_STRUCTS */
5580 
5581     default:
5582         inter_sp = sp;
5583         inter_pc = pc;
5584         errorf("(value)Indexing on illegal type '%s'.\n", typename(vec->type));
5585         return NULL;
5586     }
5587 
5588     /* NOTREACHED */
5589     return NULL;
5590 } /* push_indexed_value() */
5591 
5592 /*-------------------------------------------------------------------------*/
5593 static INLINE svalue_t *
push_rindexed_value(svalue_t * sp,bytecode_p pc)5594 push_rindexed_value (svalue_t *sp, bytecode_p pc)
5595 
5596 /* Operator F_RINDEX (string|vector v=sp[0], int   i=sp[-1])
5597  *
5598  * Compute the value (v[<i]) and push it onto the stack.
5599  * If the value would be a destructed object, 0 is pushed onto the stack
5600  * and the ref to the object is removed from the vector/mapping.
5601  */
5602 
5603 {
5604     svalue_t *vec;  /* the indexed value */
5605     svalue_t *i;    /* the index */
5606 
5607     /* Get arguments */
5608     i = sp;
5609     vec = sp - 1;
5610 
5611     switch (vec->type)
5612     {
5613     case T_STRING:
5614       {
5615         int c;
5616 
5617         c = (unsigned char)
5618             *get_string_r_item(vec, i, /* make_singular: */ MY_FALSE
5619                               , /* allow_one_past: */ MY_TRUE
5620                               , sp, pc);
5621 
5622         /* Drop the args and return the result */
5623 
5624         free_string_svalue(vec);
5625 
5626         sp = vec; /* == sp-1 */
5627         put_number(sp, c);
5628         return sp;
5629       }
5630 
5631     case T_POINTER:
5632       {
5633         svalue_t *item;
5634 
5635         item = get_vector_r_item(vec->u.vec, i, sp, pc);
5636 
5637         /* Drop the arguments */
5638         sp = vec;
5639 
5640         /* Assign the indexed element to the sp entry holding vec.
5641          * Decrement the vector ref manually to optimize the case that
5642          * this is the last ref to the vector.
5643          */
5644         if (vec->u.vec->ref == 1)
5645         {
5646             svalue_t tmp;
5647 
5648             /* Copy the indexed element into <tmp>
5649              */
5650             tmp = *item;
5651 
5652             /* Invalidate the old space of the result value and free
5653              * the vector.
5654              */
5655             item->type = T_INVALID;
5656             free_array(vec->u.vec);
5657 
5658             /* Return the result */
5659             *sp = tmp;
5660             return sp;
5661         }
5662 
5663         deref_array(vec->u.vec);
5664 
5665         /* The vector continues to live: keep the refcount as it is
5666          * and just assign the indexed element for the result.
5667          */
5668         assign_checked_svalue_no_free(sp, item);
5669         return sp;
5670       }
5671 
5672     default:
5673         inter_sp = sp;
5674         inter_pc = pc;
5675         errorf("(lvalue)Range index on illegal type '%s'.\n", typename(vec->type));
5676         return NULL;
5677     }
5678 
5679     /* NOTREACHED */
5680     return NULL;
5681 } /* push_rindexed_value() */
5682 
5683 /*-------------------------------------------------------------------------*/
5684 static INLINE svalue_t *
push_aindexed_value(svalue_t * sp,bytecode_p pc)5685 push_aindexed_value (svalue_t *sp, bytecode_p pc)
5686 
5687 /* Operator F_AINDEX (string|vector v=sp[0], int   i=sp[-1])
5688  *
5689  * Compute the value (v[>i]) and push it onto the stack.
5690  * If the value would be a destructed object, 0 is pushed onto the stack
5691  * and the ref to the object is removed from the vector/mapping.
5692  */
5693 
5694 {
5695     svalue_t *vec;  /* the indexed value */
5696     svalue_t *i;    /* the index */
5697 
5698     /* Get arguments */
5699     i = sp;
5700     vec = sp - 1;
5701 
5702     switch (vec->type)
5703     {
5704     case T_STRING:
5705       {
5706         int c;
5707 
5708         c = (unsigned char)
5709             *get_string_a_item(vec, i, /* make_singular: */ MY_FALSE
5710                               , /* allow_one_past: */ MY_TRUE
5711                               , sp, pc);
5712 
5713         /* Drop the args and return the result */
5714 
5715         free_string_svalue(vec);
5716 
5717         sp = vec; /* == sp-1 */
5718         put_number(sp, c);
5719         return sp;
5720       }
5721 
5722     case T_POINTER:
5723       {
5724         svalue_t *item;
5725 
5726         item = get_vector_a_item(vec->u.vec, i, sp, pc);
5727 
5728         /* Drop the arguments */
5729         sp = vec;
5730 
5731         /* Assign the indexed element to the sp entry holding vec.
5732          * Decrement the vector ref manually to optimize the case that
5733          * this is the last ref to the vector.
5734          */
5735         if (vec->u.vec->ref == 1)
5736         {
5737             svalue_t tmp;
5738 
5739             /* Copy the indexed element into <tmp>
5740              */
5741             tmp = *item;
5742 
5743             /* Invalidate the old space of the result value and free
5744              * the vector.
5745              */
5746             item->type = T_INVALID;
5747             free_array(vec->u.vec);
5748 
5749             /* Return the result */
5750             *sp = tmp;
5751             return sp;
5752         }
5753 
5754         deref_array(vec->u.vec);
5755 
5756         /* The vector continues to live: keep the refcount as it is
5757          * and just assign the indexed element for the result.
5758          */
5759         assign_checked_svalue_no_free(sp, item);
5760         return sp;
5761       }
5762 
5763     default:
5764         inter_sp = sp;
5765         inter_pc = pc;
5766         errorf("(lvalue)Range index on illegal type '%s'.\n", typename(vec->type));
5767         return NULL;
5768     }
5769 
5770     /* NOTREACHED */
5771     return NULL;
5772 } /* push_aindexed_value() */
5773 
5774 /*=========================================================================*/
5775 /*-------------------------------------------------------------------------*/
5776 void
m_indices_filter(svalue_t * key,svalue_t * data UNUSED,void * extra)5777 m_indices_filter ( svalue_t *key
5778                  , svalue_t *data UNUSED
5779                  , void *extra /* is a svalue_t ** */ )
5780 
5781 /* Filter function used by mapping:m_indices() to implement the
5782  * m_indices() efun. It is here take advantage of the inline expansion
5783  * of assign_svalue_no_free().
5784  *
5785  * <key> points to a key in a mapping, <extra> points to a svalue_t*
5786  * pointing to a storage place. *key is assigned to **extra, *extra is
5787  * incremented afterwards.
5788  */
5789 
5790 {
5791 #ifdef __MWERKS__
5792 #    pragma unused(data)
5793 #endif
5794     svalue_t **svpp = (svalue_t **)extra;
5795 
5796     assign_svalue_no_free( (*svpp)++, key );
5797 } /* m_indices_filter() */
5798 
5799 /*-------------------------------------------------------------------------*/
m_values_filter(svalue_t * key UNUSED,svalue_t * data,void * extra)5800 void m_values_filter ( svalue_t *key UNUSED
5801                      , svalue_t *data
5802                      , void *extra /* is a struct mvf_info * */ )
5803 
5804 /* Filter function used by efun m_values().
5805  *
5806  * <data> points to a data entry in a mapping, <extra> points to
5807  * a struct mvf_info describing the amount of data to copy, and the
5808  * target place. The <data> is copied to where <extra> points and <*extra>
5809  * is updated.
5810  */
5811 
5812 {
5813 #ifdef __MWERKS__
5814 #    pragma unused(key)
5815 #endif
5816     struct mvf_info * vip = (struct mvf_info *)extra;
5817 
5818     assign_svalue_no_free( vip->svp++, data + vip->num);
5819 } /* m_values_filter() */
5820 
5821 /*-------------------------------------------------------------------------*/
5822 void
m_unmake_filter(svalue_t * key,svalue_t * data,void * extra)5823 m_unmake_filter ( svalue_t *key
5824                 , svalue_t *data
5825                 , void *extra)
5826 
5827 /* Filter function used by efun unmkmapping().
5828  *
5829  * <key>/<data> point to key and data entry in a mapping, <extra> points to
5830  * a struct mvf_info describing the amount of data to copy, and the
5831  * target place. The <keu> and <data> is copied to where <extra> points
5832  * and <*extra> is updated.
5833  */
5834 
5835 {
5836     struct mvf_info * vip = (struct mvf_info *)extra;
5837     int i;
5838 
5839     assign_svalue_no_free(vip->svp->u.vec->item + vip->num, key);
5840     for (i = 0; i < vip->width; i++)
5841         assign_svalue_no_free(vip->svp[i+1].u.vec->item + vip->num, data+i);
5842     vip->num++;
5843 } /* m_unmake_filter() */
5844 
5845 /*-------------------------------------------------------------------------*/
5846 static INLINE svalue_t *
find_value(int num)5847 find_value (int num)
5848 
5849 /* Return the address of object-global variable number <num> in the
5850  * current variable block.
5851  *
5852  * <num> is the index of the variable in the current object's variable
5853  * array.
5854  */
5855 
5856 {
5857     /* Make sure that we are not calling from a set_this_object()
5858      * context.
5859      */
5860     if (is_sto_context())
5861     {
5862         errorf("find_value: Can't execute with "
5863               "set_this_object() in effect.\n"
5864              );
5865     }
5866 
5867 #ifdef DEBUG
5868     if (num >= current_object->prog->num_variables)
5869     {
5870         fatal("Illegal variable access %d(%d).\n",
5871             num, current_object->prog->num_variables);
5872     }
5873 #endif
5874     return &current_variables[num];
5875 } /* find_value() */
5876 
5877 /*-------------------------------------------------------------------------*/
5878 static INLINE svalue_t *
find_virtual_value(int num)5879 find_virtual_value (int num)
5880 
5881 /* For the virtually inherited variable <num> (given as index within
5882  * the current object's variable block) return the address of the actual
5883  * variable.
5884  *
5885  * If the program for this variable was inherited more than one time,
5886  * this function returns the address of the corresponding variable svalue
5887  * of the very first inheritance. If the program was inherited just once,
5888  * this function is identical to find_value().
5889  *
5890  * TODO: It would be nicer if the driver would 'know' here which inherit
5891  * TODO:: to use, either by giving the inherit index in the code, or
5892  * TODO:: by putting a reference to the base instance in the struct
5893  * TODO:: inherit.
5894  */
5895 
5896 {
5897     inherit_t *inheritp;
5898     program_t *progp;
5899     char *progpp; /* actually a program_t **, but some compilers... */
5900 
5901     /* Make sure that we are not calling from a set_this_object()
5902      * context.
5903      */
5904     if (is_sto_context())
5905     {
5906         errorf("find_virtual_value: Can't execute with "
5907               "set_this_object() in effect.\n"
5908              );
5909     }
5910 
5911     /* Set inheritp to the inherited program which defines variable <num>
5912      */
5913     inheritp = current_prog->inherit;
5914     while
5915       (   inheritp->variable_index_offset + inheritp->prog->num_variables <= num
5916        || inheritp->variable_index_offset > num)
5917     {
5918         inheritp++;
5919     }
5920 
5921     /* Get the index of the variable within the inherited program.
5922      */
5923     num -= inheritp->variable_index_offset;
5924 
5925     /* Set inheritp to the first instance of this inherited program.
5926      * A cleaner, but slighly slower way to write the following segment
5927      * is: for (inheritp = current_object->prog_inherit
5928      *         ; inheritp->prog != progp
5929      *         ; inheritp++) NOOP;
5930      */
5931     progp = inheritp->prog;
5932     progpp = (char *)&current_object->prog->inherit->prog;
5933     while (*(program_t **)progpp != progp)
5934         progpp += sizeof(inherit_t);
5935     inheritp = (inherit_t *)
5936                  (((PTRTYPE)(progpp)) - offsetof(inherit_t, prog));
5937 
5938     /* Compute the actual variable address */
5939 
5940     num += inheritp->variable_index_offset;
5941 
5942 #ifdef DEBUG
5943     if (!current_object->variables
5944      || num >= current_object->prog->num_variables
5945        )
5946     {
5947         if (num)
5948             fatal("%s Fatal: find_virtual_value() on object %p '%s' "
5949                   "w/o variables, num %d\n"
5950                  , time_stamp(), current_object, get_txt(current_object->name)
5951                  , num);
5952         else
5953             errorf("%s Error: find_virtual_value() on object %p '%s' "
5954                   "w/o variables, num %d\n"
5955                  , time_stamp(), current_object, get_txt(current_object->name)
5956                  , num);
5957     }
5958 #endif
5959 
5960     return &current_object->variables[num];
5961       /* TODO: Why not '&current_variables[num]'? */
5962 } /* find_virtual_value() */
5963 
5964 
5965 /*=========================================================================*/
5966 
5967 /*                  T Y P E S   A N D   E R R O R S                        */
5968 
5969 /*-------------------------------------------------------------------------*/
5970 /* The following functions deal with the readable display of LPC runtime
5971  * types, and of errors in general.
5972  *
5973  *   typename(type) : Return a descriptive string for a type.
5974  *   efun_arg_typename(type) : Return a descriptive string for the bit-
5975  *                    encoded type information of an efun.
5976  *   complete_instruction(instr) : Return the name of the given instruction,
5977  *                    resp. of the instruction found a the given negative
5978  *                    offset.
5979  *   raise_bad_arg(instr, arg) : Argument no. <arg> for the instruction
5980  *                    was bad.
5981  *   vefun_bad_arg(arg,sp) : Argument no. <arg> for the current vefun
5982  *                    was bad. Also restore inter_sp from sp.
5983  *   raise_arg_error(instr, arg, expected, got) : (internal) The argument
5984  *                    no. <arg> to the instruction did not have the
5985  *                    <expected> type (bit-encoded), but instead <got>
5986  *                    (the LPC type tag).
5987  *   (v)efun_gen_arg_error(arg, got, sp): Argument no. <arg> to the current
5988  *                    tabled (v)efun had the wrong type <got>. inter_sp is
5989  *                    restored from <sp>.
5990  *   (v)efun_arg_error(arg, expected, got, sp): Argument no. <arg> to the
5991  *                    current tabled (v)efun had the wrong type <got> (LPC
5992  *                    type tag), not the type <expected> (LPC type tag).
5993  *                    inter_sp is restored from <sp>.
5994  *   (v)efun_exp_arg_error(arg, expected, got, sp): Argument no. <arg> to the
5995  *                    current tabled (v)efun had the wrong type <got> (LPC
5996  *                    type tag), not the type <expected> (bit-encoded).
5997  *                    inter_sp is restored from <sp>.
5998  *   code_arg_error(arg, expected, got, pc, sp): Argument no. <arg> to the
5999  *                    current one-byte instruction had the wrong type <got>
6000  *                    (LPC type tag), not the type <expected> (LPC type tag).
6001  *                    inter_sp is restored from <sp>, inter_pc from <pc>.
6002  *   code_exp_arg_error(arg, expected, got, pc, sp): Argument no. <arg> to the
6003  *                    current one-byte instruction had the wrong type <got>
6004  *                    (LPC type tag), not the type <expected> (bit-encoded).
6005  *                    inter_sp is restored from <sp>, inter_pc from <pc>.
6006  *   op_arg_error(arg, expected, got, pc, sp): Argument no. <arg> to the
6007  *                    current one-byte operator had the wrong type <got>
6008  *                    (LPC type tag), not the type <expected> (LPC type tag).
6009  *                    inter_sp is restored from <sp>, inter_pc from <pc>.
6010  *   op_exp_arg_error(arg, expected, got, pc, sp): Argument no. <arg> to the
6011  *                    current one-byte operator had the wrong type <got>
6012  *                    (LPC type tag), not the type <expected> (bit-encoded).
6013  *                    inter_sp is restored from <sp>, inter_pc from <pc>.
6014  *
6015  *     The difference between code_... and op_... is that the op_...
6016  *     will use 'right' and 'left' for the argument names.
6017  *
6018  *   test_efun_args(instr, args, argp): (internal) Test the types for
6019  *                    <args> arguments for the given instruction, starting
6020  *                    at <argp> against the expected types according to
6021  *                    efun_lpc_types[].
6022  */
6023 
6024 /*-------------------------------------------------------------------------*/
6025 static INLINE const char *
typename_inline(int type)6026 typename_inline (int type)
6027 
6028 /* Translate the svalue <type> into a readable string.
6029  */
6030 
6031 {
6032     type &= ~(T_MOD_SWAPPED);
6033 
6034     if (type < 0
6035      || (size_t)type >= sizeof(svalue_typename)/sizeof(svalue_typename[0])
6036        )
6037         fatal("Unknown typevalue %d\n", type);
6038 
6039     return svalue_typename[type];
6040 } /* typename_inline() */
6041 
typename(int type)6042 const char * typename (int type) { return typename_inline(type); }
6043 
6044 #define typename(type) typename_inline(type)
6045 
6046 /*-------------------------------------------------------------------------*/
6047 const char *
efun_arg_typename(long type)6048 efun_arg_typename (long type)
6049 
6050 /* Translate the bit-encoded efun argument <type> into a readable
6051  * string and return it. The type encoding is the one used in
6052  * efun_lpc_types[].
6053  * Result is a pointer to a static buffer.
6054  * TODO: this function should use snprintf() for preventing buffer overflows,
6055  * TODO::especially changing svalue_typename is otherwise risky.
6056  */
6057 
6058 {
6059     static char result[400];
6060     int numtypes, i;
6061 
6062     /* TODO: better write into result and return the static buffer */
6063     if (type == TF_ANYTYPE)
6064         return "mixed";
6065 
6066     result[0] = '\0';
6067     numtypes = sizeof(svalue_typename)/sizeof(svalue_typename[0]);
6068 
6069     for (i = 0; i < numtypes; i++)
6070     {
6071         if ((1 << i) & type)
6072         {
6073             if (result[0] != '\0')
6074                 strcat(result, "/");
6075             strcat(result, typename(i));
6076         }
6077         type &=~(1 << i);
6078     }
6079 
6080     if (type != 0)
6081     {
6082         char tmp[100];
6083         if (result[0] != '\0')
6084             strcat(result, "/");
6085         sprintf(tmp, "unknown %lx", type);
6086         strcat(result, tmp);
6087     }
6088     return (const char *)result;
6089 } /* efun_arg_typename() */
6090 
6091 /*-------------------------------------------------------------------------*/
6092 static INLINE int
complete_instruction(int instr)6093 complete_instruction (int instr)
6094 
6095 /* If <instr> is negative, read the current instruction from
6096  * inter_pc - <instr> and return it; otherwise return <instr> itself.
6097  */
6098 
6099 {
6100     if (instr < 0)
6101     {
6102         /* Find and decode the actual instruction at the given offset */
6103         bytecode_p pc = inter_pc + instr;
6104 
6105         instr = *pc;
6106         switch(instr)
6107         {
6108         case F_EFUN0:  instr = pc[1] + EFUN0_OFFSET; break;
6109         case F_EFUN1:  instr = pc[1] + EFUN1_OFFSET; break;
6110         case F_EFUN2:  instr = pc[1] + EFUN2_OFFSET; break;
6111         case F_EFUN3:  instr = pc[1] + EFUN3_OFFSET; break;
6112         case F_EFUN4:  instr = pc[1] + EFUN4_OFFSET; break;
6113         case F_EFUNV:  instr = pc[1] + EFUNV_OFFSET; break;
6114         default:
6115             /* This is the instruction code we need */
6116             NOOP;
6117             break;
6118         }
6119     }
6120 
6121     return instr;
6122 } /* complete_instruction() */
6123 
6124 /*-------------------------------------------------------------------------*/
6125 static INLINE void
6126 raise_bad_arg (int instr, int arg)
6127   NORETURN;
6128 
6129 static INLINE void
raise_bad_arg(int instr,int arg)6130 raise_bad_arg (int instr, int arg)
6131 
6132 /* The argument <arg> to <instr> was unusable for some reason.
6133  * If <instr> is negative, the instruction code is read from
6134  * inter_pc - <instr>; otherwise it is the instruction code itself.
6135  *
6136  * inter_sp and inter_pc are assumed to be correct.
6137  * Raise a proper error.
6138  */
6139 
6140 {
6141     instr = complete_instruction(instr);
6142 
6143     errorf("Bad argument %d to %s().\n", arg, get_f_name(instr));
6144     /* NOTREACHED */
6145 } /* raise_bad_arg() */
6146 
6147 /*-------------------------------------------------------------------------*/
6148 void
vefun_bad_arg(int arg,svalue_t * sp)6149 vefun_bad_arg (int arg, svalue_t *sp)
6150 
6151 /* The argument <arg> to the current tabled vefun was unusable.
6152  * inter_pc is assumed to be correct, inter_sp will be set from <sp>.
6153  */
6154 
6155 {
6156     inter_sp = sp;
6157     raise_bad_arg(-2, arg);
6158     /* NOTREACHED */
6159 } /* vefun_bad_arg() */
6160 
6161 /*-------------------------------------------------------------------------*/
6162 static INLINE void
6163 raise_arg_error (int instr, int arg, long expected, int got)
6164   NORETURN;
6165 
6166 static INLINE void
raise_arg_error(int instr,int arg,long expected,int got)6167 raise_arg_error (int instr, int arg, long expected, int got)
6168 
6169 /* The argument <arg> to <instr> had the wrong type: expected was the
6170  * type <expected> (bit-encoded as in the efun_lpc_types[]), but
6171  * it got the type <got> (the svalue type tag).
6172  * If <instr> is negative, the instruction code is read from
6173  * inter_pc - <instr>; otherwise it is the instruction code itself.
6174  *
6175  * If <expected> is 0, the expected type is read from the
6176  * instrs[] table.
6177  *
6178  * inter_sp and inter_pc are assumed to be correct.
6179  * Raise a proper error.
6180  */
6181 
6182 {
6183     instr = complete_instruction(instr);
6184 
6185     if (!expected)
6186         expected = efun_lpc_types[instrs[instr].lpc_arg_index];
6187 
6188     errorf("Bad arg %d to %s(): got '%s', expected '%s'.\n"
6189          , arg, get_f_name(instr), typename(got), efun_arg_typename(expected)
6190          );
6191     /* NOTREACHED */
6192 } /* raise_arg_error() */
6193 
6194 /*-------------------------------------------------------------------------*/
6195 void
efun_gen_arg_error(int arg,int got,svalue_t * sp)6196 efun_gen_arg_error (int arg, int got, svalue_t *sp)
6197 
6198 /* The argument <arg> to the current tabled efun had the wrong type <got>.
6199  * inter_pc is assumed to be correct, inter_sp will be set from <sp>.
6200  */
6201 
6202 {
6203     inter_sp = sp;
6204     raise_arg_error(-2, arg, 0, got);
6205     /* NOTREACHED */
6206 } /* efun_gen_arg_error() */
6207 
6208 /*-------------------------------------------------------------------------*/
6209 void
vefun_gen_arg_error(int arg,int got,svalue_t * sp)6210 vefun_gen_arg_error (int arg, int got, svalue_t *sp)
6211 
6212 /* The argument <arg> to the current tabled vefun had the wrong type <got>.
6213  * inter_pc is assumed to be correct, inter_sp will be set from <sp>.
6214  */
6215 
6216 {
6217     inter_sp = sp;
6218     raise_arg_error(-2, arg, 0, got);
6219     /* NOTREACHED */
6220 } /* vefun_gen_arg_error() */
6221 
6222 /*-------------------------------------------------------------------------*/
6223 void
efun_arg_error(int arg,int expected,int got,svalue_t * sp)6224 efun_arg_error (int arg, int expected, int got, svalue_t *sp)
6225 
6226 /* The argument <arg> to the current tabled efun had the wrong type:
6227  * expected was the type <expected>, but it got the type <got>
6228  * (both values are the svalue type tag).
6229  * inter_pc is assumed to be correct, inter_sp will be set from <sp>.
6230  */
6231 
6232 {
6233     inter_sp = sp;
6234     raise_arg_error(-2, arg, 1 << expected, got);
6235     /* NOTREACHED */
6236 } /* efun_arg_error() */
6237 
6238 /*-------------------------------------------------------------------------*/
6239 void
efun_exp_arg_error(int arg,long expected,int got,svalue_t * sp)6240 efun_exp_arg_error (int arg, long expected, int got, svalue_t *sp)
6241 
6242 /* The argument <arg> to the current tabled efun had the wrong type:
6243  * expected was the type <expected> (given as bitflags), but it got the type
6244  * <got> (given as svalue type tag).
6245  * inter_pc is assumed to be correct, inter_sp will be set from <sp>.
6246  */
6247 
6248 {
6249     inter_sp = sp;
6250     raise_arg_error(-2, arg, expected, got);
6251     /* NOTREACHED */
6252 } /* efun_arg_error() */
6253 
6254 /*-------------------------------------------------------------------------*/
6255 void
vefun_arg_error(int arg,int expected,int got,svalue_t * sp)6256 vefun_arg_error (int arg, int expected, int got, svalue_t *sp)
6257 
6258 /* The argument <arg> to the current tabled vefun had the wrong type:
6259  * expected was the type <expected>, but it got the type <got>
6260  * (both values are the svalue type tag).
6261  * inter_pc is assumed to be correct, inter_sp will be set from <sp>.
6262  */
6263 
6264 {
6265     inter_sp = sp;
6266     raise_arg_error(-2, arg, 1 << expected, got);
6267     /* NOTREACHED */
6268 } /* vefun_arg_error() */
6269 
6270 /*-------------------------------------------------------------------------*/
6271 void
vefun_exp_arg_error(int arg,long expected,int got,svalue_t * sp)6272 vefun_exp_arg_error (int arg, long expected, int got, svalue_t *sp)
6273 
6274 /* The argument <arg> to the current tabled vefun had the wrong type:
6275  * expected was the type <expected> (in the bit-encoded format), but
6276  * it got the type <got> (the svalue type tag).
6277  * inter_pc is assumed to be correct, inter_sp will be set from <sp>.
6278  */
6279 
6280 {
6281     inter_sp = sp;
6282     raise_arg_error(-2, arg, expected, got);
6283     /* NOTREACHED */
6284 } /* vefun_exp_arg_error() */
6285 
6286 /*-------------------------------------------------------------------------*/
6287 static INLINE void
6288 code_exp_arg_error (int arg, long expected, int got, bytecode_p pc, svalue_t *sp)
6289   NORETURN;
6290 
6291 static INLINE void
code_exp_arg_error(int arg,long expected,int got,bytecode_p pc,svalue_t * sp)6292 code_exp_arg_error (int arg, long expected, int got, bytecode_p pc, svalue_t *sp)
6293 
6294 /* The argument <arg> to the current one-byte instruction had the wrong type:
6295  * expected was the type <expected> (in bit-flag encoding), but it got the
6296  * type <got> (the svalue type tag).
6297  * inter_pc will be set from <pc>, inter_sp will be set from <sp>.
6298  */
6299 
6300 {
6301     int instr;
6302 
6303     inter_sp = sp;
6304     inter_pc = pc;
6305 
6306     instr = complete_instruction(-1);
6307 
6308     errorf("Bad arg %d to %s: got '%s', expected '%s'.\n"
6309          , arg, get_f_name(instr), typename(got), efun_arg_typename(expected)
6310          );
6311     /* NOTREACHED */
6312 } /* code_exp_arg_error() */
6313 
6314 /*-------------------------------------------------------------------------*/
6315 static INLINE void
6316 code_arg_error (int arg, int expected, int got, bytecode_p pc, svalue_t *sp)
6317   NORETURN;
6318 
6319 static INLINE void
code_arg_error(int arg,int expected,int got,bytecode_p pc,svalue_t * sp)6320 code_arg_error (int arg, int expected, int got, bytecode_p pc, svalue_t *sp)
6321 
6322 /* The argument <arg> to the current one-byte instruction had the wrong type:
6323  * expected was the type <expected>, but it got the type <got>
6324  * (both values are the svalue type tag).
6325  * inter_pc will be set from <pc>, inter_sp will be set from <sp>.
6326  */
6327 
6328 {
6329     code_exp_arg_error(arg, 1 << expected, got, pc,sp);
6330     /* NOTREACHED */
6331 } /* code_arg_error() */
6332 
6333 /*-------------------------------------------------------------------------*/
6334 static INLINE void
6335 op_exp_arg_error (int arg, long expected, int got, bytecode_p pc, svalue_t *sp)
6336   NORETURN;
6337 
6338 static INLINE void
op_exp_arg_error(int arg,long expected,int got,bytecode_p pc,svalue_t * sp)6339 op_exp_arg_error (int arg, long expected, int got, bytecode_p pc, svalue_t *sp)
6340 
6341 /* The argument <arg> to the current one-byte operator had the wrong type:
6342  * expected was the type <expected> (bit-encoded as in efun_lpc_types[]),
6343  * but it got the type <got> (the svalue type tag).
6344  * inter_pc will be set from <pc>, inter_sp will be set from <sp>.
6345  *
6346  * This function is to be used with binary operators like + or *; the
6347  * error message will say 'left' and 'right' instead of 'arg 1' or 'arg 2'.
6348  */
6349 
6350 {
6351     int instr;
6352 
6353     inter_sp = sp;
6354     inter_pc = pc;
6355 
6356     instr = complete_instruction(-1);
6357 
6358     errorf("Bad %s arg to %s: got '%s', expected '%s'.\n"
6359          , arg == 1 ? "left" : "right"
6360          , get_f_name(instr), typename(got), efun_arg_typename(expected)
6361          );
6362     /* NOTREACHED */
6363 } /* op_exp_arg_error() */
6364 
6365 /*-------------------------------------------------------------------------*/
6366 static INLINE void
6367 op_arg_error (int arg, int expected, int got, bytecode_p pc, svalue_t *sp)
6368   NORETURN;
6369 
6370 static INLINE void
op_arg_error(int arg,int expected,int got,bytecode_p pc,svalue_t * sp)6371 op_arg_error (int arg, int expected, int got, bytecode_p pc, svalue_t *sp)
6372 
6373 /* The argument <arg> to the current one-byte operator had the wrong type:
6374  * expected was the type <expected>, but it got the type <got>
6375  * (both values are the svalue type tag).
6376  * inter_pc will be set from <pc>, inter_sp will be set from <sp>.
6377  *
6378  * This function is to be used with binary operators like + or *; the
6379  * error message will say 'left' and 'right' instead of 'arg 1' or 'arg 2'.
6380  */
6381 
6382 {
6383     op_exp_arg_error(arg, 1 << expected, got, pc, sp);
6384     /* NOTREACHED */
6385 } /* op_arg_error() */
6386 
6387 /*-------------------------------------------------------------------------*/
6388 static INLINE void
test_efun_args(int instr,int args,svalue_t * argp)6389 test_efun_args (int instr, int args, svalue_t *argp)
6390 
6391 /* Test the types of the <args> arguments for (v)efun <instr> starting at
6392  * <argp> for their correct types according to efun_lpc_types[].
6393  * Raise an error if they aren't correct (requires inter_pc and inter_sp
6394  * to be valid).
6395  */
6396 
6397 {
6398     int i;
6399     long * typep, type;
6400 
6401     typep = &(efun_lpc_types[instrs[instr].lpc_arg_index]);
6402     for (i = 1; i <= args; i++, typep++, argp++)
6403     {
6404         type = *typep;
6405         if (argp->type == T_NUMBER && !argp->u.number
6406          && (type & TF_NULL)
6407            )
6408             continue;
6409         if (!(*typep & (1 << argp->type)))
6410             raise_arg_error(instr, i, *typep, argp->type);
6411     }
6412 } /* test_efun_args() */
6413 
6414 
6415 /*-------------------------------------------------------------------------*/
6416 /* general errorhandler */
6417 static void
generic_error_handler(svalue_t * arg)6418 generic_error_handler( svalue_t * arg)
6419 /* The error handler: free the allocated buffer and the errorhandler structure.
6420  * Note: it is static, but the compiler will have to emit a function and
6421  * symbol for this because the address of the function is taken and it is
6422  * therefore not suitable to be inlined.
6423  */
6424 {
6425   errorhandler_t *handler = (errorhandler_t *)arg;
6426   if (handler->buff)
6427     xfree(handler->buff);
6428   xfree(handler);
6429 } /* general_error_handler() */
6430 
6431 /*-------------------------------------------------------------------------*/
6432 void *
xalloc_with_error_handler(size_t size)6433 xalloc_with_error_handler(size_t size)
6434 /* Allocates <size> bytes from the heap. Additionally an error handler is
6435  * pushed onto the value stack so that the requested memory is safely freed,
6436  * either by manually freeing the svalue on the stack or during stack
6437  * unwinding during errorf().
6438  * inter_sp has to point to the top-of-stack before calling and is updated to
6439  * point to the error handler svalue (new top-of-stack)!
6440  */
6441 {
6442   void *buffer;
6443   errorhandler_t *handler;
6444   /* get the memory for the handler first and fail if out-of-memory */
6445   handler = xalloc(sizeof(*handler));
6446   if (!handler)
6447   {
6448     return NULL;
6449   }
6450   /* then get the requested memory - upon error de-allocate the handler */
6451   buffer = xalloc(size);
6452   if (!buffer)
6453   {
6454     xfree(handler);
6455     return NULL;
6456   }
6457   handler->buff = buffer;
6458   /* now push error handler onto the value stack */
6459   push_error_handler(generic_error_handler, &(handler->head));
6460   return buffer;
6461 } /* alloc_with_error_handler */
6462 
6463 
6464 /*=========================================================================*/
6465 /*-------------------------------------------------------------------------*/
6466 Bool
privilege_violation(string_t * what,svalue_t * arg,svalue_t * sp)6467 privilege_violation (string_t *what, svalue_t *arg, svalue_t *sp)
6468 
6469 /* Call the mudlib to check for a privilege violation:
6470  *
6471  *   master->privilege_violation(what, current_object, arg)
6472  *
6473  * where <what> describes the type of the violation (uncounted string ref),
6474  * and <where> is the data used in the violation.
6475  * <sp> is the current stack setting.
6476  *
6477  * If the apply returns a positive number, the privilege is granted and
6478  * the function returns TRUE.
6479  * If the apply returns 0, the privilege is gently denied and the function
6480  * returns FALSE.
6481  * If the apply returns something else, or if the lfun doesn't exist,
6482  * an error is raised.
6483  *
6484  * If the current_object is the master or simul_efun object, this function
6485  * immediately returns TRUE.
6486  *
6487  * <inter_sp> is updated to <sp>, <inter_pc> is assumed to be correct.
6488  */
6489 
6490 {
6491     return privilege_violation2(what, arg, NULL, sp);
6492 } /* privilege_violation() */
6493 
6494 /*-------------------------------------------------------------------------*/
6495 Bool
privilege_violation2(string_t * what,svalue_t * arg,svalue_t * arg2,svalue_t * sp)6496 privilege_violation2 ( string_t *what, svalue_t *arg, svalue_t *arg2
6497                      , svalue_t *sp)
6498 
6499 /* Call the mudlib to check for a privilege violation:
6500  *
6501  *   master->privilege_violation(what, current_object, arg, arg2)
6502  *
6503  * where <what> describes the type of the violation (uncounted string ref),
6504  * and <arg>, <arg2> is the data used in the violation.
6505  * <sp> is the current stack setting.
6506  *
6507  * <arg2> may be NULL and is then ignored.
6508  *
6509  * If the apply returns a positive number, the privilege is granted and
6510  * the function returns TRUE.
6511  * If the apply returns 0, the privilege is gently denied and the function
6512  * returns FALSE.
6513  * If the apply returns something else, or if the lfun doesn't exist,
6514  * an error is raised.
6515  *
6516  * If the current_object is the master or simul_efun object, this function
6517  * immediately returns TRUE.
6518  *
6519  * <inter_sp> is updated to <sp>, <inter_pc> is assumed to be correct.
6520  */
6521 
6522 {
6523     svalue_t *svp;
6524     int num_arg = 3;
6525 
6526     /* Trusted objects */
6527     if (current_object == master_ob) return MY_TRUE;
6528     if (current_object == simul_efun_object) return MY_TRUE;
6529 
6530     /* Setup and call the lfun */
6531     push_ref_string(sp, what);
6532     push_ref_valid_object(sp, current_object, "privilege violation");
6533     sp++;
6534     assign_svalue_no_free(sp, arg);
6535     if (arg2 != NULL)
6536     {
6537         sp++;
6538         assign_svalue_no_free(sp, arg2);
6539         num_arg++;
6540     }
6541     inter_sp = sp;
6542     svp = apply_master(STR_PRIVILEGE, num_arg);
6543 
6544     /* Is there a lfun to call? */
6545     if (!svp || svp->type != T_NUMBER || svp->u.number < 0)
6546     {
6547         inter_sp = sp-num_arg;
6548         errorf("privilege violation: %s\n", get_txt(what));
6549         /* TODO: Print full args and types */
6550     }
6551 
6552     /* Return the result */
6553     return svp->u.number > 0;
6554 } /* privilege_violation2() */
6555 
6556 /*-------------------------------------------------------------------------*/
6557 Bool
privilege_violation4(string_t * what,object_t * whom,string_t * how_str,int how_num,svalue_t * sp)6558 privilege_violation4 ( string_t *what,    object_t *whom
6559                      , string_t *how_str, int how_num
6560                      , svalue_t *sp)
6561 
6562 /* Call the mudlib to check for a privilege violation:
6563  *
6564  *   !whom:
6565  *       master->privilege_violation(what, current_object, how_str, how_num)
6566  *   whom && how_str:
6567  *       master->privilege_violation(what, current_object, whom, how_str)
6568  *   whom && !how_str:
6569  *       master->privilege_violation(what, current_object, whom, how_num)
6570  *
6571  * where <what> describes the type of the violation, and <whom>/<how_str>/
6572  * <how_num> are data used in the violation. <sp> is the current stack setting.
6573  * All strings are not counted.
6574  *
6575  * If the apply returns a positive number, the privilege is granted and
6576  * the function returns TRUE.
6577  * If the apply returns 0, the privilege is gently denied and the function
6578  * returns FALSE.
6579  * If the apply returns something else, or if the lfun doesn't exist,
6580  * an error is raised.
6581  *
6582  * If the current_object is the master or simul_efun object, this function
6583  * immediately returns TRUE.
6584  *
6585  * If the lfun doesn't exist, or returns anything else but a positive
6586  * number, an error is raised.
6587  *
6588  * <inter_sp> is updated to <sp>, <inter_pc> is assumed to be correct.
6589  */
6590 
6591 {
6592     svalue_t *svp;
6593 
6594     /* Trust these objects */
6595     if (current_object == master_ob) return MY_TRUE;
6596     if (current_object == simul_efun_object) return MY_TRUE;
6597 
6598     /* Set up the lfun call */
6599 
6600     push_ref_string(sp, what);
6601     push_ref_valid_object(sp, current_object, "privilege_violation");
6602     if (!whom)
6603     {
6604         if (how_str)
6605             push_ref_string(sp, how_str);
6606         else
6607             push_number(sp, 0);
6608         push_number(sp, how_num);
6609     }
6610     else
6611     {
6612         push_ref_object(sp, whom, "privilege_violation");
6613         if (how_str)
6614             push_ref_string(sp, how_str);
6615         else
6616             push_number(sp, how_num);
6617     }
6618     inter_sp = sp;
6619     svp = apply_master(STR_PRIVILEGE, 4);
6620 
6621     /* Was it the proper lfun to call? */
6622     if (!svp || svp->type != T_NUMBER || svp->u.number < 0)
6623     {
6624         inter_sp = sp-4;
6625         errorf("privilege violation : %s\n", get_txt(what));
6626         /* TODO: Print full args and types */
6627     }
6628 
6629     /* Return the result */
6630     return svp->u.number > 0;
6631 } /* privilege_violation4() */
6632 
6633 /*-------------------------------------------------------------------------*/
6634 Bool
privilege_violation_n(string_t * what,object_t * whom,svalue_t * sp,int num_arg)6635 privilege_violation_n ( string_t *what, object_t *whom, svalue_t *sp, int num_arg)
6636 
6637 /* Call the mudlib to check for a privilege violation:
6638  *
6639  *   master->privilege_violation(what, current_object, whom,
6640  *                               sp[-num_arg+1], ...., sp)
6641  *
6642  * where <what> describes the type of the violation, and <whom> and the last
6643  * <num_arg> values of the stack are data used in the violation. <sp> is
6644  * also the current stack setting. All strings are not counted.
6645  *
6646  * If the apply returns a positive number, the privilege is granted and
6647  * the function returns TRUE.
6648  * If the apply returns 0, the privilege is gently denied and the function
6649  * returns FALSE.
6650  * If the apply returns something else, or if the lfun doesn't exist,
6651  * an error is raised.
6652  *
6653  * If the current_object is the master or simul_efun object, this function
6654  * immediately returns TRUE.
6655  *
6656  * If the lfun doesn't exist, or returns anything else but a positive
6657  * number, an error is raised.
6658  *
6659  * <inter_sp> is updated to <sp>, <inter_pc> is assumed to be correct.
6660  */
6661 
6662 {
6663     svalue_t *svp, *arg;
6664     int num;
6665 
6666     /* Trust these objects */
6667     if (current_object == master_ob) return MY_TRUE;
6668     if (current_object == simul_efun_object) return MY_TRUE;
6669 
6670     /* Set up the lfun call */
6671 
6672     arg = sp + 1 - num_arg;
6673 
6674     push_ref_string(sp, what);
6675     push_ref_valid_object(sp, current_object, "privilege_violation");
6676     if (!whom)
6677     {
6678         push_number(sp, 0);
6679     }
6680     else
6681     {
6682         push_ref_object(sp, whom, "privilege_violation");
6683     }
6684 
6685     for (num = num_arg; num--; arg++)
6686     {
6687         sp++;
6688         assign_svalue_no_free(sp,  arg);
6689     }
6690 
6691     inter_sp = sp;
6692     svp = apply_master(STR_PRIVILEGE, 3 + num_arg);
6693 
6694     /* Was it the proper lfun to call? */
6695     if (!svp || svp->type != T_NUMBER || svp->u.number < 0)
6696     {
6697         inter_sp = sp - 3 - num_arg;
6698         errorf("privilege violation : %s\n", get_txt(what));
6699         /* TODO: Print full args and types */
6700     }
6701 
6702     /* Return the result */
6703     return svp->u.number > 0;
6704 } /* privilege_violation_n() */
6705 
6706 /*-------------------------------------------------------------------------*/
6707 static Bool
trace_test(int b)6708 trace_test (int b)
6709 
6710 /* Test if tracing of the given option(s) <b> is allowed right now.
6711  * The function tests the options <b> against what the current interactive
6712  * requested, and if a trace_prefix is given, if the prefix matches the
6713  * name of the current object.
6714  */
6715 
6716 {
6717     interactive_t *ip;
6718 
6719     return current_interactive
6720         && O_SET_INTERACTIVE(ip, current_interactive)
6721         && (ip->trace_level & b)
6722         && (ip->trace_prefix == NULL
6723             || (current_object
6724                 && mstrprefixed(ip->trace_prefix, current_object->name)))
6725     ;
6726 } /* trace_test() */
6727 
6728 /*-------------------------------------------------------------------------*/
6729 static void
do_trace(char * msg,char * fname,char * post)6730 do_trace (char *msg, char *fname, char *post)
6731 
6732 /* If not in a heartbeat, or if heartbeat tracing is allowed, generate
6733  * a tracemessage of the form '<tracedepth> <msg> <objname> <fname> <post>'
6734  * and print it to the player using add_message().
6735  *
6736  * Don't do anything if the current command_giver is not interactive.
6737  *
6738  * <obj_name> is filled in only if TRACE_OBJNAME is requested, else
6739  * the empty string is used.
6740  */
6741 
6742 {
6743     char buf[10000];
6744     char *objname;
6745 
6746     if (!TRACEHB)
6747         return;
6748     objname = TRACETST(TRACE_OBJNAME)
6749               ? (current_object && current_object->name
6750                    ? get_txt(current_object->name)
6751                    : "?")
6752               : "";
6753     sprintf(buf, "*** %d %*s %s %s %s%s", tracedepth, tracedepth, ""
6754                , msg, objname, fname, post);
6755     add_message("%s", buf);
6756 #ifdef DEBUG
6757     add_message(message_flush);
6758 #endif
6759 } /* do_trace() */
6760 
6761 /*-------------------------------------------------------------------------*/
6762 static void
do_trace_call(fun_hdr_p funstart,Bool is_lambda)6763 do_trace_call (fun_hdr_p funstart, Bool is_lambda)
6764 
6765 /* Trace a call to the function starting at <funstart>.
6766  */
6767 
6768 {
6769     if (!++traceing_recursion || !TRACE_IS_INTERACTIVE()) /* Do not recurse! */
6770     {
6771         int save_var_ix_offset = variable_index_offset;
6772           /* TODO: Might be clobbered, but where? */
6773 
6774         /* Trace the function itself */
6775         if (is_lambda)
6776             do_trace("Call direct ", "lambda-closure", " ");
6777         else
6778         {
6779             string_t *name;
6780 
6781             memcpy(&name, FUNCTION_NAMEP(funstart), sizeof name);
6782             do_trace("Call direct ", get_txt(name), " ");
6783         }
6784 
6785         /* If requested, also trace the arguments */
6786         if (TRACEHB)
6787         {
6788             if (TRACETST(TRACE_ARGS))
6789             {
6790                 int i;
6791                 svalue_t *svp;
6792 
6793                 add_message(" with %d arguments: "
6794                            , FUNCTION_NUM_ARGS(funstart) & 0x7f);
6795                 svp = inter_fp;
6796                 for (i = (FUNCTION_NUM_ARGS(funstart) & 0x7f); --i >= 0; )
6797                 {
6798                     print_svalue(svp++);
6799                     add_message(" ");
6800                 }
6801             }
6802             add_message("\n");
6803         }
6804         variable_index_offset = save_var_ix_offset;
6805     }
6806     traceing_recursion--;
6807 } /* do_trace_call() */
6808 
6809 /*-------------------------------------------------------------------------*/
6810 static void
do_trace_return(svalue_t * sp)6811 do_trace_return (svalue_t *sp)
6812 
6813 /* Trace the return from a function call; <sp> is the current stack pointer,
6814  * pointing to the result.
6815  */
6816 
6817 {
6818     if (!++traceing_recursion || !TRACE_IS_INTERACTIVE())
6819     {
6820         if (trace_test(TRACE_RETURN))
6821         {
6822             inter_sp = sp;
6823             do_trace("Return", "", "");
6824             if (TRACEHB) {
6825                 if (TRACETST(TRACE_ARGS)) {
6826                     add_message(" with value: ");
6827                     print_svalue(sp);
6828                 }
6829                 add_message("\n");
6830             }
6831         }
6832     }
6833     traceing_recursion--;
6834 
6835     /* If requested, (re)activate TRACE_EXEC */
6836     SET_TRACE_EXEC;
6837 }
6838 
6839 /*-------------------------------------------------------------------------*/
6840 struct longjump_s *
push_error_context(svalue_t * sp,int catch_flags)6841 push_error_context (svalue_t *sp, int catch_flags)
6842 
6843 /* Create a catch recovery context, using <sp> as the stackpointer to save,
6844  * link it into the recovery stack and return the longjmp context struct.
6845  * The actual type of the catch context is determined by the <catch_flags>.
6846  */
6847 
6848 {
6849     struct catch_context *p;
6850 
6851     p = xalloc (sizeof *p);
6852     p->save_sp = sp;
6853     p->save_csp = csp;
6854     p->save_command_giver = command_giver;
6855     p->recovery_info.rt.last = rt_context;
6856     p->recovery_info.rt.type = ERROR_RECOVERY_CATCH;
6857     p->recovery_info.flags = catch_flags;
6858     p->catch_value.type = T_INVALID;
6859     rt_context = (rt_context_t *)&p->recovery_info.rt;
6860     return &p->recovery_info.con;
6861 } /* push_error_context() */
6862 
6863 /*-------------------------------------------------------------------------*/
6864 void
pop_error_context(void)6865 pop_error_context (void)
6866 
6867 /* Pop and discard the top entry in the error recovery stack, assuming
6868  * that it's a catch recovery entry.
6869  *
6870  * This function is called when the catch() completed normally.
6871  */
6872 
6873 {
6874     struct catch_context *p;
6875 
6876     p = (struct catch_context *)rt_context;
6877 
6878 #ifdef DEBUG
6879     if (!ERROR_RECOVERY_CAUGHT(p->recovery_info.rt.type))
6880         fatal("Catch: runtime stack underflow");
6881     if (csp != p->save_csp-1)
6882         fatal("Catch: Lost track of csp");
6883     /* Note: the command_giver might have changed (with the exec() efun),
6884      * so testing it is of no use.
6885      */
6886 #endif
6887     rt_context = p->recovery_info.rt.last;
6888     xfree(p);
6889 } /* pop_error_context() */
6890 
6891 /*-------------------------------------------------------------------------*/
6892 svalue_t *
pull_error_context(svalue_t * sp,svalue_t * msg)6893 pull_error_context (svalue_t *sp, svalue_t *msg)
6894 
6895 /* Restore the context saved by a catch() after a throw() or runtime error
6896  * occured. <sp> is the current stackpointer and is used to pop the elements
6897  * pushed since the catch().
6898  *
6899  * The function pops the topmost recovery entry, which must be the catch
6900  * recovery entry, restores the important global variables and returns
6901  * the saved stack pointer.
6902  *
6903  * If <msg> is not NULL the caught error message is put there.
6904  */
6905 
6906 {
6907     struct catch_context *p;
6908     struct control_stack *csp2;
6909 
6910     p = (struct catch_context *)rt_context;
6911 
6912     if (!ERROR_RECOVERY_CAUGHT(p->recovery_info.rt.type))
6913         fatal("Catch: runtime stack underflow");
6914 
6915     /* If there was a call_other() or similar, previous_ob and current_object
6916      * must be restored. For this, find the control frame where the call
6917      * occured and get the proper values from there.
6918      */
6919     csp2 = p->save_csp;
6920     while (++csp2 <= csp)
6921     {
6922         if (csp2->extern_call)
6923         {
6924             previous_ob = csp2->prev_ob;
6925             current_object = csp2->ob;
6926             break;
6927         }
6928     }
6929 
6930     /* If there was a lambda call, we have to restore current_lambda */
6931     for (csp2 = csp; csp2 >p->save_csp; csp2--)
6932     {
6933         if (current_lambda.type == T_CLOSURE)
6934             free_closure(&current_lambda);
6935         current_lambda = csp2->lambda;
6936     }
6937 
6938     /* Restore the global variables and the evaluator stack */
6939     csp = p->save_csp;
6940     pop_n_elems(sp - p->save_sp);
6941     command_giver = p->save_command_giver;
6942 
6943     /* Save the error message */
6944     if (msg)
6945         transfer_svalue_no_free(msg, &p->catch_value);
6946     else
6947         free_svalue(&p->catch_value);
6948 
6949     /* Remove the context from the context stack */
6950     rt_context = p->recovery_info.rt.last;
6951     xfree(p);
6952 
6953     return sp;
6954 } /* pull_error_context() */
6955 
6956 /*-------------------------------------------------------------------------*/
6957 void
transfer_error_message(svalue_t * v,rt_context_t * rt)6958 transfer_error_message (svalue_t *v, rt_context_t *rt)
6959  /* Saves the message <v> in the error context <rt> assuming that
6960   * it's a catch recovery context. <v> is freed afterwards.
6961   */
6962 {
6963     struct catch_context *p;
6964 
6965     p = (struct catch_context *)rt;
6966     transfer_svalue_no_free(&p->catch_value, v);
6967 }
6968 
6969 /*-------------------------------------------------------------------------*/
6970 void
push_control_stack(svalue_t * sp,bytecode_p pc,svalue_t * fp,svalue_t * context)6971 push_control_stack ( svalue_t   *sp
6972                    , bytecode_p  pc
6973                    , svalue_t   *fp
6974 #ifdef USE_NEW_INLINES
6975                    , svalue_t   *context
6976 #endif /* USE_NEW_INLINES */
6977                    )
6978 
6979 /* Push the current execution context onto the control stack.
6980  * On stack overflow, raise a 'too deep recursion' error.
6981  */
6982 
6983 {
6984 
6985     /* Check for overflow */
6986     if (csp >= &CONTROL_STACK[MAX_USER_TRACE-1])
6987     {
6988         if (!num_error || csp == &CONTROL_STACK[MAX_TRACE-1])
6989         {
6990             ERRORF(("Too deep recursion: depth %"PRIdMPINT
6991                     ", limit %d user/%d max.\n"
6992                    , (mp_int)(csp - CONTROL_STACK + 1)
6993                    , MAX_USER_TRACE, MAX_TRACE));
6994         }
6995     }
6996 
6997     /* Move csp to the next entry and fill it with the current context
6998      */
6999     csp++;
7000 
7001     /* csp->funstart  has to be set later, it is used only for tracebacks. */
7002     csp->fp = fp;
7003 #ifdef USE_NEW_INLINES
7004     csp->context = context;
7005 #endif /* USE_NEW_INLINES */
7006     csp->prog = current_prog;
7007     csp->lambda = current_lambda; put_number(&current_lambda, 0);
7008     /* csp->extern_call = MY_FALSE; It is set by eval_instruction() */
7009     csp->catch_call = MY_FALSE;
7010     csp->pc = pc;
7011     csp->function_index_offset = function_index_offset;
7012     csp->current_variables = current_variables;
7013     csp->break_sp = break_sp;
7014 #ifdef EVAL_COST_TRACE
7015     csp->eval_cost = eval_cost;
7016 #endif
7017 } /* push_control_stack() */
7018 
7019 /*-------------------------------------------------------------------------*/
7020 void
pop_control_stack(void)7021 pop_control_stack (void)
7022 
7023 /* Pop the last entry from the control stack and restore the execution
7024  * context from it - except for extern_call of which the old value will
7025  * be used immediately after the pop.
7026  */
7027 
7028 {
7029 #ifdef DEBUG
7030     if (csp < CONTROL_STACK)
7031         fatal("Popped out of the control stack");
7032 #endif
7033 
7034     if ( NULL != (current_prog = csp->prog) ) /* is 0 when we reach the bottom */
7035     {
7036         current_strings = current_prog->strings;
7037     }
7038     if (current_lambda.type == T_CLOSURE)
7039         free_closure(&current_lambda);
7040     current_lambda = csp->lambda;
7041     inter_pc = csp->pc;
7042     inter_fp = csp->fp;
7043 #ifdef USE_NEW_INLINES
7044     inter_context = csp->context;
7045 #endif /* USE_NEW_INLINES */
7046     function_index_offset = csp->function_index_offset;
7047     current_variables     = csp->current_variables;
7048     break_sp = csp->break_sp;
7049     csp--;
7050 } /* pop_control_stack() */
7051 
7052 /*-------------------------------------------------------------------------*/
7053 inherit_t *
adjust_variable_offsets(const inherit_t * inheritp,const program_t * prog,const object_t * obj)7054 adjust_variable_offsets ( const inherit_t * inheritp
7055                         , const program_t * prog
7056                         , const object_t  * obj
7057                         )
7058 
7059 /* If we do an explicit call into a virtually inherited base class we
7060  * have to find the first instance of the inherited variables.
7061  * This cannot be done at compile time because it depends on the
7062  * _object_ (i.e. the runtime environment) in which the program
7063  * is running.
7064  *
7065  * <inheritp> is the intended target for the call, <prog> is the
7066  * currently running program, <obj> is the currently used object.
7067  * The result is either NULL if no adjustment is required (then the caller
7068  * has to use the original <inheritp> passed in), or the pointer to the
7069  * inheritance structure to be used.
7070  *
7071  * TODO: A better compiler might do some backpatching and at least
7072  * TODO:: leave hints where the variables are, so that we can omit
7073  * TODO:: the explicite search. Or some load-time patching.
7074  */
7075 {
7076     inherit_t * inh = NULL;
7077 
7078     if (prog != obj->prog
7079      && inheritp->prog->num_variables
7080      && (prog->variables[inheritp->variable_index_offset
7081                          +inheritp->prog->num_variables-1
7082                         ].type.typeflags & TYPE_MOD_VIRTUAL)
7083      && !(inheritp->prog->variables[inheritp->prog->num_variables-1
7084                                    ].type.typeflags & TYPE_MOD_VIRTUAL)
7085        )
7086     {
7087         /* Now search for the first virtual inheritance of the program
7088          * in the inherit list of the topmost program.
7089          * Don't get confused by normal inherits, though.
7090          */
7091 
7092         int i = obj->prog->num_inherited;
7093         inh = obj->prog->inherit;
7094 
7095         while (i)
7096         {
7097             if (inh->prog == inheritp->prog
7098              && obj->prog->variables[inh->variable_index_offset
7099                                      +inh->prog->num_variables-1
7100                                     ].type.typeflags&TYPE_MOD_VIRTUAL
7101                )
7102                 break;
7103             inh++;
7104             i--;
7105         }
7106 
7107         /* i should always be != 0 here, with inh pointing the the
7108          * inherit structure we're looking for.
7109          */
7110 
7111 #ifdef DEBUG
7112         if (!i)
7113         {
7114             char *ts;
7115             ts = time_stamp();
7116             fprintf(stderr,
7117                     "%s Adjusting variable offsets because of virtual "
7118                         "inheritance for call\n"
7119                     "%s from %s into %s (topmost program %s) FAILED.\n"
7120                     "%s Please check the inherit tree and report it.\n"
7121                    , ts, ts
7122                    , get_txt(prog->name)
7123                    , get_txt(inheritp->prog->name)
7124                    , get_txt(obj->prog->name)
7125                    , ts);
7126             inh = NULL;
7127         }
7128 #endif
7129     }
7130 
7131     return inh;
7132 } /* adjust_variable_offsets() */
7133 
7134 /*-------------------------------------------------------------------------*/
7135 static inherit_t *
setup_inherited_call(unsigned short inhIndex)7136 setup_inherited_call (unsigned short inhIndex)
7137 
7138 /* Setup the global variables for a call to an explicitly inherited
7139  * function, inherited from <inhIndex>. Result is the pointer to the
7140  * inherit structure.
7141  */
7142 
7143 {
7144     inherit_t * inheritp = &current_prog->inherit[inhIndex];
7145 
7146 #ifdef DEBUG
7147     if (inhIndex >= current_prog->num_inherited)
7148         errorf("(setup_inherited_call): inhIndex %ld > number of inherits %ld "
7149               "in program '%s'\n"
7150              , (long)inhIndex
7151              , (long)current_prog->num_inherited
7152              , get_txt(current_prog->name)
7153              );
7154 #endif
7155 
7156     /* If we do an explicit call into a virtually inherited base class we
7157      * have to find the first instance of the inherited variables.
7158      * This cannot be done at compile time because it depends on the
7159      * _object_ (i.e. the runtime environment) in which current_prog
7160      * is running.
7161      */
7162     {
7163         inherit_t * inh;
7164 
7165         inh = adjust_variable_offsets(inheritp, current_prog, current_object);
7166         if (inh)
7167         {
7168             /* Found a virtual base class, so un-adjust the offsets. */
7169             inheritp = inh;
7170             current_variables = current_object->variables;
7171             function_index_offset = 0;
7172         }
7173     }
7174 
7175     /* Set the current program to the inherited program so that the
7176      * caller can search for the function.
7177      */
7178     current_prog = inheritp->prog;
7179 
7180     return inheritp;
7181 } /* setup_inherited_call() */
7182 
7183 /*-------------------------------------------------------------------------*/
7184 static INLINE funflag_t
setup_new_frame1(int fx,int fun_ix_offs,int var_ix_offs)7185 setup_new_frame1 (int fx, int fun_ix_offs, int var_ix_offs)
7186 
7187 /* Setup current_prog, function_ and variable_index_offset for a call
7188  * to function index <fx> in the current program.
7189  *
7190  * <fun_ix_offs> and <var_ix_offs> are offsets to be added to the
7191  * functions given offsets - this is necessary when <fx> is given relative
7192  * to some inherited program and needs to be adjusted for the topmost
7193  * program.
7194  *
7195  * Return the 'flags' for the function.
7196  */
7197 
7198 {
7199     program_t *progp;
7200     funflag_t flags;
7201 
7202     progp = current_prog;
7203 
7204     flags = progp->functions[fx];
7205 
7206     /* Handle a cross-define.
7207      * This is a rather rare occasion and usually happens only with functions
7208      * like heart_beat() which are called by function index and not by name.
7209      * This index, determined at compile time, might point to the
7210      * cross-defined function entry.
7211      */
7212     if (flags & NAME_CROSS_DEFINED)
7213     {
7214         fx += CROSSDEF_NAME_OFFSET(flags);
7215         flags = progp->functions[fx];
7216     }
7217 
7218     /* If the function is inherited, find the real function definition
7219      * and adjust the offsets to point to its code and variables.
7220      * This is an iteration walking along the inherit chain.
7221      */
7222     fun_ix_offs += fx;
7223     while (flags & NAME_INHERITED)
7224     {
7225         inherit_t *inheritp;
7226 
7227         inheritp = &progp->inherit[flags & INHERIT_MASK];
7228         progp = inheritp->prog;
7229         fx -= inheritp->function_index_offset;
7230         var_ix_offs += inheritp->variable_index_offset;
7231           /* Remember here that function offset is relative to current_prog,
7232            * but variable_offset is relative to current_object.
7233            */
7234         flags = progp->functions[fx];
7235     }
7236     /* fx is now the 'pure' function index without any offsets */
7237 
7238     /* Setup the variables and return */
7239     current_prog = progp;
7240     function_index_offset = fun_ix_offs - fx;
7241     variable_index_offset = var_ix_offs;
7242 
7243     return flags;
7244 } /* setup_new_frame1() */
7245 
7246 /*-------------------------------------------------------------------------*/
7247 static INLINE svalue_t *
setup_new_frame2(fun_hdr_p funstart,svalue_t * sp,Bool allowRefs,Bool is_lambda)7248 setup_new_frame2 (fun_hdr_p funstart, svalue_t *sp
7249                  , Bool allowRefs, Bool is_lambda)
7250 
7251 /* Before calling the function at <funstart>, massage the data on the
7252  * stack ending at <sp> to match the formal argumentlist of the function
7253  * (excessive args are removed, missing args are provided as 0),
7254  * and allocate the local variables on the stack.
7255  *
7256  * If <allowRefs> is TRUE, references may be passed as extended varargs
7257  * ('(varargs mixed *)'). Currently this is used only for simul efuns.
7258  * TODO: Investigate if holding references in arrays is really such a
7259  * TODO:: a bad thing. Maybe it's just an implementation issue.
7260  * TODO:: This also affects apply_low() and call_lambda().
7261  *
7262  * <is_lambda> has to be TRUE if the function is a lambda closure.
7263  * This information is needed for proper tracing.
7264  *
7265  * csp->num_local_variables is supposed to hold the number of actual
7266  * arguments on the stack.
7267  *
7268  * Result is the new stackpointer, the framepointer <inter_fp>,
7269  * csp->num_local_variables and <break_sp> are set up.
7270  * The context pointer <inter_context> is cleared.
7271  */
7272 
7273 {
7274     int i;        /* Difference between number of formal and actual args;
7275                    * Number of (uninitialized) local variables
7276                    */
7277     int num_arg;  /* Number of formal args */
7278 
7279     /* Setup the frame pointer */
7280     inter_fp = sp - csp->num_local_variables + 1;
7281 
7282 #ifdef USE_NEW_INLINES
7283     /* By default there is no context */
7284     inter_context = NULL;
7285 #endif /* USE_NEW_INLINES */
7286 
7287     /* (Re)move excessive arguments.
7288      * TODO: This code uses that bit7 makes num_arg negative.
7289      */
7290     num_arg = FUNCTION_NUM_ARGS(funstart);
7291     if ((i = csp->num_local_variables - num_arg) > 0)
7292     {
7293         /* More actual than formal args, or the function has
7294          * a 'varargs' argument.
7295          */
7296 
7297         if (num_arg < 0)
7298         {
7299             /* Function has a 'varargs' argument */
7300 
7301             num_arg &= 0x7f;
7302 
7303             if ((i = csp->num_local_variables - num_arg + 1) < 0)
7304             {
7305                 /* More formal than actual parameters. */
7306 
7307                 csp->num_local_variables = num_arg;
7308 
7309                 /* First, fill in zero for the rest... */
7310                 do {
7311                     *++sp = const0;
7312                 } while (++i);
7313 
7314                 /* ...and an empty array for the varargs portion */
7315                 ++sp;
7316                 put_array(sp, allocate_uninit_array(0));
7317             }
7318             else
7319             {
7320                 /* More actual than formal parameters */
7321 
7322                 vector_t *v;
7323 
7324                 csp->num_local_variables = num_arg;
7325 
7326                 /* Move the extra args into an array and put that
7327                  * onto the stack
7328                  */
7329                 v = allocate_uninit_array(i);
7330                 while (--i >= 0)
7331                 {
7332                     if (!allowRefs && sp->type == T_LVALUE)
7333                         num_arg = -1; /* mark error condition */
7334                     v->item[i] = *sp--;
7335                 }
7336 
7337                 ++sp;
7338                 put_array(sp, v);
7339 
7340                 if (num_arg < 0)
7341                 {
7342                     bytecode_p pc = funstart; /* for the ERROR() macro */
7343 
7344                     ERROR("Varargs argument passed by reference.\n");
7345                 }
7346             }
7347         }
7348         else
7349         {
7350             /* Function takes a fixed number of arguments */
7351 
7352             /* Pop the extraneous args */
7353             do {
7354                 free_svalue(sp--);
7355                 csp->num_local_variables--;
7356             } while(--i);
7357 
7358         } /* if(varargs or fixedargs) */
7359 
7360         /* Clear the local variables */
7361 
7362         if ( 0 != (i = FUNCTION_NUM_VARS(funstart)) )
7363         {
7364             csp->num_local_variables += i;
7365             do {
7366                 *++sp = const0;
7367             } while (--i);
7368         }
7369     }
7370     else
7371     {
7372         /* Enough or too little arguments supplied to a fixed-args
7373          * function: initialize the missing args and the locals
7374          * in one swoop.
7375          */
7376 
7377         if ( 0 != (i = FUNCTION_NUM_VARS(funstart) - i) )
7378         {
7379             csp->num_local_variables += i;
7380             do {
7381                 *++sp = const0;
7382             } while (--i);
7383         }
7384     }
7385 
7386     /* Check for stack overflow. Since the actual stack size is
7387      * larger than EVALUATOR_STACK_SIZE, this check at the
7388      * end should be sufficient. If not, stack_overflow() will
7389      * generate a fatal error and we have to resize.
7390      */
7391     if ( sp >= &VALUE_STACK[EVALUATOR_STACK_SIZE] )
7392         stack_overflow(sp, csp->fp, funstart);
7393 
7394     /* Count the call depth for traces and handle tracing */
7395     tracedepth++;
7396     if (TRACEP(TRACE_CALL) && TRACE_IS_INTERACTIVE())
7397     {
7398       inter_sp = sp;
7399       do_trace_call(funstart, is_lambda);
7400     }
7401 
7402 
7403     /* Initialize the break stack, pointing to the entry above
7404      * the first available svalue.
7405      */
7406     break_sp = (bytecode_p *)&sp[1].u.str;
7407 
7408     return sp;
7409 } /* setup_new_frame2() */
7410 
7411 /*-------------------------------------------------------------------------*/
7412 static void
setup_new_frame(int fx,program_t * inhProg)7413 setup_new_frame (int fx, program_t *inhProg)
7414 
7415 /* Setup a call for function <fx> in the current program.
7416  * If <inhProg> is not NULL, it is the program of the inherited function
7417  * to call.
7418  * Result are the flags for the function. Global csp->funstart is set
7419  * to the start of the function bytecode.
7420  */
7421 
7422 {
7423     funflag_t flags;
7424 
7425     if (inhProg)
7426     {
7427         program_t *progp;
7428         int       fun_ix_offs;
7429         int       var_ix_offs;
7430 
7431         progp = current_prog;
7432         fun_ix_offs = 0;
7433         var_ix_offs = 0;
7434 
7435         while (progp != inhProg)
7436         {
7437             inherit_t      *inheritp, *inh;
7438 
7439 #ifdef DEBUG
7440             if (!progp->num_inherited)
7441                 errorf("(setup_new_frame): Couldn't find program '%s' "
7442                        "in program '%s' with function index %ld. "
7443                        "Found program '%s' instead.\n"
7444                      , get_txt(inhProg->name)
7445                      , get_txt(current_prog->name)
7446                      , (long) fx
7447                      , get_txt(progp->name)
7448                      );
7449 #endif
7450             inheritp = search_function_inherit(progp, fx);
7451             fx -= inheritp->function_index_offset;
7452 
7453             inh = adjust_variable_offsets(inheritp, progp, current_object);
7454             if (inh)
7455             {
7456                 /* Virtual base class. Reset offsets. */
7457                 inheritp = inh;
7458                 fun_ix_offs = 0;
7459                 var_ix_offs = 0;
7460             }
7461 
7462             fun_ix_offs += inheritp->function_index_offset;
7463             var_ix_offs += inheritp->variable_index_offset;
7464             progp = inheritp->prog;
7465 
7466 #ifdef DEBUG
7467             if (fx >= progp->num_functions)
7468                 errorf("(setup_new_frame): fx %ld > number of "
7469                        "functions %ld in program '%s'\n"
7470                      , (long) fx
7471                      , (long) progp->num_functions
7472                      , get_txt(progp->name)
7473                      );
7474 #endif
7475         }
7476 
7477         current_prog = inhProg;
7478 
7479         flags = setup_new_frame1(fx, fun_ix_offs, var_ix_offs);
7480     }
7481     else
7482         flags = setup_new_frame1(fx, 0, 0);
7483 
7484     /* Setting csp->funstart is not just convenient, but also
7485      * required for proper error handling in setup_new_frame2()
7486      */
7487     csp->funstart = current_prog->program + (flags & FUNSTART_MASK);
7488 
7489     inter_sp = setup_new_frame2(csp->funstart, inter_sp, MY_FALSE, MY_FALSE);
7490 #ifdef DEBUG
7491     if (!current_object->variables && variable_index_offset)
7492         fatal("%s Fatal: new frame for object %p '%s' w/o variables, "
7493               "but offset %d\n"
7494              , time_stamp(), current_object, get_txt(current_object->name)
7495              , variable_index_offset);
7496 #endif
7497     current_variables = current_object->variables;
7498     if (current_variables)
7499         current_variables += variable_index_offset;
7500     current_strings = current_prog->strings;
7501 } /* setup_new_frame() */
7502 
7503 /*-------------------------------------------------------------------------*/
7504 void
reset_machine(Bool first)7505 reset_machine (Bool first)
7506 
7507 /* Reset the virtual machine. <first> is true on the very first call
7508  * (the cold boot, so to speak). Subsequent calls pass <first> as false
7509  * and this way make sure that all values currently on the stack
7510  * are properly removed.
7511  */
7512 
7513 {
7514     traceing_recursion = -1;
7515     if (first)
7516     {
7517         csp = CONTROL_STACK - 1;
7518         inter_sp = VALUE_STACK - 1;
7519         tracedepth = 0;
7520         put_number(&current_lambda, 0);
7521     }
7522     else
7523     {
7524         inter_sp = _pop_n_elems(inter_sp - VALUE_STACK + 1, inter_sp);
7525         if (current_lambda.type == T_CLOSURE)
7526             free_closure(&current_lambda);
7527         put_number(&current_lambda, 0);
7528         while (csp >= CONTROL_STACK)
7529         {
7530             if (csp->lambda.type == T_CLOSURE)
7531                 free_closure(&csp->lambda);
7532             csp--;
7533         }
7534     }
7535 } /* reset_machine() */
7536 
7537 /*-------------------------------------------------------------------------*/
7538 #ifdef DEBUG
7539 int
check_state(void)7540 check_state (void)
7541 
7542 /* Check the virtual machine for consistency. Return 0 when it is, else
7543  * print a debug message and return an error code.
7544  *
7545  * As this function can be costly, it is by default not called from
7546  * the backend loop.
7547  */
7548 
7549 {
7550     int rc;
7551 
7552     rc = 0;
7553 
7554     if (rt_context->type != ERROR_RECOVERY_BACKEND) {
7555         debug_message("%s rt_context stack inconsistent: type %d instead of %d\n"
7556                      , time_stamp(), rt_context->type, ERROR_RECOVERY_BACKEND);
7557         printf("%s rt_context stack inconsistent: type %d instead of %d\n"
7558               , time_stamp(), rt_context->type, ERROR_RECOVERY_BACKEND);
7559         if (!rc) rc = 1;
7560     }
7561     if (csp != CONTROL_STACK - 1) {
7562         debug_message("%s csp inconsistent: %p instead of %p\n"
7563                      , time_stamp(), csp, CONTROL_STACK-1);
7564         printf("%s csp inconsistent: %p instead of %p\n"
7565               , time_stamp(), csp, CONTROL_STACK-1);
7566         if (!rc) rc = 2;
7567     }
7568     if (inter_sp != VALUE_STACK - 1) {
7569         debug_message("%s sp inconsistent: %p instead of %p\n"
7570                      , time_stamp(), inter_sp, VALUE_STACK - 1);
7571         printf("%s sp inconsistent: %p instead of %p\n"
7572               , time_stamp(), inter_sp, VALUE_STACK - 1);
7573         if (!rc) rc = 3;
7574     }
7575 
7576     return rc;
7577 } /* check_state() */
7578 #endif
7579 
7580 /*-------------------------------------------------------------------------*/
7581 void
free_interpreter_temporaries(void)7582 free_interpreter_temporaries (void)
7583 
7584 /* Free all svalue the interpreter holds in global variables.
7585  * Usually the values are freed whenever a new value is stored, but
7586  * this function allows e.g. the garbage collector to free them all
7587  * at once.
7588 #ifdef TRACE_CODE
7589  * The function also cleans out all destructed objects from the
7590  * instruction trace.
7591 #endif
7592  */
7593 
7594 {
7595     free_protector_svalue(&last_indexing_protector);
7596     last_indexing_protector.type = T_NUMBER;
7597     free_svalue(&indexing_quickfix);
7598     indexing_quickfix.type = T_NUMBER;
7599     free_svalue(&apply_return_value);
7600     apply_return_value.type = T_NUMBER;
7601 
7602 #ifdef TRACE_CODE
7603     {
7604         int i;
7605 
7606         for (i = TOTAL_TRACE_LENGTH; --i >= 0; )
7607         {
7608             object_t *ob;
7609 
7610             if (NULL != (ob = previous_objects[i])
7611              && ob->flags & O_DESTRUCTED
7612                )
7613             {
7614                 free_object(ob, "free_interpreter_temporaries");
7615                 previous_objects[i] = NULL;
7616                 previous_instruction[i] = 0;
7617             }
7618         }
7619     }
7620 #endif
7621 
7622 } /* free_interpreter_temporaries() */
7623 
7624 /*-------------------------------------------------------------------------*/
7625 void
remove_object_from_stack(object_t * ob)7626 remove_object_from_stack (object_t *ob)
7627 
7628 /* Object <ob> was/will be destructed, so remove all references from
7629  * to it from the stack, including references through closures.
7630  */
7631 
7632 {
7633     svalue_t *svp;
7634 
7635     for (svp = VALUE_STACK; svp <= inter_sp; svp++)
7636     {
7637         if (object_ref(svp, ob))
7638         {
7639             free_svalue(svp);
7640             put_number(svp, 0);
7641         }
7642     } /* foreach svp in stack */
7643 } /* remove_object_from_stack() */
7644 
7645 /*-------------------------------------------------------------------------*/
7646 static INLINE void
put_default_argument(svalue_t * sp,int instruction)7647 put_default_argument (svalue_t *sp, int instruction)
7648 
7649 /* Evaluate <instruction> and put it's result into *<sp>.
7650  * This function is used to generate default arguments for efuns at runtime,
7651  * and therefor implements just the instructions F_CONST0, F_CONST1,
7652  * F_NCONST1, F_TIME, F_THIS_OBJECT, and F_THIS_PLAYER.
7653  */
7654 
7655 {
7656     switch(instruction)
7657     {
7658     case F_CONST0:
7659         put_number(sp, 0);
7660         break;
7661 
7662     case F_CONST1:
7663         put_number(sp, 1);
7664         break;
7665 
7666     case F_NCONST1:
7667         put_number(sp, -1);
7668         break;
7669 
7670     case F_TIME:
7671         put_number(sp, current_time);
7672         break;
7673 
7674     case F_THIS_OBJECT:
7675         if (current_object->flags & O_DESTRUCTED)
7676         {
7677             put_number(sp, 0);
7678             break;
7679         }
7680         put_ref_object(sp, current_object, "default: this_object");
7681         break;
7682 
7683     case F_THIS_PLAYER:
7684         if (command_giver && !(command_giver->flags & O_DESTRUCTED))
7685             put_ref_object(sp, command_giver, "default: this_player");
7686         else
7687             put_number(sp, 0);
7688         break;
7689 
7690     default:
7691         fatal("Unimplemented runtime default argument '%s' to %s().\n"
7692              , get_f_name(instruction), get_f_name(complete_instruction(-2))
7693              );
7694         break;
7695     }
7696 } /* put_default_argument() */
7697 
7698 /*-------------------------------------------------------------------------*/
7699 Bool
eval_instruction(bytecode_p first_instruction,svalue_t * initial_sp)7700 eval_instruction (bytecode_p first_instruction
7701                  , svalue_t *initial_sp)
7702 
7703 /* Evaluate the code starting at <first_instruction>, using <inital_sp>
7704  * as the stack pointer.
7705  *
7706  * All other variables like current_prog must be setup before the call.
7707  * The function will return upon encountering a F_RETURN instruction
7708  * for which .extern_call or .catch_call is true, or upon encountering
7709  * a F_END_CATCH instruction.
7710  *
7711  * The result will state the reason for returning: FALSE for F_RETURN,
7712  * and TRUE for F_END_CATCH.
7713  *
7714  * This also means that for every intra-object call eval_instruction()
7715  * is called recursively.
7716  *
7717  * There must not be destructed objects on the stack. The destruct_object()
7718  * function will automatically remove all occurences. The effect is that
7719  * all called efuns know that they won't have destructed objects as
7720  * arguments.
7721  *
7722  * All instructions/functions callable from LPC must return a value or be
7723  * declared void. This does not apply to internal control codes like F_JUMP.
7724  */
7725 
7726 {
7727     register bytecode_p     pc;  /* Current program pointer */
7728     register svalue_t *fp;  /* Current frame pointer */
7729     register svalue_t *sp;  /* Current stack pointer */
7730       /* For speed reasons, these variables shadow their global counterparts,
7731        * allowing more optimisations.
7732        * gcc feels better about setjmp() when variables are declared register.
7733        * Still we might get 'variable foo might be clobbered' warnings, but
7734        * declaring them as volatile would degrade optimization, so we don't.
7735        */
7736     int num_arg;      /* Number of arguments given to the current instr */
7737     int instruction;  /* The current instruction code */
7738     int full_instr;   /* The full instruction code; including any additional
7739                        * code bytes (e.g. for efuns)
7740                        */
7741 #ifdef DEBUG
7742     svalue_t *expected_stack; /* Expected stack at the instr end */
7743 #endif
7744 
7745     svalue_t *ap;
7746       /* Argument frame pointer: pointer to first outgoing argument to be
7747        * passed to called function.
7748        */
7749     Bool use_ap;
7750       /* TRUE if the next simul_efun/efun call is to determine the number of
7751        * arguments from the current *ap value. This variable is static in order
7752        * to survive longjmp()s, its actual scope is just within one execution
7753        * of eval_instruction().
7754        */
7755 
7756 
7757     /* Handy macros:
7758      *
7759      *   GET_NUM_ARG: Get the number of arguments, resp. check if the
7760      *                number was read correctly.
7761      *
7762      *   RAISE_ARG_ERROR(arg,expected,got),
7763      *   OP_ARG_ERROR(arg,expected,got):
7764      *                Argument <arg> had type <got> (LPC type tag), not
7765      *                type <expected> (bit-encoded).
7766      *
7767      *   BAD_ARG_ERROR(arg,expected,got),
7768      *   BAD_OP_ARG(arg,expected,got):
7769      *                Argument <arg> had type <got> (LPC type tag), not
7770      *                type <expected> (LPC type tag).
7771      *
7772      *   TYPE_TEST1/2/3/4(arg, t): Test argument <arg> of a one-byte
7773      *                instruction if it has type <t> (LPC type tag).
7774      *                The 1/2/3/4 is the number of the argument.
7775      *   TYPE_TEST_LEFT(arg, t), TYPE_TEST_RIGHT(arg, t): Test the
7776      *                argument <arg> if it has type <t> (LPC type tag).
7777      *                It is either the left or the right argument to a
7778      *                one-byte operator.
7779      *   TYPE_TEST_EXP_LEFT(arg, t), TYPE_TEST_EXP_RIGHT(arg, t): Test the
7780      *                argument <arg> if it has type <t> (bit-encoded).
7781      *                It is either the left or the right argument to a
7782      *                one-byte operator.
7783      *
7784      */
7785 
7786 #   ifdef DEBUG
7787 #       define GET_NUM_ARG \
7788             if (num_arg != GET_UINT8(pc-1)) {\
7789                 fatal("Argument count error for %s: %d vs. %d.\n", get_f_name(instruction), num_arg, GET_UINT8(pc-1));}
7790         /* The macro catches two faults: getting num_arg for instructions
7791          * which don't take arguments, and getting num_arg after incrementing
7792          * the pc too far.
7793          */
7794 #   else /* DEBUG */
7795 #       define GET_NUM_ARG num_arg = GET_UINT8(pc); inter_pc = ++pc;
7796 #   endif /* DEBUG */
7797       /* Get and/or test the number of arguments.
7798        */
7799 
7800 #   define ARG_ERROR_TEMPL(fun, arg, expected, got) \
7801        do {\
7802            inter_sp = sp; \
7803            inter_pc = pc; \
7804            fun(instruction, arg, expected, got); \
7805        }while(0)
7806 
7807 #   define RAISE_ARG_ERROR(arg, expected, got) \
7808        ARG_ERROR_TEMPL(raise_arg_error, arg, expected, got)
7809 
7810 #   define BAD_ARG_ERROR(arg, expected, got) \
7811        ARG_ERROR_TEMPL(raise_arg_error, arg, 1 << expected, got)
7812 
7813 #   define OP_ARG_ERROR_TEMPL(fun, arg, expected, got) \
7814        do {\
7815            inter_sp = sp; \
7816            inter_pc = pc; \
7817            fun(arg, expected, got, pc, sp); \
7818        }while(0)
7819 
7820 #   define BAD_OP_ARG(arg, expected, got) \
7821        OP_ARG_ERROR_TEMPL(op_arg_error, arg, expected, got)
7822 
7823 #   define OP_ARG_ERROR(arg, expected, got) \
7824        OP_ARG_ERROR_TEMPL(op_exp_arg_error, arg, expected, got)
7825 
7826 #   define TYPE_TEST_TEMPL(num, arg, t) \
7827         if ( (arg)->type != t ) code_arg_error(num, t, (arg)->type, pc, sp); else NOOP;
7828 #   define OP_TYPE_TEST_TEMPL(num, arg, t) \
7829         if ( (arg)->type != t ) op_arg_error(num, t, (arg)->type, pc, sp); else NOOP;
7830 #   define EXP_TYPE_TEST_TEMPL(num, arg, t) \
7831         if (!( (1 << (arg)->type) & (t)) ) op_exp_arg_error(num, (t), (arg)->type, pc, sp); else NOOP;
7832 
7833 #   define TYPE_TEST1(arg, t) TYPE_TEST_TEMPL(1, arg, t)
7834 #   define TYPE_TEST2(arg, t) TYPE_TEST_TEMPL(2, arg, t)
7835 #   define TYPE_TEST3(arg, t) TYPE_TEST_TEMPL(3, arg, t)
7836 #   define TYPE_TEST4(arg, t) TYPE_TEST_TEMPL(4, arg, t)
7837 
7838 #   define TYPE_TEST_LEFT(arg, t)  OP_TYPE_TEST_TEMPL(1, arg, t)
7839 #   define TYPE_TEST_RIGHT(arg, t) OP_TYPE_TEST_TEMPL(2, arg, t)
7840 
7841 #   define TYPE_TEST_EXP_LEFT(arg, t)  EXP_TYPE_TEST_TEMPL(1, arg, t)
7842 #   define TYPE_TEST_EXP_RIGHT(arg, t) EXP_TYPE_TEST_TEMPL(2, arg, t)
7843       /* Test the type of a certain argument.
7844        */
7845 
7846 #   ifdef MARK
7847 #        define CASE(x) case (x): MARK(x);
7848 #   else
7849 #        define CASE(x) case (x):
7850 #   endif
7851       /* Macro to build the case: labels for the evaluator switch.
7852        * 'MARK' adds profiling support.
7853        */
7854 
7855     /* Setup the variables.
7856      * The next F_RETURN at this level will return out of eval_instruction().
7857      */
7858     if (!csp->catch_call)
7859         csp->extern_call = MY_TRUE;
7860     sp = initial_sp;
7861     pc = first_instruction;
7862     fp = inter_fp;
7863     ap = inter_fp; /* so that call_lambda() can call us for efun closures */
7864     use_ap = MY_FALSE;
7865     runtime_no_warn_deprecated = MY_FALSE;
7866     runtime_array_range_check = MY_FALSE;
7867     SET_TRACE_EXEC;
7868 
7869     /* ------ The evaluation loop ------ */
7870 
7871 again:
7872     /* Get the next instruction and increment the pc */
7873 
7874     full_instr = instruction = LOAD_CODE(pc);
7875     if (full_instr == F_EFUN0)
7876         full_instr = GET_CODE(pc) + EFUN0_OFFSET;
7877     else if (full_instr == F_EFUN1)
7878         full_instr = GET_CODE(pc) + EFUN1_OFFSET;
7879     else if (full_instr == F_EFUN2)
7880         full_instr = GET_CODE(pc) + EFUN2_OFFSET;
7881     else if (full_instr == F_EFUN3)
7882         full_instr = GET_CODE(pc) + EFUN3_OFFSET;
7883     else if (full_instr == F_EFUN4)
7884         full_instr = GET_CODE(pc) + EFUN4_OFFSET;
7885     else if (full_instr == F_EFUNV)
7886         full_instr = GET_CODE(pc) + EFUNV_OFFSET;
7887 
7888 #if 0
7889     if (full_instr != instruction)
7890         printf("DEBUG: %p (%p): %3d %s %s\n"
7891               , pc-1, sp
7892               , full_instr, get_f_name(instruction), get_f_name(full_instr));
7893     else
7894         printf("DEBUG: %p (%p): %3d %s\n"
7895               , pc-1, sp
7896               , full_instr, get_f_name(full_instr));
7897     fflush(stdout);
7898 #endif
7899 
7900 #   ifdef TRACE_CODE
7901         /* Store some vitals in the trace buffer */
7902 
7903 #       if TOTAL_TRACE_LENGTH & TOTAL_TRACE_LENGTH-1
7904             if (++last == TOTAL_TRACE_LENGTH)
7905                 last = 0;
7906 #       else
7907             last = (last+1) & (TOTAL_TRACE_LENGTH-1);
7908 #       endif
7909         previous_instruction[last] = instruction;
7910         previous_pc[last] = pc-1;
7911         stack_size[last] = sp - fp - csp->num_local_variables;
7912         abs_stack_size[last] = sp - VALUE_STACK;
7913         if (previous_objects[last])
7914         {
7915             /* Need to free the previously stored object */
7916             free_object(previous_objects[last], "TRACE_CODE");
7917         }
7918         previous_objects[last] = ref_object(current_object, "TRACE_CODE");
7919         previous_programs[last] = current_prog;
7920 #   endif  /* ifdef TRACE_CODE */
7921 
7922 #   ifdef MALLOC_LPC_TRACE
7923         inter_pc = pc;
7924 #   endif
7925 
7926 #   ifdef OPCPROF
7927         opcount[full_instr]++;
7928 #   endif
7929 
7930     /* If requested, trace the instruction.
7931      * Print the name of the instruction, but guard against recursions.
7932      */
7933     if (trace_exec_active && TRACE_EXEC_P && TRACE_IS_INTERACTIVE())
7934     {
7935         if (!++traceing_recursion)
7936         {
7937             inter_sp = sp;
7938             do_trace("Exec ", get_f_name(full_instr), "\n");
7939             instruction = EXTRACT_UCHAR(pc-1);
7940         }
7941         traceing_recursion--;
7942     }
7943 
7944     /* Test the evaluation cost.
7945      * eval_cost < 0 signify a wrap-around - unlikely, but with these crazy
7946      * wizards everything is possible.
7947      */
7948     if (add_eval_cost(1))
7949     {
7950         rt_context_t * context;
7951 
7952         /* Evaluation too long. Restore some globals and throw
7953          * an error.
7954          */
7955 
7956         printf("%s eval_cost too big %ld\n", time_stamp(), (long)eval_cost);
7957 
7958         assign_eval_cost_inl();
7959 
7960         /* If the error isn't caught, reset the eval costs */
7961         for (context = rt_context
7962             ; !ERROR_RECOVERY_CONTEXT(context->type)
7963             ; context = context->last
7964             ) NOOP;
7965         if (context->type <= ERROR_RECOVERY_BACKEND)
7966         {
7967             CLEAR_EVAL_COST;
7968             RESET_LIMITS;
7969         }
7970 
7971         inter_pc = pc;
7972         inter_fp = fp;
7973         ERROR("Too long evaluation. Execution aborted.\n");
7974     }
7975 
7976 #if defined(DEBUG)
7977 
7978     /* Get the expected number of arguments and determined the expected
7979      * stack setting.
7980      * Note that the code deliberately looks at instruction and not
7981      * full_instr, as all multibyte instructions do not store the number
7982      * of arguments in code.
7983      */
7984     if (instrs[instruction].min_arg != instrs[instruction].max_arg
7985      && instruction != F_CALL_OTHER
7986      && instruction != F_CALL_DIRECT
7987        )
7988     {
7989         num_arg = GET_UINT8(pc);
7990         pc++;
7991     }
7992     else
7993     {
7994         /* Safety measure. It is supposed that the evaluator knows
7995          * the number of arguments.
7996          */
7997         num_arg = -1;
7998     }
7999 
8000     if (num_arg != -1 && !use_ap)
8001     {
8002         expected_stack = sp - num_arg +
8003             ( instrs[full_instr].ret_type.typeflags == TYPE_VOID ? 0 : 1 );
8004     }
8005     else if (use_ap)
8006     {
8007         expected_stack = ap -
8008             ( instrs[full_instr].ret_type.typeflags == TYPE_VOID ? 1 : 0 );
8009     }
8010     else
8011     {
8012         expected_stack = NULL;
8013     }
8014 #endif /* DEBUG */
8015 
8016     /* The monster switch to execute the instruction.
8017      * The order of the cases is held (mostly) in the order
8018      * the instructions appear in func_spec.
8019      */
8020     inter_sp = sp;
8021     inter_pc = pc;
8022       /* TODO: This continual update is crude, but circumvents a lot
8023        * TODO:: of situations where an error is thrown but inter_sp
8024        * TODO:: is invalid (heck, every assign_svalue() could cause that). In
8025        * TODO:: the long run, we should do this only for efuns (which are by
8026        * TODO:: then hopefully all tabled).
8027        */
8028     switch(instruction)
8029     {
8030     default:
8031         fatal("Undefined instruction '%s' (%d)\n", get_f_name(instruction),
8032               instruction);
8033         /* NOTREACHED */
8034         return MY_FALSE; /* hint for data flow analysis */
8035 
8036 #ifdef F_ILLEGAL
8037     CASE(F_ILLEGAL);                /* --- illegal             --- */
8038         inter_pc = pc;
8039         fatal("'illegal' instruction encountered.\n");
8040         /* NOTREACHED */
8041 #endif /* F_ILLEGAL */
8042 
8043     CASE(F_UNDEF);                  /* --- undef               --- */
8044       {
8045         /* Catch-all instructions for declared but not implemented
8046          * (defined) functions. Usually used by the compiler to
8047          * handle prototypes (in that case it is the first and only
8048          * instruction of the generated stub), it is also inserted
8049          * into lambda closures when they referenced a function
8050          * that went missing because of a replace_program.
8051          *
8052          * Note: this instruction MUST be the first in the function.
8053          */
8054 
8055         string_t *name;
8056 
8057         /* pc has already been incremented */
8058         if (pc > current_prog->program && pc <= PROGRAM_END(*current_prog))
8059         {
8060             /* Copy the function name pointer into name.
8061              */
8062             memcpy(&name, FUNCTION_NAMEP(FUNCTION_FROM_CODE(pc-1)), sizeof name);
8063         }
8064         else
8065         {
8066             /* It is a lambda closure after a replace_program. */
8067             name = STR_DANGLING_LAMBDA;
8068         }
8069         ERRORF(("Undefined function: %s\n", get_txt(name)));
8070       }
8071 
8072     CASE(F_EFUN0);                  /* --- efun0 <code>        --- */
8073     {
8074         /* Call the tabled efun EFUN0_OFFSET + <code>, where <code> is
8075          * a uint8.
8076          * The efun takes no argument.
8077          */
8078 
8079         int code;
8080 
8081         /* Check the number of arguments on the stack */
8082         if (use_ap)
8083         {
8084             int numarg = sp - ap + 1;
8085 
8086             if (numarg < 0)
8087                 ERRORF(("Not enough args for %s: got %d, expected none.\n"
8088                        , instrs[instruction].name, numarg));
8089             if (numarg > 0)
8090                 ERRORF(("Too many args for %s: got %d, expected none.\n"
8091                        , instrs[instruction].name, numarg));
8092             use_ap = MY_FALSE;
8093         }
8094 
8095         code = LOAD_UINT8(pc);
8096 #ifdef TRACE_CODE
8097         previous_instruction[last] = code + EFUN0_OFFSET;
8098 #endif
8099 #ifdef OPCPROF
8100         opcount[code+EFUN0_OFFSET]++;
8101 #endif
8102         inter_sp = sp;
8103         inter_pc = pc;
8104         assign_eval_cost_inl();
8105         sp = (*efun_table[code+EFUN0_OFFSET-TEFUN_OFFSET])(sp);
8106 #ifdef CHECK_OBJECT_REF
8107         check_all_object_shadows();
8108 #endif /* CHECK_OBJECT_REF */
8109         break;
8110     }
8111 
8112     CASE(F_EFUN1);                  /* --- efun1 <code>        --- */
8113     {
8114         /* Call the tabled efun EFUN1_OFFSET + <code>, where <code> is
8115          * a uint8.
8116          * The efun takes one argument.
8117          */
8118 
8119         int code;
8120 
8121         code = LOAD_UINT8(pc);
8122         instruction = code + EFUN1_OFFSET;
8123 
8124         /* Correct then number of arguments on the stack */
8125         if (use_ap)
8126         {
8127             int numarg = sp - ap + 1;
8128             int def;
8129 
8130             if (numarg == 0 && (def = instrs[instruction].Default) != 0)
8131             {
8132                 put_default_argument(++sp, def);
8133                 numarg++;
8134             }
8135 
8136             if (numarg < 1)
8137                 ERRORF(("Not enough args for %s: got %d, expected 1.\n"
8138                        , instrs[instruction].name, numarg));
8139             if (numarg > 1)
8140                 ERRORF(("Too many args for %s: got %d, expected 1.\n"
8141                        , instrs[instruction].name, numarg));
8142             use_ap = MY_FALSE;
8143         }
8144 
8145 #ifdef TRACE_CODE
8146         previous_instruction[last] = instruction;
8147 #endif
8148 #ifdef OPCPROF
8149         opcount[instruction]++;
8150 #endif
8151         inter_sp = sp;
8152         inter_pc = pc;
8153         assign_eval_cost_inl();
8154         test_efun_args(instruction, 1, sp);
8155         sp = (*efun_table[instruction-TEFUN_OFFSET])(sp);
8156 #ifdef CHECK_OBJECT_REF
8157         check_all_object_shadows();
8158 #endif /* CHECK_OBJECT_REF */
8159         break;
8160     }
8161 
8162     CASE(F_EFUN2);                  /* --- efun2 <code>        --- */
8163     {
8164         /* Call the tabled efun EFUN2_OFFSET + <code>, where <code> is
8165          * a uint8.
8166          * The efun takes two arguments.
8167          */
8168 
8169         int code;
8170 
8171         code = LOAD_UINT8(pc);
8172         instruction = code + EFUN2_OFFSET;
8173 
8174         /* Correct then number of arguments on the stack */
8175         if (use_ap)
8176         {
8177             int numarg = sp - ap + 1;
8178             int def;
8179 
8180             if (numarg == 1 && (def = instrs[instruction].Default) != 0)
8181             {
8182                 put_default_argument(++sp, def);
8183                 numarg++;
8184             }
8185 
8186             if (numarg < 2)
8187                 ERRORF(("Not enough args for %s: got %d, expected 2.\n"
8188                        , instrs[instruction].name, numarg));
8189             if (numarg > 2)
8190                 ERRORF(("Too many args for %s: got %d, expected 2.\n"
8191                        , instrs[instruction].name, numarg));
8192             use_ap = MY_FALSE;
8193         }
8194 
8195 #ifdef TRACE_CODE
8196         previous_instruction[last] = instruction;
8197 #endif
8198 #ifdef OPCPROF
8199         opcount[instruction]++;
8200 #endif
8201         inter_sp = sp;
8202         inter_pc = pc;
8203         assign_eval_cost_inl();
8204         test_efun_args(instruction, 2, sp-1);
8205         sp = (*efun_table[instruction-TEFUN_OFFSET])(sp);
8206 #ifdef CHECK_OBJECT_REF
8207         check_all_object_shadows();
8208 #endif /* CHECK_OBJECT_REF */
8209         break;
8210     }
8211 
8212     CASE(F_EFUN3);                  /* --- efun3 <code>        --- */
8213     {
8214         /* Call the tabled efun EFUN3_OFFSET + <code>, where <code> is
8215          * a uint8.
8216          * The efun takes three arguments.
8217          */
8218 
8219         int code;
8220 
8221         code = LOAD_UINT8(pc);
8222         instruction = code + EFUN3_OFFSET;
8223 
8224         /* Correct then number of arguments on the stack */
8225         if (use_ap)
8226         {
8227             int numarg = sp - ap + 1;
8228             int def;
8229 
8230             if (numarg == 2 && (def = instrs[instruction].Default) != 0)
8231             {
8232                 put_default_argument(++sp, def);
8233                 numarg++;
8234             }
8235 
8236             if (numarg < 3)
8237                 ERRORF(("Not enough args for %s: got %d, expected 3.\n"
8238                        , instrs[instruction].name, numarg));
8239             if (numarg > 3)
8240                 ERRORF(("Too many args for %s: got %d, expected 3.\n"
8241                        , instrs[instruction].name, numarg));
8242             use_ap = MY_FALSE;
8243         }
8244 
8245 
8246 #ifdef TRACE_CODE
8247         previous_instruction[last] = instruction;
8248 #endif
8249 #ifdef OPCPROF
8250         opcount[instruction]++;
8251 #endif
8252         inter_sp = sp;
8253         inter_pc = pc;
8254         assign_eval_cost_inl();
8255         test_efun_args(instruction, 3, sp-2);
8256         sp = (*efun_table[instruction-TEFUN_OFFSET])(sp);
8257 #ifdef CHECK_OBJECT_REF
8258         check_all_object_shadows();
8259 #endif /* CHECK_OBJECT_REF */
8260         break;
8261     }
8262 
8263     CASE(F_EFUN4);                  /* --- efun4 <code>        --- */
8264     {
8265         /* Call the tabled efun EFUN4_OFFSET + <code>, where <code> is
8266          * a uint8.
8267          * The efun takes four arguments.
8268          */
8269 
8270         int code;
8271 
8272         code = LOAD_UINT8(pc);
8273         instruction = code + EFUN4_OFFSET;
8274 
8275         /* Correct then number of arguments on the stack */
8276         if (use_ap)
8277         {
8278             int numarg = sp - ap + 1;
8279             int def;
8280 
8281             if (numarg == 3 && (def = instrs[instruction].Default) != 0)
8282             {
8283                 put_default_argument(++sp, def);
8284                 numarg++;
8285             }
8286 
8287             if (numarg < 4)
8288                 ERRORF(("Not enough args for %s: got %d, expected 4.\n"
8289                        , instrs[instruction].name, numarg));
8290             if (numarg > 4)
8291                 ERRORF(("Too many args for %s: got %d, expected 4.\n"
8292                        , instrs[instruction].name, numarg));
8293             use_ap = MY_FALSE;
8294         }
8295 
8296 #ifdef TRACE_CODE
8297         previous_instruction[last] = instruction;
8298 #endif
8299 #ifdef OPCPROF
8300         opcount[instruction]++;
8301 #endif
8302         inter_sp = sp;
8303         inter_pc = pc;
8304         assign_eval_cost_inl();
8305         test_efun_args(instruction, 4, sp-3);
8306         sp = (*efun_table[instruction-TEFUN_OFFSET])(sp);
8307 #ifdef CHECK_OBJECT_REF
8308         check_all_object_shadows();
8309 #endif /* CHECK_OBJECT_REF */
8310         break;
8311     }
8312 
8313     CASE(F_EFUNV);                  /* --- efunv <code>        --- */
8314     {
8315         /* Call the tabled efun EFUNV_OFFSET + <code>, where <code> is
8316          * a uint8, with the number of arguments determined through the
8317          * ap pointer.
8318          * The number of arguments accepted by the efun is given by the
8319          * .min_arg and .max_arg entries in the instrs[] table.
8320          */
8321 
8322         int code;
8323         int min_arg, max_arg, numarg;
8324 
8325         code = LOAD_UINT8(pc);
8326         instruction = code + EFUNV_OFFSET;
8327 
8328         numarg = sp - ap + 1;
8329         use_ap = MY_FALSE;
8330 
8331 #ifdef TRACE_CODE
8332         previous_instruction[last] = instruction;
8333 #endif
8334 #ifdef OPCPROF
8335         opcount[instruction]++;
8336 #endif
8337 
8338         inter_sp = sp;
8339         inter_pc = pc;
8340         assign_eval_cost_inl();
8341 
8342         min_arg = instrs[instruction].min_arg;
8343         max_arg = instrs[instruction].max_arg;
8344 
8345         if (numarg < min_arg)
8346             ERRORF(("Not enough args for %s: got %d, expected %d.\n"
8347                    , instrs[instruction].name, numarg, min_arg));
8348         if (max_arg >= 0 && numarg > max_arg)
8349             ERRORF(("Too many args for %s: got %d, expected %d.\n"
8350                    , instrs[instruction].name, numarg, max_arg));
8351 
8352         test_efun_args(instruction, max_arg >= 0 ? numarg : min_arg
8353                       , sp-numarg+1);
8354         sp = (*vefun_table[instruction-EFUNV_OFFSET])(sp, numarg);
8355 #ifdef CHECK_OBJECT_REF
8356         check_all_object_shadows();
8357 #endif /* CHECK_OBJECT_REF */
8358         break;
8359     }
8360 
8361     /* --- Predefined functions with counterparts in LPC --- */
8362 
8363     CASE(F_IDENTIFIER);             /* --- identifier <var_ix> --- */
8364         /* Push value of object variable <var_ix>.
8365          * It is possible that it is a variable that points to
8366          * a destructed object. In that case, it has to be replaced by 0.
8367          *
8368          * <var_ix> is a uint8.
8369          */
8370         sp++;
8371         assign_checked_svalue_no_free(sp, find_value((int)(LOAD_UINT8(pc))) );
8372         break;
8373 
8374     CASE(F_STRING);                /* --- string <ix>          --- */
8375     {
8376         /* Push the string current_strings[<ix>] onto the stack,
8377          * <ix> being a (16-Bit) ushort, stored low byte first.
8378          * See also the F_CSTRINGx functions.
8379          */
8380         unsigned short string_number;
8381 
8382         LOAD_SHORT(string_number, pc);
8383         push_ref_string(sp, current_strings[string_number]);
8384         break;
8385     }
8386 
8387     CASE(F_CSTRING3);               /* --- cstring3 <ix>       --- */
8388     {
8389         /* Push the string current_strings[0x3<ix>] onto the stack.
8390          * <ix> is a 8-Bit uint.
8391          */
8392         unsigned int ix = LOAD_UINT8(pc);
8393         push_ref_string(sp, current_strings[ix+0x300]);
8394         break;
8395     }
8396 
8397     CASE(F_CSTRING2);               /* --- cstring2 <ix>       --- */
8398     {
8399         /* Push the string current_strings[0x2<ix>] onto the stack.
8400          * <ix> is a 8-Bit uint.
8401          */
8402         unsigned int ix = LOAD_UINT8(pc);
8403         push_ref_string(sp, current_strings[ix+0x200]);
8404         break;
8405     }
8406 
8407     CASE(F_CSTRING1);               /* --- cstring1 <ix>       --- */
8408     {
8409         /* Push the string current_strings[0x1<ix>] onto the stack.
8410          * <ix> is a 8-Bit uint.
8411          */
8412         unsigned int ix = LOAD_UINT8(pc);
8413         push_ref_string(sp, current_strings[ix+0x100]);
8414         break;
8415     }
8416 
8417     CASE(F_CSTRING0);               /* --- cstring0 <ix>       --- */
8418     {
8419         /* Push the string current_strings[0x0<ix>] onto the stack.
8420          * <ix> is a 8-Bit uint.
8421          */
8422         unsigned int ix = LOAD_UINT8(pc);
8423         push_ref_string(sp, current_strings[ix]);
8424         break;
8425     }
8426 
8427     CASE(F_NUMBER);                 /* --- number <num>        --- */
8428     {
8429         /* Push the number <num> onto the stack.
8430          * <num> is a p_int stored in the host format.
8431          * See also the F_CONSTx functions.
8432          * TODO: It should be rewritten to use the LOAD_ macros (but
8433          * TODO:: then the compiler needs to use them, too.
8434          */
8435         sp++;
8436         sp->type = T_NUMBER;
8437         memcpy(&sp->u.number, pc, sizeof sp->u.number);
8438         pc += sizeof sp->u.number;
8439         break;
8440     }
8441 
8442     CASE(F_CONST0);                 /* --- const0              --- */
8443         /* Push the number 0 onto the stack.
8444          */
8445         push_number(sp, 0);
8446         break;
8447 
8448     CASE(F_CONST1);                 /* --- const1              --- */
8449         /* Push the number 1 onto the stack.
8450          */
8451         push_number(sp, 1);
8452         break;
8453 
8454     CASE(F_NCONST1);                /* --- nconst1             --- */
8455         /* Push the number -1 onto the stack.
8456          */
8457         push_number(sp, -1);
8458         break;
8459 
8460     CASE(F_CLIT);                   /* --- clit <num>          --- */
8461     {
8462         /* Push the number <num> onto the stack.
8463          * <num> is a 8-Bit uint.
8464          */
8465         push_number(sp, (p_int)LOAD_UINT8(pc));
8466         break;
8467     }
8468 
8469     CASE(F_NCLIT);                  /* --- nclit <num>         --- */
8470     {
8471         /* Push the number -<num> onto the stack.
8472          * <num> is a 8-Bit uint.
8473          */
8474         push_number(sp, -(p_int)LOAD_UINT8(pc));
8475         break;
8476     }
8477 
8478     CASE(F_FCONST0);                /* --- fconst0             --- */
8479     {
8480         /* Push the float 0.0 onto the stack.
8481          * The binary format is the one determined by STORE_DOUBLE in
8482          * datatypes.h
8483          * TODO: This code makes heavy assumptions about data sizes and
8484          * TODO:: layout. E.g. there need not be a 16-Bit integral type
8485          * TODO:: available.
8486          * TODO: It should be rewritten to use the LOAD_ macros (but
8487          * TODO:: then the compiler needs to use them, too.
8488          */
8489 
8490         double zero = 0.0;
8491         STORE_DOUBLE_USED
8492 
8493         sp++;
8494         sp->type = T_FLOAT;
8495         STORE_DOUBLE(sp, zero);
8496         break;
8497     }
8498 
8499     CASE(F_FLOAT);                  /* --- float <mant> <exp>  --- */
8500     {
8501         /* Push the float build from <mant> (4 bytes) and <exp> (2 bytes)
8502          * onto the stack. The binary format is the one determined
8503          * by STORE_DOUBLE in datatypes.h
8504          * TODO: This code makes heavy assumptions about data sizes and
8505          * TODO:: layout. E.g. there need not be a 16-Bit integral type
8506          * TODO:: available.
8507          * TODO: short doesn't to be a 16 bit wide type (which the float format
8508          * TODO:: expects). LOAD_INT16 would be nice (change in compiler as well).
8509          */
8510 
8511         int32 mantissa;
8512         short exponent;
8513 
8514         sp++;
8515         sp->type = T_FLOAT;
8516         LOAD_INT32(mantissa, pc);
8517         LOAD_SHORT(exponent, pc);
8518         sp->u.mantissa = mantissa;
8519         sp->x.exponent = exponent;
8520         break;
8521     }
8522 
8523     CASE(F_CLOSURE);            /* --- closure <ix> <inhIndex> --- */
8524 #ifdef USE_NEW_INLINES
8525     CASE(F_CONTEXT_CLOSURE); /* --- context_closure <ix> <vix> <num_ex> <num_im> --- */
8526 #endif /* USE_NEW_INLINES */
8527     {
8528         /* Push the closure value <ix> and <inhIndex> onto the stack.
8529          * Both <ix> and <inhIndex> are uint16, stored low byte first.
8530          *
8531          * For <ix>:
8532          * Values 0xf000..0xffff are efun and simul-efun symbols, the others
8533          * are operators and literals (0xf000 == CLOSURE_EFUN_OFFS)
8534          * Simul-efun symbols (0xf800..0xffff) and true efun symbolx (0xf000..
8535          * 0xf7ff for which instrs[].Default >= 0) are made signed and stored
8536          * as they are. (0xf800 == CLOSURE_SIMUL_EFUN_OFFS)
8537          * Operator symbols (0xf000..0xf7ff for which instrs[].Default == -1)
8538          * are moved into their 0xe800..0xefff range, then made signed and
8539          * stored.
8540          *
8541          * For <inhIndex>:
8542          * If not 0 for lfun closures, it is the (inheritance index + 1)
8543          * of the directly referenced inherited function.
8544 #ifdef USE_NEW_INLINES
8545          *
8546          * If it is a context closure, the context is sized to
8547          * uint16 <num_ex>+<num_in> values, uint16 <num_ex> values
8548          * are taken from the local variables beginning at <vix>,
8549          * uint16 <num_im> values are taken from the stack.
8550 #endif
8551          */
8552 
8553         /* TODO: uint16 */ unsigned short tmp_ushort;
8554         /* TODO: int32 */ int ix;
8555         /* TODO: uint16 */ unsigned short inhIndex;
8556 #ifdef USE_NEW_INLINES
8557         unsigned short explicit_context_size, implicit_context_size;
8558         svalue_t * explicit_context;
8559 #endif /* USE_NEW_INLINES */
8560 
8561         inhIndex = 0;
8562 #ifdef USE_NEW_INLINES
8563         explicit_context_size = implicit_context_size = 0;
8564 #endif /* USE_NEW_INLINES */
8565         LOAD_SHORT(tmp_ushort, pc);
8566 #ifdef USE_NEW_INLINES
8567         if (instruction == F_CONTEXT_CLOSURE)
8568         {
8569             explicit_context = fp + LOAD_UINT8(pc);
8570             LOAD_SHORT(explicit_context_size, pc);
8571             LOAD_SHORT(implicit_context_size, pc);
8572         }
8573         else
8574         {
8575             explicit_context = NULL; /* Makes the compiler happy. */
8576             LOAD_SHORT(inhIndex, pc);
8577         }
8578 #else /* USE_NEW_INLINES */
8579         LOAD_SHORT(inhIndex, pc);
8580 #endif /* USE_NEW_INLINES */
8581 
8582         ix = tmp_ushort;
8583         if (ix < CLOSURE_EFUN_OFFS)
8584         {
8585             sp++;
8586             inter_sp = sp;
8587             inter_pc = pc;
8588 #ifndef USE_NEW_INLINES
8589             closure_literal(sp, ix, inhIndex);
8590 #else /* USE_NEW_INLINES */
8591             closure_literal(sp, ix, inhIndex, explicit_context_size + implicit_context_size);
8592 #endif /* USE_NEW_INLINES */
8593             /* If out of memory, this will set sp to svalue-0 and
8594              * throw an error.
8595              */
8596 
8597 #ifdef USE_NEW_INLINES
8598 #ifdef DEBUG
8599             if (instruction == F_CONTEXT_CLOSURE
8600              && sp->x.closure_type != CLOSURE_LFUN
8601                )
8602                 fatal("(eval_instruction) context_closure used for non-lfun "
8603                       "closure type %d.\n", sp->x.closure_type);
8604 #endif
8605             /* Now copy the context values */
8606             if (explicit_context_size != 0)
8607             {
8608                 unsigned short i;
8609                 svalue_t * context = sp->u.lambda->context;
8610 
8611                 for (i = 0; i < explicit_context_size; i++)
8612                 {
8613                     transfer_svalue_no_free(context+i, explicit_context+i);
8614 
8615                     /* Set it to T_INVALID, as it is still a variable of
8616                      * the function frame and will be freed on return.
8617                      */
8618                     explicit_context[i].type = T_INVALID;
8619                 }
8620             }
8621 
8622             if (implicit_context_size != 0)
8623             {
8624                 unsigned short i;
8625                 svalue_t * arg = sp - implicit_context_size;
8626                 svalue_t * context = sp->u.lambda->context + explicit_context_size;
8627 
8628                 for (i = 0; i < implicit_context_size; i++)
8629                     transfer_svalue_no_free(context+i, arg+i);
8630 
8631                 /* Now move the created closure to the new top of the stack */
8632                 *arg = *sp;
8633                 inter_sp = sp = arg;
8634             }
8635 #endif /* USE_NEW_INLINES */
8636         }
8637         else
8638         {
8639 #ifdef USE_NEW_INLINES
8640 #ifdef DEBUG
8641             if (instruction == F_CONTEXT_CLOSURE)
8642                 fatal("(eval_instruction) context_closure used for non-lfun.\n");
8643 #endif
8644 #endif /* USE_NEW_INLINES */
8645             sp++;
8646             sp->type = T_CLOSURE;
8647             sp->u.ob = ref_object(current_object, "closure");
8648             if (ix >= CLOSURE_SIMUL_EFUN_OFFS)
8649             {
8650                 /* Sefun closure */
8651                 sp->x.closure_type = (short)ix;
8652             }
8653             else
8654             {
8655                 /* Efun or operator closure */
8656                 if (!runtime_no_warn_deprecated
8657                  && instrs[ix - CLOSURE_EFUN_OFFS].deprecated != NULL)
8658                 {
8659                     WARNF(("Warning: %s() is deprecated: %s\n"
8660                           , instrs[ix - CLOSURE_EFUN_OFFS].name
8661                           , instrs[ix - CLOSURE_EFUN_OFFS].deprecated
8662                          ));
8663                 }
8664 
8665                 sp->x.closure_type
8666                   = (short)(  instrs[ix - CLOSURE_EFUN_OFFS].Default == -1
8667                             ? ix + CLOSURE_OPERATOR-CLOSURE_EFUN
8668                             : ix);
8669             }
8670         }
8671         break;
8672     }
8673 
8674     CASE(F_SYMBOL);                 /* --- symbol <ix> <num>   --- */
8675     {
8676         /* Push a symbol of current_strings[<ix>] with <num> quotes
8677          * onto the stack.
8678          * <ix> is a uint16, stored low byte first. <num> is a uint8.
8679          */
8680 
8681         /* TODO: uint16 */ unsigned short string_number;
8682 
8683         LOAD_SHORT(string_number, pc);
8684 
8685         sp++;
8686         sp->type = T_SYMBOL;
8687         sp->x.quotes = LOAD_UINT8(pc);
8688         sp->u.str = ref_mstring(current_strings[string_number]);
8689         break;
8690     }
8691 
8692     CASE(F_DEFAULT_RETURN);         /* --- default_return      --- */
8693         /* Inserted at the end of value-returning function, this instruction
8694          * provides a default 'return 0' in case the programmer forgot about
8695          * it. The instruction also prints a warning so that the code can be
8696          * corrected.
8697          */
8698         warnf("Missing 'return <value>' statement.\n");
8699 
8700         /* Warn only once per missing return and program. */
8701         PUT_UINT8(pc-1, F_RETURN0);
8702         /* FALLTHROUGH */
8703 
8704     CASE(F_RETURN0);                /* --- return0             --- */
8705         /* Return from the function with result value 0.
8706          */
8707         push_number(sp, 0);
8708         /* FALLTHROUGH */
8709 
8710     CASE(F_RETURN);                 /* --- return              --- */
8711     {
8712         /* Return from the function with the result topmost on the stack.
8713          * If this is an .extern_call, eval_instruction()
8714          * is left here.
8715          */
8716 
8717         svalue_t *pResult;  /* Return value on stack */
8718         svalue_t *efp = fp+csp->num_local_variables; /* Expected end of frame */
8719 
8720         pResult = sp;
8721 
8722         /* Remove any intermediate error contexts */
8723         while (csp->catch_call)
8724         {
8725             pop_control_stack();
8726             pop_error_context();
8727         }
8728 
8729         /* The caller might have a yet-unterminated SAVE_ARG_FRAME in
8730          * effect (this can happen in lambda closures, when the subclosure
8731          * to compute an efun argument executes a #'return) - undo them.
8732          */
8733 
8734         while (ap && ap > efp)
8735         {
8736             while (sp > ap)
8737                 free_svalue(--sp);
8738             sp = ap-1;
8739             ap = sp->u.lvalue;
8740         }
8741 
8742         /* Deallocate frame, but not the result value.
8743          */
8744 #ifdef DEBUG
8745         if (efp > sp)
8746             fatal("Bad stack at F_RETURN, %"PRIdMPINT" values too low\n"
8747                  , (mp_int)(efp - sp));
8748         else if (efp < sp)
8749             fatal("Bad stack at F_RETURN, %"PRIdMPINT" values too high\n"
8750                  , (mp_int)(sp - efp));
8751 #endif
8752         while (sp != fp)
8753         {
8754             free_svalue(--sp);
8755         }
8756         *sp = *pResult;
8757 
8758         /* Restore the previous execution context */
8759         if ( NULL != (current_prog = csp->prog) ) /* is 0 when we reach the bottom */
8760         {
8761             current_strings = current_prog->strings;
8762         }
8763 
8764         function_index_offset = csp->function_index_offset;
8765         current_variables     = csp->current_variables;
8766         break_sp = csp->break_sp;
8767 #ifdef USE_NEW_INLINES
8768         inter_context = csp->context;
8769 #endif /* USE_NEW_INLINES */
8770         if (current_lambda.type == T_CLOSURE)
8771             free_closure(&current_lambda);
8772         current_lambda = csp->lambda;
8773 
8774         tracedepth--; /* We leave this level */
8775 
8776         if (csp->extern_call)
8777         {
8778             /* eval_instruction() must be left - setup the globals */
8779 
8780             assign_eval_cost_inl();
8781             current_object = csp->ob;
8782             previous_ob = csp->prev_ob;
8783             inter_pc = csp->pc;
8784             inter_fp = csp->fp;
8785 
8786             if (trace_level)
8787             {
8788                 do_trace_return(sp);
8789                 if (csp == CONTROL_STACK - 2)
8790                     /* TODO: This can't be legal according to ISO C */
8791                     traceing_recursion = -1;
8792             }
8793             csp--;
8794             inter_sp = sp;
8795 #ifdef CHECK_OBJECT_REF
8796             check_all_object_shadows();
8797 #endif /* CHECK_OBJECT_REF */
8798             return MY_FALSE;
8799         }
8800 
8801         /* We stay in eval_instruction() */
8802 
8803         if (trace_level)
8804             do_trace_return(sp);
8805         pc = csp->pc;
8806         fp = csp->fp;
8807         csp--;
8808         break;
8809     }
8810 
8811     CASE(F_BREAK);                  /* --- break               --- */
8812     {
8813         /* Break out of a switch() by pulling the continuation address
8814          * from the break stack.
8815          */
8816 
8817         pc = *break_sp;
8818         break_sp += sizeof(svalue_t)/sizeof(*break_sp);
8819         break;
8820     }
8821 
8822     CASE(F_SWITCH);            /* --- switch <lots of data...> --- */
8823     {
8824         /* The switch()-Statement: pop the topmost value from the stack,
8825          * search it in the given case values and set the pc to the
8826          * associated code. Also push the address of the next instruction
8827          * as break address onto the break stack.
8828          *
8829          * The compiler makes sure that there is always a 'default' case
8830          * and that all execution paths eventually execute a F_BREAK.
8831          *
8832          * The layout created by the LPC compiler is this:
8833          *
8834          *     switch b1 a2 b2 [b3 [b4] ]
8835          *            instructions (sans the first byte 'i0')...
8836          *            l[]
8837          *            [c0 [c1]]
8838          *            a0 a1 i0
8839          *            v*n
8840          *            o*n
8841          *            [d0]
8842          *
8843          * b1 & 0x03 is 0, marking this switch statement as unaligned.
8844          * Since for an efficient search the tables v*n and o*n must be
8845          * 4-Byte aligned (TODO: on some machines 8-Byte), the interpreter
8846          * will on first execution of such a switch align it (using
8847          * closure:align_switch()) by arranging the bytes a0..a2 around
8848          * the tables. The aligned layout is this:
8849          *
8850          *     switch b1 b2 [b3 [b4] ]
8851          *            instructions...
8852          *            l[]
8853          *            [c0 [c1]]            <-- p0 = pc + offset
8854          *            a0..
8855          *            v[]                  <-- tabstart
8856          *            o[]                  <-- end_tab = pc + offset + tablen
8857          *            ..a2                 <-- p1
8858          *            [d0]
8859          *
8860          *  b1 (bits 1..0) = len: the length in bytes needed to store
8861          *        'offset', 'tablen', 'default offset', 'o*n' and the
8862          *        length of lookup tables for table ranges.
8863          *  b1 (bits 7..2) = tablen lo
8864          *  c0 = tablen mid (optional)
8865          *  c1 = tablen hi  (optional)
8866          *  b2 = offset lo
8867          *  b3 = offset med (optional)
8868          *  b4 = offset hi  (optional)
8869          *  a0, a1 = default-case offset lo and med in host byte order
8870          *  d0     = default-case offset hi (optional)
8871          *  a2 'type' (bits 0..4): start position for search (used to index
8872          *                         a table with the real offsets)
8873          *            (bit  5)   : 0: numeric switch , 1: string switch
8874          *            (bits 6..7): in an unaligned switch, the true value
8875          *                         of <len> (b1, bits 1..0).
8876          *  l[]: range lookup table: each <len> bytes, network byte order
8877          *       (numeric switch only)
8878          *  v[]: case values, string_t* or p_int, host byte order
8879          *  o[]: case offsets : each <len> bytes, network byte order
8880          *
8881          * The case value table v[] holds (sorted numerically) all values
8882          * appearing in the case statements, both singular values and range
8883          * bounds. Range bound values (which are inclusive) always appear
8884          * next to each other.
8885          *
8886          * The offset table o[] holds the associated offset with
8887          * this interpretation:
8888          *
8889          *   singular cases: jump destination offsets relative to pc.
8890          *
8891          *   range cases:    the 'offset' for the lower bound is 1, the
8892          *                   offset for the upper bound gives the jump
8893          *                   destination relative to pc.
8894          *
8895          *   lookup ranges:  the 'offset' for the lower bound is 0, the
8896          *                   offset for the upper bound is an offset
8897          *                   pointing into the lookup table.
8898          *                   The real jump offset is then
8899          *                     l[o[i] + <value> - lower-bound].
8900          *
8901          *   The lookup ranges are used for an efficient implementation of
8902          *   sparse ranges like 'case 0: case 2: case 5: ...'.
8903          *
8904          *   TODO: This code still makes too many un-macro'ed mem accesses.
8905          */
8906 
8907         Bool useDefault; /* TRUE: Immediately jump to the default case */
8908         mp_int offset;  /* Length of instruction and range-table area */
8909         mp_int def_offs;  /* Offset to code for the 'default' case */
8910         int tablen; /* Number of single case entries, multiplied by 4 */
8911         int len;    /* Number of bytes per offset/length value (1..3) */
8912         int type;   /* Start position for search */
8913         static int32 off_tab[] = {
8914                 0*sizeof(char*), 0x00001*sizeof(char*), 0x00003*sizeof(char*),
8915           0x00007*sizeof(char*), 0x0000f*sizeof(char*), 0x0001f*sizeof(char*),
8916           0x0003f*sizeof(char*), 0x0007f*sizeof(char*), 0x000ff*sizeof(char*),
8917           0x001ff*sizeof(char*), 0x003ff*sizeof(char*), 0x007ff*sizeof(char*),
8918           0x00fff*sizeof(char*), 0x01fff*sizeof(char*), 0x03fff*sizeof(char*),
8919           0x07fff*sizeof(char*), 0x0ffff*sizeof(char*), 0x1ffff*sizeof(char*),
8920           0x3ffff*sizeof(char*), 0x7ffff*sizeof(char*)
8921         };
8922           /* Start offsets for the binary search for different table sizes.
8923            * This table is indexed by <type> & 0x1f, and the compiler choses
8924            * the start position to be the first power of 2 which is at least
8925            * half the table size. This way the search algorithm only needs
8926            * to check for the upper table end.
8927            * TODO: Is the choice really so?
8928            */
8929         bytecode_p p0;
8930           /* Points after the range lookup tables (initially). */
8931         bytecode_p p1;
8932           /* Points to the table of offsets. */
8933         bytecode_p tabstart;
8934           /* Points to the 'v*n' table of cases */
8935         bytecode_p end_tab;
8936           /* Points to the 'o*n' table of offsets for the cases */
8937         bytecode_p break_addr;
8938           /* Address of the first bytecode after the switch, will be pushed
8939            * onto the break stack.
8940            */
8941         mp_int s;
8942           /* Search value for the lookup, derived from the stack value.
8943            * It is either u.number or the numeric value of u.string.
8944            */
8945         /* TODO: opcode? */ unsigned char *l;
8946           /* Current search pointer into the value table v[] */
8947         mp_int r;
8948           /* Current value retrieved from *<l> */
8949         mp_int d;
8950           /* Half the distance between <l> and the current upper resp. lower
8951            * bound of the search partition
8952            */
8953         /* TODO: opcode? */ unsigned char *p2;
8954           /* For a found case, the pointer into o[] */
8955         mp_int o0, o1;
8956           /* The offsets read from *(p2-1) and *p2, resp. *p2 and *(p2+1) */
8957         int i; /* Temporary */
8958 
8959         /* Extract the basic tablen and len */
8960         tablen = EXTRACT_UCHAR(pc);
8961         if ( !(len = tablen & SWITCH_VALUELEN) )
8962         {
8963             /* Oops, first lets align the switch */
8964             align_switch(pc);
8965             tablen = EXTRACT_UCHAR(pc);
8966             len = tablen & SWITCH_VALUELEN;
8967         }
8968         tablen &= ~SWITCH_VALUELEN;
8969         /* SWITCH_TABLEN_SHIFT is 2, so don't need to do
8970          *   tablen = (tablen >> SWITCH_TABLEN_SHIFT) * 4
8971          */
8972 
8973         /* Get the offset, aka the length of instruction and range table
8974          * part, and let p0 point after them.
8975          */
8976         offset = EXTRACT_UCHAR(pc+1);
8977         if (len > 1)
8978         {
8979             offset += EXTRACT_UCHAR(pc+2) << 8;
8980             if (len > 2)
8981             {
8982                 offset += EXTRACT_UCHAR(pc+3) << 16;
8983             }
8984         }
8985         p0 = pc + offset;
8986 
8987         /* Get the full tablen, aka the number of single case entries,
8988          * and set p1 to point _after_ the offset table 'o*n'.
8989          * The computed formula is
8990          *
8991          *   p1 = p0 + tablen * sizeof(char*) + tablen * len * sizeof(char)
8992          *               (length of v*n)           (length of o*n)
8993          *
8994          * with the code taking into account that the _variable_ tablen
8995          * already comes as 'tablen * sizeof(char*)'.
8996          */
8997         if (len > 1)
8998         {
8999             tablen += *(unsigned char *)(p0++) << 8;
9000             if (len > 2)
9001             {
9002                 tablen += *(unsigned char *)(p0++) << 16;
9003 #if SIZEOF_CHAR_P == 4
9004                 p1 = (unsigned char *)(p0 + (tablen << 1) - (tablen >> 2));
9005             }
9006             else
9007             {
9008                 p1 = (unsigned char *)(p0 + tablen + (tablen >> 1));
9009 #else
9010                 p1 = (unsigned char *)(p0 + tablen + tablen*3/sizeof(p_int) );
9011             }
9012             else
9013             {
9014                 p1 = (unsigned char *)(p0 + tablen + tablen*2/sizeof(p_int) );
9015 #endif
9016             }
9017         }
9018         else
9019         {
9020             p1 = (unsigned char *)(p0 + tablen + tablen / sizeof(p_int) );
9021         }
9022 
9023         /* Gather the 'default offset' and the 'type' from the alignment
9024          * bytes before v[] (pointer to by p0) and the bytes after
9025          * o[] (pointed to by p1).
9026          * Set 'tabstart' to the real start of 'v*n'.
9027          * Set 'break_addr' to the first instruction after the switch.
9028          */
9029 
9030         {
9031             int a, b;
9032             union { unsigned char b[sizeof(p_int)-1]; unsigned short s; } abuf;
9033               /* TODO: Assumes sizeof(p_int)-1 >= sizeof(short) */
9034               /* TODO: Assumes sizeof(p_int) == 4 */
9035               /* TODO: Assumes sizeof(short) == 2 */
9036 
9037             /* Gather the bytes a0..a2 into abuf.b[] */
9038             b = (int)(((p_int)p0-1) & sizeof abuf.b);
9039               /* The number of a-bytes after 'o*n' */
9040             memcpy((char *)abuf.b, p0, sizeof abuf.b);
9041             a = (int)(sizeof abuf.b - b);
9042               /* The number of remaining bytes */
9043             memcpy((char *)(abuf.b + a), (char *)(p1 + a), (size_t)b);
9044             def_offs = abuf.s;
9045             type = abuf.b[2];
9046             if (len > 2)
9047             {
9048                 def_offs += p1[sizeof(p_int)-1] << 16;
9049                 break_addr = p1 + sizeof(p_int);
9050             }
9051             else
9052             {
9053                 break_addr = p1 + sizeof(p_int)-1;
9054             }
9055             tabstart = p0 + a;
9056         }
9057 
9058         /* Set 'end_tab' to point to the 'o*n' table,
9059          * push the break address onto the break stack.
9060          */
9061         end_tab  = tabstart + tablen;
9062         break_sp -= sizeof(svalue_t)/sizeof(*break_sp);
9063         *break_sp = break_addr;
9064 
9065         /* Get the search value from the argument passed on the
9066          * stack. This also does the type checking.
9067          */
9068         useDefault = MY_FALSE;
9069         if (type & SWITCH_TYPE)
9070         {
9071             /* String switch */
9072 
9073             if ( sp->type == T_NUMBER && !sp->u.number )
9074             {
9075                 /* Special case: uninitialized string '0'.
9076                  * Use a magic value for this one.
9077                  */
9078                 s = (mp_int)ZERO_AS_STR_CASE_LABEL;
9079             }
9080             else if ( sp->type == T_STRING )
9081             {
9082                 /* The case strings in the program shared, so whatever
9083                  * string we get on the stack, it must at least have
9084                  * a shared twin to be sensible. Get the address of
9085                  * that twin.
9086                  */
9087                 s = (mp_int)find_tabled(sp->u.str);
9088             }
9089             else
9090             {
9091                 /* Non-string value for string switch: use default */
9092                 useDefault = MY_TRUE;
9093                 s = 0;
9094             }
9095         }
9096         else if (sp->type == T_NUMBER)
9097         {
9098             /* Numeric switch and number given */
9099             s = sp->u.number;
9100         }
9101         else
9102         {
9103             /* Non-number value for numeric switch: use default */
9104             useDefault = MY_TRUE;
9105             s = 0;
9106         }
9107         pop_stack();
9108 
9109         if (useDefault)
9110         {
9111             o1 = def_offs;
9112         }
9113         else
9114         {
9115             /* Setup the binary search:
9116              *   l points roughly into the middle of the table,
9117              *   d is 1/4 of the (assumed) total size of the table
9118              */
9119             i = type & SWITCH_START;
9120             l = tabstart + off_tab[i];
9121             d = (mp_int)((off_tab[i]+sizeof(p_int)) >> 1 & ~(sizeof(p_int)-1));
9122               /* '+sizeof()' to make the off_tab[] value even and non-0 */
9123 
9124             /* Binary search for the value <s> in the table, starting at
9125              * position <l> and first subdivision size <d>.
9126              * The algorithm runs until <d> falls below the size of a case value
9127              * (sizeof(p_int)).
9128              *
9129              * After the loop terminates, o1 will be the jump offset relative
9130              * to the pc, which might be the 'default' offset if the value <s>
9131              * was not found.
9132              */
9133             for(;;)
9134             {
9135                 r = *(p_int*)l; /* Get the case value */
9136 
9137                 if (s < r)
9138                 {
9139 
9140                     /* --- s < r --- */
9141 
9142                     if (d < (mp_int)sizeof(p_int))
9143                     {
9144                         if (!d)
9145                         {
9146                             /* End of search: s not found.
9147                              *
9148                              * Set p2 to the offset matching <l> and retrieve
9149                              * o0 and o1 from there.
9150                              *
9151                              * s might still be in a range, then <l>/<p2> point to
9152                              * the entries for the upper bound.
9153                              */
9154                             p2 =   tabstart + tablen
9155                                  + ((p_int*)l - (p_int*)tabstart)*len;
9156                             o0 = EXTRACT_UCHAR(p2-1);
9157                             o1 = EXTRACT_UCHAR(p2);
9158                             if (len > 1)
9159                             {
9160                                 o0 += EXTRACT_UCHAR(p2-2) << 8;
9161                                 o1 = EXTRACT_UCHAR(p2+1) + (o1 << 8);
9162                                 if (len > 2)
9163                                 {
9164                                     o0 += EXTRACT_UCHAR(p2-3) << 16;
9165                                     o1 = EXTRACT_UCHAR(p2+2) + (o1 << 8);
9166                                 }
9167                             }
9168                             /* Because the pre-table alignment area is in the
9169                              * indexing underflow memory region, we can't make
9170                              * useful predictions on the peeked o0 value in case
9171                              * of underflow.
9172                              */
9173 
9174                             /* Test for a range */
9175 
9176                             if (o0 <= 1 && l > tabstart)
9177                             {
9178                                 /* No indexing underflow: test if s is in range */
9179 
9180                                 r = ((p_int*)l)[-1]; /* the lower bound */
9181                                 if (s >= r)
9182                                 {
9183                                     /* s is in the range */
9184                                     if (!o0)
9185                                     {
9186                                         /* Look up the real jump offset */
9187                                         l = pc + o1 + (s-r) * len;
9188                                         o1 = 0;
9189                                         i = len;
9190                                         do {
9191                                             o1 = (o1 << 8) + *l++;
9192                                         } while (--i);
9193                                         break;
9194                                     }
9195                                     /* o1 holds jump destination */
9196                                     break;
9197                                 }
9198                                 /* s is not in the range */
9199                             }
9200 
9201                             /* <s> not found at all: use 'default' address */
9202                             o1 = def_offs;
9203 
9204                             /* o1 holds jump destination */
9205                             break;
9206                         } /* if (!d) */
9207 
9208                         /* Here is 0 < d < sizeof(p_int).
9209                          * Set d = 0 and finish the loop in the next
9210                          * iteration.
9211                          * TODO: Why the delay?
9212                          */
9213                         d = 0;
9214                     }
9215                     else
9216                     {
9217                         /* Move <l> down and half the partition size <d>. */
9218                         l -= d;
9219                         d >>= 1;
9220                     }
9221                 }
9222                 else if (s > r)
9223                 {
9224 
9225                     /* --- s > r --- */
9226 
9227                     if (d < (mp_int)sizeof(p_int))
9228                     {
9229                         if (!d)
9230                         {
9231                             /* End of search: s not found.
9232                              *
9233                              * Set p2 to the offset matching <l> and retrieve
9234                              * o0 and o1 from there.
9235                              *
9236                              * s might still be in a range, then <l> points to
9237                              * the entry of the lower bound, and <p2> is set to
9238                              * the entry for the upper bound.
9239                              */
9240                             p2 = tabstart + tablen
9241                                  + (((p_int*)l - (p_int*)tabstart) + 1)*len;
9242                             o0 = EXTRACT_UCHAR(p2-1);
9243                             o1 = EXTRACT_UCHAR(p2);
9244                             if (len > 1)
9245                             {
9246                                 o0 += EXTRACT_UCHAR(p2-2) << 8;
9247                                 o1 = EXTRACT_UCHAR(p2+1) + (o1 << 8);
9248                                 if (len > 2)
9249                                 {
9250                                     o0 += EXTRACT_UCHAR(p2-3) << 16;
9251                                     o1 = EXTRACT_UCHAR(p2+2) + (o1 << 8);
9252                                 }
9253                             }
9254 
9255                             /* Test for a range */
9256 
9257                             if (o0 <= 1)
9258                             {
9259                                 /* It is a range. */
9260 
9261                                 if (s <= ((p_int*)l)[1])
9262                                 {
9263                                     /* s is in the range, and r is already correct
9264                                      * (ie the upper bound)
9265                                      */
9266                                     if (!o0)
9267                                     {
9268                                         /* Lookup the real jump offset */
9269                                         l = pc + o1 + (s-r) * len;
9270                                         o1 = 0;
9271                                         i = len;
9272                                         do {
9273                                             o1 = (o1 << 8) + *l++;
9274                                         } while (--i);
9275                                         break;
9276                                     }
9277                                     /* o1 holds jump destination */
9278                                     break;
9279                                 }
9280                                 /* s is not in the range */
9281                             }
9282 
9283                             /* <s> not found at all: use 'default' address */
9284                             o1 = def_offs;
9285 
9286                             /* o1 holds jump destination */
9287                             break;
9288                         } /* !d */
9289 
9290                         /* Here is 0 < d < sizeof(p_int).
9291                          * Set d = 0 and finish the loop in the next
9292                          * iteration.
9293                          * TODO: Why the delay?
9294                          */
9295                         d = 0;
9296                     }
9297                     else
9298                     {
9299                         /* Move <l> up, and half the partition size <d>
9300                          * If this would push l beyond the table, repeat the
9301                          * steps 'move <l> down and half the partition size'
9302                          * until <l> is within the table again.
9303                          */
9304 
9305                         l += d;
9306                         while (l >= end_tab)
9307                         {
9308                             d >>= 1;
9309                             if (d <= (mp_int)sizeof(p_int)/2)
9310                             {
9311                                 /* We can't move l further - finish the loop */
9312                                 l -= sizeof(p_int);
9313                                 d = 0;
9314                                 break;
9315                             }
9316                             l -= d;
9317                         }
9318                         d >>= 1;
9319                     }
9320                 }
9321                 else
9322                 {
9323                     /* --- s == r --- */
9324 
9325                     /* End of search: s found.
9326                      *
9327                      * Set p2 to the offset matching <l> and retrieve
9328                      * o0 and o1 from there.
9329                      *
9330                      * We don't distinguish between a singular case match
9331                      * and a match with an upper range bound, but we have
9332                      * to take extra steps in case <s> matched a lower range
9333                      * bound. In that light, o0 need not be an exact value.
9334                      */
9335                     p2 = tabstart + tablen + ((p_int*)l - (p_int*)tabstart)*len;
9336                     o0 = EXTRACT_UCHAR(p2-1);
9337                     o1 = EXTRACT_UCHAR(p2);
9338                     if (len > 1)
9339                     {
9340                         o0 |= EXTRACT_UCHAR(p2-2);
9341                         o1 = EXTRACT_UCHAR(p2+1) + (o1 << 8);
9342                         if (len > 2)
9343                         {
9344                             o0 |= EXTRACT_UCHAR(p2-3);
9345                             o1 = EXTRACT_UCHAR(p2+2) + (o1 << 8);
9346                         }
9347                     }
9348 
9349                     /* Test if <s> matched the end of a range with a lookup table.
9350                      */
9351                     /* TODO: Does this mean that the compiler never creates
9352                      * TODO:: an ordinary range at the beginning of v[]?
9353                      */
9354                     if (!o0 && l > tabstart)
9355                     {
9356                         r = ((p_int*)l)[-1]; /* the lower bound */
9357                         l = pc + o1 + (s-r) * len;
9358                         o1 = 0;
9359                         i = len;
9360                         do
9361                         {
9362                             o1 = (o1 << 8) + *l++;
9363                         } while (--i);
9364                         /* o1 holds jump destination */
9365                         break;
9366                     }
9367 
9368                     /* Test if <s> matched the start of a range */
9369                     if (o1 <= 1)
9370                     {
9371                         /* Yup. Realign p2 and reget o1 */
9372                         p2 += len;
9373 
9374                         /* Set l to point to the jump offset */
9375                         if (o1)
9376                         {
9377                             /* start of ordinary range */
9378                             l = p2;
9379                         }
9380                         else
9381                         {
9382                             /* start of range with lookup table */
9383                             i = len;
9384                             do {
9385                                 o1 = (o1 << 8) + *p2++;
9386                             } while (--i);
9387                             l = pc + o1;
9388                         }
9389 
9390                         /* Get the jump offset from where <l> points */
9391                         o1 = 0;
9392                         i = len;
9393                         do {
9394                             o1 = (o1 << 8) + *l++;
9395                         } while (--i);
9396 
9397                         /* o1 holds jump destination */
9398                         break;
9399                     }
9400 
9401                     /* At this point, s was a match with a singular case, and
9402                      * o1 already holds the jump destination.
9403                      */
9404                     break;
9405                 }
9406             } /* binary search */
9407         } /* if (useDefault) */
9408 
9409         /* o1 is now the offset to jump to. */
9410         pc += o1;
9411         break;
9412     }
9413 
9414     CASE(F_SSCANF);                 /* --- sscanf <numarg>     --- */
9415     {
9416         /* EFUN sscanf()
9417          *
9418          *   int sscanf(string str, string fmt, mixed var1, mixed var2, ...)
9419          *
9420          * Scanf <str> according to <fmt> and store the resultes in var1...
9421          * The compiler knows that var1... have to be passed as lvalues.
9422          *
9423          * Result is the number of variables assigned.
9424          */
9425         int i;
9426         svalue_t *arg;
9427 
9428         num_arg = LOAD_UINT8(pc);
9429           /* GET_NUM_ARG doesn't work here. Trust me on that. */
9430         inter_sp = sp;
9431         inter_pc = pc;
9432         arg = sp - num_arg + 1;
9433         if (arg[0].type != T_STRING)
9434             BAD_ARG_ERROR(1, T_STRING, arg[0].type);
9435         if (arg[1].type != T_STRING)
9436             BAD_ARG_ERROR(2, T_STRING, arg[1].type);
9437         i = e_sscanf(num_arg, sp);
9438         pop_n_elems(num_arg-1);
9439         free_svalue(sp);
9440         put_number(sp, i);
9441         break;
9442     }
9443 
9444 #ifdef USE_PARSE_COMMAND
9445     CASE(F_PARSE_COMMAND);      /* --- parse_command <numargs> --- */
9446     {
9447         /* EFUN parse_command()
9448          *
9449          *   int parse_command(string cmd, object|object* objs
9450          *                    , string fmt, mixed var1, mixed var2...)
9451          *
9452          * Parse the command <cmd> against <objs> and the format <fmt>
9453          * and assign the parsed values to variables var1....
9454          * The compiler knows that var1... have to be passed as lvalues.
9455          *
9456          * Result is TRUE if the pattern matches, and FALSE if not.
9457          */
9458         int i;
9459         svalue_t *arg;
9460         string_t *str;
9461 
9462         assign_eval_cost_inl();
9463         num_arg = LOAD_UINT8(pc);
9464           /* GET_NUM_ARG doesn't work here either. */
9465         arg = sp - num_arg + 1;
9466         if (arg[0].type != T_STRING)
9467             BAD_ARG_ERROR(1, T_STRING, arg[0].type);
9468         if (arg[1].type != T_OBJECT && arg[1].type != T_POINTER)
9469             RAISE_ARG_ERROR(2, TF_OBJECT|TF_POINTER, arg[1].type);
9470         if (arg[2].type != T_STRING)
9471             BAD_ARG_ERROR(3, T_STRING, arg[2].type);
9472         if (arg[1].type == T_POINTER)
9473             check_for_destr(arg[1].u.vec);
9474 
9475         inter_sp = sp;
9476         inter_pc = pc;
9477 
9478         str = trim_all_spaces(arg[0].u.str);
9479         free_mstring(arg[0].u.str);
9480         arg[0].u.str = str;
9481 
9482         str = trim_all_spaces(arg[2].u.str);
9483         free_mstring(arg[2].u.str);
9484         arg[2].u.str = str;
9485 
9486         i = e_parse_command(arg[0].u.str, &arg[1], arg[2].u.str
9487                            , &arg[3], num_arg-3);
9488         pop_n_elems(num_arg);        /* Get rid of all arguments */
9489         push_number(sp, i ? 1 : 0);      /* Push the result value */
9490         break;
9491     }
9492 #endif /* USE_PARSE_COMMAND */
9493 
9494     CASE(F_LOCAL);                  /* --- local <ix>          --- */
9495 
9496         /* Fetch the value of local variable <ix> and push it
9497          * onto the stack.
9498          */
9499         sp++;
9500         assign_local_svalue_no_free(sp, fp + LOAD_UINT8(pc));
9501         break;
9502 
9503     CASE(F_CATCH);       /* --- catch <flags> <offset> <guarded code> --- */
9504     {
9505         /* catch(...instructions...)
9506          *
9507          * Execute the instructions (max. uint8 <offset> bytes) following the
9508          * catch statement. If an error occurs, or a throw() is executed,
9509          * catch that exception, push the <catch_value> (a global var)
9510          * onto the stack and continue execution at instruction
9511          * <pc>+1+<offset>.
9512          *
9513          * The attributes of the catch are given as uint8 <flags>.
9514          * If CATCH_FLAG_RESERVE is set, the top most stack value denotes
9515          * the eval cost to reserve for the catch handling - it is removed
9516          * from the stack before continuing.
9517          *
9518          * The implementation is such that a control-stack entry is created
9519          * as if the instructions following catch are called as a subroutine
9520          * from <pc>+1+<offset>. Additionally an appropriate error context
9521          * is pushed. This way the error handling will have the VM 'return'
9522          * to the right place automatically.
9523          *
9524          * The last instruction of the guarded code is F_END_CATCH which
9525          * will clean up the control and error stack.
9526          *
9527          * If the actual guarded code is longer than 256 Bytes, the compiler
9528          * will generate appropriate branches:
9529          *
9530          *                  catch 2
9531          *                  branch guarded_code
9532          *                  branch continuation
9533          *    guarded_code: ...
9534          */
9535 
9536         uint offset;
9537         int  flags;
9538         int32 reserve_cost = CATCH_RESERVED_COST;
9539 
9540         /* Get the flags */
9541         flags = LOAD_UINT8(pc);
9542 
9543         if (flags & CATCH_FLAG_RESERVE)
9544         {
9545             if (sp->type != T_NUMBER)
9546             {
9547                 ERRORF(("Illegal 'reserve' type for catch(): got %s, expected number.\n"
9548                        , typename(sp->type)
9549                        ));
9550             }
9551 
9552             if (sp->u.number <= 0)
9553             {
9554                 ERRORF(("Illegal 'reserve' value for catch(): got %"PRIdPINT
9555                         ", expected a positive value.\n"
9556                        , sp->u.number
9557                        ));
9558             }
9559 
9560             reserve_cost = sp->u.number;
9561             sp--;
9562         }
9563         /* Get the offset to the next instruction after the CATCH statement.
9564          */
9565         offset = LOAD_UINT8(pc);
9566 
9567         /* Save the important variables in their global locations */
9568         inter_pc = pc;
9569         inter_sp = sp;
9570         inter_fp = fp;
9571 
9572         /* Perform the catch() */
9573         if (!catch_instruction(flags, offset
9574 #ifndef __INTEL_COMPILER
9575                               , (volatile svalue_t ** volatile) &inter_sp
9576 #else
9577                               , (svalue_t ** volatile) &inter_sp
9578 #endif
9579                               , inter_pc, inter_fp
9580                               , reserve_cost
9581 #ifdef USE_NEW_INLINES
9582                               , inter_context
9583 #endif /* USE_NEW_INLINES */
9584                               )
9585            )
9586         {
9587 #ifdef CHECK_OBJECT_REF
9588             check_all_object_shadows();
9589 #endif /* CHECK_OBJECT_REF */
9590             return MY_FALSE; /* Guarded code terminated with 'return' itself */
9591         }
9592 
9593         /* Restore the important variables */
9594         pc = inter_pc;
9595         sp = inter_sp;
9596         fp = inter_fp;
9597 
9598         /* Not really necessary, but tells gcc to complain less */
9599         ap = NULL; /* Will be restored with a restore_arg_frame */
9600         use_ap = MY_FALSE;
9601         instruction = F_CATCH;
9602         num_arg = -1;
9603 #ifdef DEBUG
9604         expected_stack = NULL;
9605 #endif
9606         break;
9607     }
9608 
9609     CASE(F_INC);                    /* --- inc                 --- */
9610     {
9611         /* void inc (mixed & sp[0])
9612          *
9613          * Increment the (numeric) value designed by the lvalue on top
9614          * of the stack, then remove the lvalue from the
9615          * stack (not free()!, this lvalue is just a copy).
9616          */
9617 
9618         svalue_t *svp;
9619 
9620         /* Get the designated value */
9621         TYPE_TEST1(sp, T_LVALUE);
9622         svp = sp->u.lvalue;
9623 
9624         /* Now increment where we can */
9625         if (svp->type == T_NUMBER)
9626         {
9627             if (svp->u.number == PINT_MAX)
9628             {
9629                 ERRORF(("Numeric overflow: (%"PRIdPINT")++\n",
9630                         svp->u.number));
9631                 /* NOTREACHED */
9632                 break;
9633             }
9634             svp->u.number++;
9635             sp--;
9636             break;
9637         }
9638         else if (svp->type == T_FLOAT)
9639         {
9640             STORE_DOUBLE_USED
9641             double d;
9642 
9643             d = READ_DOUBLE(svp) + 1.0;
9644             if (d < (-DBL_MAX) || d > DBL_MAX)
9645                 ERRORF(("Numeric overflow: (%g)++\n", READ_DOUBLE(svp)));
9646             sp->type = T_FLOAT;
9647             STORE_DOUBLE(svp, d);
9648             sp--;
9649             break;
9650         }
9651         else if (svp->type == T_CHAR_LVALUE)
9652         {
9653             (*svp->u.charp)++;
9654             sp--;
9655             break;
9656         }
9657         else if (svp->type == T_LVALUE
9658               || svp->type == T_PROTECTED_LVALUE)
9659         {
9660             inter_sp = sp;
9661             add_number_to_lvalue(svp, 1, NULL, NULL);
9662             sp--;
9663             break;
9664         }
9665 
9666         ERRORF(("Bad arg to ++: got '%s', expected numeric type.\n"
9667                , typename(svp->type)
9668                ));
9669         break;
9670     }
9671 
9672     CASE(F_DEC);                    /* --- dec                 --- */
9673     {
9674         /* void dec (mixed & sp[0])
9675          *
9676          * Decrement the (numeric) value designed by the lvalue on top
9677          * of the stack, then remove the lvalue from the
9678          * stack (not free()!, this lvalue is just a copy).
9679          */
9680 
9681         svalue_t *svp;
9682 
9683         /* Get the designated value */
9684         TYPE_TEST1(sp, T_LVALUE);
9685         svp = sp->u.lvalue;
9686 
9687         /* Now decrement where we can */
9688         if (svp->type == T_NUMBER)
9689         {
9690             if (svp->u.number == PINT_MIN)
9691             {
9692                 ERRORF(("Numeric overflow: (%"PRIdPINT")--\n",
9693                         svp->u.number));
9694                 /* NOTREACHED */
9695                 break;
9696             }
9697             svp->u.number--;
9698             sp--;
9699             break;
9700         }
9701         else if (svp->type == T_FLOAT)
9702         {
9703             STORE_DOUBLE_USED
9704             double d;
9705 
9706             d = READ_DOUBLE(svp) - 1.0;
9707             if (d < (-DBL_MAX) || d > DBL_MAX)
9708                 ERRORF(("Numeric overflow: (%g)--\n", READ_DOUBLE(svp)));
9709             sp->type = T_FLOAT;
9710             STORE_DOUBLE(svp, d);
9711             sp--;
9712             break;
9713         }
9714         else if (svp->type == T_CHAR_LVALUE)
9715         {
9716             (*svp->u.charp)--;
9717             sp--;
9718             break;
9719         }
9720         else if (svp->type == T_LVALUE
9721               || svp->type == T_PROTECTED_LVALUE)
9722         {
9723             inter_sp = sp;
9724             add_number_to_lvalue(svp, -1,  NULL, NULL);
9725             sp--;
9726             break;
9727         }
9728 
9729         ERRORF(("Bad arg to --: got '%s', expected numeric type.\n"
9730                , typename(svp->type)
9731                ));
9732         break;
9733     }
9734 
9735     CASE(F_POST_INC);               /* --- post_inc            --- */
9736     {
9737         /* mixed post_inc (mixed & sp[0])
9738          *
9739          * Increment the numeric value designated by the lvalue on top
9740          * of the stack, and replace the stack entry with the value
9741          * before the increment. The lvalue itself is simply removed, not
9742          * free()d.
9743          */
9744 
9745         svalue_t *svp;
9746 
9747         /* Get the designated value */
9748         TYPE_TEST1(sp, T_LVALUE);
9749         svp = sp->u.lvalue;
9750 
9751         /* Do the push and increment */
9752         if (svp->type == T_NUMBER)
9753         {
9754             if (svp->u.number == PINT_MAX)
9755             {
9756                 ERRORF(("Numeric overflow: (%"PRIdPINT")++\n",
9757                         svp->u.number));
9758                 /* NOTREACHED */
9759                 break;
9760             }
9761             put_number(sp,  svp->u.number++ );
9762             break;
9763         }
9764         else if (svp->type == T_FLOAT)
9765         {
9766             STORE_DOUBLE_USED
9767             double d;
9768 
9769             d = READ_DOUBLE(svp);
9770             sp->type = T_FLOAT;
9771             STORE_DOUBLE(sp, d);
9772             d += 1.0;
9773             if (d < (-DBL_MAX) || d > DBL_MAX)
9774                 ERRORF(("Numeric overflow: (%g)++\n", READ_DOUBLE(svp)));
9775             STORE_DOUBLE(svp, d);
9776             break;
9777         }
9778         else if (svp->type == T_CHAR_LVALUE)
9779         {
9780             put_number(sp,  (unsigned char)(*svp->u.charp) );
9781             (*svp->u.charp)++;
9782             break;
9783         }
9784         else if (svp->type == T_LVALUE
9785               || svp->type == T_PROTECTED_LVALUE)
9786         {
9787             inter_sp = sp;
9788             add_number_to_lvalue(svp, 1, sp, NULL);
9789             break;
9790         }
9791 
9792         ERRORF(("Bad arg to ++: got '%s', expected numeric type.\n"
9793                , typename(svp->type)
9794                ));
9795         break;
9796     }
9797 
9798     CASE(F_POST_DEC);               /* --- post_dec            --- */
9799     {
9800         /* mixed post_dec (mixed & sp[0])
9801          *
9802          * Decrement the numeric value designated by the lvalue on top
9803          * of the stack, and replace the stack entry with the value
9804          * before the decrement. The lvalue itself is simply removed, not
9805          * free()d.
9806          */
9807 
9808         svalue_t *svp;
9809 
9810         /* Get the designated value */
9811         TYPE_TEST1(sp, T_LVALUE);
9812         svp = sp->u.lvalue;
9813 
9814         /* Do the push and decrement */
9815         if (svp->type == T_NUMBER)
9816         {
9817             if (svp->u.number == PINT_MIN)
9818             {
9819                 ERRORF(("Numeric overflow: (%"PRIdPINT")--\n",
9820                         svp->u.number));
9821                 /* NOTREACHED */
9822                 break;
9823             }
9824             put_number(sp,  svp->u.number-- );
9825             break;
9826         }
9827         else if (svp->type == T_FLOAT)
9828         {
9829             STORE_DOUBLE_USED
9830             double d;
9831 
9832             d = READ_DOUBLE(svp);
9833             sp->type = T_FLOAT;
9834             STORE_DOUBLE(sp, d);
9835             d -= 1.0;
9836             if (d < (-DBL_MAX) || d > DBL_MAX)
9837                 ERRORF(("Numeric overflow: (%g)--\n", READ_DOUBLE(svp)));
9838             STORE_DOUBLE(svp, d);
9839             break;
9840         }
9841         else if (svp->type == T_CHAR_LVALUE)
9842         {
9843             put_number(sp, (unsigned char)(*svp->u.charp) );
9844             (*svp->u.charp)--;
9845             break;
9846         }
9847         else if (svp->type == T_LVALUE
9848               || svp->type == T_PROTECTED_LVALUE)
9849         {
9850             inter_sp = sp;
9851             add_number_to_lvalue(svp, -1, sp, NULL);
9852             break;
9853         }
9854 
9855         ERRORF(("Bad arg to --: got '%s', expected numeric type.\n"
9856                , typename(svp->type)
9857                ));
9858         break;
9859     }
9860 
9861     CASE(F_PRE_INC);                /* --- pre_inc             --- */
9862     {
9863         /* mixed pre_inc (mixed & sp[0])
9864          *
9865          * Increment the numeric value designated by the lvalue on top
9866          * of the stack, and replace the stack entry with the incremented
9867          * value. The lvalue itself is simply removed, not free()d.
9868          */
9869 
9870         svalue_t *svp;
9871 
9872         /* Get the designated value */
9873         TYPE_TEST1(sp, T_LVALUE);
9874         svp = sp->u.lvalue;
9875 
9876         /* Do the increment and push */
9877         if (svp->type == T_NUMBER)
9878         {
9879             if (svp->u.number == PINT_MAX)
9880             {
9881                 ERRORF(("Numeric overflow: ++(%"PRIdPINT")\n",
9882                         svp->u.number));
9883                 /* NOTREACHED */
9884                 break;
9885             }
9886             put_number(sp,  ++(svp->u.number) );
9887             break;
9888         }
9889         else if (svp->type == T_FLOAT)
9890         {
9891             STORE_DOUBLE_USED
9892             double d;
9893 
9894             d = READ_DOUBLE(svp) + 1.0;
9895             if (d < (-DBL_MAX) || d > DBL_MAX)
9896                 ERRORF(("Numeric overflow: ++(%g)\n", READ_DOUBLE(svp)));
9897             sp->type = T_FLOAT;
9898             STORE_DOUBLE(sp, d);
9899             STORE_DOUBLE(svp, d);
9900             break;
9901         }
9902         else if (svp->type == T_CHAR_LVALUE)
9903         {
9904             ++(*svp->u.charp);
9905             put_number(sp,  (unsigned char)(*svp->u.charp) );
9906             break;
9907         }
9908         else if (svp->type == T_LVALUE
9909               || svp->type == T_PROTECTED_LVALUE)
9910         {
9911             inter_sp = sp;
9912             add_number_to_lvalue(svp, 1, NULL, sp);
9913             break;
9914         }
9915 
9916         ERRORF(("Bad arg to ++: got '%s', expected numeric type.\n"
9917                , typename(svp->type)
9918                ));
9919         break;
9920     }
9921 
9922     CASE(F_PRE_DEC);                /* --- pre_dec             --- */
9923     {
9924         /* mixed pre_dec (mixed & sp[0])
9925          *
9926          * Decrement the numeric value designated by the lvalue on top
9927          * of the stack, and replace the stack entry with the decremented
9928          * value. The lvalue itself is simply removed, not free()d.
9929          */
9930 
9931         svalue_t *svp;
9932 
9933         /* Get the designated value */
9934         TYPE_TEST1(sp, T_LVALUE);
9935         svp = sp->u.lvalue;
9936 
9937         /* Do the decrement and push */
9938         if (svp->type == T_NUMBER)
9939         {
9940             if (svp->u.number == PINT_MIN)
9941             {
9942                 ERRORF(("Numeric overflow: --(%"PRIdPINT")\n",
9943                         svp->u.number));
9944                 /* NOTREACHED */
9945                 break;
9946             }
9947             put_number(sp,  --(svp->u.number) );
9948             break;
9949         }
9950         else if (svp->type == T_FLOAT)
9951         {
9952             STORE_DOUBLE_USED
9953             double d;
9954 
9955             d = READ_DOUBLE(svp) - 1.0;
9956             if (d < (-DBL_MAX) || d > DBL_MAX)
9957                 ERRORF(("Numeric overflow: --(%g)\n", READ_DOUBLE(svp)));
9958             sp->type = T_FLOAT;
9959             STORE_DOUBLE(sp, d);
9960             STORE_DOUBLE(svp, d);
9961             break;
9962         }
9963         else if (svp->type == T_CHAR_LVALUE)
9964         {
9965             --(*svp->u.charp);
9966             put_number(sp,  (unsigned char)(*svp->u.charp) );
9967             break;
9968         }
9969         else if (svp->type == T_LVALUE
9970               || svp->type == T_PROTECTED_LVALUE)
9971         {
9972             inter_sp = sp;
9973             add_number_to_lvalue(svp, -1, NULL, sp);
9974             break;
9975         }
9976 
9977         ERRORF(("Bad arg to --: got '%s', expected numeric type.\n"
9978                , typename(svp->type)
9979                ));
9980         break;
9981     }
9982 
9983     CASE(F_LAND);                   /* --- land <offset>       --- */
9984     {
9985         /* If sp[0] is the number 0, leave it on the stack (as result)
9986          * and branch by <offset>.
9987          * Otherwise, pop the value and just continue.
9988          */
9989 
9990         if (sp->type == T_NUMBER)
9991         {
9992             if (sp->u.number == 0)
9993             {
9994                 uint offset = LOAD_UINT8(pc);
9995                 pc += offset;
9996                 break;
9997             }
9998             /* No need to explicitely free_svalue(), it's just a number */
9999         }
10000         else
10001         {
10002             free_svalue(sp);
10003         }
10004         sp--;
10005         pc++;
10006         break;
10007     }
10008 
10009     CASE(F_LOR);                    /* --- lor <offset>        --- */
10010     {
10011         /* If sp[0] is not the number 0, leave it on the stack (as result)
10012          * and branch by <offset>.
10013          * Otherwise, pop the value and just continue.
10014          */
10015 
10016         if (sp->type == T_NUMBER && sp->u.number == 0)
10017             sp--; /* think 'free_svalue(sp--)' here... */
10018         else
10019             pc += GET_UINT8(pc);
10020         pc++;
10021         break;
10022     }
10023 
10024     CASE(F_ASSIGN);                 /* --- assign              --- */
10025     {
10026         /* Assign the value sp[-1] to the value designated by lvalue sp[0].
10027          * The assigned value sp[-1] remains on the stack as result
10028          * (ie. the assign yields a rvalue).
10029          *
10030          * Make sure that complex destinations like arrays are not freed
10031          * before the assignment is complete - see the comments to
10032          * assign_svalue().
10033          */
10034 
10035         svalue_t *dest;
10036 
10037         /* Get the designated lvalue */
10038 #ifdef DEBUG
10039         if (sp->type != T_LVALUE)
10040             FATALF(("Bad left arg to F_ASSIGN: got '%s', expected 'lvalue'.\n"
10041                    , typename(sp->type)
10042                    ));
10043 #endif
10044         dest = sp->u.lvalue;
10045         assign_svalue(dest, sp-1);
10046         sp--;
10047         break;
10048     }
10049 
10050     CASE(F_VOID_ASSIGN);            /* --- void_assign         --- */
10051     {
10052         /* Assign the value sp[-1] to the value designated by lvalue sp[0],
10053          * then remove both values from the stack.
10054          *
10055          * Make sure that complex destinations like arrays are not freed
10056          * before the assignment is complete - see the comments to
10057          * assign_svalue().
10058          */
10059 
10060 #ifdef DEBUG
10061         if (sp->type != T_LVALUE)
10062             FATALF(("Bad left arg to F_VOID_ASSIGN: got '%s', expected 'lvalue'.\n"
10063                    , typename(sp->type)
10064                    ));
10065 #endif
10066         transfer_svalue(sp->u.lvalue, sp-1);
10067         sp -= 2;
10068         break;
10069     }
10070 
10071     CASE(F_ADD);                    /* --- add                 --- */
10072         /* Add sp[0] to sp[-1] (the order is important), pop both
10073          * summands from the stack and push the result.
10074          *
10075          * Possible type combinations:
10076          *   string      + (string,int,float) -> string
10077          *   (int,float) + string             -> string
10078          *   int         + int                -> int
10079          *   float       + (int,float)        -> float
10080          *   int         + float              -> float
10081          *   vector      + vector             -> vector
10082          *   mapping     + mapping            -> mapping
10083          */
10084 
10085         switch ( sp[-1].type )
10086         {
10087 
10088         case T_STRING:
10089             inter_pc = pc;
10090             inter_sp = sp;
10091             switch ( sp->type )
10092             {
10093             case T_STRING:
10094               {
10095                 string_t *left, *right, *res;
10096 
10097                 left = (sp-1)->u.str;
10098                 right = sp->u.str;
10099 
10100                 DYN_STRING_COST(mstrsize(left) + mstrsize(right))
10101                 res = mstr_add(left, right);
10102                 if (!res)
10103                     ERRORF(("Out of memory (%zu bytes)\n"
10104                            , mstrsize(left) + mstrsize(right)
10105                            ));
10106                 free_string_svalue(sp);
10107                 sp--;
10108                 free_string_svalue(sp);
10109                 put_string(sp, res);
10110                 break;
10111               }
10112 
10113             case T_NUMBER:
10114               {
10115                 string_t *left, *res;
10116                 char buff[80];
10117                 size_t len;
10118 
10119                 left = (sp-1)->u.str;
10120                 buff[sizeof(buff)-1] = '\0';
10121                 sprintf(buff, "%"PRIdPINT, sp->u.number);
10122                 if (buff[sizeof(buff)-1] != '\0')
10123                     FATAL("Buffer overflow in F_ADD: int number too big.\n");
10124                 len = mstrsize(left)+strlen(buff);
10125                 DYN_STRING_COST(len)
10126                 res = mstr_add_txt(left, buff, strlen(buff));
10127                 if (!res)
10128                     ERRORF(("Out of memory (%zu bytes)\n", len ));
10129                 pop_n_elems(2);
10130                 push_string(sp, res);
10131                 break;
10132               }
10133 
10134             case T_FLOAT:
10135               {
10136                 char buff[160];
10137                 string_t *left, *res;
10138                 size_t len;
10139 
10140                 left = (sp-1)->u.str;
10141                 buff[sizeof(buff)-1] = '\0';
10142                 sprintf(buff, "%g", READ_DOUBLE( sp ) );
10143                 if (buff[sizeof(buff)-1] != '\0')
10144                     FATAL("Buffer overflow in F_ADD: float number too big.\n");
10145                 len = mstrsize(left)+strlen(buff);
10146                 DYN_STRING_COST(len)
10147                 res = mstr_add_txt(left, buff, strlen(buff));
10148                 if (!res)
10149                     ERRORF(("Out of memory (%zu bytes)\n", len));
10150                 sp--;
10151                 free_string_svalue(sp);
10152                 put_string(sp, res);
10153                 break;
10154               }
10155 
10156             default:
10157                 OP_ARG_ERROR(2, TF_STRING|TF_FLOAT|TF_NUMBER, sp->type);
10158                 /* NOTREACHED */
10159             }
10160             break;
10161             /* End of case T_STRING */
10162 
10163           case T_NUMBER:
10164             switch ( sp->type )
10165             {
10166             case T_STRING:
10167               {
10168                 char buff[80];
10169                 string_t *right, *res;
10170                 size_t len;
10171 
10172                 right = sp->u.str;
10173                 buff[sizeof(buff)-1] = '\0';
10174                 sprintf(buff, "%"PRIdPINT, (sp-1)->u.number);
10175                 if (buff[sizeof(buff)-1] != '\0')
10176                     FATAL("Buffer overflow in F_ADD: int number too big.\n");
10177                 len = mstrsize(right)+strlen(buff);
10178                 DYN_STRING_COST(len)
10179                 res = mstr_add_to_txt(buff, strlen(buff), right);
10180                 if (!res)
10181                     ERRORF(("Out of memory (%zu bytes)\n", len));
10182                 free_string_svalue(sp);
10183                 sp--;
10184                 /* Overwrite the number at sp */
10185                 put_string(sp, res);
10186                 break;
10187               }
10188 
10189             case T_NUMBER:
10190               {
10191                 p_int i;
10192                 p_int right = sp->u.number;
10193                 p_int left = (sp-1)->u.number;
10194 
10195                 if ((left >= 0 && right >= 0 && PINT_MAX - left < right)
10196                  || (left < 0 && right < 0 && PINT_MIN - left > right)
10197                    )
10198                 {
10199                     ERRORF(("Numeric overflow: %"PRIdPINT" + %"PRIdPINT"\n"
10200                            , left, right));
10201                     /* NOTREACHED */
10202                     break;
10203                 }
10204                 i = left + right;
10205                 sp--;
10206                 sp->u.number = i;
10207                 break;
10208               }
10209 
10210             case T_FLOAT:
10211               {
10212                 STORE_DOUBLE_USED
10213                 double sum;
10214 
10215                 sum = (double)((sp-1)->u.number) + READ_DOUBLE(sp);
10216                 if (sum < (-DBL_MAX) || sum > DBL_MAX)
10217                     ERRORF(("Numeric overflow: %"PRIdPINT" + %g\n"
10218                            , (sp-1)->u.number, READ_DOUBLE(sp)));
10219                 STORE_DOUBLE(sp-1, sum);
10220                 sp--;
10221                 sp->type = T_FLOAT;
10222                 break;
10223               }
10224 
10225             default:
10226                 OP_ARG_ERROR(2, TF_STRING|TF_FLOAT|TF_NUMBER, sp->type);
10227                 /* NOTREACHED */
10228             }
10229             break;
10230             /* End of case T_NUMBER */
10231 
10232         case T_FLOAT:
10233           {
10234             STORE_DOUBLE_USED
10235             double sum;
10236 
10237             if (sp->type == T_FLOAT)
10238             {
10239                 sum = READ_DOUBLE(sp-1) + READ_DOUBLE(sp);
10240                 if (sum < (-DBL_MAX) || sum > DBL_MAX)
10241                     ERRORF(("Numeric overflow: %g + %g\n"
10242                            , READ_DOUBLE(sp-1), READ_DOUBLE(sp)));
10243                 STORE_DOUBLE(sp-1, sum);
10244                 sp--;
10245                 break;
10246             }
10247             if (sp->type == T_NUMBER)
10248             {
10249                 sum = READ_DOUBLE(sp-1) + (double)(sp->u.number);
10250                 if (sum < (-DBL_MAX) || sum > DBL_MAX)
10251                     ERRORF(("Numeric overflow: %g + %"PRIdPINT"\n"
10252                            , READ_DOUBLE(sp-1), sp->u.number));
10253                 STORE_DOUBLE(sp-1, sum);
10254                 sp--;
10255                 break;
10256             }
10257             if (sp->type == T_STRING)
10258             {
10259                 char buff[160];
10260                 string_t *right, *res;
10261                 size_t len;
10262 
10263                 right = sp->u.str;
10264                 buff[sizeof(buff)-1] = '\0';
10265                 sprintf(buff, "%g", READ_DOUBLE(sp-1) );
10266                 if (buff[sizeof(buff)-1] != '\0')
10267                     FATAL("Buffer overflow in F_ADD: float number too big.\n");
10268                 len = mstrsize(right)+strlen(buff);
10269                 DYN_STRING_COST(len)
10270                 res = mstr_add_to_txt(buff, strlen(buff), right);
10271                 if (!res)
10272                     ERRORF(("Out of memory (%zu bytes)\n", len));
10273                 free_string_svalue(sp);
10274                 sp--;
10275                 /* Overwrite the number at sp */
10276                 put_string(sp, res);
10277                 break;
10278             }
10279             OP_ARG_ERROR(2, TF_STRING|TF_FLOAT|TF_NUMBER, sp->type);
10280             /* NOTREACHED */
10281           }
10282           /* End of case T_FLOAT */
10283 
10284         case T_POINTER:
10285           {
10286             TYPE_TEST_RIGHT(sp, T_POINTER);
10287             inter_sp = sp;
10288             inter_pc = pc;
10289             DYN_ARRAY_COST(VEC_SIZE(sp->u.vec)+VEC_SIZE(sp[-1].u.vec));
10290             inter_add_array(sp->u.vec, &(sp-1)->u.vec);
10291             sp--;
10292             break;
10293           }
10294 
10295         case T_MAPPING:
10296           {
10297             mapping_t *m;
10298 
10299             TYPE_TEST_RIGHT(sp, T_MAPPING);
10300             check_map_for_destr((sp-1)->u.map);
10301             check_map_for_destr(sp->u.map);
10302               /* required for add_mapping() */
10303             inter_pc = pc;
10304             inter_sp = sp;
10305             m = add_mapping((sp-1)->u.map,sp->u.map);
10306             if (!m) {
10307                 ERROR("Out of memory.\n");
10308             }
10309             pop_n_elems(2);
10310             push_mapping(sp, m);
10311             if ((max_mapping_size && MAP_TOTAL_SIZE(m) > (p_int)max_mapping_size)
10312              || (max_mapping_keys && MAP_SIZE(m) > (p_int)max_mapping_keys)
10313                )
10314             {
10315                 check_map_for_destr(m);
10316                 if (max_mapping_size && MAP_TOTAL_SIZE(m) > (p_int)max_mapping_size)
10317                     ERRORF(("Illegal mapping size: %"PRIdPINT
10318                             " elements (%"PRIdPINT" x %"PRIdPINT")\n"
10319                            , MAP_TOTAL_SIZE(m), MAP_SIZE(m), m->num_values));
10320 
10321                 if (max_mapping_keys && MAP_SIZE(m) > (p_int)max_mapping_keys)
10322                     ERRORF(("Illegal mapping size: %"PRIdPINT" entries\n",
10323                             MAP_SIZE(m)));
10324             }
10325             break;
10326           }
10327 
10328         default:
10329             OP_ARG_ERROR(1, TF_POINTER|TF_MAPPING|TF_STRING|TF_FLOAT|TF_NUMBER
10330                           , sp[-1].type);
10331             /* NOTREACHED */
10332         }
10333 
10334         break;
10335 
10336     CASE(F_SUBTRACT);               /* --- subtract            --- */
10337     {
10338         /* Subtract sp[0] from sp[-1] (the order is important), pop both
10339          * arguments from the stack and push the result.
10340          *
10341          * Possible type combinations:
10342          *   int         - int                -> int
10343          *   float       - (int,float)        -> float
10344          *   int         - float              -> float
10345          *   string      - string             -> string
10346          *   vector      - vector             -> vector
10347          *   mapping     - mapping            -> mapping
10348          */
10349 
10350         p_int i;
10351 
10352         if ((sp-1)->type == T_NUMBER)
10353         {
10354             if (sp->type == T_NUMBER)
10355             {
10356                 p_int left = (sp-1)->u.number;
10357                 p_int right = sp->u.number;
10358 
10359                 if ((left >= 0 && right < 0 && PINT_MAX + right < left)
10360                  || (left < 0 && right >= 0 && PINT_MIN + right > left)
10361                    )
10362                 {
10363                     ERRORF(("Numeric overflow: %"PRIdPINT" - %"PRIdPINT"\n"
10364                            , left, right));
10365                     /* NOTREACHED */
10366                     break;
10367                 }
10368 
10369                 i = left - right;
10370                 sp--;
10371                 sp->u.number = i;
10372                 break;
10373             }
10374             if (sp->type == T_FLOAT)
10375             {
10376                 STORE_DOUBLE_USED
10377                 double diff;
10378 
10379                 diff = (double)((sp-1)->u.number) - READ_DOUBLE(sp);
10380                 if (diff < (-DBL_MAX) || diff > DBL_MAX)
10381                     ERRORF(("Numeric overflow: %"PRIdPINT" - %g\n"
10382                            , (sp-1)->u.number, READ_DOUBLE(sp)));
10383                 sp--;
10384                 STORE_DOUBLE(sp, diff);
10385                 sp->type = T_FLOAT;
10386                 break;
10387             }
10388             OP_ARG_ERROR(2, TF_FLOAT|TF_NUMBER, sp->type);
10389             /* NOTREACHED */
10390         }
10391         else if ((sp-1)->type == T_FLOAT)
10392         {
10393             STORE_DOUBLE_USED
10394             double diff;
10395 
10396             if (sp->type == T_FLOAT)
10397             {
10398                 diff = READ_DOUBLE(sp-1) - READ_DOUBLE(sp);
10399                 if (diff < (-DBL_MAX) || diff > DBL_MAX)
10400                     ERRORF(("Numeric overflow: %g - %g\n"
10401                            , READ_DOUBLE(sp-1), READ_DOUBLE(sp)));
10402                 sp--;
10403                 STORE_DOUBLE(sp, diff);
10404                 break;
10405             }
10406             if (sp->type == T_NUMBER)
10407             {
10408                 diff = READ_DOUBLE(sp-1) - (double)(sp->u.number);
10409                 if (diff < (-DBL_MAX) || diff > DBL_MAX)
10410                     ERRORF(("Numeric overflow: %g - %"PRIdPINT"\n"
10411                            , READ_DOUBLE(sp-1), sp->u.number));
10412                 sp--;
10413                 STORE_DOUBLE(sp, diff);
10414                 break;
10415             }
10416             OP_ARG_ERROR(2, TF_FLOAT|TF_NUMBER, sp->type);
10417             /* NOTREACHED */
10418         }
10419         else if ((sp-1)->type == T_POINTER)
10420         {
10421             vector_t *v;
10422 
10423             TYPE_TEST_RIGHT(sp, T_POINTER);
10424             v = sp->u.vec;
10425             if (v->ref > 1)
10426             {
10427                 deref_array(v);
10428                 v = slice_array(v, 0, (mp_int)VEC_SIZE(v) - 1 );
10429             }
10430             sp--;
10431             /* subtract_array already takes care of destructed objects */
10432             sp->u.vec = subtract_array(sp->u.vec, v);
10433             break;
10434         }
10435         else if ((sp-1)->type == T_MAPPING)
10436         {
10437             mapping_t *m;
10438 
10439             TYPE_TEST_RIGHT(sp, T_MAPPING);
10440             m = subtract_mapping(sp[-1].u.map, sp->u.map);
10441             free_mapping(sp->u.map);
10442             sp--;
10443             free_mapping(sp->u.map);
10444             sp->u.map = m;
10445             break;
10446         }
10447         else if ((sp-1)->type == T_STRING)
10448         {
10449             string_t * result;
10450 
10451             TYPE_TEST_RIGHT(sp, T_STRING);
10452             inter_sp = sp;
10453             result = intersect_strings((sp-1)->u.str, sp->u.str, MY_TRUE);
10454             free_string_svalue(sp);
10455             sp--;
10456             free_string_svalue(sp);
10457             put_string(sp, result);
10458             break;
10459         }
10460 
10461         OP_ARG_ERROR(1, TF_POINTER|TF_MAPPING|TF_STRING|TF_FLOAT|TF_NUMBER
10462                       , sp[-1].type);
10463         /* NOTREACHED */
10464     }
10465 
10466     CASE(F_MULTIPLY);               /* --- multiply            --- */
10467     {
10468         /* Multiply sp[-1] by sp[0] pop both arguments from the stack
10469          * and push the result.
10470          * TODO: Could be extended to cover mappings.
10471          * TODO:: array/string multiplied by element === implode.
10472          *
10473          * Possible type combinations:
10474          *   int         * int                -> int
10475          *   float       * (int,float)        -> float
10476          *   int         * float              -> float
10477          *   string      * int                -> string
10478          *   int         * string             -> string
10479          *   array       * int                -> array
10480          *   int         * array              -> array
10481          */
10482 
10483         p_int i;
10484 
10485         switch ( sp[-1].type )
10486         {
10487         case T_NUMBER:
10488             if (sp->type == T_NUMBER)
10489             {
10490                 p_int left = (sp-1)->u.number;
10491                 p_int right = sp->u.number;
10492 
10493                 if (left > 0 && right > 0)
10494                 {
10495                     if ((left != 0 && PINT_MAX / left < right)
10496                      || (right != 0 && PINT_MAX / right < left)
10497                        )
10498                     {
10499                         ERRORF(("Numeric overflow: %"PRIdPINT" * %"PRIdPINT"\n"
10500                                , left, right));
10501                         /* NOTREACHED */
10502                         break;
10503                     }
10504                 }
10505                 else if (left < 0 && right < 0)
10506                 {
10507                     if ((left != 0 && PINT_MAX / left > right)
10508                      || (right != 0 && PINT_MAX / right > left)
10509                        )
10510                     {
10511                         ERRORF(("Numeric overflow: %"PRIdPINT
10512                                 " * %"PRIdPINT"\n"
10513                                , left, right));
10514                         /* NOTREACHED */
10515                         break;
10516                     }
10517                 }
10518                 else if (left != 0 && right != 0)
10519                 {
10520                     if ((left > 0 && PINT_MIN / left > right)
10521                      || (right > 0 && PINT_MIN / right > left)
10522                        )
10523                     {
10524                         ERRORF(("Numeric overflow: %"PRIdPINT
10525                                 " * %"PRIdPINT"\n"
10526                                , left, right));
10527                         /* NOTREACHED */
10528                         break;
10529                     }
10530                 }
10531                 i = left * right;
10532                 sp--;
10533                 sp->u.number = i;
10534                 break;
10535             }
10536             if (sp->type == T_FLOAT)
10537             {
10538                 STORE_DOUBLE_USED
10539                 double product;
10540 
10541                 product = (sp-1)->u.number * READ_DOUBLE(sp);
10542                 if (product < (-DBL_MAX) || product > DBL_MAX)
10543                     ERRORF(("Numeric overflow: %"PRIdPINT" * %g\n"
10544                            , (sp-1)->u.number, READ_DOUBLE(sp)));
10545                 sp--;
10546                 STORE_DOUBLE(sp, product);
10547                 sp->type = T_FLOAT;
10548                 break;
10549             }
10550             if (sp->type == T_STRING)
10551             {
10552                 string_t * result;
10553                 size_t slen;
10554 
10555                 if (sp[-1].u.number < 0)
10556                     ERROR("Bad right arg to *: negative number.\n");
10557 
10558                 slen = mstrsize(sp->u.str);
10559                 if (slen > (size_t)PINT_MAX
10560                  || (   slen != 0
10561                      && PINT_MAX / (p_int)slen < sp[-1].u.number)
10562                  || (   sp[-1].u.number != 0
10563                      && PINT_MAX / sp[-1].u.number < (p_int)slen)
10564                    )
10565                     ERRORF(("Result string too long (%zu * %"PRIdPINT").\n"
10566                            , slen, sp[-1].u.number
10567                            ));
10568 
10569                 result = mstr_repeat(sp->u.str, (size_t)sp[-1].u.number);
10570                 if (!result)
10571                     ERRORF(("Out of memory (%"PRIdPINT" bytes).\n"
10572                            , (p_int)mstrsize(sp->u.str) * sp[-1].u.number));
10573 
10574                 DYN_STRING_COST(mstrsize(result))
10575                 free_svalue(sp);
10576                 sp--;
10577                 /* No free_svalue(sp): it's just a number */
10578                 put_string(sp, result);
10579                 break;
10580             }
10581             if (sp->type == T_POINTER)
10582             {
10583                 vector_t *result;
10584                 mp_int reslen;
10585                 size_t len;
10586 
10587                 if (sp[-1].u.number < 0)
10588                     ERROR("Bad right arg to *: negative number.\n");
10589 
10590                 inter_sp = sp;
10591                 inter_pc = pc;
10592                 len = VEC_SIZE(sp->u.vec);
10593                 reslen = sp[-1].u.number * (mp_int)len;
10594                 result = allocate_uninit_array(reslen);
10595                 DYN_ARRAY_COST(reslen);
10596 
10597                 if (sp[-1].u.number > 0 && len)
10598                 {
10599                     size_t left;
10600                     svalue_t *from, *to;
10601 
10602                     /* Seed result[] with one copy of the array.
10603                      */
10604                     for ( from = sp->u.vec->item, to = result->item, left = len
10605                         ; left
10606                         ; from++, to++, left--)
10607                     {
10608                         assign_svalue_no_free(to, from);
10609                     } /* for() seed */
10610 
10611                     /* Now fill the remainder of the vector with
10612                      * the values already copied in there.
10613                      */
10614                     for (from = result->item, left = reslen - len
10615                         ; left
10616                         ; to++, from++, left--
10617                         )
10618                         assign_svalue_no_free(to, from);
10619                 } /* if (len) */
10620 
10621                 free_svalue(sp);
10622                 sp--;
10623                 /* No free_svalue(sp): it's just a number */
10624                 put_array(sp, result);
10625                 break;
10626             }
10627             OP_ARG_ERROR(2, TF_POINTER|TF_STRING|TF_FLOAT|TF_NUMBER
10628                           , sp->type);
10629             /* NOTREACHED */
10630         case T_FLOAT:
10631           {
10632             STORE_DOUBLE_USED
10633             double product;
10634 
10635             if (sp->type == T_FLOAT)
10636             {
10637                 product = READ_DOUBLE(sp-1) * READ_DOUBLE(sp);
10638                 if (product < (-DBL_MAX) || product > DBL_MAX)
10639                     ERRORF(("Numeric overflow: %g * %g\n"
10640                            , READ_DOUBLE(sp-1), READ_DOUBLE(sp)));
10641                 STORE_DOUBLE(sp-1, product);
10642                 sp--;
10643                 break;
10644             }
10645             if (sp->type == T_NUMBER)
10646             {
10647                 product = READ_DOUBLE(sp-1) * sp->u.number;
10648                 if (product < (-DBL_MAX) || product > DBL_MAX)
10649                     ERRORF(("Numeric overflow: %g * %"PRIdPINT"\n"
10650                            , READ_DOUBLE(sp-1), sp->u.number));
10651                 STORE_DOUBLE(sp-1, product);
10652                 sp--;
10653                 break;
10654             }
10655             OP_ARG_ERROR(2, TF_FLOAT|TF_NUMBER, sp->type);
10656             /* NOTREACHED */
10657           }
10658         case T_STRING:
10659           {
10660             if (sp->type == T_NUMBER)
10661             {
10662                 string_t * result;
10663                 size_t slen;
10664 
10665                 if (sp->u.number < 0)
10666                     ERROR("Bad left arg to *: negative number.\n");
10667 
10668                 slen = mstrsize(sp[-1].u.str);
10669                 if (slen > (size_t)PINT_MAX
10670                  || (   slen != 0
10671                      && PINT_MAX / (p_int)slen < sp->u.number)
10672                  || (   sp->u.number != 0
10673                      && PINT_MAX / sp->u.number < (p_int)slen)
10674                    )
10675                     ERRORF(("Result string too long (%"PRIdPINT" * %zu).\n"
10676                            , sp->u.number, slen));
10677 
10678                 result = mstr_repeat(sp[-1].u.str, (size_t)sp->u.number);
10679                 if (!result)
10680                     ERRORF(("Out of memory (%"PRIdMPINT" bytes).\n"
10681                            , (mp_int)mstrsize(sp[-1].u.str) * sp->u.number));
10682 
10683                 DYN_STRING_COST(mstrsize(result))
10684 
10685                 /* No free_svalue(sp): it's just a number */
10686                 sp--;
10687                 free_string_svalue(sp);
10688                 put_string(sp, result);
10689                 break;
10690             }
10691             BAD_OP_ARG(2, T_NUMBER, sp->type);
10692             /* NOTREACHED */
10693           }
10694         case T_POINTER:
10695           {
10696             if (sp->type == T_NUMBER)
10697             {
10698                 vector_t *result;
10699                 mp_int reslen;
10700                 size_t len;
10701 
10702                 if (sp->u.number < 0)
10703                     ERROR("Bad left arg to *: negative number.\n");
10704 
10705                 inter_sp = sp;
10706                 inter_pc = pc;
10707                 len = VEC_SIZE(sp[-1].u.vec);
10708                 reslen = sp->u.number * (mp_int)len;
10709                 result = allocate_uninit_array(reslen);
10710 
10711                 if (sp->u.number > 0 && len)
10712                 {
10713                     size_t left;
10714                     svalue_t *from, *to;
10715 
10716                     /* Seed result[] with one copy of the array.
10717                      */
10718                     for ( from = sp[-1].u.vec->item, to = result->item, left = len
10719                         ; left
10720                         ; from++, to++, left--)
10721                     {
10722                         assign_svalue_no_free(to, from);
10723                     } /* for() seed */
10724 
10725                     /* Now fill the remainder of the vector with
10726                      * the values already copied in there.
10727                      */
10728                     for (from = result->item, left = reslen - len
10729                         ; left
10730                         ; to++, from++, left--
10731                         )
10732                         assign_svalue_no_free(to, from);
10733                 } /* if (len) */
10734 
10735                 /* No free_svalue(sp): it's just a number */
10736                 sp--;
10737                 free_svalue(sp);
10738                 put_array(sp, result);
10739                 break;
10740               }
10741             BAD_OP_ARG(2, T_NUMBER, sp->type);
10742             /* NOTREACHED */
10743           }
10744         default:
10745             OP_ARG_ERROR(1, TF_POINTER|TF_STRING|TF_FLOAT|TF_NUMBER
10746                           , sp[-1].type);
10747             /* NOTREACHED */
10748         }
10749         break;
10750     }
10751 
10752     CASE(F_DIVIDE);                 /* --- divide              --- */
10753     {
10754         /* Divide sp[-1] by sp[0] pop both arguments from the stack
10755          * and push the result.
10756          * TODO: Could be extended to cover arrays and mappings.
10757          * TODO:: array/string divided by element === explode.
10758          *
10759          * Possible type combinations:
10760          *   int         / int                -> int
10761          *   float       / (int,float)        -> float
10762          *   int         / float              -> float
10763          */
10764 
10765         p_int i;
10766 
10767         if ((sp-1)->type == T_NUMBER)
10768         {
10769             if (sp->type == T_NUMBER) {
10770                 if (sp->u.number == 0)
10771                     ERROR("Division by zero\n");
10772                 if ((sp-1)->u.number == PINT_MIN && sp->u.number == -1)
10773                     ERRORF(("Numeric overflow: %"PRIdPINT" / -1\n"
10774                            , (sp-1)->u.number
10775                            ));
10776                 i = (sp-1)->u.number / sp->u.number;
10777                 sp--;
10778                 sp->u.number = i;
10779                 break;
10780             }
10781             if (sp->type == T_FLOAT)
10782             {
10783                 double dtmp;
10784                 STORE_DOUBLE_USED
10785 
10786                 dtmp = READ_DOUBLE( sp );
10787                 if (dtmp == 0.)
10788                     ERROR("Division by zero\n");
10789                 sp--;
10790                 dtmp = (double)sp->u.number / dtmp;
10791                 if (dtmp < (-DBL_MAX) || dtmp > DBL_MAX)
10792                     ERRORF(("Numeric overflow: %"PRIdPINT" / %g\n"
10793                            , (sp)->u.number, READ_DOUBLE(sp+1)));
10794                 STORE_DOUBLE(sp, dtmp);
10795                 sp->type = T_FLOAT;
10796                 break;
10797             }
10798             OP_ARG_ERROR(2, TF_FLOAT|TF_NUMBER, sp->type);
10799             /* NOTREACHED */
10800         }
10801         else if ((sp-1)->type == T_FLOAT)
10802         {
10803             double dtmp;
10804             STORE_DOUBLE_USED
10805 
10806             if (sp->type == T_FLOAT)
10807             {
10808                 dtmp = READ_DOUBLE( sp );
10809                 if (dtmp == 0.) {
10810                     ERROR("Division by zero\n");
10811                     return MY_FALSE;
10812                 }
10813                 sp--;
10814                 dtmp = READ_DOUBLE(sp) / dtmp;
10815                 if (dtmp < (-DBL_MAX) || dtmp > DBL_MAX)
10816                     ERRORF(("Numeric overflow: %g / %g\n"
10817                            , READ_DOUBLE(sp), READ_DOUBLE(sp+1)));
10818                 STORE_DOUBLE(sp, dtmp);
10819                 break;
10820             }
10821             if (sp->type == T_NUMBER)
10822             {
10823                 if (sp->u.number == 0) {
10824                     ERROR("Division by zero\n");
10825                     return MY_FALSE;
10826                 }
10827                 dtmp = (double)sp->u.number;
10828                 sp--;
10829                 dtmp = READ_DOUBLE(sp) / dtmp;
10830                 if (dtmp < (-DBL_MAX) || dtmp > DBL_MAX)
10831                     ERRORF(("Numeric overflow: %g / %"PRIdPINT"\n"
10832                            , READ_DOUBLE(sp), (sp+1)->u.number));
10833                 STORE_DOUBLE(sp, dtmp);
10834                 break;
10835             }
10836             OP_ARG_ERROR(2, TF_FLOAT|TF_NUMBER, sp->type);
10837             /* NOTREACHED */
10838         }
10839         OP_ARG_ERROR(1, TF_FLOAT|TF_NUMBER, sp[-1].type);
10840         /* NOTREACHED */
10841         break;
10842     }
10843 
10844     CASE(F_MOD);                    /* --- mod                 --- */
10845     {
10846         /* Compute sp[-1] modulus sp[0] pop both arguments from the stack
10847          * and push the result.
10848          * TODO: Could be extended to cover floats(!), arrays and mappings.
10849          * TODO: Define properly and add the rem operation.
10850          *
10851          * Possible type combinations:
10852          *   int         % int                -> int
10853          */
10854 
10855         int i;
10856 
10857         TYPE_TEST_LEFT((sp-1), T_NUMBER);
10858         TYPE_TEST_RIGHT(sp, T_NUMBER);
10859         if (sp->u.number == 0)
10860         {
10861             ERROR("Modulus by zero.\n");
10862             break;
10863         }
10864         else if (sp->u.number == 1
10865               || sp->u.number == -1
10866                 )
10867             i = 0;
10868               /* gcc 2.91 on Linux/x86 generates buggy code
10869                * for MIN_INT % -1. Might as well catch it all.
10870                */
10871         else
10872             i = (sp-1)->u.number % sp->u.number;
10873         sp--;
10874         sp->u.number = i;
10875         break;
10876     }
10877 
10878     CASE(F_GT);                     /* --- gt                  --- */
10879     {
10880         /* Test if sp[-1] > sp[0]. If yes, push 1 onto the stack,
10881          * else 0 (of course after popping both arguments).
10882          *
10883          * Comparable types are int, string and float, each only
10884          * to its own type.
10885          */
10886 
10887         int i;
10888 
10889         if ((sp-1)->type == T_STRING && sp->type == T_STRING)
10890         {
10891             i = mstrcmp((sp-1)->u.str, sp->u.str) > 0;
10892             free_string_svalue(sp);
10893             sp--;
10894             free_string_svalue(sp);
10895             put_number(sp, i);
10896             break;
10897         }
10898 
10899         if ((sp-1)->type == T_NUMBER && sp->type == T_NUMBER)
10900         {
10901             i = (sp-1)->u.number > sp->u.number;
10902             sp--;
10903             sp->u.number = i;
10904             break;
10905         }
10906 
10907         if ((sp-1)->type == T_FLOAT && sp->type == T_FLOAT)
10908         {
10909             i = READ_DOUBLE( sp-1 ) > READ_DOUBLE( sp );
10910             sp--;
10911             put_number(sp, i);
10912             break;
10913         }
10914 
10915         if ((sp-1)->type == T_NUMBER && sp->type == T_FLOAT)
10916         {
10917             i = (double)((sp-1)->u.number) > READ_DOUBLE( sp );
10918             sp--;
10919             put_number(sp, i);
10920             break;
10921         }
10922 
10923         if ((sp-1)->type == T_FLOAT && sp->type == T_NUMBER)
10924         {
10925             i = READ_DOUBLE( sp-1 ) > (double)(sp->u.number);
10926             sp--;
10927             put_number(sp, i);
10928             break;
10929         }
10930 
10931         TYPE_TEST_EXP_LEFT((sp-1), TF_NUMBER|TF_STRING|TF_FLOAT);
10932         TYPE_TEST_EXP_RIGHT(sp, TF_NUMBER|TF_STRING|TF_FLOAT);
10933         ERRORF(("Arguments to > don't match: %s vs %s\n"
10934                , typename(sp[-1].type), typename(sp->type)
10935                ));
10936     }
10937 
10938     CASE(F_GE);                     /* --- ge                  --- */
10939     {
10940         /* Test if sp[-1] >= sp[0]. If yes, push 1 onto the stack,
10941          * else 0 (of course after popping both arguments).
10942          *
10943          * Comparable types are int, string and float, each only
10944          * to its own type.
10945          */
10946 
10947         int i;
10948 
10949         if ((sp-1)->type == T_STRING && sp->type == T_STRING)
10950         {
10951             i = mstrcmp((sp-1)->u.str, sp->u.str) >= 0;
10952             free_string_svalue(sp);
10953             sp--;
10954             free_string_svalue(sp);
10955             put_number(sp, i);
10956             break;
10957         }
10958 
10959         if ((sp-1)->type == T_NUMBER && sp->type == T_NUMBER)
10960         {
10961             i = (sp-1)->u.number >= sp->u.number;
10962             sp--;
10963             sp->u.number = i;
10964             break;
10965         }
10966 
10967         if ((sp-1)->type == T_FLOAT && sp->type == T_FLOAT)
10968         {
10969             i = READ_DOUBLE( sp-1 ) >= READ_DOUBLE( sp );
10970             sp--;
10971             put_number(sp, i);
10972             break;
10973         }
10974 
10975         if ((sp-1)->type == T_NUMBER && sp->type == T_FLOAT)
10976         {
10977             i = (double)((sp-1)->u.number) >= READ_DOUBLE( sp );
10978             sp--;
10979             put_number(sp, i);
10980             break;
10981         }
10982 
10983         if ((sp-1)->type == T_FLOAT && sp->type == T_NUMBER)
10984         {
10985             i = READ_DOUBLE( sp-1 ) >= (double)(sp->u.number);
10986             sp--;
10987             put_number(sp, i);
10988             break;
10989         }
10990 
10991         TYPE_TEST_EXP_LEFT((sp-1), TF_NUMBER|TF_STRING|TF_FLOAT);
10992         TYPE_TEST_EXP_RIGHT(sp, TF_NUMBER|TF_STRING|TF_FLOAT);
10993         ERRORF(("Arguments to >= don't match: %s vs %s\n"
10994                , typename(sp[-1].type), typename(sp->type)
10995                ));
10996     }
10997 
10998     CASE(F_LT);                     /* --- lt                  --- */
10999     {
11000         /* Test if sp[-1] < sp[0]. If yes, push 1 onto the stack,
11001          * else 0 (of course after popping both arguments).
11002          *
11003          * Comparable types are int, string and float, each only
11004          * to its own type.
11005          */
11006 
11007         int i;
11008 
11009         if ((sp-1)->type == T_STRING && sp->type == T_STRING)
11010         {
11011             i = mstrcmp((sp-1)->u.str, sp->u.str) < 0;
11012             free_string_svalue(sp);
11013             sp--;
11014             free_string_svalue(sp);
11015             put_number(sp, i);
11016             break;
11017         }
11018 
11019         if ((sp-1)->type == T_NUMBER && sp->type == T_NUMBER)
11020         {
11021             i = (sp-1)->u.number < sp->u.number;
11022             sp--;
11023             sp->u.number = i;
11024             break;
11025         }
11026 
11027         if ((sp-1)->type == T_FLOAT && sp->type == T_FLOAT)
11028         {
11029             i = READ_DOUBLE( sp-1 ) < READ_DOUBLE( sp );
11030             sp--;
11031             put_number(sp, i);
11032             break;
11033         }
11034 
11035         if ((sp-1)->type == T_NUMBER && sp->type == T_FLOAT)
11036         {
11037             i = (double)((sp-1)->u.number) < READ_DOUBLE( sp );
11038             sp--;
11039             put_number(sp, i);
11040             break;
11041         }
11042 
11043         if ((sp-1)->type == T_FLOAT && sp->type == T_NUMBER)
11044         {
11045             i = READ_DOUBLE( sp-1 ) < (double)(sp->u.number);
11046             sp--;
11047             put_number(sp, i);
11048             break;
11049         }
11050 
11051         TYPE_TEST_EXP_LEFT((sp-1), TF_NUMBER|TF_STRING|TF_FLOAT);
11052         TYPE_TEST_EXP_RIGHT(sp, TF_NUMBER|TF_STRING|TF_FLOAT);
11053         ERRORF(("Arguments to < don't match: %s vs %s\n"
11054                , typename(sp[-1].type), typename(sp->type)
11055                ));
11056     }
11057 
11058     CASE(F_LE);                     /* --- le                  --- */
11059     {
11060         /* Test if sp[-1] <= sp[0]. If yes, push 1 onto the stack,
11061          * else 0 (of course after popping both arguments).
11062          *
11063          * Comparable types are int, string and float, each only
11064          * to its own type.
11065          */
11066 
11067         int i;
11068 
11069         if ((sp-1)->type == T_STRING && sp->type == T_STRING)
11070         {
11071             i = mstrcmp((sp-1)->u.str, sp->u.str) <= 0;
11072             free_string_svalue(sp);
11073             sp--;
11074             free_string_svalue(sp);
11075             put_number(sp, i);
11076             break;
11077         }
11078 
11079         if ((sp-1)->type == T_NUMBER && sp->type == T_NUMBER)
11080         {
11081             i = (sp-1)->u.number <= sp->u.number;
11082             sp--;
11083             sp->u.number = i;
11084             break;
11085         }
11086 
11087         if ((sp-1)->type == T_FLOAT && sp->type == T_FLOAT)
11088         {
11089             i = READ_DOUBLE( sp-1 ) <= READ_DOUBLE( sp );
11090             sp--;
11091             put_number(sp, i);
11092             break;
11093         }
11094 
11095         if ((sp-1)->type == T_NUMBER && sp->type == T_FLOAT)
11096         {
11097             i = (double)((sp-1)->u.number) <= READ_DOUBLE( sp );
11098             sp--;
11099             put_number(sp, i);
11100             break;
11101         }
11102 
11103         if ((sp-1)->type == T_FLOAT && sp->type == T_NUMBER)
11104         {
11105             i = READ_DOUBLE( sp-1 ) <= (double)(sp->u.number);
11106             sp--;
11107             put_number(sp, i);
11108             break;
11109         }
11110 
11111         TYPE_TEST_EXP_LEFT((sp-1), TF_NUMBER|TF_STRING|TF_FLOAT);
11112         TYPE_TEST_EXP_RIGHT(sp, TF_NUMBER|TF_STRING|TF_FLOAT);
11113         ERRORF(("Arguments to <= don't match: %s vs %s\n"
11114                , typename(sp[-1].type), typename(sp->type)
11115                ));
11116     }
11117 
11118     CASE(F_EQ);                     /* --- eq                  --- */
11119     {
11120         /* Test if sp[-1] == sp[0]. If yes, push 1 onto the stack,
11121          * else 0 (of course after popping both arguments).
11122          *
11123          * Comparable types are all types, each to its own. Comparisons
11124          * between distinct types (except between int and float) always
11125          * yield 'unequal'.
11126          * Vectors and mappings are compared by ref only.
11127          */
11128 
11129         int i = 0;
11130 
11131         if ((sp-1)->type == T_NUMBER && sp->type == T_FLOAT)
11132         {
11133             i = (double)((sp-1)->u.number) == READ_DOUBLE( sp );
11134         }
11135         else if ((sp-1)->type == T_FLOAT && sp->type == T_NUMBER)
11136         {
11137             i = READ_DOUBLE( sp-1 ) == (double)(sp->u.number);
11138         }
11139         else if ((sp-1)->type != sp->type)
11140         {
11141             i = 0;
11142         }
11143         else /* type are equal */
11144         {
11145             switch(sp->type)
11146             {
11147             case T_NUMBER:
11148                 i = (sp-1)->u.number == sp->u.number;
11149                 break;
11150             case T_POINTER:
11151                 i = (sp-1)->u.vec == sp->u.vec;
11152                 break;
11153 #ifdef USE_STRUCTS
11154             case T_STRUCT:
11155                 i = (sp-1)->u.strct == sp->u.strct;
11156                 if (!i && struct_size((sp-1)->u.strct) == 0
11157                        && struct_size(sp->u.strct) == 0
11158                    )
11159                 {
11160                     i = 1;
11161                 }
11162                 break;
11163 #endif
11164             case T_STRING:
11165                 i = mstreq((sp-1)->u.str, sp->u.str);
11166                 break;
11167             case T_OBJECT:
11168                 i = (sp-1)->u.ob == sp->u.ob;
11169                 break;
11170             case T_FLOAT:
11171                 i = READ_DOUBLE( sp-1 ) == READ_DOUBLE( sp );
11172                 break;
11173 
11174             case T_CLOSURE:
11175                 i = closure_eq(sp-1, sp);
11176                 break;
11177 
11178             case T_SYMBOL:
11179             case T_QUOTED_ARRAY:
11180                 i = (sp-1)->u.generic  == sp->u.generic &&
11181                     (sp-1)->x.generic == sp->x.generic;
11182                 break;
11183             case T_MAPPING:
11184                 i = (sp-1)->u.map == sp->u.map;
11185                 break;
11186             default:
11187                 if (sp->type == T_LVALUE)
11188                     errorf("Reference passed to ==\n");
11189                 FATALF(("Illegal type '%s' to ==\n",typename(sp->type)));
11190                 /* NOTREACHED */
11191                 return MY_FALSE;
11192             }
11193         }
11194 
11195         pop_stack();
11196         free_svalue(sp);
11197         put_number(sp, i);
11198         break;
11199     }
11200 
11201     CASE(F_NE);                     /* --- ne                  --- */
11202     {
11203         /* Test if sp[-1] != sp[0]. If yes, push 1 onto the stack,
11204          * else 0 (of course after popping both arguments).
11205          *
11206          * Comparable types are all types, each to its own. Comparisons
11207          * between distinct types (except between int and float) always
11208          * yield 'unequal'.
11209          * Vectors and mappings are compared by ref only.
11210          */
11211 
11212         int i = 0;
11213 
11214         if ((sp-1)->type == T_NUMBER && sp->type == T_FLOAT)
11215         {
11216             i = (double)((sp-1)->u.number) != READ_DOUBLE( sp );
11217         }
11218         else if ((sp-1)->type == T_FLOAT && sp->type == T_NUMBER)
11219         {
11220             i = READ_DOUBLE( sp-1 ) != (double)(sp->u.number);
11221         }
11222         else if ((sp-1)->type != sp->type)
11223         {
11224             i = 1;
11225         }
11226         else /* type are equal */
11227         {
11228             switch(sp->type)
11229             {
11230             case T_NUMBER:
11231                 i = (sp-1)->u.number != sp->u.number;
11232                 break;
11233             case T_STRING:
11234                 i = !mstreq((sp-1)->u.str, sp->u.str);
11235                 break;
11236             case T_POINTER:
11237                 i = (sp-1)->u.vec != sp->u.vec;
11238                 break;
11239 #ifdef USE_STRUCTS
11240             case T_STRUCT:
11241                 i = (sp-1)->u.strct != sp->u.strct;
11242                 break;
11243 #endif
11244             case T_OBJECT:
11245                 i = (sp-1)->u.ob != sp->u.ob;
11246                 break;
11247             case T_FLOAT:
11248                 i = READ_DOUBLE( sp-1 ) != READ_DOUBLE( sp );
11249                 break;
11250 
11251             case T_CLOSURE:
11252                 i = !closure_eq(sp-1, sp);
11253                 break;
11254 
11255             case T_SYMBOL:
11256             case T_QUOTED_ARRAY:
11257                 i = (sp-1)->u.generic  != sp->u.generic ||
11258                     (sp-1)->x.generic != sp->x.generic;
11259                 break;
11260             case T_MAPPING:
11261                 i = (sp-1)->u.map != sp->u.map;
11262                 break;
11263             default:
11264                 if (sp->type == T_LVALUE)
11265                     errorf("Reference passed to !=\n");
11266                 FATALF(("Illegal type '%s' to !=\n",typename(sp->type)));
11267                 /* NOTREACHED */
11268                 return MY_FALSE;
11269             }
11270         }
11271 
11272         pop_stack();
11273         free_svalue(sp);
11274         put_number(sp, i);
11275         break;
11276     }
11277 
11278     CASE(F_COMPL);                  /* --- compl               --- */
11279         /* Compute the binary complement of number sp[0] and leave
11280          * that on the stack.
11281          */
11282         TYPE_TEST1(sp, T_NUMBER);
11283         sp->u.number = ~ sp->u.number;
11284         break;
11285 
11286     CASE(F_AND);                    /* --- and                 --- */
11287     {
11288         /* Compute the intersection of sp[-1] and sp[0] and leave
11289          * the result on the stack.
11290          *
11291          * Possible type combinations:
11292          *   int    & int    -> int
11293          *   string & string -> string
11294          *   vector & vector -> vector
11295          *   vector & mapping  -> vector
11296          *   mapping & vector  -> mapping
11297          *   mapping & mapping -> mapping
11298          *
11299          */
11300 
11301         int i;
11302 
11303         if (sp->type == T_POINTER && (sp-1)->type == T_POINTER)
11304         {
11305             inter_sp = sp - 2;
11306             (sp-1)->u.vec = intersect_array((sp-1)->u.vec, sp->u.vec);
11307             sp--;
11308             break;
11309         }
11310 
11311         if (sp[-1].type == T_POINTER
11312          && sp->type == T_MAPPING)
11313         {
11314             inter_sp = sp - 2;
11315             (sp-1)->u.vec = map_intersect_array(sp[-1].u.vec, sp->u.map);
11316             sp--;
11317             break;
11318         }
11319 
11320         if (sp->type == T_STRING && (sp-1)->type == T_STRING)
11321         {
11322             string_t * result;
11323 
11324             inter_sp = sp;
11325             result = intersect_strings(sp[-1].u.str, sp->u.str, MY_FALSE);
11326             free_string_svalue(sp-1);
11327             free_string_svalue(sp);
11328             put_string(sp-1, result);
11329             sp--;
11330             break;
11331         }
11332 
11333         if (sp->type == T_NUMBER && (sp-1)->type == T_NUMBER)
11334         {
11335             i = (sp-1)->u.number & sp->u.number;
11336             sp--;
11337             sp->u.number = i;
11338             break;
11339         }
11340 
11341         if (sp[-1].type == T_MAPPING
11342          && (sp->type == T_POINTER || sp->type == T_MAPPING))
11343         {
11344             inter_sp = sp - 2;
11345             (sp-1)->u.map = map_intersect(sp[-1].u.map, sp);
11346             sp--;
11347             break;
11348         }
11349 
11350         TYPE_TEST_EXP_LEFT((sp-1), TF_NUMBER|TF_STRING|TF_POINTER|TF_MAPPING);
11351         TYPE_TEST_EXP_RIGHT(sp, TF_NUMBER|TF_STRING|TF_POINTER|TF_MAPPING);
11352         ERRORF(("Arguments to & don't match: %s vs %s\n"
11353                , typename(sp[-1].type), typename(sp->type)
11354                ));
11355 
11356     }
11357 
11358     CASE(F_OR);                     /* --- or                  --- */
11359     {
11360         /* Compute the binary-or of sp[-1] and sp[0] and leave
11361          * the result on the stack.
11362          *
11363          * Possible type combinations:
11364          *   int    | int    -> int
11365          *   array  | array  -> array
11366          *
11367          * TODO: Extend this to mappings.
11368          */
11369 
11370         int i;
11371 
11372         TYPE_TEST_EXP_LEFT((sp-1), TF_NUMBER|TF_POINTER);
11373         if ((sp-1)->type == T_NUMBER)
11374         {
11375             TYPE_TEST_RIGHT(sp, T_NUMBER);
11376             i = (sp-1)->u.number | sp->u.number;
11377             sp--;
11378             sp->u.number = i;
11379         }
11380         else if ((sp-1)->type == T_POINTER)
11381         {
11382             TYPE_TEST_RIGHT(sp, T_POINTER);
11383             inter_sp = sp;
11384             inter_pc = pc;
11385             sp--;
11386             sp->u.vec = join_array(sp->u.vec, (sp+1)->u.vec);
11387         }
11388 
11389         break;
11390     }
11391 
11392     CASE(F_XOR);                    /* --- xor                 --- */
11393     {
11394         /* Compute the binary-xor of sp[-1] and sp[0] and leave
11395          * the result on the stack.
11396          *
11397          * Possible type combinations:
11398          *   int ^ int    -> int
11399          *   array ^ array  -> array
11400          *
11401          * TODO: Extend this to mappings.
11402          */
11403 
11404         int i;
11405 
11406         TYPE_TEST_EXP_LEFT((sp-1), TF_NUMBER|TF_POINTER);
11407         if ((sp-1)->type == T_NUMBER)
11408         {
11409             TYPE_TEST_RIGHT(sp, T_NUMBER);
11410             i = (sp-1)->u.number ^ sp->u.number;
11411             sp--;
11412             sp->u.number = i;
11413         }
11414         else if ((sp-1)->type == T_POINTER)
11415         {
11416             TYPE_TEST_RIGHT(sp, T_POINTER);
11417             sp--;
11418             sp->u.vec = symmetric_diff_array(sp->u.vec, (sp+1)->u.vec);
11419         }
11420 
11421         break;
11422     }
11423 
11424     CASE(F_LSH);                    /* --- lsh                 --- */
11425     {
11426         /* Shift number sp[-1] left by sp[0] bits and leave
11427          * the result on the stack.
11428          *
11429          * Possible type combinations:
11430          *   int << int    -> int
11431          *
11432          * TODO: Extend this to vectors and mappings.
11433          * TODO: Implement an arithmetic shift.
11434          */
11435 
11436         int i;
11437 
11438         TYPE_TEST_LEFT((sp-1), T_NUMBER);
11439         TYPE_TEST_RIGHT(sp, T_NUMBER);
11440 
11441         i = sp->u.number;
11442         sp--;
11443         sp->u.number = (uint)i > MAX_SHIFT ? 0 : sp->u.number << i;
11444         break;
11445     }
11446 
11447     CASE(F_RSH);                    /* --- rsh                 --- */
11448     {
11449         /* Arithmetically shift number sp[-1] right by sp[0] bits and leave
11450          * the result on the stack.
11451          *
11452          * Possible type combinations:
11453          *   int >> int    -> int
11454          *
11455          * TODO: Extend this to vectors and mappings.
11456          */
11457 
11458         int i;
11459 
11460         TYPE_TEST_LEFT((sp-1), T_NUMBER);
11461         TYPE_TEST_RIGHT(sp, T_NUMBER);
11462 
11463         i = sp->u.number;
11464         sp--;
11465         if ((uint)i <= MAX_SHIFT)
11466             sp->u.number >>= i;
11467         else if (sp->u.number >= 0)
11468             sp->u.number = 0;
11469         else
11470             sp->u.number = -1;
11471         break;
11472     }
11473 
11474     CASE(F_RSHL);                   /* --- rshl                --- */
11475     {
11476         /* Logically shift number sp[-1] right by sp[0] bits and leave
11477          * the result on the stack.
11478          *
11479          * Possible type combinations:
11480          *   int >>> int    -> int
11481          *
11482          * TODO: Extend this to vectors and mappings.
11483          */
11484 
11485         int i;
11486 
11487         TYPE_TEST_LEFT((sp-1), T_NUMBER);
11488         TYPE_TEST_RIGHT(sp, T_NUMBER);
11489 
11490         i = sp->u.number;
11491         sp--;
11492         if ((uint)i > MAX_SHIFT)
11493             sp->u.number = 0;
11494         else
11495             sp->u.number = (p_uint)sp->u.number >> i;
11496         break;
11497     }
11498 
11499     CASE(F_NOT);                    /* --- not                 --- */
11500         /* Compute the logical negation of sp[0] and put it onto the stack.
11501          * Every value != 0 is replaced by 0, just number 0 is replaced by 1.
11502          */
11503 
11504         if (sp->type == T_NUMBER)
11505         {
11506             if (sp->u.number == 0)
11507             {
11508                 sp->u.number = 1;
11509                 break;
11510             }
11511         } else
11512             free_svalue(sp);
11513         put_number(sp, 0);
11514         break;
11515 
11516     CASE(F_NX_RANGE);               /* --- nx_range            --- */
11517     CASE(F_RX_RANGE);               /* --- rx_range            --- */
11518     CASE(F_AX_RANGE);               /* --- ax_range            --- */
11519         /* Push '1' onto the stack to make up for the missing
11520          * upper range bound, then fall through to the normal
11521          * range handling.
11522          */
11523         sp++;
11524         put_number(sp, 1);
11525         /* FALLTHROUGH */
11526 
11527     CASE(F_RANGE);                  /* --- range               --- */
11528     CASE(F_NR_RANGE);               /* --- nr_range            --- */
11529     CASE(F_RN_RANGE);               /* --- rn_range            --- */
11530     CASE(F_RR_RANGE);               /* --- rr_range            --- */
11531     CASE(F_NA_RANGE);               /* --- na_range            --- */
11532     CASE(F_AN_RANGE);               /* --- an_range            --- */
11533     CASE(F_RA_RANGE);               /* --- ra_range            --- */
11534     CASE(F_AR_RANGE);               /* --- ar_range            --- */
11535     CASE(F_AA_RANGE);               /* --- aa_range            --- */
11536       {
11537         /* Compute the range sp[-1]..sp[0] from string/array sp[-2]
11538          * and leave it on the stack.
11539          * This code also handles the NX/RX/AX_RANGE, pretending that
11540          * they are NR/RR/AR_RANGEs.
11541          */
11542 
11543         if (sp[-1].type != T_NUMBER)
11544             ERRORF(("Bad type '%s' of start interval to [..] range.\n"
11545                    , typename(sp[-1].type)
11546                    ));
11547         if (sp[0].type != T_NUMBER)
11548             ERRORF(("Bad type '%s' of end interval to [..] range.\n"
11549                    , typename(sp[0].type)
11550                    ));
11551 
11552         if (sp[-2].type == T_POINTER)
11553         {
11554             /* Slice a range from an array */
11555 
11556             vector_t *v;
11557             p_int size, i1, i2;
11558 
11559             size = VEC_SIZE(sp[-2].u.vec);
11560 
11561             if (instruction == F_RANGE
11562              || instruction == F_NR_RANGE
11563              || instruction == F_NA_RANGE
11564              || instruction == F_NX_RANGE)
11565                 i1 = sp[-1].u.number;
11566             else
11567             if (instruction == F_AN_RANGE
11568              || instruction == F_AR_RANGE
11569              || instruction == F_AA_RANGE
11570              || instruction == F_AX_RANGE)
11571             {
11572                 if (sp[-1].u.number < 0)
11573                     i1 = size + sp[-1].u.number;
11574                 else
11575                     i1 = sp[-1].u.number;
11576             }
11577             else
11578                 i1 = size - sp[-1].u.number;
11579 
11580             if (instruction == F_RANGE
11581              || instruction == F_RN_RANGE
11582              || instruction == F_AN_RANGE)
11583                 i2 = sp[0].u.number;
11584             else
11585             if (instruction == F_NA_RANGE
11586              || instruction == F_RA_RANGE
11587              || instruction == F_AA_RANGE)
11588             {
11589                 if (sp[0].u.number < 0)
11590                     i2 = size + sp[0].u.number;
11591                 else
11592                     i2 = sp[0].u.number;
11593             }
11594             else
11595                 i2 = size - sp[0].u.number;
11596 
11597             if (runtime_array_range_check)
11598             {
11599                 if (i1 < 0 || i1 >= size)
11600                 {
11601                     if (i2 < 0 || i2 >= size)
11602                         WARNF(("Warning: Out-of-bounds range limits: [%"
11603                                PRIdPINT"..%"PRIdPINT"], size %"PRIdPINT".\n"
11604                               , i1, i2, size));
11605                     else
11606                         WARNF(("Warning: Out-of-bounds lower range limits: %"
11607                                PRIdPINT", size %"PRIdPINT".\n"
11608                               , i1, size));
11609                 }
11610                 else if (i2 < 0 || i2 >= size)
11611                 {
11612                     WARNF(("Warning: Out-of-bounds upper range limits: %"
11613                            PRIdPINT", size %"PRIdPINT".\n"
11614                           , i2, size));
11615                 }
11616                 else if (i1 > i2)
11617                 {
11618                     WARNF(("Warning: Ranges of negative size: %"PRIdPINT
11619                            "..%"PRIdPINT".\n"
11620                           , i1, i2));
11621                 }
11622             }
11623 
11624             if (i2 >= size)
11625             {
11626                 i2 = size - 1;
11627             }
11628 
11629             pop_stack();
11630             pop_stack();
11631 
11632             v = slice_array(sp->u.vec, i1, i2);
11633 
11634             free_array(sp->u.vec);
11635             if (v)
11636             {
11637                 sp->u.vec = v;
11638             }
11639             else
11640             {
11641                 put_number(sp, 0);
11642             }
11643         }
11644         else if (sp[-2].type == T_STRING)
11645         {
11646             /* Slice a range from string */
11647 
11648             p_int len, from, to;
11649             string_t *res;
11650 
11651             len = mstrsize(sp[-2].u.str);
11652             if (instruction == F_RANGE
11653              || instruction == F_NR_RANGE
11654              || instruction == F_NX_RANGE
11655              || instruction == F_NA_RANGE)
11656                 from = sp[-1].u.number;
11657             else
11658             if (instruction == F_AN_RANGE
11659              || instruction == F_AR_RANGE
11660              || instruction == F_AX_RANGE
11661              || instruction == F_AA_RANGE)
11662             {
11663                 if (sp[-1].u.number < 0)
11664                     from = len + sp[-1].u.number;
11665                 else
11666                     from = sp[-1].u.number;
11667             }
11668             else
11669                 from = len - sp[-1].u.number;
11670             if (from < 0)
11671             {
11672                 from = 0;
11673             }
11674 
11675             if (instruction == F_RANGE
11676              || instruction == F_RN_RANGE
11677              || instruction == F_AN_RANGE)
11678                 to = sp[0].u.number;
11679             else
11680             if (instruction == F_NA_RANGE
11681              || instruction == F_RA_RANGE
11682              || instruction == F_AA_RANGE)
11683             {
11684                 if (sp[0].u.number < 0)
11685                     to = len + sp[0].u.number;
11686                 else
11687                     to = sp[0].u.number;
11688             }
11689             else
11690                 to = len - sp[0].u.number;
11691             if (to >= len)
11692                 to = len-1;
11693 
11694             if (to < from)
11695             {
11696                 pop_n_elems(3);
11697                 push_ref_string(sp, STR_EMPTY);
11698                 break;
11699             }
11700 
11701             if (to == len-1)
11702             {
11703                 res = mstr_extract(sp[-2].u.str, from, -1);
11704             }
11705             else
11706             {
11707                 res = mstr_extract(sp[-2].u.str, from, to);
11708             }
11709 
11710             if (res == NULL)
11711             {
11712                 ERRORF(("Out of memory (%"PRIdPINT" bytes).\n", to-from+1));
11713             }
11714             pop_n_elems(3);
11715             push_string(sp, res);
11716         }
11717         else
11718         {
11719             ERRORF(("Bad argument to [..] operand: got %s, "
11720                     "expected string/array.\n", typename(sp[-2].type)
11721                     ));
11722         }
11723         break;
11724       }
11725 
11726     CASE(F_ADD_EQ);                 /* --- add_eq              --- */
11727     CASE(F_VOID_ADD_EQ);            /* --- void_add_eq         --- */
11728     {
11729         /* Add sp[-1] to the value designated by lvalue sp[0] (the order
11730          * is important) and assign the result to sp[0].
11731          * For F_ADD_EQ, the result is also left on the stack.
11732          *
11733          * Possible type combinations:
11734          *   string       + (string,int,float) -> string
11735          *   int          + string             -> string
11736          *   int          + int                -> int
11737          *   int          + float              -> float
11738          *   float        + (float,int)        -> float
11739          *   vector       + vector             -> vector
11740          *   mapping      + mapping            -> mapping
11741          * TODO: This type mapping should be documented in 2-dim-arrays,
11742          * TODO:: one each for F_ADD_EQ, F_MULT_EQ, etc. This would
11743          * TODO:: also make the checks in the compiler simpler.
11744          */
11745 
11746         short type2;         /* type and value of sp[-1] */
11747         union u u2;
11748         svalue_t *argp; /* the actual value of sp[0] */
11749 
11750         type2 = sp[-1].type;
11751         u2 = sp[-1].u;
11752 
11753 #ifdef DEBUG
11754         TYPE_TEST_LEFT(sp, T_LVALUE);
11755 #endif
11756 
11757         /* Set argp to the actual value designated by sp[0] */
11758         for ( argp = sp->u.lvalue
11759             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
11760             ; argp = argp->u.lvalue)
11761             NOOP;
11762 
11763         /* Now do it */
11764         switch(argp->type)
11765         {
11766 
11767         case T_STRING:  /* Adding to a string */
11768           {
11769             string_t *new_string;
11770 
11771             /* Perform the addition, creating new_string */
11772             if (type2 == T_STRING)
11773             {
11774                 string_t *left, *right;
11775                 size_t len;
11776 
11777                 left = argp->u.str;
11778                 right = (sp-1)->u.str;
11779 
11780                 len = mstrsize(left) + mstrsize(right);
11781                 DYN_STRING_COST(len)
11782                 new_string = mstr_add(left, right);
11783                 if (!new_string)
11784                     ERRORF(("Out of memory (%zu bytes)\n", len));
11785                 free_string_svalue(sp-1);
11786                 sp -= 2;
11787             }
11788             else if (type2 == T_NUMBER)
11789             {
11790                 char buff[80];
11791                 size_t len;
11792 
11793                 buff[sizeof(buff)-1] = '\0';
11794                 sprintf(buff, "%ld", (long)u2.number);
11795                 if (buff[sizeof(buff)-1] != '\0')
11796                     FATAL("Buffer overflow in F_ADD_EQ: int number too big.\n");
11797                 len = mstrsize(argp->u.str)+strlen(buff);
11798                 DYN_STRING_COST(len)
11799                 new_string = mstr_add_txt(argp->u.str, buff, strlen(buff));
11800                 if (!new_string)
11801                     ERRORF(("Out of memory (%lu bytes)\n"
11802                            , (unsigned long) len
11803                            ));
11804                 sp -= 2;
11805             }
11806             else if (type2 == T_FLOAT)
11807             {
11808                 char buff[160];
11809                 size_t len;
11810 
11811                 buff[sizeof(buff)-1] = '\0';
11812                 sprintf(buff, "%g", READ_DOUBLE(sp-1) );
11813                 if (buff[sizeof(buff)-1] != '\0')
11814                     FATAL("Buffer overflow in F_ADD_EQ: float number too big.\n");
11815                 len = mstrsize(argp->u.str) + strlen(buff);
11816                 DYN_STRING_COST(len)
11817                 new_string = mstr_add_txt(argp->u.str, buff, strlen(buff));
11818                 if (!new_string)
11819                     ERRORF(("Out of memory (%zu bytes).\n", len));
11820                 sp -= 2;
11821             }
11822             else
11823             {
11824                 OP_ARG_ERROR(2, TF_STRING|TF_FLOAT|TF_NUMBER, type2);
11825                 /* NOTREACHED */
11826             }
11827 
11828             /* Replace *argp by the new string */
11829             free_string_svalue(argp);
11830             put_string(argp, new_string);
11831             break;
11832           }
11833 
11834         case T_NUMBER:  /* Add to a number */
11835             if (type2 == T_NUMBER)
11836             {
11837                 p_int left = argp->u.number;
11838                 p_int right = u2.number;
11839 
11840                 if ((left >= 0 && right >= 0 && PINT_MAX - left < right)
11841                  || (left < 0 && right < 0 && PINT_MIN - left > right)
11842                    )
11843                 {
11844                     ERRORF(("Numeric overflow: %"PRIdPINT" += %"PRIdPINT"\n"
11845                            , left, right));
11846                     /* NOTREACHED */
11847                     break;
11848                 }
11849 
11850                 if (instruction == F_VOID_ADD_EQ)
11851                 {
11852                     argp->u.number += u2.number;
11853                     sp -= 2;
11854                     goto again;
11855                 }
11856                 (--sp)->u.number = argp->u.number += u2.number;
11857                 goto again;
11858             }
11859             else if (type2 == T_FLOAT)
11860             {
11861                 STORE_DOUBLE_USED
11862                 double sum;
11863 
11864                 sum = (double)(argp->u.number) + READ_DOUBLE(sp-1);
11865                 if (sum < (-DBL_MAX) || sum > DBL_MAX)
11866                     ERRORF(("Numeric overflow: %"PRIdPINT" + %g\n"
11867                            , argp->u.number, READ_DOUBLE(sp-1)));
11868                 argp->type = T_FLOAT;
11869                 STORE_DOUBLE(argp, sum);
11870                 if (instruction == F_VOID_ADD_EQ)
11871                 {
11872                     sp -= 2;
11873                     goto again;
11874                 }
11875 
11876                 --sp;
11877                 sp->type = T_FLOAT;
11878                 STORE_DOUBLE(sp, sum);
11879                 goto again;
11880             }
11881             else if (type2 == T_STRING)
11882             {
11883                 char buff[80];
11884                 string_t *right, *res;
11885                 size_t len;
11886 
11887                 right = (sp-1)->u.str;
11888                 buff[sizeof(buff)-1] = '\0';
11889                 sprintf(buff, "%"PRIdPINT, argp->u.number);
11890                 if (buff[sizeof(buff)-1] != '\0')
11891                     FATAL("Buffer overflow in F_ADD_EQ: int number too big.\n");
11892                 len = mstrsize(right)+strlen(buff);
11893                 DYN_STRING_COST(len)
11894                 res = mstr_add_to_txt(buff, strlen(buff), right);
11895                 if (!res)
11896                     ERRORF(("Out of memory (%zu bytes)\n", len));
11897                 free_string_svalue(sp-1);
11898 
11899                 /* Overwrite the number in argp */
11900                 put_string(argp, res);
11901 
11902                 if (instruction == F_VOID_ADD_EQ)
11903                 {
11904                     sp -= 2;
11905                     goto again;
11906                 }
11907 
11908                 --sp;
11909                 put_ref_string(sp, res);
11910 
11911                 goto again;
11912             }
11913             else
11914             {
11915                 OP_ARG_ERROR(2, TF_NUMBER, type2);
11916                 /* NOTREACHED */
11917             }
11918             break;
11919 
11920         case T_CHAR_LVALUE:  /* Add to a character in a string */
11921             if (type2 == T_NUMBER)
11922             {
11923                 p_int left = (unsigned char)*argp->u.charp;
11924                 p_int right = u2.number;
11925 
11926                 if ((left >= 0 && right >= 0 && PINT_MAX - left < right)
11927                  || (left < 0 && right < 0 && PINT_MIN - left > right)
11928                    )
11929                 {
11930                     ERRORF(("Numeric overflow: %"PRIdPINT" += %"PRIdPINT"\n"
11931                            , left, right));
11932                     /* NOTREACHED */
11933                     break;
11934                 }
11935 
11936                 if (instruction == F_VOID_ADD_EQ)
11937                 {
11938                     *argp->u.charp += u2.number;
11939                     sp -= 2;
11940                     goto again;
11941                 }
11942                 (--sp)->u.number = (unsigned char)(*argp->u.charp += u2.number);
11943                 goto again;
11944             }
11945             else
11946             {
11947                 OP_ARG_ERROR(2, TF_NUMBER, type2);
11948                 /* NOTREACHED */
11949             }
11950             break;
11951 
11952         case T_MAPPING:  /* Add to a mapping */
11953             if (type2 != T_MAPPING)
11954             {
11955                 OP_ARG_ERROR(2, TF_MAPPING, type2);
11956                 /* NOTREACHED */
11957             }
11958             else
11959             {
11960                 check_map_for_destr(u2.map);
11961                 add_to_mapping(argp->u.map, u2.map);
11962                 sp -= 2;
11963                 free_mapping(u2.map);
11964                 if ((max_mapping_size && MAP_TOTAL_SIZE(argp->u.map) > (p_int)max_mapping_size)
11965                  || (max_mapping_keys && MAP_SIZE(argp->u.map) > (p_int)max_mapping_keys)
11966                   )
11967                 {
11968                     check_map_for_destr(argp->u.map);
11969                     if (max_mapping_size && MAP_TOTAL_SIZE(argp->u.map) > (p_int)max_mapping_size)
11970                         ERRORF(("Illegal mapping size: %"PRIdMPINT" elements "
11971                                 "(%"PRIdPINT" x %"PRIdPINT")\n"
11972                                , (mp_int)MAP_TOTAL_SIZE(argp->u.map)
11973                                , MAP_SIZE(argp->u.map)
11974                                , argp->u.map->num_values));
11975                     if (max_mapping_keys && MAP_SIZE(argp->u.map) > (p_int)max_mapping_keys)
11976                         ERRORF(("Illegal mapping size: %"PRIdPINT" entries\n"
11977                                , MAP_SIZE(argp->u.map)
11978                               ));
11979                 }
11980             }
11981             break;
11982 
11983         case T_POINTER:  /* Add to an array */
11984             if (type2 != T_POINTER)
11985             {
11986                 OP_ARG_ERROR(2, TF_POINTER, type2);
11987                 /* NOTREACHED */
11988             }
11989             else
11990             {
11991                 vector_t *v;
11992 
11993                 inter_sp = sp;
11994                 inter_pc = pc;
11995                 DYN_ARRAY_COST(VEC_SIZE(u2.vec)+VEC_SIZE(argp->u.vec));
11996                 v = inter_add_array(u2.vec, &argp->u.vec);
11997                 if (instruction == F_VOID_ADD_EQ)
11998                 {
11999                     sp -= 2;
12000                     goto again;
12001                 }
12002                 sp--;
12003                 sp->u.vec = ref_array(v);
12004                 goto again;
12005                 }
12006             break;
12007 
12008         case T_FLOAT:  /* Add to a float */
12009             if (type2 == T_FLOAT)
12010             {
12011                 STORE_DOUBLE_USED
12012                 double d;
12013 
12014                    /* don't use the address of u2, this would prevent putting
12015                     * it in a register
12016                     */
12017                 d = READ_DOUBLE(argp) + READ_DOUBLE(sp-1);
12018                 if (d < (-DBL_MAX) || d > DBL_MAX)
12019                     ERRORF(("Numeric overflow: %g + %g\n"
12020                            , READ_DOUBLE(argp), READ_DOUBLE(sp-1)));
12021                 STORE_DOUBLE(argp, d);
12022                 sp -= 2;
12023             }
12024             else if (type2 == T_NUMBER)
12025             {
12026                 STORE_DOUBLE_USED
12027                 double d;
12028 
12029                 d = READ_DOUBLE(argp) + (double)sp[-1].u.number;
12030                 if (d < (-DBL_MAX) || d > DBL_MAX)
12031                     ERRORF(("Numeric overflow: %g + %"PRIdPINT"\n"
12032                            , READ_DOUBLE(argp), (sp-1)->u.number));
12033                 STORE_DOUBLE(argp, d);
12034                 sp -= 2;
12035             }
12036             else
12037             {
12038                 OP_ARG_ERROR(2, TF_FLOAT|TF_NUMBER, type2);
12039                 /* NOTREACHED */
12040             }
12041             break;
12042 
12043         default:
12044             OP_ARG_ERROR(1, TF_STRING|TF_FLOAT|TF_MAPPING|TF_POINTER|TF_NUMBER
12045                         , argp->type);
12046             /* NOTREACHED */
12047         } /* end of switch */
12048 
12049         /* If the instruction is F_ADD_EQ, leave the result on the stack */
12050         if (instruction != F_VOID_ADD_EQ)
12051         {
12052             sp++;
12053             assign_svalue_no_free(sp, argp);
12054         }
12055         break;
12056     }
12057 
12058     CASE(F_SUB_EQ);                 /* --- sub_eq              --- */
12059     {
12060         /* Subtract sp[-1] from the value designated by lvalue sp[0] (the
12061          * order is important), assign the result to sp[0] and also leave
12062          * it on the stack.
12063          *
12064          * Possible type combinations:
12065          *   int         - int                -> int
12066          *   float       - (float,int)        -> float
12067          *   int         - float              -> float
12068          *   string      - string             -> string
12069          *   vector      - vector             -> vector
12070          *   mapping     - mapping            -> mapping
12071          */
12072 
12073         short type2;         /* type and value of sp[-1] */
12074         union u u2;
12075         svalue_t *argp; /* the actual value of sp[0] */
12076 
12077         type2 = sp[-1].type;
12078         u2 = sp[-1].u;
12079 
12080 #ifdef DEBUG
12081         TYPE_TEST_LEFT(sp, T_LVALUE);
12082 #endif
12083 
12084         /* Set argp to the actual value designated by sp[0] */
12085         for ( argp = sp->u.lvalue
12086             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
12087             ; argp = argp->u.lvalue)
12088             NOOP;
12089 
12090         /* Now do it */
12091         switch (argp->type)
12092         {
12093         case T_NUMBER:  /* Subtract from a number */
12094             if (type2 == T_NUMBER)
12095             {
12096                 p_int left = argp->u.number;
12097                 p_int right = u2.number;
12098 
12099                 if ((left >= 0 && right < 0 && PINT_MAX + right < left)
12100                  || (left < 0 && right >= 0 && PINT_MIN + right > left)
12101                    )
12102                 {
12103                     ERRORF(("Numeric overflow: %"PRIdPINT" -= %"PRIdPINT"\n"
12104                            , left, right));
12105                     /* NOTREACHED */
12106                     break;
12107                 }
12108                 sp--;
12109                 sp->u.number = argp->u.number -= u2.number;
12110                 break;
12111             }
12112 
12113             if (type2 == T_FLOAT)
12114             {
12115                 STORE_DOUBLE_USED
12116                 double diff;
12117 
12118                 sp--;
12119                 diff = (double)(argp->u.number) - READ_DOUBLE(sp);
12120                 if (diff < (-DBL_MAX) || diff > DBL_MAX)
12121                     ERRORF(("Numeric overflow: %"PRIdPINT" - %g\n"
12122                            , argp->u.number, READ_DOUBLE(sp)));
12123                 STORE_DOUBLE(sp, diff);
12124                 sp->type = T_FLOAT;
12125                 assign_svalue_no_free(argp, sp);
12126                 break;
12127             }
12128 
12129             /* type2 of the wrong type */
12130             OP_ARG_ERROR(2, TF_NUMBER|TF_FLOAT, type2);
12131             /* NOTREACHED */
12132             break;
12133 
12134         case T_CHAR_LVALUE:  /* Subtract from a char in a string */
12135             if (type2 != T_NUMBER)
12136             {
12137                 OP_ARG_ERROR(2, TF_NUMBER, type2);
12138                 /* NOTREACHED */
12139             }
12140 
12141             {
12142                 p_int left = (unsigned char)*argp->u.charp;
12143                 p_int right = u2.number;
12144 
12145                 if ((left >= 0 && right < 0 && PINT_MAX + right < left)
12146                  || (left < 0 && right >= 0 && PINT_MIN + right > left)
12147                    )
12148                 {
12149                     ERRORF(("Numeric overflow: %"PRIdPINT" -= %"PRIdPINT"\n"
12150                            , left, right));
12151                     /* NOTREACHED */
12152                     break;
12153                 }
12154             }
12155 
12156             sp--;
12157             sp->u.number = (unsigned char)(*argp->u.charp -= u2.number);
12158             break;
12159 
12160         case T_STRING:   /* Subtract from a string */
12161         {
12162             string_t * result;
12163 
12164             if (type2 != T_STRING)
12165             {
12166                 OP_ARG_ERROR(2, TF_STRING, type2);
12167                 /* NOTREACHED */
12168             }
12169 
12170             inter_sp = sp;
12171             result = intersect_strings(argp->u.str, (sp-1)->u.str, MY_TRUE);
12172             free_string_svalue(argp);
12173             put_string(argp, result);
12174             free_svalue(sp);
12175             sp--;
12176             free_string_svalue(sp);
12177             put_ref_string(sp, result);
12178             break;
12179         }
12180 
12181         case T_POINTER:  /* Subtract from an array */
12182           {
12183             vector_t *v, *v_old;
12184 
12185             if (type2 != T_POINTER)
12186             {
12187                 OP_ARG_ERROR(2, TF_POINTER, type2);
12188                 /* NOTREACHED */
12189             }
12190 
12191             v = u2.vec;
12192 
12193             /* Duplicate the minuend array if necessary, as
12194              * the subtraction will change and free it
12195              */
12196             if (v->ref > 1)
12197             {
12198                 deref_array(v);
12199                 v = slice_array(v, 0, (mp_int)VEC_SIZE(v)-1 );
12200             }
12201             sp--;
12202             v_old = argp->u.vec;
12203             v = subtract_array(v_old, v);
12204             argp->u.vec = v;
12205             put_ref_array(sp, v);
12206             break;
12207           }
12208 
12209         case T_FLOAT:  /* Subtract from a float */
12210             if (type2 == T_FLOAT)
12211             {
12212                 STORE_DOUBLE_USED
12213                 double d;
12214 
12215                 /* don't use the address of u2, this would prevent putting it
12216                  * in a register
12217                  */
12218                 sp--;
12219                 d = READ_DOUBLE(argp) - READ_DOUBLE(sp);
12220                 if (d < (-DBL_MAX) || d > DBL_MAX)
12221                     ERRORF(("Numeric overflow: %g + %g\n"
12222                            , READ_DOUBLE(argp), READ_DOUBLE(sp)));
12223                 STORE_DOUBLE(argp, d);
12224                 *sp = *argp;
12225             }
12226             else if (type2 == T_NUMBER)
12227             {
12228                 STORE_DOUBLE_USED
12229                 double d;
12230 
12231                 sp--;
12232                 d = READ_DOUBLE(argp) - (double)sp->u.number;
12233                 if (d < (-DBL_MAX) || d > DBL_MAX)
12234                     ERRORF(("Numeric overflow: %g + %"PRIdPINT"\n"
12235                            , READ_DOUBLE(argp), sp->u.number));
12236                 STORE_DOUBLE(argp, d);
12237                 *sp = *argp;
12238             }
12239             else
12240             {
12241                 OP_ARG_ERROR(2, TF_FLOAT|TF_NUMBER, type2);
12242                 /* NOTREACHED */
12243             }
12244             break;
12245 
12246         case T_MAPPING:  /* Subtract from a mapping */
12247             if (type2 == T_MAPPING)
12248             {
12249                 mapping_t *m;
12250 
12251                 sp--;
12252                 m = sp->u.map;
12253                 check_map_for_destr(m);
12254 
12255                 /* Test for the special case 'm - m' */
12256                 if (m == argp->u.map)
12257                 {
12258                     /* m->ref is > 1, because the content of the lvalue is
12259                      * associated with a ref
12260                      */
12261                     deref_mapping(m);
12262                     m = copy_mapping(m);
12263                 }
12264 
12265                 walk_mapping(m, sub_from_mapping_filter, argp->u.map);
12266                 free_mapping(m);
12267                 sp->u.map = ref_mapping(argp->u.map);
12268             }
12269             else if (type2 == T_MAPPING && sp[-1].u.map->num_values)
12270             {
12271                 ERROR("Bad right arg to -=: mapping has values.\n");
12272                 /* NOTREACHED */
12273             }
12274             else
12275             {
12276                 OP_ARG_ERROR(2, TF_MAPPING, type2);
12277                 /* NOTREACHED */
12278             }
12279             break;
12280 
12281         default:
12282             OP_ARG_ERROR(1, TF_STRING|TF_FLOAT|TF_MAPPING|TF_POINTER|TF_NUMBER
12283                         , argp->type);
12284             /* NOTREACHED */
12285         } /* end of switch */
12286         break;
12287     }
12288 
12289     CASE(F_MULT_EQ);                /* --- mult_eq             --- */
12290     {
12291         /* Multiply sp[-1] to the value designated by lvalue sp[0],
12292          * assign the result to sp[0] and also leave it on the stack.
12293          *
12294          * Possible type combinations:
12295          *   int         * int                -> int
12296          *   float       * (float,int)        -> float
12297          *   int         * float              -> float
12298          *   string      * int                -> string
12299          *   array       * int                -> array
12300          *
12301          * TODO: Extend this to mappings.
12302          */
12303 
12304         svalue_t *argp;
12305 
12306 #ifdef DEBUG
12307         TYPE_TEST_LEFT(sp, T_LVALUE);
12308 #endif
12309 
12310         /* Set argp to the actual value designated by sp[0] */
12311         for ( argp = sp->u.lvalue
12312             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
12313             ; argp = argp->u.lvalue)
12314             NOOP;
12315 
12316         /* Now do it */
12317         if (argp->type == T_NUMBER)
12318         {
12319             sp--;
12320             if (sp->type == T_NUMBER)
12321             {
12322                 p_int left = argp->u.number;
12323                 p_int right = sp->u.number;
12324 
12325                 if (left > 0 && right > 0)
12326                 {
12327                     if ((left != 0 && PINT_MAX / left < right)
12328                      || (right != 0 && PINT_MAX / right < left)
12329                        )
12330                     {
12331                         ERRORF(("Numeric overflow: %"PRIdPINT" *= %"
12332                                 PRIdPINT"\n"
12333                                , left, right));
12334                         /* NOTREACHED */
12335                         break;
12336                     }
12337                 }
12338                 else if (left < 0 && right < 0)
12339                 {
12340                     if ((left != 0 && PINT_MAX / left > right)
12341                      || (right != 0 && PINT_MAX / right > left)
12342                        )
12343                     {
12344                         ERRORF(("Numeric overflow: %"PRIdPINT" *= %"
12345                                 PRIdPINT"\n"
12346                                , left, right));
12347                         /* NOTREACHED */
12348                         break;
12349                     }
12350                 }
12351                 else if (left != 0 && right != 0)
12352                 {
12353                     if ((left > 0 && PINT_MIN / left > right)
12354                      || (right > 0 && PINT_MIN / right > left)
12355                        )
12356                     {
12357                         ERRORF(("Numeric overflow: %"PRIdPINT" *= %"
12358                                 PRIdPINT"\n"
12359                                , left, right));
12360                         /* NOTREACHED */
12361                         break;
12362                     }
12363                 }
12364                 sp->u.number = argp->u.number *= sp->u.number;
12365                 break;
12366             } /* type2 == T_NUMBER */
12367 
12368             if (sp->type == T_FLOAT)
12369             {
12370                 STORE_DOUBLE_USED
12371                 double product;
12372 
12373                 product = argp->u.number * READ_DOUBLE(sp);
12374                 if (product < (-DBL_MAX) || product > DBL_MAX)
12375                     ERRORF(("Numeric overflow: %"PRIdPINT" * %g\n"
12376                            , argp->u.number, READ_DOUBLE(sp)));
12377                 STORE_DOUBLE(sp, product);
12378                 sp->type = T_FLOAT;
12379                 assign_svalue_no_free(argp, sp);
12380                 break;
12381             }
12382 
12383             /* Unsupported type2 */
12384             OP_ARG_ERROR(2, TF_NUMBER|TF_FLOAT, sp->type);
12385             /* NOTREACHED */
12386         }
12387 
12388         if (argp->type == T_CHAR_LVALUE)
12389         {
12390             sp--;
12391             if (sp->type != T_NUMBER)
12392             {
12393                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
12394                 /* NOTREACHED */
12395             }
12396             {
12397                 p_int left = (unsigned char)*argp->u.charp;
12398                 p_int right = sp->u.number;
12399 
12400                 if (left > 0 && right > 0)
12401                 {
12402                     if ((left != 0 && PINT_MAX / left < right)
12403                      || (right != 0 && PINT_MAX / right < left)
12404                        )
12405                     {
12406                         ERRORF(("Numeric overflow: %"PRIdPINT" *= %"
12407                                 PRIdPINT"\n", left, right));
12408                         /* NOTREACHED */
12409                         break;
12410                     }
12411                 }
12412                 else if (left < 0 && right < 0)
12413                 {
12414                     if ((left != 0 && PINT_MAX / left > right)
12415                      || (right != 0 && PINT_MAX / right > left)
12416                        )
12417                     {
12418                         ERRORF(("Numeric overflow: %"PRIdPINT" *= %"
12419                                 PRIdPINT"\n", left, right));
12420                         /* NOTREACHED */
12421                         break;
12422                     }
12423                 }
12424                 else if (left != 0 && right != 0)
12425                 {
12426                     if ((left > 0 && PINT_MIN / left > right)
12427                      || (right > 0 && PINT_MIN / right > left)
12428                        )
12429                     {
12430                         ERRORF(("Numeric overflow: %"PRIdPINT" *= %"
12431                                 PRIdPINT"\n", left, right));
12432                         /* NOTREACHED */
12433                         break;
12434                     }
12435                 }
12436             }
12437             sp->u.number = (unsigned char)(*argp->u.charp *= sp->u.number);
12438             break;
12439         }
12440 
12441         if (argp->type == T_FLOAT)
12442         {
12443             STORE_DOUBLE_USED
12444             double d;
12445 
12446             sp--;
12447             if (sp->type == T_FLOAT)
12448             {
12449                 d = READ_DOUBLE(argp) * READ_DOUBLE(sp);
12450                 if (d < (-DBL_MAX) || d > DBL_MAX)
12451                     ERRORF(("Numeric overflow: %g * %g\n"
12452                            , READ_DOUBLE(argp), READ_DOUBLE(sp)));
12453                 STORE_DOUBLE(argp, d);
12454                 *sp = *argp;
12455             }
12456             else if (sp->type == T_NUMBER)
12457             {
12458                 d = READ_DOUBLE(argp) * (double)sp->u.number;
12459                 if (d < (-DBL_MAX) || d > DBL_MAX)
12460                     ERRORF(("Numeric overflow: %g * %"PRIdPINT"\n"
12461                            , READ_DOUBLE(argp), sp->u.number));
12462                 STORE_DOUBLE(argp, d);
12463                 *sp = *argp;
12464             }
12465             else
12466             {
12467                 OP_ARG_ERROR(2, TF_NUMBER|TF_FLOAT, sp->type);
12468                 /* NOTREACHED */
12469             }
12470             break;
12471         }
12472 
12473         if (argp->type == T_STRING)
12474         {
12475             string_t * result;
12476             size_t reslen;
12477             size_t len;
12478 
12479             sp--;
12480             if (sp->type != T_NUMBER)
12481             {
12482                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
12483                 /* NOTREACHED */
12484             }
12485             if (sp->u.number < 0)
12486             {
12487                 ERROR("Bad right arg to *=: negative number\n");
12488                 /* NOTREACHED */
12489             }
12490 
12491             len = mstrsize(argp->u.str);
12492 
12493             if (len > (size_t)PINT_MAX
12494              || (   len != 0
12495                  && PINT_MAX / (p_int)len < sp->u.number)
12496              || (   sp->u.number != 0
12497                  && PINT_MAX / sp->u.number < (p_int)len)
12498                )
12499                 ERRORF(("Result string too long (%"PRIdPINT" * %zu).\n"
12500                        , sp->u.number, len
12501                        ));
12502 
12503             reslen = (size_t)sp->u.number * len;
12504             result = mstr_repeat(argp->u.str, (size_t)sp->u.number);
12505             if (!result)
12506                 ERRORF(("Out of memory (%zu bytes).\n", reslen));
12507 
12508             DYN_STRING_COST(reslen)
12509 
12510             free_string_svalue(argp);
12511             put_string(argp, result);
12512             assign_svalue_no_free(sp, argp);
12513             break;
12514         }
12515 
12516         if (argp->type == T_POINTER)
12517         {
12518             vector_t *result;
12519             mp_int reslen;
12520             p_uint len;
12521 
12522             sp--;
12523             if (sp->type != T_NUMBER)
12524             {
12525                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
12526                 /* NOTREACHED */
12527             }
12528             if (sp->u.number < 0)
12529             {
12530                 ERROR("Bad right arg to *=: negative number\n");
12531                 /* NOTREACHED */
12532             }
12533 
12534             inter_sp = sp;
12535             inter_pc = pc;
12536             len = VEC_SIZE(argp->u.vec);
12537             reslen = sp->u.number * (mp_int)len;
12538             result = allocate_uninit_array(reslen);
12539             DYN_ARRAY_COST(reslen);
12540 
12541             if (sp->u.number > 0 && len)
12542             {
12543                 p_uint left;
12544                 svalue_t *from, *to;
12545 
12546                 /* Seed result[] with one copy of the array.
12547                  */
12548                 for ( from = argp->u.vec->item, to = result->item, left = len
12549                     ; left
12550                     ; from++, to++, left--)
12551                 {
12552                     assign_svalue_no_free(to, from);
12553                 } /* for() seed */
12554 
12555                 /* Now fill the remainder of the vector with
12556                  * the values already copied in there.
12557                  */
12558                 for (from = result->item, left = reslen - len
12559                     ; left
12560                     ; to++, from++, left--
12561                     )
12562                     assign_svalue_no_free(to, from);
12563             } /* if (len) */
12564 
12565             free_svalue(argp);
12566             put_array(argp, result);
12567             assign_svalue_no_free(sp, argp);
12568             break;
12569         }
12570 
12571         OP_ARG_ERROR(1, TF_STRING|TF_FLOAT|TF_POINTER|TF_NUMBER
12572                     , argp->type);
12573         /* NOTREACHED */
12574         break;
12575     }
12576 
12577     CASE(F_DIV_EQ);                 /* --- div_eq              --- */
12578     {
12579         /* Divide the value designated by lvalue sp[0] by sp[-1],
12580          * assign the result to sp[0] and also leave it on the stack.
12581          *
12582          * Possible type combinations:
12583          *   int         / int                -> int
12584          *   float       / (float,int)        -> float
12585          *   int         - float              -> float
12586          *
12587          * TODO: Extend this to arrays and mappings.
12588          */
12589 
12590         svalue_t *argp;
12591 
12592 #ifdef DEBUG
12593         TYPE_TEST_LEFT(sp, T_LVALUE);
12594 #endif
12595 
12596         /* Set argp to the actual value designated by sp[0] */
12597         for ( argp = sp->u.lvalue
12598             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
12599             ; argp = argp->u.lvalue)
12600             NOOP;
12601 
12602         /* Now do it */
12603         if (argp->type == T_NUMBER)
12604         {
12605             sp--;
12606             if (sp->type == T_NUMBER)
12607             {
12608                 if (sp->u.number == 0)
12609                     ERROR("Division by zero\n");
12610                 if (argp->u.number == PINT_MIN && sp->u.number == -1)
12611                     ERRORF(("Numeric overflow: %"PRIdPINT" / -1\n"
12612                            , argp->u.number
12613                            ));
12614                 sp->u.number = argp->u.number /= sp->u.number;
12615                 break;
12616             }
12617 
12618             if (sp->type == T_FLOAT)
12619             {
12620                 double dtmp;
12621                 STORE_DOUBLE_USED
12622 
12623                 dtmp = READ_DOUBLE( sp );
12624                 if (dtmp == 0.)
12625                     ERROR("Division by zero\n");
12626                 dtmp = (double)argp->u.number / dtmp;
12627                 if (dtmp < (-DBL_MAX) || dtmp > DBL_MAX)
12628                     ERRORF(("Numeric overflow: %"PRIdPINT" / %g\n"
12629                            , argp->u.number, READ_DOUBLE(sp)));
12630                 STORE_DOUBLE(sp, dtmp);
12631                 sp->type = T_FLOAT;
12632                 assign_svalue_no_free(argp, sp);
12633                 break;
12634             }
12635 
12636             /* Unsupported type2 */
12637             OP_ARG_ERROR(2, TF_NUMBER|TF_FLOAT, sp->type);
12638             /* NOTREACHED */
12639         }
12640 
12641         if (argp->type == T_CHAR_LVALUE)
12642         {
12643             sp--;
12644             if (sp->type != T_NUMBER)
12645             {
12646                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
12647                 /* NOTREACHED */
12648             }
12649             if (sp->u.number == 0)
12650                 ERROR("Division by zero\n");
12651             sp->u.number = (unsigned char)(*argp->u.charp /= sp->u.number);
12652             break;
12653         }
12654 
12655         if (argp->type == T_FLOAT)
12656         {
12657             STORE_DOUBLE_USED
12658             double d;
12659 
12660             sp--;
12661             if (sp->type == T_FLOAT)
12662             {
12663                 d = READ_DOUBLE(sp);
12664                 if (d == 0.0)
12665                     ERROR("Division by zero\n");
12666                 d = READ_DOUBLE(argp) / d;
12667                 if (d < (-DBL_MAX) || d > DBL_MAX)
12668                     ERRORF(("Numeric overflow: %g / %g\n"
12669                            , READ_DOUBLE(argp), READ_DOUBLE(sp)));
12670                 STORE_DOUBLE(argp, d);
12671                 *sp = *argp;
12672             }
12673             else if (sp->type == T_NUMBER)
12674             {
12675                 p_int i;
12676                 i = sp->u.number;
12677                 if (i == 0)
12678                     ERROR("Division by zero\n");
12679                 d = READ_DOUBLE(argp) / (double)i;
12680                 if (d < (-DBL_MAX) || d > DBL_MAX)
12681                     ERRORF(("Numeric overflow: %g / %"PRIdPINT"\n"
12682                            , READ_DOUBLE(argp), sp->u.number));
12683                 STORE_DOUBLE(argp, d);
12684                 *sp = *argp;
12685             }
12686             else
12687             {
12688                 OP_ARG_ERROR(2, TF_NUMBER|TF_FLOAT, sp->type);
12689                 /* NOTREACHED */
12690             }
12691             break;
12692         }
12693         OP_ARG_ERROR(1, TF_FLOAT|TF_NUMBER, argp->type);
12694         /* NOTREACHED */
12695     }
12696 
12697     CASE(F_MOD_EQ);                 /* --- mod_eq              --- */
12698     {
12699         /* Compute the modulus of the value designated by lvalue sp[0]
12700          * divided by sp[-1], assign the result to sp[0] and also
12701          * leave it on the stack.
12702          *
12703          * Possible type combinations:
12704          *   int         % int                -> int
12705          *
12706          * TODO: Extend this to arrays and mappings.
12707          * TODO: Implement the other remainder function.
12708          */
12709 
12710         svalue_t *argp;
12711 
12712 #ifdef DEBUG
12713         TYPE_TEST_LEFT(sp, T_LVALUE);
12714 #endif
12715 
12716         /* Set argp to the actual value designated by sp[0] */
12717         for ( argp = sp->u.lvalue
12718             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
12719             ; argp = argp->u.lvalue)
12720             NOOP;
12721 
12722         /* Now do it */
12723         if (argp->type == T_NUMBER)
12724         {
12725             sp--;
12726             if (sp->type != T_NUMBER)
12727             {
12728                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
12729                 /* NOTREACHED */
12730             }
12731             if (sp->u.number == 0)
12732                 ERROR("Division by zero\n");
12733             sp->u.number = argp->u.number %= sp->u.number;
12734             break;
12735         }
12736 
12737         if (argp->type == T_CHAR_LVALUE)
12738         {
12739             sp--;
12740             if (sp->type != T_NUMBER)
12741             {
12742                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
12743                 /* NOTREACHED */
12744             }
12745             if (sp->u.number == 0)
12746                 ERROR("Division by zero\n");
12747             sp->u.number = (unsigned char)(*argp->u.charp %= sp->u.number);
12748             break;
12749         }
12750 
12751         OP_ARG_ERROR(1, TF_NUMBER, argp->type);
12752         /* NOTREACHED */
12753     }
12754 
12755     CASE(F_AND_EQ);                 /* --- and_eq              --- */
12756     {
12757         /* Intersect the value designated by lvalue sp[0] with sp[-1],
12758          * assign the result to sp[0] and also leave it on the stack.
12759          *
12760          * Possible type combinations:
12761          *   int    & int    -> int
12762          *   string & string -> string
12763          *   array  & array  -> array
12764          *   array  & mapping -> array
12765          *   mapping & array -> mapping
12766          *   mapping & mapping -> mapping
12767          */
12768 
12769         svalue_t *argp;
12770 
12771 #ifdef DEBUG
12772         TYPE_TEST_LEFT(sp, T_LVALUE);
12773 #endif
12774 
12775         /* Set argp to the actual value designated by sp[0] */
12776         for ( argp = sp->u.lvalue
12777             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
12778             ; argp = argp->u.lvalue)
12779             NOOP;
12780 
12781         /* Now do it */
12782         if (argp->type == T_NUMBER)  /* Intersect a number */
12783         {
12784             if (sp[-1].type != T_NUMBER)
12785             {
12786                 OP_ARG_ERROR(2, TF_NUMBER, sp[-1].type);
12787                 /* NOTREACHED */
12788             }
12789             sp--;
12790             sp->u.number = argp->u.number &= sp->u.number;
12791             break;
12792         }
12793 
12794         if (argp->type == T_CHAR_LVALUE)
12795         {
12796             sp--;
12797             if (sp->type != T_NUMBER)
12798             {
12799                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
12800                 /* NOTREACHED */
12801             }
12802             sp->u.number = (unsigned char)(*argp->u.charp &= sp->u.number);
12803             break;
12804         }
12805 
12806         if (argp->type == T_POINTER)
12807         {
12808             /* Intersect an array */
12809 
12810             if (sp[-1].type == T_POINTER)
12811             {
12812                 vector_t *vec1, *vec2;
12813 
12814                 inter_sp = sp - 2;
12815                 vec1 = argp->u.vec;
12816                 vec2 = sp[-1].u.vec;
12817                 argp->type = T_NUMBER;
12818                 vec1 = intersect_array(vec1, vec2);
12819                 put_ref_array(argp, vec1);
12820                 sp--;
12821                 sp->u.vec = argp->u.vec;
12822                 free_svalue(sp+1);
12823             }
12824             else if (sp[-1].type == T_MAPPING)
12825             {
12826                 vector_t *vec;
12827                 mapping_t * map;
12828 
12829                 inter_sp = sp - 2;
12830                 vec = argp->u.vec;
12831                 map = sp[-1].u.map;
12832                 argp->type = T_NUMBER;
12833                 vec = map_intersect_array(vec, map);
12834                 put_ref_array(argp, vec);
12835                 sp--;
12836                 put_array(sp, argp->u.vec);
12837                 free_svalue(sp+1);
12838             }
12839             else
12840             {
12841                 OP_ARG_ERROR(2, TF_POINTER|TF_MAPPING, sp[-1].type);
12842                 /* NOTREACHED */
12843             }
12844             break;
12845         }
12846 
12847         if (argp->type == T_MAPPING)
12848         {
12849             /* Intersect a mapping */
12850 
12851             mapping_t *result;
12852 
12853             if (sp[-1].type != T_POINTER && sp[-1].type != T_MAPPING)
12854             {
12855                 OP_ARG_ERROR(2, TF_MAPPING|TF_POINTER, sp[-1].type);
12856                 /* NOTREACHED */
12857             }
12858 
12859             inter_sp = sp;
12860 
12861             result = map_intersect(argp->u.map, sp-1);
12862 
12863             put_mapping(argp, result);
12864 
12865             free_svalue(sp);
12866             sp--;
12867 
12868             put_ref_mapping(sp, result);
12869             break;
12870         }
12871 
12872         if (argp->type == T_STRING)
12873         {
12874             string_t * result;
12875 
12876             if (sp[-1].type != T_STRING)
12877             {
12878                 OP_ARG_ERROR(2, TF_STRING, sp[-1].type);
12879                 /* NOTREACHED */
12880             }
12881             inter_sp = sp;
12882             result = intersect_strings(argp->u.str, (sp-1)->u.str, MY_FALSE);
12883             free_string_svalue(argp);
12884             put_string(argp, result);
12885             free_svalue(sp);
12886             sp--;
12887             free_string_svalue(sp);
12888             put_ref_string(sp, result);
12889             break;
12890         }
12891 
12892         OP_ARG_ERROR(1, TF_NUMBER|TF_STRING|TF_POINTER, argp->type);
12893         /* NOTREACHED */
12894         break;
12895     }
12896 
12897     CASE(F_OR_EQ);                  /* --- or_eq               --- */
12898     {
12899         /* Binary-Or the value designated by lvalue sp[0] with sp[-1],
12900          * assign the result to sp[0] and also leave it on the stack.
12901          *
12902          * Possible type combinations:
12903          *   int   | int   -> int
12904          *   array | array -> array
12905          */
12906 
12907         svalue_t *argp;
12908 
12909 #ifdef DEBUG
12910         TYPE_TEST_LEFT(sp, T_LVALUE);
12911 #endif
12912 
12913         /* Set argp to the actual value designated by sp[0] */
12914         for ( argp = sp->u.lvalue
12915             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
12916             ; argp = argp->u.lvalue)
12917             NOOP;
12918 
12919         /* Now do it */
12920         if (argp->type == T_NUMBER)
12921         {
12922             sp--;
12923             if (sp->type != T_NUMBER)
12924             {
12925                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
12926                 /* NOTREACHED */
12927             }
12928             sp->u.number = argp->u.number |= sp->u.number;
12929             break;
12930         }
12931 
12932         if (argp->type == T_CHAR_LVALUE)
12933         {
12934             sp--;
12935             if (sp->type != T_NUMBER)
12936             {
12937                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
12938                 /* NOTREACHED */
12939             }
12940             sp->u.number = (unsigned char)(*argp->u.charp |= sp->u.number);
12941             break;
12942         }
12943 
12944         if (argp->type == T_POINTER)
12945         {
12946             /* Join an array */
12947 
12948             vector_t *vec1, *vec2;
12949 
12950             if (sp[-1].type != T_POINTER)
12951             {
12952                 OP_ARG_ERROR(2, TF_POINTER, sp[-1].type);
12953                 /* NOTREACHED */
12954             }
12955             inter_sp = sp;
12956             inter_pc = pc;
12957             vec1 = argp->u.vec;
12958             vec2 = sp[-1].u.vec;
12959             vec1 = join_array(vec1, vec2);
12960               /* The new vec1 may be one of the original vec1 or vec2 */
12961             put_ref_array(argp, vec1);
12962             sp--;
12963             sp->u.vec = argp->u.vec;
12964             free_svalue(sp+1);
12965             break;
12966         }
12967 
12968         OP_ARG_ERROR(1, TF_NUMBER|TF_POINTER, argp->type);
12969         /* NOTREACHED */
12970         break;
12971     }
12972 
12973     CASE(F_XOR_EQ);                 /* --- xor_eq              --- */
12974     {
12975         /* Binary-XOr the value designated by lvalue sp[0] with sp[-1],
12976          * assign the result to sp[0] and also leave it on the stack.
12977          *
12978          * Possible type combinations:
12979          *   int   ^ int   -> int
12980          *   array ^ array -> array
12981          *
12982          * TODO: Extend this to mappings.
12983          */
12984 
12985         svalue_t *argp;
12986 
12987 #ifdef DEBUG
12988         TYPE_TEST_LEFT(sp, T_LVALUE);
12989 #endif
12990 
12991         /* Set argp to the actual value designated by sp[0] */
12992         for ( argp = sp->u.lvalue
12993             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
12994             ; argp = argp->u.lvalue)
12995             NOOP;
12996 
12997         /* Now do it */
12998         if (argp->type == T_NUMBER)
12999         {
13000             sp--;
13001             if (sp->type != T_NUMBER)
13002             {
13003                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
13004                 /* NOTREACHED */
13005             }
13006             sp->u.number = argp->u.number ^= sp->u.number;
13007             break;
13008         }
13009 
13010         if (argp->type == T_CHAR_LVALUE)
13011         {
13012             sp--;
13013             if (sp->type != T_NUMBER)
13014             {
13015                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
13016                 /* NOTREACHED */
13017             }
13018             sp->u.number = (unsigned char)(*argp->u.charp ^= sp->u.number);
13019             break;
13020         }
13021 
13022         if (argp->type == T_POINTER)
13023         {
13024             /* Symm-diff an array */
13025 
13026             vector_t *vec1, *vec2;
13027 
13028             if (sp[-1].type != T_POINTER)
13029             {
13030                 OP_ARG_ERROR(2, TF_POINTER, sp[-1].type);
13031                 /* NOTREACHED */
13032             }
13033             inter_sp = sp - 2;
13034             vec1 = argp->u.vec;
13035             vec2 = sp[-1].u.vec;
13036             argp->type = T_NUMBER;
13037             vec1 = symmetric_diff_array(vec1, vec2);
13038             put_ref_array(argp, vec1);
13039             sp--;
13040             sp->u.vec = argp->u.vec;
13041             free_svalue(sp+1);
13042             break;
13043         }
13044 
13045         OP_ARG_ERROR(1, TF_NUMBER|TF_POINTER, argp->type);
13046         /* NOTREACHED */
13047         break;
13048     }
13049 
13050     CASE(F_LSH_EQ);                 /* --- lsh_eq              --- */
13051     {
13052         /* Shift the value designated by lvalue sp[0] left by sp[-1],
13053          * assign the result to sp[0] and also leave it on the stack.
13054          *
13055          * Possible type combinations:
13056          *   int        << int                -> int
13057          *
13058          * TODO: Implement an arithmetic shift.
13059          */
13060 
13061         int i;
13062         svalue_t *argp;
13063 
13064 #ifdef DEBUG
13065         TYPE_TEST_LEFT(sp, T_LVALUE);
13066 #endif
13067 
13068         /* Set argp to the actual value designated by sp[0] */
13069         for ( argp = sp->u.lvalue
13070             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
13071             ; argp = argp->u.lvalue)
13072             NOOP;
13073 
13074         /* Now do it */
13075         if (argp->type == T_NUMBER)
13076         {
13077             sp--;
13078             if (sp->type != T_NUMBER)
13079             {
13080                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
13081                 /* NOTREACHED */
13082             }
13083             i = sp->u.number;
13084             argp->u.number <<= (uint)i > MAX_SHIFT ? (int)MAX_SHIFT : i;
13085             sp->u.number = argp->u.number;
13086             break;
13087         }
13088 
13089         if (argp->type == T_CHAR_LVALUE)
13090         {
13091             sp--;
13092             if (sp->type != T_NUMBER)
13093             {
13094                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
13095                 /* NOTREACHED */
13096             }
13097             i = sp->u.number;
13098             *argp->u.charp <<= (uint)i > MAX_SHIFT ? (int)MAX_SHIFT : i;
13099             sp->u.number = (unsigned char)(*argp->u.charp);
13100             break;
13101         }
13102 
13103         OP_ARG_ERROR(1, TF_NUMBER, argp->type);
13104         /* NOTREACHED */
13105         break;
13106     }
13107 
13108     CASE(F_RSH_EQ);                 /* --- rsh_eq              --- */
13109     {
13110         /* Arithmetically shift the value designated by lvalue sp[0] right by
13111          * sp[-1], assign the result to sp[0] and also leave it on the stack.
13112          *
13113          * Possible type combinations:
13114          *   int        << int                -> int
13115          */
13116 
13117         int i;
13118         svalue_t *argp;
13119 
13120 #ifdef DEBUG
13121         TYPE_TEST_LEFT(sp, T_LVALUE);
13122 #endif
13123 
13124         /* Set argp to the actual value designated by sp[0] */
13125         for ( argp = sp->u.lvalue
13126             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
13127             ; argp = argp->u.lvalue)
13128             NOOP;
13129 
13130         /* Now do it */
13131         if (argp->type == T_NUMBER)
13132         {
13133             sp--;
13134             if (sp->type != T_NUMBER)
13135             {
13136                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
13137                 /* NOTREACHED */
13138             }
13139             i = sp->u.number;
13140             argp->u.number >>= (uint)i > MAX_SHIFT ? (int)(MAX_SHIFT+1) : i;
13141             sp->u.number = argp->u.number;
13142             break;
13143         }
13144 
13145         if (argp->type == T_CHAR_LVALUE)
13146         {
13147             sp--;
13148             if (sp->type != T_NUMBER)
13149             {
13150                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
13151                 /* NOTREACHED */
13152             }
13153             i = sp->u.number;
13154             *argp->u.charp >>= (uint)i > MAX_SHIFT ? (int)MAX_SHIFT : i;
13155             sp->u.number = (unsigned char)(*argp->u.charp);
13156             break;
13157         }
13158 
13159         OP_ARG_ERROR(1, TF_NUMBER, argp->type);
13160         /* NOTREACHED */ break;
13161     }
13162 
13163     CASE(F_RSHL_EQ);               /* --- rshl_eq              --- */
13164     {
13165         /* Logically shift the value designated by lvalue sp[0] right by
13166          * sp[-1], assign the result to sp[0] and also leave it on the stack.
13167          *
13168          * Possible type combinations:
13169          *   int        << int                -> int
13170          */
13171 
13172         int i;
13173         svalue_t *argp;
13174 #ifdef DEBUG
13175         TYPE_TEST_LEFT(sp, T_LVALUE);
13176 #endif
13177 
13178         /* Set argp to the actual value designated by sp[0] */
13179         for ( argp = sp->u.lvalue
13180             ; T_LVALUE == argp->type || T_PROTECTED_LVALUE == argp->type
13181             ; argp = argp->u.lvalue)
13182             NOOP;
13183 
13184         /* Now do it */
13185         if (argp->type == T_NUMBER)
13186         {
13187             sp--;
13188             if (sp->type != T_NUMBER)
13189             {
13190                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
13191                 /* NOTREACHED */
13192             }
13193             i = sp->u.number;
13194             if ((uint)i > MAX_SHIFT)
13195                 argp->u.number = 0;
13196             else
13197                 argp->u.number = (p_uint)argp->u.number >> i;
13198             sp->u.number = argp->u.number;
13199             break;
13200         }
13201 
13202         if (argp->type == T_CHAR_LVALUE)
13203         {
13204             sp--;
13205             if (sp->type != T_NUMBER)
13206             {
13207                 OP_ARG_ERROR(2, TF_NUMBER, sp->type);
13208                 /* NOTREACHED */
13209             }
13210             i = sp->u.number;
13211             if ((uint)i > MAX_SHIFT)
13212                 *argp->u.charp = 0;
13213             else
13214                 *argp->u.charp = (p_uint)*argp->u.charp >> i;
13215             sp->u.number = (unsigned char)*argp->u.charp;
13216             break;
13217         }
13218 
13219         OP_ARG_ERROR(1, TF_NUMBER, argp->type);
13220         /* NOTREACHED */
13221         break;
13222     }
13223 
13224     /* --- Machine internal instructions --- */
13225 
13226     CASE(F_POP_VALUE);              /* --- pop_value           --- */
13227         /* Pop the topmost value from the stack (freeing it).
13228          * Simple, huh?
13229          */
13230         pop_stack();
13231         break;
13232 
13233     CASE(F_POP_SECOND);             /* --- pop_second          --- */
13234         /* Pop the value under the topmost value and put the
13235          * topmost value there.
13236          */
13237         free_svalue(--sp);
13238         *sp = sp[1];
13239         break;
13240 
13241     CASE(F_DUP);                    /* --- dup                 --- */
13242         /* Push a duplicate of sp[0] onto the stack.
13243          */
13244         sp++;
13245         assign_svalue_no_free(sp, sp-1);
13246         break;
13247 
13248     CASE(F_LDUP);                   /* --- ldup                --- */
13249       {
13250         /* Push a duplicate of sp[0] onto the stack.
13251          * If sp[0] is an lvalue, it is derefenced first.
13252          */
13253         svalue_t * svp = sp;
13254         sp++;
13255         while (svp->type == T_LVALUE || svp->type == T_PROTECTED_LVALUE)
13256             svp = svp->u.lvalue;
13257         assign_svalue_no_free(sp, svp);
13258         break;
13259       }
13260 
13261     CASE(F_SWAP_VALUES);            /* --- swap_values         --- */
13262       {
13263         /* Swap sp[0] and sp[-1] on the stack.
13264          */
13265         svalue_t sv = sp[0];
13266         sp[0] = sp[-1];
13267         sp[-1] = sv;
13268         break;
13269       }
13270 
13271     CASE(F_CLEAR_LOCALS);    /* --- clear_locals <first> <num> --- */
13272       {
13273         /* Set the local variables <first> .. <first>+<num>-1 back
13274          * to svalue-0. This is used to initalize local variables
13275          * of nested scopes.
13276          */
13277         int first, num;
13278         svalue_t *plocal;
13279 
13280         first = LOAD_UINT8(pc);
13281         num = LOAD_UINT8(pc);
13282 
13283         for (plocal = fp+first; num > 0; num--, plocal++)
13284         {
13285             free_svalue(plocal);
13286             *plocal = const0;
13287         }
13288         break;
13289       }
13290 
13291     CASE(F_SAVE_ARG_FRAME);         /* --- save_arg_frame      --- */
13292       {
13293         /* Save the current value of ap on the stack and set ap to
13294          * the next stack entry.
13295          */
13296 
13297         ++sp;
13298         sp->type = T_INVALID;
13299         sp->u.lvalue = ap;
13300         ap = sp+1;
13301         break;
13302       }
13303 
13304     CASE(F_RESTORE_ARG_FRAME);      /* --- restore_arg_frame   --- */
13305       {
13306         /* While sp points at a function result, restore the value
13307          * of ap from sp[-1]; then move the result down there.
13308          */
13309 
13310         ap = sp[-1].u.lvalue;
13311         sp[-1] = sp[0];
13312         sp--;
13313         break;
13314       }
13315 
13316     CASE(F_USE_ARG_FRAME);          /* --- use_arg_frame       --- */
13317       {
13318         /* Used as a prefix (and only as a prefix) to instructions which
13319          * usually know or take the number of arguments from the bytecode.
13320          * With this prefix, the instruction uses the difference between
13321          * sp and ap as the real number of arguments.
13322          *
13323          * use_arg_frame is recognized by: simul_efun, efun{0,1,2,3,4,v}.
13324          */
13325 
13326 #ifdef DEBUG
13327         if (use_ap)
13328             fatal("Previous use_arg_frame hasn't been consumed.\n");
13329 #endif
13330         use_ap = MY_TRUE;
13331         break;
13332       }
13333 
13334     CASE(F_FLATTEN_XARG);           /* --- flatten_xarg        --- */
13335       {
13336         /* Take the value at sp and if it is an array, put
13337          * the array's contents onto the stack in its place. Other values stay
13338          * as they are.
13339          * This code is used in conjunction with save/restore/use_arg_frame
13340          * to implement flexible varargs.
13341          */
13342 
13343         if (sp->type == T_POINTER)
13344         {
13345             /* The argument is an array: flatten it */
13346 
13347             vector_t *vec;  /* the array */
13348             svalue_t *svp;  /* pointer into the array */
13349             p_int i;         /* (remaining) vector size */
13350 
13351             vec = sp->u.vec;
13352             i = VEC_SIZE(vec);
13353 
13354             /* Check if there is enough space on the stack.
13355              */
13356             if (i + (sp - VALUE_STACK) >= EVALUATOR_STACK_SIZE)
13357             {
13358                 errorf("VM Stack overflow: %"PRIdMPINT" too high.\n"
13359                      , ((mp_int)i + (sp - VALUE_STACK) - EVALUATOR_STACK_SIZE) );
13360                 /* NOTREACHED */
13361                 break;
13362             }
13363 
13364             /* Push the array elements onto the stack, overwriting the
13365              * array value itself.
13366              */
13367             if (deref_array(vec))
13368             {
13369                 for (svp = vec->item; --i >= 0; )
13370                 {
13371                     if (destructed_object_ref(svp))
13372                     {
13373                         put_number(sp, 0);
13374                         sp++;
13375                         svp++;
13376                     }
13377                     else
13378                         assign_svalue_no_free(sp++, svp++);
13379                 }
13380             }
13381             else
13382             {
13383                 /* The array will be freed, so use a faster function */
13384                 for (svp = vec->item; --i >= 0; ) {
13385                     if (destructed_object_ref(svp))
13386                     {
13387                         put_number(sp, 0);
13388                         sp++;
13389                         svp++;
13390                     }
13391                     else
13392                         transfer_svalue_no_free(sp++, svp++);
13393                 }
13394                 free_empty_vector(vec);
13395             }
13396 
13397             sp--; /* undo the last extraneous sp++ */
13398         }
13399         break;
13400       }
13401 
13402     CASE(F_FBRANCH);                /* --- fbranch <offset>    --- */
13403     {
13404         /* Jump by (32-Bit) long <offset> bytes.
13405          * The <offset> is counted from its first byte (TODO: Ugh).
13406          */
13407 
13408         long offset;
13409 
13410         GET_LONG(offset, pc);
13411         pc += offset;
13412         break;
13413     }
13414 
13415     CASE(F_LBRANCH);                /* --- lbranch <offset>    --- */
13416     {
13417         /* Jump by (16-Bit) short <offset> bytes.
13418          * The <offset> is counted from its first byte (TODO: Ugh).
13419          */
13420 
13421         short offset;
13422 
13423         GET_SHORT(offset, pc);
13424         pc += offset;
13425         break;
13426     }
13427 
13428     CASE(F_LBRANCH_WHEN_ZERO); /* --- lbranch_when_zero <offset> --- */
13429     {
13430         /* Jump by (16-Bit) short <offset> bytes if sp[0] is number 0.
13431          * The <offset> is counted from its first byte (TODO: Ugh).
13432          * sp[0] is popped from the stack.
13433          */
13434 
13435         short offset;
13436 
13437         if (sp->type == T_NUMBER && sp->u.number == 0)
13438         {
13439             GET_SHORT(offset, pc);
13440             pc += offset;
13441             sp--;
13442             break;
13443         }
13444         pc += 2;
13445         pop_stack();
13446         break;
13447     }
13448 
13449     CASE(F_LBRANCH_WHEN_NON_ZERO); /* --- lbranch_when_non_zero <offset> --- */
13450     {
13451         /* Jump by (16-Bit) short <offset> bytes if sp[0] is not number 0.
13452          * The <offset> is counted from its first byte (TODO: Ugh).
13453          * sp[0] is popped from the stack.
13454          */
13455 
13456         short offset;
13457 
13458         if (sp->type != T_NUMBER || sp->u.number != 0)
13459         {
13460             GET_SHORT(offset, pc);
13461             pc += offset;
13462             pop_stack();
13463             break;
13464         }
13465         pc += 2;
13466         sp--;
13467         break;
13468     }
13469 
13470     CASE(F_BRANCH);                 /* --- branch <offset>     --- */
13471     {
13472         /* Jump forward by uint8 <offset> bytes.
13473          * The <offset> is counted from the next instruction.
13474          */
13475 
13476         pc += GET_UINT8(pc)+1;
13477         break;
13478     }
13479 
13480     CASE(F_BRANCH_WHEN_ZERO); /* --- branch_when_zero <offset> --- */
13481     {
13482         /* Jump forward by uint8 <offset> bytes if sp[0] is number 0.
13483          * The <offset> is counted from the next instruction.
13484          * sp[0] is popped from the stack.
13485          */
13486 
13487         if (sp->type == T_NUMBER)
13488         {
13489             if (sp->u.number == 0)
13490             {
13491                 sp--;
13492                 pc += GET_UINT8(pc) + 1;
13493                 break;
13494             }
13495             sp--;
13496             pc++;
13497             break;
13498         }
13499         else
13500         {
13501             free_svalue(sp);
13502             sp--;
13503             pc++;
13504             break;
13505         }
13506     }
13507 
13508     CASE(F_BRANCH_WHEN_NON_ZERO); /* --- branch_when_non_zero <offset> --- */
13509     {
13510         /* Jump forward by uint8 <offset> bytes if sp[0] is not number 0.
13511          * The <offset> is counted from the next instruction.
13512          * sp[0] is popped from the stack.
13513          */
13514 
13515         if (sp->type == T_NUMBER)
13516         {
13517             if (sp->u.number == 0)
13518             {
13519                 sp--;
13520                 pc++;
13521                 break;
13522             }
13523         }
13524         else
13525         {
13526             free_svalue(sp);
13527         }
13528         sp--;
13529         pc += GET_UINT8(pc) + 1;
13530         break;
13531     }
13532 
13533     CASE(F_BBRANCH_WHEN_ZERO);  /* --- bbranch_when_zero <offset> --- */
13534     {
13535         /* Jump backward by uint8 <offset> bytes if sp[0] is number 0.
13536          * The <offset> is counted from its first byte (TODO: Ugh).
13537          * sp[0] is popped from the stack.
13538          */
13539 
13540         if (sp->type == T_NUMBER && sp->u.number == 0)
13541         {
13542             sp--;
13543             pc -= GET_UINT8(pc);
13544             break;
13545         }
13546         pc += 1;
13547         pop_stack();
13548         break;
13549     }
13550     CASE(F_BBRANCH_WHEN_NON_ZERO); /* --- branch_when_non_zero <offset> --- */
13551     {
13552         /* Jump backward by uint8 <offset> bytes if sp[0] is not number 0.
13553          * The <offset> is counted from its first byte (TODO: Ugh).
13554          * sp[0] is popped from the stack.
13555          */
13556 
13557         if (sp->type == T_NUMBER)
13558         {
13559             if (sp->u.number == 0)
13560             {
13561                 pc += 1;
13562                 sp--;
13563                 break;
13564             }
13565         }
13566         else
13567             free_svalue(sp);
13568         sp--;
13569         pc -= GET_UINT8(pc);
13570         break;
13571     }
13572 
13573     CASE(F_CALL_FUNCTION)         /* --- call_function <index> --- */
13574     {
13575         /* Call the function <index> with the arguments on the stack.
13576          * <index> is a (16-Bit) unsigned short, giving the index within
13577          * the programs function table. The number of arguments is determined
13578          * through the ap pointer.
13579          *
13580          * Since the function may be redefined through inheritance, the
13581          * function must be searched in the current_objects program, which
13582          * might not be the current_program.
13583          */
13584 
13585         unsigned short func_index;   /* function index within program */
13586         unsigned short func_offset;
13587           /* function index within the current object's program.
13588            * This way local function may be redefined through inheritance.
13589            */
13590         funflag_t  flags;     /* the function flags */
13591         fun_hdr_p  funstart;  /* the actual function (code) */
13592 
13593         /* Make sure that we are not calling from a set_this_object()
13594          * context.
13595          */
13596         if (is_sto_context())
13597         {
13598             ERROR("call_function: Can't execute with "
13599                   "set_this_object() in effect.\n"
13600                  );
13601         }
13602 
13603         /* Get the function's index */
13604         LOAD_SHORT(func_index, pc);
13605         func_offset = (unsigned short)(func_index + function_index_offset);
13606 
13607         /* Find the function in the function table. As the function may have
13608          * been redefined by inheritance, we must look in the last table,
13609          * which is pointed to by current_object.
13610          */
13611 
13612         if (func_offset >= current_object->prog->num_functions)
13613         {
13614             fatal("call_function: "
13615                   "Illegal function index: offset %hu (index %hu), "
13616                   "%d functions - current object %s\n"
13617                  , func_offset, func_index
13618                  , current_object->prog->num_functions
13619                  , get_txt(current_object->name)
13620                  );
13621         }
13622 
13623         /* NOT current_prog, which can be an inherited object. */
13624         flags = current_object->prog->functions[func_offset];
13625 
13626         /* If the function was cross-defined, get the real offset */
13627         if (flags & NAME_CROSS_DEFINED)
13628         {
13629             func_offset += CROSSDEF_NAME_OFFSET(flags);
13630         }
13631 
13632         /* Save all important global stack machine registers */
13633 #ifdef USE_NEW_INLINES
13634         push_control_stack(sp, pc, fp, inter_context);
13635 #else
13636         push_control_stack(sp, pc, fp);
13637 #endif /* USE_NEW_INLINES */
13638 
13639         /* Set the current program back to the objects program _after_
13640          * the control stack push, since here is where we search for
13641          * the function.
13642          */
13643         current_prog = current_object->prog;
13644 
13645         /* Search for the function definition and determine the offsets.
13646          */
13647         csp->num_local_variables = sp - ap + 1;
13648         flags = setup_new_frame1(func_offset, 0, 0);
13649         funstart = (fun_hdr_p)(current_prog->program + (flags & FUNSTART_MASK));
13650         csp->funstart = funstart;
13651 
13652         /* Setup the stack, arguments and local vars */
13653         sp = setup_new_frame2(funstart, sp, MY_FALSE, MY_FALSE);
13654 
13655         /* Finish the setup */
13656 
13657 #ifdef DEBUG
13658         if (!current_object->variables && variable_index_offset)
13659             fatal("%s Fatal: call function for object %p '%s' w/o variables, "
13660                   "but offset %d\n"
13661                  , time_stamp(), current_object, get_txt(current_object->name)
13662                  , variable_index_offset);
13663 #endif
13664         current_variables = current_object->variables;
13665         if (current_variables)
13666             current_variables += variable_index_offset;
13667         current_strings = current_prog->strings;
13668         fp = inter_fp;
13669         pc = FUNCTION_CODE(funstart);
13670         csp->extern_call = MY_FALSE;
13671         break;
13672     }
13673 
13674                    /* --- call_inherited        <prog> <index> --- */
13675                    /* --- call_inherited_noargs <prog> <index> --- */
13676     CASE(F_CALL_INHERITED);
13677     CASE(F_CALL_INHERITED_NOARGS);
13678     {
13679         /* Call the (inherited) function <index> in program <prog> with
13680          * the arguments on the stack; or for the _noargs code, with no
13681          * arguments.
13682          *
13683          * <index> is a (16-Bit) unsigned short, giving the index within
13684          * the programs function table.
13685          * <prog> is a (16-Bit) unsigned short, giving the index within
13686          * the current programs inherit table.
13687          *
13688          * The number of arguments, if needed, is determined through the
13689          * ap pointer.
13690          *
13691          * The _noargs code is used to implement wildcarded
13692          * super calls, which take no argument, but store their results
13693          * above the ap. Without this extra bytecode, the normal argument
13694          * massaging would remove the intermediate results.
13695          */
13696 
13697         unsigned short prog_index;  /* Index within the inherit table */
13698         unsigned short func_index;  /* Index within the function table */
13699         funflag_t flags;            /* the functions flags */
13700         fun_hdr_p funstart;         /* the actual function (code) */
13701         inherit_t *inheritp;        /* the inheritance descriptor */
13702 
13703         /* Make sure that we are not calling from a set_this_object()
13704          * context.
13705          */
13706         if (is_sto_context())
13707         {
13708             ERROR("call_inherited: Can't execute with "
13709                   "set_this_object() in effect.\n"
13710                  );
13711         }
13712 
13713         /* Get the program and function index, and determine the
13714          * inheritance descriptor
13715          */
13716         LOAD_SHORT(prog_index, pc);
13717         LOAD_SHORT(func_index, pc);
13718 
13719 #ifdef DEBUG
13720         inheritp = &current_prog->inherit[prog_index];
13721         if (func_index >= inheritp->prog->num_functions)
13722         {
13723             fatal("call_inherited: Illegal function index: "
13724                   "program %d, func %d, %d functions\n"
13725                  , prog_index, func_index, inheritp->prog->num_functions);
13726         }
13727 #endif
13728 
13729         /* Save all important global stack machine registers */
13730 #ifdef USE_NEW_INLINES
13731         push_control_stack(sp, pc, fp, inter_context);
13732 #else
13733         push_control_stack(sp, pc, fp);
13734 #endif /* USE_NEW_INLINES */
13735 
13736         inheritp = setup_inherited_call(prog_index);
13737 
13738         /* Search for the function definition and determine the offsets.
13739          */
13740         if (instruction != F_CALL_INHERITED_NOARGS)
13741             csp->num_local_variables = sp - ap + 1;
13742         else
13743             csp->num_local_variables = 0;
13744         flags = setup_new_frame1(
13745           func_index,
13746           function_index_offset + inheritp->function_index_offset,
13747           inheritp->variable_index_offset
13748         );
13749         funstart = (fun_hdr_p)(current_prog->program + (flags & FUNSTART_MASK));
13750         csp->funstart = funstart;
13751 
13752         /* Setup the stack, arguments and local vars */
13753         sp = setup_new_frame2(funstart, sp, MY_FALSE, MY_FALSE);
13754 
13755         /* Finish the setup */
13756         fp = inter_fp;
13757         pc = FUNCTION_CODE(funstart);
13758         current_variables += variable_index_offset;
13759         current_strings = current_prog->strings;
13760         csp->extern_call = MY_FALSE;
13761         break;
13762     }
13763 
13764     CASE(F_CALL_CLOSURE); /* --- call_closure --- */
13765         /* Call the closure on the stack with the arguments on the stack.
13766          * Just like funcall(), but as an internal call.
13767          * We leave the closure an the stack for a following F_POP_SECOND
13768          * to clear it up. This instruction is only used by lambda closures.
13769          */
13770     {
13771         num_arg = sp - ap;
13772 
13773         if (ap->type == T_CLOSURE)
13774         {
13775             inter_sp = sp;
13776 
13777             /* No external calls may be done when this object is
13778              * destructed.
13779              */
13780             if (current_object->flags & O_DESTRUCTED)
13781             {
13782                 sp = _pop_n_elems(num_arg, sp);
13783                 push_number(sp, 0);
13784                 inter_sp = sp;
13785                 warnf("Call from destructed object '%s' ignored.\n"
13786                      , get_txt(current_object->name));
13787                 return sp;
13788             }
13789 
13790             /* Call the closure and push the result.
13791              * Note that the closure might destruct itself.
13792              */
13793             inter_pc = pc;
13794 
13795             int_call_lambda(ap, num_arg, MY_FALSE, MY_FALSE);
13796 
13797             pc = inter_pc;
13798             sp = inter_sp;
13799             fp = inter_fp;
13800         }
13801         else
13802         {
13803             /* Not a closure: pop the excess args and return <cl>
13804              * as result.
13805              */
13806 
13807             sp = _pop_n_elems(num_arg, sp);
13808             push_number(sp, 0);
13809         }
13810 
13811         break;
13812     }
13813 
13814 
13815 
13816 #ifdef USE_NEW_INLINES
13817     CASE(F_CONTEXT_IDENTIFIER);  /* --- context_identifier <var_ix> --- */
13818         /* Push value of context variable <var_ix>.
13819          * It is possible that it is a variable that points to
13820          * a destructed object. In that case, it has to be replaced by 0.
13821          *
13822          * <var_ix> is a uint8.
13823          */
13824 
13825         if (inter_context == NULL)
13826             errorf("(eval_instruction) context_identifier: "
13827                   "inter_context is NULL\n");
13828             /* May happen if somebody does a funcall(symbol_function())
13829              * on the lfun of an context closure.
13830              */
13831 
13832         sp++;
13833         assign_checked_svalue_no_free(sp, inter_context+LOAD_UINT8(pc));
13834         break;
13835 
13836                                /* --- context_identifier16 <var_ix> --- */
13837     CASE(F_CONTEXT_IDENTIFIER16);
13838       {
13839         /* Push value of context variable <var_ix>.
13840          * It is possible that it is a variable that points to
13841          * a destructed object. In that case, it has to be replaced by 0.
13842          *
13843          * <var_ix> is a (16-Bit) unsigned short.
13844          */
13845         unsigned short var_index;
13846 
13847 
13848         if (inter_context == NULL)
13849             errorf("(eval_instruction) context_identifier16: "
13850                   "inter_context is NULL\n");
13851             /* May happen if somebody does a funcall(symbol_function())
13852              * on the lfun of an context closure.
13853              */
13854 
13855         LOAD_SHORT(var_index, pc);
13856         sp++;
13857         assign_checked_svalue_no_free(sp, inter_context+var_index);
13858         break;
13859      }
13860 
13861     CASE(F_PUSH_CONTEXT_LVALUE);   /* --- push_context_lvalue <num> --- */
13862         /* Push an lvalue onto the stack pointing to context variable <num>.
13863          *
13864          * <num> is an uint8.
13865          */
13866 
13867         if (inter_context == NULL)
13868             errorf("(eval_instruction) context_identifier: "
13869                   "inter_context is NULL\n");
13870             /* May happen if somebody does a funcall(symbol_function())
13871              * on the lfun of an context closure.
13872              */
13873 
13874         sp++;
13875         sp->type = T_LVALUE;
13876         sp->u.lvalue = inter_context + LOAD_UINT8(pc);
13877         break;
13878 
13879                                  /* --- push_context16_lvalue <num> --- */
13880     CASE(F_PUSH_CONTEXT16_LVALUE);
13881       {
13882         /* Push an lvalue onto the stack pointing to context variable <num>.
13883          *
13884          * <num> is an (16-Bit) unsigned short.
13885          */
13886         unsigned short var_index;
13887 
13888 
13889         if (inter_context == NULL)
13890             errorf("(eval_instruction) context_identifier: "
13891                   "inter_context is NULL\n");
13892             /* May happen if somebody does a funcall(symbol_function())
13893              * on the lfun of an context closure.
13894              */
13895 
13896         LOAD_SHORT(var_index, pc);
13897         sp++;
13898         sp->type = T_LVALUE;
13899         sp->u.lvalue = inter_context + var_index;
13900         break;
13901       }
13902 
13903 #endif /* USE_NEW_INLINES */
13904 
13905     CASE(F_PUSH_IDENTIFIER_LVALUE);  /* --- push_identifier_lvalue <num> --- */
13906         /* Push an lvalue onto the stack pointing to object-global variable
13907          * <num>.
13908          *
13909          * <num> is an uint8 and used as index in the current objects
13910          * variable table.
13911          */
13912         sp++;
13913         sp->type = T_LVALUE;
13914         sp->u.lvalue = find_value((int)(LOAD_UINT8(pc) ));
13915         break;
13916 
13917     CASE(F_VIRTUAL_VARIABLE);         /* --- virtual_variable <num> --- */
13918         /* Push the virtual object-global variable <num> onto the stack.
13919          * It is possible that it is a variable that points to
13920          * a destructed object. In that case, it has to be replaced by 0.
13921          *
13922          * <num> is an uint8 and used as index in the current objects
13923          * variable table.
13924          */
13925         sp++;
13926         assign_checked_svalue_no_free(sp
13927                                      , find_virtual_value((int)(LOAD_UINT8(pc)))
13928         );
13929         break;
13930 
13931                           /* --- push_virtual_variable_lvalue <num> --- */
13932     CASE(F_PUSH_VIRTUAL_VARIABLE_LVALUE);
13933         /* Push an lvalue onto the stack pointing to virtual object-global
13934          * variable <num>.
13935          *
13936          * <num> is an uint8 and used as index in the current objects
13937          * variable table.
13938          */
13939         sp++;
13940         sp->type = T_LVALUE;
13941         sp->u.lvalue = find_virtual_value((int)(LOAD_UINT8(pc) ));
13942         break;
13943 
13944     CASE(F_IDENTIFIER16);         /* --- identifier16 <var_ix> --- */
13945     {
13946         /* Push value of object variable <var_ix>.
13947          * It is possible that it is a variable that points to
13948          * a destructed object. In that case, it has to be replaced by 0.
13949          *
13950          * <var_ix> is a (16-Bit) unsigned short.
13951          */
13952         unsigned short var_index;
13953 
13954         LOAD_SHORT(var_index, pc);
13955         sp++;
13956         assign_checked_svalue_no_free(sp, find_value((int)var_index));
13957         break;
13958     }
13959 
13960                        /* --- push_identifier16_lvalue <var_ix> --- */
13961     CASE(F_PUSH_IDENTIFIER16_LVALUE);
13962     {
13963         /* Push an lvalue onto the stack pointing to object-global variable
13964          * <num>.
13965          *
13966          * <num> is an uint8 and used as index in the current objects
13967          * variable table.
13968          */
13969         unsigned short var_index;
13970 
13971         LOAD_SHORT(var_index, pc);
13972         sp++;
13973         sp->type = T_LVALUE;
13974         sp->u.lvalue = find_value((int)var_index);
13975         break;
13976     }
13977                          /* --- push_local_variable_lvalue <num> --- */
13978     CASE(F_PUSH_LOCAL_VARIABLE_LVALUE);
13979         /* Push an lvalue onto the stack pointing to local variable <num>.
13980          *
13981          * <num> is an uint8 and used as index onto the framepointer.
13982          */
13983         sp++;
13984         sp->type = T_LVALUE;
13985         sp->u.lvalue = fp + LOAD_UINT8(pc);
13986         break;
13987 
13988 #ifdef USE_STRUCTS
13989     CASE(F_PUSH_INDEXED_S_LVALUE); /* --- push_indexed_s_lvalue --- */
13990         /* Op. (struct v=sp[-2], mixed i=sp[-1], short idx=sp[0])
13991          *
13992          * Compute the lvalue &(v[i]) and push it into the stack. If v has
13993          * just one ref left, the indexed item is stored in indexing_quickfix
13994          * and the lvalue refers to that variable.
13995          *
13996          * <idx> gives the index of the expected struct type - the
13997          * operator accepts a struct of this type, or any of its children.
13998          * An negative <idx> accepts any struct.
13999          */
14000 
14001         sp = check_struct_op(sp, 0, -2, pc);
14002         sp = push_indexed_lvalue(sp, pc);
14003         break;
14004 #endif /* USE_STRUCTS */
14005 
14006     CASE(F_PUSH_INDEXED_LVALUE);    /* --- push_indexed_lvalue --- */
14007         /* Operator F_PUSH_INDEXED_LVALUE(vector  v=sp[-1], int   i=sp[0])
14008          * Operator F_PUSH_INDEXED_LVALUE(mapping v=sp[-1], mixed i=sp[0])
14009          *
14010          * Compute the lvalue &(v[i]) and push it into the stack. If v has
14011          * just one ref left, the indexed item is stored in indexing_quickfix
14012          * and the lvalue refers to that variable.
14013          */
14014 
14015 #ifdef USE_STRUCTS
14016         {
14017             svalue_t * svp = sp-1;
14018 
14019             while (svp->type == T_LVALUE || svp->type == T_PROTECTED_LVALUE)
14020                 svp = svp->u.lvalue;
14021             if (svp->type == T_STRUCT)
14022             {
14023                 ERRORF(("Illegal type to []: %s lvalue, "
14024                         "expected string/mapping/vector lvalue.\n"
14025                        , typename(svp->type)
14026                       ));
14027                 /* NOTREACHED */
14028             }
14029         }
14030 #endif /* USE_STRUCTS */
14031         sp = push_indexed_lvalue(sp, pc);
14032         break;
14033 
14034     CASE(F_PUSH_RINDEXED_LVALUE);   /* --- push_rindexed_lvalue --- */
14035         /* Operator F_PUSH_RINDEXED_LVALUE(vector v=sp[-1], int i=sp[0])
14036          *
14037          * Compute the lvalue &(v[<i]) and push it into the stack. If v has
14038          * just one ref left, the indexed item is stored in indexing_quickfix
14039          * and the lvalue refers to that variable.
14040          */
14041 
14042         sp = push_rindexed_lvalue(sp, pc);
14043         break;
14044 
14045     CASE(F_PUSH_AINDEXED_LVALUE);   /* --- push_aindexed_lvalue --- */
14046         /* Operator F_PUSH_AINDEXED_LVALUE(vector v=sp[-1], int i=sp[0])
14047          *
14048          * Compute the lvalue &(v[>i]) and push it into the stack. If v has
14049          * just one ref left, the indexed item is stored in indexing_quickfix
14050          * and the lvalue refers to that variable.
14051          */
14052 
14053         sp = push_aindexed_lvalue(sp, pc);
14054         break;
14055 
14056 #ifdef USE_STRUCTS
14057     CASE(F_INDEX_S_LVALUE);         /* --- index_s_lvalue     --- */
14058         /* Op. (struct &v=sp[0], int i=sp[-2], short * idx=sp[-1])
14059          *
14060          * Compute the index &(v[i]) of lvalue <v> and push it into the stack.
14061          * The computed index is a lvalue itself.
14062          *
14063          * <idx> gives the index of the expected struct type - the
14064          * operator accepts a struct of this type, or any of its children.
14065          * An negative <idx> accepts any struct.
14066          */
14067 
14068         sp = check_struct_op(sp, -1, 1, pc);
14069         sp = index_lvalue(sp, pc);
14070         break;
14071 #endif /* USE_STRUCTS */
14072 
14073     CASE(F_INDEX_LVALUE);           /* --- index_lvalue       --- */
14074         /* Operator F_INDEX_LVALUE (string|vector &v=sp[0], int   i=sp[-1])
14075          *          F_INDEX_LVALUE (mapping       &v=sp[0], mixed i=sp[-1])
14076          *
14077          * Compute the index &(v[i]) of lvalue <v> and push it into the stack.
14078          * The computed index is a lvalue itself.  If <v> is a string-lvalue,
14079          * it is made a malloced string if necessary, and the pushed result
14080          * will be a lvalue pointing to a CHAR_LVALUE stored in
14081          * <special_lvalue>.
14082          */
14083 
14084 #ifdef USE_STRUCTS
14085         {
14086             svalue_t * svp = sp;
14087 
14088             while (svp->type == T_LVALUE || svp->type == T_PROTECTED_LVALUE)
14089                 svp = svp->u.lvalue;
14090             if (svp->type == T_STRUCT)
14091             {
14092                 ERRORF(("Illegal type to []: %s lvalue, "
14093                         "expected string/mapping/vector lvalue.\n"
14094                        , typename(svp->type)
14095                       ));
14096                 /* NOTREACHED */
14097             }
14098         }
14099 #endif /* USE_STRUCTS */
14100         sp = index_lvalue(sp, pc);
14101         break;
14102 
14103     CASE(F_RINDEX_LVALUE);          /* --- rindex_lvalue      --- */
14104         /* Operator F_RINDEX_LVALUE (string|vector &v=sp[0], int   i=sp[-1])
14105          *
14106          * Compute the index &(v[<i]) of lvalue <v> and push it into the
14107          * stack. The computed index is a lvalue itself.
14108          * If <v> is a string-lvalue, it is made a malloced string if
14109          * necessary, and the pushed result will be a lvalue pointing to a
14110          * CHAR_LVALUE stored in <special_lvalue>.
14111          */
14112 
14113         sp = rindex_lvalue(sp, pc);
14114         break;
14115 
14116     CASE(F_AINDEX_LVALUE);          /* --- aindex_lvalue      --- */
14117         /* Operator F_AINDEX_LVALUE (string|vector &v=sp[0], int   i=sp[-1])
14118          *
14119          * Compute the index &(v[>i]) of lvalue <v> and push it into the
14120          * stack. The computed index is a lvalue itself.
14121          * If <v> is a string-lvalue, it is made a malloced string if
14122          * necessary, and the pushed result will be a lvalue pointing to a
14123          * CHAR_LVALUE stored in <special_lvalue>.
14124          */
14125 
14126         sp = aindex_lvalue(sp, pc);
14127         break;
14128 
14129 #ifdef USE_STRUCTS
14130     CASE(F_S_INDEX);                /* --- s_index            --- */
14131         /* Operator F_S_INDEX (struct v=sp[-2], mixed i=sp[-1], short idx=sp[0])
14132          *
14133          * Compute the value (v->i) and push it onto the stack.  If the value
14134          * would be a destructed object, 0 is pushed onto the stack and the
14135          * ref to the object is removed from the struct.
14136          *
14137          * <idx> gives the index of the expected struct type - the
14138          * operator accepts a struct of this type, or any of its children.
14139          * An negative <idx> accepts any struct.
14140          */
14141 
14142         sp = check_struct_op(sp, 0, -2, pc);
14143         sp = push_indexed_value(sp, pc);
14144         break;
14145 #endif /* USE_STRUCTS */
14146 
14147     CASE(F_INDEX);                  /* --- index              --- */
14148         /* Operator F_INDEX (string|vector v=sp[-1], int   i=sp[0])
14149          *          F_INDEX (mapping       v=sp[-1], mixed i=sp[0])
14150          *
14151          * Compute the value (v[i]) and push it onto the stack.  If the value
14152          * would be a destructed object, 0 is pushed onto the stack and the
14153          * ref to the object is removed from the vector/mapping.
14154          *
14155          * Mapping indices may use <indexing_quickfix> for temporary storage.
14156          */
14157 
14158 #ifdef USE_STRUCTS
14159         if ((sp-1)->type == T_STRUCT)
14160         {
14161             ERRORF(("Illegal type to []: %s, expected string/vector/mapping.\n"
14162                    , typename((sp-1)->type)
14163                   ));
14164             /* NOTREACHED */
14165         }
14166 #endif /* USE_STRUCTS */
14167         sp = push_indexed_value(sp, pc);
14168         break;
14169 
14170     CASE(F_RINDEX);                 /* --- rindex              --- */
14171         /* Operator F_RINDEX (string|vector v=sp[0], int   i=sp[-1])
14172          *
14173          * Compute the value (v[<i]) and push it onto the stack.  If the value
14174          * would be a destructed object, 0 is pushed onto the stack and the
14175          * ref to the object is removed from the vector/mapping.
14176          */
14177 
14178         sp = push_rindexed_value(sp, pc);
14179         break;
14180 
14181     CASE(F_AINDEX);                 /* --- aindex              --- */
14182         /* Operator F_AINDEX (string|vector v=sp[0], int   i=sp[-1])
14183          *
14184          * Compute the value (v[<i]) and push it onto the stack.  If the value
14185          * would be a destructed object, 0 is pushed onto the stack and the
14186          * ref to the object is removed from the vector/mapping.
14187          */
14188 
14189         sp = push_aindexed_value(sp, pc);
14190         break;
14191 
14192     CASE(F_RANGE_LVALUE);           /* --- range_lvalue        --- */
14193         /* Operator F_RANGE_LVALUE (string|vector &v=sp[0]
14194          *                         , int i2=sp[-1], i1=sp[-2])
14195          *
14196          * Compute the range &(v[i1..i2]) of lvalue <v> and push it into the
14197          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14198          * <special_lvalue> then is the POINTER_RANGE_- resp.
14199          * STRING_RANGE_LVALUE.
14200          *
14201          * TODO: Four different instructions for this? A single instruction plus
14202          * TODO:: argument would be as well.
14203          */
14204 
14205         inter_pc = pc;
14206         sp = range_lvalue(NN_RANGE, sp);
14207         break;
14208 
14209     CASE(F_NR_RANGE_LVALUE);           /* --- nr_range_lvalue     --- */
14210         /* Operator F_NR_RANGE_LVALUE (string|vector &v=sp[0]
14211          *                         , int i2=sp[-1], i1=sp[-2])
14212          *
14213          * Compute the range &(v[i1..<i2]) of lvalue <v> and push it into the
14214          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14215          * <special_lvalue> then is the POINTER_RANGE_- resp.
14216          * STRING_RANGE_LVALUE.
14217          */
14218 
14219         inter_pc = pc;
14220         sp = range_lvalue(NR_RANGE, sp);
14221         break;
14222 
14223     CASE(F_RN_RANGE_LVALUE);           /* --- rn_range_lvalue     --- */
14224         /* Operator F_RN_RANGE_LVALUE (string|vector &v=sp[0]
14225          *                         , int i2=sp[-1], i1=sp[-2])
14226          *
14227          * Compute the range &(v[<i1..i2]) of lvalue <v> and push it into the
14228          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14229          * <special_lvalue> then is the POINTER_RANGE_- resp.
14230          * STRING_RANGE_LVALUE.
14231          */
14232 
14233         inter_pc = pc;
14234         sp = range_lvalue(RN_RANGE, sp);
14235         break;
14236 
14237     CASE(F_RR_RANGE_LVALUE);           /* --- rr_range_lvalue     --- */
14238         /* Operator F_RR_RANGE_LVALUE (string|vector &v=sp[0]
14239          *                         , int i2=sp[-1], i1=sp[-2])
14240          *
14241          * Compute the range &(v[<i1..<i2]) of lvalue <v> and push it into the
14242          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14243          * <special_lvalue> then is the POINTER_RANGE_- resp.
14244          * STRING_RANGE_LVALUE.
14245          */
14246 
14247         inter_pc = pc;
14248         sp = range_lvalue(RR_RANGE, sp);
14249         break;
14250 
14251     CASE(F_NA_RANGE_LVALUE);           /* --- na_range_lvalue     --- */
14252         /* Operator F_NA_RANGE_LVALUE (string|vector &v=sp[0]
14253          *                         , int i2=sp[-1], i1=sp[-2])
14254          *
14255          * Compute the range &(v[i1..>i2]) of lvalue <v> and push it into the
14256          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14257          * <special_lvalue> then is the POINTER_RANGE_- resp.
14258          * STRING_RANGE_LVALUE.
14259          */
14260 
14261         inter_pc = pc;
14262         sp = range_lvalue(NA_RANGE, sp);
14263         break;
14264 
14265     CASE(F_AN_RANGE_LVALUE);           /* --- an_range_lvalue     --- */
14266         /* Operator F_AN_RANGE_LVALUE (string|vector &v=sp[0]
14267          *                         , int i2=sp[-1], i1=sp[-2])
14268          *
14269          * Compute the range &(v[>i1..i2]) of lvalue <v> and push it into the
14270          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14271          * <special_lvalue> then is the POINTER_RANGE_- resp.
14272          * STRING_RANGE_LVALUE.
14273          */
14274 
14275         inter_pc = pc;
14276         sp = range_lvalue(AN_RANGE, sp);
14277         break;
14278 
14279     CASE(F_RA_RANGE_LVALUE);           /* --- ra_range_lvalue     --- */
14280         /* Operator F_RA_RANGE_LVALUE (string|vector &v=sp[0]
14281          *                         , int i2=sp[-1], i1=sp[-2])
14282          *
14283          * Compute the range &(v[<i1..>i2]) of lvalue <v> and push it into the
14284          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14285          * <special_lvalue> then is the POINTER_RANGE_- resp.
14286          * STRING_RANGE_LVALUE.
14287          */
14288 
14289         inter_pc = pc;
14290         sp = range_lvalue(RA_RANGE, sp);
14291         break;
14292 
14293     CASE(F_AR_RANGE_LVALUE);           /* --- ar_range_lvalue     --- */
14294         /* Operator F_AR_RANGE_LVALUE (string|vector &v=sp[0]
14295          *                         , int i2=sp[-1], i1=sp[-2])
14296          *
14297          * Compute the range &(v[>i1..<i2]) of lvalue <v> and push it into the
14298          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14299          * <special_lvalue> then is the POINTER_RANGE_- resp.
14300          * STRING_RANGE_LVALUE.
14301          */
14302 
14303         inter_pc = pc;
14304         sp = range_lvalue(AR_RANGE, sp);
14305         break;
14306 
14307     CASE(F_AA_RANGE_LVALUE);           /* --- aa_range_lvalue     --- */
14308         /* Operator F_AA_RANGE_LVALUE (string|vector &v=sp[0]
14309          *                         , int i2=sp[-1], i1=sp[-2])
14310          *
14311          * Compute the range &(v[>i1..>i2]) of lvalue <v> and push it into the
14312          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14313          * <special_lvalue> then is the POINTER_RANGE_- resp.
14314          * STRING_RANGE_LVALUE.
14315          */
14316 
14317         inter_pc = pc;
14318         sp = range_lvalue(AA_RANGE, sp);
14319         break;
14320 
14321     CASE(F_NX_RANGE_LVALUE);           /* --- nx_range_lvalue     --- */
14322         /* Operator F_NX_RANGE_LVALUE (string|vector &v=sp[0]
14323          *                            , int i1=sp[-1])
14324          *
14325          * Compute the range &(v[i1..]) of lvalue <v> and push it into the
14326          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14327          * <special_lvalue> then is the POINTER_RANGE_- resp.
14328          * STRING_RANGE_LVALUE.
14329          *
14330          * We implement this by pushing '1' onto the stack and then
14331          * call F_NR_RANGE_LVALUE, effectively computing &(v[i1..<1]).
14332          */
14333 
14334         inter_pc = pc;
14335         sp++;
14336         sp[0] = sp[-1];       /* Pull up the 'v' */
14337         put_number(sp-1, 1);  /* 'Push' the 1 for the upper bound */
14338         sp = range_lvalue(NR_RANGE, sp);
14339         break;
14340 
14341     CASE(F_RX_RANGE_LVALUE);           /* --- rx_range_lvalue     --- */
14342         /* Operator F_RX_RANGE_LVALUE (string|vector &v=sp[0]
14343          *                            , int i1=sp[-1])
14344          *
14345          * Compute the range &(v[<i1..]) of lvalue <v> and push it into the
14346          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14347          * <special_lvalue> then is the POINTER_RANGE_- resp.
14348          * STRING_RANGE_LVALUE.
14349          *
14350          * We implement this by pushing '1' onto the stack and then
14351          * call F_RR_RANGE_LVALUE, effectively computing &(v[<i1..<1]).
14352          */
14353 
14354         inter_pc = pc;
14355         sp++;
14356         sp[0] = sp[-1];       /* Pull up the 'v' */
14357         put_number(sp-1, 1);  /* 'Push' the 1 for the upper bound */
14358         sp = range_lvalue(RR_RANGE, sp);
14359         break;
14360 
14361     CASE(F_AX_RANGE_LVALUE);           /* --- ax_range_lvalue     --- */
14362         /* Operator F_AX_RANGE_LVALUE (string|vector &v=sp[0]
14363          *                            , int i1=sp[-1])
14364          *
14365          * Compute the range &(v[>i1..]) of lvalue <v> and push it into the
14366          * stack.  The value pushed is a lvalue pointing to <special_lvalue>.
14367          * <special_lvalue> then is the POINTER_RANGE_- resp.
14368          * STRING_RANGE_LVALUE.
14369          *
14370          * We implement this by pushing '1' onto the stack and then
14371          * call F_AR_RANGE_LVALUE, effectively computing &(v[>i1..<1]).
14372          */
14373 
14374         inter_pc = pc;
14375         sp++;
14376         sp[0] = sp[-1];       /* Pull up the 'v' */
14377         put_number(sp-1, 1);  /* 'Push' the 1 for the upper bound */
14378         sp = range_lvalue(AR_RANGE, sp);
14379         break;
14380 
14381 #ifdef USE_STRUCTS
14382                         /* --- push_protected_indexed_s_lvalue --- */
14383     CASE(F_PUSH_PROTECTED_INDEXED_S_LVALUE);
14384         /* Op. (struct  v=sp[-2], mixed i=sp[-1], short idx=sp[0])
14385          *
14386          * Compute the lvalue &(v[i]), store it in a struct
14387          * protected_lvalue, and push the protector as PROTECTED_LVALUE
14388          * into the stack.
14389          *
14390          * short <idx> gives the index of the expected struct type - the
14391          * operator accepts a struct of this type, or any of its children.
14392          * An negative <idx> accepts any struct.
14393          */
14394 
14395         sp = check_struct_op(sp, 0, 3, pc);
14396         sp = push_protected_indexed_lvalue(sp, pc);
14397         break;
14398 #endif /* USE_STRUCTS */
14399 
14400                           /* --- push_protected_indexed_lvalue --- */
14401     CASE(F_PUSH_PROTECTED_INDEXED_LVALUE);
14402         /* Op. (vector  v=sp[-1], int   i=sp[0])
14403          * Op. (mapping v=sp[-1], mixed i=sp[0])
14404          *
14405          * Compute the lvalue &(v[i]), store it in a struct
14406          * protected_lvalue, and push the protector as PROTECTED_LVALUE
14407          * into the stack.
14408          */
14409 
14410 #ifdef USE_STRUCTS
14411         if ((sp-1)->type == T_STRUCT)
14412         {
14413             ERRORF(("Illegal type to []: %s, expected vector/mapping.\n"
14414                    , typename((sp-1)->type)
14415                   ));
14416             /* NOTREACHED */
14417         }
14418 #endif /* USE_STRUCTS */
14419         sp = push_protected_indexed_lvalue(sp, pc);
14420         break;
14421 
14422                          /* --- push_protected_rindexed_lvalue --- */
14423     CASE(F_PUSH_PROTECTED_RINDEXED_LVALUE);
14424         /* Op. (vector v=sp[-1], int i=sp[0])
14425          *
14426          * Compute the lvalue &(v[<i]), store it in a struct
14427          * protected_lvalue, and push the protector as PROTECTED_LVALUE
14428          * into the stack.
14429          */
14430 
14431         sp = push_protected_rindexed_lvalue(sp, pc);
14432         break;
14433 
14434                          /* --- push_protected_aindexed_lvalue --- */
14435     CASE(F_PUSH_PROTECTED_AINDEXED_LVALUE);
14436         /* Op. (vector v=sp[-1], int i=sp[0])
14437          *
14438          * Compute the lvalue &(v[>i]), store it in a struct
14439          * protected_lvalue, and push the protector as PROTECTED_LVALUE
14440          * into the stack.
14441          */
14442 
14443         sp = push_protected_aindexed_lvalue(sp, pc);
14444         break;
14445 
14446                       /* --- push_protected_indexed_map_lvalue --- */
14447     CASE(F_PUSH_PROTECTED_INDEXED_MAP_LVALUE);
14448         /* Op. (mapping m=sp[-2], mixed i=sp[-1], int   j=sp[0])
14449          *
14450          * Compute the lvalue &(m[i:j]), store it in a struct
14451          * protected_lvalue, and push the protector as PROTECTED_LVALUE
14452          * into the stack.
14453          */
14454 
14455         push_protected_indexed_map_lvalue(sp, pc);
14456         break;
14457 
14458 #ifdef USE_STRUCTS
14459                                /* --- protected_index_s_lvalue --- */
14460     CASE(F_PROTECTED_INDEX_S_LVALUE);
14461         /* Operator (struct &v=sp[0], mixed i=sp[-2], short idx=sp[-1])
14462          *
14463          * Compute the index &(*v[i]) of lvalue <v>, wrap it into a
14464          * protector, and push the reference to the protector as
14465          * PROTECTED_LVALUE onto the stack.
14466          *
14467          * short <idx> gives the index of the expected struct type - the
14468          * operator accepts a struct of this type, or any of its children.
14469          * An negative <idx> accepts any struct.
14470          */
14471 
14472         sp = check_struct_op(sp, -1, 1, pc);
14473         sp = protected_index_lvalue(sp, pc);
14474         break;
14475 #endif /* USE_STRUCTS */
14476 
14477                                  /* --- protected_index_lvalue --- */
14478     CASE(F_PROTECTED_INDEX_LVALUE);
14479         /* Operator (string|vector &v=sp[0], int   i=sp[-1])
14480          *          (mapping       &v=sp[0], mixed i=sp[-1])
14481          *
14482          * Compute the index &(*v[i]) of lvalue <v>, wrap it into a
14483          * protector, and push the reference to the protector as
14484          * PROTECTED_LVALUE onto the stack.
14485          *
14486          * If <v> is a protected non-string-lvalue, the protected_lvalue
14487          * referenced by <v>.u.lvalue will be deallocated, and the
14488          * protector itself will be stored in <last_indexing_protector>
14489          * for the time being.
14490          *
14491          * If <v> is a string-lvalue, it is made a malloced string if
14492          * necessary.
14493          */
14494 
14495 #ifdef USE_STRUCTS
14496         if ((sp-1)->type == T_STRUCT)
14497         {
14498             ERRORF(("Illegal type to []: %s, expected string/vector/mapping.\n"
14499                    , typename((sp-1)->type)
14500                   ));
14501             /* NOTREACHED */
14502         }
14503 #endif /* USE_STRUCTS */
14504         sp = protected_index_lvalue(sp, pc);
14505         break;
14506 
14507                                 /* --- protected_rindex_lvalue --- */
14508     CASE(F_PROTECTED_RINDEX_LVALUE);
14509         /* Operator (string|vector &v=sp[0], int   i=sp[-1])
14510          *
14511          * Compute the index &(*v[<i]) of lvalue <v>, wrap it into a
14512          * protector, and push the reference to the protector as
14513          * PROTECTED_LVALUE onto the stack.
14514          *
14515          * If <v> is a protected non-string-lvalue, the protected_lvalue
14516          * referenced by <v>.u.lvalue will be deallocated, and the
14517          * protector itself will be stored in <last_indexing_protector>
14518          * for the time being.
14519          *
14520          * If <v> is a string-lvalue, it is made a malloced string if
14521          * necessary.
14522          */
14523 
14524         sp = protected_rindex_lvalue(sp, pc);
14525         break;
14526 
14527                                 /* --- protected_aindex_lvalue --- */
14528     CASE(F_PROTECTED_AINDEX_LVALUE);
14529         /* Operator (string|vector &v=sp[0], int   i=sp[-1])
14530          *
14531          * Compute the index &(*v[>i]) of lvalue <v>, wrap it into a
14532          * protector, and push the reference to the protector as
14533          * PROTECTED_LVALUE onto the stack.
14534          *
14535          * If <v> is a protected non-string-lvalue, the protected_lvalue
14536          * referenced by <v>.u.lvalue will be deallocated, and the
14537          * protector itself will be stored in <last_indexing_protector>
14538          * for the time being.
14539          *
14540          * If <v> is a string-lvalue, it is made a malloced string if
14541          * necessary.
14542          */
14543 
14544         sp = protected_aindex_lvalue(sp, pc);
14545         break;
14546 
14547                               /* --- protected_range_lvalue --- */
14548     CASE(F_PROTECTED_RANGE_LVALUE);
14549         /* Operator (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
14550          *
14551          * Compute the range &(v[i1..i2]) of lvalue <v>, wrap it into a
14552          * protector, and push the reference to the protector onto the
14553          * stack.
14554          *
14555          * If <v> is a protected lvalue itself, its protecting svalue will
14556          * be used in the result protector.
14557          *
14558          * If <v> is a string-lvalue, it is made a malloced string if
14559          * necessary.
14560          */
14561 
14562         inter_pc = pc;
14563         sp = protected_range_lvalue(NN_RANGE, sp);
14564         break;
14565 
14566                            /* --- protected_nr_range_lvalue --- */
14567     CASE(F_PROTECTED_NR_RANGE_LVALUE);
14568         /* Operator (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
14569          *
14570          * Compute the range &(v[i1..<i2]) of lvalue <v>, wrap it into a
14571          * protector, and push the reference to the protector onto the
14572          * stack.
14573          *
14574          * If <v> is a protected lvalue itself, its protecting svalue will
14575          * be used in the result protector.
14576          *
14577          * If <v> is a string-lvalue, it is made a malloced string if
14578          * necessary.
14579          */
14580 
14581         inter_pc = pc;
14582         sp = protected_range_lvalue(NR_RANGE, sp);
14583         break;
14584 
14585                              /* --- protected_rn_range_lvalue --- */
14586     CASE(F_PROTECTED_RN_RANGE_LVALUE);
14587         /* Operator (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
14588          *
14589          * Compute the range &(v[<i1..i2]) of lvalue <v>, wrap it into a
14590          * protector, and push the reference to the protector onto the
14591          * stack.
14592          *
14593          * If <v> is a protected lvalue itself, its protecting svalue will
14594          * be used in the result protector.
14595          *
14596          * If <v> is a string-lvalue, it is made a malloced string if
14597          * necessary.
14598          */
14599 
14600         inter_pc = pc;
14601         sp = protected_range_lvalue(RN_RANGE, sp);
14602         break;
14603 
14604                              /* --- protected_rr_range_lvalue --- */
14605     CASE(F_PROTECTED_RR_RANGE_LVALUE);
14606         /* Operator (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
14607          *
14608          * Compute the range &(v[<i1..<i2]) of lvalue <v>, wrap it into a
14609          * protector, and push the reference to the protector onto the
14610          * stack.
14611          *
14612          * If <v> is a protected lvalue itself, its protecting svalue will
14613          * be used in the result protector.
14614          *
14615          * If <v> is a string-lvalue, it is made a malloced string if
14616          * necessary.
14617          */
14618 
14619         inter_pc = pc;
14620         sp = protected_range_lvalue(RR_RANGE, sp);
14621         break;
14622 
14623                            /* --- protected_na_range_lvalue --- */
14624     CASE(F_PROTECTED_NA_RANGE_LVALUE);
14625         /* Operator (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
14626          *
14627          * Compute the range &(v[i1..>i2]) of lvalue <v>, wrap it into a
14628          * protector, and push the reference to the protector onto the
14629          * stack.
14630          *
14631          * If <v> is a protected lvalue itself, its protecting svalue will
14632          * be used in the result protector.
14633          *
14634          * If <v> is a string-lvalue, it is made a malloced string if
14635          * necessary.
14636          */
14637 
14638         inter_pc = pc;
14639         sp = protected_range_lvalue(NA_RANGE, sp);
14640         break;
14641 
14642                              /* --- protected_an_range_lvalue --- */
14643     CASE(F_PROTECTED_AN_RANGE_LVALUE);
14644         /* Operator (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
14645          *
14646          * Compute the range &(v[>i1..i2]) of lvalue <v>, wrap it into a
14647          * protector, and push the reference to the protector onto the
14648          * stack.
14649          *
14650          * If <v> is a protected lvalue itself, its protecting svalue will
14651          * be used in the result protector.
14652          *
14653          * If <v> is a string-lvalue, it is made a malloced string if
14654          * necessary.
14655          */
14656 
14657         inter_pc = pc;
14658         sp = protected_range_lvalue(AN_RANGE, sp);
14659         break;
14660 
14661                            /* --- protected_ra_range_lvalue --- */
14662     CASE(F_PROTECTED_RA_RANGE_LVALUE);
14663         /* Operator (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
14664          *
14665          * Compute the range &(v[<i1..>i2]) of lvalue <v>, wrap it into a
14666          * protector, and push the reference to the protector onto the
14667          * stack.
14668          *
14669          * If <v> is a protected lvalue itself, its protecting svalue will
14670          * be used in the result protector.
14671          *
14672          * If <v> is a string-lvalue, it is made a malloced string if
14673          * necessary.
14674          */
14675 
14676         inter_pc = pc;
14677         sp = protected_range_lvalue(RA_RANGE, sp);
14678         break;
14679 
14680                              /* --- protected_ar_range_lvalue --- */
14681     CASE(F_PROTECTED_AR_RANGE_LVALUE);
14682         /* Operator (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
14683          *
14684          * Compute the range &(v[>i1..<i2]) of lvalue <v>, wrap it into a
14685          * protector, and push the reference to the protector onto the
14686          * stack.
14687          *
14688          * If <v> is a protected lvalue itself, its protecting svalue will
14689          * be used in the result protector.
14690          *
14691          * If <v> is a string-lvalue, it is made a malloced string if
14692          * necessary.
14693          */
14694 
14695         inter_pc = pc;
14696         sp = protected_range_lvalue(AR_RANGE, sp);
14697         break;
14698 
14699                              /* --- protected_aa_range_lvalue --- */
14700     CASE(F_PROTECTED_AA_RANGE_LVALUE);
14701         /* Operator (string|vector &v=sp[0], int i2=sp[-1], i1=sp[-2])
14702          *
14703          * Compute the range &(v[>i1..>i2]) of lvalue <v>, wrap it into a
14704          * protector, and push the reference to the protector onto the
14705          * stack.
14706          *
14707          * If <v> is a protected lvalue itself, its protecting svalue will
14708          * be used in the result protector.
14709          *
14710          * If <v> is a string-lvalue, it is made a malloced string if
14711          * necessary.
14712          */
14713 
14714         inter_pc = pc;
14715         sp = protected_range_lvalue(AA_RANGE, sp);
14716         break;
14717 
14718                               /* --- protected_nx_range_lvalue --- */
14719     CASE(F_PROTECTED_NX_RANGE_LVALUE);
14720         /* Operator (string|vector &v=sp[0], i1=sp[-1])
14721          *
14722          * Compute the range &(v[i1..]) of lvalue <v>, wrap it into a
14723          * protector, and push the reference to the protector onto the
14724          * stack.
14725          *
14726          * If <v> is a protected lvalue itself, its protecting svalue will
14727          * be used in the result protector.
14728          *
14729          * If <v> is a string-lvalue, it is made a malloced string if
14730          * necessary.
14731          *
14732          * We implement it by pushing '1' onto the stack and then
14733          * calling protected_nr_range_lvalue, effectively computing
14734          * &(v[i1..<1]).
14735          */
14736 
14737         inter_pc = pc;
14738         sp++;
14739         sp[0] = sp[-1];       /* Pull up the 'v' */
14740         put_number(sp-1, 1);  /* 'Push' the 1 for the upper bound */
14741         sp = protected_range_lvalue(NR_RANGE, sp);
14742         break;
14743 
14744                           /* --- protected_rx_range_lvalue --- */
14745     CASE(F_PROTECTED_RX_RANGE_LVALUE);
14746         /* Operator (string|vector &v=sp[0], int i1=sp[-1])
14747          *
14748          * Compute the range &(v[<i1..]) of lvalue <v>, wrap it into a
14749          * protector, and push the reference to the protector onto the
14750          * stack.
14751          *
14752          * If <v> is a protected lvalue itself, its protecting svalue will
14753          * be used in the result protector.
14754          *
14755          * If <v> is a string-lvalue, it is made a malloced string if
14756          * necessary.
14757          *
14758          * We implement it by pushing '1' onto the stack and then
14759          * calling protected_nr_range_lvalue, effectively computing
14760          * &(v[<i1..<1]).
14761          */
14762 
14763         inter_pc = pc;
14764         sp++;
14765         sp[0] = sp[-1];       /* Pull up the 'v' */
14766         put_number(sp-1, 1);  /* 'Push' the 1 for the upper bound */
14767         sp = protected_range_lvalue(RR_RANGE, sp);
14768         break;
14769 
14770                           /* --- protected_ax_range_lvalue --- */
14771     CASE(F_PROTECTED_AX_RANGE_LVALUE);
14772         /* Operator (string|vector &v=sp[0], int i1=sp[-1])
14773          *
14774          * Compute the range &(v[>i1..]) of lvalue <v>, wrap it into a
14775          * protector, and push the reference to the protector onto the
14776          * stack.
14777          *
14778          * If <v> is a protected lvalue itself, its protecting svalue will
14779          * be used in the result protector.
14780          *
14781          * If <v> is a string-lvalue, it is made a malloced string if
14782          * necessary.
14783          *
14784          * We implement it by pushing '1' onto the stack and then
14785          * calling protected_ar_range_lvalue, effectively computing
14786          * &(v[>i1..<1]).
14787          */
14788 
14789         inter_pc = pc;
14790         sp++;
14791         sp[0] = sp[-1];       /* Pull up the 'v' */
14792         put_number(sp-1, 1);  /* 'Push' the 1 for the upper bound */
14793         sp = protected_range_lvalue(AR_RANGE, sp);
14794         break;
14795 
14796     CASE(F_SIMUL_EFUN);             /* --- simul_efun <code>   --- */
14797     {
14798         /* Call the simul_efun <code> with the arguments on the stack.
14799          * If the simul_efun takes a variable number of arguments, or
14800          * if use_ap is TRUE, then the number of arguments is determined
14801          * through the ap pointer; otherwise the code assumes that the
14802          * compiler left the proper number of arguments on the stack.
14803          *
14804          * <code> is an ushort and indexes the function list *simul_efunp.
14805          */
14806 
14807         unsigned short      code;      /* the function index */
14808         fun_hdr_p           funstart;  /* the actual function */
14809         object_t           *ob;        /* the simul_efun object */
14810         int                 def_narg;  /* expected number of arguments */
14811         simul_efun_table_t *entry;
14812 
14813         assign_eval_cost_inl();  /* we're changing objects */
14814 
14815         /* Get the sefun code and the number of arguments on the stack */
14816         LOAD_SHORT(code, pc);
14817         def_narg = simul_efunp[code].num_arg;
14818 
14819         if (use_ap
14820          || def_narg == SIMUL_EFUN_VARARGS
14821          || (simul_efunp[code].flags & TYPE_MOD_XVARARGS)
14822            )
14823         {
14824             use_ap = MY_FALSE;  /* Reset the flag */
14825             num_arg = sp - ap + 1;
14826         }
14827         else
14828             num_arg = def_narg;
14829 
14830         /* Correct the number of arguments on the stack */
14831         if (num_arg != def_narg && def_narg != SIMUL_EFUN_VARARGS)
14832         {
14833             /* If it's an XVARARGS, we don't require the last argument. */
14834             if (simul_efunp[code].flags & TYPE_MOD_XVARARGS)
14835                 def_narg--;
14836 
14837             /* Add eventually missing arguments */
14838             while (num_arg < def_narg)
14839             {
14840                 sp++;
14841                 put_number(sp, 0);
14842                 num_arg++;
14843             }
14844 
14845             /* Remove extraneous arguments */
14846             if (!(simul_efunp[code].flags & TYPE_MOD_XVARARGS))
14847             {
14848                 while (num_arg > def_narg)
14849                 {
14850                     free_svalue(sp--);
14851                     num_arg--;
14852                 }
14853             }
14854         }
14855 
14856         /* No external calls may be done when this object is destructed.
14857          */
14858         if (current_object->flags & O_DESTRUCTED)
14859         {
14860             pop_n_elems(num_arg);
14861             push_number(sp, 0);
14862             WARNF(("Call from destructed object '%s' ignored.\n"
14863                   , get_txt(current_object->name)));
14864             break;
14865         }
14866 
14867         /* Make sure the simul_efun object exists; loading it when
14868          * necessary.
14869          */
14870         if ( !(ob = simul_efun_object) )
14871         {
14872             inter_sp = sp;
14873             inter_pc = pc;
14874             if (!assert_simul_efun_object()
14875              || !(ob = simul_efun_object)
14876                )
14877             {
14878                 errorf("Couldn't load simul_efun object.\n");
14879             }
14880         }
14881 
14882         /* Get the function code information */
14883         entry = &simul_efun_table[code];
14884 
14885         if ( NULL != (funstart = entry->funstart) )
14886         {
14887             /* The entry is valid: call the sefun by recursing into
14888              * eval_instruction(), so we can get the result from the
14889              * stack.
14890              * We recurse because some simul_efuns are called with
14891              * F_CALL_DIRECT, and the functions should not be able
14892              * to see any difference.
14893              */
14894             program_t *prog;
14895             svalue_t *new_sp;
14896 
14897 #ifdef USE_NEW_INLINES
14898             push_control_stack(sp, pc, fp, inter_context);
14899 #else
14900             push_control_stack(sp, pc, fp);
14901 #endif /* USE_NEW_INLINES */
14902             csp->ob = current_object;
14903             csp->prev_ob = previous_ob;
14904             csp->funstart = funstart;
14905             csp->num_local_variables = num_arg;
14906             current_prog = prog = entry->program;
14907             function_index_offset = entry->function_index_offset;
14908 #ifdef DEBUG
14909             if (!ob->variables && entry->variable_index_offset)
14910                 fatal("%s Fatal: call sefun for object %p '%s' w/o variables, "
14911                       "but offset %"PRIdPINT"\n"
14912                      , time_stamp(), ob, get_txt(ob->name)
14913                      , (entry->variable_index_offset));
14914 #endif
14915             current_variables = ob->variables;
14916             if (current_variables)
14917                 current_variables += entry->variable_index_offset;
14918             new_sp = setup_new_frame2(funstart, sp, MY_TRUE, MY_FALSE);
14919             /* The simul_efun object should not use simul_efuns itself... */
14920             previous_ob = current_object;
14921             current_object = ob;
14922             current_strings = prog->strings;
14923             eval_instruction(FUNCTION_CODE(funstart), new_sp);
14924             sp -= num_arg - 1;
14925             /*
14926              * The result of the function call is on the stack.
14927              */
14928             break;
14929         }
14930 
14931         /* At this point the simul_efun was discarded meanwhile and
14932          * not recreated.
14933          * Call the function the old fashioned way with apply() in case it
14934          * exists in a slightly different form.
14935          */
14936         inter_sp = sp;
14937         inter_pc = pc;
14938         call_simul_efun(code, ob, num_arg);
14939         sp = inter_sp;
14940         /*
14941          * The result of the function call is on the stack.
14942          */
14943         break;
14944     }
14945 
14946     CASE(F_AGGREGATE);              /* --- aggregate <size>    --- */
14947     {
14948         /* Create an array ({ sp[<-size>+1], ..., sp[0] }), remove the
14949          * single values from the stack and leave the array as result.
14950          *
14951          * <size> is a (16-Bit) unsigned short.
14952          *
14953          * TODO: It is tempting to introduce flat 'literal arrays',
14954          * TODO:: which can be copied quickly and just need a few
14955          * TODO:: slots to filled in, if any.
14956          */
14957 
14958         int i;
14959         vector_t *v;
14960         unsigned short num;
14961         svalue_t *value, *item;
14962 
14963         /* Get the size */
14964         LOAD_SHORT(num, pc);
14965 
14966         /* Allocate the array */
14967         i = num;
14968         v = allocate_uninit_array(i);
14969 
14970         /* Set sp and value to the first single value on the stack */
14971         sp = value = sp - i + 1;
14972 
14973         /* Move the single values into the array.
14974          * Volatile strings are made shared during this.
14975          */
14976         item = v->item;
14977         while (--i >= 0)
14978             transfer_svalue_no_free(item++, value++);
14979 
14980         /* Leave the array on the stack (ref count is already ok) */
14981         put_array(sp, v);
14982         break;
14983     }
14984 
14985     CASE(F_M_AGGREGATE);     /* --- m_aggregate <size> <width> --- */
14986     CASE(F_M_CAGGREGATE);   /* --- m_caggregate <size> <width> --- */
14987     {
14988         /* Create a mapping from the <size>*<width> single values on the
14989          * stack, remove the single values and leave the mapping as result.
14990          * Starting at the lowest entry (sp[-(<size>*<width>)]), the values
14991          * are laid out in <key>:<data 1>...<data <width>> order.
14992          * Keys may appear several times.
14993          *
14994          * m_aggregate: <size> and <width> are (16-Bit) unsigned shorts.
14995          * m_caggregate: <size> and <width> are uint8.
14996          *
14997          * TODO: It is tempting to introduce flat 'literal mappings',
14998          * TODO:: which can be copied quickly and just need a few
14999          * TODO:: slots to filled in, if any.
15000          */
15001         int i, j;
15002         mapping_t *m;
15003         svalue_t *data;
15004         int num_values;
15005         svalue_t *value;
15006 
15007         /* Get the size and width from the code.
15008          */
15009         if (instruction == F_M_CAGGREGATE)
15010         {
15011             i = LOAD_UINT8(pc);
15012             num_values = LOAD_UINT8(pc);
15013         }
15014         else
15015         {
15016             unsigned short num[2];
15017 
15018             LOAD_SHORT(num[0], pc);
15019             LOAD_SHORT(num[1], pc);
15020             i = num[0];
15021             num_values = num[1];
15022         }
15023 
15024         if (max_mapping_size && (p_uint)i * (1+num_values) > (p_uint)max_mapping_size)
15025             ERRORF(("Illegal mapping size: %"PRIuPINT" elements (%u x %u)\n"
15026                    , ((p_uint)i * (1+num_values)), i, num_values));
15027         if (max_mapping_keys && (p_uint)i > (p_uint)max_mapping_keys)
15028             ERRORF(("Illegal mapping size: %u entries\n", i));
15029 
15030         /* Get the mapping */
15031         m = allocate_mapping(i, num_values);
15032         if (!m)
15033             ERROR("Out of memory\n");
15034 
15035         /* Set sp and value to the first single value on the stack.
15036          */
15037         sp = value = sp - (i * (num_values+1)) + 1;
15038         while (--i >= 0)
15039         {
15040             /* Create/reget the mapping entry */
15041             data = get_map_lvalue_unchecked(m, value);
15042             if (!data)
15043             {
15044                 outofmemory("literal mapping");
15045                 /* NOTREACHED */
15046                 return MY_FALSE;
15047             }
15048             free_svalue(value++);
15049             for (j = num_values; --j >= 0;)
15050             {
15051                 /* Copy over the entry data */
15052                 if (data->type != T_NUMBER)
15053                     free_svalue(data);
15054                 transfer_svalue_no_free(data++, value++);
15055             }
15056         }
15057 
15058         /* Put the mapping onto the stack */
15059         put_mapping(sp, m);
15060         break;
15061     }
15062 
15063 #ifdef USE_STRUCTS
15064     CASE(F_S_AGGREGATE);
15065                         /* --- s_aggregate <idx> <num> --- */
15066     CASE(F_S_M_AGGREGATE);
15067            /* --- s_m_aggregate <idx> <num> <index>... --- */
15068     {
15069         /* Create a struct from the <num> values currently on the
15070          * stack. The struct can be found at short <idx> in
15071          * program.struct_defs[]. If <idx> is negative, the <num>+1th
15072          * value on the stack is a struct of the type to be generated
15073          * (F_S_AGGREGATE only).
15074          * For F_S_AGGREGATE, the values on the stack are to be assigned
15075          * to the struct members in ascending order.
15076          * For F_S_M_AGGREGATE, the <index>... values give for each
15077          * value on the stack into which struct member the value has to go.
15078          * This list of indices is given in reverse order, that is the
15079          * index for the topmost stack value comes first.
15080          */
15081         struct_t * st;
15082         short idx;
15083         int num_values;
15084         Bool has_template;
15085         svalue_t * svp;
15086 
15087         LOAD_SHORT(idx, pc);
15088         num_values = LOAD_UINT8(pc);
15089         has_template = MY_FALSE;
15090 
15091         if (idx < 0 && instruction == F_S_AGGREGATE)
15092         {
15093             struct_type_t *pType;
15094 
15095             if ((sp - num_values)->type != T_STRUCT)
15096             {
15097                 ERRORF(("Bad template arg to #'(<: got %s, expected struct\n"
15098                        , typename((sp - num_values)->type)
15099                       ));
15100                 /* NOTREACHED */
15101             }
15102 
15103             pType = (sp - num_values)->u.strct->type;
15104 
15105             if (num_values > struct_t_size(pType))
15106             {
15107                 ERRORF(("Too many initializers for struct %s: "
15108                         "%ld, expected %ld\n"
15109                        , get_txt(struct_t_name(pType))
15110                        , (long)num_values
15111                        , (long)struct_t_size(pType)
15112                       ));
15113                 /* NOTREACHED */
15114             }
15115             has_template = MY_TRUE;
15116             st = struct_new(pType);
15117         }
15118         else
15119         {
15120             st = struct_new(current_prog->struct_defs[idx].type);
15121         }
15122         if  (!st)
15123             ERROR("Out of memory!\n");
15124 
15125         if (instruction == F_S_AGGREGATE)
15126         {
15127             /* Easy way: just move all the values into the struct.
15128              * This allows for having less initializers than members.
15129              */
15130 
15131             for ( svp = st->member + num_values - 1
15132                 ; num_values > 0
15133                 ; num_values--, svp--, sp--
15134                 )
15135             {
15136                 *svp = *sp;
15137             }
15138         }
15139         else
15140         {
15141             /* Complex way: assign using the indices */
15142             int ix;
15143 
15144             for ( ; num_values > 0 ; num_values--, sp--)
15145             {
15146                 ix = LOAD_UINT8(pc);
15147                 st->member[ix] = *sp;
15148             }
15149         }
15150 
15151         /* If necessary, remove the template struct */
15152         if (has_template)
15153         {
15154             free_svalue(sp); sp--;
15155         }
15156 
15157         /* Put the struct onto the stack */
15158         sp++;
15159         put_struct(sp, st);
15160 
15161         break;
15162    }
15163 #endif /* USE_STRUCTS */
15164 
15165     CASE(F_PREVIOUS_OBJECT0);       /* --- previous_object0    --- */
15166         /* EFUN previous_object(void)
15167          *
15168          * Push the previous_object onto the stack, if existing and
15169          * not destructed.
15170          *
15171          * The compiler generates this code when it sees the previous_object()
15172          * efun used with no arguments.
15173          *
15174          * (Reminder: the efun previous_object(int) has a different meaning.)
15175          * TODO: How do other driver handle this?
15176          */
15177         if (previous_ob == 0 || (previous_ob->flags & O_DESTRUCTED))
15178             push_number(sp, 0);
15179         else
15180             push_ref_object(sp, previous_ob, "previous_object0");
15181         break;
15182 
15183     CASE(F_LAMBDA_CCONSTANT);    /* --- lambda_cconstant <num> --- */
15184     {
15185         /* Push the constant value <num> of this lambda closure onto
15186          * the stack.
15187          *
15188          * The values are stored in an svalue[] before the actual
15189          * function code and uint8 <num> is used to index that array
15190          * from the end.
15191          */
15192         int ix;
15193         svalue_t * cstart;
15194 
15195         /* Get the value index */
15196         ix = LOAD_UINT8(pc);
15197 
15198         /* Get the pointer to the last constant value */
15199         cstart = (svalue_t *)((char *)(csp->funstart)
15200                                    - LAMBDA_VALUE_OFFSET);
15201         sp++;
15202         assign_checked_svalue_no_free(sp, cstart - ix);
15203         break;
15204     }
15205 
15206     CASE(F_LAMBDA_CONSTANT);     /* --- lambda_constant <num> --- */
15207     {
15208         /* Push the constant value <num> of this lambda closure onto
15209          * the stack.
15210          *
15211          * The values are stored in an svalue[] before the actual
15212          * function code and (16-Bit) ushort <num> is used to index
15213          * that array from the end.
15214          */
15215         unsigned short ix;
15216         svalue_t * cstart;
15217 
15218         /* Get the value index */
15219         LOAD_SHORT(ix, pc);
15220 
15221         /* Get the pointer to the last constant value */
15222         cstart = (svalue_t *)((char *)(csp->funstart)
15223                                    - LAMBDA_VALUE_OFFSET);
15224         sp++;
15225         assign_checked_svalue_no_free(sp, cstart - ix);
15226         break;
15227     }
15228 
15229     CASE(F_MAP_INDEX);              /* --- map_index           --- */
15230     {
15231         /* Operator F_MAP_INDEX( mapping m=sp[-2], mixed i=sp[-1], int j=sp[0])
15232          *
15233          * Compute m[i,j] and push it onto the stack.
15234          */
15235 
15236         mapping_t *m;
15237         mp_int n;
15238         svalue_t *data;
15239 
15240         if (sp[-2].type != T_MAPPING)
15241         {
15242             ERRORF(("(value) Indexing on illegal type: %s, expected mapping.\n"
15243                    , typename(sp[-2].type)
15244                   ));
15245         }
15246         if (sp[0].type != T_NUMBER)
15247         {
15248             ERRORF(("Illegal sub-index type: %s, expected number.\n"
15249                    , typename(sp[0].type)
15250                   ));
15251         }
15252 
15253         m = sp[-2].u.map;
15254         n = sp->u.number;
15255 
15256         if (n < 0 || n >= m->num_values)
15257         {
15258             ERRORF(("Illegal sub-index %"PRIdMPINT", mapping width is %"
15259                     PRIdPINT".\n", n, m->num_values));
15260         }
15261 
15262         sp--; /* the key */
15263 
15264         data = get_map_value(m, sp);
15265         pop_stack();
15266 
15267         if (data == &const0)
15268         {
15269             put_number(sp, 0);
15270         }
15271         else
15272         {
15273             assign_checked_svalue_no_free(sp, data + n);
15274         }
15275         free_mapping(m);
15276         break;
15277     }
15278 
15279     CASE(F_PUSH_INDEXED_MAP_LVALUE); /* --- push_indexed_map_lvalue --- */
15280     {
15281         /* Operator F_PUSH_INDEXED_MAP_LVALUE( mapping m=sp[-2]
15282          *                                   , mixed i=sp[-1], int j=sp[0])
15283          *
15284          * Compute the lvalue &(m[i,j]) and push it into the stack. If v has
15285          * just one ref left, the indexed item is stored in indexing_quickfix
15286          * and the lvalue refers to that variable.
15287          */
15288         svalue_t *data;
15289         mapping_t *m;
15290         mp_int n;
15291 
15292         if (sp[-2].type != T_MAPPING)
15293         {
15294             ERRORF(("(lvalue) Indexing on illegal type: %s, expected mapping.\n"
15295                    , typename(sp[-2].type)
15296                   ));
15297         }
15298         if (sp[0].type != T_NUMBER)
15299         {
15300             ERRORF(("Illegal sub-index type: %s, expected number.\n"
15301                    , typename(sp[0].type)
15302                   ));
15303         }
15304 
15305         m = sp[-2].u.map;
15306         n = sp->u.number;
15307         if (n < 0 || n >= m->num_values)
15308         {
15309             ERRORF(("Illegal sub-index %"PRIdMPINT", mapping width is %"
15310                     PRIdPINT".\n", n, m->num_values));
15311         }
15312 
15313         sp--; /* the key */
15314         data = get_map_lvalue(m, sp);
15315         if (!data)
15316         {
15317             outofmemory("indexed lvalue");
15318             /* NOTREACHED */
15319             return MY_FALSE;
15320         }
15321         pop_stack();
15322 
15323         if (!m->ref)
15324         {
15325             assign_svalue (&indexing_quickfix, data + n);
15326             sp->type = T_LVALUE;
15327             sp->u.lvalue = &indexing_quickfix;
15328             break;
15329         }
15330         else
15331         {
15332             sp->type = T_LVALUE;
15333             sp->u.lvalue = data + n;
15334         }
15335         free_mapping(m);
15336         break;
15337     }
15338 
15339     CASE(F_FOREACH);       /* --- foreach     <nargs> <offset> --- */
15340     CASE(F_FOREACH_REF);   /* --- foreach_ref <nargs> <offset> --- */
15341     CASE(F_FOREACH_RANGE); /* --- foreach_range <nargs> <offset> --- */
15342     {
15343         /* Initialize a foreach() loop. On the stack are <nargs>-1
15344          * lvalues where the (l)value(s) are to be stored. The last
15345          * value on the stack is the (l)value to loop over. (Do not
15346          * confuse <nargs> with the normal NUM_ARG!).
15347          *
15348          * ushort <offset> is the distance to the FOREACH_NEXT
15349          * instruction follwing the codeblock after the instruction,
15350          * counted from the byte following this instruction.
15351          *
15352          * The instruction pushes two or three more values onto
15353          * the stack to store its internal status.
15354          *
15355          *   sp[0]  -> number 'next':  index of the next value to assign (0).
15356          *             x.generic:      0: FOREACH, 1: FOREACH_REF
15357          *                             2: FOREACH_RANGE with one extra loop
15358          *                                (this falls back to FOREACH after
15359          *                                 the first encounter of
15360          *                                 FOREACH_NEXT).
15361          *   sp[-1] -> number 'count': number of values left to loop over.
15362          *             x.generic:      <nargs>, or -<nargs> if the value
15363          *                             is mapping
15364          *   sp[-2] -> array 'm_indices': if the value is a mapping, this
15365          *                             is the array with the indices.
15366          *
15367          * After pushing the values onto the stack, the instruction
15368          * branches to the FOREACH_NEXT instruction to start the first
15369          * iteration.
15370          */
15371 
15372         int vars_required;
15373         int nargs;
15374         p_int count, start;
15375         unsigned short offset;
15376         Bool gen_refs, use_range, do_extra_loop;
15377         svalue_t * arg;
15378 
15379         gen_refs = (instruction == F_FOREACH_REF);
15380         use_range = (instruction == F_FOREACH_RANGE);
15381         do_extra_loop = MY_FALSE;
15382         start = 0;
15383 
15384         nargs = LOAD_UINT8(pc);
15385         LOAD_SHORT(offset, pc);
15386 
15387         /* Unravel the lvalue chain (if any) to get to the actual value
15388          * to loop over.
15389          */
15390         if (gen_refs && sp->type != T_LVALUE)
15391         {
15392             ERRORF(("foreach() got a %s, expected a &(string/array/mapping).\n"
15393                    , typename(sp->type)
15394                    ));
15395         }
15396 
15397         for (arg = sp
15398             ; gen_refs && arg && arg->type == T_LVALUE
15399             ; arg = arg->u.lvalue)
15400             NOOP;
15401 
15402         if (use_range && arg->type != T_NUMBER)
15403             ERRORF(("foreach() got a %s, requires a number for upper range bound.\n"
15404                    , typename(arg->type)
15405                    ));
15406 
15407         if (arg->type != T_STRING
15408          && arg->type != T_POINTER
15409          && arg->type != T_NUMBER
15410 #ifdef USE_STRUCTS
15411          && arg->type != T_STRUCT
15412 #endif /* USE_STRUCTS */
15413          && arg->type != T_MAPPING)
15414             ERRORF(("foreach() got a %s, expected a (&)string/array/mapping/struct or number.\n"
15415                    , typename(sp->type)
15416                    ));
15417 
15418         if (gen_refs && arg->type == T_NUMBER)
15419             ERROR("foreach() got a &number, expected a (&)string/array/mapping/struct or number.\n"
15420                    );
15421 
15422         /* Find out how many variables we require */
15423 
15424         if (arg->type == T_NUMBER)
15425         {
15426             count = arg->u.number;
15427             if (count < 0 && !use_range)
15428                 ERRORF(("foreach() got a %"PRIdPINT", expected a non-negative "
15429                         "number.", count));
15430             vars_required = 1;
15431         }
15432         else if (arg->type == T_STRING)
15433         {
15434             count = mstrsize(arg->u.str);
15435             vars_required = 1;
15436 
15437             if (gen_refs)
15438             {
15439                 string_t *str;
15440 
15441                 /* If the string is tabled, i.e. not changeable, or has more
15442                  * than one reference, allocate a new copy which can be
15443                  * changed safely.
15444                  */
15445                 if (!mstr_singular(arg->u.str))
15446                 {
15447                     memsafe(str = unshare_mstring(arg->u.str), mstrsize(arg->u.str)
15448                            , "modifiable string");
15449                     arg->u.str = str;
15450                 }
15451 
15452                 /* Replace the string-lvalue on the stack by the string
15453                  * itself - we don't need the lvalue any more.
15454                  */
15455                 str = ref_mstring(arg->u.str);
15456                 free_svalue(sp);
15457                 put_string(sp, str);
15458             }
15459         }
15460         else if (arg->type == T_POINTER)
15461         {
15462             check_for_destr(arg->u.vec);
15463             count = VEC_SIZE(arg->u.vec);
15464             vars_required = 1;
15465 
15466             if (gen_refs)
15467             {
15468                 /* Replace the array-lvalue on the stack by the array
15469                  * itself - we don't need the lvalue any more.
15470                  */
15471                 vector_t * vec = arg->u.vec;
15472 
15473                 (void)ref_array(vec);
15474                 free_svalue(sp);
15475                 put_array(sp, vec);
15476             }
15477         }
15478 #ifdef USE_STRUCTS
15479         else if (arg->type == T_STRUCT)
15480         {
15481             struct_check_for_destr(arg->u.strct);
15482             count = struct_size(arg->u.strct);
15483             vars_required = 1;
15484 
15485             if (gen_refs)
15486             {
15487                 /* Replace the struct-lvalue on the stack by the struct
15488                  * itself - we don't need the lvalue any more.
15489                  */
15490                 struct_t * st = arg->u.strct;
15491 
15492                 (void)ref_struct(st);
15493                 free_svalue(sp);
15494                 put_struct(sp, st);
15495             }
15496         }
15497 #endif /* USE_STRUCTS */
15498         else
15499         {
15500             mapping_t *m;
15501             vector_t  *indices;
15502 
15503             m = arg->u.map;
15504             vars_required = 1 + m->num_values;
15505             indices = m_indices(m);
15506 
15507             count = MAP_SIZE(m);
15508               /* after m_indices(), else we'd count destructed entries */
15509 
15510             if (gen_refs)
15511             {
15512                 /* Replace the mapping-lvalue on the stack by the mapping
15513                  * itself - we don't need the lvalue any more.
15514                  */
15515                 (void)ref_mapping(m);
15516                 free_svalue(sp);
15517                 put_mapping(sp, m);
15518             }
15519 
15520             /* Push the indices array and remember the fact in nargs.
15521              */
15522             sp++;
15523             put_array(sp, indices);
15524             nargs = -nargs;
15525         }
15526 
15527         /* If this is a range foreach, drop the upper bound svalue
15528          * from the stack and calculate the actual number of steps, and
15529          * get the lower bound svalue to be used as starting index.
15530          * Since this lower bound svalue is an integer as well, we can
15531          * then pretend to execute a normal foreach over an integer.
15532          */
15533         if (use_range)
15534         {
15535             free_svalue(sp); sp--;
15536             if (sp->type != T_NUMBER)
15537                 ERRORF(("foreach() got a %s, expected a number for lower range bound.\n"
15538                        , typename(sp->type)
15539                        ));
15540             start = sp->u.number;
15541             if (count < start)
15542                 count = 0;
15543             else
15544             {
15545                 count = count - sp->u.number + 1;
15546                 if (!count)
15547                 {
15548                     /* Range is __INT_MIN_..__INT_MAX__: for this
15549                      * we need to make one more loop than we can count.
15550                      */
15551                     do_extra_loop = MY_TRUE;
15552                 }
15553             }
15554         }
15555 
15556         /* Push the count and the starting index */
15557         push_number(sp, count); sp->x.generic = nargs;
15558         push_number(sp, start); sp->x.generic = do_extra_loop
15559                                                 ? 2
15560                                                 : (gen_refs ? 1 : 0);
15561 
15562 #ifdef DEBUG
15563         /* The <nargs> lvalues and our temporaries act as hidden
15564          * local variables. We therefore adapt the variable count
15565          * so that a F_RETURN won't complain.
15566          */
15567         if (nargs >= 0)
15568             csp->num_local_variables += 2 + nargs;
15569         else
15570             csp->num_local_variables += 3 + (-nargs);
15571 #endif
15572 
15573         /* Now branch to the FOREACH_NEXT */
15574         pc += offset;
15575 
15576         break;
15577     }
15578 
15579     CASE(F_FOREACH_NEXT);         /* --- foreach_next <offset> --- */
15580     {
15581         /* Start the next (resp. the first) iteration of a foreach()
15582          * loop. ushort <offset> is the distance to branch back to the
15583          * loop body, counted from the first byte of the next instruction.
15584          * For the stack layout, see F_FOREACH.
15585          */
15586 
15587         unsigned short offset;
15588         p_int     ix;
15589         svalue_t *lvalue;  /* Pointer to the first lvalue */
15590         Bool      gen_refs;
15591 
15592 
15593         LOAD_SHORT(offset, pc);
15594 
15595         ix = sp->u.number;
15596         if (sp->x.generic == 2)
15597         {
15598             sp->x.generic = 0;
15599             /* FOREACH_RANGE with extra loop: don't increment the
15600              * 'next' number on this one.
15601              */
15602         }
15603         else
15604         {
15605             /* Is there something left to iterate? */
15606             if (0 == sp[-1].u.number)
15607                 break; /* Nope */
15608 
15609             sp->u.number++; /* next number */
15610         }
15611         sp[-1].u.number--; /* decrement loop count */
15612 
15613         gen_refs = sp->x.generic;
15614 
15615         if (sp[-1].x.generic < 0)
15616         {
15617             /* We loop over a mapping */
15618 
15619             mapping_t *m;
15620             vector_t  *indices;
15621             svalue_t  *values;
15622             p_int        left;
15623 
15624             lvalue = sp + sp[-1].x.generic - 2;
15625 
15626             m = sp[-3].u.map;
15627             indices = sp[-2].u.vec;
15628 
15629             values = get_map_value(m, indices->item+ix);
15630             if (values == &const0)
15631             {
15632                 /* Whoops, the entry has vanished.
15633                  * Start over with this instruction again, the
15634                  * index on the stack has been incremented already.
15635                  */
15636                 pc -= 3;
15637                 break;
15638             }
15639 
15640             /* Assign the index we used */
15641             {
15642                 svalue_t *dest;
15643 
15644 #ifdef DEBUG
15645                 if (lvalue->type != T_LVALUE)
15646                     fatal("Bad argument to foreach(): not a lvalue\n");
15647                     /* TODO: Give type and value */
15648 #endif
15649                 dest = lvalue->u.lvalue;
15650                 assign_svalue(dest, indices->item+ix);
15651 
15652                 lvalue++;
15653             }
15654 
15655             /* Loop over the values and assign them */
15656             left = -(sp[-1].x.generic) - 2;
15657             if (left > m->num_values)
15658                 left = m->num_values;
15659 
15660             for ( ; left > 0; left--, lvalue++, values++)
15661             {
15662                 svalue_t *dest;
15663 
15664 #ifdef DEBUG
15665                 if (lvalue->type != T_LVALUE)
15666                     fatal("Bad argument to foreach(): not a lvalue\n");
15667                     /* TODO: Give type and value */
15668 #endif
15669                 dest = lvalue->u.lvalue;
15670                 if (!gen_refs)
15671                 {
15672                     assign_svalue(dest, values);
15673                 }
15674                 else
15675                 {
15676                     struct protected_lvalue * prot;
15677 
15678                     free_svalue(dest);
15679 
15680                     prot = (struct protected_lvalue *)xalloc(sizeof *prot);
15681                     prot->v.type = T_PROTECTED_LVALUE;
15682                     prot->v.u.lvalue = values;
15683                     (void)ref_mapping(m);
15684                     BUILD_MAP_PROTECTOR(prot->protector, m)
15685 
15686                     dest->type = T_LVALUE;
15687                     dest->u.lvalue = &prot->v;
15688                 }
15689             }
15690 
15691             /* Ta-Da! */
15692         }
15693         else
15694         {
15695             lvalue = sp - sp[-1].x.generic - 1;
15696 #ifdef DEBUG
15697             if (lvalue->type != T_LVALUE)
15698                 fatal("Bad argument to foreach(): not a lvalue\n");
15699                 /* TODO: Give type and value */
15700 #endif
15701             lvalue = lvalue->u.lvalue;
15702 
15703             if (sp[-2].type == T_NUMBER)
15704             {
15705                   free_svalue(lvalue);
15706                   put_number(lvalue, ix);
15707             }
15708             else if (sp[-2].type == T_STRING)
15709             {
15710                 free_svalue(lvalue);
15711                 if (!gen_refs)
15712                 {
15713                     put_number(lvalue, get_txt(sp[-2].u.str)[ix]);
15714                 }
15715                 else
15716                 {
15717                     svalue_t * str = sp-2;
15718                     struct protected_char_lvalue *val;
15719 
15720                     /* Compute and return the result */
15721 
15722                     (void)ref_mstring(str->u.str);
15723                     val = (struct protected_char_lvalue *)xalloc(sizeof *val);
15724                     val->v.type = T_PROTECTED_CHAR_LVALUE;
15725                     val->v.u.charp = &(get_txt(str->u.str)[ix]);
15726                     val->lvalue = str;
15727                     val->start = get_txt(str->u.str);
15728                     val->protector.type = T_INVALID;
15729 
15730                     lvalue->type = T_LVALUE;
15731                     lvalue->u.protected_char_lvalue = val;
15732                 }
15733             }
15734             else if (sp[-2].type == T_POINTER)
15735             {
15736                 if (ix >= VEC_SIZE(sp[-2].u.vec))
15737                     break;
15738                     /* Oops, this array shrunk while we're looping over it.
15739                      * We stop processing and continue with the following
15740                      * FOREACH_END instruction.
15741                      */
15742 
15743                 if (!gen_refs)
15744                 {
15745                     assign_svalue(lvalue, sp[-2].u.vec->item+ix);
15746                 }
15747                 else
15748                 {
15749                     svalue_t * vec = sp-2;
15750                     svalue_t * item;
15751                     struct protected_lvalue * prot;
15752 
15753                     free_svalue(lvalue);
15754 
15755                     /* Compute the indexed item and set up the protector */
15756 
15757                     item = &vec->u.vec->item[ix];
15758                     prot = (struct protected_lvalue *)xalloc(sizeof *prot);
15759                     prot->v.type = T_PROTECTED_LVALUE;
15760                     prot->v.u.lvalue = item;
15761                     put_ref_array(&(prot->protector), vec->u.vec);
15762 
15763                     lvalue->type = T_LVALUE;
15764                     lvalue->u.lvalue = &prot->v;
15765                 }
15766             }
15767 #ifdef USE_STRUCTS
15768             else if (sp[-2].type == T_STRUCT)
15769             {
15770                 if (ix >= struct_size(sp[-2].u.strct))
15771                     break;
15772                     /* Oops, somehow the struct managed to shring while
15773                      * we're looping over it.
15774                      * We stop processing and continue with the following
15775                      * FOREACH_END instruction.
15776                      */
15777 
15778                 if (!gen_refs)
15779                 {
15780                     assign_svalue(lvalue, sp[-2].u.strct->member+ix);
15781                 }
15782                 else
15783                 {
15784                     svalue_t * st = sp-2;
15785                     svalue_t * item;
15786                     struct protected_lvalue * prot;
15787 
15788                     free_svalue(lvalue);
15789 
15790                     /* Compute the indexed item and set up the protector */
15791 
15792                     item = &st->u.strct->member[ix];
15793                     prot = (struct protected_lvalue *)xalloc(sizeof *prot);
15794                     prot->v.type = T_PROTECTED_LVALUE;
15795                     prot->v.u.lvalue = item;
15796                     put_ref_struct(&(prot->protector), st->u.strct);
15797 
15798                     lvalue->type = T_LVALUE;
15799                     lvalue->u.lvalue = &prot->v;
15800                 }
15801             }
15802             else
15803               fatal("foreach() requires a string, array, struct or mapping.\n");
15804               /* If this happens, the check in F_FOREACH failed. */
15805 #else /* USE_STRUCTS */
15806             else
15807               fatal("foreach() requires a string, array or mapping.\n");
15808               /* If this happens, the check in F_FOREACH failed. */
15809 #endif /* USE_STRUCTS */
15810         }
15811 
15812         /* All that is left is to branch back. */
15813         pc -= offset;
15814         break;
15815     }
15816 
15817     CASE(F_FOREACH_END);            /* --- foreach_end         --- */
15818     {
15819         /* The foreach() loop ended or was terminated by a break.
15820          * All there's left to do is cleaning up the stack.
15821          */
15822 
15823         int nargs;
15824 
15825         nargs = sp[-1].x.generic;
15826 
15827         if (nargs < 0)
15828             nargs = (-nargs) + 3;
15829         else
15830             nargs = nargs + 2;
15831 
15832         pop_n_elems(nargs);
15833 
15834 #ifdef DEBUG
15835         /* The <nargs> lvalues and our temporaries acted as hidden
15836          * local variables. We now count back the variable count
15837          * so that a F_RETURN won't complain.
15838          */
15839         csp->num_local_variables -= nargs;
15840 #endif
15841 
15842         break;
15843     }
15844 
15845     CASE(F_END_CATCH);                  /* --- end_catch       --- */
15846         /* For a catch(...guarded code...) statement, the compiler
15847          * generates a F_END_CATCH as last instruction of the
15848          * guarded code.
15849          *
15850          * Executed when no error occured, it returns into
15851          * catch_instruction() to clean up the
15852          * error recovery information pushed by the F_CATCH
15853          * and leave a 0 on the stack.
15854          *
15855          * dump_trace() checks for this bytecode, but accepts a normal
15856          * instruction as well as an escaped instruction.
15857          */
15858 
15859         return MY_TRUE;
15860         break;
15861 
15862                           /* --- breakn_continue <num> <offset> ---*/
15863     CASE(F_BREAKN_CONTINUE);
15864         /* Implement the 'continue;' statement from within
15865          * a nested surrounding structure.
15866          *
15867          * Pop <num>+1 (uint8) break-levels from the break stack
15868          * and jump by (32-Bit) long <offset> bytes, counted from the
15869          * first by of <offset>
15870          */
15871 
15872         break_sp +=
15873           LOAD_UINT8(pc) * (sizeof(svalue_t)/sizeof(*break_sp));
15874         /* FALLTHROUGH */
15875 
15876     CASE(F_BREAK_CONTINUE);       /* --- break_continue <offset> ---*/
15877     {
15878         /* Implement the 'continue;' statement for the immediate
15879          * surrounding structure.
15880          *
15881          * Pop one break-level from the break stack and jump
15882          * by (32-Bit) unsigned long <offset> bytes, counted from the
15883          * first by of <offset>
15884          *
15885          * Pitfall: the offset is added to the current pc in 16-Bit
15886          * unsigned arithmetic, allowing to jump backwards using big
15887          * enough values.
15888          *
15889          * TODO: Make that a proper signed short.
15890          */
15891 
15892         /* TODO: uint16 */ unsigned long offset;
15893 
15894         break_sp += sizeof(svalue_t)/sizeof(*break_sp);
15895         GET_LONG(offset, pc);
15896         offset += pc - current_prog->program;
15897         pc = current_prog->program + offset;
15898         break;
15899     }
15900 
15901 #ifdef F_JUMP
15902     CASE(F_JUMP);                   /* --- jump <dest>         --- */
15903     {
15904         /* Jump to the (24-Bit) unsigned address <dest> (absolute jump).
15905          */
15906 
15907         unsigned long dest;
15908 
15909         GET_3BYTE(dest, pc);
15910         pc = current_prog->program + dest;
15911         break;
15912     }
15913 #endif /* F_JUMP */
15914 
15915     CASE(F_NO_WARN_DEPRECATED);     /* --- no_warn_deprecated  --- */
15916     {
15917         /* Set the runtime_no_warn_deprecated flag for the next
15918          * instruction.
15919          */
15920 
15921         runtime_no_warn_deprecated = MY_TRUE;
15922         break;
15923     }
15924 
15925     CASE(F_ARRAY_RANGE_CHECK);       /* --- array_range_check  --- */
15926     {
15927         /* Set the runtime_array_range_check flag for the next
15928          * instruction.
15929          */
15930 
15931         runtime_array_range_check = MY_TRUE;
15932         break;
15933     }
15934 
15935     /* --- Efuns: Miscellaneous --- */
15936 
15937     CASE(F_CLONEP);                 /* --- clonep              --- */
15938     {
15939         /* EFUN clonep()
15940          *
15941          *   int clonep()
15942          *   int clonep (object obj)
15943          *   int clonep (string obj)
15944          *
15945          * The efun returns 1 if <obj> is a clone, and 0 if it is not.
15946          * The <obj> can be given as the object itself, or by its name.
15947          * If <obj> is omitted, the current object is tested.
15948          * Arguments of other types return 0.
15949          */
15950 
15951         int i;
15952 
15953         if (sp->type == T_OBJECT)
15954         {
15955             i = (sp->u.ob->flags & O_CLONE);
15956         }
15957         else if (sp->type == T_STRING)
15958         {
15959             object_t *o;
15960 
15961             o = find_object(sp->u.str);
15962             if (!o)
15963                 ERRORF(("No such object '%s'.\n", get_txt(sp->u.str)));
15964             i = o->flags & O_CLONE;
15965         }
15966         else
15967             i = 0;
15968         free_svalue(sp);
15969         put_number(sp, i ? 1 : 0);
15970         break;
15971     }
15972 
15973     CASE(F_CLOSUREP);               /* --- closurep            --- */
15974     {
15975         /* EFUN closurep()
15976          *
15977          *   int closurep(mixed)
15978          *
15979          * Returns 1 if the argument is a closure.
15980          */
15981 
15982         int i;
15983 
15984         i = sp->type == T_CLOSURE;
15985         free_svalue(sp);
15986         put_number(sp, i);
15987         break;
15988     }
15989 
15990     CASE(F_FLOATP);                 /* --- floatp              --- */
15991     {
15992         /* EFUN floatp()
15993          *
15994          *   int floatp(mixed)
15995          *
15996          * Returns 1 if the argument is a float.
15997          */
15998 
15999         int i;
16000 
16001         i = sp->type == T_FLOAT;
16002         free_svalue(sp);
16003         put_number(sp, i);
16004         break;
16005     }
16006 
16007     CASE(F_INTP);                   /* --- intp                --- */
16008     {
16009         /* EFUN intp()
16010          *
16011          *   int intp(mixed)
16012          *
16013          * Returns 1 if the argument is an integer.
16014          */
16015 
16016         int i;
16017 
16018         i = sp->type == T_NUMBER;
16019         free_svalue(sp);
16020         put_number(sp, i);
16021         break;
16022     }
16023 
16024     CASE(F_MAPPINGP);               /* --- mappingp            --- */
16025     {
16026         /* EFUN mappingp()
16027          *
16028          *   int mappingp(mixed)
16029          *
16030          * Returns 1 if the argument is a mapping.
16031          */
16032 
16033         int i;
16034 
16035         i = sp->type == T_MAPPING;
16036         free_svalue(sp);
16037         put_number(sp, i);
16038         break;
16039     }
16040 
16041     CASE(F_OBJECTP);                /* --- objectp              --- */
16042     {
16043         /* EFUN objectp()
16044          *
16045          *   int objectp(mixed)
16046          *
16047          * Returns 1 if the argument is an object.
16048          */
16049 
16050         int i;
16051 
16052         i = sp->type == T_OBJECT;
16053         free_svalue(sp);
16054         put_number(sp, i);
16055         break;
16056     }
16057 
16058     CASE(F_POINTERP);               /* --- pointerp            --- */
16059     {
16060         /* EFUN pointerp()
16061          *
16062          *   int pointerp(mixed)
16063          *
16064          * Returns 1 if the argument is an array.
16065          */
16066 
16067         int i;
16068 
16069         i = sp->type == T_POINTER;
16070         free_svalue(sp);
16071         put_number(sp, i);
16072         break;
16073     }
16074 
16075     CASE(F_REFERENCEP);                /* --- referencep      --- */
16076       {
16077         /* EFUN referencep()
16078          *
16079          *   int referencep(mixed arg)
16080          *
16081          * Returns true if arg was passed by reference to the current
16082          * function, instead of the usual call-by-value.
16083          */
16084 
16085         int i;
16086 
16087         i = (sp->type == T_LVALUE && sp->u.lvalue->type == T_LVALUE);
16088         free_svalue(sp);
16089         put_number(sp, i);
16090         break;
16091       }
16092 
16093     CASE(F_STRINGP);                /* --- stringp             --- */
16094     {
16095         /* EFUN stringp()
16096          *
16097          *   int stringp(mixed)
16098          *
16099          * Returns 1 if the argument is a string.
16100          */
16101 
16102         int i;
16103 
16104         i = sp->type == T_STRING;
16105         free_svalue(sp);
16106         put_number(sp, i);
16107         break;
16108     }
16109 
16110 #ifdef USE_STRUCTS
16111     CASE(F_STRUCTP);                /* --- structp             --- */
16112     {
16113         /* EFUN structp()
16114          *
16115          *   int structp(mixed)
16116          *
16117          * Returns 1 if the argument is a struct.
16118          */
16119 
16120         int i;
16121 
16122         i = sp->type == T_STRUCT;
16123         free_svalue(sp);
16124         put_number(sp, i);
16125         break;
16126     }
16127 #endif
16128 
16129     CASE(F_SYMBOLP);                /* --- symbolp             --- */
16130     {
16131         /* EFUN symbolp()
16132          *
16133          *   int symbolp(mixed)
16134          *
16135          * Returns 1 if the argument is a symbol.
16136          */
16137 
16138         int i;
16139 
16140         i = sp->type == T_SYMBOL;
16141         free_svalue(sp);
16142         put_number(sp, i);
16143         break;
16144     }
16145 
16146     CASE(F_TYPEOF);                    /* --- typeof          --- */
16147       {
16148         /* EFUN typeof()
16149          *
16150          *   int typeof(mixed)
16151          *
16152          * Returns a code for the type of the argument, as defined in
16153          * <sys/lpctypes.h>
16154          */
16155 
16156         mp_int i = sp->type;
16157         free_svalue(sp);
16158         put_number(sp, i);
16159         break;
16160       }
16161 
16162     CASE(F_NEGATE);                 /* --- negate              --- */
16163         /* EFUN negate()
16164          *
16165          *   int|float negate(int|float arg)
16166          *
16167          * Negate the value <arg> and leave it on the stack.
16168          * Calls to this efun are mainly generated by the compiler when
16169          * it sees the unary '-' used.
16170          */
16171 
16172         if (sp->type == T_NUMBER)
16173         {
16174             if (sp->u.number == PINT_MIN)
16175                 ERRORF(("Numeric overflow: - %"PRIdPINT"\n", sp->u.number));
16176             sp->u.number = - sp->u.number;
16177             break;
16178         }
16179         else if (sp->type == T_FLOAT)
16180         {
16181             STORE_DOUBLE_USED
16182             double d;
16183 
16184             d = -READ_DOUBLE(sp);
16185             if (d < (-DBL_MAX) || d > DBL_MAX)
16186                 ERRORF(("Numeric overflow: -(%g)\n", READ_DOUBLE(sp)));
16187             STORE_DOUBLE(sp,d);
16188             break;
16189         }
16190         ERRORF(("Bad arg to unary minus: got %s, expected number/float\n"
16191                , typename(sp->type)
16192                ));
16193 
16194     CASE(F_RAISE_ERROR);               /* --- raise_error     --- */
16195       {
16196         /* EFUN raise_error()
16197          *
16198          *   void raise_error(string arg)
16199          *
16200          * Abort execution. If the current program execution was initiated
16201          * by catch(), that catch expression will return arg as error
16202          * code, else the arg will printed as error message. This
16203          * is very similar to throw(), but while throw() is intended to be
16204          * called inside catch(), raise_error() can be called
16205          * anywhere.
16206          */
16207 
16208         TYPE_TEST1(sp, T_STRING);
16209         ERRORF(("%s", get_txt(sp->u.str)));
16210       }
16211 
16212     CASE(F_THROW);                  /* --- throw               --- */
16213         /* EFUN throw()
16214          *
16215          *   void throw(mixed arg)
16216          *
16217          * Abort execution. If the current program execution was initiated by
16218          * catch(), that catch expression will return arg as error code.
16219          */
16220 
16221         assign_eval_cost_inl();
16222         inter_sp = --sp;
16223         inter_pc = pc;
16224         throw_error(sp+1); /* do the longjump, with extra checks... */
16225         break;
16226 
16227     /* --- Efuns: Strings --- */
16228 
16229     CASE(F_STRLEN);                 /* --- strlen              --- */
16230     {
16231         /* EFUN strlen()
16232          *
16233          *   int strlen(string str)
16234          *
16235          * Returns the length of the string str.
16236          */
16237 
16238         size_t i;
16239 
16240         if (sp->type == T_STRING)
16241         {
16242             i = mstrsize(sp->u.str);
16243             free_string_svalue(sp);
16244             put_number(sp, i);
16245             break;
16246         }
16247         if (sp->type == T_NUMBER && sp->u.number == 0)
16248             break;
16249         RAISE_ARG_ERROR(1, TF_NULL|TF_STRING, sp->type);
16250         /* NOTREACHED */
16251     }
16252 
16253     /* --- Efuns: Arrays and Mappings --- */
16254 
16255     CASE(F_SIZEOF);                 /* --- sizeof              --- */
16256     {
16257         /* EFUN sizeof()
16258          *
16259          *   int sizeof(mixed arr)
16260          *
16261          * Returns the number of elements of an array, the number of
16262          * keys in a mapping, or the number of characters in a string.
16263          *
16264          * As a special case, the number 0 can be passed, and the function
16265          * will return 0.
16266          */
16267 
16268         p_int i;
16269 
16270         if (sp->type == T_STRING)
16271         {
16272             i = mstrsize(sp->u.str);
16273             free_svalue(sp);
16274             put_number(sp, i);
16275             break;
16276         }
16277 
16278         if (sp->type == T_POINTER)
16279         {
16280             i = VEC_SIZE(sp->u.vec);
16281             free_svalue(sp);
16282             put_number(sp, i);
16283             break;
16284         }
16285 
16286 #ifdef USE_STRUCTS
16287         if (sp->type == T_STRUCT)
16288         {
16289             i = struct_size(sp->u.strct);
16290             free_svalue(sp);
16291             put_number(sp, i);
16292             break;
16293         }
16294 #endif /* USE_STRUCTS */
16295 
16296         if (sp->type == T_MAPPING)
16297         {
16298             mapping_t *m = sp->u.map;
16299             check_map_for_destr(m); /* Don't count the destructed keys! */
16300             i = MAP_SIZE(m);
16301             free_svalue(sp);
16302             put_number(sp, i);
16303             break;
16304         }
16305 
16306         if (sp->type == T_NUMBER && sp->u.number == 0)
16307             break;
16308 
16309         RAISE_ARG_ERROR(1, TF_NULL|TF_MAPPING|TF_POINTER, sp->type);
16310         /* NOTREACHED */
16311     }
16312 
16313     /* --- Efuns: Functions and Closures --- */
16314 
16315     CASE(F_CALL_DIRECT);            /* --- call_direct         --- */
16316     CASE(F_CALL_OTHER);             /* --- call_other          --- */
16317     {
16318         /* EFUN call_other(), call_direct()
16319          *
16320          *     unknown call_other(object|string ob, string str, mixed arg, ...)
16321          *     unknown ob->fun(mixed arg, ...)
16322          *
16323          *     unknown call_direct(object|string ob, string str, mixed arg, ...)
16324          *
16325          * Call a member function in another object with an argument. The
16326          * return value is returned from the other object.  The object can be
16327          * given directly or as a string (i.e. its file name). If it is given
16328          * by a string and the object does not exist yet, it will be loaded.
16329          *
16330 #ifdef USE_ARRAY_CALLS
16331          *     unknown * call_other(object|string *ob, string str, mixed arg, ...)
16332          *     unknown * ob->fun(mixed arg, ...)
16333          *
16334          * Call a member function in other objects with the given arguments.
16335          * The return values is returned collected in an array.
16336          * Every object can be given directly or as a string (i.e. its file name).
16337          * If it is given by a string and the object does not exist yet, it will
16338          * be loaded.
16339 #endif
16340          *
16341          * The difference between call_other() and call_direct()
16342          * is that the latter does not allow the evaluation of default
16343          * methods.
16344          *
16345          * TODO: A VOID_CALL_OTHER would be nice to have when the result
16346          * TODO:: is not used.
16347          */
16348 
16349         svalue_t *arg;
16350         object_t *ob;
16351         Bool      b_use_default;
16352 
16353         num_arg = sp - ap + 1;
16354         inter_pc = pc;
16355         inter_sp = sp;
16356 
16357         arg = sp - num_arg + 1;
16358 
16359         /* Test the arguments */
16360         if (arg[0].type != T_OBJECT
16361          && arg[0].type != T_STRING
16362 #ifdef USE_ARRAY_CALLS
16363          && arg[0].type != T_POINTER
16364 #endif /* USE_ARRAY_CALLS */
16365            )
16366         {
16367 #ifdef USE_ARRAY_CALLS
16368             RAISE_ARG_ERROR(1, TF_OBJECT|TF_STRING|TF_POINTER, arg[0].type);
16369 #else
16370             RAISE_ARG_ERROR(1, TF_OBJECT|TF_STRING, arg[0].type);
16371 #endif /* USE_ARRAY_CALLS */
16372         }
16373 
16374         TYPE_TEST2(arg+1, T_STRING)
16375         if (get_txt(arg[1].u.str)[0] == ':')
16376             ERRORF(("Illegal function name in call_other: %s\n",
16377                   get_txt(arg[1].u.str)));
16378 
16379         /* No external calls may be done when this object is
16380          * destructed.
16381          */
16382         if (current_object->flags & O_DESTRUCTED)
16383         {
16384             pop_n_elems(num_arg);
16385             push_number(sp, 0);
16386             WARNF(("Call from destructed object '%s' ignored.\n"
16387                   , get_txt(current_object->name)));
16388             break;
16389         }
16390 
16391 #ifdef USE_ARRAY_CALLS
16392         if (arg[0].type != T_POINTER)
16393 #endif /* USE_ARRAY_CALLS */
16394         {
16395             /* --- The normal call other to a single object --- */
16396 
16397             assign_eval_cost_inl();
16398 
16399             if (arg[0].type == T_OBJECT)
16400                 ob = arg[0].u.ob;
16401             else /* it's a string */
16402             {
16403                 ob = get_object(arg[0].u.str);
16404                 if (ob == NULL)
16405                     ERRORF(("call_other() failed: can't get object '%s'\n"
16406                            , get_txt(arg[0].u.str)));
16407             }
16408 
16409             b_use_default =    (instruction != F_CALL_DIRECT)
16410                             && (ob != master_ob);
16411 
16412             /* Traceing, if necessary */
16413             if (TRACEP(TRACE_CALL_OTHER) && TRACE_IS_INTERACTIVE())
16414             {
16415                 if (!++traceing_recursion)
16416                 {
16417                     do_trace("Call other ", get_txt(arg[1].u.str), "\n");
16418                 }
16419                 traceing_recursion--;
16420             }
16421 
16422             /* Call the function with the remaining args on the stack.
16423              */
16424             if (!int_apply(arg[1].u.str, ob, num_arg-2, MY_FALSE, b_use_default))
16425             {
16426                 /* Function not found */
16427                 if (b_use_default) /* int_apply() removed the args */
16428                     sp -= num_arg-2;
16429                 else
16430                     pop_n_elems(num_arg-2);
16431                 pop_n_elems(2);
16432                 push_number(sp, 0);
16433                 break;
16434             }
16435             sp -= num_arg - 3;
16436 
16437             /* The result of the function call is on the stack. But so
16438              * is the function name and object that was called.
16439              * These have to be removed.
16440              */
16441             arg = sp;           /* Remember where the function call result is */
16442             free_string_svalue(--sp);
16443             free_svalue(--sp);  /* Remove old arguments to call_other */
16444             *sp = *arg;         /* Re-insert function result */
16445         }
16446 #ifdef USE_ARRAY_CALLS
16447         else
16448         {
16449             /* --- The other call other to an array of objects --- */
16450 
16451             svalue_t *svp;
16452             size_t    size;
16453 
16454             /* The array with the objects will also hold the results.
16455              * For that, it mustn't be shared, therefore we create a
16456              * copy if necessary.
16457              */
16458             size = VEC_SIZE(arg->u.vec);
16459             if (arg->u.vec->ref != 1 && size != 0)
16460             {
16461                 vector_t *vec;
16462                 svalue_t *to;
16463 
16464                 vec = allocate_array_unlimited(size);
16465                 if (!vec)
16466                     ERROR("Out of memory.\n");
16467                 for (svp = arg->u.vec->item, to = vec->item
16468                     ; size != 0
16469                     ; size--, svp++, to++)
16470                     assign_svalue_no_free(to, svp);
16471                 free_array(arg->u.vec);
16472                 arg->u.vec = vec; /* adopts the reference */
16473             }
16474 
16475             /* Now loop over the array of objects and call the function
16476              * in each of it. For that, the arguments are duly replicated
16477              * for every call.
16478              */
16479             size = VEC_SIZE(arg->u.vec);
16480             svp = arg->u.vec->item;
16481             for ( ; size != 0; size--, svp++)
16482             {
16483                 int i;
16484 
16485                 assign_eval_cost_inl();
16486                 inter_sp = sp; /* Might be clobbered from previous loop */
16487 
16488                 if (svp->type == T_OBJECT)
16489                     ob = svp->u.ob;
16490                 else if (svp->type == T_STRING)
16491                 {
16492                     ob = get_object(svp->u.str);
16493                     if (ob == NULL)
16494                     {
16495                         ERRORF(("call_other() failed: can't get object '%s'\n"
16496                                , get_txt(svp->u.str)));
16497                         /* NOTREACHED */
16498                         continue;
16499                     }
16500                 }
16501                 else if (svp->type == T_NUMBER && svp->u.number == 0)
16502                 {
16503                     free_svalue(svp);
16504                     put_number(svp, 0);
16505                     continue;
16506                 }
16507                 else
16508                     ERRORF(("Bad arg for call_other() at index %"PRIdMPINT": "
16509                             "got %s, expected string/object\n"
16510                            , (mp_int)(svp - arg->u.vec->item)
16511                            , typename(svp->type)
16512                            ));
16513 
16514                 /* Destructed objects yield 0 */
16515                 if (ob->flags & O_DESTRUCTED)
16516                 {
16517                     free_svalue(svp);
16518                     put_number(svp, 0);
16519                     continue;
16520                 }
16521 
16522                 b_use_default =    (instruction != F_CALL_DIRECT)
16523                                 && (ob != master_ob);
16524 
16525                 /* Traceing, if necessary */
16526                 if (TRACEP(TRACE_CALL_OTHER) && TRACE_IS_INTERACTIVE())
16527                 {
16528                     if (!++traceing_recursion)
16529                     {
16530                         do_trace("Call other ", get_txt(arg[1].u.str), "\n");
16531                     }
16532                     traceing_recursion--;
16533                 }
16534 
16535                 /* Duplicate the arguments to pass, increasing sp on
16536                  * the way. Optimizing this for the last pass is
16537                  * dangerous as not every iteration will come here.
16538                  */
16539                 for (i = 2; i < num_arg; i++)
16540                     assign_svalue_no_free(++sp, arg+i);
16541 
16542                 /* Call the function with the remaining args on the stack.
16543                  */
16544                 inter_sp = sp; /* update to new setting */
16545                 if (!int_apply(arg[1].u.str, ob, num_arg-2, MY_FALSE, b_use_default))
16546                 {
16547                     /* Function not found, Assign 0 as result.
16548                      */
16549                     if (b_use_default) /* int_apply() removed the args */
16550                         sp -= num_arg-2;
16551                     else
16552                         pop_n_elems(num_arg-2);
16553                     free_svalue(svp);
16554                     put_number(svp, 0);
16555                 }
16556                 else
16557                 {
16558                     /* Function found - assign the result from the stack */
16559                     sp -= num_arg-3;
16560                     free_svalue(svp);
16561                     transfer_svalue_no_free(svp, sp--);
16562                 }
16563             } /* for (objects in array) */
16564 
16565             /* Remove the original function call arguments from the stack.
16566              */
16567             pop_n_elems(num_arg-2);
16568 
16569             /* Calls complete, left on the stack are now the function name
16570              * and, in arg, the final result.
16571              */
16572             free_string_svalue(sp); sp--;
16573         }
16574 #endif /* USE_ARRAY_CALLS */
16575 
16576         break;
16577     }
16578 
16579     CASE(F_EXTERN_CALL);               /* --- extern_call     --- */
16580       {
16581         /* EFUN extern_call()
16582          *
16583          *   int extern_call();
16584          *
16585          * Returns zero, if the function that is currently being executed
16586          * was called by a local call, non-zero for call_other(), driver
16587          * applies, closure calls, etc. Currently the only return value
16588          * for them is 1, but later the various methods may be
16589          * distinguished by means of the return value.
16590          */
16591 
16592 
16593         struct control_stack * pt = csp;
16594 
16595         while (pt->catch_call) pt--;
16596         push_number(sp, (pt->extern_call & ~CS_PRETEND) ? 1 : 0);
16597         break;
16598       }
16599 
16600     /* --- Efuns: Objects --- */
16601 
16602     CASE(F_MASTER);                 /* --- master              --- */
16603       {
16604         /* EFUN master()
16605          *
16606          *   object master(int dont_load)
16607          *
16608          * Return the master object. If <dont_load> is false, the
16609          * function first makes sure that the master object exists.
16610          * If <dont_load> is true, the function just returns the current
16611          * master object, or 0 if the current master has been destructed.
16612          */
16613 
16614         TYPE_TEST1(sp, T_NUMBER)
16615 
16616         if (! sp->u.number)
16617             assert_master_ob_loaded();
16618 
16619         free_svalue(sp);
16620 
16621         if (master_ob)
16622             put_ref_object(sp, master_ob, "master");
16623         else
16624             put_number(sp, 0);
16625         break;
16626      }
16627 
16628     CASE(F_THIS_INTERACTIVE);       /* --- this_interactive    --- */
16629         /* EFUN this_interactive()
16630          *
16631          *   object this_interactive(void)
16632          *
16633          * this_interactive() returns the current interactive object, if
16634          * any, i.e. the one who "hit the RETURN key".
16635          */
16636 
16637         if (current_interactive
16638          && !(current_interactive->flags & O_DESTRUCTED))
16639             push_ref_object(sp, current_interactive, "this_interactive");
16640         else
16641             push_number(sp, 0);
16642         break;
16643 
16644     CASE(F_THIS_OBJECT);            /* --- this_object         --- */
16645         /* EFUN this_object()
16646          *
16647          *   object this_object(void)
16648          *
16649          * Return the object pointer for this object.
16650          */
16651 
16652         if (current_object->flags & O_DESTRUCTED)
16653         {
16654             push_number(sp, 0);
16655             break;
16656         }
16657         push_ref_object(sp, current_object, "this_object");
16658         break;
16659 
16660     /* --- Efuns: Verbs and Commands --- */
16661 
16662     CASE(F_THIS_PLAYER);            /* --- this_player         --- */
16663         /* EFUN this_player()
16664          *
16665          *   object this_player(void)
16666          *
16667          * Return the current command giver.  This can be an interactive
16668          * user or a living object like a npc.
16669          *
16670          * If called from inside the heart_beat() of a not living object
16671          * 0 will be returned.
16672          */
16673 
16674         if (command_giver && !(command_giver->flags & O_DESTRUCTED))
16675             push_ref_object(sp, command_giver, "this_player");
16676         else
16677             push_number(sp, 0);
16678         break;
16679 
16680     /* --- Optional Efuns: Technical --- */
16681 
16682 #ifdef F_BREAK_POINT
16683     CASE(F_BREAK_POINT);            /* --- break_point         --- */
16684         /* EFUN break_point()
16685          *
16686          *   void break_point()
16687          *
16688          * This function is for system internal use and should never be called
16689          * by user objects. It is supposed to check the stack integrity and
16690          * aborts the driver when it detects corruption.
16691          *
16692          */
16693 
16694         if (sp - fp - csp->num_local_variables + 1 != 0)
16695             fatal("Bad stack pointer.\n");
16696         break;
16697 #endif
16698 
16699 #ifdef F_SWAP
16700     CASE(F_SWAP);                      /* --- swap            --- */
16701       {
16702         /* EFUN swap()
16703          *
16704          *   void swap(object obj)
16705          *
16706          * Swap out an object. This efun is only used for system internal
16707          * debugging and can cause a crash.
16708          */
16709 
16710         object_t *ob;
16711 
16712         /* Test the arguments */
16713         if (sp->type != T_OBJECT)
16714             RAISE_ARG_ERROR(1, TF_OBJECT, sp->type);
16715 
16716         ob = sp->u.ob;
16717         if (ob != current_object
16718          && !(ob->flags & O_DESTRUCTED)
16719           ) /* should also check csp */
16720         {
16721             if (!O_PROG_SWAPPED(ob))
16722                 (void)swap_program(ob);
16723             if (!O_VAR_SWAPPED(ob))
16724                 (void)swap_variables(ob);
16725         }
16726         free_svalue(sp--);
16727         break;
16728       }
16729 #endif
16730 
16731     } /* end of the monumental switch */
16732 
16733     /* Instruction executed */
16734 
16735     /* Reset the no-warn-deprecated flag */
16736     if (instruction != F_NO_WARN_DEPRECATED)
16737         runtime_no_warn_deprecated = MY_FALSE;
16738 
16739     /* Reset the no-warn-deprecated flag */
16740     if (instruction != F_ARRAY_RANGE_CHECK)
16741         runtime_array_range_check = MY_FALSE;
16742 
16743     /* Even intermediate results could exceed the stack size.
16744      * We better check for that.
16745      */
16746     if (sp - VALUE_STACK == SIZEOF_STACK - 1)
16747     {
16748         /* sp ist just at then end of the stack area */
16749         stack_overflow(sp, fp, pc);
16750     }
16751     else if ((mp_int)(sp - VALUE_STACK) > (mp_int)(SIZEOF_STACK - 1))
16752     {
16753         /* When we come here, we already overwrote the bounds
16754          * of the stack :-(
16755          */
16756         fatal("Fatal stack overflow: %"PRIdMPINT" too high\n"
16757              , (mp_int)(sp - VALUE_STACK - (SIZEOF_STACK - 1))
16758              );
16759     }
16760 
16761 #ifdef DEBUG
16762     if (expected_stack && expected_stack != sp)
16763     {
16764         fatal( "Bad stack after evaluation.\n"
16765                "sp: %p expected: %p\n"
16766                "Instruction %d(%s), num arg %d\n"
16767              , sp, expected_stack
16768              , instruction, get_f_name(instruction), num_arg);
16769     }
16770 
16771     if (sp < fp + csp->num_local_variables - 1)
16772     {
16773         fatal( "Bad stack after evaluation.\n"
16774                "sp: %p minimum expected: %p\n"
16775                "Instruction %d(%s), num arg %d\n"
16776              , sp, (fp + csp->num_local_variables - 1)
16777              , instruction, get_f_name(instruction), num_arg);
16778     }
16779 #endif /* DEBUG */
16780 
16781     /* Execute the next instruction */
16782 
16783     goto again;
16784 
16785     /* Get rid of the handy but highly local macros */
16786 #   undef GET_NUM_ARG
16787 #   undef RAISE_ARG_ERROR
16788 #   undef BAD_ARG_ERROR
16789 #   undef OP_ARG_ERROR
16790 #   undef BAD_OP_ARG
16791 #   undef TYPE_TEST1
16792 #   undef TYPE_TEST2
16793 #   undef TYPE_TEST3
16794 #   undef TYPE_TEST4
16795 #   undef TYPE_TEST_LEFT
16796 #   undef TYPE_TEST_RIGHT
16797 #   undef TYPE_TEST_EXP_LEFT
16798 #   undef TYPE_TEST_EXP_RIGHT
16799 #   undef CASE
16800 #   undef ARG_ERROR_TEMPL
16801 #   undef OP_ARG_ERROR_TEMPL
16802 #   undef TYPE_TEST_TEMPL
16803 #   undef OP_TYPE_TEST_TEMPL
16804 #   undef EXP_TYPE_TEST_TEMPL
16805 
16806 } /* eval_instruction() */
16807 
16808 /*-------------------------------------------------------------------------*/
16809 static Bool
apply_low(string_t * fun,object_t * ob,int num_arg,Bool b_ign_prot,Bool allowRefs)16810 apply_low ( string_t *fun, object_t *ob, int num_arg
16811           , Bool b_ign_prot, Bool allowRefs)
16812 
16813 /* The low-level implementation of function calls.
16814  *
16815  * Call function <fun> in <ob>ject with <num_arg> arguments pushed
16816  * onto the stack (<inter_sp> points to the last one). static and protected
16817  * functions can't be called from the outside unless <b_ign_prot> is true.
16818  * apply_low() takes care of calling shadows where necessary.
16819  *
16820  * If <allowRefs> is TRUE, references may be passed as extended varargs
16821  * ('(varargs mixed *)'). Currently this is used only for simul efuns.
16822  *
16823  * When apply_low() returns true, the call was successful, the arguments
16824  * one the stack have been popped and replaced with the result. But note
16825  * that <ob> might have been destructed during the call.
16826  *
16827  * If apply_low() returns false, the function was not found and the arguments
16828  * must be removed by the caller. One reason for failure can be an attempt
16829  * to call an inherited function '::foo' with this function.
16830  *
16831  * To speed up the calls, apply_low() maintains a cache of earlier calls, both
16832  * hits and misses.
16833  *
16834  * The function call will swap in the object and also unset its reset status.
16835  */
16836 
16837 {
16838     program_t *progp;
16839     struct control_stack *save_csp;
16840     p_int ix;
16841 
16842     /* This object will now be used, and is thus a target for
16843      * reset later on (when time due).
16844      */
16845     ob->flags &= ~O_RESET_STATE;
16846 
16847 #ifdef DEBUG
16848     if (num_error > 2) {
16849         fatal("apply_low with too many errors.\n");
16850         goto failure;
16851     }
16852 #endif
16853 
16854     /* If there is a chain of objects shadowing, start with the first
16855      * of these.
16856      */
16857     if (ob->flags & O_SHADOW)
16858     {
16859         object_t *shadow;
16860 
16861         while (NULL != (shadow = O_GET_SHADOW(ob)->shadowed_by)
16862             && shadow != current_object)
16863         {
16864             ob = shadow;
16865         }
16866     }
16867 
16868 retry_for_shadow:
16869 
16870     ob->time_of_ref = current_time;
16871 
16872     /* Load the object from swap */
16873     if (ob->flags & O_SWAPPED)
16874     {
16875         if (load_ob_from_swap(ob) < 0)
16876             errorf("Out of memory\n");
16877     }
16878 
16879     progp = ob->prog;
16880 
16881 #ifdef DEBUG
16882     if (ob->flags & O_DESTRUCTED)
16883         fatal("apply() on destructed object '%s' function '%s'\n"
16884              , ob->name != NULL ? get_txt(ob->name) : "<null>"
16885              , fun != NULL ? get_txt(fun) : "<null>"
16886              );
16887 #endif
16888 
16889     /* Get the function name as a shared (directly tabled) string.
16890      * Since function names are always tabled, such a string must exist
16891      * if the function exists.
16892      */
16893     if (!mstr_tabled(fun))
16894     {
16895         fun = find_tabled(fun);
16896         if (!fun)
16897             goto failure2;
16898     }
16899     /* fun is now guaranteed to be a shared string */
16900 
16901     /* Get the hashed index into the cache */
16902     ix =
16903       ( progp->id_number ^ (p_int)fun ^ ( (p_int)fun >> APPLY_CACHE_BITS ) )
16904          & (CACHE_SIZE-1);
16905 
16906     /* Check if we have an entry for this function call */
16907     if (cache[ix].id == progp->id_number
16908      && (cache[ix].name == fun || mstreq(cache[ix].name, fun))
16909        )
16910     {
16911         /* We have found a matching entry in the cache. The contents have
16912          * to match, not only the pointers, because cache entries for
16913          * functions not existant in _this_ object <ob> are stored as
16914          * separately allocated copy, not as another ref to the shared
16915          * string. Yet they shall be found here.
16916          */
16917 #ifdef APPLY_CACHE_STAT
16918         apply_cache_hit++;
16919 #endif
16920         if (cache[ix].progp
16921           /* Static functions may not be called from outside.
16922            * Protected functions not even from the inside
16923            */
16924           && (   !(cache[ix].flags & (TYPE_MOD_STATIC|TYPE_MOD_PROTECTED)) /* -> neither static nor protected */
16925               || b_ign_prot
16926               || (   !(cache[ix].flags & TYPE_MOD_PROTECTED)
16927                   && current_object == ob
16928                  ) /* --> static but not protected, and caller is owner */
16929              )
16930            )
16931         {
16932             /* the cache will tell us in wich program the function is, and
16933              * where.
16934              */
16935             fun_hdr_p funstart;
16936 
16937             // check for deprecated functions before pushing a new control stack frame.
16938             if (cache[ix].flags & TYPE_MOD_DEPRECATED)
16939                 warnf("Callother to deprecated function \'%s\' in object %s (%s).\n",
16940                       get_txt(fun), get_txt(ob->name), get_txt(ob->prog->name));
16941 
16942 #ifdef USE_NEW_INLINES
16943             push_control_stack(inter_sp, inter_pc, inter_fp, inter_context);
16944 #else
16945             push_control_stack(inter_sp, inter_pc, inter_fp);
16946 #endif /* USE_NEW_INLINES */
16947             csp->ob = current_object;
16948             csp->prev_ob = previous_ob;
16949             csp->num_local_variables = num_arg;
16950             csp->funstart = funstart = cache[ix].funstart;
16951             current_prog = cache[ix].progp;
16952             current_strings = current_prog->strings;
16953             function_index_offset = cache[ix].function_index_offset;
16954 #ifdef DEBUG
16955             if (!ob->variables && cache[ix].variable_index_offset)
16956                 fatal("%s Fatal: apply (cached) for object %p '%s' "
16957                       "w/o variables, but offset %d\n"
16958                      , time_stamp(), ob, get_txt(ob->name)
16959                      , cache[ix].variable_index_offset);
16960 #endif
16961             current_variables = ob->variables;
16962             if (current_variables)
16963                 current_variables += cache[ix].variable_index_offset;
16964             inter_sp = setup_new_frame2(funstart, inter_sp, allowRefs, MY_FALSE);
16965             previous_ob = current_object;
16966             current_object = ob;
16967             save_csp = csp;
16968             eval_instruction(FUNCTION_CODE(funstart), inter_sp);
16969 #ifdef DEBUG
16970             if (save_csp-1 != csp)
16971                 fatal("Bad csp after execution in apply_low\n");
16972 #endif
16973             /* Arguments and local variables are now removed. One
16974              * resulting value is always returned on the stack.
16975              */
16976             return MY_TRUE;
16977         }
16978 
16979         /* when we come here, the cache has told us that the function isn't
16980          * defined in the object
16981          */
16982     }
16983     else
16984     {
16985         /* we have to search the function */
16986 
16987 #ifdef APPLY_CACHE_STAT
16988         apply_cache_miss++;
16989 #endif
16990 
16991         if ( NULL != fun)
16992         {
16993             int fx;
16994 
16995             /* Yup, fun is a function _somewhere_ */
16996 
16997             eval_cost++;
16998             total_evalcost++;
16999             fx = find_function(fun, progp);
17000             if (fx >= 0)
17001             {
17002                 /* Found the function - setup the control stack and
17003                  * create a new cache entry.
17004                  */
17005 
17006                 funflag_t flags;
17007                 fun_hdr_p funstart;
17008 
17009                 // check for deprecated functions before pushing a new control stack frame.
17010                 if (progp->functions[fx] & TYPE_MOD_DEPRECATED)
17011                     warnf("Callother to deprecated function \'%s\' in object %s (%s).\n",
17012                           get_txt(fun), get_txt(ob->name), get_txt(ob->prog->name));
17013 
17014 #ifdef USE_NEW_INLINES
17015                 push_control_stack(inter_sp, inter_pc, inter_fp, inter_context);
17016 #else
17017                 push_control_stack(inter_sp, inter_pc, inter_fp);
17018 #endif /* USE_NEW_INLINES */
17019                   /* if an error occurs here, it won't leave the cache in an
17020                    * inconsistent state.
17021                    */
17022                 csp->ob = current_object;
17023                 csp->prev_ob = previous_ob;
17024                 if (cache[ix].name)
17025                     free_mstring(cache[ix].name);
17026 
17027                 cache[ix].id = progp->id_number;
17028                 cache[ix].name = ref_mstring(fun);
17029 
17030                 csp->num_local_variables = num_arg;
17031                 current_prog = progp;
17032                 flags = setup_new_frame1(fx, 0, 0);
17033 
17034                 current_strings = current_prog->strings;
17035 
17036                 cache[ix].progp = current_prog;
17037                 cache[ix].function_index_offset = function_index_offset;
17038                 cache[ix].variable_index_offset = variable_index_offset;
17039 
17040 #ifdef DEBUG
17041                 if (!ob->variables && variable_index_offset)
17042                     fatal("%s Fatal: apply for object %p '%s' w/o variables, "
17043                           "but offset %d\n"
17044                          , time_stamp(), ob, get_txt(ob->name)
17045                          , variable_index_offset);
17046 #endif
17047                 current_variables = ob->variables;
17048                 if (current_variables)
17049                     current_variables += variable_index_offset;
17050                 funstart = current_prog->program + (flags & FUNSTART_MASK);
17051 
17052                 cache[ix].funstart = funstart;
17053                 cache[ix].flags = progp->functions[fx]
17054                                   & (TYPE_MOD_STATIC|TYPE_MOD_PROTECTED|TYPE_MOD_DEPRECATED);
17055 
17056                 /* Static functions may not be called from outside,
17057                  * Protected functions not even from the inside.
17058                  */
17059                 if (0 != (cache[ix].flags & (TYPE_MOD_STATIC|TYPE_MOD_PROTECTED))
17060                   && (   (cache[ix].flags & TYPE_MOD_PROTECTED)
17061                       || current_object != ob)
17062                   && !b_ign_prot
17063                     )
17064                 {
17065                     /* Not found */
17066 
17067                     previous_ob = csp->prev_ob;
17068                     current_object = csp->ob;
17069                     pop_control_stack();
17070                     if (ob->flags & O_SHADOW && O_GET_SHADOW(ob)->shadowing)
17071                     {
17072                         /* This is an object shadowing another. The function
17073                          * was not found, but can maybe be found in the object
17074                          * we are shadowing.
17075                          */
17076                         ob = O_GET_SHADOW(ob)->shadowing;
17077                         goto retry_for_shadow;
17078                     }
17079                     else
17080                         goto failure;
17081                 }
17082                 csp->funstart = funstart;
17083                 inter_sp = setup_new_frame2(funstart, inter_sp, allowRefs, MY_FALSE);
17084                 previous_ob = current_object;
17085                 current_object = ob;
17086                 save_csp = csp;
17087                 eval_instruction(FUNCTION_CODE(funstart), inter_sp);
17088 #ifdef DEBUG
17089                 if (save_csp-1 != csp)
17090                     fatal("Bad csp after execution in apply_low\n");
17091 #endif
17092                 /* Arguments and local variables are now removed. One
17093                  * resulting value is always returned on the stack.
17094                  */
17095                 return MY_TRUE;
17096             } /* end if (fx >= 0) */
17097         } /* end if(fun) */
17098 
17099         /* We have to mark this function as non-existant in this object. */
17100 
17101         if (cache[ix].name)
17102             free_mstring(cache[ix].name);
17103 
17104         cache[ix].id = progp->id_number;
17105         cache[ix].name = ref_mstring(fun);
17106         cache[ix].progp = NULL;
17107     }
17108 
17109     /* At this point, the function was not found in the object. But
17110      * maybe this object is a shadow and we find the function in the
17111      * shadowed object.
17112      */
17113 
17114     if (ob->flags & O_SHADOW && O_GET_SHADOW(ob)->shadowing)
17115     {
17116         ob = O_GET_SHADOW(ob)->shadowing;
17117         goto retry_for_shadow;
17118     }
17119 
17120 failure:
17121     if (get_txt(fun)[0] == ':')
17122         errorf("Illegal function call\n");
17123 
17124 failure2:
17125     /* Failure. Deallocate stack. */
17126     return MY_FALSE;
17127 } /* apply_low() */
17128 
17129 /*-------------------------------------------------------------------------*/
17130 static int
int_apply(string_t * fun,object_t * ob,int num_arg,Bool b_ign_prot,Bool b_use_default)17131 int_apply (string_t *fun, object_t *ob, int num_arg
17132           , Bool b_ign_prot, Bool b_use_default
17133           )
17134 
17135 /* The wrapper around apply_low() to handle default methods.
17136  *
17137  * Call function <fun> in <ob>ject with <num_arg> arguments pushed
17138  * onto the stack (<inter_sp> points to the last one). static and protected
17139  * functions can't be called from the outside unless <b_ign_prot> is true.
17140  * int_apply() takes care of calling shadows where necessary.
17141  * If <b_use_default> is true and the function call can't be resolved,
17142  * the function will try to call the default method if one is defined.
17143  *
17144  * Results:
17145  *   APPLY_NOT_FOUND (0): The function was not found (and neither a default
17146  *       lfun, if allowed). If <b_use_default> was TRUE, the arguments
17147  *       have already been removed, otherwise the arguments must be
17148  *       removed by the caller.
17149  *       One eason for failure can be an attempt to call an inherited
17150  *       function '::foo' with this function.
17151  *
17152  *   APPLY_FOUND: The function was found, and the arguments on the stack
17153  *       have been popped and replaced with the result. But note
17154  *       that <ob> might have been destructed during the call.
17155  *
17156  *   APPLY_DEFAULT_FOUND: The function was not found, but the call to the
17157  *       default function succeeded and the arguments on the stack
17158  *       have been popped and replaced with the result. But note
17159  *       that <ob> might have been destructed during the call.
17160  *
17161  * The function call will swap in the object and also unset its reset status.
17162  */
17163 
17164 {
17165     if (apply_low(fun, ob, num_arg, b_ign_prot, MY_FALSE))
17166         return APPLY_FOUND;
17167 
17168     if (b_use_default)
17169     {
17170         /* Check if there is a hook */
17171         svalue_t * hook = driver_hook + H_DEFAULT_METHOD;
17172 
17173         if (hook->type == T_STRING || hook->type == T_CLOSURE)
17174         {
17175             /* We got a default method hook.
17176              * Now we have to rearrange the stack contents to
17177              * make space for three more values.
17178              */
17179             svalue_t result;
17180             svalue_t * argp;
17181             int num_extra = (hook->type == T_STRING) ? 2 : 3;
17182             int i, rc;
17183 
17184             result = const0;
17185 
17186             argp = inter_sp - num_arg + 1;
17187             for (i = 0; i < num_arg; i++)
17188                 inter_sp[-i+num_extra] = inter_sp[-i];
17189             inter_sp += num_extra;
17190 
17191             /* Add the three new arguments: &result, ob, fun
17192              * to the arguments on the stack.
17193              */
17194             argp[0].type = T_LVALUE;
17195             argp[0].u.lvalue = &result;
17196             if (hook->type == T_CLOSURE)
17197             {
17198                 put_ref_object(argp+1, ob, "int_apply");
17199                 put_ref_string(argp+2, fun);
17200             }
17201             else
17202                 put_ref_string(argp+1, fun);
17203 
17204             /* Call the function */
17205             if (hook->type == T_STRING)
17206             {
17207                 rc = apply_low(hook->u.str, ob, num_arg+num_extra, b_ign_prot, MY_TRUE);
17208             }
17209             else /* hook->type == T_CLOSURE */
17210             {
17211                 int_call_lambda(hook, num_arg+num_extra, MY_TRUE, MY_TRUE);
17212                 rc = 1; /* This call obviously succeeds */
17213             }
17214 
17215             /* Evaluate the result and clean up the stack */
17216             if (!rc)
17217             {
17218                 /* Can happen only for T_STRING hooks: Function not found,
17219                  * but caller expects a clean stack.
17220                  */
17221                 inter_sp = _pop_n_elems(num_arg+num_extra, inter_sp);
17222                 rc = APPLY_NOT_FOUND;
17223             }
17224             else if (inter_sp->type == T_NUMBER
17225              && inter_sp->u.number == 0)
17226             {
17227                 /* Default method found, but it denied executing the call.
17228                  */
17229                 inter_sp--;
17230                 free_svalue(&result);
17231                 rc = APPLY_NOT_FOUND;
17232             }
17233             else
17234             {
17235                 /* Default method found and executed.
17236                  * Copy the result onto the stack.
17237                  */
17238                 transfer_svalue(inter_sp, &result);
17239                 rc = APPLY_DEFAULT_FOUND;
17240             }
17241 
17242             /* rc is now the return value from int_apply(), and
17243              * the result, if any, is on the stack.
17244              */
17245 
17246             return rc;
17247         } /* if (hook is STRING or CLOSURE) */
17248 
17249         /* If we come here, there was no suitable default hook to
17250          * call - remove the arguments.
17251          */
17252         inter_sp = _pop_n_elems(num_arg, inter_sp);
17253     }
17254     return APPLY_NOT_FOUND;
17255 } /* int_apply() */
17256 
17257 /*-------------------------------------------------------------------------*/
17258 void
push_apply_value(void)17259 push_apply_value (void)
17260 
17261 /* Push the current <apply_return_value> onto the stack, <apply_return_value>
17262  * itself free afterwards.
17263  */
17264 
17265 {
17266     *++inter_sp = apply_return_value;
17267     apply_return_value.type = T_NUMBER;
17268 }
17269 
17270 /*-------------------------------------------------------------------------*/
17271 void
pop_apply_value(void)17272 pop_apply_value (void)
17273 
17274 /* Pop the current value on the stack into <apply_return_value>, after
17275  * freeing the latter of course.
17276  */
17277 
17278 {
17279     free_svalue(&apply_return_value);
17280     apply_return_value = *inter_sp--;
17281 }
17282 
17283 /*-------------------------------------------------------------------------*/
17284 svalue_t *
sapply_int(string_t * fun,object_t * ob,int num_arg,Bool b_find_static,Bool b_use_default)17285 sapply_int (string_t *fun, object_t *ob, int num_arg
17286            , Bool b_find_static, Bool b_use_default)
17287 
17288 /* Call function <fun> in <ob>ject with <num_arg> arguments pushed
17289  * onto the stack (<inter_sp> points to the last one). static and protected
17290  * functions can't be called from the outside unless <b_find_static> is true.
17291  * sapply() takes care of calling shadows where necessary.
17292  * If <b_use_default> is true, an unresolved apply may be redirected to
17293  * a default lfun.
17294  *
17295  * sapply() returns a pointer to the function result when the call was
17296  * successfull, or NULL on failure. The arguments are popped in any case.
17297  * The result pointer, if returned, points to a static area which will be
17298  * overwritten with the next sapply().
17299  *
17300  * The function call will swap in the object and also unset its reset status.
17301  *
17302  * interpret.h defines the macro sapply(fun,ob,num_arg) for the most
17303  * common call with b_find_static passed as false.
17304  */
17305 
17306 {
17307 #ifdef DEBUG
17308     svalue_t *expected_sp;
17309 #endif
17310 
17311     /* Handle tracing */
17312     if (TRACEP(TRACE_APPLY) && TRACE_IS_INTERACTIVE())
17313     {
17314         if (!++traceing_recursion)
17315         {
17316             do_trace("Apply", "", "\n");
17317         }
17318         traceing_recursion--;
17319     }
17320 
17321 #ifdef DEBUG
17322     expected_sp = inter_sp - num_arg;
17323 #endif
17324 
17325     /* Do the call */
17326     if (!int_apply(fun, ob, num_arg, b_find_static, b_use_default))
17327     {
17328         if (!b_use_default) /* int_apply() did not clean up the stack */
17329             inter_sp = _pop_n_elems(num_arg, inter_sp);
17330         return NULL;
17331     }
17332     transfer_svalue(&apply_return_value, inter_sp);
17333     inter_sp--;
17334 
17335 #ifdef DEBUG
17336     if (expected_sp != inter_sp)
17337         fatal("Corrupt stack pointer: expected %p, got %p.\n"
17338              , expected_sp, inter_sp);
17339 #endif
17340 
17341     return &apply_return_value;
17342 } /* sapply_int() */
17343 
17344 /*-------------------------------------------------------------------------*/
17345 svalue_t *
apply(string_t * fun,object_t * ob,int num_arg)17346 apply (string_t *fun, object_t *ob, int num_arg)
17347 
17348 /* Call function <fun> in <ob>ject with <num_arg> arguments pushed
17349  * onto the stack (<inter_sp> points to the last one). static and protected
17350  * functions can't be called from the outside.
17351  * apply() takes care of calling shadows where necessary.
17352  *
17353  * apply() returns a pointer to the function result when the call was
17354  * successfull, or NULL on failure. The arguments are popped in any case.
17355  * The result pointer, if returned, points to a static area which will be
17356  * overwritten with the next apply().
17357  *
17358  * The function call will swap in the object and also unset its reset status.
17359  *
17360  * The big difference between apply() and sapply() is that apply() sets
17361  * the tracedepth to 0 before calling the function.
17362  */
17363 
17364 {
17365     tracedepth = 0;
17366     return sapply_int(fun, ob, num_arg, MY_FALSE, MY_TRUE);
17367 } /* apply() */
17368 
17369 /*-------------------------------------------------------------------------*/
17370 void
secure_apply_error(svalue_t * save_sp,struct control_stack * save_csp,Bool external)17371 secure_apply_error ( svalue_t *save_sp, struct control_stack *save_csp
17372                    , Bool external)
17373 
17374 /* Recover from an error during a secure apply. <save_sp> and <save_csp>
17375  * are the saved evaluator stack and control stack pointers, saving the
17376  * state from when secure_apply() was entered.
17377  *
17378  * The function pops all the arguments for the call from the stack, and
17379  * then calls runtime_error() in the master object with the necessary
17380  * information, unless it is a triple fault - in that case only a
17381  * debug_message() is generated.
17382  *
17383  * If <external> is TRUE, the eval costs and limits will be reset
17384  * before runtime_error() is called. This is used for top-level master
17385  * applies which should behave like normal function calls in the error
17386  * handling.
17387  */
17388 
17389 {
17390     if (csp != save_csp)
17391     {
17392         /* Could be error before push.
17393          * We have to unroll the control stack in case it references
17394          * lambda closures.
17395          */
17396 
17397         while (csp > save_csp+1)
17398             pop_control_stack();
17399 
17400         previous_ob = csp->prev_ob;
17401         current_object = csp->ob;
17402         pop_control_stack();
17403     }
17404 
17405     if (inter_sp > save_sp)
17406         inter_sp = _pop_n_elems (inter_sp - save_sp, inter_sp);
17407         /* Note: On a stack overflow, the stack_overflow() routine
17408          * already removed the values from the stack
17409          */
17410 
17411     if (num_error == 3)
17412     {
17413         if (!out_of_memory)
17414         {
17415             debug_message("%s Master failure: %s", time_stamp()
17416                          , get_txt(current_error));
17417             free_mstring(current_error);
17418             free_mstring(current_error_file);
17419             free_mstring(current_error_object_name);
17420             if (current_error_trace)
17421             {
17422                 free_array(current_error_trace);
17423                 current_error_trace = NULL;
17424             }
17425             if (uncaught_error_trace)
17426             {
17427                 free_array(uncaught_error_trace);
17428                 uncaught_error_trace = NULL;
17429             }
17430         }
17431     }
17432     else if (!out_of_memory)
17433     {
17434         int a;
17435         object_t *save_cmd;
17436 
17437         push_string(inter_sp, current_error);
17438         a = 1;
17439         if (current_error_file)
17440         {
17441             push_string(inter_sp, current_error_file);
17442             push_string(inter_sp, current_error_object_name);
17443             push_number(inter_sp, current_error_line_number);
17444             a += 3;
17445         }
17446 
17447         if (current_heart_beat)
17448         {
17449             /* Heartbeat error: turn off the heartbeat in the object
17450              * and also pass it to RUNTIME_ERROR.
17451              */
17452 
17453             object_t *culprit;
17454 
17455             culprit = current_heart_beat;
17456             current_heart_beat = NULL;
17457             set_heart_beat(culprit, MY_FALSE);
17458             debug_message("%s Heart beat in %s turned off.\n"
17459                          , time_stamp(), get_txt(culprit->name));
17460             push_ref_valid_object(inter_sp, culprit, "heartbeat error");
17461             a++;
17462         }
17463         else
17464         {
17465             if (!current_error_file)
17466             {
17467                 /* Push dummy values to keep the argument order correct */
17468                 push_number(inter_sp, 0);
17469                 push_number(inter_sp, 0);
17470                 push_number(inter_sp, 0);
17471                 a += 3;
17472             }
17473 
17474             /* Normal error: push -1 instead of a culprit. */
17475             push_number(inter_sp, -1);
17476             a++;
17477         }
17478 
17479         if (external)
17480         {
17481             mark_end_evaluation();
17482             CLEAR_EVAL_COST;
17483             RESET_LIMITS;
17484         }
17485 
17486         save_cmd = command_giver;
17487         apply_master(STR_RUNTIME, a);
17488         command_giver = save_cmd;
17489         /* STR_RUNTIME freed all the current_ variables, except
17490          * current_error_trace.
17491          */
17492     }
17493     num_error--;
17494 
17495 } /* secure_apply_error() */
17496 
17497 /*-------------------------------------------------------------------------*/
17498 svalue_t *
secure_apply_ob(string_t * fun,object_t * ob,int num_arg,Bool external)17499 secure_apply_ob (string_t *fun, object_t *ob, int num_arg, Bool external)
17500 
17501 /* Aliases:
17502  *   secure_apply(fun, ob, num_arg) == secure_apply_ob(fun, ob, num_arg, FALSE)
17503  *   secure_callback(fun, ob, num_arg) == secure_apply_ob(fun, ob, num_arg, TRUE)
17504  *
17505  * Call function <fun> in <ob>ject with <num_arg> arguments pushed
17506  * onto the stack (<inter_sp> points to the last one). static and protected
17507  * functions can't be called from the outside.
17508  * secure_apply_ob() takes care of calling shadows where necessary.
17509  *
17510  * If <external> is TRUE, it means that this call is due to some external
17511  * event (like an ERQ message) instead of being caused by a running program.
17512  * The effect of this flag is that the error handling is like for a normal
17513  * function call (clearing the eval costs before calling runtime_error()).
17514  *
17515  * secure_apply_ob() returns a pointer to the function result when the call
17516  * was successfull, or NULL on failure. The arguments are popped in any case.
17517  * The result pointer, if returned, points to a static area which will be
17518  * overwritten with the next secure_apply_ob().
17519  *
17520  * The function call will swap in the object and also unset its reset status.
17521  *
17522  * Errors during the execution are caught (this is the big difference
17523  * to sapply()/apply()) and cause secure_apply_ob() to return NULL.
17524  */
17525 
17526 {
17527     struct error_recovery_info error_recovery_info;
17528     svalue_t *save_sp;
17529     struct control_stack *save_csp;
17530     svalue_t *result;
17531 
17532     if (ob->flags & O_DESTRUCTED)
17533         return NULL;
17534 
17535     error_recovery_info.rt.last = rt_context;
17536     error_recovery_info.rt.type = ERROR_RECOVERY_APPLY;
17537     rt_context = (rt_context_t *)&error_recovery_info.rt;
17538     save_sp = inter_sp;
17539     save_csp = csp;
17540     if (setjmp(error_recovery_info.con.text))
17541     {
17542         secure_apply_error(save_sp - num_arg, save_csp, external);
17543         result = NULL;
17544     }
17545     else
17546     {
17547         if (external)
17548             mark_start_evaluation();
17549         result = sapply(fun, ob, num_arg);
17550         if (external)
17551             mark_end_evaluation();
17552     }
17553     rt_context = error_recovery_info.rt.last;
17554     return result;
17555 } /* secure_apply_ob() */
17556 
17557 /*-------------------------------------------------------------------------*/
17558 svalue_t *
apply_master_ob(string_t * fun,int num_arg,Bool external)17559 apply_master_ob (string_t *fun, int num_arg, Bool external)
17560 
17561 /* Aliases:
17562  *   apply_master(fun, num_arg) == apply_master_ob(fun, num_arg, FALSE)
17563  *   callback_master(fun, num_arg) == apply_master_ob(fun, num_arg, TRUE)
17564  *
17565  * Call function <fun> in the master object with <num_arg> arguments pushed
17566  * onto the stack (<inter_sp> points to the last one). static and protected
17567  * functions can be called from the outside. The function takes care
17568  * of calling shadows where necessary.
17569  *
17570  * If <external> is TRUE, it means that this call is due to some external
17571  * event (like an ERQ message) instead of being caused by a running program.
17572  * The effect of this flag is that the error handling is like for a normal
17573  * function call (clearing the eval costs before calling runtime_error()).
17574  *
17575  * apply_master_object() returns a pointer to the function result when the
17576  * call was successfull, or NULL on failure. The arguments are popped in
17577  * any case.
17578  * The result pointer, if returned, points to a static area which will be
17579  * overwritten with the next apply_master_object().
17580  *
17581  * The function makes sure that there is a master object to be called. If
17582  * necessary, a new one is compiled or, failing that, an old one is
17583  * reactivated.
17584  *
17585  * Errors during the execution are caught and case the function to
17586  * return NULL.
17587  *
17588  * The function operates on an execution tick reserve of MASTER_RESERVED_COST
17589  * which is used then the normal evaluation cost is already too high.
17590  */
17591 
17592 {
17593     static int eval_cost_reserve = MASTER_RESERVED_COST;
17594       /* Available eval_cost reserver. If needed, the reserve is halved
17595        * for the duration of the apply to establish a protection against
17596        * an endless recursion of master calls.
17597        */
17598 
17599     volatile Bool reserve_used = MY_FALSE;
17600 
17601     struct error_recovery_info error_recovery_info;
17602     svalue_t *save_sp;
17603     struct control_stack *save_csp;
17604     svalue_t *result;
17605 
17606     /* Get the master object. */
17607     assert_master_ob_loaded();
17608 
17609     /* Tap into the eval_cost reserve if the end is near */
17610     if (   (max_eval_cost && eval_cost > max_eval_cost - MASTER_RESERVED_COST)
17611         && eval_cost_reserve > 1)
17612     {
17613         eval_cost -= eval_cost_reserve;
17614         assigned_eval_cost -= eval_cost_reserve;
17615         eval_cost_reserve >>= 1;
17616         reserve_used = MY_TRUE;
17617     }
17618 
17619     /* Setup the the error recovery and call the function */
17620     error_recovery_info.rt.last = rt_context;
17621     error_recovery_info.rt.type = ERROR_RECOVERY_APPLY;
17622     rt_context = (rt_context_t *)&error_recovery_info.rt;
17623     save_sp = inter_sp;
17624     save_csp = csp;
17625     if (setjmp(error_recovery_info.con.text))
17626     {
17627         secure_apply_error(save_sp - num_arg, save_csp, external);
17628         printf("%s Error in master_ob->%s()\n", time_stamp(), get_txt(fun));
17629         debug_message("%s Error in master_ob->%s()\n", time_stamp(), get_txt(fun));
17630         result = NULL;
17631     }
17632     else
17633     {
17634         if (external)
17635             mark_start_evaluation();
17636         result = sapply_int(fun, master_ob, num_arg, MY_TRUE, MY_FALSE);
17637         if (external)
17638             mark_end_evaluation();
17639     }
17640 
17641     /* Free the reserve if we used it */
17642     if (reserve_used)
17643     {
17644         eval_cost_reserve <<= 1;
17645         assigned_eval_cost = eval_cost += eval_cost_reserve;
17646     }
17647     rt_context = error_recovery_info.rt.last;
17648 
17649     return result;
17650 } /* apply_master_ob() */
17651 
17652 /*-------------------------------------------------------------------------*/
17653 void
assert_master_ob_loaded(void)17654 assert_master_ob_loaded (void)
17655 
17656 /* Make sure that there is a master object <master_ob>.
17657  * If necessary, a new master is compiled, or, failing that, an old
17658  * destructed one is reactivated. If everything fails, the driver exits.
17659  *
17660  * Note that the function may be called recursively:
17661  *  - While calling a master function from yyparse() (e.g. log_error()),
17662  *    the master self-destructs and then causes an error.
17663  *  - Another possibility is that some driver hook invokes some
17664  *    function that uses apply_master_ob().
17665  *  - The master object might have been reloaded without noticing that
17666  *    it is the master. This could happen when there already was a call to
17667  *    assert_master_ob_loaded(), clearing master_ob, and the master
17668  *    inherits itself. Partial working self-inheritance is possible if
17669  *    the H_INCLUDE_DIRS hook does something strange.
17670  */
17671 
17672 {
17673     static Bool inside = MY_FALSE;
17674       /* Flag to notice recursive calls */
17675 
17676     static object_t *destructed_master_ob = NULL;
17677       /* Old, destructed master object */
17678 
17679     int i;
17680 
17681     if (!master_ob || master_ob->flags & O_DESTRUCTED)
17682     {
17683         /* The master object has been destructed. Free our reference,
17684          * and load a new one.
17685          */
17686         if (inside || !master_ob)
17687         {
17688             object_t *ob;
17689             object_t *prev;
17690             Bool newly_removed = MY_FALSE;
17691               /* TRUE if the old master was on the list of newly
17692                * destructed objects. That is important to know
17693                * because then it still has all its variables.
17694                */
17695 
17696             /* A recursive call while loading the master, or there
17697              * was no master to begin with.
17698              * If there is a destructed master, reactivate that
17699              * one, else stop the driver.
17700              */
17701 
17702             if (!destructed_master_ob)
17703             {
17704                 add_message("Failed to load master object '%s'!\n"
17705                            , master_name);
17706                 // fatal() may call us again. But fatal() and this function
17707                 // are secured against recursion so it should be safe to call
17708                 // it from here (otherwise we would not get a core dump...).
17709                 fatal("Failed to load master object '%s'!\n",
17710                       master_name);
17711             }
17712 
17713             /* If we come here, we had a destructed master and failed
17714              * to load a new one. Now try to reactivate the
17715              * old one again.
17716              *
17717              * We don't have to reactivate any destructed inherits, though:
17718              * as long as the master references their programs, that's all
17719              * we need.
17720              */
17721 
17722             /* First, make sure that there is no half-done object
17723              * using the masters name.
17724              */
17725             if ( NULL != (ob = find_object(master_name_str)) )
17726             {
17727                 destruct(ob);
17728             }
17729 
17730             /* Get the destructed master */
17731             ob = destructed_master_ob;
17732             destructed_master_ob = NULL;
17733 
17734             /* Remove the destructed master from the list
17735              * of newly destructed objects or destructed objects.
17736              */
17737             if (newly_destructed_objs != NULL)
17738             {
17739                 if (ob == newly_destructed_objs)
17740                 {
17741                     newly_destructed_objs = ob->next_all;
17742                     newly_removed = MY_TRUE;
17743                     num_newly_destructed--;
17744 #ifdef CHECK_OBJECT_REF
17745                     {
17746                         object_shadow_t * sh = newly_destructed_obj_shadows;
17747                         newly_destructed_obj_shadows = sh->next;
17748                         xfree(sh);
17749                     }
17750 #endif /* CHECK_OBJECT_REF */
17751                 }
17752                 else
17753                 {
17754 #ifdef CHECK_OBJECT_REF
17755                     object_shadow_t *sprev;
17756 #endif /* CHECK_OBJECT_REF */
17757                     for ( prev = newly_destructed_objs
17758 #ifdef CHECK_OBJECT_REF
17759                         , sprev = newly_destructed_obj_shadows
17760 #endif /* CHECK_OBJECT_REF */
17761                         ; prev && prev->next_all != ob
17762                         ; prev = prev->next_all
17763 #ifdef CHECK_OBJECT_REF
17764                         , sprev = sprev->next
17765 #endif /* CHECK_OBJECT_REF */
17766                         ) NOOP;
17767                     if (prev)
17768                     {
17769                         prev->next_all = ob->next_all;
17770                         newly_removed = MY_TRUE;
17771                         num_newly_destructed--;
17772 #ifdef CHECK_OBJECT_REF
17773                         {
17774                             object_shadow_t *sh = sprev->next;
17775                             sprev->next = sh->next;
17776                             xfree(sh);
17777                         }
17778 #endif /* CHECK_OBJECT_REF */
17779                     }
17780                 }
17781             }
17782             if (!newly_removed && destructed_objs != NULL)
17783             {
17784                 if (ob == destructed_objs)
17785                 {
17786                     destructed_objs = ob->next_all;
17787                     if (destructed_objs)
17788                         destructed_objs->prev_all = NULL;
17789                     num_destructed--;
17790 #ifdef CHECK_OBJECT_REF
17791                     {
17792                         object_shadow_t * sh = destructed_obj_shadows;
17793                         destructed_obj_shadows = sh->next;
17794                         xfree(sh);
17795                     }
17796 #endif /* CHECK_OBJECT_REF */
17797                 }
17798                 else
17799                 {
17800 #ifdef CHECK_OBJECT_REF
17801                     object_shadow_t *sprev;
17802 #endif /* CHECK_OBJECT_REF */
17803                     for ( prev = destructed_objs
17804 #ifdef CHECK_OBJECT_REF
17805                         , sprev = destructed_obj_shadows
17806 #endif /* CHECK_OBJECT_REF */
17807                         ; prev && prev->next_all != ob
17808                         ; prev = prev->next_all
17809 #ifdef CHECK_OBJECT_REF
17810                         , sprev = sprev->next
17811 #endif /* CHECK_OBJECT_REF */
17812                         ) NOOP;
17813                     if (prev)
17814                     {
17815                         prev->next_all = ob->next_all;
17816                         if (prev->next_all)
17817                             prev->next_all->prev_all = prev;
17818                         num_destructed--;
17819 #ifdef CHECK_OBJECT_REF
17820                         {
17821                             object_shadow_t *sh = sprev->next;
17822                             sprev->next = sh->next;
17823                             xfree(sh);
17824                         }
17825 #endif /* CHECK_OBJECT_REF */
17826                     }
17827                 }
17828             }
17829             ob->flags &= ~O_DESTRUCTED;
17830 
17831             /* Restore the old masters variable space.
17832              * Remember: as long as the objects are in the 'newly destructed'
17833              * list, they still have all variables.
17834              */
17835             if (!newly_removed && ob->prog->num_variables)
17836             {
17837                 int save_privilege = malloc_privilege;
17838                 int j;
17839                 svalue_t *v;
17840 
17841                 malloc_privilege = MALLOC_SYSTEM;
17842                 ob->variables = v = (svalue_t *)
17843                     xalloc(sizeof *v * ob->prog->num_variables);
17844                 malloc_privilege = save_privilege;
17845                 for (j = ob->prog->num_variables; --j >= 0; )
17846                     *v++ = const0;
17847             }
17848 
17849             /* Reenter the object into the various lists */
17850             enter_object_hash(ob);
17851             ob->next_all = obj_list;
17852             ob->prev_all = NULL;
17853             if (obj_list)
17854                 obj_list->prev_all = ob;
17855             obj_list = ob;
17856             if (!obj_list_end)
17857                 obj_list_end = ob;
17858             num_listed_objs++;
17859             ob->super = NULL;
17860             ob->contains = NULL;
17861             ob->next_inv = NULL;
17862 
17863             /* Reactivate the old master */
17864             master_ob = ref_object(ob, "assert_master_ob_loaded");
17865             if (current_object == &dummy_current_object_for_loads)
17866                 current_object = master_ob;
17867             push_number(inter_sp, newly_removed);
17868             sapply_int(STR_REACTIVATE, ob, 1, MY_TRUE, MY_FALSE);
17869             push_number(inter_sp, 2 - (newly_removed ? 1 : 0));
17870             sapply_int(STR_INAUGURATE, ob, 1, MY_TRUE, MY_FALSE);
17871             fprintf(stderr, "%s Old master reactivated.\n", time_stamp());
17872             inside = MY_FALSE;
17873             return;
17874 
17875         } /* if (inside || !master_obj) */
17876 
17877         /* A normal call to assert_master_ob_loaded: just load a new one */
17878 
17879         fprintf(stderr, "%s assert_master_ob_loaded: Reloading master '%s'\n"
17880                , time_stamp(), master_name);
17881         destructed_master_ob = master_ob;
17882 
17883         /* Clear the pointer, in case the load failed.
17884          */
17885         master_ob = NULL;
17886         inside = MY_TRUE;
17887         if (!current_object)
17888         {
17889             current_object = &dummy_current_object_for_loads;
17890         }
17891 
17892         /* Free the driver hooks.
17893          */
17894         for (i = NUM_DRIVER_HOOKS; i--;)
17895         {
17896             assign_svalue(driver_hook+i, &const0);
17897         }
17898 
17899         init_telopts();
17900 
17901         master_ob = get_object(master_name_str);
17902         if (current_object == &dummy_current_object_for_loads)
17903         {
17904             /* This might be due to the above assignment, or to setting
17905              * it in the backend.
17906              */
17907             current_object = master_ob;
17908         }
17909 
17910         initialize_master_uid();
17911         push_number(inter_sp, 3);
17912         apply_master(STR_INAUGURATE, 1);
17913         assert_master_ob_loaded();
17914           /* ...in case inaugurate_master() destructed this object again */
17915         inside = MY_FALSE;
17916         ref_object(master_ob, "assert_master_ob_loaded");
17917 
17918         if (destructed_master_ob)
17919             free_object(destructed_master_ob, "assert_master_ob_loaded");
17920 
17921         fprintf(stderr, "%s Reloading done.\n", time_stamp());
17922     }
17923 
17924     /* Master exists. Nothing to see here, move along... */
17925 
17926 } /* assert_master_ob_loaded() */
17927 
17928 /*-------------------------------------------------------------------------*/
17929 void
int_call_lambda(svalue_t * lsvp,int num_arg,Bool allowRefs,Bool external)17930 int_call_lambda (svalue_t *lsvp, int num_arg, Bool allowRefs, Bool external)
17931 
17932 /* Call the closure <lsvp> with <num_arg> arguments on the stack. On
17933  * success, the arguments are replaced with the result, else an errorf()
17934  *
17935  * If <allowRefs> is TRUE, references may be passed as extended varargs
17936  * ('(varargs mixed *)'). Currently this is used only for simul efuns.
17937  * is generated.
17938  *
17939  * If <external> is TRUE, the eval_instruction is called to execute the
17940  * closure. Otherwise inter_pc is just set and int_call_lambda returns
17941  * (this is only valid for non-alien lfun or lambda closures).
17942  */
17943 
17944 {
17945 #  define CLEAN_CSP \
17946         previous_ob = csp->prev_ob; \
17947         current_object = csp->ob; \
17948         pop_control_stack();
17949   /* Macro to undo all the call preparations in case the closure
17950    * can't be called after all.
17951    */
17952 
17953     svalue_t *sp;
17954     lambda_t *l = lsvp->u.lambda;
17955 
17956     sp = inter_sp;
17957 
17958     /* Basic setup for the new control frame.
17959      * If the closure can't be called, all this has to be undone
17960      * using the macro CLEAN_CSP.
17961      */
17962 #ifdef USE_NEW_INLINES
17963     push_control_stack(sp, inter_pc, inter_fp, inter_context);
17964 #else
17965     push_control_stack(sp, inter_pc, inter_fp);
17966 #endif /* USE_NEW_INLINES */
17967     csp->ob = current_object;
17968     csp->prev_ob = previous_ob;
17969     csp->num_local_variables = num_arg;
17970     previous_ob = current_object;
17971 
17972     switch(lsvp->x.closure_type)
17973     {
17974 
17975     case CLOSURE_LFUN:  /* --- lfun closure --- */
17976       {
17977         Bool      extra_frame;
17978 
17979         /* Can't call from a destructed object */
17980         if (l->ob->flags & O_DESTRUCTED)
17981         {
17982             /* inter_sp == sp */
17983             CLEAN_CSP
17984             push_number(inter_sp, 0);
17985             return;
17986         }
17987 
17988         /* Reference the bound and the originating object */
17989         l->ob->time_of_ref = current_time;
17990         l->function.lfun.ob->time_of_ref = current_time;
17991         l->function.lfun.ob->flags &= ~O_RESET_STATE;
17992 
17993         current_object = l->ob;
17994 
17995         /* Can't call a function in a destructed object */
17996         if (l->function.lfun.ob->flags & O_DESTRUCTED)
17997         {
17998             /* inter_sp == sp */
17999             CLEAN_CSP
18000             push_number(inter_sp, 0);
18001             return;
18002         }
18003 
18004         /* Make the objects resident */
18005         if ( (   current_object->flags & O_SWAPPED
18006               && load_ob_from_swap(current_object) < 0)
18007          ||  (   l->function.lfun.ob->flags & O_SWAPPED
18008               && load_ob_from_swap(l->function.lfun.ob) < 0)
18009            )
18010         {
18011             /* inter_sp == sp */
18012             CLEAN_CSP
18013             errorf("Out of memory\n");
18014             /* NOTREACHED */
18015             return;
18016         }
18017 
18018 #ifdef DEBUG
18019         if (l->function.lfun.index >= l->function.lfun.ob->prog->num_functions)
18020             fatal("Calling non-existing lfun closure #%hu in program '%s' "
18021                   "with %hu functions.\n"
18022                  , l->function.lfun.index
18023                  , get_txt(l->function.lfun.ob->prog->name)
18024                  , l->function.lfun.ob->prog->num_functions
18025                 );
18026 #endif
18027 
18028         /* If the object creating the closure wasn't the one in which
18029          * it will be executed, we need to record the fact in a second
18030          * 'dummy' control frame. If we didn't, major security holes
18031          * open up.
18032          */
18033 
18034         if (l->ob != l->function.lfun.ob)
18035         {
18036             extra_frame = MY_TRUE;
18037             csp->extern_call = MY_TRUE;
18038             csp->funstart = NULL;
18039 #ifdef USE_NEW_INLINES
18040             push_control_stack(sp, 0, inter_fp, inter_context);
18041 #else
18042             push_control_stack(sp, 0, inter_fp);
18043 #endif /* USE_NEW_INLINES */
18044             csp->ob = current_object;
18045             csp->prev_ob = previous_ob;
18046             csp->num_local_variables = num_arg;
18047             previous_ob = current_object;
18048             external = MY_TRUE;
18049         }
18050         else
18051             extra_frame = MY_FALSE;
18052 
18053         /* Finish the setup of the control frame.
18054          * This is a real inter-object call.
18055          */
18056         csp->extern_call = external;
18057         current_object = l->function.lfun.ob;
18058         current_prog = current_object->prog;
18059         /* inter_sp == sp */
18060         setup_new_frame(l->function.lfun.index, l->function.lfun.inhProg);
18061 #ifdef USE_NEW_INLINES
18062         if (l->function.lfun.context_size > 0)
18063             inter_context = l->context;
18064 #endif /* USE_NEW_INLINES */
18065         if (external)
18066             eval_instruction(FUNCTION_CODE(csp->funstart), inter_sp);
18067         else
18068             inter_pc = FUNCTION_CODE(csp->funstart);
18069 
18070         /* If l->ob selfdestructs during the call, l might have been
18071          * deallocated at this point!
18072          */
18073 
18074         /* If necessary, remove the second control frame */
18075         if (extra_frame)
18076         {
18077             current_object = csp->ob;
18078             previous_ob = csp->prev_ob;
18079             pop_control_stack();
18080         }
18081 
18082         /* The result is on the stack (inter_sp) */
18083         return;
18084       }
18085 
18086     case CLOSURE_IDENTIFIER:  /* --- variable closure --- */
18087       {
18088         short i; /* the signed variant of lambda_t->function.index */
18089 
18090         CLEAN_CSP  /* no call will be done */
18091 
18092         /* Ignore any arguments passed to a variable closure. */
18093         pop_n_elems(num_arg);
18094 
18095         /* Don't use variables in a destructed object */
18096         if (l->ob->flags & O_DESTRUCTED)
18097         {
18098             push_number(inter_sp, 0);
18099             return;
18100         }
18101 
18102         /* Make the object resident */
18103         if (   (l->ob->flags & O_SWAPPED)
18104              && load_ob_from_swap(l->ob) < 0
18105            )
18106         {
18107             errorf("Out of memory.\n");
18108             /* NOTREACHED */
18109             return;
18110         }
18111 
18112         /* Do we have the variable? */
18113         if ( (i = (short)l->function.var_index) < 0)
18114         {
18115             errorf("Variable not inherited\n");
18116             /* NOTREACHED */
18117             return;
18118         }
18119 
18120         l->ob->time_of_ref = current_time;
18121 #ifdef DEBUG
18122         if (!l->ob->variables)
18123             fatal("%s Fatal: call_lambda on variable for object %p '%s' "
18124                   "w/o variables, index %d\n"
18125                  , time_stamp(), l->ob, get_txt(l->ob->name), i);
18126 #endif
18127         assign_svalue_no_free(++sp, &l->ob->variables[i]);
18128         inter_sp = sp;
18129         return;
18130       }
18131 
18132     case CLOSURE_PRELIMINARY:
18133         /* no valid current_object: fall out of the switch
18134          * and let the error handling clean up the control
18135          * stack.
18136          */
18137         break;
18138 
18139     case CLOSURE_BOUND_LAMBDA:  /* --- bound lambda closure --- */
18140       {
18141         lambda_t *l2;
18142 
18143         /* Deref the closure and then treat the resulting unbound
18144          * lambda like a normal lambda
18145          */
18146         l2 = l->function.lambda;
18147         l2->ob = l->ob;
18148         l = l2;
18149       }
18150       /* FALLTHROUGH */
18151 
18152     case CLOSURE_UNBOUND_LAMBDA:
18153       if (lsvp->x.closure_type == CLOSURE_UNBOUND_LAMBDA)
18154       {
18155           if (external)
18156               break;
18157 
18158           /* Internal call of an unbound closure.
18159            * Bind it on the fly.
18160            */
18161           l->ob = current_object;
18162       }
18163       /* FALLTHROUGH */
18164 
18165     case CLOSURE_LAMBDA:
18166       {
18167         fun_hdr_p funstart;
18168 
18169         /* Can't call from a destructed object */
18170         if (l->ob->flags & O_DESTRUCTED)
18171         {
18172             /* inter_sp == sp */
18173             CLEAN_CSP
18174             push_number(inter_sp, 0);
18175             return;
18176         }
18177 
18178         current_object = l->ob;
18179 
18180         /* Make the object resident */
18181         if (current_object->flags & O_SWAPPED
18182          && load_ob_from_swap(current_object) < 0)
18183         {
18184             /* inter_sp == sp */
18185             CLEAN_CSP
18186             errorf("Out of memory\n");
18187             /* NOTREACHED */
18188             return;
18189         }
18190 
18191         /* Reference the object */
18192         current_object->time_of_ref = current_time;
18193         current_object->flags &= ~O_RESET_STATE;
18194 
18195         /* Finish the setup */
18196 
18197         current_prog = current_object->prog;
18198         current_lambda = *lsvp; addref_closure(lsvp, "call_lambda()");
18199         variable_index_offset = 0;
18200         function_index_offset = 0;
18201         funstart = l->function.code + 1;
18202         csp->funstart = funstart;
18203         csp->extern_call = external;
18204         sp = setup_new_frame2(funstart, sp, allowRefs, MY_TRUE);
18205         current_variables = current_object->variables;
18206         current_strings = current_prog->strings;
18207         if (external)
18208             eval_instruction(FUNCTION_CODE(funstart), sp);
18209         else
18210         {
18211             inter_pc = FUNCTION_CODE(funstart);
18212             inter_sp = sp;
18213         }
18214         /* The result is on the stack (inter_sp). */
18215         return;
18216       }
18217 
18218     default: /* --- efun-, simul efun-, operator closure */
18219       {
18220         int i;  /* the closure type */
18221 
18222         current_object = lsvp->u.ob;
18223         /* Can't call from a destructed object */
18224         if (current_object->flags & O_DESTRUCTED)
18225         {
18226             /* inter_sp == sp */
18227             CLEAN_CSP
18228             push_number(inter_sp, 0);
18229             return;
18230         }
18231 
18232         /* Make the object resident */
18233         if (current_object->flags & O_SWAPPED
18234          && load_ob_from_swap(current_object) < 0)
18235         {
18236             /* inter_sp == sp */
18237             CLEAN_CSP
18238             errorf("Out of memory\n");
18239             /* NOTREACHED */
18240             return;
18241         }
18242 
18243         /* Reference the object */
18244         current_object->time_of_ref = current_time;
18245 
18246         i = lsvp->x.closure_type;
18247         if (i < CLOSURE_SIMUL_EFUN)
18248         {
18249             /* It's an operator or efun */
18250 
18251             if (i == CLOSURE_EFUN + F_UNDEF)
18252             {
18253                 /* The closure was discovered to be bound to a destructed
18254                  * object and thus disabled.
18255                  * This situation should no longer happen - in all situations
18256                  * the closure should be zeroed out.
18257                  */
18258                 CLEAN_CSP
18259                 push_number(inter_sp, 0);
18260                 return;
18261             }
18262 
18263             i -= CLOSURE_EFUN;
18264               /* Efuns have now a positive value, operators a negative one.
18265                */
18266 
18267             if (i >= 0
18268              || instrs[i -= CLOSURE_OPERATOR-CLOSURE_EFUN].min_arg)
18269             {
18270                 /* To call an operator or efun, we have to construct
18271                  * a small piece of program with this instruction.
18272                  */
18273                 bytecode_t code[9];    /* the code fragment */
18274                 bytecode_p p;          /* the code pointer */
18275 
18276                 int min, max, def;
18277 
18278                 min = instrs[i].min_arg;
18279                 max = instrs[i].max_arg;
18280                 p = code;
18281 
18282                 /* Fix up the number of arguments passed */
18283                 if (num_arg < min)
18284                 {
18285                     /* Add some arguments */
18286 
18287                     int f;
18288 
18289                     if (num_arg == min-1
18290                      && 0 != (def = instrs[i].Default) && def != -1)
18291                     {
18292                         /* We lack one argument for which a default
18293                          * is provided.
18294                          */
18295                         if (instrs[def].prefix)
18296                             *p++ = instrs[def].prefix;
18297                         *p++ = instrs[def].opcode;
18298                         max--;
18299                         min--;
18300                     }
18301                     else
18302                     {
18303                         /* Maybe there is a fitting replacement efun */
18304                         f = proxy_efun(i, num_arg);
18305                         if (f >= 0)
18306                             /* Yup, use that one */
18307                             i = f;
18308                         else
18309                         {
18310                             /* Nope. */
18311                             csp->extern_call = MY_TRUE;
18312                             inter_pc = csp->funstart = EFUN_FUNSTART;
18313                             csp->instruction = i;
18314                             errorf("Too few arguments to %s\n", instrs[i].name);
18315                         }
18316                     }
18317                 }
18318                 else if (num_arg > 0xff || (num_arg > max && max != -1))
18319                 {
18320                     csp->extern_call = MY_TRUE;
18321                     inter_pc = csp->funstart = EFUN_FUNSTART;
18322                     csp->instruction = i;
18323                     errorf("Too many arguments to %s\n", instrs[i].name);
18324                 }
18325 
18326                 /* Store the instruction code */
18327                 if (instrs[i].prefix)
18328                     *p++ = instrs[i].prefix;
18329                 *p++ = instrs[i].opcode;
18330 
18331                 /* And finally the return instruction */
18332                 if ( instrs[i].ret_type.typeflags == TYPE_VOID )
18333                     *p++ = F_RETURN0;
18334                 else
18335                     *p++ = F_RETURN;
18336 
18337                 csp->instruction = i;
18338                 csp->funstart = EFUN_FUNSTART;
18339                 csp->num_local_variables = 0;
18340                 inter_fp = sp - num_arg + 1;
18341 #ifdef USE_NEW_INLINES
18342                 inter_context = NULL;
18343 #endif /* USE_NEW_INLINES */
18344                 tracedepth++; /* Counteract the F_RETURN */
18345                 eval_instruction(code, sp);
18346                 /* The result is on the stack (inter_sp) */
18347                 return;
18348             }
18349             else
18350             {
18351                 /* It is an operator or syntactic marker: fall through
18352                  * to uncallable closure type.
18353                  */
18354                 break;
18355             }
18356         }
18357         else
18358         {
18359             /* simul_efun */
18360             object_t *ob;
18361 
18362             /* Mark the call as sefun closure */
18363             inter_pc = csp->funstart = SIMUL_EFUN_FUNSTART;
18364 
18365             /* Get the simul_efun object */
18366             if ( !(ob = simul_efun_object) )
18367             {
18368                 /* inter_sp == sp */
18369                 if (!assert_simul_efun_object()
18370                  || !(ob = simul_efun_object)
18371                    )
18372                 {
18373                     csp->extern_call = MY_TRUE;
18374                     errorf("Couldn't load simul_efun object\n");
18375                     /* NOTREACHED */
18376                     return;
18377                 }
18378             }
18379             call_simul_efun(i - CLOSURE_SIMUL_EFUN, ob, num_arg);
18380             CLEAN_CSP
18381         }
18382         /* The result is on the stack (inter_sp) */
18383         return;
18384       }
18385 
18386     }
18387 
18388     CLEAN_CSP
18389     errorf("Uncallable closure\n");
18390     /* NOTREACHED */
18391     return;
18392 
18393 #   undef CLEAN_CSP
18394 } /* int_call_lambda() */
18395 
18396 /*-------------------------------------------------------------------------*/
18397 svalue_t *
secure_call_lambda(svalue_t * closure,int num_arg,Bool external)18398 secure_call_lambda (svalue_t *closure, int num_arg, Bool external)
18399 
18400 /* Aliases:
18401  *   secure_apply_lambda(fun, num_arg)
18402  *     == secure_call_lambda(fun, num_arg, FALSE)
18403  *   secure_callback_lambda(fun, num_arg)
18404  *     == secure_call_lambda(fun, num_arg, TRUE)
18405  *
18406  * Call the closure <closure> with <num_arg> arguments on the stack.
18407  * On success, the functions returns a pointer to the result in the
18408  * global apply_return_value, on failure it returns NULL. The arguments are
18409  * removed in either case.
18410  *
18411  * If <external> is TRUE, it means that this call is due to some external
18412  * event (like an ERQ message) instead of being caused by a running program.
18413  * The effect of this flag is that the error handling is like for a normal
18414  * function call (clearing the eval costs before calling runtime_error()).
18415  *
18416  * This error recovery is the difference to call_lambda().
18417  */
18418 
18419 {
18420     struct error_recovery_info error_recovery_info;
18421     svalue_t *save_sp;
18422     struct control_stack *save_csp;
18423     svalue_t *result;
18424 
18425     error_recovery_info.rt.last = rt_context;
18426     error_recovery_info.rt.type = ERROR_RECOVERY_APPLY;
18427     rt_context = (rt_context_t *)&error_recovery_info.rt;
18428     save_sp = inter_sp;
18429     save_csp = csp;
18430 
18431     if (setjmp(error_recovery_info.con.text))
18432     {
18433         secure_apply_error(save_sp - num_arg, save_csp, external);
18434         result = NULL;
18435     }
18436     else
18437     {
18438         if (external)
18439             mark_start_evaluation();
18440         call_lambda(closure, num_arg);
18441         transfer_svalue((result = &apply_return_value), inter_sp);
18442         inter_sp--;
18443         if (external)
18444             mark_end_evaluation();
18445     }
18446     rt_context = error_recovery_info.rt.last;
18447     return result;
18448 } /* secure_call_lambda() */
18449 
18450 /*-------------------------------------------------------------------------*/
18451 static void
call_simul_efun(unsigned int code,object_t * ob,int num_arg)18452 call_simul_efun (unsigned int code, object_t *ob, int num_arg)
18453 
18454 /* Call the simul_efun <code> in the sefun object <ob> with <num_arg>
18455  * arguments on the stack. If it can't be found in the <ob>ject, the
18456  * function queries the auxiliary sefun objects in <simul_efun_vector>.
18457  *
18458  * The function is looked up in the objects by name because its original
18459  * entry in the simul_efun_table[] has been marked as "discarded".
18460  *
18461  * Leave the result on the stack on return.
18462  */
18463 
18464 {
18465     string_t *function_name;
18466 
18467     function_name = simul_efunp[code].name;
18468 
18469     /* First, try calling the function in the given object */
18470     if (!int_apply(function_name, ob, num_arg, MY_FALSE, MY_FALSE))
18471     {
18472         /* Function not found: try the alternative sefun objects */
18473         if (simul_efun_vector)
18474         {
18475             p_int i;
18476             svalue_t *v;
18477 
18478             i = VEC_SIZE(simul_efun_vector);
18479             for (v = simul_efun_vector->item+1 ; ; v++)
18480             {
18481                 if (--i <= 0 || v->type != T_STRING)
18482                 {
18483                     errorf("Calling a vanished simul_efun\n");
18484                     return;
18485                 }
18486                 if ( !(ob = get_object(v->u.str)) )
18487                     continue;
18488                 if (int_apply(function_name, ob, num_arg, MY_FALSE, MY_FALSE))
18489                     return;
18490             }
18491             return;
18492         }
18493         errorf("Calling a vanished simul_efun\n");
18494         return;
18495     }
18496     /*
18497      * The result of the function call is on the stack.
18498      */
18499 } /* call_simul_efun() */
18500 
18501 /*-------------------------------------------------------------------------*/
18502 void
call_function(program_t * progp,int fx)18503 call_function (program_t *progp, int fx)
18504 
18505 /* Call the function <fx> in program <progp> for the current_object.
18506  * This is done with no frame set up. No arguments are passed,
18507  * returned values are removed.
18508  *
18509  * Right now this function is used just for heartbeats, and the
18510  * way of calling prevents shadows from being called.
18511  */
18512 
18513 {
18514 #ifdef USE_NEW_INLINES
18515     push_control_stack(inter_sp, inter_pc, inter_fp, inter_context);
18516 #else
18517     push_control_stack(inter_sp, inter_pc, inter_fp);
18518 #endif /* USE_NEW_INLINES */
18519     csp->ob = current_object;
18520     csp->prev_ob = previous_ob;
18521 #ifdef DEBUG
18522     if (csp != CONTROL_STACK)
18523         fatal("call_function with bad csp\n");
18524 #endif
18525     csp->num_local_variables = 0;
18526     current_prog = progp;
18527     setup_new_frame(fx, NULL);
18528     previous_ob = current_object;
18529     tracedepth = 0;
18530     eval_instruction(FUNCTION_CODE(csp->funstart), inter_sp);
18531     free_svalue(inter_sp--);  /* Throw away the returned result */
18532 } /* call_function() */
18533 
18534 /*-------------------------------------------------------------------------*/
18535 int
get_line_number(bytecode_p p,program_t * progp,string_t ** namep)18536 get_line_number (bytecode_p p, program_t *progp, string_t **namep)
18537 
18538 /* Look up the line number for address <p> within the program <progp>.
18539  * Result is the line number, and *<namep> is set to the name of the
18540  * source resp. include file.
18541  *
18542  * If the code was generated from an included file, and if the name lengths
18543  * allow it, the returned name is "<program name> (<include filename>)".
18544  * In this case, the returned *<namep> points to an untabled string.
18545  *
18546  * In either case, the string returned in *<namep> has one reference
18547  * added.
18548  *
18549  * TODO: (an old comment which might no longer be true): This can be done
18550  * TODO:: much more efficiently, but that change has low priority.)
18551  */
18552 {
18553     /* Datastructure to keep track of included files */
18554     struct incinfo
18555     {
18556         string_t *name;         /* Name of parent file */
18557         struct incinfo *super;  /* Pointer to parent entry */
18558         int super_line;         /* Line number within parent file */
18559     };
18560 
18561     p_int offset;          /* (Remaining) program offset to resolve */
18562     int i;                 /* Current line number */
18563     include_t *includes;   /* Pointer to the next include info */
18564     struct incinfo *inctop = NULL;  /* The include information stack. */
18565     int relocated_from = 0;
18566     int relocated_to = -1;
18567     Bool used_system_mem;
18568       /* TRUE if the line numbers needed SYSTEM privilege to be swapped in,
18569        * because this means that afterwards they need to be deallocated
18570        * again.
18571        */
18572 
18573     if (!progp || !p)
18574     {
18575         *namep = ref_mstring(STR_UNDEFINED);
18576         return 0;
18577     }
18578 
18579     used_system_mem = MY_FALSE;
18580 
18581     /* Get the line numbers */
18582     if (!progp->line_numbers)
18583     {
18584         if (!load_line_numbers_from_swap(progp))
18585         {
18586             /* Uhhmm, out of memory - try to pull some rank */
18587 
18588             int save_privilege;
18589             Bool rc;
18590 
18591             used_system_mem = MY_TRUE;
18592             save_privilege = malloc_privilege;
18593             malloc_privilege = MALLOC_SYSTEM;
18594             rc = load_line_numbers_from_swap(progp);
18595             malloc_privilege = save_privilege;
18596             if (!rc)
18597             {
18598                 *namep = ref_mstring(STR_UNDEFINED);
18599                 return 0;
18600             }
18601         }
18602     }
18603 
18604     /* Get the offset within the program */
18605     offset = (p - progp->program);
18606     if (p < progp->program || p > PROGRAM_END(*progp))
18607     {
18608         printf("%s get_line_number(): Illegal offset %"PRIdPINT" in object %s\n"
18609               , time_stamp(), offset, get_txt(progp->name));
18610         debug_message("%s get_line_number(): Illegal offset %"PRIdPINT
18611                       " in object %s\n",
18612                       time_stamp(), offset, get_txt(progp->name));
18613         *namep = ref_mstring(STR_UNDEFINED);
18614         return 0;
18615     }
18616 
18617     includes = progp->includes;
18618 
18619     /* Decode the line number information until the line number
18620      * for offset is found. We do this by reading the line byte codes,
18621      * counting up the line number <i> while decrementing the <offset>.
18622      * If the offset becomes <= 0, we found the line.
18623      */
18624     for (i = 0, p = progp->line_numbers->line_numbers; ; )
18625     {
18626         int o;
18627 
18628         o = GET_CODE(p);
18629 
18630         if (o <= 63)  /* 0x00..0x3F */
18631         {
18632             if (o >= LI_MAXOFFSET)  /* 0x3b..0x3f */
18633             {
18634                 if (o != LI_MAXOFFSET)
18635                 {
18636                     switch (o)
18637                     {
18638 
18639                     case LI_BACK:
18640                       {
18641                         unsigned int off;
18642 
18643                         p++;
18644                         off = GET_CODE(p);
18645                         i -= off+1;
18646                         break;
18647                       }
18648 
18649                     case LI_INCLUDE:
18650                       {
18651                         /* Included file: push the information */
18652 
18653                         struct incinfo *inc_new;
18654 
18655                         /* Find the next include which generated code.
18656                          * We know that there is one.
18657                          */
18658                         while (includes->depth < 0) includes++;
18659 
18660                         i++;
18661                         inc_new = xalloc(sizeof *inc_new);
18662                         /* TODO: What if this fails? */
18663                         inc_new->name = includes->filename;
18664                         includes++;
18665                         inc_new->super = inctop;
18666                         inc_new->super_line = i;
18667                         inctop = inc_new;
18668                         i = 0;
18669                         break;
18670                       }
18671 
18672                     case LI_INCLUDE_END:
18673                       {
18674                         /* End of include: retrieve old position */
18675 
18676                         struct incinfo *inc_old;
18677 
18678                         inc_old = inctop;
18679                         i = inc_old->super_line;
18680                         inctop = inc_old->super;
18681                         xfree(inc_old );
18682                         break;
18683                       }
18684 
18685                     case LI_L_RELOCATED:
18686                       {
18687                         int h, l;
18688 
18689                         p++;
18690                         h = GET_CODE(p);
18691                         p++;
18692                         l = GET_CODE(p);
18693                         i -= 2;
18694                         relocated_to = i;
18695                         relocated_from = relocated_to - ((h << 8) + l);
18696                         p++; /* skip trailing LI_L_RELOCATED */
18697                         break;
18698                       }
18699                     }
18700                 }
18701                 else /* 0x3c */
18702                 {
18703                     offset -= o;
18704                 }
18705             }
18706             else  /* 0x00..0x3b */
18707             {
18708                 offset -= o;
18709                 i++;
18710                 if (offset <= 0)
18711                     break;
18712             }
18713         }
18714         else if (o <= 127)  /* 0x40..0x7f */
18715         {
18716             /* Simple entry: count offset and lines */
18717             offset -= (o&7) + 1;
18718             i += (o>>3) - 6;
18719             if (offset <= 0)
18720                 break;
18721         }
18722         else if (o >= 256-LI_MAXEMPTY)  /* 0xE0 .. 0xFF */
18723         {
18724             i += 256-o;
18725         }
18726         else /* 0x80 .. 0xDF */
18727         {
18728             i -= 2;
18729             relocated_from = (relocated_to = i) - (o - LI_RELOCATED);
18730         }
18731 
18732         /* Get the next line number bytecode */
18733         p++;
18734     } /* line number search */
18735 
18736     if (i == relocated_to + 1)
18737         i = relocated_from + 1;
18738         /* Perform the announced relocation */
18739 
18740     /* Here, i is the line number, and if inctop is not NULL, the
18741      * code originates from the included file pointed to by inctop.
18742      * In either case, set *<namep> to the pointer to the name
18743      * of the file.
18744      */
18745 
18746     if (inctop)
18747     {
18748         /* The code was included */
18749 
18750         string_t * namebuf;
18751 
18752         namebuf = alloc_mstring(mstrsize(inctop->name) + mstrsize(progp->name)
18753                                                        + 3);
18754         if (namebuf)
18755         {
18756             sprintf(get_txt(namebuf), "%s (%s)"
18757                            , get_txt(progp->name), get_txt(inctop->name));
18758             *namep = namebuf;
18759         }
18760         else
18761         {
18762             /* No memory for the new string - improvise */
18763             *namep = ref_mstring(inctop->name);
18764         }
18765 
18766         /* Free the include stack structures */
18767         do {
18768             struct incinfo *inc_old;
18769 
18770             inc_old = inctop;
18771             inctop = inc_old->super;
18772             xfree(inc_old);
18773         } while (inctop);
18774     }
18775     else
18776     {
18777         /* Normal code */
18778 
18779         *namep = ref_mstring(progp->name);
18780     }
18781 
18782     if (used_system_mem)
18783     {
18784         /* We used SYSTEM priviledged memory - now we have to return it.
18785          */
18786 
18787         total_prog_block_size -= progp->line_numbers->size;
18788         total_bytes_unswapped -= progp->line_numbers->size;
18789         xfree(progp->line_numbers);
18790         progp->line_numbers = NULL;
18791         reallocate_reserved_areas();
18792     }
18793 
18794     /* Return the line number */
18795     return i;
18796 } /* get_line_number() */
18797 
18798 /*-------------------------------------------------------------------------*/
18799 int
get_line_number_if_any(string_t ** name)18800 get_line_number_if_any (string_t **name)
18801 
18802 /* Look up the line number for the current execution address.
18803  * Result is the line number, and *<name> is set to the name of the
18804  * source resp. include file.
18805  *
18806  * The function recognizes sefun and lambda closures, the latter return
18807  * the approximate position offset of the offending instruction within
18808  * the closure.
18809  *
18810  * *<name> may point to an untabled string; and in any case has its
18811  * own reference.
18812  */
18813 
18814 {
18815     if (csp >= &CONTROL_STACK[0] && csp->funstart == SIMUL_EFUN_FUNSTART)
18816     {
18817         *name = ref_mstring(STR_SEFUN_CLOSURE);
18818         return 0;
18819     }
18820 
18821     if (csp >= &CONTROL_STACK[0] && csp->funstart == EFUN_FUNSTART)
18822     {
18823         static char buf[256];
18824         char *iname;
18825 
18826         iname = instrs[csp->instruction].name;
18827         if (iname)
18828         {
18829             buf[sizeof buf - 1] = '\0';
18830             buf[0] = '#';
18831             buf[1] = '\'';
18832             strcpy(buf+2, iname);
18833             if (buf[sizeof buf - 1] != '\0')
18834                 fatal("interpret:get_line_number_if_any(): "
18835                       "buffer overflow.\n");
18836             memsafe(*name = new_mstring(buf), strlen(buf), "instruction name");
18837         }
18838         else
18839             *name = ref_mstring(STR_EFUN_CLOSURE);
18840 
18841         return 0;
18842     }
18843 
18844     if (current_prog)
18845     {
18846         if (csp->funstart < current_prog->program
18847          || csp->funstart > PROGRAM_END(*current_prog))
18848         {
18849             static char name_buffer[24];
18850             string_t * location, *tmp;
18851             lambda_t * l;
18852 
18853             sprintf(name_buffer, "<lambda 0x%6p>", csp->funstart);
18854             memsafe(*name = new_mstring(name_buffer), strlen(name_buffer)
18855                    , "lambda name");
18856             /* Find the beginning of the lambda structure.*/
18857             l = (lambda_t *)( (PTRTYPE)(csp->funstart - 1)
18858                              - offsetof(lambda_t, function.code));
18859 
18860             location = closure_location(l);
18861 
18862             tmp = mstr_add(*name, location);
18863             if (tmp)
18864             {
18865                 free_mstring(*name);
18866                 *name = tmp;
18867             }
18868             free_mstring(location);
18869             return inter_pc - csp->funstart - 2;
18870         }
18871         return get_line_number(inter_pc, current_prog, name);
18872     }
18873 
18874     *name = ref_mstring(STR_EMPTY);
18875     return 0;
18876 } /* get_line_number_if_any() */
18877 
18878 /*-------------------------------------------------------------------------*/
18879 string_t *
collect_trace(strbuf_t * sbuf,vector_t ** rvec)18880 collect_trace (strbuf_t * sbuf, vector_t ** rvec )
18881 
18882 /* Collect the traceback for the current (resp. last) function call, starting
18883  * from the first frame.
18884  *
18885  * If <sbuf> is not NULL, traceback is written in readable form into the
18886  * stringbuffer <sbuf>.
18887  *
18888  * If <rvec> is not NULL, the traceback is returned in a newly created array
18889  * which pointer is put into *<rvec>. For the format of the array, see
18890  * efun debug_info().
18891  *
18892  * If a heart_beat() is involved, return an uncounted pointer to the name of
18893  * the object that had it, otherwise return NULL.
18894  */
18895 
18896 {
18897     struct control_stack *p;  /* Control frame under inspection */
18898     string_t *ret = NULL;     /* Uncounted ref to object name */
18899     bytecode_p pc = inter_pc;
18900     int line = 0;
18901     string_t *name;           /* Uncounted ref to function name */
18902     string_t *file;           /* Counted ref to most recent file name */
18903     object_t *ob = NULL;
18904     bytecode_p last_catch = NULL;  /* Last found catch */
18905 
18906     /* Temporary structure to hold the tracedata before it is condensed
18907      * into the result array.
18908      */
18909     struct traceentry {
18910         vector_t          * vec;
18911         struct traceentry * next;
18912     } *first_entry, *last_entry;
18913     size_t num_entries;
18914 
18915 #ifdef EVAL_COST_TRACE
18916 #define PUT_EVAL_COST(var, cost) \
18917         put_number(var->vec->item+TRACE_EVALCOST, cost);
18918 #else
18919 #define PUT_EVAL_COST(var, cost)
18920 #endif
18921 
18922 #define NEW_ENTRY(var, type, progname, cost) \
18923         struct traceentry * var; \
18924         var = alloca(sizeof(*var)); \
18925         if (!var) \
18926             errorf("Stack overflow in collect_trace()"); \
18927         var->vec = allocate_array_unlimited(TRACE_MAX); \
18928         var->next = NULL; \
18929         if (!first_entry) \
18930             first_entry = last_entry = var; \
18931         else { \
18932             last_entry->next = var; \
18933             last_entry = var; \
18934         } \
18935         num_entries++; \
18936         put_number(var->vec->item+TRACE_TYPE, type); \
18937         put_ref_string(var->vec->item+TRACE_PROGRAM, progname); \
18938         put_ref_string(entry->vec->item+TRACE_OBJECT, ob->name); \
18939 	PUT_EVAL_COST(var, cost)
18940 
18941 #define PUT_LOC(entry, val) \
18942         put_number(entry->vec->item+TRACE_LOC, (p_int)(val))
18943 
18944     first_entry = last_entry = NULL;
18945     num_entries = 0;
18946 
18947     if (!current_prog)
18948     {
18949         if (sbuf)
18950            strbuf_addf(sbuf, "%s\n", get_txt(STR_NO_PROG_TRACE));
18951         if (rvec)
18952         {
18953             vector_t * vec;
18954 
18955             vec = allocate_array_unlimited(1);
18956             put_ref_string(vec->item, STR_NO_PROG_TRACE);
18957             *rvec = vec;
18958         }
18959         return NULL;
18960     }
18961 
18962     if (csp < &CONTROL_STACK[0])
18963     {
18964         if (sbuf)
18965            strbuf_addf(sbuf, "%s\n", get_txt(STR_NO_TRACE));
18966         if (rvec)
18967         {
18968             vector_t * vec;
18969 
18970             vec = allocate_array_unlimited(1);
18971             put_ref_string(vec->item, STR_NO_TRACE);
18972             *rvec = vec;
18973         }
18974         return NULL;
18975     }
18976 
18977     /* Loop through the call stack.
18978      * The organisation of the control stack results in the information
18979      * for this frame (p[0]) being stored in the next (p[1]).
18980      * Confused now? Good.
18981      */
18982     file = ref_mstring(STR_EMPTY);
18983     p = &CONTROL_STACK[0];
18984     do {
18985         bytecode_p  dump_pc;  /* the frame's pc */
18986         program_t  *prog;     /* the frame's program */
18987 #ifdef EVAL_COST_TRACE
18988         int32       dump_eval_cost; /* The eval cost at that frame. */
18989 #endif
18990 
18991         /* Note: Under certain circumstances the value of file carried over
18992          * from the previous iteration is reused in this one.
18993          */
18994 
18995         if (p->extern_call)
18996         {
18997             /* Find the next extern_call and set <ob> to the
18998              * then-current object for all the coming frames.
18999              */
19000             struct control_stack *q = p;
19001             for (;;) {
19002                 if (++q > csp)
19003                 {
19004                     ob = current_object;
19005                     break;
19006                 }
19007                 if (q->extern_call)
19008                 {
19009                     ob = q->ob;
19010                     break;
19011                 }
19012             }
19013             last_catch = NULL;
19014         }
19015 
19016         /* Retrieve pc and program from the stack */
19017         if (p == csp)
19018         {
19019             dump_pc = pc;
19020             prog = current_prog;
19021 #ifdef EVAL_COST_TRACE
19022             dump_eval_cost = eval_cost;
19023 #endif
19024         }
19025         else
19026         {
19027             dump_pc = p[1].pc;
19028             prog = p[1].prog;
19029 #ifdef EVAL_COST_TRACE
19030             dump_eval_cost = p[1].eval_cost;
19031 #endif
19032         }
19033 
19034         /* Use some heuristics first to see if it could possibly be a CATCH.
19035          * The pc should point at a F_END_CATCH instruction, or at a LBRANCH
19036          * to that instruction.
19037          */
19038         if (p > &CONTROL_STACK[0] && p->funstart == p[-1].funstart)
19039         {
19040             bytecode_p pc2 = p->pc;
19041 
19042             if (!pc2)
19043                 goto not_catch;  /* shouldn't happen... */
19044 
19045             if (GET_CODE(pc2) == F_LBRANCH)
19046             {
19047                 short offset;
19048                 pc2++;
19049                 GET_SHORT(offset, pc2);
19050                 if (offset <= 0)
19051                     goto not_catch;
19052                 pc2 += offset;
19053             }
19054 
19055             if (pc2 - FUNCTION_CODE(p->funstart) < 1)
19056                 goto not_catch;
19057 
19058             if (GET_CODE(pc2-1) != F_END_CATCH)
19059             {
19060                 goto not_catch;
19061             }
19062 
19063             if (last_catch == pc2)
19064                 goto not_catch;
19065             last_catch = pc2;
19066             name = STR_CATCH;
19067             if (file)
19068                 free_mstring(file);
19069             file = NULL;
19070             line = 0;
19071             goto name_computed;
19072         }
19073 
19074 not_catch:  /* The frame does not point at a catch here */
19075 
19076         /* Efun symbol? */
19077         if (!prog || !dump_pc)
19078         {
19079             /* TODO: See comments in call_lambda(): this code
19080              * TODO:: should never be reached.
19081              */
19082             if (sbuf)
19083 #ifndef EVAL_COST_TRACE
19084                 strbuf_addf(sbuf, "<function symbol> in '%20s' ('%20s')\n"
19085 #else
19086                 strbuf_addf(sbuf, "%8d <function symbol> in '%20s' ('%20s')\n"
19087                            , dump_eval_cost
19088 #endif
19089                            , get_txt(ob->prog->name), get_txt(ob->name));
19090             if (rvec)
19091             {
19092                 NEW_ENTRY(entry, TRACE_TYPE_SYMBOL, ob->prog->name, dump_eval_cost);
19093             }
19094             continue;
19095         }
19096 
19097         /* simul_efun closure? */
19098         if (p[0].funstart == SIMUL_EFUN_FUNSTART)
19099         {
19100             if (sbuf)
19101                 strbuf_addf( sbuf
19102 #ifndef EVAL_COST_TRACE
19103                            , "<simul_efun closure> bound to '%20s' ('%20s')\n"
19104 #else
19105                            , "%8d <simul_efun closure> bound to '%20s' ('%20s')\n"
19106                            , dump_eval_cost
19107 #endif
19108                            , get_txt(ob->prog->name), get_txt(ob->name));
19109             if (rvec)
19110             {
19111                 NEW_ENTRY(entry, TRACE_TYPE_SEFUN, ob->prog->name, dump_eval_cost);
19112             }
19113             continue;
19114         }
19115 
19116         /* efun closure? */
19117         if (p[0].funstart == EFUN_FUNSTART)
19118         {
19119             char * iname;
19120 
19121             iname = instrs[p[0].instruction].name;
19122             if (iname)
19123             {
19124                 if (sbuf)
19125 #ifndef EVAL_COST_TRACE
19126                     strbuf_addf(sbuf, "#\'%-14s for '%20s' ('%20s')\n"
19127 #else
19128                     strbuf_addf(sbuf, "%8d #\'%-14s for '%20s' ('%20s')\n"
19129                                , dump_eval_cost
19130 #endif
19131                                , iname, get_txt(ob->prog->name)
19132                                , get_txt(ob->name));
19133                 if (rvec)
19134                 {
19135                     string_t *tmp;
19136 
19137                     NEW_ENTRY(entry, TRACE_TYPE_EFUN, ob->prog->name, dump_eval_cost);
19138                     memsafe(tmp = new_mstring(iname), strlen(iname)
19139                            , "instruction name");
19140                     put_string(entry->vec->item+TRACE_NAME, tmp);
19141                 }
19142             }
19143             else
19144             {
19145                 if (sbuf)
19146 #ifndef EVAL_COST_TRACE
19147                     strbuf_addf( sbuf, "<efun closure %d> for '%20s' ('%20s')\n"
19148 #else
19149                     strbuf_addf( sbuf, "%8d <efun closure %d> for '%20s' ('%20s')\n"
19150                                , dump_eval_cost
19151 #endif
19152                                , p[0].instruction, get_txt(ob->prog->name)
19153                                , get_txt(ob->name));
19154                 if (rvec)
19155                 {
19156                     NEW_ENTRY(entry, TRACE_TYPE_EFUN, ob->prog->name, dump_eval_cost);
19157                     put_number(entry->vec->item+TRACE_NAME, p[0].instruction);
19158                 }
19159             }
19160             continue;
19161         }
19162 
19163         /* Lambda closure? */
19164         if (p[0].funstart < prog->program
19165          || p[0].funstart > PROGRAM_END(*prog))
19166         {
19167             if (sbuf)
19168                 strbuf_addf( sbuf
19169 #ifndef EVAL_COST_TRACE
19170                            , "<lambda 0x%6lx> in '%20s' ('%20s') offset %ld\n"
19171 #else
19172                            , "%8d <lambda 0x%6lx> in '%20s' ('%20s') offset %ld\n"
19173                            , dump_eval_cost
19174 #endif
19175                            , (long)p[0].funstart
19176                            , get_txt(ob->prog->name)
19177                            , get_txt(ob->name)
19178                            , (long)(FUNCTION_FROM_CODE(dump_pc) - p[0].funstart)
19179                            );
19180             if (rvec)
19181             {
19182                 NEW_ENTRY(entry, TRACE_TYPE_LAMBDA, ob->prog->name, dump_eval_cost);
19183                 put_number(entry->vec->item+TRACE_NAME, (p_int)p[0].funstart);
19184                 PUT_LOC(entry, (FUNCTION_FROM_CODE(dump_pc) - p[0].funstart));
19185             }
19186             continue;
19187         }
19188 
19189         /* Nothing of the above: a normal program */
19190         if (file)
19191             free_mstring(file);
19192         line = get_line_number(dump_pc, prog, &file);
19193         memcpy(&name, FUNCTION_NAMEP(p[0].funstart), sizeof name);
19194 
19195 name_computed: /* Jump target from the catch detection */
19196 
19197         /* Print the name and line */
19198 
19199         if (mstreq(name, STR_HEART_BEAT) && p != csp)
19200             ret = p->extern_call ? (p->ob ? p->ob->name : NULL) : ob->name;
19201 
19202         if (sbuf)
19203         {
19204             if (file != NULL)
19205 #ifndef EVAL_COST_TRACE
19206                 strbuf_addf(sbuf, "'%15s' in '%20s' ('%20s') line %d\n"
19207 #else
19208                 strbuf_addf(sbuf, "%8d '%15s' in '%20s' ('%20s') line %d\n"
19209                            , dump_eval_cost
19210 #endif
19211                            , get_txt(name), get_txt(file)
19212                            , get_txt(ob->name), line);
19213             else
19214 #ifndef EVAL_COST_TRACE
19215                 strbuf_addf(sbuf, "'%15s' in %22s ('%20s')\n"
19216 #else
19217                 strbuf_addf(sbuf, "%8d '%15s' in %22s ('%20s')\n"
19218                            , dump_eval_cost
19219 #endif
19220                            , get_txt(name), "", get_txt(ob->name));
19221         }
19222 
19223         if (rvec)
19224         {
19225             NEW_ENTRY(entry, TRACE_TYPE_LFUN, file != NULL ? file : STR_EMPTY, dump_eval_cost);
19226             put_ref_string(entry->vec->item+TRACE_NAME, name);
19227             PUT_LOC(entry, line);
19228         }
19229 
19230     } while (++p <= csp);
19231 
19232     if (file)
19233         free_mstring(file);
19234 
19235 
19236     /* Condense the singular entries into the result array */
19237     if (rvec)
19238     {
19239         vector_t * vec;
19240         size_t ix;
19241 
19242         vec = allocate_array_unlimited(num_entries+1);
19243 
19244         if (ret)
19245             put_ref_string(vec->item, ret);
19246 
19247         for (ix = 1; first_entry != NULL; ix++, first_entry = first_entry->next)
19248         {
19249             put_array(vec->item+ix, first_entry->vec);
19250         }
19251 
19252         *rvec = vec;
19253     }
19254 
19255     /* Done */
19256     return ret;
19257 
19258 #undef NEW_ENTRY
19259 #undef PUT_LOC
19260 
19261 } /* collect_trace() */
19262 
19263 /*-------------------------------------------------------------------------*/
19264 string_t *
dump_trace(Bool how,vector_t ** rvec)19265 dump_trace (Bool how, vector_t ** rvec)
19266 
19267 /* Write out a traceback, starting from the first frame. If a heart_beat()
19268  * is involved, return (uncounted) the name of the object that had it.
19269  *
19270  * If <how> is FALSE (the normal case), the trace is written with
19271  * debug_message() only. If <how> is TRUE (used for internal errors), the
19272  * trace is also written to stdout.
19273  *
19274  * If TRACE_CODE is defined and <how> is true, the last executed
19275  * instructions are printed, too.
19276  *
19277  * If <rvec> is not NULL, the traceback is returned in a newly created array
19278  * which pointer is put into *<rvec>. For the format of the array, see
19279  * efun debug_info().
19280  */
19281 
19282 {
19283     strbuf_t sbuf;
19284     string_t *hb_obj_name;
19285 
19286     strbuf_zero(&sbuf);
19287     hb_obj_name = collect_trace(&sbuf, rvec);
19288 
19289     /* Print the last instructions if required */
19290 #ifdef TRACE_CODE
19291     if (how) {
19292         /* TODO: This number of instructions should be a runtime arg */
19293 #ifdef DEBUG
19294         (void)last_instructions(200, MY_TRUE, NULL);
19295         if (inter_pc)
19296             printf("%6p: %3d %3d %3d %3d %3d %3d %3d %3d\n"
19297                   , inter_pc
19298                   , inter_pc[0], inter_pc[1], inter_pc[2], inter_pc[3]
19299                   , inter_pc[4], inter_pc[5], inter_pc[6], inter_pc[7] );
19300         else
19301             printf("No program counter.\n");
19302 #else  /* DEBUG */
19303         last_instructions(20, MY_TRUE, NULL);
19304 #endif /* DEBUG */
19305     }
19306 #endif /* TRACE_CODE */
19307 
19308     /* Print the trace */
19309     if (how)
19310         fputs(sbuf.buf, stdout);
19311     debug_message("%s", sbuf.buf);
19312 
19313     /* Cleanup and return */
19314     strbuf_free(&sbuf);
19315 
19316     return hb_obj_name;
19317 } /* dump_trace() */
19318 
19319 /*-------------------------------------------------------------------------*/
19320 void
invalidate_apply_low_cache(void)19321 invalidate_apply_low_cache (void)
19322 
19323 /* Called in the (unlikely) case that all programs had to be renumbered,
19324  * this invalidates the call cache.
19325  */
19326 
19327 {
19328     int i;
19329 
19330     for (i = 0; i < CACHE_SIZE; i++)
19331     {
19332         cache[i].id = 0;
19333         if (cache[i].name)
19334         {
19335             free_mstring(cache[i].name);
19336             cache[i].name = NULL;
19337         }
19338     }
19339 }
19340 
19341 
19342 /*-------------------------------------------------------------------------*/
19343 size_t
interpreter_overhead(void)19344 interpreter_overhead (void)
19345 
19346 /* Return the amount of memory allocated for the interpreter.
19347  * Right now, there is none.
19348  */
19349 
19350 {
19351     size_t sum;
19352 
19353     sum = 0;
19354 
19355     return sum;
19356 } /* interpreter_overhead() */
19357 
19358 
19359 #ifdef GC_SUPPORT
19360 
19361 /*-------------------------------------------------------------------------*/
19362 void
clear_interpreter_refs(void)19363 clear_interpreter_refs (void)
19364 
19365 /* GC Support: Clear the interpreter references.
19366  */
19367 
19368 {
19369 #ifdef TRACE_CODE
19370     {
19371         int i;
19372 
19373         for (i = TOTAL_TRACE_LENGTH; --i >= 0; )
19374         {
19375             object_t *ob;
19376 
19377             if (NULL != (ob = previous_objects[i])
19378              && ob->flags & O_DESTRUCTED
19379              && ob->ref
19380                )
19381             {
19382                 ob->ref = 0;
19383                 ob->prog->ref = 0;
19384                 clear_program_ref(ob->prog, MY_FALSE);
19385             }
19386         }
19387     }
19388 #endif
19389 } /* clear_interpreter_refs() */
19390 
19391 /*-------------------------------------------------------------------------*/
19392 void
count_interpreter_refs(void)19393 count_interpreter_refs (void)
19394 
19395 /* GC Support: Count/mark all interpreter held structures.
19396  */
19397 
19398 {
19399     int i;
19400 
19401     for (i = CACHE_SIZE; --i>= 0; ) {
19402         if (cache[i].name)
19403             count_ref_from_string(cache[i].name);
19404     }
19405 #ifdef TRACE_CODE
19406     for (i = TOTAL_TRACE_LENGTH; --i >= 0; )
19407     {
19408         object_t *ob;
19409 
19410         if ( NULL != (ob = previous_objects[i]) )
19411         {
19412             if (ob->flags & O_DESTRUCTED)
19413             {
19414                 previous_objects[i] = NULL;
19415                 previous_instruction[i] = 0;
19416                 reference_destructed_object(ob);
19417             }
19418             else
19419             {
19420                 ob->ref++;
19421             }
19422         }
19423     }
19424 #endif
19425 }
19426 /*-------------------------------------------------------------------------*/
19427 
19428 #endif /* GC_SUPPORT */
19429 
19430 /*=========================================================================*/
19431 
19432 /*                            D E B U G G I N G                            */
19433 
19434 /*-------------------------------------------------------------------------*/
19435 #ifdef OPCPROF
19436 Bool
opcdump(string_t * fname)19437 opcdump (string_t * fname)
19438 
19439 /* Print the usage statistics for the opcodes into the file <fname>.
19440  * Return TRUE on success, FALSE if <fname> can't be written.
19441  */
19442 
19443 {
19444     int i;
19445     FILE *f;
19446 
19447     fname = check_valid_path(fname, current_object, STR_OPCDUMP, MY_TRUE);
19448     if (!fname)
19449         return MY_FALSE;
19450     f = fopen(get_txt(fname), "w");
19451     free_mstring(fname);
19452     if (!f)
19453         return MY_FALSE;
19454     FCOUNT_WRITE(fname);
19455 
19456 
19457     for(i = 0; i < MAXOPC; i++)
19458     {
19459         if (opcount[i])
19460 #ifdef VERBOSE_OPCPROF
19461             fprintf(f,"%d: \"%-16s\" %6d\n",i, get_f_name(i), opcount[i]);
19462 #else
19463             fprintf(f,"%d: %d\n", i, opcount[i]);
19464 #endif
19465     }
19466     fclose(f);
19467 
19468     return MY_TRUE;
19469 }
19470 #endif /* OPCPROF */
19471 
19472 
19473 #ifdef TRACE_CODE
19474 
19475 /*-------------------------------------------------------------------------*/
19476 static char *
get_arg(int a)19477 get_arg (int a)
19478 
19479 /* Return the argument for the instruction at previous_pc[<a>] as a string.
19480  * If there is no argument, return "".
19481  *
19482  * Helper function for last_instructions().
19483  */
19484 
19485 {
19486     static char buff[12];
19487     bytecode_p from, to;
19488     int b;
19489 
19490     b = (a+1) % TOTAL_TRACE_LENGTH;
19491     from = previous_pc[a];
19492     to = previous_pc[b];
19493 
19494     if (to - from < 2)
19495         return "";
19496 
19497     if (to - from == 2)
19498     {
19499         snprintf(buff, sizeof(buff), "%d", GET_CODE(from+1));
19500         return buff;
19501     }
19502 
19503     if (to - from == 3)
19504     {
19505         short arg;
19506 
19507         GET_SHORT(arg, from+1);
19508         snprintf(buff, sizeof(buff), "%hd", arg);
19509         return buff;
19510     }
19511 
19512     if (to - from == 5)
19513     {
19514         int32 arg;
19515 
19516         GET_INT32(arg, from+1);
19517         snprintf(buff, sizeof(buff), "%"PRId32, arg);
19518         return buff;
19519     }
19520 
19521     return "";
19522 } /* get_arg() */
19523 
19524 /*-------------------------------------------------------------------------*/
19525 static void
last_instr_output(char * str,svalue_t ** svpp)19526 last_instr_output (char *str, svalue_t **svpp)
19527 
19528 /* <svpp> == NULL: print string <str>
19529  * <svpp> != NULL: store a copy of <str> as string-svalue to *<svpp>, then
19530  *                 increment *<svpp>
19531  *
19532  * Helper function to last_instructions() to either print strings for
19533  * a tracedump, or to push them onto the evaluator stack for the efun
19534  * last_instructions().
19535  */
19536 
19537 {
19538     if (svpp)
19539     {
19540         string_t *s;
19541         memsafe(s = new_mstring(str), strlen(str), "copy of instruction name");
19542         put_string((*svpp), s);
19543         (*svpp)++;
19544     }
19545     else
19546     {
19547         fputs(str, stdout);
19548         putc('\n', stdout);
19549     }
19550 } /* last_instr_output() */
19551 
19552 /*-------------------------------------------------------------------------*/
19553 static Bool
program_referenced(program_t * prog,program_t * prog2)19554 program_referenced (program_t *prog, program_t *prog2)
19555 
19556 /* Return TRUE if <prog2> inherits <prog>.
19557  *
19558  * Auxiliary function to last_instructions().
19559  */
19560 
19561 {
19562     inherit_t *inh;
19563     int i;
19564 
19565     if (prog == prog2)
19566         return MY_TRUE;
19567 
19568     /* If a prog2 is swapped out, it can't have prog inherited
19569      * and swapped in.
19570      */
19571     if (P_PROG_SWAPPED(prog2))
19572         return MY_FALSE;
19573 
19574     /* Recursively test the inherits */
19575     for (i = prog2->num_inherited, inh = prog2->inherit; --i >= 0; inh++)
19576     {
19577         if (program_referenced(prog, inh->prog))
19578             return MY_TRUE;
19579     }
19580 
19581     return MY_FALSE;
19582 }
19583 
19584 /*-------------------------------------------------------------------------*/
19585 static Bool
program_exists(program_t * prog,object_t * guess)19586 program_exists (program_t *prog, object_t *guess)
19587 
19588 /* Test if <prog> exists - either by itself or as inherited program.
19589  * Start testing with the program of <guess>, if it is not there,
19590  * test all objects in the list.
19591  *
19592  * Auxiliary function to last_instructions().
19593  */
19594 
19595 {
19596     if (program_referenced(prog, guess->prog))
19597         return MY_TRUE;
19598 
19599     for (guess = obj_list; guess; guess = guess->next_all)
19600     {
19601 #ifdef DEBUG
19602         if (guess->flags & O_DESTRUCTED)  /* TODO: Can't happen */
19603             continue;
19604 #endif
19605         if (program_referenced(prog, guess->prog))
19606             return MY_TRUE;
19607     }
19608 
19609     return MY_FALSE;
19610 }
19611 
19612 /*-------------------------------------------------------------------------*/
19613 int
last_instructions(int length,Bool verbose,svalue_t ** svpp)19614 last_instructions (int length, Bool verbose, svalue_t **svpp)
19615 
19616 /* 'Print' a dump of the <length> last instructions. If <svpp> is NULL,
19617  * all the data is printed, else *<svpp> points to the evaluator stack
19618  * and all the 'printed' lines are pushed onto the stack using *<svpp>
19619  * as pointer.
19620  *
19621  * If <verbose> is true, more information is printed.
19622  *
19623  * Return the index for the last executed instruction.
19624  *
19625  * This function is called from dump_trace() and f_last_instructions().
19626  */
19627 
19628 {
19629     int i;
19630     object_t *old_obj;
19631     char buf[400];
19632     string_t *old_file;
19633     int old_line, line = 0;
19634 
19635     old_obj = NULL;
19636     old_file = NULL;
19637     old_line = 0;
19638     i = (last - length + TOTAL_TRACE_LENGTH) % TOTAL_TRACE_LENGTH;
19639 
19640     /* Walk through the instructions.
19641      * Instructions with value 0 are not used yet, or have been
19642      * removed while cleaning up destructed objects.
19643      */
19644     do {
19645         i = (i + 1) % TOTAL_TRACE_LENGTH;
19646         if (previous_instruction[i] != 0)
19647         {
19648             if (verbose)
19649             {
19650                 string_t *file;
19651                 program_t *ppr;
19652                 bytecode_p ppc;
19653 
19654                 ppr = previous_programs[i];
19655                 ppc = previous_pc[i]+1;
19656                 if (!program_exists(ppr, previous_objects[i]))
19657                 {
19658                     file = ref_mstring(STR_PROG_DEALLOCATED);
19659                     line = 0;
19660                 }
19661                 else if (ppc < ppr->program || ppc > PROGRAM_END(*ppr))
19662                 {
19663                     file = ref_mstring(STR_UNKNOWN_LAMBDA);
19664                     line = 0;
19665                 }
19666                 else
19667                 {
19668                     line = get_line_number(ppc, ppr, &file);
19669                 }
19670 
19671                 if (previous_objects[i] != old_obj
19672                  || (old_file && !mstreq(file, old_file))
19673                    )
19674                 {
19675                     snprintf(buf, sizeof(buf), "%.170s %.160s line %d"
19676                                , get_txt(previous_objects[i]->name)
19677                                , get_txt(file), line
19678                     );
19679                     last_instr_output(buf, svpp);
19680                     old_obj = previous_objects[i];
19681                     if (old_file)
19682                         free_mstring(old_file);
19683                     old_file = ref_mstring(file);
19684                 }
19685 
19686                 if (file)
19687                     free_mstring(file);
19688             }
19689             snprintf(buf, sizeof(buf)-40, "%6p: %3d %8s %-26s (%td:%3td)"
19690                    , previous_pc[i]
19691                    , previous_instruction[i] /* instrs.h has these numbers */
19692                    , get_arg(i)
19693                    , get_f_name(previous_instruction[i])
19694                    , (stack_size[i] + 1)
19695                    , (abs_stack_size[i])
19696             );
19697             if (verbose && line != old_line)
19698                 snprintf(buf + strlen(buf), 40, "\tline %d", old_line = line);
19699             last_instr_output(buf, svpp);
19700         }
19701     } while (i != last);
19702 
19703     if (old_file)
19704         free_mstring(old_file);
19705 
19706     return last;
19707 } /* last_instructions() */
19708 
19709 /*-------------------------------------------------------------------------*/
19710 svalue_t *
f_last_instructions(svalue_t * sp)19711 f_last_instructions (svalue_t *sp)
19712 
19713 /* EFUN last_instructions()
19714  *
19715  *   string *last_instructions (int length, int verbose)
19716  *
19717  * Return an array showing the 'length' last executed
19718  * instructions in disassembled form. If 'verbose' is non-zero
19719  * (the default), line number information are also included.
19720  * Each string is built as this:
19721  *
19722  *   Opcode-Address: Opcode Operand Mnemonic (Stackdepth) Linenumber
19723  *
19724  * The Stackdepth information consists of two numbers <rel>:<abs>:
19725  * <rel> is the relative stack usage in this function, <abs> is the
19726  * absolute stack usage.
19727  *
19728  * The linenumber information is appended if requested and a new
19729  * source line is reached. Also, calls between objects produce a
19730  *
19731  *   Objectname Programname Linenumber
19732  *
19733  * entry in the resulting array (in verbose mode only).
19734  *
19735  * There is a preconfigured upper limit for the backtrace.
19736  */
19737 
19738 {
19739     vector_t *v, *v2;
19740     mp_int num_instr, size;
19741     svalue_t *svp;
19742 
19743     /* Test the arguments */
19744     num_instr = sp[-1].u.number;
19745     if (num_instr <= 0)
19746         errorf("Illegal number of instructions: %"PRIdMPINT".\n", num_instr);
19747 
19748     sp--;
19749     inter_sp = sp; /* Out of memory possible */
19750     if (num_instr > TOTAL_TRACE_LENGTH)
19751         num_instr = TOTAL_TRACE_LENGTH;
19752 
19753     /* Allocate the result vector */
19754     size = sp[1].u.number ? num_instr << 1 : num_instr;
19755     v = allocate_array(size);
19756 
19757     /* Enter the vector into the stack for now, so that it will be
19758      * freed when an out of memory error occurs.
19759      */
19760     put_array(sp, v);
19761     svp = v->item;
19762     last_instructions(num_instr, sp[1].u.number != 0, &svp);
19763 
19764     /* If we allocated the vector to big, get a shorter one and copy
19765      * the data.
19766      */
19767     if (svp - v->item < size)
19768     {
19769         size = svp - v->item;
19770         v2 = allocate_array(size);
19771         memcpy(v2->item, v->item, size * sizeof *svp);
19772         sp->u.vec = v2;
19773         free_empty_vector(v);
19774     }
19775 
19776     return sp;
19777 } /* f_last_instructions() */
19778 
19779 /*-------------------------------------------------------------------------*/
19780 
19781 #endif /* TRACE_CODE */
19782 
19783 /*-------------------------------------------------------------------------*/
control_stack_depth(void)19784 int control_stack_depth (void)
19785   /* Returns the number of frames on the control stack. Can be used to estimate
19786    * the still available stack depth in recursive code.
19787    */
19788 {
19789     return (csp - CONTROL_STACK) + 1;
19790 } /* control_stack_depth() */
19791 
19792 /*-------------------------------------------------------------------------*/
19793 static INLINE int
caller_stack_depth(void)19794 caller_stack_depth(void)
19795 /* static helper function for f_caller_stack_depth() and f_caller_stack() for
19796  * calculating the stack depth. It is a separate function because the code
19797  * is used at two places and the compiler will probably inline it anyway.
19798  */
19799 {
19800   int depth;
19801   Bool done;
19802   struct control_stack *p;
19803 
19804   /* Determine the depth of the call stack */
19805   p = csp;
19806   for (depth = 0, done = MY_FALSE; ; depth++)
19807   {
19808     do {
19809       if (p == CONTROL_STACK)
19810       {
19811         done = MY_TRUE;
19812         break;
19813       }
19814     } while ( !(--p)[1].extern_call );
19815     if (done)
19816       break;
19817   }
19818 
19819   return depth;
19820 } /* caller_stack_depth() */
19821 
19822 /*-------------------------------------------------------------------------*/
19823 svalue_t *
f_caller_stack_depth(svalue_t * sp)19824 f_caller_stack_depth (svalue_t *sp)
19825 /* EFUN caller_stack_depth()
19826  *
19827  *   int caller_stack_depth(void)
19828  *
19829  * Returns the number of previous objects on the stack. This
19830  * can be used for security checks.
19831  */
19832 
19833 {
19834     push_number(sp, caller_stack_depth());
19835 
19836     return sp;
19837 } /* f_caller_stack_depth() */
19838 
19839 /*-------------------------------------------------------------------------*/
19840 svalue_t *
f_caller_stack(svalue_t * sp)19841 f_caller_stack (svalue_t *sp)
19842 
19843 /* EFUN caller_stack()
19844  *
19845  *   object *caller_stack()
19846  *   object *caller_stack(int add_interactive)
19847  *
19848  * Returns an array of the previous_object()s who caused the
19849  * call_other() to this_object().  previous_object(i) equals
19850  * caller_stack()[i].
19851 
19852  * If you pass the optional argument <add_interactive> (as true
19853  * value), this_interactive() (or 0 if not existing) is appended
19854  * to the array.
19855  */
19856 
19857 {
19858     int depth, i;
19859     Bool done;
19860     struct control_stack *p;
19861     vector_t *v;
19862     svalue_t *svp;
19863 
19864     /* Determine the depth of the call stack */
19865     depth = caller_stack_depth();
19866 
19867     /* Allocate and fill in the result array */
19868     v = allocate_uninit_array(depth + (sp->u.number ? 1 : 0));
19869     p = csp;
19870     for (i = 0, svp = v->item, done = MY_FALSE; i < depth; i++, svp++)
19871     {
19872         object_t *prev;
19873         do {
19874             if (p == CONTROL_STACK)
19875             {
19876                 done = MY_TRUE;
19877                 break;
19878             }
19879         } while ( !(--p)[1].extern_call);
19880 
19881         /* Break if end of stack */
19882         if (done)
19883             break;
19884 
19885         /* Get 'the' calling object */
19886         if (p[1].extern_call & CS_PRETEND)
19887             prev = p[1].pretend_to_be;
19888         else
19889             prev = p[1].ob;
19890 
19891         /* Enter it into the array */
19892         if (prev == NULL || prev->flags & O_DESTRUCTED)
19893             put_number(svp, 0);
19894         else
19895             put_ref_object(svp, prev, "caller_stack");
19896     }
19897 
19898 #ifdef DEBUG
19899     if (i < depth)
19900     {
19901         errorf("Computed stack depth to %d, but found only %d objects\n"
19902              , depth, i);
19903         /* NOTREACHED */
19904         return sp;
19905     }
19906 #endif
19907 
19908     /* If so desired, add the interactive object */
19909     if (sp->u.number)
19910     {
19911         if ( current_interactive
19912          && !(current_interactive->flags & O_DESTRUCTED))
19913         {
19914             put_ref_object(svp, current_interactive, "caller_stack");
19915         }
19916         else
19917             put_number(svp, 0);
19918     }
19919 
19920     /* Assign the result and return */
19921     put_array(sp, v);
19922 
19923     return sp;
19924 } /* f_caller_stack() */
19925 
19926 /*-------------------------------------------------------------------------*/
19927 svalue_t *
f_previous_object(svalue_t * sp)19928 f_previous_object (svalue_t *sp)
19929 
19930 /* EFUN previous_object()
19931  *
19932  *   object previous_object(int i)
19933  *
19934  * Follow back the last <i> call_other()s and return the calling
19935  * object (i.e. previous_object(2) returns the caller of the
19936  * caller). It must hold 1 <= i < caller_stack_depth().
19937  * Any value of i < 1 is treated as i == 1.
19938  *
19939  * There is an important special case: in functions called by the
19940  * gamedriver in reaction to some external event (e.g. commands
19941  * added by add_action), previous_object() will return
19942  * this_object(), but previous_object(1) will return 0.
19943  */
19944 
19945 {
19946     int i;
19947     struct control_stack *p;
19948     object_t *prev_ob;
19949 
19950     /* Test the arguments */
19951     i = sp->u.number;
19952     if (i > MAX_TRACE) {
19953         sp->u.number = 0;
19954         return sp;
19955     }
19956 
19957     /* Set p back to the <i>th extern call */
19958     p = csp;
19959     do {
19960         do {
19961             if (p == CONTROL_STACK) {
19962                 sp->u.number = 0;
19963                 return sp;
19964             }
19965         } while ( !(--p)[1].extern_call );
19966     } while (--i >= 0);
19967 
19968     /* Determine the object and push it */
19969     if (p[1].extern_call & CS_PRETEND)
19970         prev_ob = p[1].pretend_to_be;
19971     else
19972         prev_ob = p[1].ob;
19973 
19974     if (!prev_ob || prev_ob->flags & O_DESTRUCTED)
19975         sp->u.number = 0;
19976     else
19977         put_ref_object(sp, prev_ob, "previous_object");
19978 
19979     return sp;
19980 } /* f_previous_object() */
19981 
19982 
19983 
19984 #ifdef DEBUG
19985 
19986 /*-------------------------------------------------------------------------*/
19987 void
count_inherits(program_t * progp)19988 count_inherits (program_t *progp)
19989 
19990 /* Check Refcounts: Increment the extra_ref of all programs inherited
19991  * by <progp>. If one of those programs has not been visited yet,
19992  * its extra_ref is set to 1 and this function is called recursively.
19993  *
19994  * If check_..._search_prog is set and equal to one of the inherited
19995  * programs, a notice is printed.
19996  */
19997 
19998 {
19999     int i;
20000     program_t *progp2;
20001 
20002     /* Clones will not add to the ref count of inherited progs */
20003     for (i = 0; i < progp->num_inherited; i++)
20004     {
20005         progp2 = progp->inherit[i].prog;
20006         progp2->extra_ref++;
20007         if (progp2 == check_a_lot_ref_counts_search_prog)
20008             printf("%s Found prog, inherited by %s, new total ref %"
20009                    PRIdPINT"\n",
20010                    time_stamp(), get_txt(progp->name), progp2->ref);
20011         if (NULL == register_pointer(ptable, progp2))
20012         {
20013             continue;
20014         }
20015         progp2->extra_ref = 1;
20016         if (progp2->blueprint)
20017         {
20018             count_extra_ref_in_object(progp2->blueprint);
20019         }
20020         count_inherits(progp2);
20021     }
20022 } /* count_inherits() */
20023 
20024 /*-------------------------------------------------------------------------*/
20025 static void
count_extra_ref_in_mapping_filter(svalue_t * key,svalue_t * data,void * extra)20026 count_extra_ref_in_mapping_filter ( svalue_t *key, svalue_t *data
20027                                   , void * extra)
20028 
20029 /* Count the extra refs for <key> and the associated <data>. <extra>
20030  * is a mp_int giving the number of data values.
20031  */
20032 
20033 {
20034     count_extra_ref_in_vector(key, 1);
20035     count_extra_ref_in_vector(data, (size_t)extra);
20036 }
20037 
20038 /*-------------------------------------------------------------------------*/
20039 static void
check_extra_ref_in_mapping_filter(svalue_t * key,svalue_t * data,void * extra)20040 check_extra_ref_in_mapping_filter (svalue_t *key, svalue_t *data
20041                                   , void * extra)
20042 
20043 /* Check the extra refs for <key> and the associated <data>. <extra>
20044  * is a mp_int giving the number of data values.
20045  */
20046 
20047 {
20048     check_extra_ref_in_vector(key, 1);
20049     check_extra_ref_in_vector(data, (size_t)extra);
20050 }
20051 
20052 static void
count_extra_ref_in_prog(program_t * prog)20053 count_extra_ref_in_prog (program_t *prog)
20054 /* Count extra refs for <prog>.
20055  */
20056 {
20057     if (NULL != register_pointer(ptable, prog))
20058     {
20059         prog->extra_ref = 1;
20060         if (prog->blueprint)
20061         {
20062             count_extra_ref_in_object(prog->blueprint);
20063         }
20064         count_inherits(prog);
20065     }
20066 }
20067 
20068 /*-------------------------------------------------------------------------*/
20069 void
count_extra_ref_in_object(object_t * ob)20070 count_extra_ref_in_object (object_t *ob)
20071 
20072 /* Count the extra refs for object <ob>. If the object has been visited
20073  * before, extra_ref is just incremented. Otherwise, extra_ref is
20074  * set to 1 and all depending refs are counted.
20075  *
20076  * If check_..._search_prog is set and matches the objects program,
20077  * a notice is printed.
20078  */
20079 
20080 {
20081     int was_swapped = MY_FALSE;
20082 
20083     ob->extra_ref++;
20084     if ( NULL == register_pointer(ptable, ob) )
20085     {
20086         return;
20087     }
20088 
20089     ob->extra_ref = 1;
20090     if ( !O_PROG_SWAPPED(ob) )
20091     {
20092         ob->prog->extra_ref++;
20093         if (ob->prog == check_a_lot_ref_counts_search_prog)
20094             printf("%s Found program for object %s\n", time_stamp()
20095                   , get_txt(ob->name));
20096     }
20097 
20098     /* Clones will not add to the ref count of inherited progs */
20099     if (O_PROG_SWAPPED(ob))
20100     {
20101          if (load_ob_from_swap(ob) < 0)
20102             debug_message( "%s check-refcounts: Program for '%s' can't be "
20103                            "swapped in - extra refcounts may be wrong.\n"
20104                          , time_stamp(), get_txt(ob->name));
20105          else
20106              was_swapped = MY_TRUE;
20107     }
20108 
20109     if (!O_PROG_SWAPPED(ob))
20110     {
20111         count_extra_ref_in_prog(ob->prog);
20112     }
20113 
20114     if (was_swapped)
20115         swap_program(ob);
20116 } /* count_extra_ref_in_object() */
20117 
20118 /*-------------------------------------------------------------------------*/
20119 static void
count_extra_ref_in_closure(lambda_t * l,ph_int type)20120 count_extra_ref_in_closure (lambda_t *l, ph_int type)
20121 
20122 /* Count the extra refs in the closure <l> of type <type>.
20123  */
20124 
20125 {
20126     if (CLOSURE_HAS_CODE(type))
20127     {
20128         /* We need to count the extra_refs in the constant values. */
20129 
20130         mp_int num_values;
20131         svalue_t *svp;
20132 
20133         svp = (svalue_t *)l;
20134         if ( (num_values = EXTRACT_UCHAR(l->function.code)) == 0xff)
20135             num_values = svp[-0x100].u.number;
20136         svp -= num_values;
20137         count_extra_ref_in_vector(svp, (size_t)num_values);
20138     }
20139     else
20140     {
20141         /* Count the referenced closures and objects */
20142         if (type == CLOSURE_BOUND_LAMBDA)
20143         {
20144             lambda_t *l2 = l->function.lambda;
20145 
20146             if (NULL != register_pointer(ptable, l2) )
20147                 count_extra_ref_in_closure(l2, CLOSURE_UNBOUND_LAMBDA);
20148         }
20149         else if (type == CLOSURE_LFUN)
20150         {
20151             count_extra_ref_in_object(l->function.lfun.ob);
20152             if (l->function.lfun.inhProg)
20153             {
20154                 l->function.lfun.inhProg->extra_ref++;
20155                 count_extra_ref_in_prog(l->function.lfun.inhProg);
20156             }
20157         }
20158     }
20159 
20160     if (type != CLOSURE_UNBOUND_LAMBDA)
20161     {
20162         count_extra_ref_in_object(l->ob);
20163     }
20164 
20165     if (l->prog_ob)
20166     {
20167         count_extra_ref_in_object(l->prog_ob);
20168     }
20169 } /* count_extra_ref_in_closure() */
20170 
20171 /*-------------------------------------------------------------------------*/
20172 void
count_extra_ref_in_vector(svalue_t * svp,size_t num)20173 count_extra_ref_in_vector (svalue_t *svp, size_t num)
20174 
20175 /* Count the extra_refs of all <num> values starting at <svp>.
20176  */
20177 
20178 {
20179     svalue_t *p;
20180 
20181     if (!svp)
20182         return;
20183 
20184     for (p = svp; p < svp+num; p++)
20185     {
20186         switch(p->type)
20187         {
20188 
20189         case T_CLOSURE:
20190             if (CLOSURE_MALLOCED(p->x.closure_type))
20191             {
20192                 lambda_t *l;
20193 
20194                 l = p->u.lambda;
20195                 if ( NULL == register_pointer(ptable, l) )
20196                     continue;
20197                 count_extra_ref_in_closure(l, p->x.closure_type);
20198                 continue;
20199             }
20200             /* FALLTHROUGH */
20201 
20202         case T_OBJECT:
20203           {
20204             count_extra_ref_in_object(p->u.ob);
20205             continue;
20206           }
20207 
20208         case T_QUOTED_ARRAY:
20209         case T_POINTER:
20210             p->u.vec->extra_ref++;
20211             if (NULL == register_pointer(ptable, p->u.vec) )
20212                 continue;
20213             p->u.vec->extra_ref = 1;
20214             count_extra_ref_in_vector(&p->u.vec->item[0], VEC_SIZE(p->u.vec));
20215             continue;
20216 
20217 #ifdef USE_STRUCTS
20218         case T_STRUCT:
20219             if (NULL == register_pointer(ptable, p->u.strct) )
20220                 continue;
20221             count_extra_ref_in_vector(&p->u.strct->member[0], struct_size(p->u.strct));
20222             continue;
20223 #endif /* USE_STRUCTS */
20224 
20225         case T_MAPPING:
20226             if (NULL == register_pointer(ptable, p->u.map) ) continue;
20227             walk_mapping(
20228               p->u.map,
20229               count_extra_ref_in_mapping_filter,
20230               (void *)p->u.map->num_values
20231             );
20232             continue; /* no extra ref count implemented */
20233         }
20234     }
20235 } /* count_extra_ref_in_vector() */
20236 
20237 /*-------------------------------------------------------------------------*/
20238 static void
check_extra_ref_in_vector(svalue_t * svp,size_t num)20239 check_extra_ref_in_vector (svalue_t *svp, size_t num)
20240 
20241 /* Check the extra_refs of the <num> values starting at <svp>
20242  */
20243 
20244 {
20245     svalue_t *p;
20246 
20247     if (!svp)
20248         return;
20249 
20250     for (p = svp; p < svp+num; p++)
20251     {
20252         switch(p->type)
20253         {
20254         case T_QUOTED_ARRAY:
20255         case T_POINTER:
20256             if (NULL == register_pointer(ptable, p->u.vec) )
20257                 continue;
20258             check_extra_ref_in_vector(&p->u.vec->item[0], VEC_SIZE(p->u.vec));
20259             p->u.vec->extra_ref = 0;
20260             continue;
20261 
20262 #ifdef USE_STRUCTS
20263         case T_STRUCT:
20264             if (NULL == register_pointer(ptable, p->u.strct) )
20265                 continue;
20266             check_extra_ref_in_vector(&p->u.strct->member[0], struct_size(p->u.strct));
20267             p->u.vec->extra_ref = 0;
20268             continue;
20269 #endif /* USE_STRUCTS */
20270 
20271         case T_MAPPING:
20272             if (NULL == register_pointer(ptable, p->u.map) ) continue;
20273             walk_mapping(
20274               p->u.map,
20275               check_extra_ref_in_mapping_filter,
20276               (void *)((p_int)p->u.map->num_values)
20277             );
20278             continue; /* no extra ref count implemented */
20279         }
20280     }
20281 } /* check_extra_ref_in_vector() */
20282 
20283 /*-------------------------------------------------------------------------*/
20284 void
check_a_lot_ref_counts(program_t * search_prog)20285 check_a_lot_ref_counts (program_t *search_prog)
20286 
20287 /* Loop through every object and variable in the game and check all
20288  * reference counts. This will surely take some time and should be
20289  * used only for debugging.
20290  *
20291  * If <search_prog> is set, the function will just count the references
20292  * and print the information for the given program, if found.
20293  *
20294  * The function must be called after removing all destructed objects.
20295  *
20296  * TODO: No extra_refs implemented in mappings.
20297  * TODO: Put this code somewhere else.
20298  */
20299 
20300 {
20301     object_t *ob;
20302 
20303     check_a_lot_ref_counts_search_prog = search_prog;
20304 
20305     /* Pass 1: Compute the ref counts.
20306      *
20307      * The pointer table keeps track of objects already visited,
20308      * eliminating the need for a separate pass to clear the
20309      * ref counts.
20310      */
20311     ptable = new_pointer_table();
20312     if (!ptable)
20313     {
20314         debug_message("%s Out of memory while checking all refcounts.\n"
20315                      , time_stamp());
20316         return;
20317     }
20318 
20319     /* List of all objects.
20320      */
20321     for (ob = obj_list; ob; ob = ob->next_all)
20322     {
20323         if (ob->flags & O_DESTRUCTED)
20324         {
20325             /* This shouldn't happen
20326              * TODO: remove check? enclose in #ifdef DEBUG? */
20327             debug_message("%s Found destructed object '%s' where it shouldn't "
20328                           "be.\n", time_stamp(), get_txt(ob->name));
20329             continue;
20330         }
20331         if (O_VAR_SWAPPED(ob))
20332             load_ob_from_swap(ob);
20333         count_extra_ref_in_vector(ob->variables, (size_t)ob->extra_num_variables);
20334         count_extra_ref_in_object(ob);
20335     }
20336 
20337     if (master_ob)
20338         master_ob->extra_ref++;
20339 
20340     if (d_flag > 3)
20341     {
20342         debug_message("%s obj_list evaluated\n", time_stamp());
20343     }
20344 
20345     /* The current stack.
20346      */
20347     count_extra_ref_in_vector(VALUE_STACK, (size_t)(inter_sp - VALUE_STACK + 1));
20348     if (d_flag > 3)
20349     {
20350         debug_message("%s stack evaluated\n", time_stamp());
20351     }
20352 
20353 
20354     /* Other variables and lists.
20355      */
20356     count_extra_ref_from_call_outs();
20357     count_extra_ref_from_wiz_list();
20358     count_simul_efun_extra_refs(ptable);
20359     count_comm_extra_refs();
20360 
20361 #ifdef TRACE_CODE
20362     {
20363         int j;
20364 
20365         for (j = TOTAL_TRACE_LENGTH; --j >= 0; )
20366         {
20367             if ( NULL != (ob = previous_objects[j]) )
20368             {
20369                 count_extra_ref_in_object(ob);
20370             }
20371         }
20372     }
20373 #endif
20374 
20375     count_extra_ref_in_vector(&indexing_quickfix, 1);
20376     count_extra_ref_in_vector(&last_indexing_protector, 1);
20377     null_vector.extra_ref++;
20378     count_extra_ref_in_vector(driver_hook, NUM_DRIVER_HOOKS);
20379 
20380     /* Done with the counting */
20381     free_pointer_table(ptable);
20382 
20383     /* Was that all for this time? */
20384     if (search_prog)
20385         return;
20386 
20387     /* Pass 3: Check the ref counts.
20388      *
20389      * The (new) pointer table is used as before.
20390      */
20391     ptable = new_pointer_table();
20392     if (!ptable)
20393     {
20394         debug_message("%s Out of memory while checking all refcounts.\n"
20395                      , time_stamp());
20396         return;
20397     }
20398 
20399     for (ob = obj_list; ob; ob = ob->next_all) {
20400         if (ob->flags & O_DESTRUCTED)  /* shouldn't happen */
20401             continue;
20402 
20403         if (ob->ref != ob->extra_ref)
20404         {
20405              debug_message("%s Bad ref count in object %s: listed %"
20406                            PRIdPINT" - counted %"PRIdPINT"\n"
20407                           , time_stamp(), get_txt(ob->name)
20408                           , ob->ref, ob->extra_ref);
20409         }
20410         else if ( !(ob->flags & O_SWAPPED) )
20411         {
20412             if (ob->prog->ref != ob->prog->extra_ref)
20413             {
20414                 /* an inheriting file might be swapped */
20415                 if (time_to_swap + 1 > 0
20416                  && ob->prog->ref > ob->prog->extra_ref)
20417                 {
20418                     debug_message("%s high ref count in prog %s: "
20419                                   "listed %"PRIdPINT" - counted %"PRIdPINT"\n"
20420                                  , time_stamp()
20421                                  , get_txt(ob->prog->name), ob->prog->ref
20422                                  , ob->prog->extra_ref);
20423                 }
20424                 else
20425                 {
20426                     check_a_lot_ref_counts(ob->prog);
20427                     debug_message("%s Bad ref count in prog %s: "
20428                                   "listed %"PRIdPINT" - counted %"PRIdPINT"\n"
20429                                  , time_stamp()
20430                                  , get_txt(ob->prog->name)
20431                                  , ob->prog->ref, ob->prog->extra_ref);
20432                 }
20433             }
20434         } /* !SWAPPED */
20435         check_extra_ref_in_vector(ob->variables, ob->extra_num_variables);
20436     } /* for */
20437 
20438     check_extra_ref_in_vector(VALUE_STACK, (size_t)(inter_sp - VALUE_STACK + 1));
20439 
20440     free_pointer_table(ptable);
20441 } /* check_a_lot_of_ref_counts() */
20442 
20443 /*-------------------------------------------------------------------------*/
20444 
20445 #endif /* DEBUG */
20446 
20447 
20448 /*=========================================================================*/
20449 
20450 /*                             E F U N S                                   */
20451 
20452 /*-------------------------------------------------------------------------*/
20453 /* (Re)define a couple a macros for the efuns below
20454  */
20455 
20456 #undef ERROR
20457 #define ERROR(s) {inter_sp = sp; errorf(s);}
20458 
20459 /*-------------------------------------------------------------------------*/
20460 svalue_t *
v_apply(svalue_t * sp,int num_arg)20461 v_apply (svalue_t *sp, int num_arg)
20462 
20463 /* EFUN apply()
20464  *
20465  *     mixed apply(mixed|closure cl, ...)
20466  *
20467  * Call the closure <cl> and pass it all the extra arguments
20468  * given in the call. If the last argument is an array, it
20469  * is flattened, ie. passed as a bunch of single arguments.
20470  * TODO: Use the MudOS-Notation '(*f)(...)' as alternative.
20471  */
20472 
20473 {
20474     svalue_t *args;
20475 
20476     args = sp -num_arg +1;
20477 
20478     if (args->type != T_CLOSURE)
20479     {
20480         /* Not a closure: pop the excess args and return <cl>
20481          * as result.
20482          */
20483 
20484         while (--num_arg)
20485             free_svalue(sp--);
20486         return sp;
20487     }
20488 
20489     if (sp->type == T_POINTER)
20490     {
20491         /* The last argument is an array: flatten it */
20492 
20493         vector_t *vec;  /* the array */
20494         svalue_t *svp;  /* pointer into the array */
20495         long i;              /* (remaining) vector size */
20496 
20497         vec = sp->u.vec;
20498         i = (long)VEC_SIZE(vec);
20499         num_arg += i - 1;
20500 
20501         /* Check if the target closure can handle
20502          * all the arguments without overflowing the stack.
20503          */
20504         switch( (sp - num_arg + i)->x.closure_type )
20505         {
20506         default:
20507             if ((sp - num_arg + i)->x.closure_type >= 0)
20508                 errorf("Uncallable closure in apply().\n");
20509             /* else: operator/sefun/efun closure: FALLTHROUGH */
20510         case CLOSURE_LFUN:
20511         case CLOSURE_LAMBDA:
20512         case CLOSURE_BOUND_LAMBDA:
20513             if (num_arg + (sp - VALUE_STACK) < EVALUATOR_STACK_SIZE)
20514                 break;
20515             errorf("VM Stack overflow: %zu too high.\n",
20516                  (size_t)(num_arg + (sp - VALUE_STACK) - EVALUATOR_STACK_SIZE) );
20517             break;
20518         }
20519 
20520         /* Push the array elements onto the stack, overwriting the
20521          * array value itself.
20522          */
20523         if (deref_array(vec))
20524         {
20525             for (svp = vec->item; --i >= 0; )
20526             {
20527                 if (destructed_object_ref(svp))
20528                 {
20529                     put_number(sp, 0);
20530                     sp++;
20531                     svp++;
20532                 }
20533                 else
20534                     assign_svalue_no_free(sp++, svp++);
20535             }
20536         }
20537         else
20538         {
20539             /* The array will be freed, so use a faster function */
20540             for (svp = vec->item; --i >= 0; ) {
20541                 if (destructed_object_ref(svp))
20542                 {
20543                     put_number(sp, 0);
20544                     sp++;
20545                     svp++;
20546                 }
20547                 else
20548                     transfer_svalue_no_free(sp++, svp++);
20549             }
20550             free_empty_vector(vec);
20551         }
20552 
20553         sp--; /* undo the last extraneous sp++ */
20554     }
20555 
20556     /* Prepare to call the closure */
20557 
20558     args = sp -num_arg +1;
20559 
20560     /* No external calls may be done when this object is
20561      * destructed.
20562      */
20563     if (current_object->flags & O_DESTRUCTED)
20564     {
20565         sp = _pop_n_elems(num_arg, sp);
20566         push_number(sp, 0);
20567         inter_sp = sp;
20568         warnf("Call from destructed object '%s' ignored.\n"
20569              , get_txt(current_object->name));
20570         return sp;
20571     }
20572 
20573     inter_sp = sp;
20574 
20575 
20576     /* Call the closure and push the result.
20577      * Note that the closure might destruct itself.
20578      */
20579     call_lambda(args, num_arg - 1);
20580     sp = args;
20581     free_svalue(sp);
20582     *sp = sp[1];
20583 
20584     return sp;
20585 } /* v_apply() */
20586 
20587 /*-------------------------------------------------------------------------*/
20588 svalue_t *
v_funcall(svalue_t * sp,int num_arg)20589 v_funcall (svalue_t *sp, int num_arg)
20590 
20591 /* EFUN funcall()
20592  *
20593  *   mixed funcall(mixed|closure cl, mixed arg ...)
20594  *
20595  * Evaluates the closure. The extra args will be passed as args
20596  * to the closure. If cl is not a closure, it will simply be
20597  * returned.
20598  */
20599 
20600 {
20601     svalue_t *args;
20602 
20603     args = sp -num_arg +1;
20604 
20605     if (args->type == T_CLOSURE)
20606     {
20607         /* No external calls may be done when this object is
20608          * destructed.
20609          */
20610         if (current_object->flags & O_DESTRUCTED) {
20611             sp = _pop_n_elems(num_arg, sp);
20612             push_number(sp, 0);
20613             inter_sp = sp;
20614             warnf("Call from destructed object '%s' ignored.\n"
20615                  , get_txt(current_object->name));
20616             return sp;
20617         }
20618 
20619         /* Call the closure and push the result.
20620          * Note that the closure might destruct itself.
20621          */
20622         call_lambda(args, num_arg - 1);
20623         sp = args;
20624         free_svalue(sp);
20625         *sp = sp[1];
20626     }
20627     else
20628     {
20629         /* Not a closure: pop the excess args and return <cl>
20630          * as result.
20631          */
20632 
20633         while (--num_arg)
20634             free_svalue(sp--);
20635     }
20636 
20637     return sp;
20638 } /* v_funcall() */
20639 
20640 /*-------------------------------------------------------------------------*/
20641 static svalue_t *
int_call_resolved(Bool b_use_default,svalue_t * sp,int num_arg)20642 int_call_resolved (Bool b_use_default, svalue_t *sp, int num_arg)
20643 
20644 /* EFUN call_resolved(), call_direct_resolved()
20645  *
20646  *   int call_resolved(mixed & result, object ob, string func, ...)
20647  *   int call_direct_resolved(mixed & result, object ob, string func, ...)
20648  *
20649  * Similar to call_other(_direct)(). If ob->func() is defined and publicly
20650  * accessible, any of the optional extra arguments are passed to
20651  * ob->func(...). The result of that function call is stored in
20652  * result, which must be passed by reference.
20653  *
20654  * If the current object is already destructed, or the ob does not
20655  * exist, or ob does not define a public accessible function named
20656  * func, call_direct_resolved() returns 0 as failure code, else 1 for
20657  * success.
20658  *
20659  * If the current object is already destructed, or the ob does not
20660  * exist, or ob does not define a public accessible function named
20661  * func and no default method is available, call_resolved() returns 0.
20662  * If the call succeeded, the efun returns 1; if the call succeeded
20663  * through a default method, the efun returns -1.
20664  *
20665  * ob can also be a file_name. If a string is passed for ob, and
20666  * no object with that name does exist, an error occurs.
20667  */
20668 
20669 {
20670     svalue_t *arg;
20671     object_t *ob;
20672     int rc;
20673 
20674     arg = sp - num_arg + 1;
20675 
20676     /* Test the arguments */
20677     if (arg[1].type == T_NUMBER)
20678         ob = NULL;
20679     else if (arg[1].type == T_OBJECT)
20680         ob = arg[1].u.ob;
20681     else /* it's a string */
20682     {
20683         ob = get_object(arg[1].u.str);
20684         if (!ob)
20685             errorf("call_resolved() failed: can't get object '%s'.\n"
20686                  , get_txt(arg[1].u.str));
20687     }
20688 
20689     /* No external calls may be done when this object is
20690      * destructed.
20691      * Similar, don't do calls if the target object is destructed.
20692      */
20693     if (current_object->flags & O_DESTRUCTED
20694      || NULL == ob)
20695     {
20696         sp = _pop_n_elems(num_arg, sp);
20697         push_number(sp, 0);
20698         inter_sp = sp;
20699         warnf("Call from destructed object '%s' ignored.\n"
20700              , get_txt(current_object->name));
20701         return sp;
20702     }
20703 
20704     /* Handle traceing. */
20705     if (TRACEP(TRACE_CALL_OTHER) && TRACE_IS_INTERACTIVE())
20706     {
20707         if (!++traceing_recursion)
20708         {
20709             inter_sp = sp;
20710             do_trace("Call other ", get_txt(arg[2].u.str), "\n");
20711         }
20712         traceing_recursion--;
20713     }
20714 
20715     /* Send the remaining arguments to the function.
20716      */
20717     if (ob == master_ob)
20718         b_use_default = MY_FALSE;
20719     rc = int_apply(arg[2].u.str, ob, num_arg-3, MY_FALSE, b_use_default);
20720     if (rc == APPLY_NOT_FOUND)
20721     {
20722         /* Function not found */
20723         if (b_use_default)
20724             sp -= num_arg-3;
20725         else
20726             sp = _pop_n_elems(num_arg-3, sp);
20727         sp = _pop_n_elems(2, sp);
20728         free_svalue(sp);
20729         put_number(sp, 0);
20730         return sp;
20731     }
20732 
20733     /* The result of the function call is on the stack. But, so
20734      * is the function name and object that was called.
20735      * These have to be removed.
20736      */
20737     sp = inter_sp;
20738     transfer_svalue(arg, sp--);  /* Copy the function call result */
20739     sp = _pop_n_elems(2, sp);     /* Remove old arguments to call_solved */
20740     free_svalue(sp);             /* Free the lvalue */
20741     put_number(sp, rc == APPLY_FOUND ? 1 : -1);
20742 
20743     return sp;
20744 } /* f_call_resolved() */
20745 
20746 /*-------------------------------------------------------------------------*/
20747 svalue_t *
v_call_resolved(svalue_t * sp,int num_arg)20748 v_call_resolved (svalue_t *sp, int num_arg)
20749 
20750 /* EFUN call_resolved()
20751  *
20752  * This is just a wrapper around the real implementation.
20753  */
20754 
20755 {
20756     return int_call_resolved(MY_TRUE, sp, num_arg);
20757 } /* v_call_resolved() */
20758 
20759 /*-------------------------------------------------------------------------*/
20760 svalue_t *
v_call_direct_resolved(svalue_t * sp,int num_arg)20761 v_call_direct_resolved (svalue_t *sp, int num_arg)
20762 
20763 /* EFUN call_direct_resolved()
20764  *
20765  * This is just a wrapper around the real implementation.
20766  */
20767 
20768 {
20769     return int_call_resolved(MY_FALSE, sp, num_arg);
20770 } /* v_call_direct_resolved() */
20771 
20772 /*-------------------------------------------------------------------------*/
20773 svalue_t *
f_get_eval_cost(svalue_t * sp)20774 f_get_eval_cost (svalue_t *sp)
20775 
20776 /* EFUN get_eval_cost()
20777  *
20778  *   int get_eval_cost()
20779  *
20780  * Returns the remaining evaluation cost the current
20781  * execution (the current command) may use up.
20782  *
20783  * It starts at a driver given high value (__MAX_EVAL_COST__) and
20784  * is reduced with each executed statement.
20785  */
20786 
20787 {
20788     push_number(sp, (max_eval_cost ? max_eval_cost : PINT_MAX) - eval_cost);
20789 
20790     return sp;
20791 } /* f_get_eval_cost() */
20792 
20793 /*-------------------------------------------------------------------------*/
20794 svalue_t *
f_set_this_object(svalue_t * sp)20795 f_set_this_object (svalue_t *sp)
20796 
20797 /* EFUN set_this_object()
20798  *
20799  *   void set_this_object(object object_to_pretend_to_be);
20800  *
20801  * Set this_object() to <object_to_pretend_to_be>. A privilege
20802  * violation ("set_this_object", this_object(), object_to_be)
20803  * occurs.
20804  *
20805  * It changes the result of this_object() in the using function, and
20806  * the result of previous_object() in functions called in other
20807  * objects by call_other(). Its effect will remain till there is a
20808  * return of an external function call, or another call of
20809  * set_this_object(). While executing code in the master
20810  * object's program or the primary simul_efun object's program,
20811  * set_this_object() is granted even if this_object() is altered by
20812  * set_this_object(). This does not apply to functions inherited from
20813  * other programs.
20814  *
20815  * Use it with extreme care to avoid inconsistencies.  After a call of
20816  * set_this_object(), some LPC-constructs might behave in an odd
20817  * manner, or even crash the system. In particular, using global
20818  * variables or calling local functions (except by call_other) is
20819  * illegal.
20820  *
20821  * With the current implementation, global variables can be accessed,
20822  * but this is not guaranteed to work in subsequent versions.
20823  *
20824  * Allowed are call_other, map functions, access of local variables
20825  * (which might hold array pointers to a global array), simple
20826  * arithmetic and the assignment operators.
20827  */
20828 
20829 {
20830 
20831     if (sp->u.ob != current_object)
20832     {
20833         if ((master_ob != NULL && current_variables == master_ob->variables)
20834          || (simul_efun_object != NULL && current_variables == simul_efun_object->variables)
20835          || privilege_violation(STR_SET_THIS_OBJECT, sp, sp))
20836         {
20837             struct control_stack *p;
20838 
20839             /* Find the 'extern_call' entry in the call stack which
20840              * determined the current this_object().
20841              */
20842             for (p = csp; !p->extern_call; p--) NOOP;
20843 
20844             p->extern_call |= CS_PRETEND;
20845             p->pretend_to_be = current_object = sp->u.ob;
20846         }
20847     }
20848 
20849     free_svalue(sp);
20850     sp--;
20851     return sp;
20852 } /* f_set_this_object() */
20853 
20854 /*-------------------------------------------------------------------------*/
20855 svalue_t *
f_trace(svalue_t * sp)20856 f_trace (svalue_t *sp)
20857 
20858 /* EFUN trace()
20859  *
20860  *   int trace(int traceflags)
20861  *
20862  * Sets the trace flags and returns the old trace flags. When
20863  * tracing is on, a lot of information is printed during
20864  * execution and too much output can crash your connection or
20865  * even the whole driver.
20866  *
20867  * Tracing is done on a per-connection basis: each interactive(!)
20868  * user may specifiy its own tracelevel and -prefix. Each gets the
20869  * traceoutput for just the code executed during the evaluation
20870  * of the commands he entered.
20871  *
20872  * The trace bits are:
20873  *
20874  *   TRACE_NOTHING     (  0): stop tracing.
20875  *
20876  *   TRACE_CALL        (  1): trace all calls to lfuns.
20877  *   TRACE_CALL_OTHER  (  2): trace call_others()s.
20878  *   TRACE_RETURN      (  4): trace function returns.
20879  *   TRACE_ARGS        (  8): print function arguments and results.
20880  *   TRACE_EXEC        ( 16): trace all executed instructions.
20881  *   TRACE_HEART_BEAT  ( 32): trace heartbeat code.
20882  *   TRACE_APPLY       ( 64): trace driver applies.
20883  *   TRACE_OBJNAME     (128): print the object names.
20884  *
20885  * TRACE_EXEC and TRACE_HEART_BEAT should be avoided as they cause massive
20886  * output! TRACE_OBJNAME should be avoided when you know what you trace.
20887  *
20888  * The master-lfun valid_trace() is called to verify the
20889  * usage of this efun.
20890  */
20891 
20892 {
20893     int ot;
20894     interactive_t *ip;
20895 
20896     ot = -1;
20897 
20898     /* If the command_giver is allowed to do so... */
20899     if (command_giver
20900      && O_SET_INTERACTIVE(ip, command_giver))
20901     {
20902         svalue_t *arg;
20903 
20904         assign_eval_cost_inl();
20905         inter_sp = sp;
20906         push_ref_string(inter_sp, STR_TRACE);
20907         push_number(inter_sp, sp->u.number);
20908         arg = apply_master(STR_VALID_TRACE, 2);
20909         if (arg)
20910         {
20911             /* ... then set the new tracelevel */
20912             if (arg->type != T_NUMBER || arg->u.number != 0)
20913             {
20914                 ot = ip->trace_level;
20915                 trace_level |=
20916                   ip->trace_level = sp->u.number;
20917             }
20918         }
20919     }
20920 
20921     /* Return the old level */
20922     sp->u.number = ot;
20923     SET_TRACE_EXEC;
20924     return sp;
20925 } /* f_trace() */
20926 
20927 /*-------------------------------------------------------------------------*/
20928 svalue_t *
f_traceprefix(svalue_t * sp)20929 f_traceprefix (svalue_t *sp)
20930 
20931 /* EFUN traceprefix()
20932  *
20933  *   string traceprefix(string prefix)
20934  *   string traceprefix(int dummy)
20935  *
20936  * If called with a string, only objects matching this prefix will be traced.
20937  * The string must not contain a leading "/" because the object names are
20938  * stored internally without it. If called with a number, the traceprefix will
20939  * be ignored and all objects will be traced. Returns the last traceprefix or
20940  * 0 if there wasn't any.
20941  *
20942  * The master-lfun valid_trace() is called to verify the usage of this
20943  * efun.
20944  */
20945 
20946 {
20947     string_t *old;
20948     interactive_t *ip;
20949 
20950     old = NULL;
20951 
20952     /* If the command_giver is allowed to do that... */
20953     if (command_giver
20954      && O_SET_INTERACTIVE(ip, command_giver))
20955     {
20956         svalue_t *arg;
20957 
20958         inter_sp = sp;
20959         push_ref_string(inter_sp, STR_TRACEPREFIX);
20960         inter_sp++; assign_svalue_no_free(inter_sp, sp);
20961         assign_eval_cost_inl();
20962         arg = apply_master(STR_VALID_TRACE,2);
20963         if (arg)
20964         {
20965             /* ... then so shall it be */
20966             if (arg && (arg->type != T_NUMBER || arg->u.number))
20967             {
20968                 old = ip->trace_prefix;
20969                 if (sp->type == T_STRING)
20970                 {
20971                     ip->trace_prefix = make_tabled_from(sp->u.str);
20972                       /* tabled for faster comparisons */
20973                 }
20974                 else
20975                     ip->trace_prefix = NULL;
20976             }
20977         }
20978     }
20979 
20980     free_svalue(sp);
20981 
20982     /* Return the old prefix */
20983     if (old)
20984         put_string(sp, old);
20985     else
20986         put_number(sp, 0);
20987     return sp;
20988 } /* f_traceprefix() */
20989 
20990 /***************************************************************************/
20991