URI:
       rules.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       rules.c (9699B)
       ---
            1 #include <signal.h>
            2 #include <stdio.h>
            3 #include <stdlib.h>
            4 #include <string.h>
            5 
            6 #include "make.h"
            7 
            8 #define TABSIZ 128
            9 #define FORCE   1
           10 #define NOFORCE 0
           11 
           12 static Target *htab[TABSIZ], *deftarget;
           13 
           14 void
           15 dumprules(void)
           16 {
           17         int i;
           18         Target **pp, **q, *p;
           19 
           20         for (pp = htab; pp < &htab[TABSIZ]; ++pp) {
           21                 for (p = *pp; p; p = p->next) {
           22                         if (!p->defined)
           23                                 continue;
           24                         printf("%s:", p->name);
           25                         for (q = p->deps; q && *q; ++q)
           26                                 printf(" %s", (*q)->name);
           27                         putchar('\n');
           28                         for (i = 0; i < p->nactions; i++)
           29                                 printf("\t%s\n", p->actions[i].line);
           30                         putchar('\n');
           31                 }
           32         }
           33 }
           34 
           35 static Target *
           36 lookup(char *name)
           37 {
           38         Target *tp;
           39         int h = hash(name) & TABSIZ-1;
           40 
           41         for (tp = htab[h]; tp && strcmp(tp->name, name); tp = tp->next)
           42                 ;
           43 
           44         if (tp)
           45                 return tp;
           46 
           47         tp = emalloc(sizeof(*tp));
           48         tp->name = estrdup(name);
           49         tp->target = tp->name;
           50         tp->req = NULL;
           51         tp->ndeps = 0;
           52         tp->deps = NULL;
           53         tp->actions = NULL;
           54         tp->nactions = 0;
           55         tp->next = htab[h];
           56         tp->defined = 0;
           57         htab[h] = tp;
           58 
           59         return tp;
           60 }
           61 
           62 static void
           63 cleanup(Target *tp)
           64 {
           65         int sig, precious;
           66         Target *p, **q;
           67 
           68         sig = stop;
           69         printf("make: signal %d arrived\n", sig);
           70 
           71         precious = 0;
           72         p = lookup(".PRECIOUS");
           73         for (q = p->deps; q && *q; q++) {
           74                 if (strcmp((*q)->name, tp->name) == 0) {
           75                         precious = 1;
           76                         break;
           77                 }
           78         }
           79 
           80         if (!precious && !nflag && !qflag && !is_dir(tp->name)) {
           81                 printf("make: trying to remove target %s\n", tp->name);
           82                 remove(tp->name);
           83         }
           84 
           85         signal(sig, SIG_DFL);
           86         raise(sig);
           87 }
           88 
           89 static int
           90 depends(char *dep, char *target)
           91 {
           92 
           93         int i;
           94         char *dname;
           95         Target **p, *tp;
           96 
           97         if (strcmp(target, dep) == 0)
           98                 return 1;
           99 
          100         tp = lookup(dep);
          101         for (p = tp->deps; p && *p; ++p) {
          102                 dname = (*p)->name;
          103                 if (depends(dname, target))
          104                         return 1;
          105         }
          106 
          107         return 0;
          108 }
          109 
          110 static int
          111 is_suffix(char *s)
          112 {
          113         int n;
          114 
          115         if (s[0] != '.')
          116                 return 0;
          117 
          118         for (n = 0; s = strchr(s, '.'); n++)
          119                 s++;
          120 
          121         return n == 2;
          122 }
          123 
          124 void
          125 addtarget(char *target, int ndeps)
          126 {
          127         Target *tp = lookup(target);
          128 
          129         tp->defined = 1;
          130         if (!deftarget && target[0] != '.') {
          131                 deftarget = tp;
          132                 return;
          133         }
          134 
          135         if (strcmp(target, ".SUFFIXES") == 0 && ndeps == 0) {
          136                 free(tp->deps);
          137                 tp->deps = NULL;
          138                 tp->ndeps = 0;
          139                 return;
          140         }
          141 
          142         if (strcmp(target, ".DEFAULT") == 0) {
          143                 if (ndeps > 0)
          144                         error("DEFAULT rule with prerequisites");
          145                 return;
          146         }
          147 
          148         if (strcmp(target, ".SILENT") == 0 && ndeps == 0) {
          149                 sflag = 1;
          150                 return;
          151         }
          152 
          153         if (strcmp(target, ".IGNORE") == 0 && ndeps == 0) {
          154                 iflag = 1;
          155                 return;
          156         }
          157 }
          158 
          159 void
          160 adddep(char *target, char *dep)
          161 {
          162         int i;
          163         size_t siz;
          164         Target **p, *tp = lookup(target);
          165 
          166         if (depends(dep, target)) {
          167                 warning("circular dependency %s <- %s dropped", target, dep);
          168                 return;
          169         }
          170 
          171         for (p = tp->deps; p && *p; ++p) {
          172                 if (strcmp((*p)->name, dep) == 0)
          173                         return;
          174         }
          175 
          176         tp->ndeps++;
          177         siz = (tp->ndeps + 1) * sizeof(Target *);
          178         tp->deps = erealloc(tp->deps, siz);
          179         tp->deps[tp->ndeps-1] = lookup(dep);
          180         tp->deps[tp->ndeps] = NULL;
          181 
          182         debug("adding dependency %s <- %s", target, dep);
          183 }
          184 
          185 static void
          186 freeaction(struct action *act)
          187 {
          188         free(act->line);
          189         freeloc(&act->loc);
          190 }
          191 
          192 void
          193 addrule(char *target, struct action  *acts, int n)
          194 {
          195         int i;
          196         struct action *v;
          197         Target *tp = lookup(target);
          198 
          199         debug("adding actions for target %s", target);
          200 
          201         if (tp->actions) {
          202                 debug("overring actions of target %s", target);
          203                 for (i = 0; i < tp->nactions; i++)
          204                         freeaction(&tp->actions[i]);
          205                 free(tp->actions);
          206         }
          207 
          208         v = emalloc(n * sizeof(*v));
          209         for (i = 0; i < n; i++) {
          210                 v[i].line = estrdup(acts[i].line);
          211                 v[i].loc.lineno = acts[i].loc.lineno;
          212                 v[i].loc.fname = estrdup(acts[i].loc.fname);
          213         }
          214 
          215         tp->nactions = n;
          216         tp->actions = v;
          217 }
          218 
          219 static int
          220 execline(Target *tp, char *line, int ignore, int silence)
          221 {
          222         char *s, *t;
          223         Target *p, **q;
          224         int r, at, plus, minus, l;
          225 
          226         debug("executing '%s'", line);
          227 
          228         at = plus = minus = 0;
          229         for (s = line; ; s++) {
          230                 switch (*s) {
          231                 case '@':
          232                         at = 1;
          233                         break;
          234                 case '-':
          235                         minus = 1;
          236                         break;
          237                 case '+':
          238                         plus = 1;
          239                         break;
          240                 default:
          241                         goto out_loop;
          242                 }
          243         }
          244 
          245 out_loop:
          246         /* unescape $$ */
          247         for (l = strlen(s)+1, t = s; *t; --l, ++t) {
          248                 if (t[0] == '$' && t[1] == '$') {
          249                         memmove(t+1, t+2, l-2);
          250                         l--;
          251                 }
          252         }
          253 
          254         if (tflag && !plus)
          255                 return 0;
          256 
          257         if (sflag || silence || (qflag && !plus))
          258                 at = 1;
          259         if (nflag)
          260                 at = 0;
          261         if (!at) {
          262                 puts(s);
          263                 fflush(stdout);
          264         }
          265 
          266         if ((nflag || qflag) && !plus) {
          267                 if (qflag)
          268                         exitstatus = 1;
          269                 return 0;
          270         }
          271 
          272         if (minus || iflag || ignore)
          273                 ignore = 1;
          274 
          275         r = launch(s, ignore);
          276         if (ignore)
          277                 return 0;
          278 
          279         return r;
          280 }
          281 
          282 static int
          283 touch(char *name, int ignore, int silence)
          284 {
          285         char *cmd;
          286         int r, n;
          287 
          288         n = snprintf(NULL, 0, "touch %s", name) + 1;
          289         cmd = emalloc(n);
          290         snprintf(cmd, n, "touch %s", name);
          291 
          292         if (!sflag && !silence)
          293                 puts(cmd);
          294 
          295         r = system(cmd);
          296         free(cmd);
          297 
          298         if (ignore || iflag)
          299                 return 0;
          300 
          301         return r;
          302 }
          303 
          304 static int
          305 touchdeps(Target *tp, int ignore, int silent)
          306 {
          307         int r;
          308         Target **p;
          309 
          310         if (tp->req) {
          311                 r = touch(tp->req, silent, ignore);
          312                 if (r)
          313                         return r;
          314         }
          315 
          316         for (p = tp->deps; p && *p; ++p) {
          317                 r = touch((*p)->name, silent, ignore);
          318                 if (r)
          319                         return r;
          320         }
          321 
          322         return 0;
          323 }
          324 
          325 static int
          326 run(Target *tp)
          327 {
          328         int r, i, ignore, silent;
          329         char *s;
          330         Target *p, **q;
          331 
          332         silent = 0;
          333         p = lookup(".SILENT");
          334         for (q = p->deps; q && *q; ++q) {
          335                 if (strcmp((*q)->name, tp->name) == 0) {
          336                         debug("target %s error silent by .SILENT", tp->name);
          337                         silent = 1;
          338                 }
          339         }
          340 
          341         ignore = 0;
          342         p = lookup(".IGNORE");
          343         for (q = p->deps; q && *q; ++q) {
          344                 if (strcmp((*q)->name, tp->name) == 0) {
          345                         debug("target %s error ignored by .IGNORE", tp->name);
          346                         ignore = 1;
          347                 }
          348         }
          349 
          350         if (tflag) {
          351                 r = touchdeps(tp, ignore, silent);
          352                 if (r)
          353                         return r;
          354         }
          355 
          356         for (i = 0; i < tp->nactions; i++) {
          357                 struct action *p;
          358 
          359                 if (stop)
          360                         cleanup(tp);
          361 
          362                 p = &tp->actions[i];
          363                 debug("executing action '%s'", p->line);
          364                 s = expandstring(p->line, tp, &p->loc);
          365                 r = execline(tp, s, ignore, silent);
          366                 free(s);
          367 
          368                 if (r)
          369                         return r;
          370         }
          371 
          372         if (tflag) {
          373                 r = touch(tp->target, ignore, silent);
          374                 if (r)
          375                         return r;
          376         }
          377 
          378         return 0;
          379 }
          380 
          381 static int
          382 enabled(char *suffix)
          383 {
          384         Target **p, *tp = lookup(".SUFFIXES");
          385 
          386         for (p = tp->deps; p && *p; ++p) {
          387                 if (strcmp(suffix, (*p)->name) == 0)
          388                         return 1;
          389         }
          390 
          391         return 0;
          392 }
          393 
          394 static Target *
          395 inference(Target *tp, int force)
          396 {
          397         time_t t;
          398         int tolen, r;
          399         char *to, *from;
          400         Target *q, **p, *suffixes;
          401         char buf[FILENAME_MAX], fname[FILENAME_MAX];
          402 
          403         debug("searching an inference rule for %s", tp->name);
          404 
          405         to = strrchr(tp->name, '.');
          406         if (to && !enabled(to))
          407                 return NULL;
          408         tolen = to ? to - tp->name : strlen(tp->name);
          409 
          410         if (!to)
          411                 to = "";
          412 
          413         suffixes = lookup(".SUFFIXES");
          414         for (p = suffixes->deps; p && *p; ++p) {
          415                 from = (*p)->name;
          416                 debug("trying suffix %s", from);
          417 
          418                 r = snprintf(buf,
          419                              sizeof(buf),
          420                              "%s%s",
          421                              from, to);
          422 
          423                 if (r < 0 || r >= sizeof(buf))
          424                         error("suffixes too long %s %s", from, to);
          425 
          426                 q = lookup(buf);
          427                 if (!q->actions)
          428                         continue;
          429 
          430                 r = snprintf(fname,
          431                              sizeof(fname),
          432                              "%*.*s%s",
          433                              tolen, tolen, tp->name, from);
          434 
          435                 if (r < 0 || r >= sizeof(fname)) {
          436                         error("prerequisite name too long %s %s",
          437                               tp->name, from);
          438                 }
          439 
          440                 debug("\tsearching prerequisite %s", fname);
          441 
          442                 t = stamp(fname);
          443                 if (t == -1) {
          444                         debug("\tprerequisite %s not found", fname);
          445                         continue;
          446                 }
          447 
          448                 if (!force && t <= tp->stamp) {
          449                         debug("\tdiscarded because is newer");
          450                         debug("\t%s: %s", tp->name, ctime(&tp->stamp));
          451                         debug("\t%s: %s", fname, ctime(&t));
          452                         continue;
          453                 }
          454 
          455                 free(q->req);
          456                 q->req = estrdup(fname);
          457                 q->deps = tp->deps;
          458                 q->target = tp->name;
          459                 q->stamp = tp->stamp;
          460 
          461                 debug("using inference rule %s with %s", q->name, fname);
          462                 return q;
          463         }
          464 
          465         return NULL;
          466 }
          467 
          468 static int
          469 update(Target *tp)
          470 {
          471         Target *p;
          472 
          473         debug("%s needs to be updated", tp->name);
          474 
          475         if (tp->actions) {
          476                 debug("using target rule to build %s", tp->name);
          477                 return run(tp);
          478         }
          479 
          480         if ((p = inference(tp, FORCE)) != NULL) {
          481                 debug("using inference rule %s", p->name);
          482                 return run(p);
          483         }
          484 
          485         p = lookup(".DEFAULT");
          486         if (p->defined) {
          487                 debug("using default rule");
          488                 return run(p);
          489         }
          490 
          491         debug("not rule found to update %s", tp->name);
          492 
          493         if (!tp->defined)
          494                 error("don't know how to make %s", tp->name);
          495 
          496         return 0;
          497 }
          498 
          499 static int 
          500 rebuild(Target *tp, int *buildp)
          501 {
          502         Target **p, *q;;
          503         int r, need, build, err, def;
          504 
          505         debug("checking rebuild of %s", tp->name);
          506 
          507         tp->stamp = stamp(tp->name);
          508 
          509         def = err = need = 0;
          510         for (p = tp->deps; p && *p; ++p) {
          511                 if (stop)
          512                         cleanup(tp);
          513 
          514                 q = *p;
          515                 debug("checking dependency %s", q->name);
          516 
          517                 if (strcmp(q->name, tp->name) == 0 && q->actions)
          518                         def = 1;
          519 
          520                 build = 0;
          521                 if (rebuild(q, &build) != 0) {
          522                         err = 1;
          523                         continue;
          524                 }
          525 
          526                 if (build) {
          527                         debug("rebuild of %s forces rebuild of %s",
          528                                q->name, tp->name);
          529                         need = 1;
          530                 } else if (q->stamp > tp->stamp) {
          531                         debug("dependency %s is newer than %s",
          532                               q->name, tp->name);
          533                         need = 1;
          534                 }
          535         }
          536 
          537         if (tp->stamp == -1) {
          538                 need = 1;
          539         } else if (!def)  {
          540                 debug("no action found for %s, looking a inference rule",
          541                       tp->name);
          542                 if (inference(tp, NOFORCE))
          543                         need = 1;
          544         }
          545 
          546         if (err) {
          547                 warning("target %s not remade because of errors", tp->name);
          548                 return 1;
          549         } else if (need) {
          550                 *buildp = 1;
          551 
          552                 debug("target %s needs updating", tp->name);
          553                 r = update(tp);
          554                 if (r == 0)
          555                         return 0;
          556 
          557                 if (stop)
          558                         cleanup(tp);
          559 
          560                 exitstatus = 1;
          561 
          562                 if (!kflag)
          563                         error("target %s: error %d", tp->name, r);
          564                 else
          565                         warning("target %s: error %d", tp->name, r);
          566                 return r;
          567         }
          568 
          569         return 0;
          570 }
          571 
          572 int
          573 build(char *name)
          574 {
          575         int build, r;
          576 
          577         if (!name) {
          578                 if (!deftarget) {
          579                         printf("make: no target to make\n");
          580                         return 0;
          581                 }
          582                 name = deftarget->name;
          583         }
          584 
          585         debug("checking target %s", name);
          586 
          587         build = 0;
          588         return rebuild(lookup(name), &build);
          589 }