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(&stdout); 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 didn't get done", runerrs || (node->flags&MADE)); 37 if(did == 0) 38 Bprint(&stdout, "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 n->flags |= CANPRETEND; 48 MADESET(n, NOTMADE); 49 for(a = n->prereqs; a; a = a->next) 50 if(a->n) 51 clrmade(a->n); 52 } 53 54 static void 55 unpretend(Node *n) 56 { 57 MADESET(n, NOTMADE); 58 n->flags &= ~(CANPRETEND|PRETENDING); 59 n->time = 0; 60 } 61 62 int 63 work(Node *node, Node *p, Arc *parc) 64 { 65 Arc *a, *ra; 66 int weoutofdate; 67 int ready; 68 int did = 0; 69 70 /*print("work(%s) flags=0x%x time=%ld\n", node->name, node->flags, node->time);/**/ 71 if(node->flags&BEINGMADE) 72 return(did); 73 if((node->flags&MADE) && (node->flags&PRETENDING) && p && outofdate(p, parc, 0)){ 74 if(explain) 75 fprint(1, "unpretending %s(%ld) because %s is out of date(%ld)\n", 76 node->name, node->time, p->name, p->time); 77 unpretend(node); 78 } 79 /* 80 have a look if we are pretending in case 81 someone has been unpretended out from underneath us 82 */ 83 if(node->flags&MADE){ 84 if(node->flags&PRETENDING){ 85 node->time = 0; 86 }else 87 return(did); 88 } 89 /* consider no prerequsite case */ 90 if(node->prereqs == 0){ 91 if(node->time == 0){ 92 fprint(2, "mk: don't know how to make '%s'\n", node->name); 93 if(kflag){ 94 node->flags |= BEINGMADE; 95 runerrs++; 96 } else 97 Exit(); 98 } else 99 MADESET(node, MADE); 100 return(did); 101 } 102 /* 103 now see if we are out of date or what 104 */ 105 ready = 1; 106 weoutofdate = aflag; 107 ra = 0; 108 for(a = node->prereqs; a; a = a->next) 109 if(a->n){ 110 did = work(a->n, node, a) || did; 111 if(a->n->flags&(NOTMADE|BEINGMADE)) 112 ready = 0; 113 if(outofdate(node, a, 0)){ 114 weoutofdate = 1; 115 if((ra == 0) || (ra->n == 0) 116 || (ra->n->time < a->n->time)) 117 ra = a; 118 } 119 } else { 120 if(node->time == 0){ 121 if(ra == 0) 122 ra = a; 123 weoutofdate = 1; 124 } 125 } 126 if(ready == 0) /* can't do anything now */ 127 return(did); 128 if(weoutofdate == 0){ 129 MADESET(node, MADE); 130 return(did); 131 } 132 /* 133 can we pretend to be made? 134 */ 135 if((iflag == 0) && (node->time == 0) && (node->flags&(PRETENDING|CANPRETEND)) && 136 p && ra->n && !outofdate(p, ra, 0)){ 137 node->flags &= ~CANPRETEND; 138 MADESET(node, MADE); 139 if(explain && ((node->flags&PRETENDING) == 0)) 140 fprint(1, "pretending %s has time %ld\n", node->name, node->time); 141 node->flags |= PRETENDING; 142 return(did); 143 } 144 /* 145 node is out of date and we REALLY do have to do something. 146 quickly rescan for pretenders 147 */ 148 for(a = node->prereqs; a; a = a->next) 149 if(a->n && (a->n->flags&PRETENDING)){ 150 if(explain) 151 Bprint(&stdout, "unpretending %s because of %s because of %s\n", 152 a->n->name, node->name, ra->n? ra->n->name : "rule with no prerequisites"); 153 154 unpretend(a->n); 155 did = work(a->n, node, a) || did; 156 ready = 0; 157 } 158 if(ready == 0) /* try later unless nothing has happened for -k's sake */ 159 return(did || work(node, p, parc)); 160 did = dorecipe(node) || did; 161 return(did); 162 } 163 164 void 165 update(int fake, Node *node) 166 { 167 Arc *a; 168 169 MADESET(node, fake? BEINGMADE : MADE); 170 if(((node->flags&VIRTUAL) == 0) && (access(node->name, 0) == 0)){ 171 node->time = timeof(node->name, 1); 172 node->flags &= ~(CANPRETEND|PRETENDING); 173 for(a = node->prereqs; a; a = a->next) 174 if(a->prog) 175 outofdate(node, a, 1); 176 } else { 177 node->time = 1; 178 for(a = node->prereqs; a; a = a->next) 179 if(a->n && outofdate(node, a, 1)) 180 node->time = a->n->time; 181 } 182 /* print("----node %s time=%ld flags=0x%x\n", node->name, node->time, node->flags);/**/ 183 } 184 185 static 186 pcmp(char *prog, char *n1, char *n2) 187 { 188 char buf[3*NAMEBLOCK]; 189 int pid; 190 191 pid = fork(); 192 if(pid < 0){ 193 fprint(2, "mk: "); 194 perror("pcmp fork"); 195 Exit(); 196 } 197 Bflush(&stdout); 198 if(pid == 0){ 199 sprint(buf, "%s '%s' '%s'", prog, n1, n2); 200 execl(shell, shellname, "-Ic", buf, (char *)0); 201 perror("exec shell"); 202 _exits("shell exec error"); 203 } else { 204 while(waitup(-3, &pid) >= 0) 205 ; 206 return(pid? 2:1); 207 } 208 } 209 210 int 211 outofdate(Node *node, Arc *arc, int eval) 212 { 213 char buf[3*NAMEBLOCK], *str; 214 Symtab *sym; 215 int ret; 216 217 str = 0; 218 if(arc->prog){ 219 sprint(buf, "%s%c%s", node->name, 0377, arc->n->name); 220 if(!(sym = symlook(buf, S_OUTOFDATE, (char *)0)) || eval){ 221 if(!sym) 222 str = strdup(buf); 223 ret = pcmp(arc->prog, node->name, arc->n->name); 224 if(sym) 225 sym->value = (char *)ret; 226 else 227 symlook(str, S_OUTOFDATE, (char *)ret); 228 } else 229 ret = (int)sym->value; 230 return(ret-1); 231 } else 232 return node->time < arc->n->time; 233 } 234