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