/*-------------------------------------------------------------------------*/ static string_t * get_wiz_name (const char *file) /* For the filename <file> return the name of the wizard responsible * for it. This actual query is done with a master apply. * * Result is NULL or an uncounted string reference. */ { svalue_t *ret; /* Don't call the master if it isn't loaded! */ if (!master_ob) return NULL; push_c_string(inter_sp, file); ret = apply_master(STR_GET_WNAME, 1); if (ret == 0 || ret->type != T_STRING) return NULL; return ret->u.str; } /* get_wiz_name() */
/*-------------------------------------------------------------------------*/ Bool assert_simul_efun_object (void) /* (Re)load the simul_efun object and extract all information we need. * Result is TRUE if either the simul_efun object could be loaded, or if * master::get_simul_efun() did not return a string/string vector to * name the simul efun object. The result is FALSE if master::get_simul_efun() * specified a simul efun object, which couldn't be found. * * In other words: after calling assert_simul_efun_object(), the caller * still has to check if simul_efun_object is NULL. * * At the time of call, simul_efun_object must be NULL. */ { svalue_t *svp; object_t *ob; program_t *progp; CBool *visible; /* Flag for every function: visible or not */ string_t *name; int i, j, num_fun; invalidate_simul_efuns(); /* Invalidate the simul_efun information */ free_defines(); /* to prevent #defines hideing places for globals */ /* Get the name(s) of the simul_efun object. */ svp = apply_master(STR_GET_SEFUN, 0); /* If a simul_efun_object appears during the GET_SEFUN call, it * might have been due to a recursive get_simul_efun() call which may * have gotten an old backup copy. This can lead to hard-to-debug * variable and function definition inconsistencies. */ if (simul_efun_object) { printf("%s simul_efun object appeared while asking for it.\n", time_stamp()); return MY_TRUE; } if (svp == NULL) { printf("%s No simul_efun\n", time_stamp()); return MY_TRUE; } if (svp->type == T_POINTER) { simul_efun_vector = svp->u.vec; svp->type = T_NUMBER; if (VEC_SIZE(svp->u.vec)) svp = svp->u.vec->item; } if (svp->type != T_STRING) { printf("%s No simul_efun\n", time_stamp()); return MY_TRUE; } /* Make the (primary) simul_efun name */ name = del_slash(svp->u.str); if (simul_efun_file_name) free_mstring(simul_efun_file_name); simul_efun_file_name = make_tabled(name); /* Get the object and load the program */ ob = find_object(simul_efun_file_name); if (ob == NULL) { fprintf(stderr, "%s The simul_efun file %s was not loaded.\n" , time_stamp(), get_txt(simul_efun_file_name)); fprintf(stderr, "%s The function get_simul_efun() in the master must load it.\n" , time_stamp()); return MY_FALSE; } if (O_PROG_SWAPPED(ob) && load_ob_from_swap(ob) < 0) { fprintf(stderr, "%s Out of memory (unswap object '%s') ==> " "No simul_efun\n", time_stamp(), get_txt(ob->name)); return MY_TRUE; } reference_prog( (simul_efun_program = ob->prog), "get_simul_efun"); num_fun = ob->prog->num_function_names; if (num_fun == 0) return MY_TRUE; if (!simul_efunp) { simul_efunp = xalloc(sizeof (function_t) * num_fun); } else num_fun = total_simul_efun; free_defines(); /* to prevent #defines hideing places for globals */ /* locals and defines are freed now. There are still reserved words, * but it is impossible to define a function with the name being * a reserved word, thus, there will be no clashes with higher-priority * shared identifiers. */ progp = ob->prog; visible = alloca((i = ob->prog->num_functions) * sizeof(*visible)); memset(visible, 0, i); i = ob->prog->num_function_names; while (--i >= 0) visible[progp->function_names[i]] = MY_TRUE; /* The functions .num_function_names+1 .. .num_functions are not * visible by definition. */ /* Loop over the functions in the simul_efun object and * copy the salient information. */ for (i = 0; i < ob->prog->num_functions; i++) { int ix; funflag_t flags, flags2; bytecode_p funstart; mp_int fun_ix_offs, var_ix_offs; program_t *inherit_progp; function_t*funheader; if (!visible[i]) continue; ix = i; flags2 = flags = progp->functions[ix]; flags &= ~FUNSTART_MASK; /* Pinpoint the function, resolving inheritance where * necessary. */ fun_ix_offs = ix; var_ix_offs = 0; inherit_progp = progp; while (flags2 & NAME_INHERITED) { inherit_t *inheritp; inheritp = &inherit_progp->inherit[flags2 & INHERIT_MASK]; ix -= inheritp->function_index_offset; var_ix_offs += inheritp->variable_index_offset; inherit_progp = inheritp->prog; flags2 = inherit_progp->functions[ix]; } fun_ix_offs -= ix; funstart = inherit_progp->program + (flags2 & FUNSTART_MASK); funheader = inherit_progp->function_headers + FUNCTION_HEADER_INDEX(funstart); /* Don't stumble over undefined functions */ if (is_undef_function(funstart)) { flags |= NAME_UNDEFINED; } /* If the function is __INIT, pretend it's a private function */ if ( !(flags & (TYPE_MOD_STATIC|TYPE_MOD_PRIVATE|NAME_UNDEFINED)) ) { if (mstreq(funheader->name, STR_VARINIT)) flags |= TYPE_MOD_PRIVATE; } /* If the function is indeed visible, get its information */ if ( !(flags & (TYPE_MOD_STATIC|TYPE_MOD_PROTECTED|TYPE_MOD_PRIVATE|NAME_UNDEFINED)) ) { string_t *function_name; ident_t *p; unsigned char num_arg; function_name = funheader->name; num_arg = funheader->num_arg; /* Find or make the identifier for the function */ p = make_shared_identifier_mstr(function_name, I_TYPE_GLOBAL, 0); if (p->type == I_TYPE_UNKNOWN) { init_global_identifier(p, /* bVariable: */ MY_FALSE); p->next_all = all_simul_efuns; all_simul_efuns = p; } if (flags & TYPE_MOD_VARARGS) num_arg = SIMUL_EFUN_VARARGS; /* Find the proper index in simul_efunp[] */ switch(0) { default: /* TRY... */ /* Try to find a discarded sefun entry with matching * name, number of arguments and XVARARGS flag to reuse. */ if (all_discarded_simul_efun >= 0) { int last; j = all_discarded_simul_efun; while ( (j = simul_efunp[last = j].offset.next_sefun) >= 0) { if (num_arg != simul_efunp[j].num_arg || 0 != ((simul_efunp[j].flags ^ flags) & TYPE_MOD_XVARARGS) ) continue; if (!mstreq(function_name, simul_efunp[j].name)) continue; /* Found one: remove it from the 'discarded' list */ simul_efunp[last].offset.next_sefun = simul_efunp[j].offset.next_sefun; break; } if (j >= 0) break; /* switch */ } /* New simul_efun: make a new entry */ (void)ref_mstring(function_name); j = num_simul_efun++; if (num_simul_efun > num_fun) { num_fun = num_simul_efun + 12; simul_efunp = rexalloc(simul_efunp , sizeof (function_t) * num_fun ); } simul_efunp[j].name = function_name; simul_efunp[j].num_arg = num_arg; } /* switch() */ /* j now indexes the simul_efunp[] entry to use */ p->u.global.sim_efun = j; simul_efunp[j].flags = funheader->flags; simul_efunp[j].type = funheader->type; simul_efunp[j].num_locals = funheader->num_locals; /* If possible, make an entry in the simul_efun table */ if ((size_t)j < SEFUN_TABLE_SIZE) { simul_efun_table[j].funstart = funstart; simul_efun_table[j].program = inherit_progp; simul_efun_table[j].function_index_offset = fun_ix_offs; simul_efun_table[j].variable_index_offset = var_ix_offs; } } /* if (function visible) */ } /* for ( all functions) */ total_simul_efun = num_fun; simul_efun_object = ob; return MY_TRUE; } /* get_simul_efun_object() */