/
dgd-net/
dgd-net/doc/
dgd-net/doc/kfun/
dgd-net/src/host/unix/
dgd-net/src/kfun/
# include "dgd.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "xfloat.h"
# include "interpret.h"
# include "data.h"
# include "ed.h"
# include "call_out.h"
# include "comm.h"
# include "node.h"
# include "compile.h"

/*
 * NAME:	call_driver_object()
 * DESCRIPTION:	call a function in the driver object
 */
bool call_driver_object(func, narg)
char *func;
int narg;
{
    static object *driver;
    static Uint dcount;
    static char *driver_name;

    if (driver == (object *) NULL || dcount != driver->count) {
	if (driver_name == (char *) NULL) {
	    driver_name = conf_driver();
	}
	driver = o_find(driver_name);
	if (driver == (object *) NULL) {
	    driver = c_compile(driver_name);
	}
	dcount = driver->count;
    }
    if (!i_call(driver, func, TRUE, narg)) {
	fatal("missing function in driver object: %s", func);
    }
    return TRUE;
}

static bool swap;	/* are objects to be swapped out? */
static bool dump;	/* is the program to dump? */
static bool intr;	/* received an interrupt? */
static bool stop;	/* is the program to terminate? */

/*
 * NAME:	swapout()
 * DESCRIPTION:	indicate that objects are to be swapped out
 */
void swapout()
{
    swap = TRUE;
}

/*
 * NAME:	dump_state()
 * DESCRIPTION:	indicate that the state must be dumped
 */
void dump_state()
{
    dump = TRUE;
}

/*
 * NAME:	interrupt()
 * DESCRIPTION:	register an interrupt
 */
void interrupt()
{
    intr = TRUE;
}

/*
 * NAME:	finish()
 * DESCRIPTION:	indicate that the program must finish
 */
void finish()
{
    stop = TRUE;
}

/*
 * NAME:	dgd_main()
 * DESCRIPTION:	the main loop of DGD
 */
int dgd_main(argc, argv)
int argc;
char **argv;
{
    char buf[INBUF_SIZE];
    int size;
    object *usr;

    if (argc < 2 || argc > 3) {
	P_message("Usage: dgd config_file [dump_file]\012");	/* LF */
	return 2;
    }

    if (ec_push()) {
	warning((char *) NULL);
	fatal("error during initialization");
    }
    if (argc == 2) {
	conf_init(argv[1], (char *) NULL);
    } else {
	conf_init(argv[1], argv[2]);
    }
    ec_pop();

    while (ec_push()) {
	i_log_error(FALSE);
	i_clear();
    }

    do {
	P_getevent();
	if (intr) {
	    intr = FALSE;
	    call_driver_object("interrupt", 0);
	    i_del_value(sp++);
	}

	co_call();
	comm_flush(FALSE);

	if (!stop) {
	    usr = comm_receive(buf, &size);
	    if (usr != (object *) NULL) {
		(--sp)->type = T_STRING;
		str_ref(sp->u.string = str_new(buf, (long) size));
		if (i_call(usr, "receive_message", TRUE, 1)) {
		    i_del_value(sp++);
		}
		comm_flush(TRUE);
	    }
	}

	o_clean();

	if (!mcheck()) {
	    d_swapout(1);
	    arr_freeall();
	    mpurge();
	    mexpand();
	} else if (swap) {
	    d_swapout(1);
	    arr_freeall();
	    mpurge();
	}
	swap = FALSE;

	if (dump) {
	    d_swapsync();
	    conf_dump();
	    dump = FALSE;
	}

	sw_copy();
    } while (!stop);

    ec_pop();
    comm_finish();
    ed_finish();
    sw_finish();
    return 0;
}