xref: /original-bsd/usr.sbin/config/mkmakefile.c (revision 92d3de31)
1 /*	mkmakefile.c	1.26	83/04/24	*/
2 
3 /*
4  * Build the makefile for the system, from
5  * the information in the files files and the
6  * additional files for the machine being compiled to.
7  */
8 
9 #include <stdio.h>
10 #include <ctype.h>
11 #include "y.tab.h"
12 #include "config.h"
13 
14 #define next_word(fp, wd) \
15 	{ register char *word = get_word(fp); \
16 	  if (word == (char *)EOF) \
17 		return; \
18 	  else \
19 		wd = word; \
20 	}
21 
22 static	struct file_list *fcur;
23 char *tail();
24 
25 /*
26  * Lookup a file, by make.
27  */
28 struct file_list *
29 fl_lookup(file)
30 	register char *file;
31 {
32 	register struct file_list *fp;
33 
34 	for (fp = ftab ; fp != 0; fp = fp->f_next) {
35 		if (eq(fp->f_fn, file))
36 			return (fp);
37 	}
38 	return (0);
39 }
40 
41 /*
42  * Lookup a file, by final component name.
43  */
44 struct file_list *
45 fltail_lookup(file)
46 	register char *file;
47 {
48 	register struct file_list *fp;
49 
50 	for (fp = ftab ; fp != 0; fp = fp->f_next) {
51 		if (eq(tail(fp->f_fn), tail(file)))
52 			return (fp);
53 	}
54 	return (0);
55 }
56 
57 /*
58  * Make a new file list entry
59  */
60 struct file_list *
61 new_fent()
62 {
63 	register struct file_list *fp;
64 
65 	fp = (struct file_list *) malloc(sizeof *fp);
66 	fp->f_needs = 0;
67 	fp->f_next = 0;
68 	if (fcur == 0)
69 		fcur = ftab = fp;
70 	else
71 		fcur->f_next = fp;
72 	fcur = fp;
73 	return (fp);
74 }
75 
76 char	*COPTS;
77 
78 /*
79  * Build the makefile from the skeleton
80  */
81 makefile()
82 {
83 	FILE *ifp, *ofp;
84 	char line[BUFSIZ];
85 	struct opt *op;
86 
87 	read_files();
88 	strcpy(line, "../conf/makefile.");
89 	(void) strcat(line, machinename);
90 	ifp = fopen(line, "r");
91 	if (ifp == 0) {
92 		perror(line);
93 		exit(1);
94 	}
95 	ofp = fopen(path("makefile"), "w");
96 	if (ofp == 0) {
97 		perror(path("makefile"));
98 		exit(1);
99 	}
100 	fprintf(ofp, "IDENT=-D%s", raise(ident));
101 	if (profiling)
102 		fprintf(ofp, " -DGPROF");
103 	if (cputype == 0) {
104 		printf("cpu type must be specified\n");
105 		exit(1);
106 	}
107 	{ struct cputype *cp;
108 	  for (cp = cputype; cp; cp = cp->cpu_next)
109 		fprintf(ofp, " -D%s", cp->cpu_name);
110 	}
111 	for (op = opt; op; op = op->op_next)
112 		if (op->op_value)
113 			fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value);
114 		else
115 			fprintf(ofp, " -D%s", op->op_name);
116 	fprintf(ofp, "\n");
117 	if (hadtz == 0)
118 		printf("timezone not specified; gmt assumed\n");
119 #ifdef vax
120 	if (maxusers == 0) {
121 		printf("maxusers not specified; 24 assumed\n");
122 		maxusers = 24;
123 	} else if (maxusers < 8) {
124 		printf("minimum of 8 maxusers assumed\n");
125 		maxusers = 8;
126 	} else if (maxusers > 128) {
127 		printf("maxusers truncated to 128\n");
128 		maxusers = 128;
129 	}
130 #endif
131 #ifdef sun
132 	if (maxusers == 0) {
133 		printf("maxusers not specified; 8 assumed\n");
134 		maxusers = 8;
135 	} else if (maxusers < 2) {
136 		printf("minimum of 2 maxusers assumed\n");
137 		maxusers = 2;
138 	} else if (maxusers > 32) {
139 		printf("maxusers truncated to 32\n");
140 		maxusers = 32;
141 	}
142 #endif
143 	fprintf(ofp, "PARAM=-DTIMEZONE=%d -DDST=%d -DMAXUSERS=%d\n",
144 	    timezone, dst, maxusers);
145 	while (fgets(line, BUFSIZ, ifp) != 0) {
146 		if (*line == '%')
147 			goto percent;
148 		if (profiling && strncmp(line, "COPTS=", 6) == 0) {
149 			register char *cp;
150 
151 			fprintf(ofp, "GPROF.EX=/usr/src/lib/libc/csu/gmon.ex\n");
152 			cp = index(line, '\n');
153 			if (cp)
154 				*cp = 0;
155 			cp = line + 6;
156 			while (*cp && (*cp == ' ' || *cp == '\t'))
157 				cp++;
158 			COPTS = malloc((unsigned)(strlen(cp) + 1));
159 			if (COPTS == 0) {
160 				printf("config: out of memory\n");
161 				exit(1);
162 			}
163 			strcpy(COPTS, cp);
164 			fprintf(ofp, "%s -pg\n", line);
165 			continue;
166 		}
167 		fprintf(ofp, "%s", line);
168 		continue;
169 	percent:
170 		if (eq(line, "%OBJS\n"))
171 			do_objs(ofp);
172 		else if (eq(line, "%CFILES\n"))
173 			do_cfiles(ofp);
174 		else if (eq(line, "%RULES\n"))
175 			do_rules(ofp);
176 		else if (eq(line, "%LOAD\n"))
177 			do_load(ofp);
178 		else
179 			fprintf(stderr,
180 			    "Unknown %% construct in generic makefile: %s",
181 			    line);
182 	}
183 	(void) fclose(ifp);
184 	(void) fclose(ofp);
185 }
186 
187 /*
188  * Read in the information about files used in making the system.
189  * Store it in the ftab linked list.
190  */
191 read_files()
192 {
193 	FILE *fp;
194 	register struct file_list *tp;
195 	register struct device *dp;
196 	char *wd, *this, *needs, *devorprof;
197 	char fname[32];
198 	int nreqs;
199 	int first = 1;
200 
201 	ftab = 0;
202 	(void) strcpy(fname, "files");
203 openit:
204 	fp = fopen(fname, "r");
205 	if (fp == 0) {
206 		perror(fname);
207 		exit(1);
208 	}
209 next:
210 	/* filename	[ standard | optional dev* ] [ device-driver ] */
211 	wd = get_word(fp);
212 	if (wd == (char *)EOF) {
213 		(void) fclose(fp);
214 		if (first == 1) {
215 			(void) sprintf(fname, "files.%s", machinename);
216 			first++;
217 			goto openit;
218 		}
219 		if (first == 2) {
220 			(void) sprintf(fname, "files.%s", raise(ident));
221 			first++;
222 			fp = fopen(fname, "r");
223 			if (fp != 0)
224 				goto next;
225 		}
226 		return;
227 	}
228 	if (wd == 0)
229 		goto next;
230 	this = ns(wd);
231 	next_word(fp, wd);
232 	if (wd == 0) {
233 		printf("%s: No type for %s.\n",
234 		    fname, this);
235 		exit(1);
236 	}
237 	if (fl_lookup(this)) {
238 		printf("%s: Duplicate file %s.\n",
239 		    fname, this);
240 		exit(1);
241 	}
242 	tp = 0;
243 	if (first == 3 && (tp = fltail_lookup(this)) != 0)
244 		printf("%s: Local file %s overrides %s.\n",
245 		    fname, this, tp->f_fn);
246 	nreqs = 0;
247 	devorprof = "";
248 	needs = 0;
249 	if (eq(wd, "standard"))
250 		goto checkdev;
251 	if (!eq(wd, "optional")) {
252 		printf("%s: %s must be optional or standard\n",
253 		    fname, this);
254 		exit(1);
255 	}
256 nextopt:
257 	next_word(fp, wd);
258 	if (wd == 0)
259 		goto doneopt;
260 	devorprof = wd;
261 	if (eq(wd, "device-driver") || eq(wd, "profiling-routine")) {
262 		next_word(fp, wd);
263 		goto save;
264 	}
265 	nreqs++;
266 	if (needs == 0)
267 		needs = ns(wd);
268 	for (dp = dtab; dp != 0; dp = dp->d_next)
269 		if (eq(dp->d_name, wd))
270 			goto nextopt;
271 	while ((wd = get_word(fp)) != 0)
272 		;
273 	if (tp == 0)
274 		tp = new_fent();
275 	tp->f_fn = this;
276 	tp->f_type = INVISIBLE;
277 	tp->f_needs = needs;
278 	goto next;
279 doneopt:
280 	if (nreqs == 0) {
281 		printf("%s: what is %s optional on?\n",
282 		    fname, this);
283 		exit(1);
284 	}
285 checkdev:
286 	if (wd) {
287 		next_word(fp, wd);
288 		if (wd != 0) {
289 			devorprof = wd;
290 			next_word(fp, wd);
291 		}
292 	}
293 save:
294 	if (wd != 0) {
295 		printf("%s: syntax error describing %s\n",
296 		    fname, this);
297 		exit(1);
298 	}
299 	if (eq(devorprof, "profiling-routine") && profiling == 0)
300 		goto next;
301 	if (tp == 0)
302 		tp = new_fent();
303 	tp->f_fn = this;
304 	if (eq(devorprof, "device-driver"))
305 		tp->f_type = DEVICE;
306 	else if (eq(devorprof, "profiling-routine"))
307 		tp->f_type = PROFILING;
308 	else
309 		tp->f_type = NORMAL;
310 	tp->f_needs = needs;
311 	goto next;
312 }
313 
314 do_objs(fp)
315 	FILE *fp;
316 {
317 	register struct file_list *tp, *fl;
318 	register int lpos, len;
319 	register char *cp, och, *sp;
320 	char swapname[32];
321 
322 	fprintf(fp, "OBJS=");
323 	lpos = 6;
324 	for (tp = ftab; tp != 0; tp = tp->f_next) {
325 		if (tp->f_type == INVISIBLE)
326 			continue;
327 		sp = tail(tp->f_fn);
328 		for (fl = conf_list; fl != 0; fl = fl->f_next) {
329 			(void) sprintf(swapname, "swap%s.c", fl->f_fn);
330 			if (eq(sp, swapname))
331 				goto cont;
332 		}
333 		cp = sp + (len = strlen(sp)) - 1;
334 		och = *cp;
335 		*cp = 'o';
336 		if (len + lpos > 72) {
337 			lpos = 8;
338 			fprintf(fp, "\\\n\t");
339 		}
340 		fprintf(fp, "%s ", sp);
341 		lpos += len + 1;
342 		*cp = och;
343 cont:;
344 	}
345 	if (lpos != 8)
346 		putc('\n', fp);
347 }
348 
349 do_cfiles(fp)
350 	FILE *fp;
351 {
352 	register struct file_list *tp;
353 	register int lpos, len;
354 
355 	fprintf(fp, "CFILES=");
356 	lpos = 8;
357 	for (tp = ftab; tp != 0; tp = tp->f_next) {
358 		if (tp->f_type == INVISIBLE)
359 			continue;
360 		if (tp->f_fn[strlen(tp->f_fn)-1] != 'c')
361 			continue;
362 		if ((len = 3 + strlen(tp->f_fn)) + lpos > 72) {
363 			lpos = 8;
364 			fprintf(fp, "\\\n\t");
365 		}
366 		fprintf(fp, "../%s ", tp->f_fn);
367 		lpos += len + 1;
368 	}
369 	if (lpos != 8)
370 		putc('\n', fp);
371 }
372 
373 char *
374 tail(fn)
375 	char *fn;
376 {
377 	register char *cp;
378 
379 	cp = rindex(fn, '/');
380 	if (cp == 0)
381 		return (fn);
382 	return (cp+1);
383 }
384 
385 /*
386  * Create the makerules for each file
387  * which is part of the system.
388  * Devices are processed with the special c2 option -i
389  * which avoids any problem areas with i/o addressing
390  * (e.g. for the VAX); assembler files are processed by as.
391  */
392 do_rules(f)
393 	FILE *f;
394 {
395 	register char *cp, *np, och, *tp;
396 	register struct file_list *ftp;
397 
398 for (ftp = ftab; ftp != 0; ftp = ftp->f_next) {
399 	if (ftp->f_type == INVISIBLE)
400 		continue;
401 	cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
402 	och = *cp;
403 	*cp = '\0';
404 	fprintf(f, "%so: ../%s%c\n", tail(np), np, och);
405 	tp = tail(np);
406 	if (och == 's') {
407 		fprintf(f, "\t${AS} -o %so ../%ss\n\n", tp, np);
408 		continue;
409 	}
410 	switch (ftp->f_type) {
411 
412 	case NORMAL:
413 		switch (machine) {
414 
415 		case MACHINE_VAX:
416 			fprintf(f, "\t${CC} -I. -c -S ${COPTS} ../%sc\n", np);
417 			fprintf(f, "\t${C2} %ss | sed -f ../%s/asm.sed |",
418 			    tp, machinename);
419 			fprintf(f, " ${AS} -o %so\n", tp);
420 			fprintf(f, "\trm -f %ss\n\n", tp);
421 			break;
422 
423 		case MACHINE_SUN:
424 			fprintf(f, "\t${CC} -I. -c -O ${COPTS} ../%sc\n\n", np);
425 			break;
426 		}
427 		break;
428 
429 	case DEVICE:
430 		switch (machine) {
431 
432 		case MACHINE_VAX:
433 			fprintf(f, "\t${CC} -I. -c -S ${COPTS} ../%sc\n", np);
434 			fprintf(f,"\t${C2} -i %ss | sed -f ../%s/asm.sed |",
435 			    tp, machinename);
436 			fprintf(f, " ${AS} -o %so\n", tp);
437 			fprintf(f, "\trm -f %ss\n\n", tp);
438 			break;
439 
440 		case MACHINE_SUN:
441 			fprintf(f, "\t${CC} -I. -c -O ${COPTS} ../%sc\n\n", np);
442 		}
443 		break;
444 
445 	case PROFILING:
446 		if (!profiling)
447 			continue;
448 		if (COPTS == 0) {
449 			fprintf(stderr,
450 			    "config: COPTS undefined in generic makefile");
451 			COPTS = "";
452 		}
453 		switch (machine) {
454 
455 		case MACHINE_VAX:
456 			fprintf(f, "\t${CC} -I. -c -S %s ../%sc\n", COPTS, np);
457 			fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp);
458 			fprintf(f,
459 			    "\tsed -f ../vax/asm.sed %ss | ${AS} -o %so\n",
460 			    tp, tp);
461 			fprintf(f, "\trm -f %ss\n\n", tp);
462 			break;
463 
464 		case MACHINE_SUN:
465 			fprintf(stderr,
466 			    "config: don't know how to profile kernel on sun\n");
467 			break;
468 		}
469 		break;
470 
471 	default:
472 		printf("Don't know rules for %s", np);
473 		break;
474 	}
475 	*cp = och;
476 }
477 }
478 
479 /*
480  * Create the load strings
481  */
482 do_load(f)
483 	register FILE *f;
484 {
485 	register struct file_list *fl;
486 	int first = 1;
487 	char swapname[32];
488 
489 	for (fl = conf_list; fl != 0; fl = fl->f_next) {
490 		fprintf(f, "%s: makefile locore.o ${OBJS} param.o",
491 		    fl->f_needs);
492 		fprintf(f, " ioconf.o swap%s.o\n", fl->f_fn);
493 		fprintf(f, "\t@echo loading %s\n\t@rm -f %s\n",
494 		    fl->f_needs, fl->f_needs);
495 		if (first) {
496 			first = 0;
497 			fprintf(f, "\t@sh ../conf/newvers.sh\n");
498 			fprintf(f, "\t@${CC} $(CFLAGS) -c vers.c\n");
499 		}
500 		switch (machine) {
501 
502 		case MACHINE_VAX:
503 			fprintf(f, "\t@${LD} -n -o %s -e start -x -T 80000000 ",
504 				fl->f_needs);
505 			fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o ");
506 			fprintf(f, "swap%s.o\n", fl->f_fn);
507 			break;
508 
509 		case MACHINE_SUN:
510 			fprintf(f, "\t@${LD} -o %s -e start -x -T 4000 ",
511 				fl->f_needs);
512 			fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o ");
513 			fprintf(f, "swap%s.o\n", fl->f_fn);
514 			break;
515 		}
516 		fprintf(f, "\t@echo rearranging symbols\n");
517 		fprintf(f, "\t@-symorder ../%s/symbols.sort %s\n",
518 		    machinename, fl->f_needs);
519 		fprintf(f, "\t@size %s\n", fl->f_needs);
520 		fprintf(f, "\t@chmod 755 %s\n\n", fl->f_needs);
521 	}
522 	for (fl = conf_list; fl != 0; fl = fl->f_next) {
523 		(void) sprintf(swapname, "swap%s.c", fl->f_fn);
524 		if (fltail_lookup(swapname) != 0)
525 			continue;
526 		fprintf(f, "swap%s.o: ../%s/swap%s.c\n",
527 		    fl->f_fn, machinename, fl->f_fn);
528 		switch (machine) {
529 
530 		case MACHINE_VAX:
531 			fprintf(f, "\t${CC} -I. -c -S ${COPTS}");
532 			fprintf(f, " ../%s/swap%s.c\n", machinename, fl->f_fn);
533 			fprintf(f, "\t${C2} swap%s.s | sed -f ../%s/asm.sed",
534 			    fl->f_fn, machinename);
535 			fprintf(f, " | ${AS} -o swap%s.o\n",
536 			    fl->f_fn);
537 			fprintf(f, "\trm -f swap%s.s\n\n", fl->f_fn);
538 			break;
539 
540 		case MACHINE_SUN:
541 			fprintf(f, "\t${CC} -I. -c -O ${COPTS} ");
542 			fprintf(f, "../%s/swap%s.c\n\n", machinename, fl->f_fn);
543 			break;
544 		}
545 	}
546 	fprintf(f, "all:");
547 	for (fl = conf_list; fl != 0; fl = fl->f_next)
548 		fprintf(f, " %s", fl->f_needs);
549 	fprintf(f, "\n");
550 }
551 
552 char *
553 raise(str)
554 	register char *str;
555 {
556 	register char *cp = str;
557 
558 	while (*str) {
559 		if (islower(*str))
560 			*str = toupper(*str);
561 		str++;
562 	}
563 	return (cp);
564 }
565