xref: /plan9-contrib/sys/src/cmd/rc/here.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include "rc.h"
2 #include "exec.h"
3 #include "io.h"
4 #include "fns.h"
5 struct here *here, **ehere;
6 int ser=0;
7 char tmp[]="/tmp/here0000.0000";
8 char hex[]="0123456789abcdef";
9 void psubst(io*, char*);
10 void pstrs(io*, word*);
11 void hexnum(char *p, int n)
12 {
13 	*p++=hex[(n>>12)&0xF];
14 	*p++=hex[(n>>8)&0xF];
15 	*p++=hex[(n>>4)&0xF];
16 	*p=hex[n&0xF];
17 }
18 tree *heredoc(tree *tag)
19 {
20 	struct here *h=new(struct here);
21 	if(tag->type!=WORD) yyerror("Bad here tag");
22 	h->next=0;
23 	if(here)
24 		*ehere=h;
25 	else
26 		here=h;
27 	ehere=&h->next;
28 	h->tag=tag;
29 	hexnum(&tmp[9], getpid());
30 	hexnum(&tmp[14], ser++);
31 	h->name=strdup(tmp);
32 	return token(tmp, WORD);
33 }
34 /*
35  * bug: lines longer than NLINE get split -- this can cause spurious
36  * missubstitution, or a misrecognized EOF marker.
37  */
38 #define	NLINE	4096
39 void readhere(void){
40 	struct here *h, *nexth;
41 	io *f;
42 	char *s, *tag;
43 	int c, subst;
44 	char line[NLINE+1];
45 	for(h=here;h;h=nexth){
46 		subst=!h->tag->quoted;
47 		tag=h->tag->str;
48 		c=Creat(h->name);
49 		if(c<0) yyerror("can't create here document");
50 		f=openfd(c);
51 		s=line;
52 		pprompt();
53 		while((c=rchr(runq->cmdfd))!=EOF){
54 			if(c=='\n' || s==&line[NLINE]){
55 				*s='\0';
56 				if(strcmp(line, tag)==0) break;
57 				if(subst) psubst(f, line);
58 				else pstr(f, line);
59 				s=line;
60 				if(c=='\n'){
61 					pprompt();
62 					pchr(f, c);
63 				}
64 				else *s++=c;
65 			}
66 			else *s++=c;
67 		}
68 		flush(f);
69 		closeio(f);
70 		cleanhere(h->name);
71 		nexth=h->next;
72 		efree((char *)h);
73 	}
74 	here=0;
75 	doprompt=1;
76 }
77 void psubst(io *f, char *s)
78 {
79 	char *t, *u;
80 	int savec, n, c;
81 	word *star;
82 	while(*s){
83 		if(*s!='$'){
84 			if(0xa0<=(*s&0xff) && (*s&0xff)<=0xf5){
85 				pchr(f, *s++);
86 				if(*s=='\0') break;
87 			}
88 			else if(0xf6<=(*s&0xff) && (*s&0xff)<=0xf7){
89 				pchr(f, *s++);
90 				if(*s=='\0') break;
91 				pchr(f, *s++);
92 				if(*s=='\0') break;
93 			}
94 			pchr(f, *s++);
95 		}
96 		else{
97 			t=++s;
98 			if(*t=='$') pchr(f, *t++);
99 			else{
100 				while(*t && idchr(*t)) t++;
101 				savec=*t;
102 				*t='\0';
103 				n=0;
104 				for(u=s;*u && '0'<=*u && *u<='9';u++) n=n*10+*u-'0';
105 				if(n && *u=='\0'){
106 					star=vlook("*")->val;
107 					if(star && 1<=n && n<=count(star)){
108 						while(--n) star=star->next;
109 						pstr(f, star->word);
110 					}
111 				}
112 				else
113 					pstrs(f, vlook(s)->val);
114 				*t=savec;
115 				if(savec=='^') t++;
116 			}
117 			s=t;
118 		}
119 	}
120 }
121 void pstrs(io *f, word *a)
122 {
123 	if(a){
124 		while(a->next && a->next->word){
125 			pstr(f, a->word);
126 			pchr(f, ' ');
127 			a=a->next;
128 		}
129 		pstr(f, a->word);
130 	}
131 }
132