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

📄 interp.c

📁 Unix下的MUD客户端程序
💻 C
字号:
/* interp.c: Execute linear compiled VTC code */#include "vt.h"#include "prmt.h"#ifdef PROTOTYPESstatic 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 *);#elsestatic void revise_cframes(), revise_estates(), cpop(), cpop_normal();static void abort_interp();#endif/* The data and call stacks */#define INIT_SIZE 64Dframe *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 100Array *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; } elsevoid 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++);}

⌨️ 快捷键说明

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