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 }