sync with plan 9
This commit is contained in:
parent
79049567a0
commit
c8f538425f
23 changed files with 1962 additions and 1227 deletions
|
|
@ -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++;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue