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