9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

mk.c (5249B)


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