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

📄 cmd.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "sam.h"#include "parse.h"static char	linex[]="\n";static char	wordx[]=" \t\n";Cmdtab cmdtab[]={/*	cmdc	text	regexp	addr	defcmd	defaddr	count	token	 fn	*/	'\n',	0,	0,	0,	0,	aDot,	0,	0,	nl_cmd,	'a',	1,	0,	0,	0,	aDot,	0,	0,	a_cmd,	'b',	0,	0,	0,	0,	aNo,	0,	linex,	b_cmd,	'B',	0,	0,	0,	0,	aNo,	0,	linex,	b_cmd,	'c',	1,	0,	0,	0,	aDot,	0,	0,	c_cmd,	'd',	0,	0,	0,	0,	aDot,	0,	0,	d_cmd,	'D',	0,	0,	0,	0,	aNo,	0,	linex,	D_cmd,	'e',	0,	0,	0,	0,	aNo,	0,	wordx,	e_cmd,	'f',	0,	0,	0,	0,	aNo,	0,	wordx,	f_cmd,	'g',	0,	1,	0,	'p',	aDot,	0,	0,	g_cmd,	'i',	1,	0,	0,	0,	aDot,	0,	0,	i_cmd,	'k',	0,	0,	0,	0,	aDot,	0,	0,	k_cmd,	'm',	0,	0,	1,	0,	aDot,	0,	0,	m_cmd,	'n',	0,	0,	0,	0,	aNo,	0,	0,	n_cmd,	'p',	0,	0,	0,	0,	aDot,	0,	0,	p_cmd,	'q',	0,	0,	0,	0,	aNo,	0,	0,	q_cmd,	'r',	0,	0,	0,	0,	aDot,	0,	wordx,	e_cmd,	's',	0,	1,	0,	0,	aDot,	1,	0,	s_cmd,	't',	0,	0,	1,	0,	aDot,	0,	0,	m_cmd,	'u',	0,	0,	0,	0,	aNo,	2,	0,	u_cmd,	'v',	0,	1,	0,	'p',	aDot,	0,	0,	g_cmd,	'w',	0,	0,	0,	0,	aAll,	0,	wordx,	w_cmd,	'x',	0,	1,	0,	'p',	aDot,	0,	0,	x_cmd,	'y',	0,	1,	0,	'p',	aDot,	0,	0,	x_cmd,	'X',	0,	1,	0,	'f',	aNo,	0,	0,	X_cmd,	'Y',	0,	1,	0,	'f',	aNo,	0,	0,	X_cmd,	'!',	0,	0,	0,	0,	aNo,	0,	linex,	plan9_cmd,	'>',	0,	0,	0,	0,	aDot,	0,	linex,	plan9_cmd,	'<',	0,	0,	0,	0,	aDot,	0,	linex,	plan9_cmd,	'|',	0,	0,	0,	0,	aDot,	0,	linex,	plan9_cmd,	'=',	0,	0,	0,	0,	aDot,	0,	linex,	eq_cmd,	'c'|0x100,0,	0,	0,	0,	aNo,	0,	wordx,	cd_cmd,	0,	0,	0,	0,	0,	0,	0,	0,};Cmd	*parsecmd(int);Addr	*compoundaddr(void);Addr	*simpleaddr(void);void	freecmd(void);void	okdelim(int);Rune	line[BLOCKSIZE];Rune	termline[BLOCKSIZE];Rune	*linep = line;Rune	*terminp = termline;Rune	*termoutp = termline;List	cmdlist = { 'p' };List	addrlist = { 'p' };List	relist = { 'p' };List	stringlist = { 'p' };int	eof;voidresetcmd(void){	linep = line;	*linep = 0;	terminp = termoutp = termline;	freecmd();}intinputc(void){	int n, nbuf;	char buf[3];	Rune r;    Again:	nbuf = 0;	if(downloaded){		while(termoutp == terminp){			cmdupdate();			if(patset)				tellpat();			while(termlocked > 0){				outT0(Hunlock);				termlocked--;			}			if(rcv() == 0)				return -1;		}		r = *termoutp++;		if(termoutp == terminp)			terminp = termoutp = termline;	}else{   		do{			n = read(0, buf+nbuf, 1);			if(n <= 0)				return -1;			nbuf += n;		}while(!fullrune(buf, nbuf));		chartorune(&r, buf);	}	if(r == 0){		warn(Wnulls);		goto Again;	}	return r;}intinputline(void){	int i, c, start;	/*	 * Could set linep = line and i = 0 here and just	 * error(Etoolong) below, but this way we keep	 * old input buffer history around for a while.	 * This is useful only for debugging.	 */	i = linep - line;	do{		if((c = inputc())<=0)			return -1;		if(i == nelem(line)-1){			if(linep == line)				error(Etoolong);			start = linep - line;			runemove(line, linep, i-start);			i -= start;			linep = line;		}	}while((line[i++]=c) != '\n');	line[i] = 0;	return 1;}intgetch(void){	if(eof)		return -1;	if(*linep==0 && inputline()<0){		eof = TRUE;		return -1;	}	return *linep++;}intnextc(void){	if(*linep == 0)		return -1;	return *linep;}voidungetch(void){	if(--linep < line)		panic("ungetch");}Posngetnum(int signok){	Posn n=0;	int c, sign;	sign = 1;	if(signok>1 && nextc()=='-'){		sign = -1;		getch();	}	if((c=nextc())<'0' || '9'<c)	/* no number defaults to 1 */		return sign;	while('0'<=(c=getch()) && c<='9')		n = n*10 + (c-'0');	ungetch();	return sign*n;}intskipbl(void){	int c;	do		c = getch();	while(c==' ' || c=='\t');	if(c >= 0)		ungetch();	return c;}voidtermcommand(void){	Posn p;	for(p=cmdpt; p<cmd->nc; p++){		if(terminp >= termline+nelem(termline)){			cmdpt = cmd->nc;			error(Etoolong);		}		*terminp++ = filereadc(cmd, p);	}	cmdpt = cmd->nc;}voidcmdloop(void){	Cmd *cmdp;	File *ocurfile;	int loaded;	for(;;){		if(!downloaded && curfile && curfile->unread)			load(curfile);		if((cmdp = parsecmd(0))==0){			if(downloaded){				rescue();				exits("eof");			}			break;		}		ocurfile = curfile;		loaded = curfile && !curfile->unread;		if(cmdexec(curfile, cmdp) == 0)			break;		freecmd();		cmdupdate();		update();		if(downloaded && curfile &&		    (ocurfile!=curfile || (!loaded && !curfile->unread)))			outTs(Hcurrent, curfile->tag);			/* don't allow type ahead on files that aren't bound */		if(downloaded && curfile && curfile->rasp == 0)			terminp = termoutp;	}}Cmd *newcmd(void){	Cmd *p;	p = emalloc(sizeof(Cmd));	inslist(&cmdlist, cmdlist.nused, p);	return p;}Addr*newaddr(void){	Addr *p;	p = emalloc(sizeof(Addr));	inslist(&addrlist, addrlist.nused, p);	return p;}String*newre(void){	String *p;	p = emalloc(sizeof(String));	inslist(&relist, relist.nused, p);	Strinit(p);	return p;}String*newstring(void){	String *p;	p = emalloc(sizeof(String));	inslist(&stringlist, stringlist.nused, p);	Strinit(p);	return p;}voidfreecmd(void){	int i;	while(cmdlist.nused > 0)		free(cmdlist.voidpptr[--cmdlist.nused]);	while(addrlist.nused > 0)		free(addrlist.voidpptr[--addrlist.nused]);	while(relist.nused > 0){		i = --relist.nused;		Strclose(relist.stringpptr[i]);		free(relist.stringpptr[i]);	}	while(stringlist.nused>0){		i = --stringlist.nused;		Strclose(stringlist.stringpptr[i]);		free(stringlist.stringpptr[i]);	}}intlookup(int c){	int i;	for(i=0; cmdtab[i].cmdc; i++)		if(cmdtab[i].cmdc == c)			return i;	return -1;}voidokdelim(int c){	if(c=='\\' || ('a'<=c && c<='z')	|| ('A'<=c && c<='Z') || ('0'<=c && c<='9'))		error_c(Edelim, c);}voidatnl(void){	skipbl();	if(getch() != '\n')		error(Enewline);}voidgetrhs(String *s, int delim, int cmd){	int c;	while((c = getch())>0 && c!=delim && c!='\n'){		if(c == '\\'){			if((c=getch()) <= 0)				error(Ebadrhs);			if(c == '\n'){				ungetch();				c='\\';			}else if(c == 'n')				c='\n';			else if(c!=delim && (cmd=='s' || c!='\\'))	/* s does its own */				Straddc(s, '\\');		}		Straddc(s, c);	}	ungetch();	/* let client read whether delimeter, '\n' or whatever */}String *collecttoken(char *end){	String *s = newstring();	int c;	while((c=nextc())==' ' || c=='\t')		Straddc(s, getch()); /* blanks significant for getname() */	while((c=getch())>0 && utfrune(end, c)==0)		Straddc(s, c);	Straddc(s, 0);	if(c != '\n')		atnl();	return s;}String *collecttext(void){	String *s = newstring();	int begline, i, c, delim;	if(skipbl()=='\n'){		getch();		i = 0;		do{			begline = i;			while((c = getch())>0 && c!='\n')				i++, Straddc(s, c);			i++, Straddc(s, '\n');			if(c < 0)				goto Return;		}while(s->s[begline]!='.' || s->s[begline+1]!='\n');		Strdelete(s, s->n-2, s->n);	}else{		okdelim(delim = getch());		getrhs(s, delim, 'a');		if(nextc()==delim)			getch();		atnl();	}    Return:	Straddc(s, 0);		/* JUST FOR CMDPRINT() */	return s;}Cmd *parsecmd(int nest){	int i, c;	Cmdtab *ct;	Cmd *cp, *ncp;	Cmd cmd;	cmd.next = cmd.ccmd = 0;	cmd.re = 0;	cmd.flag = cmd.num = 0;	cmd.addr = compoundaddr();	if(skipbl() == -1)		return 0;	if((c=getch())==-1)		return 0;	cmd.cmdc = c;	if(cmd.cmdc=='c' && nextc()=='d'){	/* sleazy two-character case */		getch();		/* the 'd' */		cmd.cmdc='c'|0x100;	}	i = lookup(cmd.cmdc);	if(i >= 0){		if(cmd.cmdc == '\n')			goto Return;	/* let nl_cmd work it all out */		ct = &cmdtab[i];		if(ct->defaddr==aNo && cmd.addr)			error(Enoaddr);		if(ct->count)			cmd.num = getnum(ct->count);		if(ct->regexp){			/* x without pattern -> .*\n, indicated by cmd.re==0 */			/* X without pattern is all files */			if((ct->cmdc!='x' && ct->cmdc!='X') ||			   ((c = nextc())!=' ' && c!='\t' && c!='\n')){				skipbl();				if((c = getch())=='\n' || c<0)					error(Enopattern);				okdelim(c);				cmd.re = getregexp(c);				if(ct->cmdc == 's'){					cmd.ctext = newstring();					getrhs(cmd.ctext, c, 's');					if(nextc() == c){						getch();						if(nextc() == 'g')							cmd.flag = getch();					}							}			}		}		if(ct->addr && (cmd.caddr=simpleaddr())==0)			error(Eaddress);		if(ct->defcmd){			if(skipbl() == '\n'){				getch();				cmd.ccmd = newcmd();				cmd.ccmd->cmdc = ct->defcmd;			}else if((cmd.ccmd = parsecmd(nest))==0)				panic("defcmd");		}else if(ct->text)			cmd.ctext = collecttext();		else if(ct->token)			cmd.ctext = collecttoken(ct->token);		else			atnl();	}else		switch(cmd.cmdc){		case '{':			cp = 0;			do{				if(skipbl()=='\n')					getch();				ncp = parsecmd(nest+1);				if(cp)					cp->next = ncp;				else					cmd.ccmd = ncp;			}while(cp = ncp);			break;		case '}':			atnl();			if(nest==0)				error(Enolbrace);			return 0;		default:			error_c(Eunk, cmd.cmdc);		}    Return:	cp = newcmd();	*cp = cmd;	return cp;}String*				/* BUGGERED */getregexp(int delim){	String *r = newre();	int c;	for(Strzero(&genstr); ; Straddc(&genstr, c))		if((c = getch())=='\\'){			if(nextc()==delim)				c = getch();			else if(nextc()=='\\'){				Straddc(&genstr, c);				c = getch();			}		}else if(c==delim || c=='\n')			break;	if(c!=delim && c)		ungetch();	if(genstr.n > 0){		patset = TRUE;		Strduplstr(&lastpat, &genstr);		Straddc(&lastpat, '\0');	}	if(lastpat.n <= 1)		error(Epattern);	Strduplstr(r, &lastpat);	return r;}Addr *simpleaddr(void){	Addr addr;	Addr *ap, *nap;	addr.next = 0;	addr.left = 0;	switch(skipbl()){	case '#':		addr.type = getch();		addr.num = getnum(1);		break;	case '0': case '1': case '2': case '3': case '4':	case '5': case '6': case '7': case '8': case '9': 		addr.num = getnum(1);		addr.type='l';		break;	case '/': case '?': case '"':		addr.are = getregexp(addr.type = getch());		break;	case '.':	case '$':	case '+':	case '-':	case '\'':		addr.type = getch();		break;	default:		return 0;	}	if(addr.next = simpleaddr())		switch(addr.next->type){		case '.':		case '$':		case '\'':			if(addr.type!='"')		case '"':				error(Eaddress);			break;		case 'l':		case '#':			if(addr.type=='"')				break;			/* fall through */		case '/':		case '?':			if(addr.type!='+' && addr.type!='-'){				/* insert the missing '+' */				nap = newaddr();				nap->type='+';				nap->next = addr.next;				addr.next = nap;			}			break;		case '+':		case '-':			break;		default:			panic("simpleaddr");		}	ap = newaddr();	*ap = addr;	return ap;}Addr *compoundaddr(void){	Addr addr;	Addr *ap, *next;	addr.left = simpleaddr();	if((addr.type = skipbl())!=',' && addr.type!=';')		return addr.left;	getch();	next = addr.next = compoundaddr();	if(next && (next->type==',' || next->type==';') && next->left==0)		error(Eaddress);	ap = newaddr();	*ap = addr;	return ap;}

⌨️ 快捷键说明

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