]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/mk/mk.c
ip/ipconfig: format ipmask with %M instead of %I
[plan9front.git] / sys / src / cmd / mk / mk.c
1 #include        "mk.h"
2
3 int runerrs;
4
5 void
6 mk(char *target)
7 {
8         Node *node;
9         int did = 0;
10
11         nproc();                /* it can be updated dynamically */
12         nrep();                 /* it can be updated dynamically */
13         runerrs = 0;
14         node = graph(target);
15         if(DEBUG(D_GRAPH)){
16                 dumpn("new target\n", node);
17                 Bflush(&bout);
18         }
19         clrmade(node);
20         while(node->flags&NOTMADE){
21                 if(work(node, (Node *)0, (Arc *)0))
22                         did = 1;        /* found something to do */
23                 else {
24                         if(waitup(1, (int *)0) > 0){
25                                 if(node->flags&(NOTMADE|BEINGMADE)){
26                                         assert(/*must be run errors*/ runerrs);
27                                         break;  /* nothing more waiting */
28                                 }
29                         }
30                 }
31         }
32         if(node->flags&BEINGMADE)
33                 waitup(-1, (int *)0);
34         while(jobs)
35                 waitup(-2, (int *)0);
36         assert(/*target didnt get done*/ runerrs || (node->flags&MADE));
37         if(did == 0)
38                 Bprint(&bout, "mk: '%s' is up to date\n", node->name);
39 }
40
41 void
42 clrmade(Node *n)
43 {
44         Arc *a;
45
46         n->flags &= ~(CANPRETEND|PRETENDING);
47         if(strchr(n->name, '(') ==0 || n->time)
48                 n->flags |= CANPRETEND;
49         MADESET(n, NOTMADE);
50         for(a = n->prereqs; a; a = a->next)
51                 if(a->n)
52                         clrmade(a->n);
53 }
54
55 static void
56 unpretend(Node *n)
57 {
58         MADESET(n, NOTMADE);
59         n->flags &= ~(CANPRETEND|PRETENDING);
60         n->time = 0;
61 }
62
63 int
64 work(Node *node, Node *p, Arc *parc)
65 {
66         Arc *a, *ra;
67         int weoutofdate;
68         int ready;
69         int did = 0;
70         char cwd[256];
71
72         /*print("work(%s) flags=0x%x time=%ld\n", node->name, node->flags, node->time);/**/
73         if(node->flags&BEINGMADE)
74                 return(did);
75         if((node->flags&MADE) && (node->flags&PRETENDING) && p && outofdate(p, parc, 0)){
76                 if(explain)
77                         fprint(1, "unpretending %s(%ld) because %s is out of date(%ld)\n",
78                                 node->name, node->time, p->name, p->time);
79                 unpretend(node);
80         }
81         /*
82                 have a look if we are pretending in case
83                 someone has been unpretended out from underneath us
84         */
85         if(node->flags&MADE){
86                 if(node->flags&PRETENDING){
87                         node->time = 0;
88                 }else
89                         return(did);
90         }
91         /* consider no prerequisite case */
92         if(node->prereqs == 0){
93                 if(node->time == 0){
94                         if(getwd(cwd, sizeof cwd))
95                                 fprint(2, "mk: don't know how to make '%s' in directory %s\n", node->name, cwd);
96                         else
97                                 fprint(2, "mk: don't know how to make '%s'\n", node->name);
98                         if(kflag){
99                                 node->flags |= BEINGMADE;
100                                 runerrs++;
101                         } else
102                                 Exit();
103                 } else
104                         MADESET(node, MADE);
105                 return(did);
106         }
107         /*
108                 now see if we are out of date or what
109         */
110         ready = 1;
111         weoutofdate = aflag;
112         ra = 0;
113         for(a = node->prereqs; a; a = a->next)
114                 if(a->n){
115                         did = work(a->n, node, a) || did;
116                         if(a->n->flags&(NOTMADE|BEINGMADE))
117                                 ready = 0;
118                         if(outofdate(node, a, 0)){
119                                 weoutofdate = 1;
120                                 if((ra == 0) || (ra->n == 0)
121                                                 || (ra->n->time < a->n->time))
122                                         ra = a;
123                         }
124                 } else {
125                         if(node->time == 0){
126                                 if(ra == 0)
127                                         ra = a;
128                                 weoutofdate = 1;
129                         }
130                 }
131         if(ready == 0)  /* can't do anything now */
132                 return(did);
133         if(weoutofdate == 0){
134                 MADESET(node, MADE);
135                 return(did);
136         }
137         /*
138                 can we pretend to be made?
139         */
140         if((iflag == 0) && (node->time == 0) && (node->flags&(PRETENDING|CANPRETEND))
141                         && p && ra->n && !outofdate(p, ra, 0)){
142                 node->flags &= ~CANPRETEND;
143                 MADESET(node, MADE);
144                 if(explain && ((node->flags&PRETENDING) == 0))
145                         fprint(1, "pretending %s has time %ld\n", node->name, node->time);
146                 node->flags |= PRETENDING;
147                 return(did);
148         }
149         /*
150                 node is out of date and we REALLY do have to do something.
151                 quickly rescan for pretenders
152         */
153         for(a = node->prereqs; a; a = a->next)
154                 if(a->n && (a->n->flags&PRETENDING)){
155                         if(explain)
156                                 Bprint(&bout, "unpretending %s because of %s because of %s\n",
157                                 a->n->name, node->name, ra->n? ra->n->name : "rule with no prerequisites");
158
159                         unpretend(a->n);
160                         did = work(a->n, node, a) || did;
161                         ready = 0;
162                 }
163         if(ready == 0)  /* try later unless nothing has happened for -k's sake */
164                 return(did || work(node, p, parc));
165         did = dorecipe(node) || did;
166         return(did);
167 }
168
169 void
170 update(int fake, Node *node)
171 {
172         Arc *a;
173
174         MADESET(node, fake? BEINGMADE : MADE);
175         if(((node->flags&VIRTUAL) == 0) && (access(node->name, 0) == 0)){
176                 node->time = timeof(node->name, 1);
177                 node->flags &= ~(CANPRETEND|PRETENDING);
178                 for(a = node->prereqs; a; a = a->next)
179                         if(a->prog)
180                                 outofdate(node, a, 1);
181         } else {
182                 node->time = 1;
183                 for(a = node->prereqs; a; a = a->next)
184                         if(a->n && outofdate(node, a, 1))
185                                 node->time = a->n->time;
186         }
187 /*      print("----node %s time=%ld flags=0x%x\n", node->name, node->time, node->flags);/**/
188 }
189
190 static
191 pcmp(char *prog, char *p, char *q)
192 {
193         char buf[3*NAMEBLOCK];
194         int pid;
195
196         Bflush(&bout);
197         snprint(buf, sizeof buf, "%s '%s' '%s'\n", prog, p, q);
198         pid = pipecmd(buf, 0, 0);
199         while(waitup(-3, &pid) >= 0)
200                 ;
201         return(pid? 2:1);
202 }
203
204 int
205 outofdate(Node *node, Arc *arc, int eval)
206 {
207         char buf[3*NAMEBLOCK], *str;
208         Symtab *sym;
209         int ret;
210
211         str = 0;
212         if(arc->prog){
213                 snprint(buf, sizeof buf, "%s%c%s", node->name, 0377,
214                         arc->n->name);
215                 sym = symlook(buf, S_OUTOFDATE, 0);
216                 if(sym == 0 || eval){
217                         if(sym == 0)
218                                 str = strdup(buf);
219                         ret = pcmp(arc->prog, node->name, arc->n->name);
220                         if(sym)
221                                 sym->u.value = ret;
222                         else
223                                 symlook(str, S_OUTOFDATE, (void *)ret);
224                 } else
225                         ret = sym->u.value;
226                 return(ret-1);
227         } else if(strchr(arc->n->name, '(') && arc->n->time == 0)  /* missing archive member */
228                 return 1;
229         else
230                 /*
231                  * Treat equal times as out-of-date.
232                  * It's a race, and the safer option is to do
233                  * extra building rather than not enough.
234                  */
235                 return node->time <= arc->n->time;
236 }