sync with plan 9
This commit is contained in:
parent
79049567a0
commit
c8f538425f
@ -7,9 +7,9 @@
|
|||||||
#define c1 t->child[1]
|
#define c1 t->child[1]
|
||||||
#define c2 t->child[2]
|
#define c2 t->child[2]
|
||||||
int codep, ncode;
|
int codep, ncode;
|
||||||
#define emitf(x) ((void)(codep!=ncode || morecode()), codebuf[codep].f=(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 emiti(x) ((void)(codep!=ncode || morecode()), codebuf[codep].i = (x), codep++)
|
||||||
#define emits(x) ((void)(codep!=ncode || morecode()), codebuf[codep].s=(x), codep++)
|
#define emits(x) ((void)(codep!=ncode || morecode()), codebuf[codep].s = (x), codep++)
|
||||||
void stuffdot(int);
|
void stuffdot(int);
|
||||||
char *fnstr(tree*);
|
char *fnstr(tree*);
|
||||||
void outcode(tree*, int);
|
void outcode(tree*, int);
|
||||||
@ -17,22 +17,32 @@ void codeswitch(tree*, int);
|
|||||||
int iscase(tree*);
|
int iscase(tree*);
|
||||||
code *codecopy(code*);
|
code *codecopy(code*);
|
||||||
void codefree(code*);
|
void codefree(code*);
|
||||||
int morecode(void){
|
|
||||||
|
int
|
||||||
|
morecode(void)
|
||||||
|
{
|
||||||
ncode+=100;
|
ncode+=100;
|
||||||
codebuf=(code *)realloc((char *)codebuf, ncode*sizeof codebuf[0]);
|
codebuf = (code *)realloc((char *)codebuf, ncode*sizeof codebuf[0]);
|
||||||
if(codebuf==0) panic("Can't realloc %d bytes in morecode!",
|
if(codebuf==0)
|
||||||
|
panic("Can't realloc %d bytes in morecode!",
|
||||||
ncode*sizeof codebuf[0]);
|
ncode*sizeof codebuf[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void stuffdot(int a){
|
|
||||||
if(a<0 || codep<=a) panic("Bad address %d in stuffdot", a);
|
void
|
||||||
codebuf[a].i=codep;
|
stuffdot(int a)
|
||||||
}
|
|
||||||
int compile(tree *t)
|
|
||||||
{
|
{
|
||||||
ncode=100;
|
if(a<0 || codep<=a)
|
||||||
codebuf=(code *)emalloc(ncode*sizeof codebuf[0]);
|
panic("Bad address %d in stuffdot", a);
|
||||||
codep=0;
|
codebuf[a].i = codep;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
compile(tree *t)
|
||||||
|
{
|
||||||
|
ncode = 100;
|
||||||
|
codebuf = (code *)emalloc(ncode*sizeof codebuf[0]);
|
||||||
|
codep = 0;
|
||||||
emiti(0); /* reference count */
|
emiti(0); /* reference count */
|
||||||
outcode(t, flag['e']?1:0);
|
outcode(t, flag['e']?1:0);
|
||||||
if(nerror){
|
if(nerror){
|
||||||
@ -44,31 +54,39 @@ int compile(tree *t)
|
|||||||
emitf(0);
|
emitf(0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
void cleanhere(char *f)
|
|
||||||
|
void
|
||||||
|
cleanhere(char *f)
|
||||||
{
|
{
|
||||||
emitf(Xdelhere);
|
emitf(Xdelhere);
|
||||||
emits(strdup(f));
|
emits(strdup(f));
|
||||||
}
|
}
|
||||||
char *fnstr(tree *t)
|
|
||||||
|
char*
|
||||||
|
fnstr(tree *t)
|
||||||
{
|
{
|
||||||
io *f=openstr();
|
io *f = openstr();
|
||||||
char *v;
|
char *v;
|
||||||
extern char nl;
|
extern char nl;
|
||||||
char svnl=nl;
|
char svnl = nl;
|
||||||
nl=';';
|
nl=';';
|
||||||
pfmt(f, "%t", t);
|
pfmt(f, "%t", t);
|
||||||
nl=svnl;
|
nl = svnl;
|
||||||
v=f->strp;
|
v = f->strp;
|
||||||
f->strp=0;
|
f->strp = 0;
|
||||||
closeio(f);
|
closeio(f);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
void outcode(tree *t, int eflag)
|
|
||||||
|
void
|
||||||
|
outcode(tree *t, int eflag)
|
||||||
{
|
{
|
||||||
int p, q;
|
int p, q;
|
||||||
tree *tt;
|
tree *tt;
|
||||||
if(t==0) return;
|
if(t==0)
|
||||||
if(t->type!=NOT && t->type!=';') runq->iflast=0;
|
return;
|
||||||
|
if(t->type!=NOT && t->type!=';')
|
||||||
|
runq->iflast = 0;
|
||||||
switch(t->type){
|
switch(t->type){
|
||||||
default:
|
default:
|
||||||
pfmt(err, "bad type %d in outcode\n", t->type);
|
pfmt(err, "bad type %d in outcode\n", t->type);
|
||||||
@ -92,10 +110,13 @@ void outcode(tree *t, int eflag)
|
|||||||
break;
|
break;
|
||||||
case '&':
|
case '&':
|
||||||
emitf(Xasync);
|
emitf(Xasync);
|
||||||
p=emiti(0);
|
if(havefork){
|
||||||
outcode(c0, eflag);
|
p = emiti(0);
|
||||||
emitf(Xexit);
|
outcode(c0, eflag);
|
||||||
stuffdot(p);
|
emitf(Xexit);
|
||||||
|
stuffdot(p);
|
||||||
|
} else
|
||||||
|
emits(fnstr(c0));
|
||||||
break;
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
outcode(c0, eflag);
|
outcode(c0, eflag);
|
||||||
@ -110,15 +131,18 @@ void outcode(tree *t, int eflag)
|
|||||||
break;
|
break;
|
||||||
case '`':
|
case '`':
|
||||||
emitf(Xbackq);
|
emitf(Xbackq);
|
||||||
p=emiti(0);
|
if(havefork){
|
||||||
outcode(c0, 0);
|
p = emiti(0);
|
||||||
emitf(Xexit);
|
outcode(c0, 0);
|
||||||
stuffdot(p);
|
emitf(Xexit);
|
||||||
|
stuffdot(p);
|
||||||
|
} else
|
||||||
|
emits(fnstr(c0));
|
||||||
break;
|
break;
|
||||||
case ANDAND:
|
case ANDAND:
|
||||||
outcode(c0, 0);
|
outcode(c0, 0);
|
||||||
emitf(Xtrue);
|
emitf(Xtrue);
|
||||||
p=emiti(0);
|
p = emiti(0);
|
||||||
outcode(c1, eflag);
|
outcode(c1, eflag);
|
||||||
stuffdot(p);
|
stuffdot(p);
|
||||||
break;
|
break;
|
||||||
@ -144,7 +168,7 @@ void outcode(tree *t, int eflag)
|
|||||||
outcode(c0, eflag);
|
outcode(c0, eflag);
|
||||||
if(c1){
|
if(c1){
|
||||||
emitf(Xfn);
|
emitf(Xfn);
|
||||||
p=emiti(0);
|
p = emiti(0);
|
||||||
emits(fnstr(c1));
|
emits(fnstr(c1));
|
||||||
outcode(c1, eflag);
|
outcode(c1, eflag);
|
||||||
emitf(Xunlocal); /* get rid of $* */
|
emitf(Xunlocal); /* get rid of $* */
|
||||||
@ -157,22 +181,23 @@ void outcode(tree *t, int eflag)
|
|||||||
case IF:
|
case IF:
|
||||||
outcode(c0, 0);
|
outcode(c0, 0);
|
||||||
emitf(Xif);
|
emitf(Xif);
|
||||||
p=emiti(0);
|
p = emiti(0);
|
||||||
outcode(c1, eflag);
|
outcode(c1, eflag);
|
||||||
emitf(Xwastrue);
|
emitf(Xwastrue);
|
||||||
stuffdot(p);
|
stuffdot(p);
|
||||||
break;
|
break;
|
||||||
case NOT:
|
case NOT:
|
||||||
if(!runq->iflast) yyerror("`if not' does not follow `if(...)'");
|
if(!runq->iflast)
|
||||||
|
yyerror("`if not' does not follow `if(...)'");
|
||||||
emitf(Xifnot);
|
emitf(Xifnot);
|
||||||
p=emiti(0);
|
p = emiti(0);
|
||||||
outcode(c0, eflag);
|
outcode(c0, eflag);
|
||||||
stuffdot(p);
|
stuffdot(p);
|
||||||
break;
|
break;
|
||||||
case OROR:
|
case OROR:
|
||||||
outcode(c0, 0);
|
outcode(c0, 0);
|
||||||
emitf(Xfalse);
|
emitf(Xfalse);
|
||||||
p=emiti(0);
|
p = emiti(0);
|
||||||
outcode(c1, eflag);
|
outcode(c1, eflag);
|
||||||
stuffdot(p);
|
stuffdot(p);
|
||||||
break;
|
break;
|
||||||
@ -183,15 +208,20 @@ void outcode(tree *t, int eflag)
|
|||||||
emitf(Xmark);
|
emitf(Xmark);
|
||||||
outcode(c0, eflag);
|
outcode(c0, eflag);
|
||||||
emitf(Xsimple);
|
emitf(Xsimple);
|
||||||
if(eflag) emitf(Xeflag);
|
if(eflag)
|
||||||
|
emitf(Xeflag);
|
||||||
break;
|
break;
|
||||||
case SUBSHELL:
|
case SUBSHELL:
|
||||||
emitf(Xsubshell);
|
emitf(Xsubshell);
|
||||||
p=emiti(0);
|
if(havefork){
|
||||||
outcode(c0, eflag);
|
p = emiti(0);
|
||||||
emitf(Xexit);
|
outcode(c0, eflag);
|
||||||
stuffdot(p);
|
emitf(Xexit);
|
||||||
if(eflag) emitf(Xeflag);
|
stuffdot(p);
|
||||||
|
} else
|
||||||
|
emits(fnstr(c0));
|
||||||
|
if(eflag)
|
||||||
|
emitf(Xeflag);
|
||||||
break;
|
break;
|
||||||
case SWITCH:
|
case SWITCH:
|
||||||
codeswitch(t, eflag);
|
codeswitch(t, eflag);
|
||||||
@ -202,14 +232,16 @@ void outcode(tree *t, int eflag)
|
|||||||
emitf(Xmark);
|
emitf(Xmark);
|
||||||
outcode(c0, eflag);
|
outcode(c0, eflag);
|
||||||
emitf(Xmatch);
|
emitf(Xmatch);
|
||||||
if(eflag) emitf(Xeflag);
|
if(eflag)
|
||||||
|
emitf(Xeflag);
|
||||||
break;
|
break;
|
||||||
case WHILE:
|
case WHILE:
|
||||||
q=codep;
|
q = codep;
|
||||||
outcode(c0, 0);
|
outcode(c0, 0);
|
||||||
if(q==codep) emitf(Xsettrue); /* empty condition == while(true) */
|
if(q==codep)
|
||||||
|
emitf(Xsettrue); /* empty condition == while(true) */
|
||||||
emitf(Xtrue);
|
emitf(Xtrue);
|
||||||
p=emiti(0);
|
p = emiti(0);
|
||||||
outcode(c1, eflag);
|
outcode(c1, eflag);
|
||||||
emitf(Xjump);
|
emitf(Xjump);
|
||||||
emiti(q);
|
emiti(q);
|
||||||
@ -235,8 +267,8 @@ void outcode(tree *t, int eflag)
|
|||||||
emitf(Xmark);
|
emitf(Xmark);
|
||||||
outcode(c0, eflag);
|
outcode(c0, eflag);
|
||||||
emitf(Xlocal);
|
emitf(Xlocal);
|
||||||
p=emitf(Xfor);
|
p = emitf(Xfor);
|
||||||
q=emiti(0);
|
q = emiti(0);
|
||||||
outcode(c2, eflag);
|
outcode(c2, eflag);
|
||||||
emitf(Xjump);
|
emitf(Xjump);
|
||||||
emiti(p);
|
emiti(p);
|
||||||
@ -263,10 +295,14 @@ void outcode(tree *t, int eflag)
|
|||||||
case PIPEFD:
|
case PIPEFD:
|
||||||
emitf(Xpipefd);
|
emitf(Xpipefd);
|
||||||
emiti(t->rtype);
|
emiti(t->rtype);
|
||||||
p=emiti(0);
|
if(havefork){
|
||||||
outcode(c0, eflag);
|
p = emiti(0);
|
||||||
emitf(Xexit);
|
outcode(c0, eflag);
|
||||||
stuffdot(p);
|
emitf(Xexit);
|
||||||
|
stuffdot(p);
|
||||||
|
} else {
|
||||||
|
emits(fnstr(c0));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case REDIR:
|
case REDIR:
|
||||||
emitf(Xmark);
|
emitf(Xmark);
|
||||||
@ -283,28 +319,31 @@ void outcode(tree *t, int eflag)
|
|||||||
case HERE:
|
case HERE:
|
||||||
emitf(Xread);
|
emitf(Xread);
|
||||||
break;
|
break;
|
||||||
|
case RDWR:
|
||||||
|
emitf(Xrdwr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
emiti(t->fd0);
|
emiti(t->fd0);
|
||||||
outcode(c1, eflag);
|
outcode(c1, eflag);
|
||||||
emitf(Xpopredir);
|
emitf(Xpopredir);
|
||||||
break;
|
break;
|
||||||
case '=':
|
case '=':
|
||||||
tt=t;
|
tt = t;
|
||||||
for(;t && t->type=='=';t=c2);
|
for(;t && t->type=='=';t = c2);
|
||||||
if(t){
|
if(t){
|
||||||
for(t=tt;t->type=='=';t=c2){
|
for(t = tt;t->type=='=';t = c2){
|
||||||
emitf(Xmark);
|
emitf(Xmark);
|
||||||
outcode(c1, eflag);
|
outcode(c1, eflag);
|
||||||
emitf(Xmark);
|
emitf(Xmark);
|
||||||
outcode(c0, eflag);
|
outcode(c0, eflag);
|
||||||
emitf(Xlocal);
|
emitf(Xlocal);
|
||||||
}
|
}
|
||||||
t=tt;
|
t = tt;
|
||||||
outcode(c2, eflag);
|
outcode(c2, eflag);
|
||||||
for(;t->type=='=';t=c2) emitf(Xunlocal);
|
for(;t->type=='=';t = c2) emitf(Xunlocal);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
for(t=tt;t;t=c2){
|
for(t = tt;t;t = c2){
|
||||||
emitf(Xmark);
|
emitf(Xmark);
|
||||||
outcode(c1, eflag);
|
outcode(c1, eflag);
|
||||||
emitf(Xmark);
|
emitf(Xmark);
|
||||||
@ -312,17 +351,22 @@ void outcode(tree *t, int eflag)
|
|||||||
emitf(Xassign);
|
emitf(Xassign);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t=tt; /* so tests below will work */
|
t = tt; /* so tests below will work */
|
||||||
break;
|
break;
|
||||||
case PIPE:
|
case PIPE:
|
||||||
emitf(Xpipe);
|
emitf(Xpipe);
|
||||||
emiti(t->fd0);
|
emiti(t->fd0);
|
||||||
emiti(t->fd1);
|
emiti(t->fd1);
|
||||||
p=emiti(0);
|
if(havefork){
|
||||||
q=emiti(0);
|
p = emiti(0);
|
||||||
outcode(c0, eflag);
|
q = emiti(0);
|
||||||
emitf(Xexit);
|
outcode(c0, eflag);
|
||||||
stuffdot(p);
|
emitf(Xexit);
|
||||||
|
stuffdot(p);
|
||||||
|
} else {
|
||||||
|
emits(fnstr(c0));
|
||||||
|
q = emiti(0);
|
||||||
|
}
|
||||||
outcode(c1, eflag);
|
outcode(c1, eflag);
|
||||||
emitf(Xreturn);
|
emitf(Xreturn);
|
||||||
stuffdot(q);
|
stuffdot(q);
|
||||||
@ -330,8 +374,8 @@ void outcode(tree *t, int eflag)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(t->type!=NOT && t->type!=';')
|
if(t->type!=NOT && t->type!=';')
|
||||||
runq->iflast=t->type==IF;
|
runq->iflast = t->type==IF;
|
||||||
else if(c0) runq->iflast=c0->type==IF;
|
else if(c0) runq->iflast = c0->type==IF;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* switch code looks like this:
|
* switch code looks like this:
|
||||||
@ -353,7 +397,9 @@ void outcode(tree *t, int eflag)
|
|||||||
* leave:
|
* leave:
|
||||||
* Xpopm
|
* Xpopm
|
||||||
*/
|
*/
|
||||||
void codeswitch(tree *t, int eflag)
|
|
||||||
|
void
|
||||||
|
codeswitch(tree *t, int eflag)
|
||||||
{
|
{
|
||||||
int leave; /* patch jump address to leave switch */
|
int leave; /* patch jump address to leave switch */
|
||||||
int out; /* jump here to leave switch */
|
int out; /* jump here to leave switch */
|
||||||
@ -368,23 +414,23 @@ void codeswitch(tree *t, int eflag)
|
|||||||
emitf(Xmark);
|
emitf(Xmark);
|
||||||
outcode(c0, eflag);
|
outcode(c0, eflag);
|
||||||
emitf(Xjump);
|
emitf(Xjump);
|
||||||
nextcase=emiti(0);
|
nextcase = emiti(0);
|
||||||
out=emitf(Xjump);
|
out = emitf(Xjump);
|
||||||
leave=emiti(0);
|
leave = emiti(0);
|
||||||
stuffdot(nextcase);
|
stuffdot(nextcase);
|
||||||
t=c1->child[0];
|
t = c1->child[0];
|
||||||
while(t->type==';'){
|
while(t->type==';'){
|
||||||
tt=c1;
|
tt = c1;
|
||||||
emitf(Xmark);
|
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);
|
emitf(Xcase);
|
||||||
nextcase=emiti(0);
|
nextcase = emiti(0);
|
||||||
t=tt;
|
t = tt;
|
||||||
for(;;){
|
for(;;){
|
||||||
if(t->type==';'){
|
if(t->type==';'){
|
||||||
if(iscase(c0)) break;
|
if(iscase(c0)) break;
|
||||||
outcode(c0, eflag);
|
outcode(c0, eflag);
|
||||||
t=c1;
|
t = c1;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(!iscase(t)) outcode(t, eflag);
|
if(!iscase(t)) outcode(t, eflag);
|
||||||
@ -398,23 +444,32 @@ void codeswitch(tree *t, int eflag)
|
|||||||
stuffdot(leave);
|
stuffdot(leave);
|
||||||
emitf(Xpopm);
|
emitf(Xpopm);
|
||||||
}
|
}
|
||||||
int iscase(tree *t)
|
|
||||||
|
int
|
||||||
|
iscase(tree *t)
|
||||||
{
|
{
|
||||||
if(t->type!=SIMPLE) return 0;
|
if(t->type!=SIMPLE)
|
||||||
do t=c0; while(t->type==ARGLIST);
|
return 0;
|
||||||
|
do t = c0; while(t->type==ARGLIST);
|
||||||
return t->type==WORD && !t->quoted && strcmp(t->str, "case")==0;
|
return t->type==WORD && !t->quoted && strcmp(t->str, "case")==0;
|
||||||
}
|
}
|
||||||
code *codecopy(code *cp)
|
|
||||||
|
code*
|
||||||
|
codecopy(code *cp)
|
||||||
{
|
{
|
||||||
cp[0].i++;
|
cp[0].i++;
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
void codefree(code *cp)
|
|
||||||
|
void
|
||||||
|
codefree(code *cp)
|
||||||
{
|
{
|
||||||
code *p;
|
code *p;
|
||||||
if(--cp[0].i!=0) return;
|
if(--cp[0].i!=0)
|
||||||
for(p=cp+1;p->f;p++){
|
return;
|
||||||
|
for(p = cp+1;p->f;p++){
|
||||||
if(p->f==Xappend || p->f==Xclose || p->f==Xread || p->f==Xwrite
|
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==Xasync || p->f==Xbackq || p->f==Xcase || p->f==Xfalse
|
||||||
|| p->f==Xfor || p->f==Xjump
|
|| p->f==Xfor || p->f==Xjump
|
||||||
|| p->f==Xsubshell || p->f==Xtrue) p++;
|
|| p->f==Xsubshell || p->f==Xtrue) p++;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@ extern void Xappend(void), Xasync(void), Xbackq(void), Xbang(void), Xclose(void)
|
|||||||
extern void Xconc(void), Xcount(void), Xdelfn(void), Xdol(void), Xqdol(void), Xdup(void);
|
extern void Xconc(void), Xcount(void), Xdelfn(void), Xdol(void), Xqdol(void), Xdup(void);
|
||||||
extern void Xexit(void), Xfalse(void), Xfn(void), Xfor(void), Xglob(void);
|
extern void Xexit(void), Xfalse(void), Xfn(void), Xfor(void), Xglob(void);
|
||||||
extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(void);
|
extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(void);
|
||||||
|
extern void Xrdwr(void);
|
||||||
extern void Xrdfn(void), Xunredir(void), Xstar(void), Xreturn(void), Xsubshell(void);
|
extern void Xrdfn(void), Xunredir(void), Xstar(void), Xreturn(void), Xsubshell(void);
|
||||||
extern void Xtrue(void), Xword(void), Xwrite(void), Xpipefd(void), Xcase(void);
|
extern void Xtrue(void), Xword(void), Xwrite(void), Xpipefd(void), Xcase(void);
|
||||||
extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void);
|
extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void);
|
||||||
@ -51,7 +52,6 @@ struct thread{
|
|||||||
int iflag; /* interactive? */
|
int iflag; /* interactive? */
|
||||||
int lineno; /* linenumber */
|
int lineno; /* linenumber */
|
||||||
int pid; /* process for Xpipewait to wait for */
|
int pid; /* process for Xpipewait to wait for */
|
||||||
int done; /* have we seen a wait message for this process? */
|
|
||||||
char status[NSTATUS]; /* status for Xpipewait */
|
char status[NSTATUS]; /* status for Xpipewait */
|
||||||
tree *treenodes; /* tree nodes created by this process */
|
tree *treenodes; /* tree nodes created by this process */
|
||||||
thread *ret; /* who continues when this finishes */
|
thread *ret; /* who continues when this finishes */
|
||||||
@ -61,12 +61,16 @@ code *codecopy(code*);
|
|||||||
code *codebuf; /* compiler output */
|
code *codebuf; /* compiler output */
|
||||||
int ntrap; /* number of outstanding traps */
|
int ntrap; /* number of outstanding traps */
|
||||||
int trap[NSIG]; /* number of outstanding traps per type */
|
int trap[NSIG]; /* number of outstanding traps per type */
|
||||||
extern struct builtin{
|
struct builtin{
|
||||||
char *name;
|
char *name;
|
||||||
void (*fnc)(void);
|
void (*fnc)(void);
|
||||||
}Builtin[];
|
};
|
||||||
|
extern struct builtin Builtin[];
|
||||||
int eflagok; /* kludge flag so that -e doesn't exit in startup */
|
int eflagok; /* kludge flag so that -e doesn't exit in startup */
|
||||||
|
int havefork;
|
||||||
|
|
||||||
void execcd(void), execwhatis(void), execeval(void), execexec(void);
|
void execcd(void), execwhatis(void), execeval(void), execexec(void);
|
||||||
|
int execforkexec(void);
|
||||||
void execexit(void), execshift(void);
|
void execexit(void), execshift(void);
|
||||||
void execwait(void), execumask(void), execdot(void), execflag(void);
|
void execwait(void), execumask(void), execdot(void), execflag(void);
|
||||||
void execfunc(var*), execcmds(io *);
|
void execfunc(var*), execcmds(io *);
|
||||||
|
|||||||
@ -7,13 +7,14 @@ int Eintr(void);
|
|||||||
int Executable(char*);
|
int Executable(char*);
|
||||||
void Execute(word*, word*);
|
void Execute(word*, word*);
|
||||||
void Exit(char*);
|
void Exit(char*);
|
||||||
|
int ForkExecute(char*, char**, int, int, int);
|
||||||
int Globsize(char*);
|
int Globsize(char*);
|
||||||
int Isatty(int);
|
int Isatty(int);
|
||||||
void Memcpy(char*, char*, long);
|
void Memcpy(char*, char*, long);
|
||||||
void Noerror(void);
|
void Noerror(void);
|
||||||
int Opendir(char*);
|
int Opendir(char*);
|
||||||
long Read(int, char*, long);
|
long Read(int, char*, long);
|
||||||
int Readdir(int, char*);
|
int Readdir(int, char*, int);
|
||||||
long Seek(int, long, long);
|
long Seek(int, long, long);
|
||||||
void Trapinit(void);
|
void Trapinit(void);
|
||||||
void Unlink(char*);
|
void Unlink(char*);
|
||||||
@ -27,7 +28,6 @@ void cleanhere(char*);
|
|||||||
void codefree(code*);
|
void codefree(code*);
|
||||||
int compile(tree*);
|
int compile(tree*);
|
||||||
char * list2str(word*);
|
char * list2str(word*);
|
||||||
char * _list2str(word*, int);
|
|
||||||
int count(word*);
|
int count(word*);
|
||||||
void deglob(char*);
|
void deglob(char*);
|
||||||
void dotrap(void);
|
void dotrap(void);
|
||||||
@ -35,10 +35,12 @@ void freenodes(void);
|
|||||||
void freewords(word*);
|
void freewords(word*);
|
||||||
void globlist(void);
|
void globlist(void);
|
||||||
int idchr(int);
|
int idchr(int);
|
||||||
void itoa(char*, long);
|
void inttoascii(char*, long);
|
||||||
void kinit(void);
|
void kinit(void);
|
||||||
|
int mapfd(int);
|
||||||
int match(char*, char*, int);
|
int match(char*, char*, int);
|
||||||
int matchfn(char*, char*);
|
int matchfn(char*, char*);
|
||||||
|
char** mkargv(word*);
|
||||||
void panic(char*, int);
|
void panic(char*, int);
|
||||||
void pathinit(void);
|
void pathinit(void);
|
||||||
void poplist(void);
|
void poplist(void);
|
||||||
@ -48,9 +50,9 @@ void pushlist(void);
|
|||||||
void pushredir(int, int, int);
|
void pushredir(int, int, int);
|
||||||
void pushword(char*);
|
void pushword(char*);
|
||||||
void readhere(void);
|
void readhere(void);
|
||||||
|
word* searchpath(char*);
|
||||||
void setstatus(char*);
|
void setstatus(char*);
|
||||||
void setvar(char*, word*);
|
void setvar(char*, word*);
|
||||||
void _setvar(char*, word*, int);
|
|
||||||
void skipnl(void);
|
void skipnl(void);
|
||||||
void start(code*, int, var*);
|
void start(code*, int, var*);
|
||||||
int truestatus(void);
|
int truestatus(void);
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "getflags.h"
|
#include "getflags.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
char *flagset[]={"<flag>"};
|
char *flagset[] = {"<flag>"};
|
||||||
char **flag[NFLAG];
|
char **flag[NFLAG];
|
||||||
char cmdline[NCMDLINE+1];
|
char cmdline[NCMDLINE+1];
|
||||||
char *cmdname;
|
char *cmdname;
|
||||||
@ -19,105 +19,118 @@ static int reason;
|
|||||||
#define FLAGSYN 3
|
#define FLAGSYN 3
|
||||||
#define BADFLAG 4
|
#define BADFLAG 4
|
||||||
static int badflag;
|
static int badflag;
|
||||||
int getflags(int argc, char *argv[], char *flags, int stop)
|
|
||||||
|
int
|
||||||
|
getflags(int argc, char *argv[], char *flags, int stop)
|
||||||
{
|
{
|
||||||
char *s, *t;
|
char *s, *t;
|
||||||
int i, j, c, count;
|
int i, j, c, count;
|
||||||
flagarg=flags;
|
flagarg = flags;
|
||||||
if(cmdname==0) cmdname=argv[0];
|
if(cmdname==0)
|
||||||
s=cmdline;
|
cmdname = argv[0];
|
||||||
for(i=0;i!=argc;i++){
|
s = cmdline;
|
||||||
for(t=argv[i];*t;t++)
|
for(i = 0;i!=argc;i++){
|
||||||
|
for(t = argv[i];*t;t++)
|
||||||
if(s!=&cmdline[NCMDLINE])
|
if(s!=&cmdline[NCMDLINE])
|
||||||
*s++=*t;
|
*s++=*t;
|
||||||
if(i!=argc-1 && s!=&cmdline[NCMDLINE])
|
if(i!=argc-1 && s!=&cmdline[NCMDLINE])
|
||||||
*s++=' ';
|
*s++=' ';
|
||||||
}
|
}
|
||||||
*s='\0';
|
*s='\0';
|
||||||
i=1;
|
i = 1;
|
||||||
while(i!=argc){
|
while(i!=argc){
|
||||||
if(argv[i][0]!='-' || argv[i][1]=='\0'){
|
if(argv[i][0]!='-' || argv[i][1]=='\0'){
|
||||||
if(stop) return argc;
|
if(stop)
|
||||||
|
return argc;
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
s=argv[i]+1;
|
s = argv[i]+1;
|
||||||
while(*s){
|
while(*s){
|
||||||
c=*s++;
|
c=*s++;
|
||||||
count=scanflag(c, flags);
|
count = scanflag(c, flags);
|
||||||
if(count==-1) return -1;
|
if(count==-1)
|
||||||
if(flag[c]){ reason=RESET; badflag=c; return -1; }
|
return -1;
|
||||||
|
if(flag[c]){ reason = RESET; badflag = c; return -1; }
|
||||||
if(count==0){
|
if(count==0){
|
||||||
flag[c]=flagset;
|
flag[c] = flagset;
|
||||||
if(*s=='\0'){
|
if(*s=='\0'){
|
||||||
for(j=i+1;j<=argc;j++)
|
for(j = i+1;j<=argc;j++)
|
||||||
argv[j-1]=argv[j];
|
argv[j-1] = argv[j];
|
||||||
--argc;
|
--argc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(*s=='\0'){
|
if(*s=='\0'){
|
||||||
for(j=i+1;j<=argc;j++)
|
for(j = i+1;j<=argc;j++)
|
||||||
argv[j-1]=argv[j];
|
argv[j-1] = argv[j];
|
||||||
--argc;
|
--argc;
|
||||||
s=argv[i];
|
s = argv[i];
|
||||||
}
|
}
|
||||||
if(argc-i<count){
|
if(argc-i<count){
|
||||||
reason=FEWARGS;
|
reason = FEWARGS;
|
||||||
badflag=c;
|
badflag = c;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
reverse(argv+i, argv+argc);
|
reverse(argv+i, argv+argc);
|
||||||
reverse(argv+i, argv+argc-count);
|
reverse(argv+i, argv+argc-count);
|
||||||
reverse(argv+argc-count+1, argv+argc);
|
reverse(argv+argc-count+1, argv+argc);
|
||||||
argc-=count;
|
argc-=count;
|
||||||
flag[c]=argv+argc+1;
|
flag[c] = argv+argc+1;
|
||||||
flag[c][0]=s;
|
flag[c][0] = s;
|
||||||
s="";
|
s="";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return argc;
|
return argc;
|
||||||
}
|
}
|
||||||
static void reverse(char **p, char **q)
|
|
||||||
|
static void
|
||||||
|
reverse(char **p, char **q)
|
||||||
{
|
{
|
||||||
char *t;
|
char *t;
|
||||||
for(;p<q;p++,--q){ t=*p; *p=*q; *q=t; }
|
for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; }
|
||||||
}
|
}
|
||||||
static int scanflag(int c, char *f)
|
|
||||||
|
static int
|
||||||
|
scanflag(int c, char *f)
|
||||||
{
|
{
|
||||||
int fc, count;
|
int fc, count;
|
||||||
if(0<=c && c<NFLAG) while(*f){
|
if(0<=c && c<NFLAG)
|
||||||
if(*f==' '){
|
while(*f){
|
||||||
f++;
|
if(*f==' '){
|
||||||
continue;
|
|
||||||
}
|
|
||||||
fc=*f++;
|
|
||||||
if(*f==':'){
|
|
||||||
f++;
|
|
||||||
if(*f<'0' || '9'<*f){ reason=FLAGSYN; return -1; }
|
|
||||||
count=0;
|
|
||||||
while('0'<=*f && *f<='9') count=count*10+*f++-'0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
count=0;
|
|
||||||
if(*f=='['){
|
|
||||||
do{
|
|
||||||
f++;
|
f++;
|
||||||
if(*f=='\0'){ reason=FLAGSYN; return -1; }
|
continue;
|
||||||
}while(*f!=']');
|
}
|
||||||
f++;
|
fc=*f++;
|
||||||
|
if(*f==':'){
|
||||||
|
f++;
|
||||||
|
if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; }
|
||||||
|
count = 0;
|
||||||
|
while('0'<=*f && *f<='9') count = count*10+*f++-'0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
count = 0;
|
||||||
|
if(*f=='['){
|
||||||
|
do{
|
||||||
|
f++;
|
||||||
|
if(*f=='\0'){ reason = FLAGSYN; return -1; }
|
||||||
|
}while(*f!=']');
|
||||||
|
f++;
|
||||||
|
}
|
||||||
|
if(c==fc)
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
if(c==fc) return count;
|
reason = BADFLAG;
|
||||||
}
|
badflag = c;
|
||||||
reason=BADFLAG;
|
|
||||||
badflag=c;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
void usage(char *tail)
|
|
||||||
|
void
|
||||||
|
usage(char *tail)
|
||||||
{
|
{
|
||||||
char *s, *t, c;
|
char *s, *t, c;
|
||||||
int count, nflag=0;
|
int count, nflag = 0;
|
||||||
switch(reason){
|
switch(reason){
|
||||||
case RESET:
|
case RESET:
|
||||||
errs("Flag -");
|
errs("Flag -");
|
||||||
@ -140,46 +153,52 @@ void usage(char *tail)
|
|||||||
}
|
}
|
||||||
errs("Usage: ");
|
errs("Usage: ");
|
||||||
errs(cmdname);
|
errs(cmdname);
|
||||||
for(s=flagarg;*s;){
|
for(s = flagarg;*s;){
|
||||||
c=*s;
|
c=*s;
|
||||||
if(*s++==' ') continue;
|
if(*s++==' ')
|
||||||
|
continue;
|
||||||
if(*s==':'){
|
if(*s==':'){
|
||||||
s++;
|
s++;
|
||||||
count=0;
|
count = 0;
|
||||||
while('0'<=*s && *s<='9') count=count*10+*s++-'0';
|
while('0'<=*s && *s<='9') count = count*10+*s++-'0';
|
||||||
}
|
}
|
||||||
else count=0;
|
else count = 0;
|
||||||
if(count==0){
|
if(count==0){
|
||||||
if(nflag==0) errs(" [-");
|
if(nflag==0)
|
||||||
|
errs(" [-");
|
||||||
nflag++;
|
nflag++;
|
||||||
errc(c);
|
errc(c);
|
||||||
}
|
}
|
||||||
if(*s=='['){
|
if(*s=='['){
|
||||||
s++;
|
s++;
|
||||||
while(*s!=']' && *s!='\0') s++;
|
while(*s!=']' && *s!='\0') s++;
|
||||||
if(*s==']') s++;
|
if(*s==']')
|
||||||
|
s++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(nflag) errs("]");
|
if(nflag)
|
||||||
for(s=flagarg;*s;){
|
errs("]");
|
||||||
|
for(s = flagarg;*s;){
|
||||||
c=*s;
|
c=*s;
|
||||||
if(*s++==' ') continue;
|
if(*s++==' ')
|
||||||
|
continue;
|
||||||
if(*s==':'){
|
if(*s==':'){
|
||||||
s++;
|
s++;
|
||||||
count=0;
|
count = 0;
|
||||||
while('0'<=*s && *s<='9') count=count*10+*s++-'0';
|
while('0'<=*s && *s<='9') count = count*10+*s++-'0';
|
||||||
}
|
}
|
||||||
else count=0;
|
else count = 0;
|
||||||
if(count!=0){
|
if(count!=0){
|
||||||
errs(" [-");
|
errs(" [-");
|
||||||
errc(c);
|
errc(c);
|
||||||
if(*s=='['){
|
if(*s=='['){
|
||||||
s++;
|
s++;
|
||||||
t=s;
|
t = s;
|
||||||
while(*s!=']' && *s!='\0') s++;
|
while(*s!=']' && *s!='\0') s++;
|
||||||
errs(" ");
|
errs(" ");
|
||||||
errn(t, s-t);
|
errn(t, s-t);
|
||||||
if(*s==']') s++;
|
if(*s==']')
|
||||||
|
s++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
while(count--) errs(" arg");
|
while(count--) errs(" arg");
|
||||||
@ -188,7 +207,8 @@ void usage(char *tail)
|
|||||||
else if(*s=='['){
|
else if(*s=='['){
|
||||||
s++;
|
s++;
|
||||||
while(*s!=']' && *s!='\0') s++;
|
while(*s!=']' && *s!='\0') s++;
|
||||||
if(*s==']') s++;
|
if(*s==']')
|
||||||
|
s++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(tail){
|
if(tail){
|
||||||
@ -198,20 +218,27 @@ void usage(char *tail)
|
|||||||
errs("\n");
|
errs("\n");
|
||||||
Exit("bad flags");
|
Exit("bad flags");
|
||||||
}
|
}
|
||||||
static void errn(char *s, int count)
|
|
||||||
|
static void
|
||||||
|
errn(char *s, int count)
|
||||||
{
|
{
|
||||||
while(count){ errc(*s++); --count; }
|
while(count){ errc(*s++); --count; }
|
||||||
}
|
}
|
||||||
static void errs(char *s)
|
|
||||||
|
static void
|
||||||
|
errs(char *s)
|
||||||
{
|
{
|
||||||
while(*s) errc(*s++);
|
while(*s) errc(*s++);
|
||||||
}
|
}
|
||||||
#define NBUF 80
|
#define NBUF 80
|
||||||
static char buf[NBUF], *bufp=buf;
|
static char buf[NBUF], *bufp = buf;
|
||||||
static void errc(int c){
|
|
||||||
|
static void
|
||||||
|
errc(int c)
|
||||||
|
{
|
||||||
*bufp++=c;
|
*bufp++=c;
|
||||||
if(bufp==&buf[NBUF] || c=='\n'){
|
if(bufp==&buf[NBUF] || c=='\n'){
|
||||||
Write(2, buf, bufp-buf);
|
Write(2, buf, bufp-buf);
|
||||||
bufp=buf;
|
bufp = buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,68 +6,77 @@ struct word *globv;
|
|||||||
/*
|
/*
|
||||||
* delete all the GLOB marks from s, in place
|
* delete all the GLOB marks from s, in place
|
||||||
*/
|
*/
|
||||||
void deglob(char *s)
|
|
||||||
|
void
|
||||||
|
deglob(char *s)
|
||||||
{
|
{
|
||||||
char *t=s;
|
char *t = s;
|
||||||
do{
|
do{
|
||||||
if(*t==GLOB) t++;
|
if(*t==GLOB)
|
||||||
|
t++;
|
||||||
*s++=*t;
|
*s++=*t;
|
||||||
}while(*t++);
|
}while(*t++);
|
||||||
}
|
}
|
||||||
int globcmp(const void *s, const void *t)
|
|
||||||
|
int
|
||||||
|
globcmp(const void *s, const void *t)
|
||||||
{
|
{
|
||||||
return strcmp(*(char**)s, *(char**)t);
|
return strcmp(*(char**)s, *(char**)t);
|
||||||
}
|
}
|
||||||
void globsort(word *left, word *right)
|
|
||||||
|
void
|
||||||
|
globsort(word *left, word *right)
|
||||||
{
|
{
|
||||||
char **list;
|
char **list;
|
||||||
word *a;
|
word *a;
|
||||||
int n=0;
|
int n = 0;
|
||||||
for(a=left;a!=right;a=a->next) n++;
|
for(a = left;a!=right;a = a->next) n++;
|
||||||
list=(char **)emalloc(n*sizeof(char *));
|
list = (char **)emalloc(n*sizeof(char *));
|
||||||
for(a=left,n=0;a!=right;a=a->next,n++) list[n]=a->word;
|
for(a = left,n = 0;a!=right;a = a->next,n++) list[n] = a->word;
|
||||||
qsort((char *)list, n, sizeof(char *), globcmp);
|
qsort((void *)list, n, sizeof(void *), globcmp);
|
||||||
for(a=left,n=0;a!=right;a=a->next,n++) a->word=list[n];
|
for(a = left,n = 0;a!=right;a = a->next,n++) a->word = list[n];
|
||||||
efree((char *)list);
|
efree((char *)list);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Push names prefixed by globname and suffixed by a match of p onto the astack.
|
* Push names prefixed by globname and suffixed by a match of p onto the astack.
|
||||||
* namep points to the end of the prefix in globname.
|
* namep points to the end of the prefix in globname.
|
||||||
*/
|
*/
|
||||||
void globdir(char *p, char *namep)
|
|
||||||
|
void
|
||||||
|
globdir(char *p, char *namep)
|
||||||
{
|
{
|
||||||
char *t, *newp;
|
char *t, *newp;
|
||||||
int f;
|
int f;
|
||||||
/* scan the pattern looking for a component with a metacharacter in it */
|
/* scan the pattern looking for a component with a metacharacter in it */
|
||||||
if(*p=='\0'){
|
if(*p=='\0'){
|
||||||
globv=newword(globname, globv);
|
globv = newword(globname, globv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t=namep;
|
t = namep;
|
||||||
newp=p;
|
newp = p;
|
||||||
while(*newp){
|
while(*newp){
|
||||||
if(*newp==GLOB)
|
if(*newp==GLOB)
|
||||||
break;
|
break;
|
||||||
*t=*newp++;
|
*t=*newp++;
|
||||||
if(*t++=='/'){
|
if(*t++=='/'){
|
||||||
namep=t;
|
namep = t;
|
||||||
p=newp;
|
p = newp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If we ran out of pattern, append the name if accessible */
|
/* If we ran out of pattern, append the name if accessible */
|
||||||
if(*newp=='\0'){
|
if(*newp=='\0'){
|
||||||
*t='\0';
|
*t='\0';
|
||||||
if(access(globname, 0)==0)
|
if(access(globname, 0)==0)
|
||||||
globv=newword(globname, globv);
|
globv = newword(globname, globv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* read the directory and recur for any entry that matches */
|
/* read the directory and recur for any entry that matches */
|
||||||
*namep='\0';
|
*namep='\0';
|
||||||
if((f=Opendir(globname[0]?globname:"."))<0) return;
|
if((f = Opendir(globname[0]?globname:"."))<0) return;
|
||||||
while(*newp!='/' && *newp!='\0') newp++;
|
while(*newp!='/' && *newp!='\0') newp++;
|
||||||
while(Readdir(f, namep)){
|
while(Readdir(f, namep, *newp=='/')){
|
||||||
if(matchfn(namep, p)){
|
if(matchfn(namep, p)){
|
||||||
for(t=namep;*t;t++);
|
for(t = namep;*t;t++);
|
||||||
globdir(newp, t);
|
globdir(newp, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,22 +86,24 @@ void globdir(char *p, char *namep)
|
|||||||
* Push all file names matched by p on the current thread's stack.
|
* Push all file names matched by p on the current thread's stack.
|
||||||
* If there are no matches, the list consists of p.
|
* If there are no matches, the list consists of p.
|
||||||
*/
|
*/
|
||||||
void glob(char *p)
|
|
||||||
|
void
|
||||||
|
glob(char *p)
|
||||||
{
|
{
|
||||||
word *svglobv=globv;
|
word *svglobv = globv;
|
||||||
int globlen=Globsize(p);
|
int globlen = Globsize(p);
|
||||||
if(!globlen){
|
if(!globlen){
|
||||||
deglob(p);
|
deglob(p);
|
||||||
globv=newword(p, globv);
|
globv = newword(p, globv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
globname=emalloc(globlen);
|
globname = emalloc(globlen);
|
||||||
globname[0]='\0';
|
globname[0]='\0';
|
||||||
globdir(p, globname);
|
globdir(p, globname);
|
||||||
efree(globname);
|
efree(globname);
|
||||||
if(svglobv==globv){
|
if(svglobv==globv){
|
||||||
deglob(p);
|
deglob(p);
|
||||||
globv=newword(p, globv);
|
globv = newword(p, globv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
globsort(globv, svglobv);
|
globsort(globv, svglobv);
|
||||||
@ -100,12 +111,18 @@ void glob(char *p)
|
|||||||
/*
|
/*
|
||||||
* Do p and q point at equal utf codes
|
* Do p and q point at equal utf codes
|
||||||
*/
|
*/
|
||||||
int equtf(char *p, char *q){
|
|
||||||
if(*p!=*q) return 0;
|
int
|
||||||
|
equtf(char *p, char *q)
|
||||||
|
{
|
||||||
|
if(*p!=*q)
|
||||||
|
return 0;
|
||||||
if(twobyte(*p)) return p[1]==q[1];
|
if(twobyte(*p)) return p[1]==q[1];
|
||||||
if(threebyte(*p)){
|
if(threebyte(*p)){
|
||||||
if(p[1]!=q[1]) return 0;
|
if(p[1]!=q[1])
|
||||||
if(p[1]=='\0') return 1; /* broken code at end of string! */
|
return 0;
|
||||||
|
if(p[1]=='\0')
|
||||||
|
return 1; /* broken code at end of string! */
|
||||||
return p[2]==q[2];
|
return p[2]==q[2];
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -114,7 +131,10 @@ int equtf(char *p, char *q){
|
|||||||
* Return a pointer to the next utf code in the string,
|
* Return a pointer to the next utf code in the string,
|
||||||
* not jumping past nuls in broken utf codes!
|
* not jumping past nuls in broken utf codes!
|
||||||
*/
|
*/
|
||||||
char *nextutf(char *p){
|
|
||||||
|
char*
|
||||||
|
nextutf(char *p)
|
||||||
|
{
|
||||||
if(twobyte(*p)) return p[1]=='\0'?p+1:p+2;
|
if(twobyte(*p)) return p[1]=='\0'?p+1:p+2;
|
||||||
if(threebyte(*p)) return p[1]=='\0'?p+1:p[2]=='\0'?p+2:p+3;
|
if(threebyte(*p)) return p[1]=='\0'?p+1:p[2]=='\0'?p+2:p+3;
|
||||||
return p+1;
|
return p+1;
|
||||||
@ -122,7 +142,10 @@ char *nextutf(char *p){
|
|||||||
/*
|
/*
|
||||||
* Convert the utf code at *p to a unicode value
|
* Convert the utf code at *p to a unicode value
|
||||||
*/
|
*/
|
||||||
int unicode(char *p){
|
|
||||||
|
int
|
||||||
|
unicode(char *p)
|
||||||
|
{
|
||||||
int u=*p&0xff;
|
int u=*p&0xff;
|
||||||
if(twobyte(u)) return ((u&0x1f)<<6)|(p[1]&0x3f);
|
if(twobyte(u)) return ((u&0x1f)<<6)|(p[1]&0x3f);
|
||||||
if(threebyte(u)) return (u<<12)|((p[1]&0x3f)<<6)|(p[2]&0x3f);
|
if(threebyte(u)) return (u<<12)|((p[1]&0x3f)<<6)|(p[2]&0x3f);
|
||||||
@ -135,77 +158,97 @@ int unicode(char *p){
|
|||||||
* ? matches any single character
|
* ? matches any single character
|
||||||
* [...] matches the enclosed list of characters
|
* [...] matches the enclosed list of characters
|
||||||
*/
|
*/
|
||||||
int matchfn(char *s, char *p)
|
|
||||||
|
int
|
||||||
|
matchfn(char *s, char *p)
|
||||||
{
|
{
|
||||||
if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.')
|
if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.')
|
||||||
return 0;
|
return 0;
|
||||||
return match(s, p, '/');
|
return match(s, p, '/');
|
||||||
}
|
}
|
||||||
int match(char *s, char *p, int stop)
|
|
||||||
|
int
|
||||||
|
match(char *s, char *p, int stop)
|
||||||
{
|
{
|
||||||
int compl, hit, lo, hi, t, c;
|
int compl, hit, lo, hi, t, c;
|
||||||
for(;*p!=stop && *p!='\0';s=nextutf(s),p=nextutf(p)){
|
for(;*p!=stop && *p!='\0';s = nextutf(s),p = nextutf(p)){
|
||||||
if(*p!=GLOB){
|
if(*p!=GLOB){
|
||||||
if(!equtf(p, s)) return 0;
|
if(!equtf(p, s)) return 0;
|
||||||
}
|
}
|
||||||
else switch(*++p){
|
else switch(*++p){
|
||||||
case GLOB:
|
case GLOB:
|
||||||
if(*s!=GLOB) return 0;
|
if(*s!=GLOB)
|
||||||
|
return 0;
|
||||||
break;
|
break;
|
||||||
case '*':
|
case '*':
|
||||||
for(;;){
|
for(;;){
|
||||||
if(match(s, nextutf(p), stop)) return 1;
|
if(match(s, nextutf(p), stop)) return 1;
|
||||||
if(!*s) break;
|
if(!*s)
|
||||||
s=nextutf(s);
|
break;
|
||||||
|
s = nextutf(s);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
case '?':
|
case '?':
|
||||||
if(*s=='\0') return 0;
|
if(*s=='\0')
|
||||||
|
return 0;
|
||||||
break;
|
break;
|
||||||
case '[':
|
case '[':
|
||||||
if(*s=='\0') return 0;
|
if(*s=='\0')
|
||||||
c=unicode(s);
|
return 0;
|
||||||
|
c = unicode(s);
|
||||||
p++;
|
p++;
|
||||||
compl=*p=='~';
|
compl=*p=='~';
|
||||||
if(compl) p++;
|
if(compl)
|
||||||
hit=0;
|
p++;
|
||||||
|
hit = 0;
|
||||||
while(*p!=']'){
|
while(*p!=']'){
|
||||||
if(*p=='\0') return 0; /* syntax error */
|
if(*p=='\0')
|
||||||
lo=unicode(p);
|
return 0; /* syntax error */
|
||||||
p=nextutf(p);
|
lo = unicode(p);
|
||||||
if(*p!='-') hi=lo;
|
p = nextutf(p);
|
||||||
|
if(*p!='-')
|
||||||
|
hi = lo;
|
||||||
else{
|
else{
|
||||||
p++;
|
p++;
|
||||||
if(*p=='\0') return 0; /* syntax error */
|
if(*p=='\0')
|
||||||
hi=unicode(p);
|
return 0; /* syntax error */
|
||||||
p=nextutf(p);
|
hi = unicode(p);
|
||||||
if(hi<lo){ t=lo; lo=hi; hi=t; }
|
p = nextutf(p);
|
||||||
|
if(hi<lo){ t = lo; lo = hi; hi = t; }
|
||||||
}
|
}
|
||||||
if(lo<=c && c<=hi) hit=1;
|
if(lo<=c && c<=hi)
|
||||||
|
hit = 1;
|
||||||
}
|
}
|
||||||
if(compl) hit=!hit;
|
if(compl)
|
||||||
if(!hit) return 0;
|
hit=!hit;
|
||||||
|
if(!hit)
|
||||||
|
return 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *s=='\0';
|
return *s=='\0';
|
||||||
}
|
}
|
||||||
void globlist1(word *gl)
|
|
||||||
|
void
|
||||||
|
globlist1(word *gl)
|
||||||
{
|
{
|
||||||
if(gl){
|
if(gl){
|
||||||
globlist1(gl->next);
|
globlist1(gl->next);
|
||||||
glob(gl->word);
|
glob(gl->word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void globlist(void){
|
|
||||||
|
void
|
||||||
|
globlist(void)
|
||||||
|
{
|
||||||
word *a;
|
word *a;
|
||||||
globv=0;
|
globv = 0;
|
||||||
globlist1(runq->argv->words);
|
globlist1(runq->argv->words);
|
||||||
poplist();
|
poplist();
|
||||||
pushlist();
|
pushlist();
|
||||||
if(globv){
|
if(globv){
|
||||||
for(a=globv;a->next;a=a->next);
|
for(a = globv;a->next;a = a->next);
|
||||||
a->next=runq->argv->words;
|
a->next = runq->argv->words;
|
||||||
runq->argv->words=globv;
|
runq->argv->words = globv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
#include <u.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "getflags.h"
|
#include "getflags.h"
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
@ -13,9 +11,7 @@ Xasync(void)
|
|||||||
{
|
{
|
||||||
int null = open("/dev/null", 0);
|
int null = open("/dev/null", 0);
|
||||||
int pid;
|
int pid;
|
||||||
int tcpgrp, pgrp;
|
|
||||||
char npid[10];
|
char npid[10];
|
||||||
|
|
||||||
if(null<0){
|
if(null<0){
|
||||||
Xerror("Can't open /dev/null\n");
|
Xerror("Can't open /dev/null\n");
|
||||||
return;
|
return;
|
||||||
@ -26,12 +22,6 @@ Xasync(void)
|
|||||||
Xerror("try again");
|
Xerror("try again");
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
/*
|
|
||||||
* Should make reads of tty fail, writes succeed.
|
|
||||||
*/
|
|
||||||
signal(SIGTTIN, SIG_IGN);
|
|
||||||
signal(SIGTTOU, SIG_IGN);
|
|
||||||
|
|
||||||
pushredir(ROPEN, null, 0);
|
pushredir(ROPEN, null, 0);
|
||||||
start(runq->code, runq->pc+1, runq->local);
|
start(runq->code, runq->pc+1, runq->local);
|
||||||
runq->ret = 0;
|
runq->ret = 0;
|
||||||
|
|||||||
246
src/cmd/rc/havep9p.c
Normal file
246
src/cmd/rc/havep9p.c
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
#include <u.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#if defined(PLAN9PORT) && defined(__sun__)
|
||||||
|
# define BSD_COMP /* sigh. for TIOCNOTTY */
|
||||||
|
#endif
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "rc.h"
|
||||||
|
#include "getflags.h"
|
||||||
|
#include "exec.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "fns.h"
|
||||||
|
|
||||||
|
int havefork = 1;
|
||||||
|
|
||||||
|
void
|
||||||
|
Xasync(void)
|
||||||
|
{
|
||||||
|
int null=open("/dev/null", 0);
|
||||||
|
int tty;
|
||||||
|
int pid;
|
||||||
|
char npid[10];
|
||||||
|
if(null<0){
|
||||||
|
Xerror("Can't open /dev/null\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){
|
||||||
|
case -1:
|
||||||
|
close(null);
|
||||||
|
Xerror("try again");
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
/*
|
||||||
|
* I don't know what the right thing to do here is,
|
||||||
|
* so this is all experimentally determined.
|
||||||
|
* If we just dup /dev/null onto 0, then running
|
||||||
|
* ssh foo & will reopen /dev/tty, try to read a password,
|
||||||
|
* get a signal, and repeat, in a tight loop, forever.
|
||||||
|
* Arguably this is a bug in ssh (it behaves the same
|
||||||
|
* way under bash as under rc) but I'm fixing it here
|
||||||
|
* anyway. If we dissociate the process from the tty,
|
||||||
|
* then it won't be able to open /dev/tty ever again.
|
||||||
|
* The SIG_IGN on SIGTTOU makes writing the tty
|
||||||
|
* (via fd 1 or 2, for example) succeed even though
|
||||||
|
* our pgrp is not the terminal's controlling pgrp.
|
||||||
|
*/
|
||||||
|
if((tty=open("/dev/tty", OREAD)) >= 0){
|
||||||
|
/*
|
||||||
|
* Should make reads of tty fail, writes succeed.
|
||||||
|
*/
|
||||||
|
signal(SIGTTIN, SIG_IGN);
|
||||||
|
signal(SIGTTOU, SIG_IGN);
|
||||||
|
ioctl(tty, TIOCNOTTY);
|
||||||
|
close(tty);
|
||||||
|
}
|
||||||
|
if(isatty(0))
|
||||||
|
pushredir(ROPEN, null, 0);
|
||||||
|
else
|
||||||
|
close(null);
|
||||||
|
start(runq->code, runq->pc+1, runq->local);
|
||||||
|
runq->ret=0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
close(null);
|
||||||
|
runq->pc=runq->code[runq->pc].i;
|
||||||
|
inttoascii(npid, pid);
|
||||||
|
setvar("apid", newword(npid, (word *)0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Xpipe(void)
|
||||||
|
{
|
||||||
|
struct thread *p = runq;
|
||||||
|
int pc = p->pc, forkid;
|
||||||
|
int lfd = p->code[pc++].i;
|
||||||
|
int rfd = p->code[pc++].i;
|
||||||
|
int pfd[2];
|
||||||
|
|
||||||
|
if(pipe(pfd)<0){
|
||||||
|
Xerror("can't get pipe");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(forkid=fork()){
|
||||||
|
case -1:
|
||||||
|
Xerror("try again");
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
start(p->code, pc+2, runq->local);
|
||||||
|
runq->ret=0;
|
||||||
|
close(pfd[PRD]);
|
||||||
|
pushredir(ROPEN, pfd[PWR], lfd);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
start(p->code, p->code[pc].i, runq->local);
|
||||||
|
close(pfd[PWR]);
|
||||||
|
pushredir(ROPEN, pfd[PRD], rfd);
|
||||||
|
p->pc=p->code[pc+1].i;
|
||||||
|
p->pid=forkid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Xbackq(void)
|
||||||
|
{
|
||||||
|
char wd[8193];
|
||||||
|
int c;
|
||||||
|
char *s, *ewd = &wd[8192], *stop;
|
||||||
|
struct io *f;
|
||||||
|
var *ifs = vlook("ifs");
|
||||||
|
word *v, *nextv;
|
||||||
|
int pfd[2];
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
stop = ifs->val?ifs->val->word:"";
|
||||||
|
if(pipe(pfd)<0){
|
||||||
|
Xerror("can't make pipe");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(pid = fork()){
|
||||||
|
case -1: Xerror("try again");
|
||||||
|
close(pfd[PRD]);
|
||||||
|
close(pfd[PWR]);
|
||||||
|
return;
|
||||||
|
case 0:
|
||||||
|
close(pfd[PRD]);
|
||||||
|
start(runq->code, runq->pc+1, runq->local);
|
||||||
|
pushredir(ROPEN, pfd[PWR], 1);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
close(pfd[PWR]);
|
||||||
|
f=openfd(pfd[PRD]);
|
||||||
|
s=wd;
|
||||||
|
v=0;
|
||||||
|
while((c=rchr(f))!=EOF){
|
||||||
|
if(strchr(stop, c) || s==ewd){
|
||||||
|
if(s!=wd){
|
||||||
|
*s='\0';
|
||||||
|
v=newword(wd, v);
|
||||||
|
s=wd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else *s++=c;
|
||||||
|
}
|
||||||
|
if(s!=wd){
|
||||||
|
*s='\0';
|
||||||
|
v=newword(wd, v);
|
||||||
|
}
|
||||||
|
closeio(f);
|
||||||
|
Waitfor(pid, 0);
|
||||||
|
/* v points to reversed arglist -- reverse it onto argv */
|
||||||
|
while(v){
|
||||||
|
nextv=v->next;
|
||||||
|
v->next=runq->argv->words;
|
||||||
|
runq->argv->words=v;
|
||||||
|
v=nextv;
|
||||||
|
}
|
||||||
|
runq->pc=runq->code[runq->pc].i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Who should wait for the exit from the fork?
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Xpipefd(void)
|
||||||
|
{
|
||||||
|
struct thread *p=runq;
|
||||||
|
int pc=p->pc;
|
||||||
|
char name[40];
|
||||||
|
int pfd[2];
|
||||||
|
int sidefd, mainfd;
|
||||||
|
if(pipe(pfd)<0){
|
||||||
|
Xerror("can't get pipe");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(p->code[pc].i==READ){
|
||||||
|
sidefd=pfd[PWR];
|
||||||
|
mainfd=pfd[PRD];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
sidefd=pfd[PRD];
|
||||||
|
mainfd=pfd[PWR];
|
||||||
|
}
|
||||||
|
switch(fork()){
|
||||||
|
case -1:
|
||||||
|
Xerror("try again");
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
start(p->code, pc+2, runq->local);
|
||||||
|
close(mainfd);
|
||||||
|
pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
|
||||||
|
runq->ret=0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
close(sidefd);
|
||||||
|
pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */
|
||||||
|
strcpy(name, Fdprefix);
|
||||||
|
inttoascii(name+strlen(name), mainfd);
|
||||||
|
pushword(name);
|
||||||
|
p->pc=p->code[pc+1].i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Xsubshell(void)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
switch(pid=fork()){
|
||||||
|
case -1:
|
||||||
|
Xerror("try again");
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
start(runq->code, runq->pc+1, runq->local);
|
||||||
|
runq->ret=0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Waitfor(pid, 1);
|
||||||
|
runq->pc=runq->code[runq->pc].i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
execforkexec(void)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
int n;
|
||||||
|
char buf[ERRMAX];
|
||||||
|
|
||||||
|
switch(pid = fork()){
|
||||||
|
case -1:
|
||||||
|
return -1;
|
||||||
|
case 0:
|
||||||
|
pushword("exec");
|
||||||
|
execexec();
|
||||||
|
strcpy(buf, "can't exec: ");
|
||||||
|
n = strlen(buf);
|
||||||
|
errstr(buf+n, ERRMAX-n);
|
||||||
|
Exit(buf);
|
||||||
|
}
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
@ -3,32 +3,37 @@
|
|||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
struct here *here, **ehere;
|
struct here *here, **ehere;
|
||||||
int ser=0;
|
int ser = 0;
|
||||||
char tmp[]="/tmp/here0000.0000";
|
char tmp[]="/tmp/here0000.0000";
|
||||||
char hex[]="0123456789abcdef";
|
char hex[]="0123456789abcdef";
|
||||||
void psubst(io*, char*);
|
void psubst(io*, char*);
|
||||||
void pstrs(io*, word*);
|
void pstrs(io*, word*);
|
||||||
void hexnum(char *p, int n)
|
|
||||||
|
void
|
||||||
|
hexnum(char *p, int n)
|
||||||
{
|
{
|
||||||
*p++=hex[(n>>12)&0xF];
|
*p++=hex[(n>>12)&0xF];
|
||||||
*p++=hex[(n>>8)&0xF];
|
*p++=hex[(n>>8)&0xF];
|
||||||
*p++=hex[(n>>4)&0xF];
|
*p++=hex[(n>>4)&0xF];
|
||||||
*p=hex[n&0xF];
|
*p = hex[n&0xF];
|
||||||
}
|
}
|
||||||
tree *heredoc(tree *tag)
|
|
||||||
|
tree*
|
||||||
|
heredoc(tree *tag)
|
||||||
{
|
{
|
||||||
struct here *h=new(struct here);
|
struct here *h = new(struct here);
|
||||||
if(tag->type!=WORD) yyerror("Bad here tag");
|
if(tag->type!=WORD)
|
||||||
h->next=0;
|
yyerror("Bad here tag");
|
||||||
|
h->next = 0;
|
||||||
if(here)
|
if(here)
|
||||||
*ehere=h;
|
*ehere = h;
|
||||||
else
|
else
|
||||||
here=h;
|
here = h;
|
||||||
ehere=&h->next;
|
ehere=&h->next;
|
||||||
h->tag=tag;
|
h->tag = tag;
|
||||||
hexnum(&tmp[9], getpid());
|
hexnum(&tmp[9], getpid());
|
||||||
hexnum(&tmp[14], ser++);
|
hexnum(&tmp[14], ser++);
|
||||||
h->name=strdup(tmp);
|
h->name = strdup(tmp);
|
||||||
return token(tmp, WORD);
|
return token(tmp, WORD);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -36,27 +41,32 @@ tree *heredoc(tree *tag)
|
|||||||
* missubstitution, or a misrecognized EOF marker.
|
* missubstitution, or a misrecognized EOF marker.
|
||||||
*/
|
*/
|
||||||
#define NLINE 4096
|
#define NLINE 4096
|
||||||
void readhere(void){
|
|
||||||
|
void
|
||||||
|
readhere(void)
|
||||||
|
{
|
||||||
struct here *h, *nexth;
|
struct here *h, *nexth;
|
||||||
io *f;
|
io *f;
|
||||||
char *s, *tag;
|
char *s, *tag;
|
||||||
int c, subst;
|
int c, subst;
|
||||||
char line[NLINE+1];
|
char line[NLINE+1];
|
||||||
for(h=here;h;h=nexth){
|
for(h = here;h;h = nexth){
|
||||||
subst=!h->tag->quoted;
|
subst=!h->tag->quoted;
|
||||||
tag=h->tag->str;
|
tag = h->tag->str;
|
||||||
c=Creat(h->name);
|
c = Creat(h->name);
|
||||||
if(c<0) yyerror("can't create here document");
|
if(c<0)
|
||||||
f=openfd(c);
|
yyerror("can't create here document");
|
||||||
s=line;
|
f = openfd(c);
|
||||||
|
s = line;
|
||||||
pprompt();
|
pprompt();
|
||||||
while((c=rchr(runq->cmdfd))!=EOF){
|
while((c = rchr(runq->cmdfd))!=EOF){
|
||||||
if(c=='\n' || s==&line[NLINE]){
|
if(c=='\n' || s==&line[NLINE]){
|
||||||
*s='\0';
|
*s='\0';
|
||||||
if(strcmp(line, tag)==0) break;
|
if(tag && strcmp(line, tag)==0) break;
|
||||||
if(subst) psubst(f, line);
|
if(subst)
|
||||||
|
psubst(f, line);
|
||||||
else pstr(f, line);
|
else pstr(f, line);
|
||||||
s=line;
|
s = line;
|
||||||
if(c=='\n'){
|
if(c=='\n'){
|
||||||
pprompt();
|
pprompt();
|
||||||
pchr(f, c);
|
pchr(f, c);
|
||||||
@ -68,13 +78,15 @@ void readhere(void){
|
|||||||
flush(f);
|
flush(f);
|
||||||
closeio(f);
|
closeio(f);
|
||||||
cleanhere(h->name);
|
cleanhere(h->name);
|
||||||
nexth=h->next;
|
nexth = h->next;
|
||||||
efree((char *)h);
|
efree((char *)h);
|
||||||
}
|
}
|
||||||
here=0;
|
here = 0;
|
||||||
doprompt=1;
|
doprompt = 1;
|
||||||
}
|
}
|
||||||
void psubst(io *f, char *s)
|
|
||||||
|
void
|
||||||
|
psubst(io *f, char *s)
|
||||||
{
|
{
|
||||||
char *t, *u;
|
char *t, *u;
|
||||||
int savec, n;
|
int savec, n;
|
||||||
@ -83,48 +95,55 @@ void psubst(io *f, char *s)
|
|||||||
if(*s!='$'){
|
if(*s!='$'){
|
||||||
if(0xa0<=(*s&0xff) && (*s&0xff)<=0xf5){
|
if(0xa0<=(*s&0xff) && (*s&0xff)<=0xf5){
|
||||||
pchr(f, *s++);
|
pchr(f, *s++);
|
||||||
if(*s=='\0') break;
|
if(*s=='\0')
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if(0xf6<=(*s&0xff) && (*s&0xff)<=0xf7){
|
else if(0xf6<=(*s&0xff) && (*s&0xff)<=0xf7){
|
||||||
pchr(f, *s++);
|
pchr(f, *s++);
|
||||||
if(*s=='\0') break;
|
if(*s=='\0')
|
||||||
|
break;
|
||||||
pchr(f, *s++);
|
pchr(f, *s++);
|
||||||
if(*s=='\0') break;
|
if(*s=='\0')
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
pchr(f, *s++);
|
pchr(f, *s++);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
t=++s;
|
t=++s;
|
||||||
if(*t=='$') pchr(f, *t++);
|
if(*t=='$')
|
||||||
|
pchr(f, *t++);
|
||||||
else{
|
else{
|
||||||
while(*t && idchr(*t)) t++;
|
while(*t && idchr(*t)) t++;
|
||||||
savec=*t;
|
savec=*t;
|
||||||
*t='\0';
|
*t='\0';
|
||||||
n=0;
|
n = 0;
|
||||||
for(u=s;*u && '0'<=*u && *u<='9';u++) n=n*10+*u-'0';
|
for(u = s;*u && '0'<=*u && *u<='9';u++) n = n*10+*u-'0';
|
||||||
if(n && *u=='\0'){
|
if(n && *u=='\0'){
|
||||||
star=vlook("*")->val;
|
star = vlook("*")->val;
|
||||||
if(star && 1<=n && n<=count(star)){
|
if(star && 1<=n && n<=count(star)){
|
||||||
while(--n) star=star->next;
|
while(--n) star = star->next;
|
||||||
pstr(f, star->word);
|
pstr(f, star->word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pstrs(f, vlook(s)->val);
|
pstrs(f, vlook(s)->val);
|
||||||
*t=savec;
|
*t = savec;
|
||||||
if(savec=='^') t++;
|
if(savec=='^')
|
||||||
|
t++;
|
||||||
}
|
}
|
||||||
s=t;
|
s = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void pstrs(io *f, word *a)
|
|
||||||
|
void
|
||||||
|
pstrs(io *f, word *a)
|
||||||
{
|
{
|
||||||
if(a){
|
if(a){
|
||||||
while(a->next && a->next->word){
|
while(a->next && a->next->word){
|
||||||
pstr(f, a->word);
|
pstr(f, a->word);
|
||||||
pchr(f, ' ');
|
pchr(f, ' ');
|
||||||
a=a->next;
|
a = a->next;
|
||||||
}
|
}
|
||||||
pstr(f, a->word);
|
pstr(f, a->word);
|
||||||
}
|
}
|
||||||
|
|||||||
231
src/cmd/rc/io.c
231
src/cmd/rc/io.c
@ -2,68 +2,121 @@
|
|||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
int pfmtnest=0;
|
int pfmtnest = 0;
|
||||||
void pfmt(io *f, char *fmt, ...){
|
|
||||||
|
void
|
||||||
|
pfmt(io *f, char *fmt, ...)
|
||||||
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char err[ERRMAX];
|
char err[ERRMAX];
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pfmtnest++;
|
pfmtnest++;
|
||||||
for(;*fmt;fmt++)
|
for(;*fmt;fmt++)
|
||||||
if(*fmt!='%') pchr(f, *fmt);
|
if(*fmt!='%')
|
||||||
|
pchr(f, *fmt);
|
||||||
else switch(*++fmt){
|
else switch(*++fmt){
|
||||||
case '\0': va_end(ap); return;
|
case '\0':
|
||||||
case 'c': pchr(f, va_arg(ap, int)); break;
|
va_end(ap);
|
||||||
case 'd': pdec(f, va_arg(ap, int)); break;
|
return;
|
||||||
case 'o': poct(f, va_arg(ap, unsigned)); break;
|
case 'c':
|
||||||
case 'p': phex(f, (long)va_arg(ap, char *)); break; /*unportable*/
|
pchr(f, va_arg(ap, int));
|
||||||
case 'Q': pquo(f, va_arg(ap, char *)); break;
|
break;
|
||||||
case 'q': pwrd(f, va_arg(ap, char *)); break;
|
case 'd':
|
||||||
case 'r': errstr(err, sizeof err); pstr(f, err); break;
|
pdec(f, va_arg(ap, int));
|
||||||
case 's': pstr(f, va_arg(ap, char *)); break;
|
break;
|
||||||
case 't': pcmd(f, va_arg(ap, struct tree *)); break;
|
case 'o':
|
||||||
case 'v': pval(f, va_arg(ap, struct word *)); break;
|
poct(f, va_arg(ap, unsigned));
|
||||||
default: pchr(f, *fmt); break;
|
break;
|
||||||
|
case 'p':
|
||||||
|
pptr(f, va_arg(ap, void*));
|
||||||
|
break;
|
||||||
|
case 'Q':
|
||||||
|
pquo(f, va_arg(ap, char *));
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
pwrd(f, va_arg(ap, char *));
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
errstr(err, sizeof err); pstr(f, err);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
pstr(f, va_arg(ap, char *));
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
pcmd(f, va_arg(ap, struct tree *));
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
pval(f, va_arg(ap, struct word *));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pchr(f, *fmt);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if(--pfmtnest==0) flush(f);
|
if(--pfmtnest==0)
|
||||||
|
flush(f);
|
||||||
}
|
}
|
||||||
void pchr(io *b, int c)
|
|
||||||
|
void
|
||||||
|
pchr(io *b, int c)
|
||||||
{
|
{
|
||||||
if(b->bufp==b->ebuf) fullbuf(b, c);
|
if(b->bufp==b->ebuf)
|
||||||
|
fullbuf(b, c);
|
||||||
else *b->bufp++=c;
|
else *b->bufp++=c;
|
||||||
}
|
}
|
||||||
int rchr(io *b)
|
|
||||||
|
int
|
||||||
|
rchr(io *b)
|
||||||
{
|
{
|
||||||
if(b->bufp==b->ebuf) return emptybuf(b);
|
if(b->bufp==b->ebuf)
|
||||||
|
return emptybuf(b);
|
||||||
return *b->bufp++ & 0xFF;
|
return *b->bufp++ & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pquo(io *f, char *s)
|
void
|
||||||
|
pquo(io *f, char *s)
|
||||||
{
|
{
|
||||||
pchr(f, '\'');
|
pchr(f, '\'');
|
||||||
for(;*s;s++)
|
for(;*s;s++)
|
||||||
if(*s=='\'') pfmt(f, "''");
|
if(*s=='\'')
|
||||||
|
pfmt(f, "''");
|
||||||
else pchr(f, *s);
|
else pchr(f, *s);
|
||||||
pchr(f, '\'');
|
pchr(f, '\'');
|
||||||
}
|
}
|
||||||
void pwrd(io *f, char *s)
|
|
||||||
|
void
|
||||||
|
pwrd(io *f, char *s)
|
||||||
{
|
{
|
||||||
char *t;
|
char *t;
|
||||||
for(t=s;*t;t++) if(!wordchr(*t)) break;
|
for(t = s;*t;t++) if(!wordchr(*t)) break;
|
||||||
if(t==s || *t) pquo(f, s);
|
if(t==s || *t)
|
||||||
|
pquo(f, s);
|
||||||
else pstr(f, s);
|
else pstr(f, s);
|
||||||
}
|
}
|
||||||
void phex(io *f, long p)
|
|
||||||
|
void
|
||||||
|
pptr(io *f, void *v)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
for(n=28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
|
uintptr p;
|
||||||
|
|
||||||
|
p = (uintptr)v;
|
||||||
|
if(sizeof(uintptr) == sizeof(uvlong) && p>>32)
|
||||||
|
for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
|
||||||
|
|
||||||
|
for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
|
||||||
}
|
}
|
||||||
void pstr(io *f, char *s)
|
|
||||||
|
void
|
||||||
|
pstr(io *f, char *s)
|
||||||
{
|
{
|
||||||
if(s==0) s="(null)";
|
if(s==0)
|
||||||
|
s="(null)";
|
||||||
while(*s) pchr(f, *s++);
|
while(*s) pchr(f, *s++);
|
||||||
}
|
}
|
||||||
void pdec(io *f, long n)
|
|
||||||
|
void
|
||||||
|
pdec(io *f, int n)
|
||||||
{
|
{
|
||||||
if(n<0){
|
if(n<0){
|
||||||
n=-n;
|
n=-n;
|
||||||
@ -73,110 +126,136 @@ void pdec(io *f, long n)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* n is two's complement minimum integer */
|
/* n is two's complement minimum integer */
|
||||||
n=1-n;
|
n = 1-n;
|
||||||
pchr(f, '-');
|
pchr(f, '-');
|
||||||
pdec(f, n/10);
|
pdec(f, n/10);
|
||||||
pchr(f, n%10+'1');
|
pchr(f, n%10+'1');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(n>9) pdec(f, n/10);
|
if(n>9)
|
||||||
|
pdec(f, n/10);
|
||||||
pchr(f, n%10+'0');
|
pchr(f, n%10+'0');
|
||||||
}
|
}
|
||||||
void poct(io *f, ulong n)
|
|
||||||
|
void
|
||||||
|
poct(io *f, unsigned n)
|
||||||
{
|
{
|
||||||
if(n>7) poct(f, n>>3);
|
if(n>7)
|
||||||
|
poct(f, n>>3);
|
||||||
pchr(f, (n&7)+'0');
|
pchr(f, (n&7)+'0');
|
||||||
}
|
}
|
||||||
void pval(io *f, word *a)
|
|
||||||
|
void
|
||||||
|
pval(io *f, word *a)
|
||||||
{
|
{
|
||||||
if(a){
|
if(a){
|
||||||
while(a->next && a->next->word){
|
while(a->next && a->next->word){
|
||||||
pwrd(f, a->word);
|
pwrd(f, a->word);
|
||||||
pchr(f, ' ');
|
pchr(f, ' ');
|
||||||
a=a->next;
|
a = a->next;
|
||||||
}
|
}
|
||||||
pwrd(f, a->word);
|
pwrd(f, a->word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int fullbuf(io *f, int c)
|
|
||||||
|
int
|
||||||
|
fullbuf(io *f, int c)
|
||||||
{
|
{
|
||||||
flush(f);
|
flush(f);
|
||||||
return *f->bufp++=c;
|
return *f->bufp++=c;
|
||||||
}
|
}
|
||||||
void flush(io *f)
|
|
||||||
|
void
|
||||||
|
flush(io *f)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
char *s;
|
char *s;
|
||||||
if(f->strp){
|
if(f->strp){
|
||||||
n=f->ebuf-f->strp;
|
n = f->ebuf-f->strp;
|
||||||
f->strp=realloc(f->strp, n+101);
|
f->strp = realloc(f->strp, n+101);
|
||||||
if(f->strp==0) panic("Can't realloc %d bytes in flush!", n+101);
|
if(f->strp==0)
|
||||||
f->bufp=f->strp+n;
|
panic("Can't realloc %d bytes in flush!", n+101);
|
||||||
f->ebuf=f->bufp+100;
|
f->bufp = f->strp+n;
|
||||||
for(s=f->bufp;s<=f->ebuf;s++) *s='\0';
|
f->ebuf = f->bufp+100;
|
||||||
|
for(s = f->bufp;s<=f->ebuf;s++) *s='\0';
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
n=f->bufp-f->buf;
|
n = f->bufp-f->buf;
|
||||||
if(n && Write(f->fd, f->buf, n) < 0){
|
if(n && Write(f->fd, f->buf, n) < 0){
|
||||||
Write(3, "Write error\n", 12);
|
Write(3, "Write error\n", 12);
|
||||||
if(ntrap) dotrap();
|
if(ntrap)
|
||||||
|
dotrap();
|
||||||
}
|
}
|
||||||
f->bufp=f->buf;
|
f->bufp = f->buf;
|
||||||
f->ebuf=f->buf+NBUF;
|
f->ebuf = f->buf+NBUF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
io *openfd(int fd){
|
|
||||||
io *f;
|
io*
|
||||||
f=new(struct io);
|
openfd(int fd)
|
||||||
f->fd=fd;
|
{
|
||||||
f->bufp=f->ebuf=f->buf;
|
io *f = new(struct io);
|
||||||
f->strp=0;
|
f->fd = fd;
|
||||||
|
f->bufp = f->ebuf = f->buf;
|
||||||
|
f->strp = 0;
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
io *openstr(void){
|
|
||||||
io *f=new(struct io);
|
io*
|
||||||
|
openstr(void)
|
||||||
|
{
|
||||||
|
io *f = new(struct io);
|
||||||
char *s;
|
char *s;
|
||||||
f->fd=-1;
|
f->fd=-1;
|
||||||
f->bufp=f->strp=emalloc(101);
|
f->bufp = f->strp = emalloc(101);
|
||||||
f->ebuf=f->bufp+100;
|
f->ebuf = f->bufp+100;
|
||||||
for(s=f->bufp;s<=f->ebuf;s++) *s='\0';
|
for(s = f->bufp;s<=f->ebuf;s++) *s='\0';
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Open a corebuffer to read. EOF occurs after reading len
|
* Open a corebuffer to read. EOF occurs after reading len
|
||||||
* characters from buf.
|
* characters from buf.
|
||||||
*/
|
*/
|
||||||
io *opencore(char *s, int len)
|
|
||||||
|
io*
|
||||||
|
opencore(char *s, int len)
|
||||||
{
|
{
|
||||||
io *f=new(struct io);
|
io *f = new(struct io);
|
||||||
char *buf=emalloc(len);
|
char *buf = emalloc(len);
|
||||||
f->fd= -1 /*open("/dev/null", 0)*/;
|
f->fd= -1 /*open("/dev/null", 0)*/;
|
||||||
f->bufp=f->strp=buf;
|
f->bufp = f->strp = buf;
|
||||||
f->ebuf=buf+len;
|
f->ebuf = buf+len;
|
||||||
Memcpy(buf, s, len);
|
Memcpy(buf, s, len);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
void rewind(io *io)
|
void
|
||||||
|
rewind(io *io)
|
||||||
{
|
{
|
||||||
if(io->fd==-1) io->bufp=io->strp;
|
if(io->fd==-1)
|
||||||
|
io->bufp = io->strp;
|
||||||
else{
|
else{
|
||||||
io->bufp=io->ebuf=io->buf;
|
io->bufp = io->ebuf = io->buf;
|
||||||
Seek(io->fd, 0L, 0);
|
Seek(io->fd, 0L, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
void closeio(io *io)
|
void
|
||||||
|
closeio(io *io)
|
||||||
{
|
{
|
||||||
if(io->fd>=0) close(io->fd);
|
if(io->fd>=0)
|
||||||
if(io->strp) efree(io->strp);
|
close(io->fd);
|
||||||
|
if(io->strp)
|
||||||
|
efree(io->strp);
|
||||||
efree((char *)io);
|
efree((char *)io);
|
||||||
}
|
}
|
||||||
int emptybuf(io *f)
|
|
||||||
|
int
|
||||||
|
emptybuf(io *f)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
if(f->fd==-1 || (n=Read(f->fd, f->buf, NBUF))<=0) return EOF;
|
if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF;
|
||||||
f->bufp=f->buf;
|
f->bufp = f->buf;
|
||||||
f->ebuf=f->buf+n;
|
f->ebuf = f->buf+n;
|
||||||
return *f->bufp++&0xff;
|
return *f->bufp++&0xff;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,9 +18,9 @@ int rchr(io*);
|
|||||||
void closeio(io*);
|
void closeio(io*);
|
||||||
void flush(io*);
|
void flush(io*);
|
||||||
int fullbuf(io*, int);
|
int fullbuf(io*, int);
|
||||||
void pdec(io*, long);
|
void pdec(io*, int);
|
||||||
void poct(io*, ulong);
|
void poct(io*, unsigned);
|
||||||
void phex(io*, long);
|
void pptr(io*, void*);
|
||||||
void pquo(io*, char*);
|
void pquo(io*, char*);
|
||||||
void pwrd(io*, char*);
|
void pwrd(io*, char*);
|
||||||
void pstr(io*, char*);
|
void pstr(io*, char*);
|
||||||
|
|||||||
278
src/cmd/rc/lex.c
278
src/cmd/rc/lex.c
@ -4,11 +4,15 @@
|
|||||||
#include "getflags.h"
|
#include "getflags.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
int getnext(void);
|
int getnext(void);
|
||||||
int wordchr(int c)
|
|
||||||
|
int
|
||||||
|
wordchr(int c)
|
||||||
{
|
{
|
||||||
return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
|
return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
|
||||||
}
|
}
|
||||||
int idchr(int c)
|
|
||||||
|
int
|
||||||
|
idchr(int c)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Formerly:
|
* Formerly:
|
||||||
@ -17,127 +21,170 @@ int idchr(int c)
|
|||||||
*/
|
*/
|
||||||
return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
|
return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
|
||||||
}
|
}
|
||||||
int future=EOF;
|
int future = EOF;
|
||||||
int doprompt=1;
|
int doprompt = 1;
|
||||||
int inquote;
|
int inquote;
|
||||||
|
int incomm;
|
||||||
/*
|
/*
|
||||||
* Look ahead in the input stream
|
* Look ahead in the input stream
|
||||||
*/
|
*/
|
||||||
int nextc(void){
|
|
||||||
if(future==EOF) future=getnext();
|
int
|
||||||
|
nextc(void)
|
||||||
|
{
|
||||||
|
if(future==EOF)
|
||||||
|
future = getnext();
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Consume the lookahead character.
|
* Consume the lookahead character.
|
||||||
*/
|
*/
|
||||||
int advance(void){
|
|
||||||
int c=nextc();
|
int
|
||||||
lastc=future;
|
advance(void)
|
||||||
future=EOF;
|
{
|
||||||
|
int c = nextc();
|
||||||
|
lastc = future;
|
||||||
|
future = EOF;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* read a character from the input stream
|
* read a character from the input stream
|
||||||
*/
|
*/
|
||||||
int getnext(void){
|
|
||||||
register int c;
|
int
|
||||||
static int peekc=EOF;
|
getnext(void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
static int peekc = EOF;
|
||||||
if(peekc!=EOF){
|
if(peekc!=EOF){
|
||||||
c=peekc;
|
c = peekc;
|
||||||
peekc=EOF;
|
peekc = EOF;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
if(runq->eof) return EOF;
|
if(runq->eof)
|
||||||
if(doprompt) pprompt();
|
return EOF;
|
||||||
c=rchr(runq->cmdfd);
|
if(doprompt)
|
||||||
|
pprompt();
|
||||||
|
c = rchr(runq->cmdfd);
|
||||||
if(!inquote && c=='\\'){
|
if(!inquote && c=='\\'){
|
||||||
c=rchr(runq->cmdfd);
|
c = rchr(runq->cmdfd);
|
||||||
if(c=='\n'){
|
if(c=='\n' && !incomm){ /* don't continue a comment */
|
||||||
doprompt=1;
|
doprompt = 1;
|
||||||
c=' ';
|
c=' ';
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
peekc=c;
|
peekc = c;
|
||||||
c='\\';
|
c='\\';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
doprompt=doprompt || c=='\n' || c==EOF;
|
doprompt = doprompt || c=='\n' || c==EOF;
|
||||||
if(c==EOF) runq->eof++;
|
if(c==EOF)
|
||||||
|
runq->eof++;
|
||||||
else if(flag['V'] || ndot>=2 && flag['v']) pchr(err, c);
|
else if(flag['V'] || ndot>=2 && flag['v']) pchr(err, c);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
void pprompt(void){
|
|
||||||
|
void
|
||||||
|
pprompt(void)
|
||||||
|
{
|
||||||
var *prompt;
|
var *prompt;
|
||||||
if(runq->iflag){
|
if(runq->iflag){
|
||||||
pstr(err, promptstr);
|
pstr(err, promptstr);
|
||||||
flush(err);
|
flush(err);
|
||||||
prompt=vlook("prompt");
|
prompt = vlook("prompt");
|
||||||
if(prompt->val && prompt->val->next)
|
if(prompt->val && prompt->val->next)
|
||||||
promptstr=prompt->val->next->word;
|
promptstr = prompt->val->next->word;
|
||||||
else
|
else
|
||||||
promptstr="\t";
|
promptstr="\t";
|
||||||
}
|
}
|
||||||
runq->lineno++;
|
runq->lineno++;
|
||||||
doprompt=0;
|
doprompt = 0;
|
||||||
}
|
}
|
||||||
void skipwhite(void){
|
|
||||||
|
void
|
||||||
|
skipwhite(void)
|
||||||
|
{
|
||||||
int c;
|
int c;
|
||||||
for(;;){
|
for(;;){
|
||||||
c=nextc();
|
c = nextc();
|
||||||
if(c=='#'){ /* Why did this used to be if(!inquote && c=='#') ?? */
|
/* Why did this used to be if(!inquote && c=='#') ?? */
|
||||||
|
if(c=='#'){
|
||||||
|
incomm = 1;
|
||||||
for(;;){
|
for(;;){
|
||||||
c=nextc();
|
c = nextc();
|
||||||
if(c=='\n' || c==EOF) break;
|
if(c=='\n' || c==EOF) {
|
||||||
|
incomm = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(c==' ' || c=='\t') advance();
|
if(c==' ' || c=='\t')
|
||||||
|
advance();
|
||||||
else return;
|
else return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void skipnl(void){
|
|
||||||
register int c;
|
void
|
||||||
|
skipnl(void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
for(;;){
|
for(;;){
|
||||||
skipwhite();
|
skipwhite();
|
||||||
c=nextc();
|
c = nextc();
|
||||||
if(c!='\n') return;
|
if(c!='\n')
|
||||||
|
return;
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int nextis(int c){
|
|
||||||
|
int
|
||||||
|
nextis(int c)
|
||||||
|
{
|
||||||
if(nextc()==c){
|
if(nextc()==c){
|
||||||
advance();
|
advance();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
char *addtok(char *p, int val){
|
|
||||||
if(p==0) return 0;
|
char*
|
||||||
|
addtok(char *p, int val)
|
||||||
|
{
|
||||||
|
if(p==0)
|
||||||
|
return 0;
|
||||||
if(p==&tok[NTOK-1]){
|
if(p==&tok[NTOK-1]){
|
||||||
*p=0;
|
*p = 0;
|
||||||
yyerror("token buffer too short");
|
yyerror("token buffer too short");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*p++=val;
|
*p++=val;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
char *addutf(char *p, int c){
|
|
||||||
p=addtok(p, c);
|
char*
|
||||||
|
addutf(char *p, int c)
|
||||||
|
{
|
||||||
|
p = addtok(p, c);
|
||||||
if(twobyte(c)) /* 2-byte escape */
|
if(twobyte(c)) /* 2-byte escape */
|
||||||
return addtok(p, advance());
|
return addtok(p, advance());
|
||||||
if(threebyte(c)){ /* 3-byte escape */
|
if(threebyte(c)){ /* 3-byte escape */
|
||||||
p=addtok(p, advance());
|
p = addtok(p, advance());
|
||||||
return addtok(p, advance());
|
return addtok(p, advance());
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
int lastdol; /* was the last token read '$' or '$#' or '"'? */
|
int lastdol; /* was the last token read '$' or '$#' or '"'? */
|
||||||
int lastword; /* was the last token read a word or compound word terminator? */
|
int lastword; /* was the last token read a word or compound word terminator? */
|
||||||
int yylex(void){
|
|
||||||
register int c, d=nextc();
|
int
|
||||||
register char *w=tok;
|
yylex(void)
|
||||||
register struct tree *t;
|
{
|
||||||
yylval.tree=0;
|
int c, d = nextc();
|
||||||
|
char *w = tok;
|
||||||
|
struct tree *t;
|
||||||
|
yylval.tree = 0;
|
||||||
/*
|
/*
|
||||||
* Embarassing sneakiness: if the last token read was a quoted or unquoted
|
* Embarassing sneakiness: if the last token read was a quoted or unquoted
|
||||||
* WORD then we alter the meaning of what follows. If the next character
|
* WORD then we alter the meaning of what follows. If the next character
|
||||||
@ -146,7 +193,7 @@ int yylex(void){
|
|||||||
* we insert a `^' before it.
|
* we insert a `^' before it.
|
||||||
*/
|
*/
|
||||||
if(lastword){
|
if(lastword){
|
||||||
lastword=0;
|
lastword = 0;
|
||||||
if(d=='('){
|
if(d=='('){
|
||||||
advance();
|
advance();
|
||||||
strcpy(tok, "( [SUB]");
|
strcpy(tok, "( [SUB]");
|
||||||
@ -157,15 +204,15 @@ int yylex(void){
|
|||||||
return '^';
|
return '^';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inquote=0;
|
inquote = 0;
|
||||||
skipwhite();
|
skipwhite();
|
||||||
switch(c=advance()){
|
switch(c = advance()){
|
||||||
case EOF:
|
case EOF:
|
||||||
lastdol=0;
|
lastdol = 0;
|
||||||
strcpy(tok, "EOF");
|
strcpy(tok, "EOF");
|
||||||
return EOF;
|
return EOF;
|
||||||
case '$':
|
case '$':
|
||||||
lastdol=1;
|
lastdol = 1;
|
||||||
if(nextis('#')){
|
if(nextis('#')){
|
||||||
strcpy(tok, "$#");
|
strcpy(tok, "$#");
|
||||||
return COUNT;
|
return COUNT;
|
||||||
@ -177,7 +224,7 @@ int yylex(void){
|
|||||||
strcpy(tok, "$");
|
strcpy(tok, "$");
|
||||||
return '$';
|
return '$';
|
||||||
case '&':
|
case '&':
|
||||||
lastdol=0;
|
lastdol = 0;
|
||||||
if(nextis('&')){
|
if(nextis('&')){
|
||||||
skipnl();
|
skipnl();
|
||||||
strcpy(tok, "&&");
|
strcpy(tok, "&&");
|
||||||
@ -186,7 +233,7 @@ int yylex(void){
|
|||||||
strcpy(tok, "&");
|
strcpy(tok, "&");
|
||||||
return '&';
|
return '&';
|
||||||
case '|':
|
case '|':
|
||||||
lastdol=0;
|
lastdol = 0;
|
||||||
if(nextis(c)){
|
if(nextis(c)){
|
||||||
skipnl();
|
skipnl();
|
||||||
strcpy(tok, "||");
|
strcpy(tok, "||");
|
||||||
@ -194,7 +241,7 @@ int yylex(void){
|
|||||||
}
|
}
|
||||||
case '<':
|
case '<':
|
||||||
case '>':
|
case '>':
|
||||||
lastdol=0;
|
lastdol = 0;
|
||||||
/*
|
/*
|
||||||
* funny redirection tokens:
|
* funny redirection tokens:
|
||||||
* redir: arrow | arrow '[' fd ']'
|
* redir: arrow | arrow '[' fd ']'
|
||||||
@ -204,121 +251,128 @@ int yylex(void){
|
|||||||
* some possibilities are nonsensical and get a message.
|
* some possibilities are nonsensical and get a message.
|
||||||
*/
|
*/
|
||||||
*w++=c;
|
*w++=c;
|
||||||
t=newtree();
|
t = newtree();
|
||||||
switch(c){
|
switch(c){
|
||||||
case '|':
|
case '|':
|
||||||
t->type=PIPE;
|
t->type = PIPE;
|
||||||
t->fd0=1;
|
t->fd0 = 1;
|
||||||
t->fd1=0;
|
t->fd1 = 0;
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
t->type=REDIR;
|
t->type = REDIR;
|
||||||
if(nextis(c)){
|
if(nextis(c)){
|
||||||
t->rtype=APPEND;
|
t->rtype = APPEND;
|
||||||
*w++=c;
|
*w++=c;
|
||||||
}
|
}
|
||||||
else t->rtype=WRITE;
|
else t->rtype = WRITE;
|
||||||
t->fd0=1;
|
t->fd0 = 1;
|
||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
t->type=REDIR;
|
t->type = REDIR;
|
||||||
if(nextis(c)){
|
if(nextis(c)){
|
||||||
t->rtype=HERE;
|
t->rtype = HERE;
|
||||||
*w++=c;
|
*w++=c;
|
||||||
}
|
} else if (nextis('>')){
|
||||||
else t->rtype=READ;
|
t->rtype = RDWR;
|
||||||
t->fd0=0;
|
*w++=c;
|
||||||
|
} else t->rtype = READ;
|
||||||
|
t->fd0 = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(nextis('[')){
|
if(nextis('[')){
|
||||||
*w++='[';
|
*w++='[';
|
||||||
c=advance();
|
c = advance();
|
||||||
|
*w++=c;
|
||||||
if(c<'0' || '9'<c){
|
if(c<'0' || '9'<c){
|
||||||
RedirErr:
|
RedirErr:
|
||||||
*w++ = c;
|
*w = 0;
|
||||||
*w=0;
|
|
||||||
yyerror(t->type==PIPE?"pipe syntax"
|
yyerror(t->type==PIPE?"pipe syntax"
|
||||||
:"redirection syntax");
|
:"redirection syntax");
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
t->fd0=0;
|
t->fd0 = 0;
|
||||||
do{
|
do{
|
||||||
t->fd0=t->fd0*10+c-'0';
|
t->fd0 = t->fd0*10+c-'0';
|
||||||
*w++=c;
|
*w++=c;
|
||||||
c=advance();
|
c = advance();
|
||||||
}while('0'<=c && c<='9');
|
}while('0'<=c && c<='9');
|
||||||
if(c=='='){
|
if(c=='='){
|
||||||
*w++='=';
|
*w++='=';
|
||||||
if(t->type==REDIR) t->type=DUP;
|
if(t->type==REDIR)
|
||||||
c=advance();
|
t->type = DUP;
|
||||||
|
c = advance();
|
||||||
if('0'<=c && c<='9'){
|
if('0'<=c && c<='9'){
|
||||||
t->rtype=DUPFD;
|
t->rtype = DUPFD;
|
||||||
t->fd1=t->fd0;
|
t->fd1 = t->fd0;
|
||||||
t->fd0=0;
|
t->fd0 = 0;
|
||||||
do{
|
do{
|
||||||
t->fd0=t->fd0*10+c-'0';
|
t->fd0 = t->fd0*10+c-'0';
|
||||||
*w++=c;
|
*w++=c;
|
||||||
c=advance();
|
c = advance();
|
||||||
}while('0'<=c && c<='9');
|
}while('0'<=c && c<='9');
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(t->type==PIPE) goto RedirErr;
|
if(t->type==PIPE)
|
||||||
t->rtype=CLOSE;
|
goto RedirErr;
|
||||||
|
t->rtype = CLOSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*w=0;
|
|
||||||
if(c!=']'
|
if(c!=']'
|
||||||
|| t->type==DUP && (t->rtype==HERE || t->rtype==APPEND))
|
|| t->type==DUP && (t->rtype==HERE || t->rtype==APPEND))
|
||||||
goto RedirErr;
|
goto RedirErr;
|
||||||
*w++=']';
|
*w++=']';
|
||||||
}
|
}
|
||||||
*w='\0';
|
*w='\0';
|
||||||
yylval.tree=t;
|
yylval.tree = t;
|
||||||
if(t->type==PIPE) skipnl();
|
if(t->type==PIPE)
|
||||||
|
skipnl();
|
||||||
return t->type;
|
return t->type;
|
||||||
case '\'':
|
case '\'':
|
||||||
lastdol=0;
|
lastdol = 0;
|
||||||
lastword=1;
|
lastword = 1;
|
||||||
inquote=1;
|
inquote = 1;
|
||||||
for(;;){
|
for(;;){
|
||||||
c=advance();
|
c = advance();
|
||||||
if(c==EOF) break;
|
if(c==EOF)
|
||||||
|
break;
|
||||||
if(c=='\''){
|
if(c=='\''){
|
||||||
if(nextc()!='\'')
|
if(nextc()!='\'')
|
||||||
break;
|
break;
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
w=addutf(w, c);
|
w = addutf(w, c);
|
||||||
}
|
}
|
||||||
if(w!=0) *w='\0';
|
if(w!=0)
|
||||||
t=token(tok, WORD);
|
*w='\0';
|
||||||
t->quoted=1;
|
t = token(tok, WORD);
|
||||||
yylval.tree=t;
|
t->quoted = 1;
|
||||||
|
yylval.tree = t;
|
||||||
return t->type;
|
return t->type;
|
||||||
}
|
}
|
||||||
if(!wordchr(c)){
|
if(!wordchr(c)){
|
||||||
lastdol=0;
|
lastdol = 0;
|
||||||
tok[0]=c;
|
tok[0] = c;
|
||||||
tok[1]='\0';
|
tok[1]='\0';
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
for(;;){
|
for(;;){
|
||||||
/* next line should have (char)c==GLOB, but ken's compiler is broken */
|
/* next line should have (char)c==GLOB, but ken's compiler is broken */
|
||||||
if(c=='*' || c=='[' || c=='?' || c==(unsigned char)GLOB)
|
if(c=='*' || c=='[' || c=='?' || c==(unsigned char)GLOB)
|
||||||
w=addtok(w, GLOB);
|
w = addtok(w, GLOB);
|
||||||
w=addutf(w, c);
|
w = addutf(w, c);
|
||||||
c=nextc();
|
c = nextc();
|
||||||
if(lastdol?!idchr(c):!wordchr(c)) break;
|
if(lastdol?!idchr(c):!wordchr(c)) break;
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
lastword=1;
|
lastword = 1;
|
||||||
lastdol=0;
|
lastdol = 0;
|
||||||
if(w!=0) *w='\0';
|
if(w!=0)
|
||||||
t=klook(tok);
|
*w='\0';
|
||||||
if(t->type!=WORD) lastword=0;
|
t = klook(tok);
|
||||||
t->quoted=0;
|
if(t->type!=WORD)
|
||||||
yylval.tree=t;
|
lastword = 0;
|
||||||
|
t->quoted = 0;
|
||||||
|
yylval.tree = t;
|
||||||
return t->type;
|
return t->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ OFILES=\
|
|||||||
var.$O\
|
var.$O\
|
||||||
y.tab.$O\
|
y.tab.$O\
|
||||||
plan9ish.$O\
|
plan9ish.$O\
|
||||||
|
havep9p.$O\
|
||||||
|
|
||||||
HFILES=\
|
HFILES=\
|
||||||
rc.h\
|
rc.h\
|
||||||
|
|||||||
@ -5,39 +5,66 @@ char nl='\n'; /* change to semicolon for bourne-proofing */
|
|||||||
#define c0 t->child[0]
|
#define c0 t->child[0]
|
||||||
#define c1 t->child[1]
|
#define c1 t->child[1]
|
||||||
#define c2 t->child[2]
|
#define c2 t->child[2]
|
||||||
void pdeglob(io *f, char *s)
|
|
||||||
|
void
|
||||||
|
pdeglob(io *f, char *s)
|
||||||
{
|
{
|
||||||
while(*s){
|
while(*s){
|
||||||
if(*s==GLOB) s++;
|
if(*s==GLOB)
|
||||||
|
s++;
|
||||||
pchr(f, *s++);
|
pchr(f, *s++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void pcmd(io *f, tree *t)
|
|
||||||
|
void
|
||||||
|
pcmd(io *f, tree *t)
|
||||||
{
|
{
|
||||||
if(t==0) return;
|
if(t==0)
|
||||||
|
return;
|
||||||
switch(t->type){
|
switch(t->type){
|
||||||
default: pfmt(f, "bad %d %p %p %p", t->type, c0, c1, c2); break;
|
default: pfmt(f, "bad %d %p %p %p", t->type, c0, c1, c2);
|
||||||
case '$': pfmt(f, "$%t", c0); break;
|
break;
|
||||||
case '"': pfmt(f, "$\"%t", c0); break;
|
case '$': pfmt(f, "$%t", c0);
|
||||||
case '&': pfmt(f, "%t&", c0); break;
|
break;
|
||||||
case '^': pfmt(f, "%t^%t", c0, c1); break;
|
case '"': pfmt(f, "$\"%t", c0);
|
||||||
case '`': pfmt(f, "`%t", c0); break;
|
break;
|
||||||
case ANDAND: pfmt(f, "%t && %t", c0, c1); break;
|
case '&': pfmt(f, "%t&", c0);
|
||||||
case BANG: pfmt(f, "! %t", c0); break;
|
break;
|
||||||
case BRACE: pfmt(f, "{%t}", c0); break;
|
case '^': pfmt(f, "%t^%t", c0, c1);
|
||||||
case COUNT: pfmt(f, "$#%t", c0); break;
|
break;
|
||||||
case FN: pfmt(f, "fn %t %t", c0, c1); break;
|
case '`': pfmt(f, "`%t", c0);
|
||||||
case IF: pfmt(f, "if%t%t", c0, c1); break;
|
break;
|
||||||
case NOT: pfmt(f, "if not %t", c0); break;
|
case ANDAND: pfmt(f, "%t && %t", c0, c1);
|
||||||
case OROR: pfmt(f, "%t || %t", c0, c1); break;
|
break;
|
||||||
|
case BANG: pfmt(f, "! %t", c0);
|
||||||
|
break;
|
||||||
|
case BRACE: pfmt(f, "{%t}", c0);
|
||||||
|
break;
|
||||||
|
case COUNT: pfmt(f, "$#%t", c0);
|
||||||
|
break;
|
||||||
|
case FN: pfmt(f, "fn %t %t", c0, c1);
|
||||||
|
break;
|
||||||
|
case IF: pfmt(f, "if%t%t", c0, c1);
|
||||||
|
break;
|
||||||
|
case NOT: pfmt(f, "if not %t", c0);
|
||||||
|
break;
|
||||||
|
case OROR: pfmt(f, "%t || %t", c0, c1);
|
||||||
|
break;
|
||||||
case PCMD:
|
case PCMD:
|
||||||
case PAREN: pfmt(f, "(%t)", c0); break;
|
case PAREN: pfmt(f, "(%t)", c0);
|
||||||
case SUB: pfmt(f, "$%t(%t)", c0, c1); break;
|
break;
|
||||||
case SIMPLE: pfmt(f, "%t", c0); break;
|
case SUB: pfmt(f, "$%t(%t)", c0, c1);
|
||||||
case SUBSHELL: pfmt(f, "@ %t", c0); break;
|
break;
|
||||||
case SWITCH: pfmt(f, "switch %t %t", c0, c1); break;
|
case SIMPLE: pfmt(f, "%t", c0);
|
||||||
case TWIDDLE: pfmt(f, "~ %t %t", c0, c1); break;
|
break;
|
||||||
case WHILE: pfmt(f, "while %t%t", c0, c1); break;
|
case SUBSHELL: pfmt(f, "@ %t", c0);
|
||||||
|
break;
|
||||||
|
case SWITCH: pfmt(f, "switch %t %t", c0, c1);
|
||||||
|
break;
|
||||||
|
case TWIDDLE: pfmt(f, "~ %t %t", c0, c1);
|
||||||
|
break;
|
||||||
|
case WHILE: pfmt(f, "while %t%t", c0, c1);
|
||||||
|
break;
|
||||||
case ARGLIST:
|
case ARGLIST:
|
||||||
if(c0==0)
|
if(c0==0)
|
||||||
pfmt(f, "%t", c1);
|
pfmt(f, "%t", c1);
|
||||||
@ -48,22 +75,26 @@ void pcmd(io *f, tree *t)
|
|||||||
break;
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
if(c0){
|
if(c0){
|
||||||
if(c1) pfmt(f, "%t%c%t", c0, nl, c1);
|
if(c1)
|
||||||
|
pfmt(f, "%t%c%t", c0, nl, c1);
|
||||||
else pfmt(f, "%t", c0);
|
else pfmt(f, "%t", c0);
|
||||||
}
|
}
|
||||||
else pfmt(f, "%t", c1);
|
else pfmt(f, "%t", c1);
|
||||||
break;
|
break;
|
||||||
case WORDS:
|
case WORDS:
|
||||||
if(c0) pfmt(f, "%t ", c0);
|
if(c0)
|
||||||
|
pfmt(f, "%t ", c0);
|
||||||
pfmt(f, "%t", c1);
|
pfmt(f, "%t", c1);
|
||||||
break;
|
break;
|
||||||
case FOR:
|
case FOR:
|
||||||
pfmt(f, "for(%t", c0);
|
pfmt(f, "for(%t", c0);
|
||||||
if(c1) pfmt(f, " in %t", c1);
|
if(c1)
|
||||||
|
pfmt(f, " in %t", c1);
|
||||||
pfmt(f, ")%t", c2);
|
pfmt(f, ")%t", c2);
|
||||||
break;
|
break;
|
||||||
case WORD:
|
case WORD:
|
||||||
if(t->quoted) pfmt(f, "%Q", t->str);
|
if(t->quoted)
|
||||||
|
pfmt(f, "%Q", t->str);
|
||||||
else pdeglob(f, t->str);
|
else pdeglob(f, t->str);
|
||||||
break;
|
break;
|
||||||
case DUP:
|
case DUP:
|
||||||
@ -79,27 +110,35 @@ void pcmd(io *f, tree *t)
|
|||||||
case HERE:
|
case HERE:
|
||||||
pchr(f, '<');
|
pchr(f, '<');
|
||||||
case READ:
|
case READ:
|
||||||
|
case RDWR:
|
||||||
pchr(f, '<');
|
pchr(f, '<');
|
||||||
if(t->fd0!=0) pfmt(f, "[%d]", t->fd0);
|
if(t->rtype==RDWR)
|
||||||
|
pchr(f, '>');
|
||||||
|
if(t->fd0!=0)
|
||||||
|
pfmt(f, "[%d]", t->fd0);
|
||||||
break;
|
break;
|
||||||
case APPEND:
|
case APPEND:
|
||||||
pchr(f, '>');
|
pchr(f, '>');
|
||||||
case WRITE:
|
case WRITE:
|
||||||
pchr(f, '>');
|
pchr(f, '>');
|
||||||
if(t->fd0!=1) pfmt(f, "[%d]", t->fd0);
|
if(t->fd0!=1)
|
||||||
|
pfmt(f, "[%d]", t->fd0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pfmt(f, "%t", c0);
|
pfmt(f, "%t", c0);
|
||||||
if(c1) pfmt(f, " %t", c1);
|
if(c1)
|
||||||
|
pfmt(f, " %t", c1);
|
||||||
break;
|
break;
|
||||||
case '=':
|
case '=':
|
||||||
pfmt(f, "%t=%t", c0, c1);
|
pfmt(f, "%t=%t", c0, c1);
|
||||||
if(c2) pfmt(f, " %t", c2);
|
if(c2)
|
||||||
|
pfmt(f, " %t", c2);
|
||||||
break;
|
break;
|
||||||
case PIPE:
|
case PIPE:
|
||||||
pfmt(f, "%t|", c0);
|
pfmt(f, "%t|", c0);
|
||||||
if(t->fd1==0){
|
if(t->fd1==0){
|
||||||
if(t->fd0!=1) pfmt(f, "[%d]", t->fd0);
|
if(t->fd0!=1)
|
||||||
|
pfmt(f, "[%d]", t->fd0);
|
||||||
}
|
}
|
||||||
else pfmt(f, "[%d=%d]", t->fd0, t->fd1);
|
else pfmt(f, "[%d=%d]", t->fd0, t->fd1);
|
||||||
pfmt(f, "%t", c1);
|
pfmt(f, "%t", c1);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
struct{
|
struct{
|
||||||
void (*f)(void);
|
void (*f)(void);
|
||||||
char *name;
|
char *name;
|
||||||
}fname[]={
|
}fname[] = {
|
||||||
Xappend, "Xappend",
|
Xappend, "Xappend",
|
||||||
Xasync, "Xasync",
|
Xasync, "Xasync",
|
||||||
Xbang, "Xbang",
|
Xbang, "Xbang",
|
||||||
@ -18,6 +18,7 @@ struct{
|
|||||||
Xjump, "Xjump",
|
Xjump, "Xjump",
|
||||||
Xmark, "Xmark",
|
Xmark, "Xmark",
|
||||||
Xpopm, "Xpopm",
|
Xpopm, "Xpopm",
|
||||||
|
Xrdwr, "Xrdwr",
|
||||||
Xread, "Xread",
|
Xread, "Xread",
|
||||||
Xreturn, "Xreturn",
|
Xreturn, "Xreturn",
|
||||||
Xtrue, "Xtrue",
|
Xtrue, "Xtrue",
|
||||||
@ -50,18 +51,21 @@ struct{
|
|||||||
Xrdfn, "Xrdfn",
|
Xrdfn, "Xrdfn",
|
||||||
Xqdol, "Xqdol",
|
Xqdol, "Xqdol",
|
||||||
0};
|
0};
|
||||||
void pfnc(io *fd, thread *t)
|
|
||||||
|
void
|
||||||
|
pfnc(io *fd, thread *t)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
void (*fn)(void)=t->code[t->pc].f;
|
void (*fn)(void) = t->code[t->pc].f;
|
||||||
list *a;
|
list *a;
|
||||||
pfmt(fd, "pid %d cycle %p %d ", getpid(), t->code, t->pc);
|
pfmt(fd, "pid %d cycle %p %d ", getpid(), t->code, t->pc);
|
||||||
for(i=0;fname[i].f;i++) if(fname[i].f==fn){
|
for(i = 0;fname[i].f;i++) if(fname[i].f==fn){
|
||||||
pstr(fd, fname[i].name);
|
pstr(fd, fname[i].name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!fname[i].f) pfmt(fd, "%p", fn);
|
if(!fname[i].f)
|
||||||
for(a=t->argv;a;a=a->next) pfmt(fd, " (%v)", a->words);
|
pfmt(fd, "%p", fn);
|
||||||
|
for(a = t->argv;a;a = a->next) pfmt(fd, " (%v)", a->words);
|
||||||
pchr(fd, '\n');
|
pchr(fd, '\n');
|
||||||
flush(fd);
|
flush(fd);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -411,9 +411,11 @@ int Opendir(char *name)
|
|||||||
close(f);
|
close(f);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int Readdir(int f, char *p)
|
int Readdir(int f, char *p, int onlydirs)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
USED(onlydirs); /* only advisory */
|
||||||
|
|
||||||
if(f<0 || f>=NFD)
|
if(f<0 || f>=NFD)
|
||||||
return 0;
|
return 0;
|
||||||
if(dir[f].i==dir[f].n){ /* read */
|
if(dir[f].i==dir[f].n){ /* read */
|
||||||
|
|||||||
@ -80,6 +80,7 @@ char tok[NTOK];
|
|||||||
#define HERE 4
|
#define HERE 4
|
||||||
#define DUPFD 5
|
#define DUPFD 5
|
||||||
#define CLOSE 6
|
#define CLOSE 6
|
||||||
|
#define RDWR 7
|
||||||
struct var{
|
struct var{
|
||||||
char *name; /* ascii name */
|
char *name; /* ascii name */
|
||||||
word *val; /* value */
|
word *val; /* value */
|
||||||
|
|||||||
@ -15,22 +15,24 @@ exitnext(void){
|
|||||||
while(c->f==Xpopredir) c++;
|
while(c->f==Xpopredir) c++;
|
||||||
return c->f==Xexit;
|
return c->f==Xexit;
|
||||||
}
|
}
|
||||||
void Xsimple(void){
|
|
||||||
|
void
|
||||||
|
Xsimple(void)
|
||||||
|
{
|
||||||
word *a;
|
word *a;
|
||||||
thread *p=runq;
|
thread *p = runq;
|
||||||
var *v;
|
var *v;
|
||||||
struct builtin *bp;
|
struct builtin *bp;
|
||||||
int pid, n;
|
int pid;
|
||||||
char buf[ERRMAX];
|
|
||||||
globlist();
|
globlist();
|
||||||
a=runq->argv->words;
|
a = runq->argv->words;
|
||||||
if(a==0){
|
if(a==0){
|
||||||
Xerror1("empty argument list");
|
Xerror1("empty argument list");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(flag['x'])
|
if(flag['x'])
|
||||||
pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
|
pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
|
||||||
v=gvlook(a->word);
|
v = gvlook(a->word);
|
||||||
if(v->fn)
|
if(v->fn)
|
||||||
execfunc(v);
|
execfunc(v);
|
||||||
else{
|
else{
|
||||||
@ -41,10 +43,10 @@ void Xsimple(void){
|
|||||||
poplist();
|
poplist();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
a=a->next;
|
a = a->next;
|
||||||
popword();
|
popword();
|
||||||
}
|
}
|
||||||
for(bp=Builtin;bp->name;bp++)
|
for(bp = Builtin;bp->name;bp++)
|
||||||
if(strcmp(a->word, bp->name)==0){
|
if(strcmp(a->word, bp->name)==0){
|
||||||
(*bp->fnc)();
|
(*bp->fnc)();
|
||||||
return;
|
return;
|
||||||
@ -58,30 +60,22 @@ void Xsimple(void){
|
|||||||
else{
|
else{
|
||||||
flush(err);
|
flush(err);
|
||||||
Updenv(); /* necessary so changes don't go out again */
|
Updenv(); /* necessary so changes don't go out again */
|
||||||
switch(pid=fork()){
|
if((pid = execforkexec()) < 0){
|
||||||
case -1:
|
|
||||||
Xerror("try again");
|
Xerror("try again");
|
||||||
return;
|
return;
|
||||||
case 0:
|
|
||||||
pushword("exec");
|
|
||||||
execexec();
|
|
||||||
strcpy(buf, "can't exec: ");
|
|
||||||
n = strlen(buf);
|
|
||||||
errstr(buf+n, ERRMAX-n);
|
|
||||||
Exit(buf);
|
|
||||||
default:
|
|
||||||
kidpid = pid;
|
|
||||||
poplist();
|
|
||||||
/* interrupts don't get us out */
|
|
||||||
while(Waitfor(pid, 1) < 0)
|
|
||||||
;
|
|
||||||
kidpid = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* interrupts don't get us out */
|
||||||
|
poplist();
|
||||||
|
while(Waitfor(pid, 1) < 0)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct word nullpath={ "", 0};
|
struct word nullpath = { "", 0};
|
||||||
void doredir(redir *rp)
|
|
||||||
|
void
|
||||||
|
doredir(redir *rp)
|
||||||
{
|
{
|
||||||
if(rp){
|
if(rp){
|
||||||
doredir(rp->next);
|
doredir(rp->next);
|
||||||
@ -92,22 +86,32 @@ void doredir(redir *rp)
|
|||||||
close(rp->from);
|
close(rp->from);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RDUP: Dup(rp->from, rp->to); break;
|
case RDUP:
|
||||||
case RCLOSE: close(rp->from); break;
|
Dup(rp->from, rp->to);
|
||||||
|
break;
|
||||||
|
case RCLOSE:
|
||||||
|
close(rp->from);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
word *searchpath(char *w){
|
|
||||||
|
word*
|
||||||
|
searchpath(char *w)
|
||||||
|
{
|
||||||
word *path;
|
word *path;
|
||||||
if(strncmp(w, "/", 1)==0
|
if(strncmp(w, "/", 1)==0
|
||||||
/* || strncmp(w, "#", 1)==0 */
|
/* || strncmp(w, "#", 1)==0 */
|
||||||
|| strncmp(w, "./", 2)==0
|
|| strncmp(w, "./", 2)==0
|
||||||
|| strncmp(w, "../", 3)==0
|
|| strncmp(w, "../", 3)==0
|
||||||
|| (path=vlook("path")->val)==0)
|
|| (path = vlook("path")->val)==0)
|
||||||
path=&nullpath;
|
path=&nullpath;
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
void execexec(void){
|
|
||||||
|
void
|
||||||
|
execexec(void)
|
||||||
|
{
|
||||||
popword(); /* "exec" */
|
popword(); /* "exec" */
|
||||||
if(runq->argv->words==0){
|
if(runq->argv->words==0){
|
||||||
Xerror1("empty argument list");
|
Xerror1("empty argument list");
|
||||||
@ -117,19 +121,24 @@ void execexec(void){
|
|||||||
Execute(runq->argv->words, searchpath(runq->argv->words->word));
|
Execute(runq->argv->words, searchpath(runq->argv->words->word));
|
||||||
poplist();
|
poplist();
|
||||||
}
|
}
|
||||||
void execfunc(var *func)
|
|
||||||
|
void
|
||||||
|
execfunc(var *func)
|
||||||
{
|
{
|
||||||
word *starval;
|
word *starval;
|
||||||
popword();
|
popword();
|
||||||
starval=runq->argv->words;
|
starval = runq->argv->words;
|
||||||
runq->argv->words=0;
|
runq->argv->words = 0;
|
||||||
poplist();
|
poplist();
|
||||||
start(func->fn, func->pc, (struct var *)0);
|
start(func->fn, func->pc, (struct var *)0);
|
||||||
runq->local=newvar(strdup("*"), runq->local);
|
runq->local = newvar(strdup("*"), runq->local);
|
||||||
runq->local->val=starval;
|
runq->local->val = starval;
|
||||||
runq->local->changed=1;
|
runq->local->changed = 1;
|
||||||
}
|
}
|
||||||
int dochdir(char *word){
|
|
||||||
|
int
|
||||||
|
dochdir(char *word)
|
||||||
|
{
|
||||||
/* report to /dev/wdir if it exists and we're interactive */
|
/* report to /dev/wdir if it exists and we're interactive */
|
||||||
static int wdirfd = -2;
|
static int wdirfd = -2;
|
||||||
if(chdir(word)<0) return -1;
|
if(chdir(word)<0) return -1;
|
||||||
@ -141,21 +150,26 @@ int dochdir(char *word){
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
void execcd(void){
|
|
||||||
word *a=runq->argv->words;
|
void
|
||||||
|
execcd(void)
|
||||||
|
{
|
||||||
|
word *a = runq->argv->words;
|
||||||
word *cdpath;
|
word *cdpath;
|
||||||
char dir[512];
|
char dir[512];
|
||||||
setstatus("can't cd");
|
setstatus("can't cd");
|
||||||
cdpath=vlook("cdpath")->val;
|
cdpath = vlook("cdpath")->val;
|
||||||
switch(count(a)){
|
switch(count(a)){
|
||||||
default:
|
default:
|
||||||
pfmt(err, "Usage: cd [directory]\n");
|
pfmt(err, "Usage: cd [directory]\n");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if(a->next->word[0]=='/' || cdpath==0) cdpath=&nullpath;
|
if(a->next->word[0]=='/' || cdpath==0)
|
||||||
for(;cdpath;cdpath=cdpath->next){
|
cdpath=&nullpath;
|
||||||
|
for(;cdpath;cdpath = cdpath->next){
|
||||||
strcpy(dir, cdpath->word);
|
strcpy(dir, cdpath->word);
|
||||||
if(dir[0]) strcat(dir, "/");
|
if(dir[0])
|
||||||
|
strcat(dir, "/");
|
||||||
strcat(dir, a->next->word);
|
strcat(dir, a->next->word);
|
||||||
if(dochdir(dir)>=0){
|
if(dochdir(dir)>=0){
|
||||||
if(strlen(cdpath->word)
|
if(strlen(cdpath->word)
|
||||||
@ -165,10 +179,11 @@ void execcd(void){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(cdpath==0) pfmt(err, "Can't cd %s: %r\n", a->next->word);
|
if(cdpath==0)
|
||||||
|
pfmt(err, "Can't cd %s: %r\n", a->next->word);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
a=vlook("HOME")->val;
|
a = vlook("home")->val;
|
||||||
if(count(a)>=1){
|
if(count(a)>=1){
|
||||||
if(dochdir(a->word)>=0)
|
if(dochdir(a->word)>=0)
|
||||||
setstatus("");
|
setstatus("");
|
||||||
@ -181,14 +196,22 @@ void execcd(void){
|
|||||||
}
|
}
|
||||||
poplist();
|
poplist();
|
||||||
}
|
}
|
||||||
void execexit(void){
|
|
||||||
|
void
|
||||||
|
execexit(void)
|
||||||
|
{
|
||||||
switch(count(runq->argv->words)){
|
switch(count(runq->argv->words)){
|
||||||
default: pfmt(err, "Usage: exit [status]\nExiting anyway\n");
|
default:
|
||||||
case 2: setstatus(runq->argv->words->next->word);
|
pfmt(err, "Usage: exit [status]\nExiting anyway\n");
|
||||||
|
case 2:
|
||||||
|
setstatus(runq->argv->words->next->word);
|
||||||
case 1: Xexit();
|
case 1: Xexit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void execshift(void){
|
|
||||||
|
void
|
||||||
|
execshift(void)
|
||||||
|
{
|
||||||
int n;
|
int n;
|
||||||
word *a;
|
word *a;
|
||||||
var *star;
|
var *star;
|
||||||
@ -198,72 +221,87 @@ void execshift(void){
|
|||||||
setstatus("shift usage");
|
setstatus("shift usage");
|
||||||
poplist();
|
poplist();
|
||||||
return;
|
return;
|
||||||
case 2: n=atoi(runq->argv->words->next->word); break;
|
case 2:
|
||||||
case 1: n=1; break;
|
n = atoi(runq->argv->words->next->word);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
n = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
star=vlook("*");
|
star = vlook("*");
|
||||||
for(;n && star->val;--n){
|
for(;n && star->val;--n){
|
||||||
a=star->val->next;
|
a = star->val->next;
|
||||||
efree(star->val->word);
|
efree(star->val->word);
|
||||||
efree((char *)star->val);
|
efree((char *)star->val);
|
||||||
star->val=a;
|
star->val = a;
|
||||||
star->changed=1;
|
star->changed = 1;
|
||||||
}
|
}
|
||||||
setstatus("");
|
setstatus("");
|
||||||
poplist();
|
poplist();
|
||||||
}
|
}
|
||||||
int octal(char *s)
|
|
||||||
|
int
|
||||||
|
octal(char *s)
|
||||||
{
|
{
|
||||||
int n=0;
|
int n = 0;
|
||||||
while(*s==' ' || *s=='\t' || *s=='\n') s++;
|
while(*s==' ' || *s=='\t' || *s=='\n') s++;
|
||||||
while('0'<=*s && *s<='7') n=n*8+*s++-'0';
|
while('0'<=*s && *s<='7') n = n*8+*s++-'0';
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
int mapfd(int fd)
|
|
||||||
|
int
|
||||||
|
mapfd(int fd)
|
||||||
{
|
{
|
||||||
redir *rp;
|
redir *rp;
|
||||||
for(rp=runq->redir;rp;rp=rp->next){
|
for(rp = runq->redir;rp;rp = rp->next){
|
||||||
switch(rp->type){
|
switch(rp->type){
|
||||||
case RCLOSE:
|
case RCLOSE:
|
||||||
if(rp->from==fd) fd=-1;
|
if(rp->from==fd)
|
||||||
|
fd=-1;
|
||||||
break;
|
break;
|
||||||
case RDUP:
|
case RDUP:
|
||||||
case ROPEN:
|
case ROPEN:
|
||||||
if(rp->to==fd) fd=rp->from;
|
if(rp->to==fd)
|
||||||
|
fd = rp->from;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
union code rdcmds[4];
|
union code rdcmds[4];
|
||||||
void execcmds(io *f)
|
|
||||||
|
void
|
||||||
|
execcmds(io *f)
|
||||||
{
|
{
|
||||||
static int first=1;
|
static int first = 1;
|
||||||
if(first){
|
if(first){
|
||||||
rdcmds[0].i=1;
|
rdcmds[0].i = 1;
|
||||||
rdcmds[1].f=Xrdcmds;
|
rdcmds[1].f = Xrdcmds;
|
||||||
rdcmds[2].f=Xreturn;
|
rdcmds[2].f = Xreturn;
|
||||||
first=0;
|
first = 0;
|
||||||
}
|
}
|
||||||
start(rdcmds, 1, runq->local);
|
start(rdcmds, 1, runq->local);
|
||||||
runq->cmdfd=f;
|
runq->cmdfd = f;
|
||||||
runq->iflast=0;
|
runq->iflast = 0;
|
||||||
}
|
}
|
||||||
void execeval(void){
|
|
||||||
|
void
|
||||||
|
execeval(void)
|
||||||
|
{
|
||||||
char *cmdline, *s, *t;
|
char *cmdline, *s, *t;
|
||||||
int len=0;
|
int len = 0;
|
||||||
word *ap;
|
word *ap;
|
||||||
if(count(runq->argv->words)<=1){
|
if(count(runq->argv->words)<=1){
|
||||||
Xerror1("Usage: eval cmd ...");
|
Xerror1("Usage: eval cmd ...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eflagok=1;
|
eflagok = 1;
|
||||||
for(ap=runq->argv->words->next;ap;ap=ap->next)
|
for(ap = runq->argv->words->next;ap;ap = ap->next)
|
||||||
len+=1+strlen(ap->word);
|
len+=1+strlen(ap->word);
|
||||||
cmdline=emalloc(len);
|
cmdline = emalloc(len);
|
||||||
s=cmdline;
|
s = cmdline;
|
||||||
for(ap=runq->argv->words->next;ap;ap=ap->next){
|
for(ap = runq->argv->words->next;ap;ap = ap->next){
|
||||||
for(t=ap->word;*t;) *s++=*t++;
|
for(t = ap->word;*t;) *s++=*t++;
|
||||||
*s++=' ';
|
*s++=' ';
|
||||||
}
|
}
|
||||||
s[-1]='\n';
|
s[-1]='\n';
|
||||||
@ -272,36 +310,39 @@ void execeval(void){
|
|||||||
efree(cmdline);
|
efree(cmdline);
|
||||||
}
|
}
|
||||||
union code dotcmds[14];
|
union code dotcmds[14];
|
||||||
void execdot(void){
|
|
||||||
int iflag=0;
|
void
|
||||||
|
execdot(void)
|
||||||
|
{
|
||||||
|
int iflag = 0;
|
||||||
int fd;
|
int fd;
|
||||||
list *av;
|
list *av;
|
||||||
thread *p=runq;
|
thread *p = runq;
|
||||||
char *zero;
|
char *zero;
|
||||||
static int first=1;
|
static int first = 1;
|
||||||
char file[512];
|
char file[512];
|
||||||
word *path;
|
word *path;
|
||||||
if(first){
|
if(first){
|
||||||
dotcmds[0].i=1;
|
dotcmds[0].i = 1;
|
||||||
dotcmds[1].f=Xmark;
|
dotcmds[1].f = Xmark;
|
||||||
dotcmds[2].f=Xword;
|
dotcmds[2].f = Xword;
|
||||||
dotcmds[3].s="0";
|
dotcmds[3].s="0";
|
||||||
dotcmds[4].f=Xlocal;
|
dotcmds[4].f = Xlocal;
|
||||||
dotcmds[5].f=Xmark;
|
dotcmds[5].f = Xmark;
|
||||||
dotcmds[6].f=Xword;
|
dotcmds[6].f = Xword;
|
||||||
dotcmds[7].s="*";
|
dotcmds[7].s="*";
|
||||||
dotcmds[8].f=Xlocal;
|
dotcmds[8].f = Xlocal;
|
||||||
dotcmds[9].f=Xrdcmds;
|
dotcmds[9].f = Xrdcmds;
|
||||||
dotcmds[10].f=Xunlocal;
|
dotcmds[10].f = Xunlocal;
|
||||||
dotcmds[11].f=Xunlocal;
|
dotcmds[11].f = Xunlocal;
|
||||||
dotcmds[12].f=Xreturn;
|
dotcmds[12].f = Xreturn;
|
||||||
first=0;
|
first = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
eflagok=1;
|
eflagok = 1;
|
||||||
popword();
|
popword();
|
||||||
if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
|
if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
|
||||||
iflag=1;
|
iflag = 1;
|
||||||
popword();
|
popword();
|
||||||
}
|
}
|
||||||
/* get input file */
|
/* get input file */
|
||||||
@ -309,18 +350,20 @@ void execdot(void){
|
|||||||
Xerror1("Usage: . [-i] file [arg ...]");
|
Xerror1("Usage: . [-i] file [arg ...]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
zero=strdup(p->argv->words->word);
|
zero = strdup(p->argv->words->word);
|
||||||
popword();
|
popword();
|
||||||
fd=-1;
|
fd=-1;
|
||||||
for(path=searchpath(zero);path;path=path->next){
|
for(path = searchpath(zero);path;path = path->next){
|
||||||
strcpy(file, path->word);
|
strcpy(file, path->word);
|
||||||
if(file[0]) strcat(file, "/");
|
if(file[0])
|
||||||
|
strcat(file, "/");
|
||||||
strcat(file, zero);
|
strcat(file, zero);
|
||||||
|
if((fd = open(file, 0))>=0) break;
|
||||||
if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */
|
if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */
|
||||||
fd=Dup1(0);
|
fd = Dup1(0);
|
||||||
if(fd>=0) break;
|
if(fd>=0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if((fd=open(file, 0))>=0) break;
|
|
||||||
}
|
}
|
||||||
if(fd<0){
|
if(fd<0){
|
||||||
pfmt(err, "%s: ", zero);
|
pfmt(err, "%s: ", zero);
|
||||||
@ -331,38 +374,41 @@ void execdot(void){
|
|||||||
/* set up for a new command loop */
|
/* set up for a new command loop */
|
||||||
start(dotcmds, 1, (struct var *)0);
|
start(dotcmds, 1, (struct var *)0);
|
||||||
pushredir(RCLOSE, fd, 0);
|
pushredir(RCLOSE, fd, 0);
|
||||||
runq->cmdfile=zero;
|
runq->cmdfile = zero;
|
||||||
runq->cmdfd=openfd(fd);
|
runq->cmdfd = openfd(fd);
|
||||||
runq->iflag=iflag;
|
runq->iflag = iflag;
|
||||||
runq->iflast=0;
|
runq->iflast = 0;
|
||||||
/* push $* value */
|
/* push $* value */
|
||||||
pushlist();
|
pushlist();
|
||||||
runq->argv->words=p->argv->words;
|
runq->argv->words = p->argv->words;
|
||||||
/* free caller's copy of $* */
|
/* free caller's copy of $* */
|
||||||
av=p->argv;
|
av = p->argv;
|
||||||
p->argv=av->next;
|
p->argv = av->next;
|
||||||
efree((char *)av);
|
efree((char *)av);
|
||||||
/* push $0 value */
|
/* push $0 value */
|
||||||
pushlist();
|
pushlist();
|
||||||
pushword(zero);
|
pushword(zero);
|
||||||
ndot++;
|
ndot++;
|
||||||
}
|
}
|
||||||
void execflag(void){
|
|
||||||
|
void
|
||||||
|
execflag(void)
|
||||||
|
{
|
||||||
char *letter, *val;
|
char *letter, *val;
|
||||||
switch(count(runq->argv->words)){
|
switch(count(runq->argv->words)){
|
||||||
case 2:
|
case 2:
|
||||||
setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set");
|
setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set");
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
letter=runq->argv->words->next->word;
|
letter = runq->argv->words->next->word;
|
||||||
val=runq->argv->words->next->next->word;
|
val = runq->argv->words->next->next->word;
|
||||||
if(strlen(letter)==1){
|
if(strlen(letter)==1){
|
||||||
if(strcmp(val, "+")==0){
|
if(strcmp(val, "+")==0){
|
||||||
flag[(uchar)letter[0]]=flagset;
|
flag[(uchar)letter[0]] = flagset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(strcmp(val, "-")==0){
|
if(strcmp(val, "-")==0){
|
||||||
flag[(uchar)letter[0]]=0;
|
flag[(uchar)letter[0]] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,53 +418,57 @@ void execflag(void){
|
|||||||
}
|
}
|
||||||
poplist();
|
poplist();
|
||||||
}
|
}
|
||||||
void execwhatis(void){ /* mildly wrong -- should fork before writing */
|
|
||||||
|
void
|
||||||
|
execwhatis(void){ /* mildly wrong -- should fork before writing */
|
||||||
word *a, *b, *path;
|
word *a, *b, *path;
|
||||||
var *v;
|
var *v;
|
||||||
struct builtin *bp;
|
struct builtin *bp;
|
||||||
char file[512];
|
char file[512];
|
||||||
struct io out[1];
|
struct io out[1];
|
||||||
int found, sep;
|
int found, sep;
|
||||||
a=runq->argv->words->next;
|
a = runq->argv->words->next;
|
||||||
if(a==0){
|
if(a==0){
|
||||||
Xerror1("Usage: whatis name ...");
|
Xerror1("Usage: whatis name ...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setstatus("");
|
setstatus("");
|
||||||
out->fd=mapfd(1);
|
out->fd = mapfd(1);
|
||||||
out->bufp=out->buf;
|
out->bufp = out->buf;
|
||||||
out->ebuf=&out->buf[NBUF];
|
out->ebuf = &out->buf[NBUF];
|
||||||
out->strp=0;
|
out->strp = 0;
|
||||||
for(;a;a=a->next){
|
for(;a;a = a->next){
|
||||||
v=vlook(a->word);
|
v = vlook(a->word);
|
||||||
if(v->val){
|
if(v->val){
|
||||||
pfmt(out, "%s=", a->word);
|
pfmt(out, "%s=", a->word);
|
||||||
if(v->val->next==0)
|
if(v->val->next==0)
|
||||||
pfmt(out, "%q\n", v->val->word);
|
pfmt(out, "%q\n", v->val->word);
|
||||||
else{
|
else{
|
||||||
sep='(';
|
sep='(';
|
||||||
for(b=v->val;b && b->word;b=b->next){
|
for(b = v->val;b && b->word;b = b->next){
|
||||||
pfmt(out, "%c%q", sep, b->word);
|
pfmt(out, "%c%q", sep, b->word);
|
||||||
sep=' ';
|
sep=' ';
|
||||||
}
|
}
|
||||||
pfmt(out, ")\n");
|
pfmt(out, ")\n");
|
||||||
}
|
}
|
||||||
found=1;
|
found = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
found=0;
|
found = 0;
|
||||||
v=gvlook(a->word);
|
v = gvlook(a->word);
|
||||||
if(v->fn) pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
|
if(v->fn)
|
||||||
|
pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
|
||||||
else{
|
else{
|
||||||
for(bp=Builtin;bp->name;bp++)
|
for(bp = Builtin;bp->name;bp++)
|
||||||
if(strcmp(a->word, bp->name)==0){
|
if(strcmp(a->word, bp->name)==0){
|
||||||
pfmt(out, "builtin %s\n", a->word);
|
pfmt(out, "builtin %s\n", a->word);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!bp->name){
|
if(!bp->name){
|
||||||
for(path=searchpath(a->word);path;path=path->next){
|
for(path = searchpath(a->word);path;path = path->next){
|
||||||
strcpy(file, path->word);
|
strcpy(file, path->word);
|
||||||
if(file[0]) strcat(file, "/");
|
if(file[0])
|
||||||
|
strcat(file, "/");
|
||||||
strcat(file, a->word);
|
strcat(file, a->word);
|
||||||
if(Executable(file)){
|
if(Executable(file)){
|
||||||
pfmt(out, "%s\n", file);
|
pfmt(out, "%s\n", file);
|
||||||
@ -435,11 +485,20 @@ void execwhatis(void){ /* mildly wrong -- should fork before writing */
|
|||||||
poplist();
|
poplist();
|
||||||
flush(err);
|
flush(err);
|
||||||
}
|
}
|
||||||
void execwait(void){
|
|
||||||
|
void
|
||||||
|
execwait(void)
|
||||||
|
{
|
||||||
switch(count(runq->argv->words)){
|
switch(count(runq->argv->words)){
|
||||||
default: Xerror1("Usage: wait [pid]"); return;
|
default:
|
||||||
case 2: Waitfor(atoi(runq->argv->words->next->word), 0); break;
|
Xerror1("Usage: wait [pid]");
|
||||||
case 1: Waitfor(-1, 0); break;
|
return;
|
||||||
|
case 2:
|
||||||
|
Waitfor(atoi(runq->argv->words->next->word), 0);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Waitfor(-1, 0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
poplist();
|
poplist();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,20 +2,29 @@
|
|||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
char *emalloc(long n){
|
|
||||||
char *p=(char *)Malloc(n);
|
char*
|
||||||
if(p==0) panic("Can't malloc %d bytes", n);
|
emalloc(long n)
|
||||||
/* if(err){ pfmt(err, "malloc %d->%p\n", n, p); flush(err); } */
|
{
|
||||||
|
char *p = (char *)Malloc(n);
|
||||||
|
if(p==0)
|
||||||
|
panic("Can't malloc %d bytes", n);
|
||||||
|
/* if(err){ pfmt(err, "malloc %d->%p\n", n, p); flush(err); } /**/
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
void efree(char *p)
|
|
||||||
|
void
|
||||||
|
efree(char *p)
|
||||||
{
|
{
|
||||||
/* pfmt(err, "free %p\n", p); flush(err); */
|
/* pfmt(err, "free %p\n", p); flush(err); /**/
|
||||||
if(p) free(p);
|
if(p)
|
||||||
|
free(p);
|
||||||
else pfmt(err, "free 0\n");
|
else pfmt(err, "free 0\n");
|
||||||
}
|
}
|
||||||
extern int lastword, lastdol;
|
extern int lastword, lastdol;
|
||||||
void yyerror(char *m)
|
|
||||||
|
void
|
||||||
|
yyerror(char *m)
|
||||||
{
|
{
|
||||||
pfmt(err, "rc: ");
|
pfmt(err, "rc: ");
|
||||||
if(runq->cmdfile && !runq->iflag)
|
if(runq->cmdfile && !runq->iflag)
|
||||||
@ -24,17 +33,21 @@ void yyerror(char *m)
|
|||||||
pfmt(err, "%s: ", runq->cmdfile);
|
pfmt(err, "%s: ", runq->cmdfile);
|
||||||
else if(!runq->iflag)
|
else if(!runq->iflag)
|
||||||
pfmt(err, "line %d: ", runq->lineno);
|
pfmt(err, "line %d: ", runq->lineno);
|
||||||
if(tok[0] && tok[0]!='\n') pfmt(err, "token %q: ", tok);
|
if(tok[0] && tok[0]!='\n')
|
||||||
|
pfmt(err, "token %q: ", tok);
|
||||||
pfmt(err, "%s\n", m);
|
pfmt(err, "%s\n", m);
|
||||||
flush(err);
|
flush(err);
|
||||||
lastword=0;
|
lastword = 0;
|
||||||
lastdol=0;
|
lastdol = 0;
|
||||||
while(lastc!='\n' && lastc!=EOF) advance();
|
while(lastc!='\n' && lastc!=EOF) advance();
|
||||||
nerror++;
|
nerror++;
|
||||||
setvar("status", newword(m, (word *)0));
|
setvar("status", newword(m, (word *)0));
|
||||||
}
|
}
|
||||||
char *bp;
|
char *bp;
|
||||||
void iacvt(int n){
|
|
||||||
|
static void
|
||||||
|
iacvt(int n)
|
||||||
|
{
|
||||||
if(n<0){
|
if(n<0){
|
||||||
*bp++='-';
|
*bp++='-';
|
||||||
n=-n; /* doesn't work for n==-inf */
|
n=-n; /* doesn't work for n==-inf */
|
||||||
@ -43,13 +56,17 @@ void iacvt(int n){
|
|||||||
iacvt(n/10);
|
iacvt(n/10);
|
||||||
*bp++=n%10+'0';
|
*bp++=n%10+'0';
|
||||||
}
|
}
|
||||||
void itoa(char *s, long n)
|
|
||||||
|
void
|
||||||
|
inttoascii(char *s, long n)
|
||||||
{
|
{
|
||||||
bp=s;
|
bp = s;
|
||||||
iacvt(n);
|
iacvt(n);
|
||||||
*bp='\0';
|
*bp='\0';
|
||||||
}
|
}
|
||||||
void panic(char *s, int n)
|
|
||||||
|
void
|
||||||
|
panic(char *s, int n)
|
||||||
{
|
{
|
||||||
pfmt(err, "rc: ");
|
pfmt(err, "rc: ");
|
||||||
pfmt(err, s, n);
|
pfmt(err, s, n);
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
%term WORD REDIR DUP PIPE SUB
|
%term WORD REDIR DUP PIPE SUB
|
||||||
%term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */
|
%term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */
|
||||||
/* operator priorities -- lowest first */
|
/* operator priorities -- lowest first */
|
||||||
%left LOW
|
|
||||||
%left IF WHILE FOR SWITCH ')' NOT
|
%left IF WHILE FOR SWITCH ')' NOT
|
||||||
%left ANDAND OROR
|
%left ANDAND OROR
|
||||||
%left BANG SUBSHELL
|
%left BANG SUBSHELL
|
||||||
@ -10,7 +9,6 @@
|
|||||||
%left '^'
|
%left '^'
|
||||||
%right '$' COUNT '"'
|
%right '$' COUNT '"'
|
||||||
%left SUB
|
%left SUB
|
||||||
%left '='
|
|
||||||
%{
|
%{
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
@ -80,7 +78,6 @@ first: comword
|
|||||||
word: keyword {lastword=1; $1->type=WORD;}
|
word: keyword {lastword=1; $1->type=WORD;}
|
||||||
| comword
|
| comword
|
||||||
| word '^' word {$$=tree2('^', $1, $3);}
|
| word '^' word {$$=tree2('^', $1, $3);}
|
||||||
| word '=' word %prec LOW {$$=tree2('^', tree2('^', $1, token("=", WORD)), $3);}
|
|
||||||
comword: '$' word {$$=tree1('$', $2);}
|
comword: '$' word {$$=tree1('$', $2);}
|
||||||
| '$' word SUB words ')' {$$=tree2(SUB, $2, $4);}
|
| '$' word SUB words ')' {$$=tree2(SUB, $2, $4);}
|
||||||
| '"' word {$$=tree1('"', $2);}
|
| '"' word {$$=tree1('"', $2);}
|
||||||
|
|||||||
@ -3,22 +3,25 @@
|
|||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
extern char *Signame[];
|
extern char *Signame[];
|
||||||
void dotrap(void){
|
|
||||||
register int i;
|
void
|
||||||
register struct var *trapreq;
|
dotrap(void)
|
||||||
register struct word *starval;
|
{
|
||||||
starval=vlook("*")->val;
|
int i;
|
||||||
while(ntrap) for(i=0;i!=NSIG;i++) while(trap[i]){
|
struct var *trapreq;
|
||||||
|
struct word *starval;
|
||||||
|
starval = vlook("*")->val;
|
||||||
|
while(ntrap) for(i = 0;i!=NSIG;i++) while(trap[i]){
|
||||||
--trap[i];
|
--trap[i];
|
||||||
--ntrap;
|
--ntrap;
|
||||||
if(getpid()!=mypid) Exit(getstatus());
|
if(getpid()!=mypid) Exit(getstatus());
|
||||||
trapreq=vlook(Signame[i]);
|
trapreq = vlook(Signame[i]);
|
||||||
if(trapreq->fn){
|
if(trapreq->fn){
|
||||||
start(trapreq->fn, trapreq->pc, (struct var *)0);
|
start(trapreq->fn, trapreq->pc, (struct var *)0);
|
||||||
runq->local=newvar(strdup("*"), runq->local);
|
runq->local = newvar(strdup("*"), runq->local);
|
||||||
runq->local->val=copywords(starval, (struct word *)0);
|
runq->local->val = copywords(starval, (struct word *)0);
|
||||||
runq->local->changed=1;
|
runq->local->changed = 1;
|
||||||
runq->redir=runq->startredir=0;
|
runq->redir = runq->startredir = 0;
|
||||||
}
|
}
|
||||||
else if(i==SIGINT || i==SIGQUIT){
|
else if(i==SIGINT || i==SIGQUIT){
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -7,108 +7,140 @@ tree *treenodes;
|
|||||||
* create and clear a new tree node, and add it
|
* create and clear a new tree node, and add it
|
||||||
* to the node list.
|
* to the node list.
|
||||||
*/
|
*/
|
||||||
tree *newtree(void){
|
|
||||||
tree *t=new(tree);
|
tree*
|
||||||
t->iskw=0;
|
newtree(void)
|
||||||
t->str=0;
|
{
|
||||||
t->child[0]=t->child[1]=t->child[2]=0;
|
tree *t = new(tree);
|
||||||
t->next=treenodes;
|
t->iskw = 0;
|
||||||
treenodes=t;
|
t->str = 0;
|
||||||
|
t->child[0] = t->child[1] = t->child[2] = 0;
|
||||||
|
t->next = treenodes;
|
||||||
|
treenodes = t;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
void freenodes(void){
|
|
||||||
|
void
|
||||||
|
freenodes(void)
|
||||||
|
{
|
||||||
tree *t, *u;
|
tree *t, *u;
|
||||||
for(t=treenodes;t;t=u){
|
for(t = treenodes;t;t = u){
|
||||||
u=t->next;
|
u = t->next;
|
||||||
if(t->str) efree(t->str);
|
if(t->str)
|
||||||
|
efree(t->str);
|
||||||
efree((char *)t);
|
efree((char *)t);
|
||||||
}
|
}
|
||||||
treenodes=0;
|
treenodes = 0;
|
||||||
}
|
}
|
||||||
tree *tree1(int type, tree *c0)
|
|
||||||
|
tree*
|
||||||
|
tree1(int type, tree *c0)
|
||||||
{
|
{
|
||||||
return tree3(type, c0, (tree *)0, (tree *)0);
|
return tree3(type, c0, (tree *)0, (tree *)0);
|
||||||
}
|
}
|
||||||
tree *tree2(int type, tree *c0, tree *c1)
|
|
||||||
|
tree*
|
||||||
|
tree2(int type, tree *c0, tree *c1)
|
||||||
{
|
{
|
||||||
return tree3(type, c0, c1, (tree *)0);
|
return tree3(type, c0, c1, (tree *)0);
|
||||||
}
|
}
|
||||||
tree *tree3(int type, tree *c0, tree *c1, tree *c2)
|
|
||||||
|
tree*
|
||||||
|
tree3(int type, tree *c0, tree *c1, tree *c2)
|
||||||
{
|
{
|
||||||
tree *t;
|
tree *t;
|
||||||
if(type==';'){
|
if(type==';'){
|
||||||
if(c0==0) return c1;
|
if(c0==0)
|
||||||
if(c1==0) return c0;
|
return c1;
|
||||||
|
if(c1==0)
|
||||||
|
return c0;
|
||||||
}
|
}
|
||||||
t=newtree();
|
t = newtree();
|
||||||
t->type=type;
|
t->type = type;
|
||||||
t->child[0]=c0;
|
t->child[0] = c0;
|
||||||
t->child[1]=c1;
|
t->child[1] = c1;
|
||||||
t->child[2]=c2;
|
t->child[2] = c2;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
tree *mung1(tree *t, tree *c0)
|
|
||||||
|
tree*
|
||||||
|
mung1(tree *t, tree *c0)
|
||||||
{
|
{
|
||||||
t->child[0]=c0;
|
t->child[0] = c0;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
tree *mung2(tree *t, tree *c0, tree *c1)
|
|
||||||
|
tree*
|
||||||
|
mung2(tree *t, tree *c0, tree *c1)
|
||||||
{
|
{
|
||||||
t->child[0]=c0;
|
t->child[0] = c0;
|
||||||
t->child[1]=c1;
|
t->child[1] = c1;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
tree *mung3(tree *t, tree *c0, tree *c1, tree *c2)
|
|
||||||
|
tree*
|
||||||
|
mung3(tree *t, tree *c0, tree *c1, tree *c2)
|
||||||
{
|
{
|
||||||
t->child[0]=c0;
|
t->child[0] = c0;
|
||||||
t->child[1]=c1;
|
t->child[1] = c1;
|
||||||
t->child[2]=c2;
|
t->child[2] = c2;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
tree *epimung(tree *comp, tree *epi)
|
|
||||||
|
tree*
|
||||||
|
epimung(tree *comp, tree *epi)
|
||||||
{
|
{
|
||||||
tree *p;
|
tree *p;
|
||||||
if(epi==0) return comp;
|
if(epi==0)
|
||||||
for(p=epi;p->child[1];p=p->child[1]);
|
return comp;
|
||||||
p->child[1]=comp;
|
for(p = epi;p->child[1];p = p->child[1]);
|
||||||
|
p->child[1] = comp;
|
||||||
return epi;
|
return epi;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Add a SIMPLE node at the root of t and percolate all the redirections
|
* Add a SIMPLE node at the root of t and percolate all the redirections
|
||||||
* up to the root.
|
* up to the root.
|
||||||
*/
|
*/
|
||||||
tree *simplemung(tree *t)
|
|
||||||
|
tree*
|
||||||
|
simplemung(tree *t)
|
||||||
{
|
{
|
||||||
tree *u;
|
tree *u;
|
||||||
struct io *s;
|
struct io *s;
|
||||||
t=tree1(SIMPLE, t);
|
t = tree1(SIMPLE, t);
|
||||||
s=openstr();
|
s = openstr();
|
||||||
pfmt(s, "%t", t);
|
pfmt(s, "%t", t);
|
||||||
t->str=strdup(s->strp);
|
t->str = strdup(s->strp);
|
||||||
closeio(s);
|
closeio(s);
|
||||||
for(u=t->child[0];u->type==ARGLIST;u=u->child[0]){
|
for(u = t->child[0];u->type==ARGLIST;u = u->child[0]){
|
||||||
if(u->child[1]->type==DUP
|
if(u->child[1]->type==DUP
|
||||||
|| u->child[1]->type==REDIR){
|
|| u->child[1]->type==REDIR){
|
||||||
u->child[1]->child[1]=t;
|
u->child[1]->child[1] = t;
|
||||||
t=u->child[1];
|
t = u->child[1];
|
||||||
u->child[1]=0;
|
u->child[1] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
tree *token(char *str, int type)
|
|
||||||
|
tree*
|
||||||
|
token(char *str, int type)
|
||||||
{
|
{
|
||||||
tree *t=newtree();
|
tree *t = newtree();
|
||||||
t->type=type;
|
t->type = type;
|
||||||
t->str=strdup(str);
|
t->str = strdup(str);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
void freetree(tree *p)
|
|
||||||
|
void
|
||||||
|
freetree(tree *p)
|
||||||
{
|
{
|
||||||
if(p==0) return;
|
if(p==0)
|
||||||
|
return;
|
||||||
freetree(p->child[0]);
|
freetree(p->child[0]);
|
||||||
freetree(p->child[1]);
|
freetree(p->child[1]);
|
||||||
freetree(p->child[2]);
|
freetree(p->child[2]);
|
||||||
if(p->str) efree(p->str);
|
if(p->str)
|
||||||
|
efree(p->str);
|
||||||
efree((char *)p);
|
efree((char *)p);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
int hash(char *s, int n)
|
|
||||||
|
int
|
||||||
|
hash(char *s, int n)
|
||||||
{
|
{
|
||||||
register int h=0, i=1;
|
int h = 0, i = 1;
|
||||||
while(*s) h+=*s++*i++;
|
while(*s) h+=*s++*i++;
|
||||||
h%=n;
|
h%=n;
|
||||||
return h<0?h+n:h;
|
return h<0?h+n:h;
|
||||||
@ -14,16 +16,21 @@ struct kw{
|
|||||||
int type;
|
int type;
|
||||||
struct kw *next;
|
struct kw *next;
|
||||||
}*kw[NKW];
|
}*kw[NKW];
|
||||||
void kenter(int type, char *name)
|
|
||||||
|
void
|
||||||
|
kenter(int type, char *name)
|
||||||
{
|
{
|
||||||
register int h=hash(name, NKW);
|
int h = hash(name, NKW);
|
||||||
register struct kw *p=new(struct kw);
|
struct kw *p = new(struct kw);
|
||||||
p->type=type;
|
p->type = type;
|
||||||
p->name=name;
|
p->name = name;
|
||||||
p->next=kw[h];
|
p->next = kw[h];
|
||||||
kw[h]=p;
|
kw[h] = p;
|
||||||
}
|
}
|
||||||
void kinit(void){
|
|
||||||
|
void
|
||||||
|
kinit(void)
|
||||||
|
{
|
||||||
kenter(FOR, "for");
|
kenter(FOR, "for");
|
||||||
kenter(IN, "in");
|
kenter(IN, "in");
|
||||||
kenter(WHILE, "while");
|
kenter(WHILE, "while");
|
||||||
@ -35,47 +42,59 @@ void kinit(void){
|
|||||||
kenter(SWITCH, "switch");
|
kenter(SWITCH, "switch");
|
||||||
kenter(FN, "fn");
|
kenter(FN, "fn");
|
||||||
}
|
}
|
||||||
tree *klook(char *name)
|
|
||||||
|
tree*
|
||||||
|
klook(char *name)
|
||||||
{
|
{
|
||||||
struct kw *p;
|
struct kw *p;
|
||||||
tree *t=token(name, WORD);
|
tree *t = token(name, WORD);
|
||||||
for(p=kw[hash(name, NKW)];p;p=p->next)
|
for(p = kw[hash(name, NKW)];p;p = p->next)
|
||||||
if(strcmp(p->name, name)==0){
|
if(strcmp(p->name, name)==0){
|
||||||
t->type=p->type;
|
t->type = p->type;
|
||||||
t->iskw=1;
|
t->iskw = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
var *gvlook(char *name)
|
|
||||||
|
var*
|
||||||
|
gvlook(char *name)
|
||||||
{
|
{
|
||||||
int h=hash(name, NVAR);
|
int h = hash(name, NVAR);
|
||||||
var *v;
|
var *v;
|
||||||
for(v=gvar[h];v;v=v->next) if(strcmp(v->name, name)==0) return v;
|
for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v;
|
||||||
return gvar[h]=newvar(strdup(name), gvar[h]);
|
return gvar[h] = newvar(strdup(name), gvar[h]);
|
||||||
}
|
}
|
||||||
var *vlook(char *name)
|
|
||||||
|
var*
|
||||||
|
vlook(char *name)
|
||||||
{
|
{
|
||||||
var *v;
|
var *v;
|
||||||
if(runq)
|
if(runq)
|
||||||
for(v=runq->local;v;v=v->next)
|
for(v = runq->local;v;v = v->next)
|
||||||
if(strcmp(v->name, name)==0) return v;
|
if(strcmp(v->name, name)==0) return v;
|
||||||
return gvlook(name);
|
return gvlook(name);
|
||||||
}
|
}
|
||||||
void _setvar(char *name, word *val, int callfn)
|
|
||||||
|
void
|
||||||
|
_setvar(char *name, word *val, int callfn)
|
||||||
{
|
{
|
||||||
register struct var *v=vlook(name);
|
struct var *v = vlook(name);
|
||||||
freewords(v->val);
|
freewords(v->val);
|
||||||
v->val=val;
|
v->val=val;
|
||||||
v->changed=1;
|
v->changed=1;
|
||||||
if(callfn && v->changefn)
|
if(callfn && v->changefn)
|
||||||
v->changefn(v);
|
v->changefn(v);
|
||||||
}
|
}
|
||||||
void setvar(char *name, word *val)
|
|
||||||
|
void
|
||||||
|
setvar(char *name, word *val)
|
||||||
{
|
{
|
||||||
_setvar(name, val, 1);
|
_setvar(name, val, 1);
|
||||||
}
|
}
|
||||||
void bigpath(var *v)
|
|
||||||
|
void
|
||||||
|
bigpath(var *v)
|
||||||
{
|
{
|
||||||
/* convert $PATH to $path */
|
/* convert $PATH to $path */
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
@ -107,19 +126,42 @@ void bigpath(var *v)
|
|||||||
}
|
}
|
||||||
_setvar("path", w, 0);
|
_setvar("path", w, 0);
|
||||||
}
|
}
|
||||||
void littlepath(var *v)
|
|
||||||
|
char*
|
||||||
|
list2strcolon(word *words)
|
||||||
|
{
|
||||||
|
char *value, *s, *t;
|
||||||
|
int len = 0;
|
||||||
|
word *ap;
|
||||||
|
for(ap = words;ap;ap = ap->next)
|
||||||
|
len+=1+strlen(ap->word);
|
||||||
|
value = emalloc(len+1);
|
||||||
|
s = value;
|
||||||
|
for(ap = words;ap;ap = ap->next){
|
||||||
|
for(t = ap->word;*t;) *s++=*t++;
|
||||||
|
*s++=':';
|
||||||
|
}
|
||||||
|
if(s==value)
|
||||||
|
*s='\0';
|
||||||
|
else s[-1]='\0';
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
littlepath(var *v)
|
||||||
{
|
{
|
||||||
/* convert $path to $PATH */
|
/* convert $path to $PATH */
|
||||||
char *p;
|
char *p;
|
||||||
word *w;
|
word *w;
|
||||||
|
|
||||||
p = _list2str(v->val, ':');
|
p = list2strcolon(v->val);
|
||||||
w = new(word);
|
w = new(word);
|
||||||
w->word = p;
|
w->word = p;
|
||||||
w->next = nil;
|
w->next = nil;
|
||||||
_setvar("PATH", w, 1); /* 1: recompute $path to expose colon problems */
|
_setvar("PATH", w, 1); /* 1: recompute $path to expose colon problems */
|
||||||
}
|
}
|
||||||
void pathinit(void)
|
|
||||||
|
void
|
||||||
|
pathinit(void)
|
||||||
{
|
{
|
||||||
var *v;
|
var *v;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user