main.c (5175B)
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, *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 232 for ( ; *argv; ++argv) { 233 s = *argv; 234 if (s[0] != '-') { 235 if (!assign(s, where, export)) 236 break; 237 continue; 238 } 239 while (*++s) 240 parseflag(*s, &s, &argv); 241 } 242 243 if (targets) 244 *targets = argv; 245 } 246 247 static void 248 parsemakeflags(void) 249 { 250 int c, n; 251 char *s, *flags, **arr; 252 253 if ((flags = getenv("MAKEFLAGS")) == NULL) 254 return; 255 256 setmacro("MAKEFLAGS", "", MAKEFLAGS, EXPORT); 257 258 while (*flags == ' ' || *flags == '\t') 259 flags++; 260 261 if (flags[0] != '-' && !strchr(flags, '=')) { 262 while (*flags) { 263 parseflag(*flags, &flags, NULL); 264 flags++; 265 } 266 } else { 267 n = 0; 268 arr = NULL; 269 for (s = strtok(flags, " \t"); s; s = strtok(NULL, " \t")) { 270 n++; 271 arr = erealloc(arr, sizeof(char *) * (n+1)); 272 arr[n-1] = s; 273 arr[n] = NULL; 274 } 275 276 if (arr) 277 parseargv(arr, NULL, MAKEFLAGS, NOEXPORT); 278 free(arr); 279 } 280 } 281 282 static void 283 parsemakefiles(char **argv) 284 { 285 char *s, *arg; 286 int c, hasmake; 287 288 hasmake = 0; 289 for ( ; *argv && **argv == '-'; ++argv) { 290 for (s = *argv; c = *s; ++s) { 291 if (hasargs(c)) 292 arg = getarg(&s, &argv); 293 294 if (c == 'f') { 295 if (strcmp(arg, "-") == 0) 296 arg = NULL; 297 parse(arg); 298 hasmake = 1; 299 } 300 } 301 } 302 303 if (hasmake) 304 return; 305 306 if (parse("makefile")) 307 return; 308 if (parse("Makefile")) 309 return; 310 } 311 312 /* 313 * We want to enable debug as earlier as possible, 314 * if we wait until we read the Makefiles then 315 * we are going to lose to much debug information. 316 */ 317 static void 318 enadebug(char *argv[]) 319 { 320 int c; 321 char *p; 322 323 for ( ; *argv && **argv == '-'; ++argv) { 324 p = *argv; 325 for (++p; c = *p; ++p) { 326 if (hasargs(c)) 327 getarg(&p, &argv); 328 if (c == 'd') 329 dflag = 1; 330 } 331 } 332 } 333 334 int 335 main(int argc, char *argv[]) 336 { 337 char *arg0, **targets; 338 339 signal(SIGINT, sighandler); 340 signal(SIGHUP, sighandler); 341 signal(SIGTERM, sighandler); 342 signal(SIGQUIT, sighandler); 343 344 targets = NULL; 345 arg0 = *argv++; 346 347 enadebug(argv); 348 inject(defaults); 349 setmacro("MAKE", arg0, MAKEFILE, NOEXPORT); 350 351 parsemakeflags(); 352 parseargv(argv, &targets, CMDLINE, EXPORT); 353 parsemakefiles(argv); 354 355 if (pflag) { 356 dumpmacros(); 357 dumprules(); 358 } 359 360 if (!*targets) { 361 build(NULL); 362 } else { 363 while (*targets) 364 build(*targets++); 365 } 366 367 exit(exitstatus); 368 369 return 0; 370 }