# include "dgd.h" # include "str.h" # include "array.h" # include "object.h" # include "xfloat.h" # include "interpret.h" # include "data.h" # include "editor.h" # include "call_out.h" # include "comm.h" # include "node.h" # include "compile.h" static uindex dindex; /* driver object index */ static Uint dcount; /* driver object count */ static sector fragment; /* swap fragment parameter */ static bool rebuild; /* rebuild swapfile? */ bool intr; /* received an interrupt? */ /* * NAME: call_driver_object() * DESCRIPTION: call a function in the driver object */ bool call_driver_object(f, func, narg) frame *f; char *func; int narg; { object *driver; char *driver_name; if (dindex == UINDEX_MAX || dcount != (driver=OBJR(dindex))->count || !(driver->flags & O_DRIVER)) { driver_name = conf_driver(); driver = o_find(driver_name, OACC_READ); if (driver == (object *) NULL) { driver = c_compile(f, driver_name, (object *) NULL, (string *) NULL, FALSE); } dindex = driver->index; dcount = driver->count; } if (!i_call(f, driver, (array *) NULL, func, strlen(func), TRUE, narg)) { fatal("missing function in driver object: %s", func); } return TRUE; } /* * NAME: interrupt() * DESCRIPTION: register an interrupt */ void interrupt() { intr = TRUE; } /* * NAME: endthread() * DESCRIPTION: clean up after a thread has terminated */ void endthread() { comm_flush(); if (ext_cleanup != (void (*) P((void))) NULL) { (*ext_cleanup)(); } d_export(); o_clean(); i_clear(); ed_clear(); ec_clear(); co_swapcount(d_swapout(fragment)); if (stop) { if (ext_finish != (void (*) P((void))) NULL) { (*ext_finish)(); } comm_finish(); ed_finish(); # ifdef DEBUG swap = 1; # endif } if (swap || !m_check()) { /* * swap out everything and possibly extend the static memory area */ d_swapout(1); arr_freeall(); m_purge(); swap = FALSE; } if (dump) { /* * create a state dump */ d_swapsync(); conf_dump(); dump = FALSE; rebuild = TRUE; } if (stop) { sw_finish(); m_finish(); exit(0); } } /* * NAME: errhandler() * DESCRIPTION: default error handler */ void errhandler(f, depth) frame *f; Int depth; { i_runtime_error(f, (Int) 0); } /* * NAME: dgd_main() * DESCRIPTION: the main loop of DGD */ int dgd_main(argc, argv) int argc; char **argv; { Uint rtime, timeout; unsigned short rmtime, mtime; if (argc < 2 || argc > 3) { P_message("Usage: dgd config_file [dump_file]\012"); /* LF */ return 2; } /* initialize */ dindex = UINDEX_MAX; swap = dump = rebuild = intr = stop = FALSE; rtime = 0; if (!conf_init(argv[1], (argc == 3) ? argv[2] : (char *) NULL, &fragment)) { return 2; /* initialization failed */ } for (;;) { /* interrupts */ if (intr) { intr = FALSE; if (!ec_push((ec_ftn) errhandler)) { call_driver_object(cframe, "interrupt", 0); i_del_value(cframe->sp++); ec_pop(); } endthread(); } /* rebuild swapfile */ if (rebuild) { timeout = co_time(&mtime); if (timeout > rtime || (timeout == rtime && mtime >= rmtime)) { rebuild = sw_copy(timeout); if (rebuild) { rtime = timeout + 1; rmtime = mtime; } else { rtime = 0; } } } /* handle user input */ timeout = co_delay(rtime, rmtime, &mtime); comm_receive(cframe, timeout, mtime); /* callouts */ co_call(cframe); } }