xref: /plan9-contrib/sys/src/cmd/mk/main.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include	"mk.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier #define		MKFILE		"mkfile"
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier static char *version = "@(#)mk general release 4 (plan 9)";
63e12c5d1SDavid du Colombier int debug;
73e12c5d1SDavid du Colombier Rule *rules, *metarules;
83e12c5d1SDavid du Colombier int nproclimit;
93e12c5d1SDavid du Colombier int nflag = 0;
103e12c5d1SDavid du Colombier int tflag = 0;
113e12c5d1SDavid du Colombier int iflag = 0;
123e12c5d1SDavid du Colombier int kflag = 0;
133e12c5d1SDavid du Colombier int aflag = 0;
14*219b2ee8SDavid du Colombier int uflag = 0;
153e12c5d1SDavid du Colombier char *explain = 0;
163e12c5d1SDavid du Colombier Word *target1;
173e12c5d1SDavid du Colombier int nreps = 1;
183e12c5d1SDavid du Colombier Job *jobs;
193e12c5d1SDavid du Colombier char shell[] = SHELL;
203e12c5d1SDavid du Colombier char shellname[] = SHELL;
213e12c5d1SDavid du Colombier Biobuf stdout;
223e12c5d1SDavid du Colombier Rule *patrule;
23*219b2ee8SDavid du Colombier void badusage(void);
243e12c5d1SDavid du Colombier #ifdef	PROF
253e12c5d1SDavid du Colombier short buf[10000];
263e12c5d1SDavid du Colombier #endif	PROF
273e12c5d1SDavid du Colombier 
283e12c5d1SDavid du Colombier void
293e12c5d1SDavid du Colombier main(int argc, char **argv)
303e12c5d1SDavid du Colombier {
313e12c5d1SDavid du Colombier 	Word *w;
323e12c5d1SDavid du Colombier 	char *s;
333e12c5d1SDavid du Colombier 	char *files[256], **f = files, **ff;
343e12c5d1SDavid du Colombier 	int sflag = 0;
353e12c5d1SDavid du Colombier 	int i;
363e12c5d1SDavid du Colombier 	int tfd = -1;
373e12c5d1SDavid du Colombier 	Biobuf tb;
383e12c5d1SDavid du Colombier 	Bufblock *buf;
39*219b2ee8SDavid du Colombier 	Bufblock *whatif;
403e12c5d1SDavid du Colombier 	static char temp[] = "/tmp/mkargXXXXXX";
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	/*
433e12c5d1SDavid du Colombier 	 *  start with a copy of the current environment variables
443e12c5d1SDavid du Colombier 	 *  instead of sharing them
453e12c5d1SDavid du Colombier 	 */
463e12c5d1SDavid du Colombier 	rfork(RFENVG);
473e12c5d1SDavid du Colombier 
483e12c5d1SDavid du Colombier 	Binit(&stdout, 1, OWRITE);
493e12c5d1SDavid du Colombier 	buf = newbuf();
50*219b2ee8SDavid du Colombier 	whatif = 0;
513e12c5d1SDavid du Colombier 	USED(argc);
523e12c5d1SDavid du Colombier 	for(argv++; *argv && (**argv == '-'); argv++)
533e12c5d1SDavid du Colombier 	{
543e12c5d1SDavid du Colombier 		bufcpy(buf, argv[0], strlen(argv[0]));
553e12c5d1SDavid du Colombier 		insert(buf, ' ');
563e12c5d1SDavid du Colombier 		switch(argv[0][1])
573e12c5d1SDavid du Colombier 		{
583e12c5d1SDavid du Colombier 		case 'a':
593e12c5d1SDavid du Colombier 			aflag = 1;
603e12c5d1SDavid du Colombier 			break;
613e12c5d1SDavid du Colombier 		case 'd':
623e12c5d1SDavid du Colombier 			if(*(s = &argv[0][2]))
633e12c5d1SDavid du Colombier 				while(*s) switch(*s++)
643e12c5d1SDavid du Colombier 				{
653e12c5d1SDavid du Colombier 				case 'p':	debug |= D_PARSE; break;
663e12c5d1SDavid du Colombier 				case 'g':	debug |= D_GRAPH; break;
673e12c5d1SDavid du Colombier 				case 'e':	debug |= D_EXEC; break;
683e12c5d1SDavid du Colombier 				}
693e12c5d1SDavid du Colombier 			else
703e12c5d1SDavid du Colombier 				debug = 0xFFFF;
713e12c5d1SDavid du Colombier 			break;
723e12c5d1SDavid du Colombier 		case 'e':
733e12c5d1SDavid du Colombier 			explain = &argv[0][2];
743e12c5d1SDavid du Colombier 			break;
753e12c5d1SDavid du Colombier 		case 'f':
763e12c5d1SDavid du Colombier 			if(*++argv == 0)
77*219b2ee8SDavid du Colombier 				badusage();
783e12c5d1SDavid du Colombier 			*f++ = *argv;
793e12c5d1SDavid du Colombier 			bufcpy(buf, argv[0], strlen(argv[0]));
803e12c5d1SDavid du Colombier 			insert(buf, ' ');
813e12c5d1SDavid du Colombier 			break;
823e12c5d1SDavid du Colombier 		case 'i':
833e12c5d1SDavid du Colombier 			iflag = 1;
843e12c5d1SDavid du Colombier 			break;
853e12c5d1SDavid du Colombier 		case 'k':
863e12c5d1SDavid du Colombier 			kflag = 1;
873e12c5d1SDavid du Colombier 			break;
883e12c5d1SDavid du Colombier 		case 'n':
893e12c5d1SDavid du Colombier 			nflag = 1;
903e12c5d1SDavid du Colombier 			break;
913e12c5d1SDavid du Colombier 		case 's':
923e12c5d1SDavid du Colombier 			sflag = 1;
933e12c5d1SDavid du Colombier 			break;
943e12c5d1SDavid du Colombier 		case 't':
953e12c5d1SDavid du Colombier 			tflag = 1;
963e12c5d1SDavid du Colombier 			break;
97*219b2ee8SDavid du Colombier 		case 'u':
98*219b2ee8SDavid du Colombier 			uflag = 1;
99*219b2ee8SDavid du Colombier 			break;
1003e12c5d1SDavid du Colombier 		case 'w':
101*219b2ee8SDavid du Colombier 			if(whatif == 0)
102*219b2ee8SDavid du Colombier 				whatif = newbuf();
103*219b2ee8SDavid du Colombier 			else
104*219b2ee8SDavid du Colombier 				insert(whatif, ' ');
1053e12c5d1SDavid du Colombier 			if(argv[0][2])
106*219b2ee8SDavid du Colombier 				bufcpy(whatif, &argv[0][2], strlen(&argv[0][2]));
1073e12c5d1SDavid du Colombier 			else {
1083e12c5d1SDavid du Colombier 				if(*++argv == 0)
109*219b2ee8SDavid du Colombier 					badusage();
110*219b2ee8SDavid du Colombier 				bufcpy(whatif, &argv[0][0], strlen(&argv[0][0]));
1113e12c5d1SDavid du Colombier 			}
1123e12c5d1SDavid du Colombier 			break;
1133e12c5d1SDavid du Colombier 		default:
114*219b2ee8SDavid du Colombier 			badusage();
1153e12c5d1SDavid du Colombier 		}
1163e12c5d1SDavid du Colombier 	}
1173e12c5d1SDavid du Colombier #ifdef	PROF
1183e12c5d1SDavid du Colombier 	{
1193e12c5d1SDavid du Colombier 		extern etext();
1203e12c5d1SDavid du Colombier 		monitor(main, etext, buf, sizeof buf, 300);
1213e12c5d1SDavid du Colombier 	}
1223e12c5d1SDavid du Colombier #endif	PROF
1233e12c5d1SDavid du Colombier 
1243e12c5d1SDavid du Colombier 	if(aflag)
1253e12c5d1SDavid du Colombier 		iflag = 1;
126*219b2ee8SDavid du Colombier 	usage();
1273e12c5d1SDavid du Colombier 	for(i = strlen(shell)-1; i >= 0; i--)
1283e12c5d1SDavid du Colombier 			if(shell[i] == '/')
1293e12c5d1SDavid du Colombier 				break;
1303e12c5d1SDavid du Colombier 	strcpy(shellname, shell+i+1);
1313e12c5d1SDavid du Colombier 	syminit();
1323e12c5d1SDavid du Colombier 	initenv();
133*219b2ee8SDavid du Colombier 	usage();
1343e12c5d1SDavid du Colombier 
1353e12c5d1SDavid du Colombier 	/*
1363e12c5d1SDavid du Colombier 		assignment args become null strings
1373e12c5d1SDavid du Colombier 	*/
1383e12c5d1SDavid du Colombier 	for(i = 0; argv[i]; i++) if(utfrune(argv[i], '=')){
1393e12c5d1SDavid du Colombier 		bufcpy(buf, argv[i], strlen(argv[i]));
1403e12c5d1SDavid du Colombier 		insert(buf, ' ');
1413e12c5d1SDavid du Colombier 		if(tfd < 0){
1423e12c5d1SDavid du Colombier 			mktemp(temp);
143*219b2ee8SDavid du Colombier 			close(create(temp, OWRITE, 0600));
1443e12c5d1SDavid du Colombier 			if((tfd = open(temp, 2)) < 0){
1453e12c5d1SDavid du Colombier 				perror(temp);
1463e12c5d1SDavid du Colombier 				Exit();
1473e12c5d1SDavid du Colombier 			}
1483e12c5d1SDavid du Colombier 			Binit(&tb, tfd, OWRITE);
1493e12c5d1SDavid du Colombier 		}
1503e12c5d1SDavid du Colombier 		Bprint(&tb, "%s\n", argv[i]);
1513e12c5d1SDavid du Colombier 		*argv[i] = 0;
1523e12c5d1SDavid du Colombier 	}
1533e12c5d1SDavid du Colombier 	if(tfd >= 0){
1543e12c5d1SDavid du Colombier 		Bflush(&tb);
1553e12c5d1SDavid du Colombier 		LSEEK(tfd, 0L, 0);
1563e12c5d1SDavid du Colombier 		parse("command line args", tfd, 1, 1);
157*219b2ee8SDavid du Colombier 		remove(temp);
1583e12c5d1SDavid du Colombier 	}
1593e12c5d1SDavid du Colombier 
1603e12c5d1SDavid du Colombier 	if (buf->current != buf->start) {
1613e12c5d1SDavid du Colombier 		buf->current--;
1623e12c5d1SDavid du Colombier 		insert(buf, 0);
1633e12c5d1SDavid du Colombier 	}
1643e12c5d1SDavid du Colombier 	symlook("MKFLAGS", S_VAR, (char *) stow(buf->start));
1653e12c5d1SDavid du Colombier 	buf->current = buf->start;
1663e12c5d1SDavid du Colombier 	for(i = 0; argv[i]; i++){
1673e12c5d1SDavid du Colombier 		if(*argv[i] == 0) continue;
1683e12c5d1SDavid du Colombier 		if(i)
1693e12c5d1SDavid du Colombier 			insert(buf, ' ');
1703e12c5d1SDavid du Colombier 		bufcpy(buf, argv[i], strlen(argv[i]));
1713e12c5d1SDavid du Colombier 	}
1723e12c5d1SDavid du Colombier 	insert(buf, 0);
1733e12c5d1SDavid du Colombier 	symlook("MKARGS", S_VAR, (char *) stow(buf->start));
1743e12c5d1SDavid du Colombier 	freebuf(buf);
1753e12c5d1SDavid du Colombier 
1763e12c5d1SDavid du Colombier 	if(f == files){
1773e12c5d1SDavid du Colombier 		if(access(MKFILE, 4) == 0)
1783e12c5d1SDavid du Colombier 			parse(MKFILE, open(MKFILE, 0), 0, 1);
1793e12c5d1SDavid du Colombier 	} else
1803e12c5d1SDavid du Colombier 		for(ff = files; ff < f; ff++)
1813e12c5d1SDavid du Colombier 			parse(*ff, open(*ff, 0), 0, 1);
1823e12c5d1SDavid du Colombier 	if(DEBUG(D_PARSE)){
1833e12c5d1SDavid du Colombier 		dumpw("default targets", target1);
1843e12c5d1SDavid du Colombier 		dumpr("rules", rules);
1853e12c5d1SDavid du Colombier 		dumpr("metarules", metarules);
1863e12c5d1SDavid du Colombier 		dumpv("variables");
1873e12c5d1SDavid du Colombier 	}
188*219b2ee8SDavid du Colombier 	if(whatif){
189*219b2ee8SDavid du Colombier 		insert(whatif, 0);
190*219b2ee8SDavid du Colombier 		timeinit(whatif->start);
191*219b2ee8SDavid du Colombier 		freebuf(whatif);
192*219b2ee8SDavid du Colombier 	}
1933e12c5d1SDavid du Colombier 	execinit();
1943e12c5d1SDavid du Colombier 	/* skip assignment args */
1953e12c5d1SDavid du Colombier 	while(*argv && (**argv == 0))
1963e12c5d1SDavid du Colombier 		argv++;
197*219b2ee8SDavid du Colombier 
198*219b2ee8SDavid du Colombier 	atnotify(notifyf, 1);
1993e12c5d1SDavid du Colombier 	if(*argv == 0){
2003e12c5d1SDavid du Colombier 		if(target1)
2013e12c5d1SDavid du Colombier 			for(w = target1; w; w = w->next)
2023e12c5d1SDavid du Colombier 				mk(w->s);
2033e12c5d1SDavid du Colombier 		else {
2043e12c5d1SDavid du Colombier 			fprint(2, "mk: nothing to mk\n");
2053e12c5d1SDavid du Colombier 			Exit();
2063e12c5d1SDavid du Colombier 		}
2073e12c5d1SDavid du Colombier 	} else {
2083e12c5d1SDavid du Colombier 		if(sflag){
2093e12c5d1SDavid du Colombier 			for(; *argv; argv++)
2103e12c5d1SDavid du Colombier 				if(**argv)
2113e12c5d1SDavid du Colombier 					mk(*argv);
2123e12c5d1SDavid du Colombier 		} else {
2133e12c5d1SDavid du Colombier 			Word *head, *tail, *t;
2143e12c5d1SDavid du Colombier 
2153e12c5d1SDavid du Colombier 			/* fake a new rule with all the args as prereqs */
2163e12c5d1SDavid du Colombier 			tail = 0;
217*219b2ee8SDavid du Colombier 			t = 0;
2183e12c5d1SDavid du Colombier 			for(; *argv; argv++)
2193e12c5d1SDavid du Colombier 				if(**argv){
2203e12c5d1SDavid du Colombier 					if(tail == 0)
2213e12c5d1SDavid du Colombier 						tail = t = newword(*argv);
2223e12c5d1SDavid du Colombier 					else {
2233e12c5d1SDavid du Colombier 						t->next = newword(*argv);
2243e12c5d1SDavid du Colombier 						t = t->next;
2253e12c5d1SDavid du Colombier 					}
2263e12c5d1SDavid du Colombier 				}
2273e12c5d1SDavid du Colombier 			if(tail->next == 0)
2283e12c5d1SDavid du Colombier 				mk(tail->s);
2293e12c5d1SDavid du Colombier 			else {
2303e12c5d1SDavid du Colombier 				head = newword("command line arguments");
2313e12c5d1SDavid du Colombier 				addrules(head, tail, strdup(""), VIR, inline, 1, (char *)0);
2323e12c5d1SDavid du Colombier 				mk(head->s);
2333e12c5d1SDavid du Colombier 			}
2343e12c5d1SDavid du Colombier 		}
2353e12c5d1SDavid du Colombier 	}
236*219b2ee8SDavid du Colombier 	if(uflag)
237*219b2ee8SDavid du Colombier 		prusage();
2383e12c5d1SDavid du Colombier 	exits(0);
2393e12c5d1SDavid du Colombier }
2403e12c5d1SDavid du Colombier 
2413e12c5d1SDavid du Colombier void
242*219b2ee8SDavid du Colombier badusage(void)
2433e12c5d1SDavid du Colombier {
2443e12c5d1SDavid du Colombier 
2453e12c5d1SDavid du Colombier 	fprint(2, "Usage: mk [-f file] [-n] [-a] [-e] [-t] [-k] [-i] [-d[egp]] [targets ...]\n");
2463e12c5d1SDavid du Colombier 	Exit();
2473e12c5d1SDavid du Colombier }
2483e12c5d1SDavid du Colombier 
2493e12c5d1SDavid du Colombier char *
2503e12c5d1SDavid du Colombier Malloc(int n)
2513e12c5d1SDavid du Colombier {
2523e12c5d1SDavid du Colombier 	register char *s;
2533e12c5d1SDavid du Colombier 
254*219b2ee8SDavid du Colombier 	s = malloc(n);
255*219b2ee8SDavid du Colombier 	if(!s) {
2563e12c5d1SDavid du Colombier 		fprint(2, "mk: cannot alloc %d bytes\n", n);
2573e12c5d1SDavid du Colombier 		Exit();
258*219b2ee8SDavid du Colombier 	}
259*219b2ee8SDavid du Colombier 	return(s);
2603e12c5d1SDavid du Colombier }
2613e12c5d1SDavid du Colombier 
2623e12c5d1SDavid du Colombier char *
2633e12c5d1SDavid du Colombier Realloc(char *s, int n)
2643e12c5d1SDavid du Colombier {
265*219b2ee8SDavid du Colombier 	s = realloc(s, n);
266*219b2ee8SDavid du Colombier 	if(!s) {
2673e12c5d1SDavid du Colombier 		fprint(2, "mk: cannot alloc %d bytes\n", n);
2683e12c5d1SDavid du Colombier 		Exit();
269*219b2ee8SDavid du Colombier 	}
270*219b2ee8SDavid du Colombier 	return(s);
2713e12c5d1SDavid du Colombier }
2723e12c5d1SDavid du Colombier 
2733e12c5d1SDavid du Colombier void
2743e12c5d1SDavid du Colombier Exit(void)
2753e12c5d1SDavid du Colombier {
2763e12c5d1SDavid du Colombier 	while(wait(0) >= 0)
2773e12c5d1SDavid du Colombier 		;
2783e12c5d1SDavid du Colombier 	exits("error");
2793e12c5d1SDavid du Colombier }
2803e12c5d1SDavid du Colombier 
2813e12c5d1SDavid du Colombier /*
2823e12c5d1SDavid du Colombier char *
2833e12c5d1SDavid du Colombier strndup(char *s, unsigned n)
2843e12c5d1SDavid du Colombier {
2853e12c5d1SDavid du Colombier 	register char *goo;
2863e12c5d1SDavid du Colombier 
2873e12c5d1SDavid du Colombier 	goo = Malloc(n);
2883e12c5d1SDavid du Colombier 	memmove(goo, s, (COUNT)n);
2893e12c5d1SDavid du Colombier 	return(goo);
2903e12c5d1SDavid du Colombier }
2913e12c5d1SDavid du Colombier */
2923e12c5d1SDavid du Colombier 
2933e12c5d1SDavid du Colombier void
2943e12c5d1SDavid du Colombier assert(char *s, int n)
2953e12c5d1SDavid du Colombier {
2963e12c5d1SDavid du Colombier 	if(!n){
2973e12c5d1SDavid du Colombier 		fprint(2, "mk: Assertion ``%s'' failed.\n", s);
2983e12c5d1SDavid du Colombier 		Exit();
2993e12c5d1SDavid du Colombier 	}
3003e12c5d1SDavid du Colombier }
3013e12c5d1SDavid du Colombier 
3023e12c5d1SDavid du Colombier void
3033e12c5d1SDavid du Colombier regerror(char *s)
3043e12c5d1SDavid du Colombier {
3053e12c5d1SDavid du Colombier 	if(patrule)
3063e12c5d1SDavid du Colombier 		fprint(2, "mk: %s:%d: regular expression error; %s\n",
3073e12c5d1SDavid du Colombier 			patrule->file, patrule->line, s);
3083e12c5d1SDavid du Colombier 	else
3093e12c5d1SDavid du Colombier 		fprint(2, "mk: %s:%d: regular expression error; %s\n",
3103e12c5d1SDavid du Colombier 			infile, inline, s);
3113e12c5d1SDavid du Colombier 	Exit();
3123e12c5d1SDavid du Colombier }
313