Home
       main.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
       main.c (4529B)
       ---
            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 static 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;
          131 
          132         s = getmacro("MAKEFLAGS");
          133         n = snprintf(NULL, 0, "%s %s", s, text);
          134 
          135         t = emalloc(n+1);
          136         snprintf(t, n+1, "%s %s", s, text);
          137         setmacro("MAKEFLAGS", t, EXPORT);
          138 
          139         free(t);
          140 }
          141 
          142 static void
          143 parseflag(int flag, char **args, char ***argv)
          144 {
          145         char *arg;
          146 
          147         switch (flag) {
          148         case 'j':
          149         case 'f':
          150                 getarg(args, argv);
          151                 break;
          152         case 'e':
          153                 eflag = 1;
          154                 appendmakeflags("-e");
          155                 break;
          156         case 'i':
          157                 iflag = 1;
          158                 appendmakeflags("-i");
          159                 break;
          160         case 'k':
          161                 kflag = 1;
          162                 appendmakeflags("-k");
          163                 break;
          164         case 'n':
          165                 nflag = 1;
          166                 appendmakeflags("-n");
          167                 break;
          168         case 'p':
          169                 pflag = 1;
          170                 break;
          171         case 'q':
          172                 qflag = 1;
          173                 appendmakeflags("-q");
          174                 break;
          175         case 'r':
          176                 addtarget(".SUFFIXES", 0);
          177                 appendmakeflags("-r");
          178                 break;        
          179         case 'S':
          180                 kflag = 0;
          181                 appendmakeflags("-S");
          182                 break;
          183         case 's':
          184                 sflag = 1;
          185                 appendmakeflags("-s");
          186                 break;
          187         case 't':
          188                 tflag = 1;
          189                 appendmakeflags("-t");
          190                 break;
          191         case 'd':
          192                 dflag = 1;
          193                 appendmakeflags("-d");
          194                 break;
          195         default:
          196                 usage();
          197         }
          198 }
          199 
          200 static int
          201 assign(char *s, int export)
          202 {
          203         int pos;
          204         char *t;
          205 
          206         if ((t = strchr(s, '=')) == NULL)
          207                 return 0;
          208 
          209         pos = t - s;
          210 
          211         appendmakeflags(s);
          212         t = estrdup(s); 
          213         t[pos] = '\0';
          214 
          215         setmacro(t, t+pos+1, export);
          216         free(t);
          217         return 1;
          218 }
          219 
          220 static void
          221 parseargv(char **argv, char ***targets, int export)
          222 {
          223         char *s;
          224 
          225         for ( ; *argv; ++argv) {
          226                 s = *argv;
          227                 if (s[0] != '-') {
          228                         if (!assign(s, export))
          229                                 break;
          230                         continue;
          231                 }
          232                 while (*++s)
          233                         parseflag(*s, &s, &argv);
          234         }
          235 
          236         if (targets)
          237                 *targets = argv;
          238 }
          239 
          240 static void
          241 parsemakeflags(void)
          242 {
          243         int c, n;
          244         char *s, *flags, **arr;
          245 
          246         if ((flags = getenv("MAKEFLAGS")) == NULL)
          247                 return;
          248 
          249         setmacro("MAKEFLAGS", "", EXPORT);
          250 
          251         while (*flags == ' ' || *flags == '\t')
          252                 flags++;
          253 
          254         if (flags[0] != '-') {
          255                 while (*flags) {
          256                         parseflag(*flags, &flags, NULL);
          257                         flags++;
          258                 }
          259         } else {
          260                 n = 0;
          261                 arr = NULL;
          262                 for (s = strtok(flags, " \t"); s; s = strtok(NULL, " \t")) {
          263                         n++;
          264                         arr = erealloc(arr, sizeof(char *) * (n+1));
          265                         arr[n-1] = s;
          266                         arr[n] = NULL;
          267                 }
          268 
          269                 parseargv(arr, NULL, NOEXPORT);
          270                 free(arr);
          271         }
          272 }
          273 
          274 static void
          275 parsemakefiles(char **argv)
          276 {
          277         char *s, *arg;
          278         int c, hasmake;
          279 
          280         hasmake = 0;
          281         for ( ; *argv && **argv == '-'; ++argv) {
          282                 for (s = *argv; c = *s; ++s) {
          283                         if (c == 'f' || c == 'j')
          284                                 arg = getarg(&s, &argv);
          285 
          286                         if (c == 'f') {
          287                                 if (strcmp(arg, "-") == 0)
          288                                         arg = NULL;
          289                                 parse(arg);
          290                                 hasmake = 1;
          291                         }
          292                 }
          293         }
          294 
          295         if (hasmake)
          296                 return;
          297 
          298         if (parse("makefile"))
          299                 return;
          300         if (parse("Makefile"))
          301                 return;
          302 }
          303 
          304 int
          305 main(int argc, char *argv[])
          306 {
          307         char *arg0;
          308 
          309         signal(SIGINT, sighandler);
          310         signal(SIGHUP, sighandler);
          311         signal(SIGTERM, sighandler);
          312         signal(SIGQUIT, sighandler);
          313 
          314         arg0 = *argv++;
          315 
          316         inject(defaults);
          317         parsemakefiles(argv);
          318         parsemakeflags();
          319         parseargv(argv, &argv, EXPORT);
          320 
          321         setmacro("MAKE", arg0, NOEXPORT);
          322 
          323         if (pflag) {
          324                 dumpmacros();
          325                 dumprules();
          326         }
          327 
          328         if (!*argv) {
          329                 build(NULL);
          330         } else {
          331                 while (*argv)
          332                         build(*argv++);
          333         }
          334 
          335         exit(exitstatus);
          336 
          337         return 0;
          338 }