V9/jtools/src/sam/cmd.c

Compare this file to the similar file:
Show the results in this format:

#include "sam.h"
#include "parse.h"

int	nl_cmd(), a_cmd(), b_cmd(), c_cmd(), cd_cmd(), d_cmd(), D_cmd(), e_cmd();
int	f_cmd(), g_cmd(), i_cmd(), k_cmd(), m_cmd(), n_cmd(), p_cmd(), q_cmd();
int	s_cmd(), u_cmd(), w_cmd(), x_cmd(), X_cmd(), unix_cmd(), eq_cmd();

static char	linex[]="\n";
static char	wordx[]=" \t\n";
struct 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,	1,	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,	unix_cmd,
	'>',	0,	0,	0,	0,	aDot,	0,	linex,	unix_cmd,
	'<',	0,	0,	0,	0,	aDot,	0,	linex,	unix_cmd,
	'|',	0,	0,	0,	0,	aDot,	0,	linex,	unix_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();
Addr	*compoundaddr();
Addr	*simpleaddr();
uchar	line[BLOCKSIZE];
uchar	termline[BLOCKSIZE];
uchar	*linep=line;
uchar	*terminp=termline;
uchar	*termoutp=termline;
List	cmdlist;
List	addrlist;
List	relist;
List	stringlist;
int	eof;

resetcmd(){
	linep=line;
	*linep=0;
	terminp=termoutp=termline;
	freecmd();
}
getc(){
	if(eof)
		return -1;
	if(*linep==0 && inputline()<0){
		eof=TRUE;
		return -1;
	}
	return *linep++;
}
nextc(){
	if(*linep==0)
		return -1;
	return *linep;
}
ungetc(){
	if(--linep<line)
		panic("ungetc");
}
inputline(){
	register i, c;
	linep=line;
	i=0;
	do{
		if((c=inputc())<=0)
			return -1;
		if(i==(sizeof line)-1)
			error(Etoolong);
	}while((line[i++]=c)!='\n');
	line[i]=0;
	return 1;
}
termcommand()
{
	register Posn p;
	dounlock=TRUE;
	Fgetcset(cmd, cmdpt);
	for(p=cmdpt; p<cmd->nbytes; p++)
		*terminp++=Fgetc(cmd);
	cmdpt=cmd->nbytes;
}
inputc()
{
	register c, n;
	uchar cc;
   Again:
	if(downloaded){
		while(termoutp==terminp){
			if(cmd && cmd->mod!=0){
				Fupdate(cmd, FALSE, downloaded);
				cmd->dot.r.p1=cmd->dot.r.p2=cmd->nbytes;
				telldot(cmd);
			}
			if(dounlock){
				outT0(Hunlock);
				dounlock=FALSE;
			}
			if(patset)
				tellpat();
			if(rcv()==0)
				return -1;
		}
		c= *termoutp++;
		if(termoutp==terminp)
			terminp=termoutp=termline;
		n=1;
	}else{
		n=read(0, (char *)&cc, 1);
		c=cc;
	}
	if(n<=0)
		return -1;
	if(c==0 || (c&HIGHBIT)){
		warn(Wnonascii);
		goto Again;
	}
	return c;
}
cmdloop(){
	Cmd *cmdp;
	File *ocurfile;
	int loaded;
	for(;;){
		if(!downloaded && curfile && curfile->state==Unread)
			load(curfile);
		if((cmdp=parsecmd(0))==0)
			break;
		ocurfile=curfile;
		loaded=curfile && curfile->state!=Unread;
		if(cmdexec(curfile, cmdp)==0)
			break;
		freecmd();
		update();
		if(downloaded && curfile &&
		    (ocurfile!=curfile || (!loaded && curfile->state!=Unread)))
			outTs(Hcurrent, curfile->tag);
	}
}
Cmd *
newcmd(){
	register Cmd *p;
	p=new(Cmd, 1);
	inslist(&cmdlist, cmdlist.nused, (long)p);
	return p;
}
Addr *
newaddr(){
	register Addr *p;
	p=new(Addr, 1);
	inslist(&addrlist, addrlist.nused, (long)p);
	return p;
}
Regexp *
newre(){
	register Regexp *p;
	p=new(Regexp, 1);
	inslist(&relist, relist.nused, (long)p);
	strinit(&p->text);
	return p;
}
String *
newstring(){
	register String *p;
	p=new(String, 1);
	inslist(&stringlist, stringlist.nused, (long)p);
	strinit(p);
	return p;
}
freecmd()
{
	register i;
	while(cmdlist.nused>0)
		free((uchar *)cmdlist.ptr[--cmdlist.nused]);
	while(addrlist.nused>0)
		free((uchar *)addrlist.ptr[--addrlist.nused]);
	while(relist.nused>0){
		i= --relist.nused;
		strclose(&((Regexp *)relist.ptr[i])->text);
		free((uchar *)relist.ptr[i]);	/* WARNING!! */
	}
	while(stringlist.nused>0){
		i= --stringlist.nused;
		strclose((String *)stringlist.ptr[i]);
		free((uchar *)stringlist.ptr[i]);
	}
}
lookup(c)
	register c;
{
	register i;
	for(i=0; cmdtab[i].cmdc; i++)
		if(cmdtab[i].cmdc==c)
			return i;
	return -1;
}
okdelim(c){
	if(c=='\\' || ('a'<=c && c<='z') || ('A'<=c && c<='Z') || ('0'<=c && c<='9'))
		error_c(Edelim, c);
}
atnl(){
	skipbl();
	if(getc()!='\n')
		error(Enewline);
}
getrhs(s, delim, cmd)
	register String *s;
	register delim;
{
	register c;
	while((c=getc())>0 && c!=delim && c!='\n'){
		if(c=='\\'){
			if((c=getc())<=0)
				error(Ebadrhs);
			if(c=='\n'){
				ungetc();
				c='\\';
			}else if(c=='n')
				c='\n';
			else if(c!=delim && (cmd=='s' || c!='\\'))	/* s does its own */
				straddc(s, '\\');
		}
		straddc(s, c);
	}
	ungetc();	/* let client read whether delimeter, '\n' or whatever */
}
String *
collecttoken(end)
	register char *end;
{
	register String *s=newstring();
	register c, i;
	i=0;
	while((c=nextc())==' ' || c=='\t')
		i++, straddc(s, getc()); /* blanks significant for getname() */
	while((c=getc())>0 && strchr(end, c)==0)
		i++, straddc(s, c);
	straddc(s, 0);
	if(c!='\n')
		atnl();
	return s;
}
String *
collecttext(){
	register String *s=newstring();
	register begline, i;
	register c, delim;
	if(skipbl()=='\n'){
		getc();
		i=0;
		do{
			begline=i;
			while((c=getc())>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, (long)s->n-2, (long)s->n);
	}else{
		okdelim(delim=getc());
		getrhs(s, delim, 'a');
		if(nextc()==delim)
			getc();
		atnl();
	}
    Return:
	straddc(s, 0);		/* JUST FOR CMDPRINT() */
	return s;
}
Cmd *
parsecmd(nest)
{
	register i, c;
	register struct cmdtab *ct;
	register 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=getc())==-1)
		return 0;
	cmd.cmdc=c;
	if(cmd.cmdc=='c' && nextc()=='d'){	/* sleazy two-character case */
		getc();		/* 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();
		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=getc())=='\n' || c<0)
					error(Enopattern);
				cmd.re=getregexp(c);
				if(ct->cmdc=='s'){
					cmd.ctext=newstring();
					getrhs(cmd.ctext, c, 's');
					if(nextc()==c){
						getc();
						if(nextc()=='g')
							cmd.flag=getc();
					}
			
				}
			}
		}
		if(ct->addr && (cmd.caddr=simpleaddr())==0)
			error(Eaddress);
		if(ct->defcmd){
			if(skipbl()=='\n'){
				getc();
				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')
					getc();
				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;
}
Regexp *				/* BUGGERED */
getregexp(delim)
	register delim;
{
	register Regexp *r=newre();
	register c;
	for(strzero(&genstr); ; straddc(&genstr, c))
		if((c=getc())=='\\'){
			if(nextc()==delim)
				c=getc();
			else if(nextc()=='\\'){
				straddc(&genstr, c);
				c=getc();
			}
		}else if(c==delim || c=='\n')
			break;
	if(c!=delim && c)
		ungetc();
	if(genstr.n>0){
		patset=TRUE;
		strdupstr(&lastpat, &genstr);
		straddc(&lastpat, '\0');
	}
	if(lastpat.n<=1)
		error(Epattern);
	strdupstr(&r->text, &lastpat);
	return r;
}
Addr *
compoundaddr(){
	Addr addr;
	register Addr *ap;
	addr.aprev=simpleaddr();
	if((addr.type=skipbl())!=',' && addr.type!=';')
		return addr.aprev;
	getc();
	addr.next=compoundaddr();
	if(addr.next && addr.next->aprev==0)
		error(Eaddress);
	ap=newaddr();
	*ap=addr;
	return ap;
}
Addr *
simpleaddr()
{
	Addr addr;
	register Addr *ap, *nap;
	addr.next=0;
	switch(skipbl()){
	case '#':
		addr.type=getc();
		addr.num=getnum();
		break;
	case '0': case '1': case '2': case '3': case '4':
	case '5': case '6': case '7': case '8': case '9': 
		addr.num=getnum();
		addr.type='l';
		break;
	case '/': case '?': case '"':
		addr.are=getregexp(addr.type=getc());
		break;
	case '.':
	case '$':
	case '+':
	case '-':
	case '\'':
		addr.type=getc();
		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;
}