URI: 
       mk.c - 9base - revived minimalist port of Plan 9 userland to Unix
  HTML git clone git://git.suckless.org/9base
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR 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 }