sync with plan 9

This commit is contained in:
rsc 2007-03-26 12:02:41 +00:00
parent 79049567a0
commit c8f538425f
23 changed files with 1962 additions and 1227 deletions

View file

@ -7,9 +7,9 @@
#define c1 t->child[1]
#define c2 t->child[2]
int codep, ncode;
#define emitf(x) ((void)(codep!=ncode || morecode()), codebuf[codep].f=(x), codep++)
#define emiti(x) ((void)(codep!=ncode || morecode()), codebuf[codep].i=(x), codep++)
#define emits(x) ((void)(codep!=ncode || morecode()), codebuf[codep].s=(x), codep++)
#define emitf(x) ((void)(codep!=ncode || morecode()), codebuf[codep].f = (x), codep++)
#define emiti(x) ((void)(codep!=ncode || morecode()), codebuf[codep].i = (x), codep++)
#define emits(x) ((void)(codep!=ncode || morecode()), codebuf[codep].s = (x), codep++)
void stuffdot(int);
char *fnstr(tree*);
void outcode(tree*, int);
@ -17,22 +17,32 @@ void codeswitch(tree*, int);
int iscase(tree*);
code *codecopy(code*);
void codefree(code*);
int morecode(void){
int
morecode(void)
{
ncode+=100;
codebuf=(code *)realloc((char *)codebuf, ncode*sizeof codebuf[0]);
if(codebuf==0) panic("Can't realloc %d bytes in morecode!",
codebuf = (code *)realloc((char *)codebuf, ncode*sizeof codebuf[0]);
if(codebuf==0)
panic("Can't realloc %d bytes in morecode!",
ncode*sizeof codebuf[0]);
return 0;
}
void stuffdot(int a){
if(a<0 || codep<=a) panic("Bad address %d in stuffdot", a);
codebuf[a].i=codep;
}
int compile(tree *t)
void
stuffdot(int a)
{
ncode=100;
codebuf=(code *)emalloc(ncode*sizeof codebuf[0]);
codep=0;
if(a<0 || codep<=a)
panic("Bad address %d in stuffdot", a);
codebuf[a].i = codep;
}
int
compile(tree *t)
{
ncode = 100;
codebuf = (code *)emalloc(ncode*sizeof codebuf[0]);
codep = 0;
emiti(0); /* reference count */
outcode(t, flag['e']?1:0);
if(nerror){
@ -44,31 +54,39 @@ int compile(tree *t)
emitf(0);
return 1;
}
void cleanhere(char *f)
void
cleanhere(char *f)
{
emitf(Xdelhere);
emits(strdup(f));
}
char *fnstr(tree *t)
char*
fnstr(tree *t)
{
io *f=openstr();
io *f = openstr();
char *v;
extern char nl;
char svnl=nl;
char svnl = nl;
nl=';';
pfmt(f, "%t", t);
nl=svnl;
v=f->strp;
f->strp=0;
nl = svnl;
v = f->strp;
f->strp = 0;
closeio(f);
return v;
}
void outcode(tree *t, int eflag)
void
outcode(tree *t, int eflag)
{
int p, q;
tree *tt;
if(t==0) return;
if(t->type!=NOT && t->type!=';') runq->iflast=0;
if(t==0)
return;
if(t->type!=NOT && t->type!=';')
runq->iflast = 0;
switch(t->type){
default:
pfmt(err, "bad type %d in outcode\n", t->type);
@ -92,10 +110,13 @@ void outcode(tree *t, int eflag)
break;
case '&':
emitf(Xasync);
p=emiti(0);
outcode(c0, eflag);
emitf(Xexit);
stuffdot(p);
if(havefork){
p = emiti(0);
outcode(c0, eflag);
emitf(Xexit);
stuffdot(p);
} else
emits(fnstr(c0));
break;
case ';':
outcode(c0, eflag);
@ -110,15 +131,18 @@ void outcode(tree *t, int eflag)
break;
case '`':
emitf(Xbackq);
p=emiti(0);
outcode(c0, 0);
emitf(Xexit);
stuffdot(p);
if(havefork){
p = emiti(0);
outcode(c0, 0);
emitf(Xexit);
stuffdot(p);
} else
emits(fnstr(c0));
break;
case ANDAND:
outcode(c0, 0);
emitf(Xtrue);
p=emiti(0);
p = emiti(0);
outcode(c1, eflag);
stuffdot(p);
break;
@ -144,7 +168,7 @@ void outcode(tree *t, int eflag)
outcode(c0, eflag);
if(c1){
emitf(Xfn);
p=emiti(0);
p = emiti(0);
emits(fnstr(c1));
outcode(c1, eflag);
emitf(Xunlocal); /* get rid of $* */
@ -157,22 +181,23 @@ void outcode(tree *t, int eflag)
case IF:
outcode(c0, 0);
emitf(Xif);
p=emiti(0);
p = emiti(0);
outcode(c1, eflag);
emitf(Xwastrue);
stuffdot(p);
break;
case NOT:
if(!runq->iflast) yyerror("`if not' does not follow `if(...)'");
if(!runq->iflast)
yyerror("`if not' does not follow `if(...)'");
emitf(Xifnot);
p=emiti(0);
p = emiti(0);
outcode(c0, eflag);
stuffdot(p);
break;
case OROR:
outcode(c0, 0);
emitf(Xfalse);
p=emiti(0);
p = emiti(0);
outcode(c1, eflag);
stuffdot(p);
break;
@ -183,15 +208,20 @@ void outcode(tree *t, int eflag)
emitf(Xmark);
outcode(c0, eflag);
emitf(Xsimple);
if(eflag) emitf(Xeflag);
if(eflag)
emitf(Xeflag);
break;
case SUBSHELL:
emitf(Xsubshell);
p=emiti(0);
outcode(c0, eflag);
emitf(Xexit);
stuffdot(p);
if(eflag) emitf(Xeflag);
if(havefork){
p = emiti(0);
outcode(c0, eflag);
emitf(Xexit);
stuffdot(p);
} else
emits(fnstr(c0));
if(eflag)
emitf(Xeflag);
break;
case SWITCH:
codeswitch(t, eflag);
@ -202,14 +232,16 @@ void outcode(tree *t, int eflag)
emitf(Xmark);
outcode(c0, eflag);
emitf(Xmatch);
if(eflag) emitf(Xeflag);
if(eflag)
emitf(Xeflag);
break;
case WHILE:
q=codep;
q = codep;
outcode(c0, 0);
if(q==codep) emitf(Xsettrue); /* empty condition == while(true) */
if(q==codep)
emitf(Xsettrue); /* empty condition == while(true) */
emitf(Xtrue);
p=emiti(0);
p = emiti(0);
outcode(c1, eflag);
emitf(Xjump);
emiti(q);
@ -235,8 +267,8 @@ void outcode(tree *t, int eflag)
emitf(Xmark);
outcode(c0, eflag);
emitf(Xlocal);
p=emitf(Xfor);
q=emiti(0);
p = emitf(Xfor);
q = emiti(0);
outcode(c2, eflag);
emitf(Xjump);
emiti(p);
@ -263,10 +295,14 @@ void outcode(tree *t, int eflag)
case PIPEFD:
emitf(Xpipefd);
emiti(t->rtype);
p=emiti(0);
outcode(c0, eflag);
emitf(Xexit);
stuffdot(p);
if(havefork){
p = emiti(0);
outcode(c0, eflag);
emitf(Xexit);
stuffdot(p);
} else {
emits(fnstr(c0));
}
break;
case REDIR:
emitf(Xmark);
@ -283,28 +319,31 @@ void outcode(tree *t, int eflag)
case HERE:
emitf(Xread);
break;
case RDWR:
emitf(Xrdwr);
break;
}
emiti(t->fd0);
outcode(c1, eflag);
emitf(Xpopredir);
break;
case '=':
tt=t;
for(;t && t->type=='=';t=c2);
tt = t;
for(;t && t->type=='=';t = c2);
if(t){
for(t=tt;t->type=='=';t=c2){
for(t = tt;t->type=='=';t = c2){
emitf(Xmark);
outcode(c1, eflag);
emitf(Xmark);
outcode(c0, eflag);
emitf(Xlocal);
}
t=tt;
t = tt;
outcode(c2, eflag);
for(;t->type=='=';t=c2) emitf(Xunlocal);
for(;t->type=='=';t = c2) emitf(Xunlocal);
}
else{
for(t=tt;t;t=c2){
for(t = tt;t;t = c2){
emitf(Xmark);
outcode(c1, eflag);
emitf(Xmark);
@ -312,17 +351,22 @@ void outcode(tree *t, int eflag)
emitf(Xassign);
}
}
t=tt; /* so tests below will work */
t = tt; /* so tests below will work */
break;
case PIPE:
emitf(Xpipe);
emiti(t->fd0);
emiti(t->fd1);
p=emiti(0);
q=emiti(0);
outcode(c0, eflag);
emitf(Xexit);
stuffdot(p);
if(havefork){
p = emiti(0);
q = emiti(0);
outcode(c0, eflag);
emitf(Xexit);
stuffdot(p);
} else {
emits(fnstr(c0));
q = emiti(0);
}
outcode(c1, eflag);
emitf(Xreturn);
stuffdot(q);
@ -330,8 +374,8 @@ void outcode(tree *t, int eflag)
break;
}
if(t->type!=NOT && t->type!=';')
runq->iflast=t->type==IF;
else if(c0) runq->iflast=c0->type==IF;
runq->iflast = t->type==IF;
else if(c0) runq->iflast = c0->type==IF;
}
/*
* switch code looks like this:
@ -353,7 +397,9 @@ void outcode(tree *t, int eflag)
* leave:
* Xpopm
*/
void codeswitch(tree *t, int eflag)
void
codeswitch(tree *t, int eflag)
{
int leave; /* patch jump address to leave switch */
int out; /* jump here to leave switch */
@ -368,23 +414,23 @@ void codeswitch(tree *t, int eflag)
emitf(Xmark);
outcode(c0, eflag);
emitf(Xjump);
nextcase=emiti(0);
out=emitf(Xjump);
leave=emiti(0);
nextcase = emiti(0);
out = emitf(Xjump);
leave = emiti(0);
stuffdot(nextcase);
t=c1->child[0];
t = c1->child[0];
while(t->type==';'){
tt=c1;
tt = c1;
emitf(Xmark);
for(t=c0->child[0];t->type==ARGLIST;t=c0) outcode(c1, eflag);
for(t = c0->child[0];t->type==ARGLIST;t = c0) outcode(c1, eflag);
emitf(Xcase);
nextcase=emiti(0);
t=tt;
nextcase = emiti(0);
t = tt;
for(;;){
if(t->type==';'){
if(iscase(c0)) break;
outcode(c0, eflag);
t=c1;
t = c1;
}
else{
if(!iscase(t)) outcode(t, eflag);
@ -398,23 +444,32 @@ void codeswitch(tree *t, int eflag)
stuffdot(leave);
emitf(Xpopm);
}
int iscase(tree *t)
int
iscase(tree *t)
{
if(t->type!=SIMPLE) return 0;
do t=c0; while(t->type==ARGLIST);
if(t->type!=SIMPLE)
return 0;
do t = c0; while(t->type==ARGLIST);
return t->type==WORD && !t->quoted && strcmp(t->str, "case")==0;
}
code *codecopy(code *cp)
code*
codecopy(code *cp)
{
cp[0].i++;
return cp;
}
void codefree(code *cp)
void
codefree(code *cp)
{
code *p;
if(--cp[0].i!=0) return;
for(p=cp+1;p->f;p++){
if(--cp[0].i!=0)
return;
for(p = cp+1;p->f;p++){
if(p->f==Xappend || p->f==Xclose || p->f==Xread || p->f==Xwrite
|| p->f==Xrdwr
|| p->f==Xasync || p->f==Xbackq || p->f==Xcase || p->f==Xfalse
|| p->f==Xfor || p->f==Xjump
|| p->f==Xsubshell || p->f==Xtrue) p++;