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