|  | #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(tag && 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); | 
|  | } | 
|  | } |