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 }