xref: /plan9/sys/src/cmd/rc/here.c (revision 8cc1c73ac888c72077712859b03e7c83105a4b4f)
13e12c5d1SDavid du Colombier #include "rc.h"
23e12c5d1SDavid du Colombier #include "exec.h"
33e12c5d1SDavid du Colombier #include "io.h"
43e12c5d1SDavid du Colombier #include "fns.h"
5*8cc1c73aSDavid du Colombier 
63e12c5d1SDavid du Colombier struct here *here, **ehere;
73e12c5d1SDavid du Colombier int ser = 0;
83e12c5d1SDavid du Colombier char tmp[] = "/tmp/here0000.0000";
93e12c5d1SDavid du Colombier char hex[] = "0123456789abcdef";
10276e7d6dSDavid du Colombier 
11276e7d6dSDavid du Colombier void psubst(io*, uchar*);
123e12c5d1SDavid du Colombier void pstrs(io*, word*);
13dc5a79c1SDavid du Colombier 
14dc5a79c1SDavid du Colombier void
hexnum(char * p,int n)15dc5a79c1SDavid du Colombier hexnum(char *p, int n)
163e12c5d1SDavid du Colombier {
173e12c5d1SDavid du Colombier 	*p++ = hex[(n>>12)&0xF];
183e12c5d1SDavid du Colombier 	*p++ = hex[(n>>8)&0xF];
193e12c5d1SDavid du Colombier 	*p++ = hex[(n>>4)&0xF];
203e12c5d1SDavid du Colombier 	*p = hex[n&0xF];
213e12c5d1SDavid du Colombier }
22dc5a79c1SDavid du Colombier 
23dc5a79c1SDavid du Colombier tree*
heredoc(tree * tag)24dc5a79c1SDavid du Colombier heredoc(tree *tag)
253e12c5d1SDavid du Colombier {
263e12c5d1SDavid du Colombier 	struct here *h = new(struct here);
27*8cc1c73aSDavid du Colombier 
28dc5a79c1SDavid du Colombier 	if(tag->type != WORD)
29dc5a79c1SDavid du Colombier 		yyerror("Bad here tag");
303e12c5d1SDavid du Colombier 	h->next = 0;
313e12c5d1SDavid du Colombier 	if(here)
323e12c5d1SDavid du Colombier 		*ehere = h;
333e12c5d1SDavid du Colombier 	else
343e12c5d1SDavid du Colombier 		here = h;
353e12c5d1SDavid du Colombier 	ehere = &h->next;
363e12c5d1SDavid du Colombier 	h->tag = tag;
373e12c5d1SDavid du Colombier 	hexnum(&tmp[9], getpid());
383e12c5d1SDavid du Colombier 	hexnum(&tmp[14], ser++);
393e12c5d1SDavid du Colombier 	h->name = strdup(tmp);
403e12c5d1SDavid du Colombier 	return token(tmp, WORD);
413e12c5d1SDavid du Colombier }
42*8cc1c73aSDavid du Colombier 
433e12c5d1SDavid du Colombier /*
443e12c5d1SDavid du Colombier  * bug: lines longer than NLINE get split -- this can cause spurious
453e12c5d1SDavid du Colombier  * missubstitution, or a misrecognized EOF marker.
463e12c5d1SDavid du Colombier  */
473e12c5d1SDavid du Colombier #define	NLINE	4096
48dc5a79c1SDavid du Colombier 
49dc5a79c1SDavid du Colombier void
readhere(void)50dc5a79c1SDavid du Colombier readhere(void)
51dc5a79c1SDavid du Colombier {
5299eb86a7SDavid du Colombier 	int c, subst;
53*8cc1c73aSDavid du Colombier 	char *s, *tag;
543e12c5d1SDavid du Colombier 	char line[NLINE+1];
55*8cc1c73aSDavid du Colombier 	io *f;
56*8cc1c73aSDavid du Colombier 	struct here *h, *nexth;
57*8cc1c73aSDavid du Colombier 
583e12c5d1SDavid du Colombier 	for(h = here; h; h = nexth){
593e12c5d1SDavid du Colombier 		subst = !h->tag->quoted;
603e12c5d1SDavid du Colombier 		tag = h->tag->str;
613e12c5d1SDavid du Colombier 		c = Creat(h->name);
62dc5a79c1SDavid du Colombier 		if(c < 0)
63dc5a79c1SDavid du Colombier 			yyerror("can't create here document");
643e12c5d1SDavid du Colombier 		f = openfd(c);
653e12c5d1SDavid du Colombier 		s = line;
663e12c5d1SDavid du Colombier 		pprompt();
673e12c5d1SDavid du Colombier 		while((c = rchr(runq->cmdfd)) != EOF){
683e12c5d1SDavid du Colombier 			if(c == '\n' || s == &line[NLINE]){
693e12c5d1SDavid du Colombier 				*s = '\0';
70*8cc1c73aSDavid du Colombier 				if(tag && strcmp(line, tag) == 0)
71*8cc1c73aSDavid du Colombier 					break;
72dc5a79c1SDavid du Colombier 				if(subst)
73276e7d6dSDavid du Colombier 					psubst(f, (uchar *)line);
74276e7d6dSDavid du Colombier 				else
75276e7d6dSDavid du Colombier 					pstr(f, line);
763e12c5d1SDavid du Colombier 				s = line;
773e12c5d1SDavid du Colombier 				if(c == '\n'){
783e12c5d1SDavid du Colombier 					pprompt();
793e12c5d1SDavid du Colombier 					pchr(f, c);
80*8cc1c73aSDavid du Colombier 				}else
81*8cc1c73aSDavid du Colombier 					*s++ = c;
82*8cc1c73aSDavid du Colombier 			}else
83*8cc1c73aSDavid du Colombier 				*s++ = c;
843e12c5d1SDavid du Colombier 		}
853e12c5d1SDavid du Colombier 		flush(f);
863e12c5d1SDavid du Colombier 		closeio(f);
873e12c5d1SDavid du Colombier 		cleanhere(h->name);
883e12c5d1SDavid du Colombier 		nexth = h->next;
893e12c5d1SDavid du Colombier 		efree((char *)h);
903e12c5d1SDavid du Colombier 	}
913e12c5d1SDavid du Colombier 	here = 0;
923e12c5d1SDavid du Colombier 	doprompt = 1;
933e12c5d1SDavid du Colombier }
94dc5a79c1SDavid du Colombier 
95dc5a79c1SDavid du Colombier void
psubst(io * f,uchar * s)96276e7d6dSDavid du Colombier psubst(io *f, uchar *s)
973e12c5d1SDavid du Colombier {
987dd7cddfSDavid du Colombier 	int savec, n;
99276e7d6dSDavid du Colombier 	uchar *t, *u;
100*8cc1c73aSDavid du Colombier 	Rune r;
1013e12c5d1SDavid du Colombier 	word *star;
102*8cc1c73aSDavid du Colombier 
1033e12c5d1SDavid du Colombier 	while(*s){
104*8cc1c73aSDavid du Colombier 		if(*s != '$'){		/* copy plain text rune */
105*8cc1c73aSDavid du Colombier 			if(*s < Runeself)
1063e12c5d1SDavid du Colombier 				pchr(f, *s++);
1073e12c5d1SDavid du Colombier 			else{
108*8cc1c73aSDavid du Colombier 				n = chartorune(&r, (char *)s);
109*8cc1c73aSDavid du Colombier 				while(n-- > 0)
110*8cc1c73aSDavid du Colombier 					pchr(f, *s++);
111*8cc1c73aSDavid du Colombier 			}
112*8cc1c73aSDavid du Colombier 		}else{			/* $something -- perform substitution */
1133e12c5d1SDavid du Colombier 			t = ++s;
114dc5a79c1SDavid du Colombier 			if(*t == '$')
115dc5a79c1SDavid du Colombier 				pchr(f, *t++);
1163e12c5d1SDavid du Colombier 			else{
117*8cc1c73aSDavid du Colombier 				while(*t && idchr(*t))
118*8cc1c73aSDavid du Colombier 					t++;
1193e12c5d1SDavid du Colombier 				savec = *t;
1203e12c5d1SDavid du Colombier 				*t = '\0';
1213e12c5d1SDavid du Colombier 				n = 0;
122*8cc1c73aSDavid du Colombier 				for(u = s; *u && '0' <= *u && *u <= '9'; u++)
123*8cc1c73aSDavid du Colombier 					n = n*10 + *u - '0';
1243e12c5d1SDavid du Colombier 				if(n && *u == '\0'){
1253e12c5d1SDavid du Colombier 					star = vlook("*")->val;
1263e12c5d1SDavid du Colombier 					if(star && 1 <= n && n <= count(star)){
127*8cc1c73aSDavid du Colombier 						while(--n)
128*8cc1c73aSDavid du Colombier 							star = star->next;
1293e12c5d1SDavid du Colombier 						pstr(f, star->word);
1303e12c5d1SDavid du Colombier 					}
131*8cc1c73aSDavid du Colombier 				}else
132276e7d6dSDavid du Colombier 					pstrs(f, vlook((char *)s)->val);
1333e12c5d1SDavid du Colombier 				*t = savec;
134dc5a79c1SDavid du Colombier 				if(savec == '^')
135dc5a79c1SDavid du Colombier 					t++;
1363e12c5d1SDavid du Colombier 			}
1373e12c5d1SDavid du Colombier 			s = t;
1383e12c5d1SDavid du Colombier 		}
1393e12c5d1SDavid du Colombier 	}
1403e12c5d1SDavid du Colombier }
141dc5a79c1SDavid du Colombier 
142dc5a79c1SDavid du Colombier void
pstrs(io * f,word * a)143dc5a79c1SDavid du Colombier pstrs(io *f, word *a)
1443e12c5d1SDavid du Colombier {
1453e12c5d1SDavid du Colombier 	if(a){
1463e12c5d1SDavid du Colombier 		while(a->next && a->next->word){
1473e12c5d1SDavid du Colombier 			pstr(f, a->word);
1483e12c5d1SDavid du Colombier 			pchr(f, ' ');
1493e12c5d1SDavid du Colombier 			a = a->next;
1503e12c5d1SDavid du Colombier 		}
1513e12c5d1SDavid du Colombier 		pstr(f, a->word);
1523e12c5d1SDavid du Colombier 	}
1533e12c5d1SDavid du Colombier }
154