void c_call(int func, int num_arg) { function_t *funp; func += function_index_offset; /* * Find the function in the function table. As the * function may have been redefined by inheritance, we * must look in the last table, which is pointed to by * current_object. */ DEBUG_CHECK(func >= current_object->prog->last_inherited + current_object->prog->num_functions_defined, "Illegal function index\n"); if (current_object->prog->function_flags[func] & FUNC_UNDEFINED) error("Undefined function: %s\n", function_name(current_object->prog, func)); /* Save all important global stack machine registers */ push_control_stack(FRAME_FUNCTION); caller_type = ORIGIN_LOCAL; /* This assigment must be done after push_control_stack() */ current_prog = current_object->prog; /* * If it is an inherited function, search for the real * definition. */ csp->num_local_variables = num_arg + num_varargs; num_varargs = 0; funp = setup_new_frame(func); csp->pc = pc; /* The corrected return address */ call_program(current_prog, funp->address); }
void c_call_inherited(int inh, int func, int num_arg) { inherit_t *ip = current_prog->inherit + inh; program_t *temp_prog = ip->prog; function_t *funp; push_control_stack(FRAME_FUNCTION); caller_type = ORIGIN_LOCAL; current_prog = temp_prog; csp->num_local_variables = num_arg + num_varargs; num_varargs = 0; function_index_offset += ip->function_index_offset; variable_index_offset += ip->variable_index_offset; funp = setup_inherited_frame(func); csp->pc = pc; call_program(current_prog, funp->address); }
svalue_t * call_function_pointer (funptr_t * funp, int num_arg) { static func_t *oefun_table = efun_table - BASE; array_t *v; if (!funp->hdr.owner || (funp->hdr.owner->flags & O_DESTRUCTED)) error("Owner (/%s) of function pointer is destructed.\n", (funp->hdr.owner ? funp->hdr.owner->obname : "(null)")); setup_fake_frame(funp); if ((v=funp->hdr.args)) { check_for_destr(v); num_arg = merge_arg_lists(num_arg, v, 0); } switch (funp->hdr.type) { case FP_SIMUL: call_simul_efun(funp->f.simul.index, num_arg); break; case FP_EFUN: { int i, def; fp = sp - num_arg + 1; i = funp->f.efun.index; if (num_arg == instrs[i].min_arg - 1 && ((def = instrs[i].Default) != DEFAULT_NONE)) { if (def == DEFAULT_THIS_OBJECT) { push_object(current_object); } else { push_number(def); } num_arg++; } else if (num_arg < instrs[i].min_arg) { error("Too few arguments to efun %s in efun pointer.\n", query_instr_name(i)); } else if (num_arg > instrs[i].max_arg && instrs[i].max_arg != -1) { error("Too many arguments to efun %s in efun pointer.\n", query_instr_name(i)); } /* possibly we should add TRACE, OPC, etc here; also on eval_cost here, which is ok for just 1 efun */ { int j, n = num_arg; st_num_arg = num_arg; if (n >= 4 || instrs[i].max_arg == -1) n = instrs[i].min_arg; for (j = 0; j < n; j++) { CHECK_TYPES(sp - num_arg + j + 1, instrs[i].type[j], j + 1, i); } (*oefun_table[i])(); free_svalue(&apply_ret_value, "call_function_pointer"); if (instrs[i].ret_type == TYPE_NOVALUE) apply_ret_value = const0; else apply_ret_value = *sp--; remove_fake_frame(); return &apply_ret_value; } } case FP_LOCAL | FP_NOT_BINDABLE: { function_t *func; fp = sp - num_arg + 1; if (current_object->prog->function_flags[funp->f.local.index] & (FUNC_PROTOTYPE|FUNC_UNDEFINED)) error("Undefined lfun pointer called: %s\n", function_name(current_object->prog, funp->f.local.index)); push_control_stack(FRAME_FUNCTION); current_prog = funp->hdr.owner->prog; caller_type = ORIGIN_LOCAL; csp->num_local_variables = num_arg; func = setup_new_frame(funp->f.local.index); call_program(current_prog, func->address); break; } case FP_FUNCTIONAL: case FP_FUNCTIONAL | FP_NOT_BINDABLE: { fp = sp - num_arg + 1; push_control_stack(FRAME_FUNP); current_prog = funp->f.functional.prog; csp->fr.funp = funp; caller_type = ORIGIN_FUNCTIONAL; setup_variables(num_arg, funp->f.functional.num_local, funp->f.functional.num_arg); function_index_offset = funp->f.functional.fio; variable_index_offset = funp->f.functional.vio; call_program(funp->f.functional.prog, funp->f.functional.offset); break; } default: error("Unsupported function pointer type.\n"); } free_svalue(&apply_ret_value, "call_function_pointer"); apply_ret_value = *sp--; remove_fake_frame(); return &apply_ret_value; }