1 #include "mk.h"
2
3 char *infile;
4 int mkinline;
5 static int rhead(char *, Word **, Word **, int *, char **);
6 static char *rbody(Biobuf*);
7 extern Word *target1;
8
9 void
parse(char * f,int fd,int varoverride)10 parse(char *f, int fd, int varoverride)
11 {
12 int hline;
13 char *body;
14 Word *head, *tail;
15 int attr, set, pid;
16 char *prog, *p;
17 int newfd;
18 Biobuf in;
19 Bufblock *buf;
20
21 if(fd < 0){
22 perror(f);
23 Exit();
24 }
25 ipush();
26 infile = strdup(f);
27 mkinline = 1;
28 Binit(&in, fd, OREAD);
29 buf = newbuf();
30 while(assline(&in, buf)){
31 hline = mkinline;
32 switch(rhead(buf->start, &head, &tail, &attr, &prog))
33 {
34 case '<':
35 p = wtos(tail, ' ');
36 if(*p == 0){
37 SYNERR(-1);
38 fprint(2, "missing include file name\n");
39 Exit();
40 }
41 newfd = open(p, OREAD);
42 if(newfd < 0){
43 fprint(2, "warning: skipping missing include file: ");
44 perror(p);
45 } else
46 parse(p, newfd, 0);
47 break;
48 case '|':
49 p = wtos(tail, ' ');
50 if(*p == 0){
51 SYNERR(-1);
52 fprint(2, "missing include program name\n");
53 Exit();
54 }
55 execinit();
56 pid=pipecmd(p, envy, &newfd);
57 if(newfd < 0){
58 fprint(2, "warning: skipping missing program file: ");
59 perror(p);
60 } else
61 parse(p, newfd, 0);
62 while(waitup(-3, &pid) >= 0)
63 ;
64 if(pid != 0){
65 fprint(2, "bad include program status\n");
66 Exit();
67 }
68 break;
69 case ':':
70 body = rbody(&in);
71 addrules(head, tail, body, attr, hline, prog);
72 break;
73 case '=':
74 if(head->next){
75 SYNERR(-1);
76 fprint(2, "multiple vars on left side of assignment\n");
77 Exit();
78 }
79 if(symlook(head->s, S_OVERRIDE, 0)){
80 set = varoverride;
81 } else {
82 set = 1;
83 if(varoverride)
84 symlook(head->s, S_OVERRIDE, (void *)"");
85 }
86 if(set){
87 /*
88 char *cp;
89 dumpw("tail", tail);
90 cp = wtos(tail, ' '); print("assign %s to %s\n", head->s, cp); free(cp);
91 */
92 setvar(head->s, (void *) tail);
93 symlook(head->s, S_WESET, (void *)"");
94 }
95 if(attr)
96 symlook(head->s, S_NOEXPORT, (void *)"");
97 break;
98 default:
99 SYNERR(hline);
100 fprint(2, "expected one of :<=\n");
101 Exit();
102 break;
103 }
104 }
105 close(fd);
106 freebuf(buf);
107 ipop();
108 }
109
110 void
addrules(Word * head,Word * tail,char * body,int attr,int hline,char * prog)111 addrules(Word *head, Word *tail, char *body, int attr, int hline, char *prog)
112 {
113 Word *w;
114
115 assert(/*addrules args*/ head && body);
116 /* tuck away first non-meta rule as default target*/
117 if(target1 == 0 && !(attr®EXP)){
118 for(w = head; w; w = w->next)
119 if(charin(w->s, "%&"))
120 break;
121 if(w == 0)
122 target1 = wdup(head);
123 }
124 for(w = head; w; w = w->next)
125 addrule(w->s, tail, body, head, attr, hline, prog);
126 }
127
128 static int
rhead(char * line,Word ** h,Word ** t,int * attr,char ** prog)129 rhead(char *line, Word **h, Word **t, int *attr, char **prog)
130 {
131 char *p;
132 char *pp;
133 int sep;
134 Rune r;
135 int n;
136 Word *w;
137
138 p = charin(line,":=<");
139 if(p == 0)
140 return('?');
141 sep = *p;
142 *p++ = 0;
143 if(sep == '<' && *p == '|'){
144 sep = '|';
145 p++;
146 }
147 *attr = 0;
148 *prog = 0;
149 if(sep == '='){
150 pp = charin(p, termchars); /* termchars is shell-dependent */
151 if (pp && *pp == '=') {
152 while (p != pp) {
153 n = chartorune(&r, p);
154 switch(r)
155 {
156 default:
157 SYNERR(-1);
158 fprint(2, "unknown attribute '%c'\n",*p);
159 Exit();
160 case 'U':
161 *attr = 1;
162 break;
163 }
164 p += n;
165 }
166 p++; /* skip trailing '=' */
167 }
168 }
169 if((sep == ':') && *p && (*p != ' ') && (*p != '\t')){
170 while (*p) {
171 n = chartorune(&r, p);
172 if (r == ':')
173 break;
174 p += n;
175 switch(r)
176 {
177 default:
178 SYNERR(-1);
179 fprint(2, "unknown attribute '%c'\n", p[-1]);
180 Exit();
181 case 'D':
182 *attr |= DEL;
183 break;
184 case 'E':
185 *attr |= NOMINUSE;
186 break;
187 case 'n':
188 *attr |= NOVIRT;
189 break;
190 case 'N':
191 *attr |= NOREC;
192 break;
193 case 'P':
194 pp = utfrune(p, ':');
195 if (pp == 0 || *pp == 0)
196 goto eos;
197 *pp = 0;
198 *prog = strdup(p);
199 *pp = ':';
200 p = pp;
201 break;
202 case 'Q':
203 *attr |= QUIET;
204 break;
205 case 'R':
206 *attr |= REGEXP;
207 break;
208 case 'U':
209 *attr |= UPD;
210 break;
211 case 'V':
212 *attr |= VIR;
213 break;
214 }
215 }
216 if (*p++ != ':') {
217 eos:
218 SYNERR(-1);
219 fprint(2, "missing trailing :\n");
220 Exit();
221 }
222 }
223 *h = w = stow(line);
224 if(*w->s == 0 && sep != '<' && sep != '|') {
225 SYNERR(mkinline-1);
226 fprint(2, "no var on left side of assignment/rule\n");
227 Exit();
228 }
229 *t = stow(p);
230 return(sep);
231 }
232
233 static char *
rbody(Biobuf * in)234 rbody(Biobuf *in)
235 {
236 Bufblock *buf;
237 int r, lastr;
238 char *p;
239
240 lastr = '\n';
241 buf = newbuf();
242 for(;;){
243 r = Bgetrune(in);
244 if (r < 0)
245 break;
246 if (lastr == '\n') {
247 if (r == '#')
248 rinsert(buf, r);
249 else if (r != ' ' && r != '\t') {
250 Bungetrune(in);
251 break;
252 }
253 } else
254 rinsert(buf, r);
255 lastr = r;
256 if (r == '\n')
257 mkinline++;
258 }
259 insert(buf, 0);
260 p = strdup(buf->start);
261 freebuf(buf);
262 return p;
263 }
264
265 struct input
266 {
267 char *file;
268 int line;
269 struct input *next;
270 };
271 static struct input *inputs = 0;
272
273 void
ipush(void)274 ipush(void)
275 {
276 struct input *in, *me;
277
278 me = (struct input *)Malloc(sizeof(*me));
279 me->file = infile;
280 me->line = mkinline;
281 me->next = 0;
282 if(inputs == 0)
283 inputs = me;
284 else {
285 for(in = inputs; in->next; )
286 in = in->next;
287 in->next = me;
288 }
289 }
290
291 void
ipop(void)292 ipop(void)
293 {
294 struct input *in, *me;
295
296 assert(/*pop input list*/ inputs != 0);
297 if(inputs->next == 0){
298 me = inputs;
299 inputs = 0;
300 } else {
301 for(in = inputs; in->next->next; )
302 in = in->next;
303 me = in->next;
304 in->next = 0;
305 }
306 infile = me->file;
307 mkinline = me->line;
308 free((char *)me);
309 }
310