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

📄 t7.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * 7.  Macros, strings, diversion, and position traps. * * 	macros can override builtins *	builtins can be renamed or removed! */#include "a.h"enum{	MAXARG = 10,	MAXMSTACK = 40};/* macro invocation frame */typedef struct Mac Mac;struct Mac{	int argc;	Rune *argv[MAXARG];};Mac		mstack[MAXMSTACK];int		nmstack;void		emitdi(void);void		flushdi(void);/* * Run a user-defined macro. */void popmacro(void);intrunmacro(int dot, int argc, Rune **argv){	Rune *p;	int i;	Mac *m;	if(verbose && isupperrune(argv[0][0])) fprint(2, "run: %S\n", argv[0]);	p = getds(argv[0]);	if(p == nil){		if(verbose)			warn("ignoring unknown request %C%S", dot, argv[0]);		if(verbose > 1){			for(i=0; i<argc; i++)				fprint(2, " %S", argv[i]);			fprint(2, "\n");		}		return -1;	}	if(nmstack >= nelem(mstack)){		fprint(2, "%L: macro stack overflow:");		for(i=0; i<nmstack; i++)			fprint(2, " %S", mstack[i].argv[0]);		fprint(2, "\n");		return -1;	}	m = &mstack[nmstack++];	m->argc = argc;	for(i=0; i<argc; i++)		m->argv[i] = erunestrdup(argv[i]);	pushinputstring(p);	nr(L(".$"), argc-1);	inputnotify(popmacro);	return 0;}voidpopmacro(void){	int i;	Mac *m;		if(--nmstack < 0){		fprint(2, "%L: macro stack underflow\n");		return;	}	m = &mstack[nmstack];	for(i=0; i<m->argc; i++)		free(m->argv[i]);	if(nmstack > 0)		nr(L(".$"), mstack[nmstack-1].argc-1);	else		nr(L(".$"), 0);}void popmacro1(void);jmp_buf runjb[10];int nrunjb;voidrunmacro1(Rune *name){	Rune *argv[2];	int obol;	if(verbose) fprint(2, "outcb %p\n", outcb);	obol = bol;	argv[0] = name;	argv[1] = nil;	bol = 1;	if(runmacro('.', 1, argv) >= 0){		inputnotify(popmacro1);		if(!setjmp(runjb[nrunjb++]))			runinput();		else			if(verbose) fprint(2, "finished %S\n", name);	}	bol = obol;}voidpopmacro1(void){	popmacro();	if(nrunjb >= 0)		longjmp(runjb[--nrunjb], 1);}/* * macro arguments * *	"" means " inside " " *	"" empty string *	\newline can be done *	argument separator is space (not tab) *	number register .$ = number of arguments *	no arguments outside macros or in strings * *	arguments copied in copy mode *//* * diversions * *	processed output diverted  *	dn dl registers vertical and horizontal size of last diversion *	.z - current diversion name *//* * traps * *	skip most *	.t register - distance to next trap */static Rune *trap0;voidouttrap(void){	Rune *t;	if(outcb)		return;	if(trap0){if(verbose) fprint(2, "trap: %S\n", trap0);		t = trap0;		trap0 = nil;		runmacro1(t);		free(t);	}}/* .wh - install trap */voidr_wh(int argc, Rune **argv){	int i;	if(argc < 2)		return;	i = eval(argv[1]);	if(argc == 2){		if(i == 0){			free(trap0);			trap0 = nil;		}else			if(verbose)				warn("not removing trap at %d", i);	}	if(argc > 2){		if(i == 0){			free(trap0);			trap0 = erunestrdup(argv[2]);		}else			if(verbose)				warn("not installing %S trap at %d", argv[2], i);	}}voidr_ch(int argc, Rune **argv){	int i;		if(argc == 2){		if(trap0 && runestrcmp(argv[1], trap0) == 0){			free(trap0);			trap0 = nil;		}else			if(verbose)				warn("not removing %S trap", argv[1]);		return;	}	if(argc >= 3){		i = eval(argv[2]);		if(i == 0){			free(trap0);			trap0 = erunestrdup(argv[1]);		}else			if(verbose)				warn("not moving %S trap to %d", argv[1], i);	}}voidr_dt(int argc, Rune **argv){	USED(argc);	USED(argv);	warn("ignoring diversion trap");}/* define macro - .de, .am, .ig */voidr_de(int argc, Rune **argv){	Rune *end, *p;	Fmt fmt;	int ignore, len;	delreq(argv[1]);	delraw(argv[1]);	ignore = runestrcmp(argv[0], L("ig")) == 0;	if(!ignore)		runefmtstrinit(&fmt);	end = L("..");	if(argc >= 3)		end = argv[2];	if(runestrcmp(argv[0], L("am")) == 0 && (p=getds(argv[1])) != nil)		fmtrunestrcpy(&fmt, p);	len = runestrlen(end);	while((p = readline(CopyMode)) != nil){		if(runestrncmp(p, end, len) == 0 		&& (p[len]==' ' || p[len]==0 || p[len]=='\t'			|| (p[len]=='\\' && p[len+1]=='}'))){			free(p);			goto done;		}		if(!ignore)			fmtprint(&fmt, "%S\n", p);		free(p);	}	warn("eof in %C%S %S - looking for %#Q", dot, argv[0], argv[1], end);done:	if(ignore)		return;	p = runefmtstrflush(&fmt);	if(p == nil)		sysfatal("out of memory");	ds(argv[1], p);	free(p);}/* define string .ds .as */voidr_ds(Rune *cmd){	Rune *name, *line, *p;		name = copyarg();	line = readline(CopyMode);	if(name == nil || line == nil){		free(name);		return;	}	p = line;	if(*p == '"')		p++;	if(cmd[0] == 'd')		ds(name, p);	else		as(name, p);	free(name);	free(line);}/* remove request, macro, or string */voidr_rm(int argc, Rune **argv){	int i;	emitdi();	for(i=1; i<argc; i++){		delreq(argv[i]);		delraw(argv[i]);		ds(argv[i], nil);	}}/* .rn - rename request, macro, or string */voidr_rn(int argc, Rune **argv){	USED(argc);	renreq(argv[1], argv[2]);	renraw(argv[1], argv[2]);	ds(argv[2], getds(argv[1]));	ds(argv[1], nil);}/* .di - divert output to macro xx *//* .da - divert, appending to macro *//* page offsetting is not done! */Fmt difmt;int difmtinit;Rune di[20][100];int ndi;voidemitdi(void){	flushdi();	runefmtstrinit(&difmt);	difmtinit = 1;	fmtrune(&difmt, Uformatted);}voidflushdi(void){	int n;	Rune *p;		if(ndi == 0 || difmtinit == 0)		return;	fmtrune(&difmt, Uunformatted);	p = runefmtstrflush(&difmt);	memset(&difmt, 0, sizeof difmt);	difmtinit = 0;	if(p == nil)		warn("out of memory in diversion %C%S", dot, di[ndi-1]);	else{		n = runestrlen(p);		if(n > 0 && p[n-1] != '\n'){			p = runerealloc(p, n+2);			p[n] = '\n';			p[n+1] = 0;		}	}	as(di[ndi-1], p);	free(p);}voidoutdi(Rune r){if(!difmtinit) abort();	if(r == Uempty)		return;	fmtrune(&difmt, r);}/* .di, .da */voidr_di(int argc, Rune **argv){	br();	if(argc > 2)		warn("extra arguments to %C%S", dot, argv[0]);	if(argc == 1){		/* end diversion */		if(ndi <= 0){			// warn("unmatched %C%S", dot, argv[0]);			return;		}		flushdi();		if(--ndi == 0){			_nr(L(".z"), nil);			outcb = nil;		}else{			_nr(L(".z"), di[ndi-1]);			runefmtstrinit(&difmt);			fmtrune(&difmt, Uformatted);			difmtinit = 1;		}		return;	}	/* start diversion */	/* various register state should be saved, but it's all useless to us */	flushdi();	if(ndi >= nelem(di))		sysfatal("%Cdi overflow", dot);	if(argv[0][1] == 'i')		ds(argv[1], nil);	_nr(L(".z"), argv[1]);	runestrcpy(di[ndi++], argv[1]);	runefmtstrinit(&difmt);	fmtrune(&difmt, Uformatted);	difmtinit = 1;	outcb = outdi;}/* .wh - install trap *//* .ch - change trap *//* .dt - install diversion trap *//* set input-line count trap */int itrapcount;int itrapwaiting;Rune *itrapname;voidr_it(int argc, Rune **argv){	if(argc < 3){		itrapcount = 0;		return;	}	itrapcount = eval(argv[1]);	free(itrapname);	itrapname = erunestrdup(argv[2]);}voiditrap(void){	itrapset();	if(itrapwaiting){		itrapwaiting = 0;		runmacro1(itrapname);	}}voiditrapset(void){	if(itrapcount > 0 && --itrapcount == 0)		itrapwaiting = 1;}/* .em - invoke macro when all input is over */voidr_em(int argc, Rune **argv){	Rune buf[20];		USED(argc);	runesnprint(buf, nelem(buf), ".%S\n", argv[1]);	as(L("eof"), buf);}inte_star(void){	Rune *p;		p = getds(getname());	if(p)		pushinputstring(p);	return 0;}inte_t(void){	if(inputmode&CopyMode)		return '\t';	return 0;}inte_a(void){	if(inputmode&CopyMode)		return '\a';	return 0;}inte_backslash(void){	if(inputmode&ArgMode)		ungetrune('\\');	return backslash;}inte_dot(void){	return '.';}inte_dollar(void){	int c;	c = getnext();	if(c < '1' || c > '9'){		ungetnext(c);		return 0;	}	c -= '0';	if(nmstack <= 0 || mstack[nmstack-1].argc <= c)		return 0;	pushinputstring(mstack[nmstack-1].argv[c]);	return 0;}voidt7init(void){		addreq(L("de"), r_de, -1);	addreq(L("am"), r_de, -1);	addreq(L("ig"), r_de, -1);	addraw(L("ds"), r_ds);	addraw(L("as"), r_ds);	addreq(L("rm"), r_rm, -1);	addreq(L("rn"), r_rn, -1);	addreq(L("di"), r_di, -1);	addreq(L("da"), r_di, -1);	addreq(L("it"), r_it, -1);	addreq(L("em"), r_em, 1);	addreq(L("wh"), r_wh, -1);	addreq(L("ch"), r_ch, -1);	addreq(L("dt"), r_dt, -1);		addesc('$', e_dollar, CopyMode|ArgMode|HtmlMode);	addesc('*', e_star, CopyMode|ArgMode|HtmlMode);	addesc('t', e_t, CopyMode|ArgMode);	addesc('a', e_a, CopyMode|ArgMode);	addesc('\\', e_backslash, ArgMode|CopyMode);	addesc('.', e_dot, CopyMode|ArgMode);		ds(L("eof"), L(".sp 0.5i\n"));	ds(L(".."), L(""));}

⌨️ 快捷键说明

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