Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/nmake/read.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1984-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* Glenn Fowler
23
* AT&T Research
24
*
25
* make file read routines
26
*/
27
28
#include "make.h"
29
30
/*
31
* read the base and global rules
32
*/
33
34
static void
35
readrules(void)
36
{
37
register char* s;
38
register Sfio_t* tmp;
39
register List_t* p;
40
41
state.global = 1;
42
43
/*
44
* read the base rules
45
*/
46
47
if (!(s = state.rules))
48
state.rules = null;
49
else if (*s)
50
{
51
tmp = sfstropen();
52
edit(tmp, s, KEEP, KEEP, external.object);
53
readfile(sfstruse(tmp), COMP_BASE|(state.explicitrules ? COMP_RULES : 0), NiL);
54
edit(tmp, s, DELETE, KEEP, DELETE);
55
state.rules = strdup(sfstruse(tmp));
56
sfstrclose(tmp);
57
}
58
setvar(external.rules, state.rules, 0)->property |= V_compiled;
59
60
/*
61
* read the explicit global makefiles
62
*
63
* NOTE: internal.tmplist is used to handle the effects
64
* of load() on internal list pointers
65
*/
66
67
if (p = internal.globalfiles->prereqs)
68
{
69
for (p = internal.tmplist->prereqs = listcopy(p); p; p = p->next)
70
readfile(p->rule->name, COMP_GLOBAL, NiL);
71
freelist(internal.tmplist->prereqs);
72
internal.tmplist->prereqs = 0;
73
}
74
state.global = 0;
75
}
76
77
/*
78
* read a file given an open file pointer
79
*/
80
81
static void
82
readfp(Sfio_t* sp, register Rule_t* r, int type)
83
{
84
register char* s;
85
register char* t;
86
int n;
87
int needrules;
88
int preprocess;
89
int splice;
90
char* name;
91
char* b;
92
char* e;
93
char* objfile;
94
Rule_t* x;
95
Sfio_t* fp;
96
97
objfile = 0;
98
name = r->name;
99
if (!state.makefile)
100
{
101
/*
102
* set up the related file names
103
*/
104
105
fp = sfstropen();
106
setvar(external.file, r->name, 0)->property |= V_compiled;
107
edit(fp, r->name, DELETE, KEEP, KEEP);
108
state.makefile = strdup(sfstruse(fp));
109
sfstrclose(fp);
110
objfile = objectfile();
111
}
112
needrules = !state.base && !state.rules;
113
114
/*
115
* load if object file
116
*/
117
118
if (loadable(sp, r, 0))
119
{
120
if (!state.base && !state.global && !state.list)
121
error(3, "%s: explicit make object files must be global", r->name);
122
if (!state.rules)
123
readrules();
124
message((-2, "loading %sobject file %s", state.global ? "global " : null, r->name));
125
if (load(sp, r->name, 0, 0) > 0)
126
{
127
sfclose(sp);
128
return;
129
}
130
error(3, "%s: must be recompiled", name);
131
}
132
133
/*
134
* check object corresponding to file
135
*/
136
137
if (state.global || !state.forceread && (!(type & COMP_FILE) || needrules))
138
{
139
fp = sfstropen();
140
if (!objfile)
141
{
142
edit(fp, r->name, DELETE, KEEP, external.object);
143
objfile = sfstruse(fp);
144
}
145
state.init++;
146
x = bindfile(NiL, objfile, 0);
147
state.init--;
148
sfstrclose(fp);
149
if (!x || !x->time)
150
/* ignore */;
151
else if (x == r)
152
error(3, "%s must be recompiled", r->name);
153
else if (fp = sfopen(NiL, s = x->name, "br"))
154
{
155
if (needrules)
156
x->dynamic |= D_built;
157
if (loadable(fp, x, 1))
158
{
159
if (needrules)
160
{
161
if (state.rules && !state.explicitrules)
162
{
163
edit(internal.tmp, state.rules, DELETE, KEEP, DELETE);
164
edit(internal.wrk, b = getval(external.rules, VAL_PRIMARY), DELETE, KEEP, DELETE);
165
if (strcmp(sfstruse(internal.tmp), sfstruse(internal.wrk)))
166
{
167
error(state.exec || state.mam.out ? -1 : 1, "%s: base rules changed to %s", sfstrbase(internal.tmp), sfstrbase(internal.wrk));
168
state.rules = b;
169
state.forceread = 1;
170
needrules = 1;
171
}
172
}
173
if (!state.forceread)
174
{
175
needrules = 0;
176
readrules();
177
}
178
}
179
if (!state.forceread)
180
{
181
message((-2, "loading %s file %s", state.global ? "global" : "object", s));
182
n = load(fp, s, 1, 0);
183
if (n > 0)
184
{
185
sfclose(fp);
186
sfclose(sp);
187
return;
188
}
189
}
190
r = getrule(name);
191
}
192
sfclose(fp);
193
if (state.global)
194
error(1, "%s: reading%s", r->name, state.forceread ? " -- should be compiled before local makefiles" : null);
195
else if (state.writeobject)
196
error(state.exec || state.mam.out ? -1 : 1, "%s: recompiling", s);
197
}
198
}
199
200
/*
201
* at this point we have to read it
202
* if its the first makefile then the
203
* base rules must be determined and loaded
204
* along with the global rules before the parse
205
*/
206
207
preprocess = state.preprocess;
208
if (!state.global)
209
{
210
/*
211
* first check for and apply makefile converter
212
*/
213
214
s = 0;
215
if (*(t = getval(external.convert, VAL_PRIMARY)))
216
{
217
char* u;
218
char* v;
219
Sfio_t* exp;
220
221
exp = sfstropen();
222
if (e = strchr(r->name, '/'))
223
e++;
224
else
225
e = r->name;
226
b = tokopen(t, 1);
227
while ((t = tokread(b)) && (t = colonlist(exp, t, 0, ' ')))
228
{
229
u = tokopen(t, 0);
230
while ((v = tokread(u)) && !streq(e, v));
231
tokclose(u);
232
if (!(s = tokread(b)))
233
{
234
error(2, "%s: %s: no action for file", external.convert, t);
235
break;
236
}
237
if (v)
238
{
239
s = getarg((e = t = strdup(s), &e), NiL);
240
break;
241
}
242
s = 0;
243
}
244
tokclose(b);
245
sfstrclose(exp);
246
}
247
if (s)
248
{
249
message((-2, "converting %s using \"%s\"", r->name, s));
250
sfclose(sp);
251
if (!(sp = fapply(internal.internal, null, r->name, s, CO_ALWAYS|CO_LOCAL|CO_URGENT)))
252
error(3, "%s: error in makefile converter \"%s\"", r->name, s);
253
free(t);
254
preprocess = -1;
255
}
256
if (needrules)
257
{
258
if ((s = sfreserve(sp, 0, 0)) && (n = sfvalue(sp)) >= 0)
259
{
260
int c;
261
int d;
262
int old;
263
264
if (n > 0)
265
{
266
if (n > MAXNAME)
267
n = MAXNAME;
268
else
269
n--;
270
}
271
272
/*
273
* quick makefile type check while
274
* checking for base rules
275
*/
276
277
old = 0;
278
splice = 0;
279
b = s;
280
c = *(s + n);
281
*(s + n) = 0;
282
for (;;)
283
{
284
if (e = strchr(s, '\n'))
285
*e = 0;
286
else if (c != '\n')
287
break;
288
if (splice)
289
/* skip */;
290
else if (*s == SALT)
291
{
292
while (isspace(*++s));
293
for (t = s; isalnum(*t); t++);
294
d = *t;
295
*t = 0;
296
if (strneq(s, "rules", 5))
297
{
298
if (*t = d)
299
t++;
300
while (*t == ' ' || *t == '\t')
301
t++;
302
rules(*t == '/' && *(t + 1) == '*' ? null : t);
303
break;
304
}
305
else if (!strmatch(s, "assert|comment|define|elif|else|endif|endmac|error|ident|if|ifdef|ifndef|include|line|macdef|pragma|unassert|undef|warning"))
306
old = 1;
307
else if (!preprocess)
308
preprocess = 1;
309
*t = d;
310
}
311
else if (*s == '<' && *(s + 1) == '<')
312
{
313
old = preprocess = 0;
314
break;
315
}
316
else
317
{
318
while (isspace(*s))
319
s++;
320
if (strneq(s, "rules", 5))
321
{
322
for (s += 5; *s == ' ' || *s == '\t'; s++);
323
rules(*s == '/' && *(s + 1) == '*' ? null : s);
324
old = 0;
325
break;
326
}
327
else if (strneq(s, ".SOURCE", 7) && (*(s + 7) == '.' || *(s + 7) == ':' || isspace(*(s + 7))))
328
{
329
old = 0;
330
break;
331
}
332
else
333
{
334
d = ':';
335
while (*s)
336
{
337
if (*s == '/' && *(s + 1) == '*' && (*(s + 2) == '*' || isspace(*(s + 2)) || !*(s + 2)))
338
break;
339
else if (*s == d)
340
{
341
if (*++s == d)
342
s++;
343
else if (isalnum(*s))
344
{
345
while (isalnum(*s))
346
s++;
347
if (*s == d)
348
break;
349
}
350
d = 0;
351
}
352
while (*s && *s != d && !isspace(*s))
353
s++;
354
while (isspace(*s))
355
s++;
356
}
357
if (*s)
358
{
359
old = 0;
360
break;
361
}
362
}
363
}
364
if (!(s = e))
365
break;
366
splice = e > b && *(e - 1) == '\\';
367
*s++ = '\n';
368
}
369
if (e)
370
*e = '\n';
371
*(b + n) = c;
372
if (old)
373
punt(1);
374
}
375
if (!state.rules)
376
state.rules = getval(external.rules, VAL_PRIMARY);
377
readrules();
378
r = getrule(name);
379
}
380
}
381
382
/*
383
* check for obsolete makefile preprocessor
384
*/
385
386
if (preprocess > 0)
387
{
388
s = "$(MAKEPP) $(MAKEPPFLAGS) $(>)";
389
message((-2, "preprocessing %s using \"%s\"", r->name, s));
390
sfclose(sp);
391
if (!(sp = fapply(internal.internal, null, r->name, s, CO_ALWAYS|CO_LOCAL|CO_URGENT)))
392
error(3, "%s: error in makefile preprocessor \"%s\"", r->name, s);
393
}
394
395
/*
396
* parse the file
397
*/
398
399
if (state.base)
400
{
401
if (!state.compile)
402
state.compile = RECOMPILE;
403
state.global = 1;
404
}
405
n = state.reading;
406
state.reading = 1;
407
parse(sp, NiL, r->name, NiL);
408
sfclose(sp);
409
state.reading = n;
410
if (!state.compile && !state.global)
411
state.compile = RECOMPILE;
412
if ((state.questionable & 0x00000400) || !state.global)
413
state.forceread = 1;
414
}
415
416
/*
417
* read a makefile
418
*/
419
420
int
421
readfile(register char* file, int type, char* filter)
422
{
423
register Rule_t* r;
424
Sfio_t* rfp;
425
Stat_t st;
426
427
if (streq(file, "-") && (file = "/dev/null") || isdynamic(file))
428
{
429
rfp = sfstropen();
430
expand(rfp, file);
431
state.init++;
432
file = makerule(sfstruse(rfp))->name;
433
state.init--;
434
sfstrclose(rfp);
435
}
436
state.init++;
437
r = bindfile(NiL, file, BIND_MAKEFILE|BIND_RULE);
438
state.init--;
439
if (r && (r->time || strneq(r->name, "/dev/", 5) && !rstat(r->name, &st, 0)))
440
{
441
compref(r, type);
442
r->dynamic |= D_scanned;
443
file = r->name;
444
if (rfp = filter ? fapply(internal.internal, null, file, filter, CO_ALWAYS|CO_LOCAL|CO_URGENT) : rsfopen(file))
445
{
446
if (state.mam.dynamic || state.mam.regress)
447
mampush(state.mam.out, r, P_force);
448
if (state.user)
449
{
450
r->status = EXISTS;
451
parse(rfp, NiL, file, NiL);
452
sfclose(rfp);
453
}
454
else
455
readfp(rfp, r, type);
456
if (state.mam.dynamic || state.mam.regress)
457
mampop(state.mam.out, r, 0);
458
if ((type & COMP_BASE) && r->uname)
459
{
460
oldname(r);
461
r->dynamic &= ~D_bound;
462
}
463
if (state.pushed)
464
{
465
state.pushed = 0;
466
state.global = state.push_global;
467
state.user = state.push_user;
468
}
469
return(1);
470
}
471
if ((type & COMP_DONTCARE) || (r->property & P_dontcare))
472
{
473
r->property |= P_dontcare;
474
return(0);
475
}
476
}
477
if (!(type & COMP_DONTCARE))
478
error((type & COMP_INCLUDE) ? 2 : 3, "%s: cannot read%s", file, (type & COMP_INCLUDE) ? " include file" : (type & COMP_GLOBAL) ? " global rules" : (type & COMP_BASE) ? " base rules" : null);
479
else if ((type & COMP_INCLUDE) && error_info.line)
480
compref(r ? r : makerule(file), type);
481
return(0);
482
}
483
484