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