scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | 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 }