⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interp.c

📁 使用BorlandC++4.5编译的一个MUD客户端程序
💻 C
字号:
head	2.1;access;symbols;locks; strict;comment	@ * @;2.1date	95.10.24.15.46.14;	author tsurace;	state Release;branches;next	1.1;1.1date	95.10.12.19.23.19;	author tsurace;	state Beta;branches;next	;desc@VTC interpreter thingy.@2.1log@Roll.@text@/* interp.c: Execute linear compiled VTC code */
/* $Id: interp.c 1.1 1995/10/12 19:23:19 tsurace Beta tsurace $ */

#include "vt.h"
#include "prmt.h"

#ifdef PROTOTYPES
static int pcall(Dframe *, int, int);
static void cpop(void);
static void cpop_normal(void);
static void abort_interp(void);
static void revise_cframes(Cframe *, int, Dframe *, Dframe *);
static void revise_estates(Estate *, Dframe *, Dframe *);
static void interp_context(Unode *, Unode *);
#else
static void revise_cframes(), revise_estates(), cpop(), cpop_normal();
static void abort_interp();
#endif

/* The data and call stacks */
#define INIT_SIZE 64
Dframe *dstack;				/* The data stack	    */
Cframe *cstack;				/* The call stack	    */
int dpos = 0, cpos = 0;			/* Positions in both stacks */
int dsize = INIT_SIZE;			/* Allocated space	    */
int curprmt;				/* Current prmt number	    */
static int csize = INIT_SIZE;
#define INIT_GVARS 100
Array *gvars;				/* Global variable values   */
extern int break_pending;
extern Unode *cur_rmt, *active_win;
extern Unode rmt_ring, win_ring;
extern Estate *events, *gen_read, *gen_high, *gen_low;

/* Short-cut for Cinstr */
static Instr *ins;

extern Prmt prmtab[];
int iwidth[] =
 { 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 };

#define Ctop	(cstack[cpos - 1])
#define Cinstr	(Ctop.instr)
#define Cprog	(Ctop.prog)
#define Dtop	(dstack[dpos - 1])
#define Dextend if (1) { if (dpos == dsize) double_dstack(); dpos++; } else
#define Dextendn(n) if (1) { while (dpos + (n) > dsize) double_dstack(); } else
#define Dpush(df) if (1) { Dextend; Dtop = (df); } else
#define Dpop() deref_frame(&dstack[--dpos])
#define Ierror(x) if (1) { outputf x; finish_error(); \
			   abort_interp(); return; } else
#define Set_ins(x) if (1) { ins = (x); update = 0; } else

void init_interp()
{
	dstack = Newarray(Dframe, INIT_SIZE);
	cstack = Newarray(Cframe, INIT_SIZE);
	gvars = add_array(INIT_GVARS, dfalloc(INIT_GVARS), 1, 0, 0);
}

/* Interprets program on top of call stack until the highest detached
** frame finishes execution, or the program is aborted or suspended. */
void interp()
{
	Dframe *dp, df;
	Func *func;
	int update, val;

	ins = Cinstr;
    while (1) {
	if (break_pending) {
		abort_interp();
		return;
	}
	update = 1;
	switch(ins->type) {
	    case I_ICONST:
		Dextend;
		Dset_int(Dtop, ins[1].iconst);
	    Case I_SCONST:
		Dextend;
		Dset_sptr_ref(Dtop, istr_rs(ins[1].sconst), 0);
	    Case I_PCALL:
		if (!pcall(&df, ins[1].pc.argc, ins[1].pc.pnum))
			return;
		if (df.type != F_EXCEPT) {
			Dpush(df);
			move_frame_refs(&df, &Dtop);
		}
		update = 0;
	    Case I_FCALL:
		func = ins[2].func;
		if (!func->cmd || ins[1].argc < func->cmd->reqargs)
			Ierror((!func->cmd ? "Undefined function %s"
			       : "Not enough arguments to %s", func->name));
		Cinstr = ins + 3;
		cpush(func->cmd, ins[1].argc, 1, 0);
		Set_ins(Cinstr);
	    Case I_EXEC:
		dp = &dstack[dpos - ins[1].argc - 1];
		if (dp->type == F_PPTR) {
			if (!pcall(dp, ins[1].argc, dp->Dpnum))
				return;
		} else if (dp->type == F_FPTR) {
			if (ins[1].argc < dp->Dfunc->cmd->reqargs)
				Ierror(("Not enough arguments to %s",
				       dp->Dfunc->name));
			Cinstr = ins + 2;
			func = dp->Dfunc;
			move_frames_refs(ins[1].argc, dp + 1, dp);
			Copy(dp + 1, dp, ins[1].argc, Dframe);
			dpos--;
			cpush(func->cmd, ins[1].argc, 1, 0);
			ins = Cinstr;
		} else
			Ierror(("Invalid function call"));
		update = 0;
	    Case I_BOBJ:
		Dextend;
		Dset_elem(Dtop, F_BPTR, Dbobj, ins[1].bobj);
	    Case I_GVAR:
		Dextend;
		Dset_aptr(Dtop, gvars, ins[1].tnum);
	    Case I_AVAR:
		Dextend;
		Dset_aptr(Dtop, Ctop.avars, ins[1].tnum);
		add_fref(&Dtop.Darray->r.fr, &Dtop);
	    Case I_LVAR:
		Dextend;
		Dset_aptr(Dtop, Ctop.lvars, ins[1].tnum);
		add_fref(&Dtop.Darray->r.fr, &Dtop);
	    Case I_PPTR:
		Dextend;
		Dset_elem(Dtop, F_PPTR, Dpnum, ins[1].pnum);
	    Case I_FPTR:
		func = ins[1].func;
		if (!func->cmd)
			Ierror(("Undefined function %s", func->name));
		Dextend;
		Dset_elem(Dtop, F_FPTR, Dfunc, ins[1].func);
	    Case I_JMPF:
		if (Dffalse(Dtop))
			Set_ins(ins[1].loc);
		Dpop();
	    Case I_JMPT:
		if (Dftrue(Dtop))
			Set_ins(ins[1].loc);
		Dpop();
	    Case I_JMPPF:
		if (Dffalse(Dtop))
			Set_ins(ins[1].loc);
		else	
			Dpop();
	    Case I_JMPPT:
		if (Dftrue(Dtop))
			Set_ins(ins[1].loc);
		else
			Dpop();
	    Case I_JMP:
		Set_ins(ins[1].loc);
	    Case I_CVTB: /* Careful */
		dp = &Dtop;
		deref_frame(dp);
		dp->Dval = Dftrue(*dp);
		dp->type = F_INT;
	    Case I_EVAL:
		dp = &Dtop;
		if (dp->type == F_SPTR) {
			val = (unsigned char) Soelem(*dp);
			dec_ref_istr(dp->Distr);
			Dset_int(*dp, val);
		} else if (dp->type == F_APTR) {
			if (Ainbounds(*dp))
				df = dp->Darray->vals[dp->Dapos];
			else
				df.type = F_NULL;
			ref_frame(&df);
			deref_frame(dp);
			*dp = df;
			move_frame_refs(&df, dp);
		} else if (dp->type == F_BPTR) {
			dp->type = F_NULL;
			(*dp->Dbobj)(dp);
			ref_frame(dp);
		} else
			Ierror(("Invalid pointer dereferenced"));
	    Case I_NULL:
		Dextend;
		Dtop.type = F_NULL;
	    Case I_POP:
		Dpop();
	    Case I_DUP:
		Dextend;
		Dtop = dstack[dpos - 2];
		ref_frame(&Dtop);
	    Case I_STOP:
		if (Ctop.attached) {
			cpop_normal();
			ins = Cinstr;
			update = 0;
		} else {
			cpop_normal();
			Dpop();
			return;
		}
	}
	if (update)
		ins += iwidth[ins->type];
    }
}

static int pcall(dp, argc, pnum)
	Dframe *dp;
	int argc, pnum;
{
	Dframe *argv = &dstack[dpos - argc];
	int pargc = prmtab[pnum].argc;

	curprmt = pnum;
	Cinstr = ins + 2;
	if (pargc >= 0 && argc != pargc) {
		outputf("Too %s arguments to %s",
			argc < pargc ? "few" : "many", prmtab[pnum].name);
		finish_error();
		abort_interp();
		return 0;
	}
	dp->type = F_NULL;
	(*prmtab[pnum].func)(dp, argc, argv);
	ins = Cinstr;
	if (dp->type == F_EXCEPT) {
		if (dp->Dval == INTERP_ERROR)
			abort_interp();
		return dp->Dval == INTERP_NOFREE;
	}
	ref_frame(dp);
	deref_frames(argc, &dstack[dpos - argc]);
	dpos -= argc;
	return 1;
}

static void cpop()
{
	dec_ref_prog(Ctop.prog);
	destroy_pointers(Ctop.avars->r.fr);
	arfree(Ctop.avars);
	destroy_pointers(Ctop.lvars->r.fr);
	arfree(Ctop.lvars);
	cpos--;
}

static void cpop_normal()
{
	if (Ctop.dstart != dpos - 1) {
		deref_frames(dpos - Ctop.dstart - 1, &dstack[Ctop.dstart]);
		dstack[Ctop.dstart] = Dtop;
		move_frame_refs(&Dtop, &dstack[Ctop.dstart]);
		dpos = Ctop.dstart + 1;
	}
	cpop();
}

static void abort_interp()
{
	while (Ctop.attached)
		cpop();
	deref_frames(dpos - Ctop.dstart, &dstack[Ctop.dstart]);
	dpos = Ctop.dstart;
	cpop();
}

static void revise_cframes(cf, num, oldstack, newstack)
	Cframe *cf;
	int num;
	Dframe *oldstack, *newstack;
{
	while (num--) {
		cf->avars->vals = cf->avars->vals - oldstack + newstack;
		cf->lvars->vals = cf->lvars->vals - oldstack + newstack;
		cf++;
	}
}

static void revise_estates(es, oldstack, newstack)
	Estate *es;
	Dframe *oldstack, *newstack;
{
	for (; es; es = es->next)
		revise_cframes(es->cimage, es->cframes, oldstack, newstack);
}

void double_dstack()
{
	Dframe *new;
	Unode *un;

	new = Newarray(Dframe, dsize * 2);
	Copy(dstack, new, dpos, Dframe);
	move_frames_refs(dpos, dstack, new);
	revise_cframes(cstack, cpos, dstack, new);
	for (un = rmt_ring.next; !un->dummy; un = un->next)
		revise_estates(un->Rrstack, dstack, new);
	for (un = win_ring.next; !un->dummy; un = un->next) {
		revise_estates(un->Wghstack, dstack, new);
		revise_estates(un->Wglstack, dstack, new);
		revise_estates(un->Wrstack, dstack, new);
	}
	revise_estates(events, dstack, new);
	revise_estates(gen_read, dstack, new);
	revise_estates(gen_high, dstack, new);
	revise_estates(gen_low, dstack, new);
	Discardarray(dstack, Dframe, dsize);
	dstack = new;
	dsize *= 2;
}

void cpush(prog, argc, attached, progress)
	Prog *prog;
	int argc, attached, progress;
{
	Cframe *cf;
	int i, argc_alloc = max(argc, prog->avarc);

	if (cpos == csize)
		Double(cstack, Cframe, csize);
	Dextendn(prog->lvarc + argc_alloc - argc);
	cf = &cstack[cpos++];
	prog->refs++;
	cf->prog = prog;
	cf->instr = prog->code;
	cf->dstart = dpos - argc - progress;
	cf->attached = attached;
	for (i = 0; i < prog->lvarc + argc_alloc - argc; i++, dpos++)
		dstack[dpos].type = F_NULL;
	cf->avars = add_array(argc_alloc, &dstack[cf->dstart], 1, 1, 0);
	cf->lvars = add_array(prog->lvarc, &dstack[cf->dstart + argc_alloc],
			      1, 1, 0);
	cf->avars->r.fr = cf->lvars->r.fr = NULL;
	cf->uargc = argc;
	cf->uargv = 0;
}

/* Interface to interpreter */

/* Set up a cur_rmt and cur_win context and call interp() */
static void interp_context(win, rmt)
	Unode *win, *rmt;
{
	Unode *old_win, *old_rmt;
	int owin_id, ormt_id;

	old_win = cur_win;
	owin_id = cur_win ? cur_win->id : 0;
	old_rmt = cur_rmt;
	ormt_id = cur_rmt ? cur_rmt->id : 0;
	cur_win = win;
	cur_rmt = rmt;
	interp();
	cur_win = (old_win && old_win->id == owin_id) ? old_win : NULL;
	cur_rmt = (old_rmt && old_rmt->id == ormt_id) ? old_rmt : NULL;
}

/* Start up a program with no arguments */
void run_prog(prog)
	Prog *prog;
{
	if (prog->reqargs) {
		outputf("Function %s called with too few arguments\n",
			lookup_prog(prog));
		return;
	}
	cpush(prog, 0, 0, 0);
	interp();
}

void run_prog_istr(prog, is, win, rmt)
	Prog *prog;
	Istr *is;
	Unode *win, *rmt;
{
	Dframe df;

	if (prog->reqargs > 1) {
		outputf("Function %s called with too few arguments\n",
			lookup_prog(prog));
		return;
	}
	Dset_sptr(df, is, 0);
	is->refs++;
	Dpush(df);
	cpush(prog, 1, 0, 0);
	interp_context(win, rmt);
}

/* Suspend execution and return an image of it */
Estate *suspend(argc)
	int argc;
{
	Estate *es;
	Cframe *cp;
	int nf;

	deref_frames(argc, &dstack[dpos - argc]);
	dpos -= argc;
	es = New(Estate);
	for (cp = &Ctop; cp->attached; cp--);
	es->dframes = nf = dpos - cp->dstart;
	es->dimage = Newarray(Dframe, nf);
	Copy(&dstack[cp->dstart], es->dimage, nf, Dframe);
	move_frames_refs(nf, &dstack[cp->dstart], es->dimage);
	dpos = cp->dstart;
	es->cframes = nf = cstack + cpos - cp;
	es->cimage = Newarray(Cframe, nf);
	Copy(cp, es->cimage, nf, Cframe);
	cpos = cp - cstack;
	es->win = cur_win;
	es->wid = cur_win ? cur_win->id : 0;
	es->rmt = cur_rmt;
	es->rid = cur_rmt ? cur_rmt->id : 0;
	return es;
}

/* Free up the information in an image deleted by the console */
void discard_estate(eptr)
	Estate **eptr;
{
	Estate *es = *eptr;
	int i;
	Cframe *cf;

	*eptr = es->next;
	deref_frames(es->dframes, es->dimage);
	Discardarray(es->dimage, Dframe, es->dframes);
	for (cf = es->cimage, i = 0; i < es->cframes; i++) {
		destroy_pointers(cf[i].avars->r.fr);
		arfree(cf[i].avars);
		destroy_pointers(cf[i].lvars->r.fr);
		arfree(cf[i].lvars);
	}
	Discardarray(es->cimage, Cframe, es->cframes);
	Discard(es, Estate);
}

/* Resume a suspended program */
void resume(eptr, dp)
	Estate **eptr;
	Dframe *dp;
{
	Estate *es = *eptr;
	int adjust, i;

	*eptr = es->next;
	if (dpos + es->dframes >= dsize)
		double_dstack();
	if (cpos + es->cframes >= csize)
		Double(cstack, Cframe, csize);
	adjust = es->cimage[0].dstart - dpos;
	if (adjust) {
		for (i = 0; i < es->cframes; i++) {
			es->cimage[i].dstart -= adjust;
			es->cimage[i].avars->vals -= adjust;
			es->cimage[i].lvars->vals -= adjust;
		}
	}
	Copy(es->dimage, &dstack[dpos], es->dframes, Dframe);
	move_frames_refs(es->dframes, es->dimage, &dstack[dpos]);
	Discardarray(es->dimage, Dframe, es->dframes);
	dpos += es->dframes;
	Copy(es->cimage, &cstack[cpos], es->cframes, Cframe);
	Discardarray(es->cimage, Cframe, es->cframes);
	cpos += es->cframes;
	Dpush(*dp);
	interp_context((es->win && es->wid == es->win->id) ? es->win : NULL,
		       (es->rmt && es->rid == es->rmt->id) ? es->rmt : NULL);
	Discard(es, Estate);
}

void resume_istr(eptr, is)
	Estate **eptr;
	Istr *is;
{
	Dframe df;

	Dset_sptr_ref(df, is, 0);
	is->refs++;
	resume(eptr, &df);
}

void resume_int(eptr, num)
	Estate **eptr;
	int num;
{
	Dframe df;

	Dset_int(df, num);
	resume(eptr, &df);
}

void destroy_pipe(elist)
	Estate *elist;
{
	while (elist)
		discard_estate(&elist);
}

void break_pipe(elist)
	Estate *elist;
{
	Dframe null;

	null.type = F_NULL;
	while (elist)
		resume(&elist, &null);
}

/* General routines for dealing with data frames */

void ref_frame(df)
	Dframe *df;
{
	switch (df->type) {
	    case F_WIN:
	    case F_RMT:
	    case F_KEY:
	    case F_FILE:
		add_fref(&df->Dunode->frefs, df);
	    Case F_SPTR:
		df->Distr->refs++;
	    Case F_APTR:
		if (df->Darray->fixed)
			add_fref(&df->Darray->r.fr, df);
		else if (df->Darray->isp)
			df->Darray->r.plist->refs++;
		else if (!df->Darray->intern)
			df->Darray->r.refs++;
	    Case F_REG:
		df->Dreg->refs++;
	    Case F_PLIST:
		df->Dplist->refs++;
	}
}

void ref_frames(num, frames)
	int num;
	Dframe *frames;
{
	while (num--)
		ref_frame(frames++);
}

void move_frame_refs(old, new)
	Dframe *old, *new;
{
	switch(old->type) {
	    case F_WIN:
	    case F_RMT:
	    case F_KEY:
	    case F_FILE:
		move_fref(old->Dunode->frefs, old, new);
	    Case F_APTR:
		if (old->Darray->fixed)
			move_fref(old->Darray->r.fr, old, new);
	}
}

void move_frames_refs(num, old, new)
	int num;
	Dframe *old, *new;
{
	while (num--)
		move_frame_refs(old++, new++);
}

void deref_frame(df)
	Dframe *df;
{
	switch(df->type) {
	    case F_WIN:
	    case F_RMT:
	    case F_KEY:
	    case F_FILE:
		elim_fref(&df->Dunode->frefs, df);
	    Case F_SPTR:
		dec_ref_istr(df->Distr);
	    Case F_APTR:
		if (df->Darray->fixed)
			elim_fref(&df->Darray->r.fr, df);
		else if (df->Darray->isp)
			dec_ref_plist(df->Darray->r.plist);
		else if (!df->Darray->intern)
			dec_ref_array(df->Darray);
	    Case F_REG:
		if (!--df->Dreg->refs) {
			if (df->Dreg->rs)
				dec_ref_rstr(df->Dreg->rs);
			free(df->Dreg);
		}
	    Case F_PLIST:
		dec_ref_plist(df->Dplist);
	}
}

void deref_frames(num, frames)
	int num;
	Dframe *frames;
{
	while (num--)
		deref_frame(frames++);
}

@1.1log@Initial revision@text@d2 1a2 1/* $Id$ */@

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -