/
MudOS_0.9.19/bin/
MudOS_0.9.19/doc/concepts/
MudOS_0.9.19/doc/driver/
MudOS_0.9.19/doc/efuns/bitstrings/
MudOS_0.9.19/doc/efuns/buffers/
MudOS_0.9.19/doc/efuns/communication/
MudOS_0.9.19/doc/efuns/core/
MudOS_0.9.19/doc/efuns/mappings/
MudOS_0.9.19/doc/efuns/math/
MudOS_0.9.19/doc/efuns/security/
MudOS_0.9.19/doc/lpc/constructs/
MudOS_0.9.19/doc/lpc/types/
MudOS_0.9.19/doc/platforms/
MudOS_0.9.19/etc/
MudOS_0.9.19/mudlib/
MudOS_0.9.19/mudlib/lil/
MudOS_0.9.19/mudlib/lil/clone/
MudOS_0.9.19/mudlib/lil/command/
MudOS_0.9.19/mudlib/lil/data/
MudOS_0.9.19/mudlib/lil/etc/
MudOS_0.9.19/mudlib/lil/include/
MudOS_0.9.19/mudlib/lil/inherit/
MudOS_0.9.19/mudlib/lil/inherit/master/
MudOS_0.9.19/mudlib/lil/log/
MudOS_0.9.19/mudlib/lil/single/
MudOS_0.9.19/mudlib/lil/u/
MudOS_0.9.19/src/testsuite/
MudOS_0.9.19/src/testsuite/clone/
MudOS_0.9.19/src/testsuite/command/
MudOS_0.9.19/src/testsuite/data/
MudOS_0.9.19/src/testsuite/etc/
MudOS_0.9.19/src/testsuite/include/
MudOS_0.9.19/src/testsuite/inherit/
MudOS_0.9.19/src/testsuite/inherit/master/
MudOS_0.9.19/src/testsuite/log/
MudOS_0.9.19/src/testsuite/single/
MudOS_0.9.19/src/testsuite/single/efuns/
MudOS_0.9.19/src/testsuite/u/
#include "efuns.h"
#include "replace_program.h"
/*
 * replace_program.c
 * replaces the program in a running object with one of the programs
 * it inherits, in order to save memory.
 * Ported from Amylaars LP 3.2 driver 
 */

extern int tot_alloc_object_size;

struct replace_ob *obj_list_replace = (struct replace_ob *)0;

void replace_programs() {
    struct replace_ob *r_ob, *r_next;
    int i,j;
    struct svalue *svp;
#ifdef DEBUG
    if (d_flag)
	debug_message("start of replace_programs\n");
#endif
    for (r_ob=obj_list_replace; r_ob; r_ob = r_next) {
	struct program *old_prog;

	if (r_ob->ob->flags & O_SWAPPED)
	    load_ob_from_swap(r_ob->ob);
        i = r_ob->ob->prog->p.i.num_variables - r_ob->new_prog->p.i.num_variables;
#ifdef DEBUG
	if (d_flag)
	    debug_message("%d less variables\n",i);
#endif
        tot_alloc_object_size -= i * sizeof(struct svalue[1]);
        svp = r_ob->ob->variables;
        j = r_ob->var_offset;
        i -= j;
#ifdef DEBUG
	if (d_flag)
	    debug_message("freeing %d variables:\n",j);
#endif
        while (--j >= 0) free_svalue(svp++);
#ifdef DEBUG
	if (d_flag)
	    debug_message("freed.\n");
#endif
        for ( j=0; j<(int)r_ob->new_prog->p.i.num_variables; j++)
            r_ob->ob->variables[j] = svp[j];
        svp += j;
#ifdef DEBUG
	if (d_flag)
	    debug_message("freeing %d variables:\n",i);
#endif
        while (--i >= 0) free_svalue(svp++);
#ifdef DEBUG
	if (d_flag)
	    debug_message("freed.\n");
#endif
        r_ob->new_prog->p.i.ref++;
	old_prog = r_ob->ob->prog;
        r_ob->ob->prog = r_ob->new_prog;
	r_ob->ob->flags |= O_CLONE;
	r_ob->ob->flags |= O_VIRTUAL;
        r_next = r_ob->next;
        free_prog(old_prog, 1);
#ifdef DEBUG
	if (d_flag)
	    debug_message("program freed.\n");
#endif
#ifndef NO_SHADOWS
	if (r_ob->ob->shadowing) {
	    /* The master couldn't decide if it's a legal shadowing before
	     * the program was actually replaced. It is possible that the
	     * blueprint to the replacing program is already destructed,
	     * and it's source changed.
	     * On the other hand, if we called the master now, all kind of
	     * volatile data structures could result, even new entries for
	     * obj_list_replace. This would eventually require to reference it,
	     * and all the lrpp's , in check_a_lot_ref_counts() and
	     * garbage_collection() . Being able to use replace_program() in
	     * shadows is hardly worth this effort. Thus, we simply stop
	     * the shadowing.
	     */
	    r_ob->ob->shadowing->shadowed = r_ob->ob->shadowed;
	    if (r_ob->ob->shadowed) {
		r_ob->ob->shadowed->shadowing = r_ob->ob->shadowing;
		r_ob->ob->shadowed = 0;
	    }
	    r_ob->ob->shadowing = 0;
	}
#endif
        FREE((char *)r_ob);
    }
    obj_list_replace = (struct replace_ob *)0;
#ifdef DEBUG
    if (d_flag)
	debug_message("end of replace_programs\n");
#endif
}

#ifdef F_REPLACE_PROGRAM
struct program *search_inherited(str, prg, offpnt)
    char *str;
    struct program *prg;
    int *offpnt;
{
    struct program *tmp;
    int i;

#ifdef DEBUG
    if (d_flag) {
	debug_message("search_inherited started\n");
	debug_message("searching for PRG(%s) in PRG(%s)\n",str,prg->name);
	debug_message("num_inherited=%d\n", prg->p.i.num_inherited);
    }
#endif
    for (i=0; i < (int)prg->p.i.num_inherited; i++) {
#ifdef DEBUG
	if (d_flag) {
	    debug_message("index %d:\n",i);
	    debug_message("checking PRG(%s)\n", prg->p.i.inherit[i].prog->name);
	}
#endif
	if ( strcmp(str, prg->p.i.inherit[i].prog->name ) == 0 ) {
#ifdef DEBUG
	    if (d_flag)
		debug_message("match found\n");
#endif
	    *offpnt = prg->p.i.inherit[i].variable_index_offset;
	    return prg->p.i.inherit[i].prog;
	} else if ( tmp = search_inherited(str, prg->p.i.inherit[i].prog,
	  offpnt) )
	{
#ifdef DEBUG
	    if (d_flag)
		debug_message("deferred match found\n");
#endif
	    *offpnt += prg->p.i.inherit[i].variable_index_offset;
	    return tmp;
	}
    }
#ifdef DEBUG
	if (d_flag)
	    debug_message("search_inherited failed\n");
#endif
    return (struct program *)0;
}

struct replace_ob *retrieve_replace_program_entry() {
    struct replace_ob *r_ob;

    for (r_ob = obj_list_replace; r_ob; r_ob = r_ob->next) {
	if (r_ob->ob == current_object) {
	    return r_ob;
	}
    }
    return 0;
}

void
f_replace_program(num_arg, instruction)
        int num_arg;
        int instruction;
{
struct replace_ob *tmp;
int name_len;
char *name,*xname;
struct program *new_prog;
int var_offset;

	if(sp->type!=T_STRING)
          bad_arg(1,instruction);
#ifdef DEBUG
	if (d_flag)
	    debug_message("replace_program called\n");
#endif
	if (!current_object)
	    error("replace_program called with no current object\n");
	if (strcmp(current_object->name, query_simul_efun_file_name())==0)
	    error("replace_program on simul_efun object\n");
	name_len = strlen(sp->u.string);
	name = (char *)MALLOC(name_len+3);
        xname=name;
	strcpy(name,sp->u.string);
	if (name[name_len-2] != '.' || name[name_len-1] != 'c')
	    strcat(name,".c");
	if (*name == '/')
	    name++;
	new_prog = search_inherited(name, current_object->prog, &var_offset);
        FREE(xname);
	if (!new_prog) {
	    error("program to replace the current with has to be inherited\n");
	}
	if ( !(tmp = retrieve_replace_program_entry()) )
	{
	    tmp = (struct replace_ob *)XALLOC(sizeof *tmp);
	    tmp->ob = current_object;
	    tmp->next = obj_list_replace;
	    obj_list_replace = tmp;
	}
	tmp->new_prog = new_prog;
	tmp->var_offset = var_offset;
#ifdef DEBUG
	if (d_flag)
	    debug_message("replace_program finished\n");
#endif
}

#endif