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