Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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&REGEXP)){
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
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 *
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
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
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
}