main.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       main.c (5332B)
       ---
            1 #include <errno.h>
            2 #include <signal.h>
            3 #include <stdarg.h>
            4 #include <stdio.h>
            5 #include <stdlib.h>
            6 #include <string.h>
            7 
            8 #include "make.h"
            9 
           10 #ifndef SIGINT
           11 #define SIGINT -1
           12 #endif
           13 
           14 #ifndef SIGTERM
           15 #define SIGTERM -1
           16 #endif
           17 
           18 #ifndef SIGQUIT
           19 #define SIGQUIT -1
           20 #endif
           21 
           22 #ifndef SIGHUP
           23 #define SIGHUP -1
           24 #endif
           25 
           26 int kflag, dflag, nflag, iflag, sflag;
           27 int eflag, pflag, tflag, qflag;
           28 int exitstatus;
           29 volatile sig_atomic_t  stop;
           30 
           31 void
           32 debug(char *fmt, ...)
           33 {
           34         va_list va;
           35 
           36         if (!dflag)
           37                 return;
           38 
           39         va_start(va, fmt);
           40         vfprintf(stdout, fmt, va);
           41         fputc('\n', stdout);
           42         va_end(va);
           43 }
           44 
           45 int
           46 hash(char *name)
           47 {
           48         int c;
           49         unsigned h = 5381;
           50 
           51         while (c = *name++)
           52                 h = h*33 ^ c;
           53 
           54         return h;
           55 }
           56 
           57 void *
           58 emalloc(size_t siz)
           59 {
           60         void *p;
           61 
           62         if ((p = malloc(siz)) == NULL) {
           63                 perror("make");
           64                 exit(EXIT_FAILURE);
           65         }
           66 
           67         return p;
           68 }
           69 
           70 void *
           71 erealloc(void *p, size_t siz)
           72 {
           73         if ((p = realloc(p, siz)) == NULL) {
           74                 perror("make");
           75                 exit(EXIT_FAILURE);
           76         }
           77 
           78         return p;
           79 }
           80 
           81 char *
           82 estrdup(char *s)
           83 {
           84         size_t len;
           85 
           86         len = strlen(s) + 1;
           87         return memcpy(emalloc(len), s, len);
           88 }
           89 
           90 void
           91 sighandler(int signo)
           92 {
           93         stop = signo;
           94 }
           95 
           96 static void
           97 usage(void)
           98 {
           99         fputs("usage: make [-eiknprSstd] [-f file] [-j jobs] "
          100               "[macro=value ...] [target ...]\n",
          101               stderr);
          102         exit(EXIT_FAILURE);
          103 }
          104 
          105 static char *
          106 getarg(char **args, char ***argv)
          107 {
          108         char *s;
          109 
          110         if ((*args)[1]) {
          111                 s = (*args) + 1;
          112                 *args += strlen(*args) - 1;
          113                 return s;
          114         }
          115 
          116         if (!argv)
          117                 usage();
          118 
          119         if ((*argv)[1] == NULL)
          120                 usage();
          121         (*argv)++;
          122 
          123         return **argv;
          124 }
          125 
          126 static void
          127 appendmakeflags(char *text)
          128 {
          129         int n;
          130         char *s, *t, *fmt;
          131 
          132         s = getmacro("MAKEFLAGS");
          133         fmt = *s ? "%s %s" : "%s%s";
          134         n = snprintf(NULL, 0, fmt, s, text);
          135 
          136         t = emalloc(n+1);
          137         snprintf(t, n+1, fmt, s, text);
          138         setmacro("MAKEFLAGS", t, MAKEFLAGS, EXPORT);
          139 
          140         free(t);
          141 }
          142 
          143 static int
          144 hasargs(int c)
          145 {
          146         return c == 'f' || c == 'j';
          147 }
          148 
          149 static void
          150 parseflag(int flag, char **args, char ***argv)
          151 {
          152         if (hasargs(flag))
          153                 getarg(args, argv);
          154 
          155         switch (flag) {
          156         case 'j':
          157         case 'f':
          158                 break;
          159         case 'e':
          160                 eflag = 1;
          161                 appendmakeflags("-e");
          162                 break;
          163         case 'i':
          164                 iflag = 1;
          165                 appendmakeflags("-i");
          166                 break;
          167         case 'k':
          168                 kflag = 1;
          169                 appendmakeflags("-k");
          170                 break;
          171         case 'n':
          172                 nflag = 1;
          173                 appendmakeflags("-n");
          174                 break;
          175         case 'p':
          176                 pflag = 1;
          177                 break;
          178         case 'q':
          179                 qflag = 1;
          180                 appendmakeflags("-q");
          181                 break;
          182         case 'r':
          183                 addtarget(".SUFFIXES", 0);
          184                 appendmakeflags("-r");
          185                 break;        
          186         case 'S':
          187                 kflag = 0;
          188                 appendmakeflags("-S");
          189                 break;
          190         case 's':
          191                 sflag = 1;
          192                 appendmakeflags("-s");
          193                 break;
          194         case 't':
          195                 tflag = 1;
          196                 appendmakeflags("-t");
          197                 break;
          198         case 'd':
          199                 dflag = 1;
          200                 appendmakeflags("-d");
          201                 break;
          202         default:
          203                 usage();
          204         }
          205 }
          206 
          207 static int
          208 assign(char *s, int where, int export)
          209 {
          210         int pos;
          211         char *t;
          212 
          213         if ((t = strchr(s, '=')) == NULL)
          214                 return 0;
          215 
          216         pos = t - s;
          217 
          218         appendmakeflags(s);
          219         t = estrdup(s); 
          220         t[pos] = '\0';
          221 
          222         setmacro(t, t+pos+1, where, export);
          223         free(t);
          224         return 1;
          225 }
          226 
          227 static void
          228 parseargv(char **argv, char ***targets, int where, int export)
          229 {
          230         char *s;
          231         char *hm = NULL;
          232 
          233         for ( ; *argv; ++argv) {
          234                 s = *argv;
          235                 if (hm == NULL && strcmp(s, "--") == 0) {
          236                         hm = *argv;
          237                 } else if (hm && s[0] == '-') {
          238                         break;
          239                 } else if (s[0] != '-') {
          240                         if (!assign(s, where, export))
          241                                 break;
          242                         continue;
          243                 }
          244                 while (hm == NULL && *++s)
          245                         parseflag(*s, &s, &argv);
          246         }
          247 
          248         if (targets)
          249                 *targets = argv;
          250 }
          251 
          252 static void
          253 parsemakeflags(void)
          254 {
          255         int c, n;
          256         char *s, *flags, **arr;
          257 
          258         if ((flags = getenv("MAKEFLAGS")) == NULL)
          259                 return;
          260 
          261         setmacro("MAKEFLAGS", "", MAKEFLAGS, EXPORT);
          262 
          263         while (*flags == ' ' || *flags == '\t')
          264                 flags++;
          265 
          266         if (flags[0] != '-' && !strchr(flags, '=')) {
          267                 while (*flags) {
          268                         parseflag(*flags, &flags, NULL);
          269                         flags++;
          270                 }
          271         } else {
          272                 n = 0;
          273                 arr = NULL;
          274                 for (s = strtok(flags, " \t"); s; s = strtok(NULL, " \t")) {
          275                         n++;
          276                         arr = erealloc(arr, sizeof(char *) * (n+1));
          277                         arr[n-1] = s;
          278                         arr[n] = NULL;
          279                 }
          280 
          281                 if (arr)
          282                         parseargv(arr, NULL, MAKEFLAGS, NOEXPORT);
          283                 free(arr);
          284         }
          285 }
          286 
          287 static void
          288 parsemakefiles(char **argv)
          289 {
          290         char *s, *arg;
          291         int c, hasmake;
          292 
          293         hasmake = 0;
          294         for ( ; *argv && **argv == '-'; ++argv) {
          295                 for (s = *argv; c = *s; ++s) {
          296                         if (hasargs(c))
          297                                 arg = getarg(&s, &argv);
          298 
          299                         if (c == 'f') {
          300                                 if (strcmp(arg, "-") == 0)
          301                                         arg = NULL;
          302                                 parse(arg);
          303                                 hasmake = 1;
          304                         }
          305                 }
          306         }
          307 
          308         if (hasmake)
          309                 return;
          310 
          311         if (parse("makefile"))
          312                 return;
          313         if (parse("Makefile"))
          314                 return;
          315 }
          316 
          317 /*
          318  * We want to enable debug as earlier as possible,
          319  * if we wait until we read the Makefiles then
          320  * we are going to lose to much debug information.
          321  */
          322 static void
          323 enadebug(char *argv[])
          324 {
          325         int c;
          326         char *p;
          327 
          328         for ( ; *argv && **argv == '-'; ++argv) {
          329                 p = *argv;
          330                 for (++p; c = *p; ++p) {
          331                         if (hasargs(c))
          332                                 getarg(&p, &argv);
          333                         if (c == 'd')
          334                                 dflag = 1;
          335                 }
          336         }
          337 }
          338 
          339 int
          340 main(int argc, char *argv[])
          341 {
          342         char *arg0, **targets;
          343 
          344         signal(SIGINT, sighandler);
          345         signal(SIGHUP, sighandler);
          346         signal(SIGTERM, sighandler);
          347         signal(SIGQUIT, sighandler);
          348 
          349         targets = NULL;
          350         arg0 = *argv++;
          351 
          352         enadebug(argv);
          353         inject(defaults);
          354         setmacro("MAKE", arg0, MAKEFILE, NOEXPORT);
          355 
          356         parsemakeflags();
          357         parseargv(argv, &targets, CMDLINE, EXPORT);
          358         parsemakefiles(argv);
          359 
          360         if (pflag) {
          361                 dumpmacros();
          362                 dumprules();
          363                 exit(EXIT_SUCCESS);
          364         }
          365 
          366         if (!*targets) {
          367                 build(NULL);
          368         } else {
          369                 while (*targets)
          370                         build(*targets++);
          371         }
          372 
          373         exit(exitstatus);
          374 
          375         return 0;
          376 }