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 ¤t_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 *)¤t_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 ¤t_object->variables[num];
5961 /* TODO: Why not '¤t_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(¤t_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(¤t_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(¤t_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 = ¤t_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(¤t_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(¤t_lambda);
7527 put_number(¤t_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(¤t_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 = ¤t_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