xref: /plan9-contrib/sys/src/cmd/mk/main.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include	"mk.h"
2 
3 #define		MKFILE		"mkfile"
4 
5 static char *version = "@(#)mk general release 4 (plan 9)";
6 int debug;
7 Rule *rules, *metarules;
8 int nproclimit;
9 int nflag = 0;
10 int tflag = 0;
11 int iflag = 0;
12 int kflag = 0;
13 int aflag = 0;
14 int uflag = 0;
15 char *explain = 0;
16 Word *target1;
17 int nreps = 1;
18 Job *jobs;
19 char shell[] = SHELL;
20 char shellname[] = SHELL;
21 Biobuf stdout;
22 Rule *patrule;
23 void badusage(void);
24 #ifdef	PROF
25 short buf[10000];
26 #endif	PROF
27 
28 void
29 main(int argc, char **argv)
30 {
31 	Word *w;
32 	char *s;
33 	char *files[256], **f = files, **ff;
34 	int sflag = 0;
35 	int i;
36 	int tfd = -1;
37 	Biobuf tb;
38 	Bufblock *buf;
39 	Bufblock *whatif;
40 	static char temp[] = "/tmp/mkargXXXXXX";
41 
42 	/*
43 	 *  start with a copy of the current environment variables
44 	 *  instead of sharing them
45 	 */
46 	rfork(RFENVG);
47 
48 	Binit(&stdout, 1, OWRITE);
49 	buf = newbuf();
50 	whatif = 0;
51 	USED(argc);
52 	for(argv++; *argv && (**argv == '-'); argv++)
53 	{
54 		bufcpy(buf, argv[0], strlen(argv[0]));
55 		insert(buf, ' ');
56 		switch(argv[0][1])
57 		{
58 		case 'a':
59 			aflag = 1;
60 			break;
61 		case 'd':
62 			if(*(s = &argv[0][2]))
63 				while(*s) switch(*s++)
64 				{
65 				case 'p':	debug |= D_PARSE; break;
66 				case 'g':	debug |= D_GRAPH; break;
67 				case 'e':	debug |= D_EXEC; break;
68 				}
69 			else
70 				debug = 0xFFFF;
71 			break;
72 		case 'e':
73 			explain = &argv[0][2];
74 			break;
75 		case 'f':
76 			if(*++argv == 0)
77 				badusage();
78 			*f++ = *argv;
79 			bufcpy(buf, argv[0], strlen(argv[0]));
80 			insert(buf, ' ');
81 			break;
82 		case 'i':
83 			iflag = 1;
84 			break;
85 		case 'k':
86 			kflag = 1;
87 			break;
88 		case 'n':
89 			nflag = 1;
90 			break;
91 		case 's':
92 			sflag = 1;
93 			break;
94 		case 't':
95 			tflag = 1;
96 			break;
97 		case 'u':
98 			uflag = 1;
99 			break;
100 		case 'w':
101 			if(whatif == 0)
102 				whatif = newbuf();
103 			else
104 				insert(whatif, ' ');
105 			if(argv[0][2])
106 				bufcpy(whatif, &argv[0][2], strlen(&argv[0][2]));
107 			else {
108 				if(*++argv == 0)
109 					badusage();
110 				bufcpy(whatif, &argv[0][0], strlen(&argv[0][0]));
111 			}
112 			break;
113 		default:
114 			badusage();
115 		}
116 	}
117 #ifdef	PROF
118 	{
119 		extern etext();
120 		monitor(main, etext, buf, sizeof buf, 300);
121 	}
122 #endif	PROF
123 
124 	if(aflag)
125 		iflag = 1;
126 	usage();
127 	for(i = strlen(shell)-1; i >= 0; i--)
128 			if(shell[i] == '/')
129 				break;
130 	strcpy(shellname, shell+i+1);
131 	syminit();
132 	initenv();
133 	usage();
134 
135 	/*
136 		assignment args become null strings
137 	*/
138 	for(i = 0; argv[i]; i++) if(utfrune(argv[i], '=')){
139 		bufcpy(buf, argv[i], strlen(argv[i]));
140 		insert(buf, ' ');
141 		if(tfd < 0){
142 			mktemp(temp);
143 			close(create(temp, OWRITE, 0600));
144 			if((tfd = open(temp, 2)) < 0){
145 				perror(temp);
146 				Exit();
147 			}
148 			Binit(&tb, tfd, OWRITE);
149 		}
150 		Bprint(&tb, "%s\n", argv[i]);
151 		*argv[i] = 0;
152 	}
153 	if(tfd >= 0){
154 		Bflush(&tb);
155 		LSEEK(tfd, 0L, 0);
156 		parse("command line args", tfd, 1, 1);
157 		remove(temp);
158 	}
159 
160 	if (buf->current != buf->start) {
161 		buf->current--;
162 		insert(buf, 0);
163 	}
164 	symlook("MKFLAGS", S_VAR, (char *) stow(buf->start));
165 	buf->current = buf->start;
166 	for(i = 0; argv[i]; i++){
167 		if(*argv[i] == 0) continue;
168 		if(i)
169 			insert(buf, ' ');
170 		bufcpy(buf, argv[i], strlen(argv[i]));
171 	}
172 	insert(buf, 0);
173 	symlook("MKARGS", S_VAR, (char *) stow(buf->start));
174 	freebuf(buf);
175 
176 	if(f == files){
177 		if(access(MKFILE, 4) == 0)
178 			parse(MKFILE, open(MKFILE, 0), 0, 1);
179 	} else
180 		for(ff = files; ff < f; ff++)
181 			parse(*ff, open(*ff, 0), 0, 1);
182 	if(DEBUG(D_PARSE)){
183 		dumpw("default targets", target1);
184 		dumpr("rules", rules);
185 		dumpr("metarules", metarules);
186 		dumpv("variables");
187 	}
188 	if(whatif){
189 		insert(whatif, 0);
190 		timeinit(whatif->start);
191 		freebuf(whatif);
192 	}
193 	execinit();
194 	/* skip assignment args */
195 	while(*argv && (**argv == 0))
196 		argv++;
197 
198 	atnotify(notifyf, 1);
199 	if(*argv == 0){
200 		if(target1)
201 			for(w = target1; w; w = w->next)
202 				mk(w->s);
203 		else {
204 			fprint(2, "mk: nothing to mk\n");
205 			Exit();
206 		}
207 	} else {
208 		if(sflag){
209 			for(; *argv; argv++)
210 				if(**argv)
211 					mk(*argv);
212 		} else {
213 			Word *head, *tail, *t;
214 
215 			/* fake a new rule with all the args as prereqs */
216 			tail = 0;
217 			t = 0;
218 			for(; *argv; argv++)
219 				if(**argv){
220 					if(tail == 0)
221 						tail = t = newword(*argv);
222 					else {
223 						t->next = newword(*argv);
224 						t = t->next;
225 					}
226 				}
227 			if(tail->next == 0)
228 				mk(tail->s);
229 			else {
230 				head = newword("command line arguments");
231 				addrules(head, tail, strdup(""), VIR, inline, 1, (char *)0);
232 				mk(head->s);
233 			}
234 		}
235 	}
236 	if(uflag)
237 		prusage();
238 	exits(0);
239 }
240 
241 void
242 badusage(void)
243 {
244 
245 	fprint(2, "Usage: mk [-f file] [-n] [-a] [-e] [-t] [-k] [-i] [-d[egp]] [targets ...]\n");
246 	Exit();
247 }
248 
249 char *
250 Malloc(int n)
251 {
252 	register char *s;
253 
254 	s = malloc(n);
255 	if(!s) {
256 		fprint(2, "mk: cannot alloc %d bytes\n", n);
257 		Exit();
258 	}
259 	return(s);
260 }
261 
262 char *
263 Realloc(char *s, int n)
264 {
265 	s = realloc(s, n);
266 	if(!s) {
267 		fprint(2, "mk: cannot alloc %d bytes\n", n);
268 		Exit();
269 	}
270 	return(s);
271 }
272 
273 void
274 Exit(void)
275 {
276 	while(wait(0) >= 0)
277 		;
278 	exits("error");
279 }
280 
281 /*
282 char *
283 strndup(char *s, unsigned n)
284 {
285 	register char *goo;
286 
287 	goo = Malloc(n);
288 	memmove(goo, s, (COUNT)n);
289 	return(goo);
290 }
291 */
292 
293 void
294 assert(char *s, int n)
295 {
296 	if(!n){
297 		fprint(2, "mk: Assertion ``%s'' failed.\n", s);
298 		Exit();
299 	}
300 }
301 
302 void
303 regerror(char *s)
304 {
305 	if(patrule)
306 		fprint(2, "mk: %s:%d: regular expression error; %s\n",
307 			patrule->file, patrule->line, s);
308 	else
309 		fprint(2, "mk: %s:%d: regular expression error; %s\n",
310 			infile, inline, s);
311 	Exit();
312 }
313