diff options
author | rsc <devnull@localhost> | 2003-11-23 18:04:08 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2003-11-23 18:04:08 +0000 |
commit | f08fdedcee12c06e3ce9ac9bec363915978e8289 (patch) | |
tree | d67a27473be1e8f98d3694028104d9ddf915345b /src/cmd/rc/here.c | |
parent | 5993a8f2756bc455101a8c9ce95347d5050e7883 (diff) | |
download | plan9port-f08fdedcee12c06e3ce9ac9bec363915978e8289.tar.gz plan9port-f08fdedcee12c06e3ce9ac9bec363915978e8289.tar.bz2 plan9port-f08fdedcee12c06e3ce9ac9bec363915978e8289.zip |
Plan 9's rc.
not a clear win over byron's,
but at least it has the right syntax.
Diffstat (limited to 'src/cmd/rc/here.c')
-rw-r--r-- | src/cmd/rc/here.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/cmd/rc/here.c b/src/cmd/rc/here.c new file mode 100644 index 00000000..2a0fe2f2 --- /dev/null +++ b/src/cmd/rc/here.c @@ -0,0 +1,131 @@ +#include "rc.h" +#include "exec.h" +#include "io.h" +#include "fns.h" +struct here *here, **ehere; +int ser=0; +char tmp[]="/tmp/here0000.0000"; +char hex[]="0123456789abcdef"; +void psubst(io*, char*); +void pstrs(io*, word*); +void hexnum(char *p, int n) +{ + *p++=hex[(n>>12)&0xF]; + *p++=hex[(n>>8)&0xF]; + *p++=hex[(n>>4)&0xF]; + *p=hex[n&0xF]; +} +tree *heredoc(tree *tag) +{ + struct here *h=new(struct here); + if(tag->type!=WORD) yyerror("Bad here tag"); + h->next=0; + if(here) + *ehere=h; + else + here=h; + ehere=&h->next; + h->tag=tag; + hexnum(&tmp[9], getpid()); + hexnum(&tmp[14], ser++); + h->name=strdup(tmp); + return token(tmp, WORD); +} +/* + * bug: lines longer than NLINE get split -- this can cause spurious + * missubstitution, or a misrecognized EOF marker. + */ +#define NLINE 4096 +void readhere(void){ + struct here *h, *nexth; + io *f; + char *s, *tag; + int c, subst; + char line[NLINE+1]; + for(h=here;h;h=nexth){ + subst=!h->tag->quoted; + tag=h->tag->str; + c=Creat(h->name); + if(c<0) yyerror("can't create here document"); + f=openfd(c); + s=line; + pprompt(); + while((c=rchr(runq->cmdfd))!=EOF){ + if(c=='\n' || s==&line[NLINE]){ + *s='\0'; + if(strcmp(line, tag)==0) break; + if(subst) psubst(f, line); + else pstr(f, line); + s=line; + if(c=='\n'){ + pprompt(); + pchr(f, c); + } + else *s++=c; + } + else *s++=c; + } + flush(f); + closeio(f); + cleanhere(h->name); + nexth=h->next; + efree((char *)h); + } + here=0; + doprompt=1; +} +void psubst(io *f, char *s) +{ + char *t, *u; + int savec, n; + word *star; + while(*s){ + if(*s!='$'){ + if(0xa0<=(*s&0xff) && (*s&0xff)<=0xf5){ + pchr(f, *s++); + if(*s=='\0') break; + } + else if(0xf6<=(*s&0xff) && (*s&0xff)<=0xf7){ + pchr(f, *s++); + if(*s=='\0') break; + pchr(f, *s++); + if(*s=='\0') break; + } + pchr(f, *s++); + } + else{ + t=++s; + if(*t=='$') pchr(f, *t++); + else{ + while(*t && idchr(*t)) t++; + savec=*t; + *t='\0'; + n=0; + for(u=s;*u && '0'<=*u && *u<='9';u++) n=n*10+*u-'0'; + if(n && *u=='\0'){ + star=vlook("*")->val; + if(star && 1<=n && n<=count(star)){ + while(--n) star=star->next; + pstr(f, star->word); + } + } + else + pstrs(f, vlook(s)->val); + *t=savec; + if(savec=='^') t++; + } + s=t; + } + } +} +void pstrs(io *f, word *a) +{ + if(a){ + while(a->next && a->next->word){ + pstr(f, a->word); + pchr(f, ' '); + a=a->next; + } + pstr(f, a->word); + } +} |