main.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
       ---
       main.c (5346B)
       ---
            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         killchild();
           94         stop = signo;
           95 }
           96 
           97 static void
           98 usage(void)
           99 {
          100         fputs("usage: make [-eiknprSstd] [-f file] [-j jobs] "
          101               "[macro=value ...] [target ...]\n",
          102               stderr);
          103         exit(EXIT_FAILURE);
          104 }
          105 
          106 static char *
          107 getarg(char **args, char ***argv)
          108 {
          109         char *s;
          110 
          111         if ((*args)[1]) {
          112                 s = (*args) + 1;
          113                 *args += strlen(*args) - 1;
          114                 return s;
          115         }
          116 
          117         if (!argv)
          118                 usage();
          119 
          120         if ((*argv)[1] == NULL)
          121                 usage();
          122         (*argv)++;
          123 
          124         return **argv;
          125 }
          126 
          127 static void
          128 appendmakeflags(char *text)
          129 {
          130         int n;
          131         char *s, *t, *fmt;
          132 
          133         s = getmacro("MAKEFLAGS");
          134         fmt = *s ? "%s %s" : "%s%s";
          135         n = snprintf(NULL, 0, fmt, s, text);
          136 
          137         t = emalloc(n+1);
          138         snprintf(t, n+1, fmt, s, text);
          139         setmacro("MAKEFLAGS", t, MAKEFLAGS, EXPORT);
          140 
          141         free(t);
          142 }
          143 
          144 static int
          145 hasargs(int c)
          146 {
          147         return c == 'f' || c == 'j';
          148 }
          149 
          150 static void
          151 parseflag(int flag, char **args, char ***argv)
          152 {
          153         if (hasargs(flag))
          154                 getarg(args, argv);
          155 
          156         switch (flag) {
          157         case 'j':
          158         case 'f':
          159                 break;
          160         case 'e':
          161                 eflag = 1;
          162                 appendmakeflags("-e");
          163                 break;
          164         case 'i':
          165                 iflag = 1;
          166                 appendmakeflags("-i");
          167                 break;
          168         case 'k':
          169                 kflag = 1;
          170                 appendmakeflags("-k");
          171                 break;
          172         case 'n':
          173                 nflag = 1;
          174                 appendmakeflags("-n");
          175                 break;
          176         case 'p':
          177                 pflag = 1;
          178                 break;
          179         case 'q':
          180                 qflag = 1;
          181                 appendmakeflags("-q");
          182                 break;
          183         case 'r':
          184                 addtarget(".SUFFIXES", 0);
          185                 appendmakeflags("-r");
          186                 break;        
          187         case 'S':
          188                 kflag = 0;
          189                 appendmakeflags("-S");
          190                 break;
          191         case 's':
          192                 sflag = 1;
          193                 appendmakeflags("-s");
          194                 break;
          195         case 't':
          196                 tflag = 1;
          197                 appendmakeflags("-t");
          198                 break;
          199         case 'd':
          200                 dflag = 1;
          201                 appendmakeflags("-d");
          202                 break;
          203         default:
          204                 usage();
          205         }
          206 }
          207 
          208 static int
          209 assign(char *s, int where, int export)
          210 {
          211         int pos;
          212         char *t;
          213 
          214         if ((t = strchr(s, '=')) == NULL)
          215                 return 0;
          216 
          217         pos = t - s;
          218 
          219         appendmakeflags(s);
          220         t = estrdup(s); 
          221         t[pos] = '\0';
          222 
          223         setmacro(t, t+pos+1, where, export);
          224         free(t);
          225         return 1;
          226 }
          227 
          228 static void
          229 parseargv(char **argv, char ***targets, int where, int export)
          230 {
          231         char *s;
          232         char *hm = NULL;
          233 
          234         for ( ; *argv; ++argv) {
          235                 s = *argv;
          236                 if (hm == NULL && strcmp(s, "--") == 0) {
          237                         hm = *argv;
          238                 } else if (hm && s[0] == '-') {
          239                         break;
          240                 } else if (s[0] != '-') {
          241                         if (!assign(s, where, export))
          242                                 break;
          243                         continue;
          244                 }
          245                 while (hm == NULL && *++s)
          246                         parseflag(*s, &s, &argv);
          247         }
          248 
          249         if (targets)
          250                 *targets = argv;
          251 }
          252 
          253 static void
          254 parsemakeflags(void)
          255 {
          256         int c, n;
          257         char *s, *flags, **arr;
          258 
          259         if ((flags = getenv("MAKEFLAGS")) == NULL)
          260                 return;
          261 
          262         setmacro("MAKEFLAGS", "", MAKEFLAGS, EXPORT);
          263 
          264         while (*flags == ' ' || *flags == '\t')
          265                 flags++;
          266 
          267         if (flags[0] != '-' && !strchr(flags, '=')) {
          268                 while (*flags) {
          269                         parseflag(*flags, &flags, NULL);
          270                         flags++;
          271                 }
          272         } else {
          273                 n = 0;
          274                 arr = NULL;
          275                 for (s = strtok(flags, " \t"); s; s = strtok(NULL, " \t")) {
          276                         n++;
          277                         arr = erealloc(arr, sizeof(char *) * (n+1));
          278                         arr[n-1] = s;
          279                         arr[n] = NULL;
          280                 }
          281 
          282                 if (arr)
          283                         parseargv(arr, NULL, MAKEFLAGS, NOEXPORT);
          284                 free(arr);
          285         }
          286 }
          287 
          288 static void
          289 parsemakefiles(char **argv)
          290 {
          291         char *s, *arg;
          292         int c, hasmake;
          293 
          294         hasmake = 0;
          295         for ( ; *argv && **argv == '-'; ++argv) {
          296                 for (s = *argv; c = *s; ++s) {
          297                         if (hasargs(c))
          298                                 arg = getarg(&s, &argv);
          299 
          300                         if (c == 'f') {
          301                                 if (strcmp(arg, "-") == 0)
          302                                         arg = NULL;
          303                                 parse(arg);
          304                                 hasmake = 1;
          305                         }
          306                 }
          307         }
          308 
          309         if (hasmake)
          310                 return;
          311 
          312         if (parse("makefile"))
          313                 return;
          314         if (parse("Makefile"))
          315                 return;
          316 }
          317 
          318 /*
          319  * We want to enable debug as earlier as possible,
          320  * if we wait until we read the Makefiles then
          321  * we are going to lose to much debug information.
          322  */
          323 static void
          324 enadebug(char *argv[])
          325 {
          326         int c;
          327         char *p;
          328 
          329         for ( ; *argv && **argv == '-'; ++argv) {
          330                 p = *argv;
          331                 for (++p; c = *p; ++p) {
          332                         if (hasargs(c))
          333                                 getarg(&p, &argv);
          334                         if (c == 'd')
          335                                 dflag = 1;
          336                 }
          337         }
          338 }
          339 
          340 int
          341 main(int argc, char *argv[])
          342 {
          343         char *arg0, **targets;
          344 
          345         signal(SIGINT, sighandler);
          346         signal(SIGHUP, sighandler);
          347         signal(SIGTERM, sighandler);
          348         signal(SIGQUIT, sighandler);
          349 
          350         targets = NULL;
          351         arg0 = *argv++;
          352 
          353         enadebug(argv);
          354         inject(defaults);
          355         setmacro("MAKE", arg0, MAKEFILE, NOEXPORT);
          356 
          357         parsemakeflags();
          358         parseargv(argv, &targets, CMDLINE, EXPORT);
          359         parsemakefiles(argv);
          360 
          361         if (pflag) {
          362                 dumpmacros();
          363                 dumprules();
          364                 exit(EXIT_SUCCESS);
          365         }
          366 
          367         if (!*targets) {
          368                 build(NULL);
          369         } else {
          370                 while (*targets)
          371                         build(*targets++);
          372         }
          373 
          374         exit(exitstatus);
          375 
          376         return 0;
          377 }