Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/nmake/make.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 target proof algorithm
26
*/
27
28
#include "make.h"
29
30
#define PREVIEW(r,x) do{if(r->preview>x->preview&&(r->scan&&r->scan==x->scan||!r->scan&&!((r->property|x->property)&P_virtual)))r->preview=x->preview;}while(0)
31
32
/*
33
* make scan prereqs
34
*/
35
36
static int
37
makescan(register Rule_t* r, Time_t* tm)
38
{
39
register Rule_t* s;
40
register Rule_t* u;
41
register List_t* p;
42
List_t* q;
43
int errors = 0;
44
Time_t tevent;
45
Time_t t;
46
47
message((-2, "check scan prerequisites"));
48
q = scan(r, &tevent);
49
for (p = q; p; p = p->next)
50
{
51
s = p->rule;
52
if (!s->scan && (u = staterule(RULE, bind(s), NiL, 0)) && u->scan)
53
s->scan = u->scan;
54
make(s, &t, NiL, P_implicit);
55
}
56
errors += complete(r, q, &t, P_implicit);
57
if (tevent < t)
58
tevent = t;
59
*tm = tevent;
60
return errors;
61
}
62
63
/*
64
* insert|append global g prereqs to r
65
*/
66
67
static void
68
globalprereqs(register Rule_t* r, Rule_t* g)
69
{
70
register List_t* p;
71
register List_t* q;
72
register List_t* t;
73
register List_t* u;
74
Rule_t* x;
75
List_t* pos = 0;
76
77
while (x = associate(g, r, NiL, &pos))
78
if (p = x->prereqs)
79
{
80
for (q = t = 0; p; p = p->next)
81
if (p->rule != r)
82
{
83
newlist(u);
84
if (t)
85
t->next = u;
86
else
87
q = u;
88
(t = u)->rule = p->rule;
89
}
90
if (q)
91
{
92
t->next = 0;
93
r->prereqs = g == internal.insert_p ? append(q, r->prereqs) : append(r->prereqs, q);
94
if (x->dynamic & D_dynamic)
95
dynamic(r);
96
remdup(r->prereqs);
97
}
98
}
99
}
100
101
/*
102
* undo alias of a -> r in preparation for update()
103
* return unaliased a
104
*/
105
106
static Rule_t*
107
unalias(register Rule_t* r, register Rule_t* a, char* name)
108
{
109
Frame_t* oframe;
110
111
message((-3, "unalias(%s) -> %s", a->name, name));
112
if (a == r)
113
{
114
a->uname = name;
115
a->dynamic |= D_alias;
116
}
117
else
118
{
119
oframe = a->active;
120
a->active = r->active;
121
r->active = r->active->previous;
122
a->active->previous = oframe;
123
a->status = r->status;
124
r->status = NOTYET;
125
a->action = r->action;
126
if (r == state.frame->target)
127
state.frame->target = a;
128
}
129
if (r->view && a->active && !state.mam.statix)
130
a->active->original = a->name;
131
oldname(a);
132
return a;
133
}
134
135
/*
136
* prepare for update and execute action
137
* r is the target (possibly with explicit action)
138
* a is the implicit action rule
139
* arg for P_functional
140
*/
141
142
static int
143
update(register Rule_t* r, register Rule_t* a, char* arg)
144
{
145
register List_t* p;
146
register Rule_t* u;
147
int errors;
148
char* s;
149
150
errors = 0;
151
if (state.override)
152
{
153
/*
154
* save explicit target generation for non-override runs
155
*/
156
157
if (r == a && r->time && (!(r->property & P_target) || !(r->property & (P_archive|P_command|P_make))))
158
{
159
r->time = CURTIME;
160
r->dynamic |= D_triggered;
161
if (r->dynamic & D_member)
162
{
163
r->dynamic &= ~D_member;
164
r->dynamic |= D_membertoo;
165
}
166
return errors;
167
}
168
}
169
for (p = joint(r); p; p = p->next)
170
{
171
u = p->rule;
172
if (u->dynamic & D_alias)
173
u = makerule(u->name);
174
if (u->dynamic & D_member)
175
{
176
u->dynamic &= ~D_member;
177
u->dynamic |= D_membertoo;
178
}
179
if (!state.override && u->action)
180
a = u;
181
if (!(u->property & P_state))
182
{
183
if (u->uname)
184
{
185
if (u->view)
186
{
187
u->view = 0;
188
if (u->active && !state.mam.statix)
189
u->active->original = u->name;
190
}
191
oldname(u);
192
}
193
else if (u->view)
194
{
195
if (r == a)
196
u->view = 0;
197
else if (state.fsview)
198
{
199
u->view = 0;
200
if (u->active && !state.mam.statix)
201
{
202
if (state.expandview)
203
{
204
mount(u->name, sfstrbase(internal.tmp), FS3D_GET|FS3D_VIEW|FS3D_SIZE(sfstrsize(internal.tmp)), NiL);
205
u->active->original = makerule(sfstrbase(internal.tmp))->name;
206
}
207
else
208
u->active->original = u->name;
209
}
210
}
211
else
212
{
213
int n;
214
215
/*
216
* this condition is definitely a bug
217
* this fix will have to do until the
218
* place that set u->uname=0 is found
219
*/
220
221
n = 0;
222
s = u->name;
223
while (s = strchr(s, '/'))
224
{
225
n++;
226
if (getrule(++s) == u)
227
{
228
message((-1, "local binding %s recovered from %s", s, u->name));
229
u->view = 0;
230
if (u->active && !state.mam.statix)
231
u->active->original = u->name;
232
u->name = maprule(s, u);
233
break;
234
}
235
}
236
if (!s)
237
{
238
if (!n)
239
u->view = 0;
240
else if (!(u->property & P_dontcare))
241
error(1, "%s: modifying lower view=%d file", u->name, u->view);
242
}
243
}
244
}
245
}
246
}
247
if ((r->property & P_attribute) || (r->property & P_functional) && !(r->active->stem = arg))
248
{
249
if (!state.accept && !(r->property & P_accept))
250
r->dynamic |= D_triggered;
251
statetime(r, 1);
252
}
253
else
254
{
255
r->action = a->action;
256
trigger(r, a, a->action, CO_LOCALSTACK);
257
}
258
return errors;
259
}
260
261
/*
262
* top level make
263
* p temporarily or'd into r->property
264
* arg for P_functional
265
*
266
* r->status determines the status of each rule:
267
*
268
* NOTYET nothing done yet
269
* UPDATE rule in process of being updated
270
* MAKING rule action being executed
271
* TOUCH archive member to be touched
272
* EXISTS rule has already been made
273
* IGNORE rule make failed but ignore errors
274
* FAILED rule make failed
275
*/
276
277
void
278
maketop(register Rule_t* r, int p, char* arg)
279
{
280
Time_t t;
281
Flags_t o;
282
283
#if _HUH_2004_06_20
284
if ((p & (P_force|P_repeat)) == (P_force|P_repeat) && (r->property & (P_functional|P_make)) == P_make)
285
{
286
register Rule_t* a;
287
288
a = catrule(internal.internal->name, ".%%", r->name, 1);
289
a->property |= P_internal|P_virtual;
290
if (a->prereqs)
291
freelist(a->prereqs);
292
a->prereqs = cons(r, NiL);
293
r = a;
294
}
295
#endif
296
o = r->property & p;
297
r->property |= p;
298
if (p & P_ignore)
299
state.keepgoing |= 2;
300
make(r, &t, arg, 0);
301
complete(r, r->prereqs, NiL, 0);
302
state.keepgoing &= 1;
303
r->property &= ~p;
304
r->property |= o;
305
}
306
307
/*
308
* intermediate level make
309
*/
310
311
int
312
make(register Rule_t* r, Time_t* ttarget, char* arg, Flags_t flags)
313
{
314
register List_t* p;
315
register Rule_t* r1;
316
Time_t t;
317
Time_t tevent;
318
Time_t otime;
319
char* s;
320
char* v;
321
char* r3name;
322
int errors;
323
int explicit;
324
int must;
325
int otargetview;
326
int pop;
327
Rule_t* r0;
328
Rule_t* r2;
329
Rule_t* r3;
330
Rule_t* r4;
331
Rule_t* parent;
332
List_t* q;
333
Frame_t* fp;
334
Frame_t* oframe;
335
Frame_t frame;
336
Sfio_t* mam;
337
char stem[MAXNAME];
338
339
trap();
340
errors = 0;
341
*ttarget = 0;
342
if (state.expandall)
343
return errors;
344
if (r == internal.query)
345
{
346
interpreter(NiL);
347
return errors;
348
}
349
if (r->property & P_use)
350
{
351
/*
352
* r->use rules modify the parent
353
*/
354
355
r1 = state.frame->target;
356
if (!(r->property & P_metarule) && r1->action && !state.override)
357
return errors;
358
if (r->status == NOTYET)
359
{
360
/*
361
* check if the action changed
362
*/
363
364
r0 = staterule(RULE, r, NiL, 1);
365
if (r->action && (!r0->action || !streq(r->action, r0->action)) || !r->action && r0->action)
366
{
367
reason((1, "%s action changed [#1]", r->name));
368
r0->action = r->action;
369
r0->time = ((r1->property & P_accept) || state.accept) ? OLDTIME : CURTIME;
370
state.savestate = 1;
371
}
372
else if ((r1->property & P_accept) || state.accept)
373
r0->time = OLDTIME;
374
r->time = r0->time;
375
r->status = EXISTS;
376
}
377
#if DEBUG
378
else if (r->status != EXISTS)
379
error(PANIC, "%s rule %s has invalid status=%d", internal.use->name, r->name, r->status);
380
#endif
381
tevent = ((r->property & P_metarule) && (r1->property & P_implicit) && r1->action) ? 0 : r->time;
382
383
/*
384
* append the prerequisites
385
*/
386
387
q = listcopy(r->prereqs);
388
if (r->dynamic & D_dynamic)
389
{
390
fp = r->active;
391
r->active = state.frame;
392
dynamic(r);
393
r->active = fp;
394
r->dynamic |= D_dynamic;
395
}
396
p = r->prereqs;
397
r->prereqs = q;
398
r1->prereqs = append(r1->prereqs, p);
399
if (r->property & P_metarule)
400
for (; p; p = p->next)
401
{
402
r2 = p->rule;
403
if (r2->dynamic & D_scope)
404
r1->dynamic |= D_hasscope;
405
else if ((r2->property & (P_make|P_local|P_use)) == (P_make|P_local))
406
{
407
r2->property |= P_virtual;
408
r1->dynamic |= D_hasscope;
409
errors += make(r2, &t, NiL, 0);
410
if (tevent < t)
411
tevent = t;
412
}
413
else if ((r2->property & (P_after|P_use)) == P_after)
414
{
415
r1->dynamic |= D_hasafter;
416
if ((r2->property & (P_make|P_foreground)) == (P_make|P_foreground))
417
r1->dynamic |= D_hasmake;
418
}
419
else if ((r2->property & (P_before|P_use)) == P_before)
420
r1->dynamic |= D_hasbefore;
421
else if (r2->semaphore)
422
r1->dynamic |= D_hassemaphore;
423
else if ((r2->property & (P_joint|P_target)) != P_joint)
424
{
425
errors += make(r2, &t, NiL, 0);
426
if (tevent < t)
427
tevent = t;
428
}
429
}
430
431
/*
432
* propagate the attributes
433
*/
434
435
merge(r, r1, MERGE_ATTR);
436
if (!(r->property & P_metarule))
437
r1->action = r->action;
438
if ((r->property & P_dontcare) && !state.unwind)
439
state.unwind = error_info.indent;
440
if (!(r->property & P_ignore))
441
{
442
*ttarget = tevent;
443
PREVIEW(r1, r);
444
}
445
return errors;
446
}
447
else if (r->semaphore)
448
return complete(r, NiL, ttarget, 0);
449
450
/*
451
* check if rule has been or is in the process of being made
452
*/
453
454
message((-1, "make(%s%s%s)", r->name, arg ? " " : null, arg ? arg : null));
455
error_info.indent++;
456
r3 = r;
457
r3name = unbound(r3);
458
zero(frame);
459
frame.flags = flags;
460
frame.target = r;
461
frame.parent = state.frame;
462
parent = frame.parent->target;
463
frame.previous = r->active;
464
r->active = &frame;
465
for (;;)
466
{
467
if (r->status != NOTYET)
468
{
469
if (!(r->property & P_repeat))
470
{
471
tevent = r->time;
472
r0 = 0;
473
if (!(r->property & P_state))
474
{
475
if (mam = mamout(r))
476
pop = mampush(mam, r, flags);
477
if (r->scan && !(r->dynamic & D_scanned) && state.scan)
478
{
479
if (r->status == MAKING)
480
complete(r, NiL, NiL, 0);
481
if (r->status == EXISTS)
482
{
483
otime = r->time;
484
r0 = staterule(RULE, r, NiL, 1);
485
if (r0->time)
486
r->time = r0->time;
487
makescan(r, &t);
488
if (tevent < t)
489
r->time = r0->event = tevent = t;
490
else
491
r->time = otime;
492
}
493
}
494
if (mam && pop)
495
{
496
if (state.mam.statix)
497
r->dynamic |= D_built;
498
mampop(mam, r, P_virtual);
499
}
500
}
501
if (!(r->property & P_ignore))
502
{
503
if (r->dynamic & D_aliaschanged)
504
tevent = CURTIME;
505
else if (!(r->dynamic & D_triggered) && parent->scan == SCAN_IGNORE && (r0 || (r0 = staterule(RULE, r, NiL, 0))) && tevent < r0->time)
506
tevent = r0->time;
507
*ttarget = tevent;
508
PREVIEW(parent, r);
509
}
510
message((-1, "time(%s) = %s", r->name, timestr(tevent)));
511
r->active = frame.previous;
512
if (state.unwind == error_info.indent)
513
{
514
state.unwind = 0;
515
errors = 0;
516
}
517
error_info.indent--;
518
return r->status == FAILED;
519
}
520
if (r->status == MAKING)
521
complete(r, NiL, NiL, 0);
522
}
523
if ((r->property & P_dontcare) && !state.unwind)
524
state.unwind = error_info.indent;
525
otime = r->time;
526
if ((r1 = bind(r)) == r)
527
break;
528
if ((r->property & P_target) && !(r1->property & P_target))
529
{
530
r->dynamic &= ~D_alias;
531
break;
532
}
533
fp = r1->active;
534
r1->active = r->active;
535
r->active = r->active->previous;
536
r = r1;
537
r->active->target = r;
538
r->active->previous = fp;
539
}
540
if ((r3 == r || (r->property & P_target) && !(r3->property & P_target)) && (!(r->dynamic & D_alias) || r3name == unbound(r)))
541
r3 = 0;
542
otargetview = state.targetview;
543
if (state.maxview && !(r->property & P_state) && !r->scan && r->view <= state.maxview)
544
state.targetview = r->view;
545
frame.action = r->action;
546
frame.prereqs = r->prereqs;
547
if ((r->property & (P_joint|P_target)) == (P_joint|P_target))
548
for (p = r->prereqs->rule->prereqs; p; p = p->next)
549
if ((r1 = p->rule) != r)
550
{
551
fp = r1->active;
552
r1->active = r->active;
553
bind(r1);
554
r1->active = fp;
555
if (r1->status == NOTYET)
556
{
557
r0 = staterule(RULE, r1, NiL, 1);
558
if (!statetimeq(r1, r0) || !r0->event)
559
{
560
if ((r1->property & P_dontcare) && !r1->time)
561
r1->event = r0->event;
562
else
563
{
564
reason((1, "%s joint sibling %s is out of date", r->name, r1->name));
565
staterule(RULE, r, NiL, 1)->time = 0;
566
}
567
}
568
}
569
fp = newof(0, Frame_t, 1, 0);
570
fp->target = r1;
571
fp->parent = state.frame;
572
fp->previous = r1->active;
573
fp->action = r1->action;
574
fp->prereqs = r1->prereqs;
575
r1->active = fp;
576
}
577
oframe = state.frame;
578
state.frame = &frame;
579
if (r->dynamic & D_dynamic)
580
dynamic(r);
581
if (r->property & P_state)
582
while (r->active->prereqs && r->active->prereqs->next)
583
r->active->prereqs = r->active->prereqs->next;
584
r->dynamic &= ~(D_hasafter|D_hasbefore|D_hasmake|D_hasscope|D_hassemaphore|D_triggered);
585
r->status = UPDATE;
586
message((-1, "time(%s) = %s", r->name, timestr(r->time)));
587
if (mam = mamout(r))
588
{
589
pop = mampush(mam, r, flags);
590
if (state.mam.statix)
591
r->dynamic |= D_built;
592
}
593
594
/*
595
* check for file changes since the last make
596
* the changes take a few forms:
597
*
598
* o the file modify time has changed since the
599
* last make
600
*
601
* o the file is from a different directory than
602
* the last make -- this is checked by using
603
* the modify time of the file which may fail
604
* (low probability) if the two source files
605
* in question have both the same (base) name
606
* and the same modify time -- this avoids
607
* saving the full bound names in the state file
608
*
609
* notice that this technique detects when an old source
610
* file is reinstated and forces updating just as if
611
* the file had been touched
612
*/
613
614
must = 0;
615
tevent = 0;
616
if (r->property & P_state)
617
{
618
r0 = 0;
619
if (r->time != otime)
620
{
621
otime = r->time;
622
must = r->must = 1;
623
tevent = CURTIME;
624
}
625
}
626
else
627
{
628
otime = r->time;
629
must = 0;
630
r0 = staterule(RULE, r, NiL, 1);
631
if (!(r->property & P_virtual))
632
{
633
if (!state.intermediate && !r->time && r0->time && r0->event && (r0->dynamic & D_built) && !(parent->property & P_state) && (r2 = staterule(RULE, parent, NiL, 0)) && (r2->dynamic & D_built))
634
{
635
message((-1, "pretending intermediate target %s exists", r->name));
636
must = 1;
637
otime = r->time = r0->time;
638
r->dynamic |= D_intermediate;
639
r->must++;
640
}
641
else if (!statetimeq(r, r0) || !r0->event || (r->dynamic & D_aliaschanged))
642
{
643
if (!(r->property & P_accept) && !state.accept)
644
{
645
if (r->dynamic & D_aliaschanged)
646
reason((1, "%s [%s] binds to a different file", r->name, timestr(r->time)));
647
else
648
{
649
if (r->time && r->time < r0->time && (r->dynamic & D_regular))
650
error(1, "%s has been replaced by an older version", unbound(r));
651
if (r0->event && r0->time)
652
reason((1, "%s [%s] has changed [%s]", r->name, timestr(r->time), timestr(r0->time)));
653
else if (r0->event && r->view)
654
reason((1, "%s [%s] has changed in view %s", r->name, timestr(r->time), state.view[r->view].path));
655
else
656
reason((1, "%s [%s] has no previous state", r->name, timestr(r->time)));
657
}
658
must = 1;
659
r0->event = CURTIME;
660
r->must++;
661
state.savestate = 1;
662
}
663
if ((r->dynamic & (D_alias|D_bound)) == (D_alias|D_bound))
664
{
665
s = r->uname;
666
r->uname = 0;
667
r1 = staterule(RULE, r, NiL, 0);
668
r->uname = s;
669
if (r1 && r1 != r0 && r1->time)
670
{
671
r0->time = r1->time;
672
r0->event = r1->event;
673
}
674
else
675
{
676
r0->time = r->time;
677
r0->property |= P_force;
678
}
679
}
680
else
681
{
682
r0->time = r->time;
683
r0->property |= P_force;
684
}
685
}
686
if ((r->property & P_accept) || state.accept)
687
{
688
if (r->time < r0->event && (r1 = staterule(PREREQS, r, NiL, 0)) && r1->time >= r0->event)
689
r->time = r1->time;
690
else if (!r->time)
691
r0->event = OLDTIME;
692
else if (r->time < r0->event)
693
r->time = r0->event;
694
else
695
r0->event = r->time;
696
state.savestate = 1;
697
}
698
else
699
r->time = r0->event;
700
}
701
}
702
703
/*
704
* check global insert|append pattern prerequisites
705
*/
706
707
globalprereqs(r, internal.insert_p);
708
globalprereqs(r, internal.append_p);
709
710
/*
711
* check explicit prerequisites
712
*/
713
714
message((-2, "check explicit prerequisites"));
715
explicit = 0;
716
p = r->prereqs;
717
while (p)
718
{
719
r1 = p->rule;
720
if (r1->mark & M_bind)
721
r1->mark &= ~M_bind;
722
else if (r1->dynamic & D_scope)
723
r->dynamic |= D_hasscope;
724
else if ((r1->property & (P_make|P_local|P_use)) == (P_make|P_local))
725
{
726
r1->property |= P_virtual;
727
r->dynamic |= D_hasscope;
728
errors += make(r1, &t, NiL, 0);
729
if (tevent < t)
730
tevent = t;
731
}
732
else if ((r1->property & (P_after|P_use)) == P_after)
733
{
734
r->dynamic |= D_hasafter;
735
if ((r1->property & (P_make|P_foreground)) == (P_make|P_foreground))
736
r->dynamic |= D_hasmake;
737
}
738
else if ((r1->property & (P_before|P_use)) == P_before)
739
r->dynamic |= D_hasbefore;
740
else if (r1->semaphore)
741
r->dynamic |= D_hassemaphore;
742
else if ((r1->property & (P_joint|P_target)) != P_joint)
743
{
744
explicit = 1;
745
errors += make(r1, &t, NiL, 0);
746
if (tevent < t)
747
tevent = t;
748
if (r->time < t || (r1->dynamic & D_same))
749
r->must++;
750
if ((r2 = associate(internal.require_p, r1, NiL, NiL)) && (v = call(r2, unbound(r1))))
751
{
752
if (r->prereqs == r->active->prereqs)
753
for (p = r->prereqs = listcopy(r->prereqs); p->rule != r1; p = p->next);
754
q = 0;
755
while (s = getarg(&v, NiL))
756
{
757
if ((r2 = makerule(s)) == r1)
758
r1->mark |= M_bind;
759
if (streq(r2->name, "-"))
760
r1->property |= P_virtual;
761
else if (q)
762
q = q->next = cons(r2, q->next);
763
else
764
(q = p)->rule = r2;
765
}
766
if (q && !(state.questionable & 0x00020000))
767
{
768
unsigned long u = 0;
769
unsigned long n = 0;
770
771
/*
772
* mutually dependent requirements can
773
* get us into a loop -- this limits
774
* the total number to half the square
775
* of the number of unique non-virtual
776
* prereqs
777
*/
778
779
for (q = r->prereqs; q; q = q->next)
780
if (!(q->rule->property & P_virtual))
781
{
782
n++;
783
if (!(q->rule->mark & M_mark))
784
{
785
q->rule->mark |= M_mark;
786
u++;
787
}
788
}
789
if (u < 4)
790
u = 4;
791
if (n > (u * u) / 2)
792
{
793
for (q = r->prereqs; q; q = q->next)
794
if (!(q->rule->property & P_virtual) && (q->rule->mark & M_mark))
795
q->rule->mark &= ~(M_mark|M_generate);
796
else
797
q->rule->mark |= M_generate;
798
for (q = p; q; q = q->next)
799
if (!q->next || !(q->next->rule->mark & M_generate))
800
{
801
p = q;
802
message((-2, "require loop avoidance skips to %s [total=%lu uniqe=%lu]", q->next ? q->next->rule->name : "END", n, u));
803
break;
804
}
805
}
806
for (q = r->prereqs; q; q = q->next)
807
q->rule->mark &= ~(M_mark|M_generate);
808
}
809
}
810
}
811
p = p->next;
812
}
813
814
/*
815
* check metarule prerequisites
816
*/
817
818
if (!errors && !(r->property & (P_attribute|P_functional|P_operator|P_state|P_virtual)) && ((r->property & P_implicit) || !r->action && !explicit))
819
{
820
message((-2, "check metarule prerequisites"));
821
#if DEBUG
822
if (!r->active)
823
{
824
dumprule(sfstderr, r);
825
error(PANIC, "%s: active=0", r->name);
826
}
827
#endif
828
if (r0 && (flags & P_implicit))
829
r0->property |= P_implicit;
830
if ((r2 = metaget(r, r->active, stem, &r4)) && !(state.questionable & 0x00100000) && ((state.questionable & 0x00200000) || !(r->property & P_implicit)) && strchr(unbound(r), '/') && !strchr(r4->name, '/'))
831
r2 = 0;
832
if (r2)
833
{
834
r1 = r4;
835
if (state.mam.out && !mam)
836
{
837
mam = state.mam.out;
838
pop = mampush(mam, r, flags);
839
}
840
if (mam)
841
sfprintf(mam, "%smeta %s %s %s %s\n", state.mam.label, mamname(r), r4->name, state.mam.statix ? localview(r2) : r2->name, stem);
842
debug((-9, "metarule=%s source=%s stem=%s", r4->name, r2->name, stem));
843
frame.stem = stem;
844
845
/*
846
* primary metarule match
847
*/
848
849
if ((r1->property & P_accept) && r->must == 1 && r0 && r0->time)
850
{
851
tevent = 0;
852
r->must = 0;
853
must = 0;
854
}
855
else if (!r0 || !r0->time)
856
{
857
tevent = CURTIME;
858
r->must++;
859
must = 1;
860
}
861
862
/*
863
* check the implicit source prerequisite
864
*/
865
866
if (!(errors += make(r2, &t, NiL, 0)))
867
{
868
if (tevent < t)
869
tevent = t;
870
if (r->time < t || (r2->dynamic & D_same))
871
r->must++;
872
if (r1->property & P_after)
873
{
874
r2->property |= P_after;
875
r->dynamic |= D_hasafter;
876
}
877
if (r1->property & P_before)
878
{
879
r2->property |= P_before;
880
r->dynamic |= D_hasbefore;
881
}
882
883
/*
884
* check joint metarule targets
885
*/
886
887
if (r4 = metainfo('S', r1->name, NiL, 0))
888
{
889
Rule_t* joint;
890
Rule_t* x;
891
Rule_t* r5;
892
Sfio_t* tmp;
893
int i;
894
895
message((-2, "check joint metarule targets"));
896
tmp = sfstropen();
897
sfprintf(tmp, "%s.%s", internal.joint->name, unbound(r2));
898
joint = makerule(sfstruse(tmp));
899
joint->property |= P_joint|P_readonly|P_virtual;
900
for (p = r4->prereqs; p; p = p->next)
901
{
902
metaexpand(tmp, stem, p->rule->name);
903
s = sfstruse(tmp);
904
x = makerule(s);
905
if (x->property & P_joint)
906
x->prereqs->rule = joint;
907
else
908
{
909
x->property |= P_joint|P_target;
910
x->prereqs = cons(joint, x->prereqs);
911
}
912
joint->prereqs = append(joint->prereqs, cons(x, NiL));
913
if (x != r)
914
{
915
message((-1, "make(%s)", s));
916
error_info.indent++;
917
918
/*
919
* NOTE: some joint targets may not be generated
920
*/
921
922
t = (r4 = bindfile(NiL, s, 0)) ? r4->time : (Time_t)0;
923
if (!(r5 = staterule(RULE, r4, s, 0)))
924
i = state.accept;
925
else if (t)
926
{
927
r5->dynamic |= D_built;
928
i = state.accept || statetimeq(r4, r5);
929
}
930
else
931
i = !r5->time;
932
if (!i)
933
{
934
tevent = CURTIME;
935
reason((1, "joint metarule target %s [%s] changed [%s]", s, timestr(r4 ? r4->time : (Time_t)0), timestr(r5 ? r5->time : (Time_t)0)));
936
}
937
x->status = r->status;
938
message((-1, "time(%s) = %s", s, timestr(t)));
939
if (state.unwind == error_info.indent)
940
{
941
state.unwind = 0;
942
errors = 0;
943
}
944
error_info.indent--;
945
if (!x->active || x->active->parent != oframe)
946
{
947
fp = newof(0, Frame_t, 1, 0);
948
fp->target = x;
949
fp->parent = oframe;
950
fp->previous = x->active;
951
fp->action = x->action;
952
fp->prereqs = x->prereqs;
953
x->active = fp;
954
}
955
}
956
}
957
sfstrclose(tmp);
958
}
959
960
/*
961
* check the metarule
962
*/
963
964
errors += make(r1, &t, NiL, 0);
965
if (!errors)
966
{
967
/*UNDENT*/
968
if (tevent < t)
969
tevent = t;
970
if (r->time < t || (r1->dynamic & D_same))
971
r->must++;
972
973
/*
974
* check the explicit action
975
*/
976
977
if ((r->property & P_implicit) && r->action && r->action == r->active->action && (!r0->action || !streq(r0->action, r->action)))
978
{
979
reason((1, "%s action changed [#2]", r->name));
980
r0->action = r->action;
981
state.savestate = 1;
982
if (!(r->property & P_accept) && !state.accept)
983
{
984
tevent = CURTIME;
985
r->must++;
986
}
987
}
988
if ((state.questionable & 0x00000010) && r->view > r->preview && !(r->property & P_accept) && (!(r4 = staterule(PREREQS, r, NiL, 0)) || !r4->time))
989
{
990
reason((1, "%s view %d must be in view %d", r->name, r->view, r->preview));
991
tevent = CURTIME;
992
r->must++;
993
}
994
995
/*
996
* check for update
997
*/
998
999
timefix(tevent);
1000
if (must || r->time < tevent && (!(r4 = staterule(PREREQS, r, NiL, 0)) || r4->time < tevent) || (r->property & P_force) || prereqchange(r, r->prereqs, r0, r0->prereqs) || state.force)
1001
{
1002
if (state.touch)
1003
r->time = CURTIME;
1004
1005
/*
1006
* trigger the action
1007
*/
1008
1009
if (r3)
1010
{
1011
r = unalias(r, r3, r3name);
1012
if (r0)
1013
r0 = staterule(RULE, r, NiL, 1);
1014
}
1015
r->active->primary = r2->name;
1016
errors += update(r, r1, arg);
1017
}
1018
/*INDENT*/
1019
}
1020
}
1021
}
1022
else if (!errors && (r->property & P_implicit) && !state.override)
1023
{
1024
errors++;
1025
r->status = FAILED;
1026
parentage(internal.tmp, r, " : ");
1027
error(state.keepgoing || state.unwind ? 1 : 3, "can't find source for %s", sfstruse(internal.tmp));
1028
state.errors++;
1029
}
1030
}
1031
else
1032
r2 = 0;
1033
1034
/*
1035
* determine the update rule if no metarule applied
1036
*/
1037
1038
if (r2)
1039
{
1040
r1 = 0;
1041
r0->dynamic |= D_built;
1042
}
1043
else if (r->action)
1044
{
1045
r1 = r;
1046
if (r0)
1047
{
1048
if (r->action == r->active->action && (!r0->action || !streq(r0->action, r->action)))
1049
{
1050
reason((1, "%s action changed [#3]", r->name));
1051
r0->action = r->action;
1052
state.savestate = 1;
1053
if (!(r->property & P_accept) && !state.accept)
1054
{
1055
tevent = CURTIME;
1056
r->must++;
1057
}
1058
}
1059
r0->dynamic |= D_built;
1060
}
1061
}
1062
else
1063
{
1064
r1 = 0;
1065
if (r0)
1066
{
1067
if (r0->action)
1068
{
1069
reason((1, "%s action changed [#4]", r->name));
1070
r0->action = 0;
1071
state.savestate = 1;
1072
}
1073
1074
/*
1075
* at this point we accept the target as terminal source
1076
*/
1077
1078
r0->dynamic &= ~D_built;
1079
1080
/*
1081
* ... unless it doesn't exist
1082
*/
1083
1084
if (!r0->time)
1085
r->time = 0;
1086
}
1087
}
1088
if (r1)
1089
{
1090
if ((state.questionable & 0x00000010) && r->view > r->preview && !(r->property & P_accept) && (!(r4 = staterule(PREREQS, r, NiL, 0)) || !r4->time))
1091
{
1092
reason((1, "%s view %d must be in view %d", r->name, r->view, r->preview));
1093
must = 1;
1094
tevent = CURTIME;
1095
r->must++;
1096
}
1097
else if ((r->property & (P_attribute|P_functional|P_ignore|P_target)) == P_target && (state.force || r0 && !r0->time))
1098
{
1099
/*
1100
* this takes care of non-file targets
1101
*/
1102
1103
must = 1;
1104
tevent = CURTIME;
1105
r->must++;
1106
}
1107
}
1108
1109
/*
1110
* do the explicit action
1111
*/
1112
1113
timefix(tevent);
1114
message((-2, "[%s] : [%s]%s%s%s", timestr(r->time), timestr(tevent), errors ? " ERRORS" : null, errors && state.unwind >= error_info.indent ? " ignored" : null, must ? " must" : null));
1115
if (errors && !(state.questionable & 0x00800000))
1116
r->status = FAILED;
1117
else
1118
{
1119
if (!errors && !(r->dynamic & D_triggered) && r->status == UPDATE && (r1 && must || r->time < tevent && (!(r4 = staterule(PREREQS, r, NiL, 0)) || r4->time < tevent) || !r->time || !r2 && ((r->property & P_force) || r0 && (r->prereqs || r->action) && prereqchange(r, r->prereqs, r0, r0->prereqs))))
1120
{
1121
if (r1)
1122
{
1123
if (r3)
1124
{
1125
r = unalias(r, r3, r3name);
1126
if (r0)
1127
r0 = staterule(RULE, r, NiL, 1);
1128
}
1129
errors += update(r, r1, arg);
1130
}
1131
else if (r->property & P_dontcare)
1132
{
1133
statetime(r, 0);
1134
tevent = 0;
1135
}
1136
else if (!(r->property & (P_state|P_virtual)))
1137
{
1138
if (!(r->property & (P_target|P_terminal)) || r2 || (r->property & P_terminal) && !r->time)
1139
{
1140
if (r->status == UPDATE)
1141
{
1142
/*
1143
* the attribute test handles rules in
1144
* make object files that have since
1145
* become attributes, e.g., .READONLY
1146
*/
1147
1148
if ((r->property & P_attribute) || (r1 = associate(internal.dontcare_p, r, NiL, NiL)) && call(r1, r->name))
1149
{
1150
r->status = IGNORE;
1151
statetime(r, 0);
1152
tevent = 0;
1153
}
1154
else
1155
{
1156
errors++;
1157
r->status = FAILED;
1158
parentage(internal.tmp, r, " : ");
1159
error(state.keepgoing || state.unwind ? 1 : 3, "don't know how to make %s", sfstruse(internal.tmp));
1160
state.errors++;
1161
}
1162
}
1163
}
1164
else if (state.exec || state.mam.statix)
1165
{
1166
statetime(r, 0);
1167
if (!(r->property & P_terminal))
1168
tevent = 0;
1169
}
1170
}
1171
}
1172
if (!(r->dynamic & D_triggered))
1173
trigger(r, NiL, NiL, 0);
1174
}
1175
if (r->property & P_statevar)
1176
{
1177
if (state.targetview >= 0)
1178
{
1179
if (!tstbit(r->checked[RULE], state.targetview))
1180
staterule(RULE, r, NiL, 1);
1181
if (!tstbit(r->checked[CONSISTENT], state.targetview))
1182
{
1183
reason((1, "%s inconsistent with view %s", r->name, state.view[state.targetview].path));
1184
tevent = CURTIME;
1185
}
1186
}
1187
if (!state.accept && !(r->property & P_accept) && r->time < tevent)
1188
r->time = tevent;
1189
}
1190
else if (!(r->property & P_state))
1191
{
1192
if (!(r->property & P_archive) && r->scan && state.scan)
1193
{
1194
if (r->status == MAKING)
1195
complete(r, NiL, NiL, 0);
1196
if (r->status == UPDATE || r->status == EXISTS)
1197
{
1198
tevent = r->time;
1199
errors += makescan(r, &t);
1200
if (tevent < t)
1201
tevent = t;
1202
}
1203
}
1204
else
1205
{
1206
if (r->property & P_parameter)
1207
tevent = OLDTIME;
1208
if (r0 && ((r0->dynamic & D_built) || !r0->scan))
1209
{
1210
if (r0->prereqs != r->prereqs)
1211
{
1212
#if _HUH_1992_09_30 /* this test is insufficient */
1213
if ((r->property & (P_joint|P_target)) != (P_joint|P_target))
1214
freelist(r0->prereqs);
1215
#endif
1216
r0->prereqs = r->prereqs;
1217
}
1218
r0->attribute = r->attribute;
1219
r0->scan = 0;
1220
}
1221
}
1222
if (r0 && (r->property & (P_joint|P_target)) == (P_joint|P_target))
1223
for (p = r->prereqs->rule->prereqs; p; p = p->next)
1224
if (p->rule != r)
1225
{
1226
r1 = staterule(RULE, p->rule, NiL, 1);
1227
r1->prereqs = r0->prereqs;
1228
r1->attribute = r0->attribute;
1229
r1->scan = r0->scan;
1230
r1->action = r0->action;
1231
}
1232
if (r->time < tevent || (r->property & (P_attribute|P_parameter)))
1233
{
1234
r->time = tevent;
1235
if (!r0)
1236
r0 = staterule(RULE, r, NiL, 1);
1237
r0->event = tevent;
1238
}
1239
}
1240
if (r->status == FAILED)
1241
errors++;
1242
if (r->property & P_state)
1243
{
1244
if (r->time != otime)
1245
state.savestate = 1;
1246
}
1247
else if (state.force && (!(r->property & P_dontcare) || r->action || r2))
1248
r->time = CURTIME;
1249
if (r0 && (r->dynamic & D_triggered) && (r->property & P_make))
1250
{
1251
r0->time = r0->event = r->time;
1252
state.savestate = 1;
1253
}
1254
1255
/*
1256
* restore and return
1257
*/
1258
1259
for (p = joint(r); p; p = p->next)
1260
{
1261
r1 = p->rule;
1262
if (fp = r1->active)
1263
{
1264
if ((r1->property & P_state) && fp->prereqs)
1265
fp->prereqs->next = 0;
1266
r1->action = fp->action;
1267
r1->active = fp->previous;
1268
if (fp != &frame)
1269
free(fp);
1270
}
1271
if (r1 != r)
1272
{
1273
r1->time = r->time;
1274
r1->status = r->status;
1275
}
1276
}
1277
state.targetview = otargetview;
1278
state.frame = oframe;
1279
if (state.unwind == error_info.indent)
1280
{
1281
state.unwind = 0;
1282
errors = 0;
1283
}
1284
error_info.indent--;
1285
if (!(r->property & P_ignore))
1286
{
1287
t = r->time;
1288
if (parent->scan == SCAN_IGNORE)
1289
{
1290
if (!(r->dynamic & D_triggered) && !r->must)
1291
t = r0 ? r0->time : otime;
1292
}
1293
else if ((parent->property & P_archive) && (r->dynamic & D_regular) && (parent->dynamic & D_entries) && !(r->dynamic & D_member) && !(r->property & (P_archive|P_command|P_dontcare|P_ignore|P_state|P_virtual)))
1294
t = CURTIME;
1295
*ttarget = t;
1296
PREVIEW(parent, r);
1297
}
1298
message((-1, "time(%s) = %s", r->name, timestr(*ttarget)));
1299
if (mam && pop)
1300
mampop(mam, r, P_virtual);
1301
return errors;
1302
}
1303
1304
/*
1305
* make explicit before prerequisites if r's action will trigger
1306
*/
1307
1308
int
1309
makebefore(register Rule_t* r)
1310
{
1311
register List_t* p;
1312
register int errors;
1313
Time_t t;
1314
1315
errors = 0;
1316
if ((r->dynamic & (D_hasbefore|D_triggered)) == (D_hasbefore|D_triggered))
1317
{
1318
r->dynamic &= ~D_hasbefore;
1319
message((-2, "check explicit before `prerequisites'"));
1320
for (p = r->prereqs; p; p = p->next)
1321
if ((p->rule->property & (P_after|P_before)) == P_before)
1322
errors += make(p->rule, &t, NiL, 0);
1323
}
1324
return errors;
1325
}
1326
1327
/*
1328
* make explicit after prerequisites if r's action triggered
1329
*/
1330
1331
int
1332
makeafter(register Rule_t* r, Flags_t property)
1333
{
1334
register List_t* p;
1335
register int errors;
1336
Time_t t;
1337
1338
errors = 0;
1339
if ((r->dynamic & (D_hasafter|D_triggered)) == (D_hasafter|D_triggered))
1340
{
1341
statetime(r, -1);
1342
r->dynamic &= ~(D_hasafter|D_hasmake);
1343
message((-2, "check explicit %safter `prerequisites'", (property & P_dontcare) ? "dontcare " : null));
1344
for (p = r->prereqs; p; p = p->next)
1345
if ((p->rule->property & P_failure) == property)
1346
errors += make(p->rule, &t, NiL, 0);
1347
}
1348
return errors;
1349
}
1350
1351