xref: /original-bsd/usr.sbin/config/mkmakefile.c (revision 7562ff97)
1 /*
2  * Copyright (c) 1980,1990 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)mkmakefile.c	5.28 (Berkeley) 06/01/90";
10 #endif /* not lint */
11 
12 /*
13  * Build the makefile for the system, from
14  * the information in the files files and the
15  * additional files for the machine being compiled to.
16  */
17 
18 #include <stdio.h>
19 #include <ctype.h>
20 #include "y.tab.h"
21 #include "config.h"
22 #include "pathnames.h"
23 
24 #define next_word(fp, wd) \
25 	{ register char *word = get_word(fp); \
26 	  if (word == (char *)EOF) \
27 		return; \
28 	  else \
29 		wd = word; \
30 	}
31 
32 static	struct file_list *fcur;
33 char *tail();
34 
35 /*
36  * Lookup a file, by name.
37  */
38 struct file_list *
39 fl_lookup(file)
40 	register char *file;
41 {
42 	register struct file_list *fp;
43 
44 	for (fp = ftab ; fp != 0; fp = fp->f_next) {
45 		if (eq(fp->f_fn, file))
46 			return (fp);
47 	}
48 	return (0);
49 }
50 
51 /*
52  * Lookup a file, by final component name.
53  */
54 struct file_list *
55 fltail_lookup(file)
56 	register char *file;
57 {
58 	register struct file_list *fp;
59 
60 	for (fp = ftab ; fp != 0; fp = fp->f_next) {
61 		if (eq(tail(fp->f_fn), tail(file)))
62 			return (fp);
63 	}
64 	return (0);
65 }
66 
67 /*
68  * Make a new file list entry
69  */
70 struct file_list *
71 new_fent()
72 {
73 	register struct file_list *fp;
74 
75 	fp = (struct file_list *) malloc(sizeof *fp);
76 	fp->f_needs = 0;
77 	fp->f_next = 0;
78 	fp->f_flags = 0;
79 	fp->f_type = 0;
80 	if (fcur == 0)
81 		fcur = ftab = fp;
82 	else
83 		fcur->f_next = fp;
84 	fcur = fp;
85 	return (fp);
86 }
87 
88 char	*COPTS;
89 static	struct users {
90 	int	u_default;
91 	int	u_min;
92 	int	u_max;
93 } users[] = {
94 	{ 24, 8, 1024 },		/* MACHINE_VAX */
95 	{ 4, 2, 128 },			/* MACHINE_TAHOE */
96 	{ 8, 2, 64 },			/* MACHINE_HP300 */
97 };
98 #define	NUSERS	(sizeof (users) / sizeof (users[0]))
99 
100 /*
101  * Build the makefile from the skeleton
102  */
103 makefile()
104 {
105 	FILE *ifp, *ofp;
106 	char line[BUFSIZ];
107 	struct opt *op;
108 	struct users *up;
109 
110 	read_files();
111 	strcpy(line, "../conf/Makefile.");
112 	(void) strcat(line, machinename);
113 	ifp = fopen(line, "r");
114 	if (ifp == 0) {
115 		perror(line);
116 		exit(1);
117 	}
118 	ofp = fopen(path("Makefile"), "w");
119 	if (ofp == 0) {
120 		perror(path("Makefile"));
121 		exit(1);
122 	}
123 	fprintf(ofp, "IDENT=-D%s", raise(ident));
124 	if (profiling)
125 		fprintf(ofp, " -DGPROF");
126 	if (cputype == 0) {
127 		printf("cpu type must be specified\n");
128 		exit(1);
129 	}
130 	{ struct cputype *cp;
131 	  for (cp = cputype; cp; cp = cp->cpu_next)
132 		fprintf(ofp, " -D%s", cp->cpu_name);
133 	}
134 	for (op = opt; op; op = op->op_next)
135 		if (op->op_value)
136 			fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value);
137 		else
138 			fprintf(ofp, " -D%s", op->op_name);
139 	fprintf(ofp, "\n");
140 	if (hadtz == 0)
141 		printf("timezone not specified; gmt assumed\n");
142 	if ((unsigned)machine > NUSERS) {
143 		printf("maxusers config info isn't present, using vax\n");
144 		up = &users[MACHINE_VAX-1];
145 	} else
146 		up = &users[machine-1];
147 	if (maxusers == 0) {
148 		printf("maxusers not specified; %d assumed\n", up->u_default);
149 		maxusers = up->u_default;
150 	} else if (maxusers < up->u_min) {
151 		printf("minimum of %d maxusers assumed\n", up->u_min);
152 		maxusers = up->u_min;
153 	} else if (maxusers > up->u_max)
154 		printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers);
155 	fprintf(ofp, "PARAM=-DTIMEZONE=%d -DDST=%d -DMAXUSERS=%d\n",
156 	    timezone, dst, maxusers);
157 	for (op = mkopt; op; op = op->op_next)
158 		fprintf(ofp, "%s=%s\n", op->op_name, op->op_value);
159 	while (fgets(line, BUFSIZ, ifp) != 0) {
160 		if (*line == '%')
161 			goto percent;
162 		if ((debugging || profiling) &&
163 		    strncmp(line, "COPTS=", 6) == 0) {
164 			register char *cp;
165 
166 			cp = index(line, '\n');
167 			if (cp)
168 				*cp = 0;
169 			if (profiling) {
170 				cp = line + 6;
171 				while (*cp && (*cp == ' ' || *cp == '\t'))
172 					cp++;
173 				COPTS = malloc((unsigned)(strlen(cp) + 1));
174 				if (COPTS == 0) {
175 					printf("config: out of memory\n");
176 					exit(1);
177 				}
178 				strcpy(COPTS, cp);
179 			}
180 			fprintf(ofp, "%s", line);
181 			if (debugging)
182 				fprintf(ofp, " -g");
183 			if (profiling) {
184 				fprintf(ofp, " -pg\n");
185 				fprintf(ofp, _PATH_GPROF, machinename);
186 			} else
187 				fprintf(ofp, "\n");
188 			continue;
189 		}
190 		fprintf(ofp, "%s", line);
191 		continue;
192 	percent:
193 		if (eq(line, "%OBJS\n"))
194 			do_objs(ofp);
195 		else if (eq(line, "%CFILES\n"))
196 			do_cfiles(ofp);
197 		else if (eq(line, "%RULES\n"))
198 			do_rules(ofp);
199 		else if (eq(line, "%LOAD\n"))
200 			do_load(ofp);
201 		else
202 			fprintf(stderr,
203 			    "Unknown %% construct in generic makefile: %s",
204 			    line);
205 	}
206 	(void) fclose(ifp);
207 	(void) fclose(ofp);
208 }
209 
210 /*
211  * Read in the information about files used in making the system.
212  * Store it in the ftab linked list.
213  */
214 read_files()
215 {
216 	FILE *fp;
217 	register struct file_list *tp, *pf;
218 	register struct device *dp;
219 	struct device *save_dp;
220 	register struct opt *op;
221 	char *wd, *this, *needs, *devorprof;
222 	char fname[32];
223 	int nreqs, first = 1, configdep, isdup, std;
224 
225 	ftab = 0;
226 	(void) strcpy(fname, "files");
227 openit:
228 	fp = fopen(fname, "r");
229 	if (fp == 0) {
230 		perror(fname);
231 		exit(1);
232 	}
233 next:
234 	/*
235 	 * filename	[ standard | optional ] [ config-dependent ]
236 	 *	[ dev* | profiling-routine ] [ device-driver]
237 	 */
238 	wd = get_word(fp);
239 	if (wd == (char *)EOF) {
240 		(void) fclose(fp);
241 		if (first == 1) {
242 			(void) sprintf(fname, "files.%s", machinename);
243 			first++;
244 			goto openit;
245 		}
246 		if (first == 2) {
247 			(void) sprintf(fname, "files.%s", raise(ident));
248 			first++;
249 			fp = fopen(fname, "r");
250 			if (fp != 0)
251 				goto next;
252 		}
253 		return;
254 	}
255 	if (wd == 0)
256 		goto next;
257 	this = ns(wd);
258 	next_word(fp, wd);
259 	if (wd == 0) {
260 		printf("%s: No type for %s.\n",
261 		    fname, this);
262 		exit(1);
263 	}
264 	if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags))
265 		isdup = 1;
266 	else
267 		isdup = 0;
268 	tp = 0;
269 	if (first == 3 && (tp = fltail_lookup(this)) != 0)
270 		printf("%s: Local file %s overrides %s.\n",
271 		    fname, this, tp->f_fn);
272 	nreqs = 0;
273 	devorprof = "";
274 	configdep = 0;
275 	needs = 0;
276 	std = 0;
277 	if (eq(wd, "standard"))
278 		std = 1;
279 	else if (!eq(wd, "optional")) {
280 		printf("%s: %s must be optional or standard\n", fname, this);
281 		exit(1);
282 	}
283 nextparam:
284 	next_word(fp, wd);
285 	if (wd == 0)
286 		goto doneparam;
287 	if (eq(wd, "config-dependent")) {
288 		configdep++;
289 		goto nextparam;
290 	}
291 	devorprof = wd;
292 	if (eq(wd, "device-driver") || eq(wd, "profiling-routine")) {
293 		next_word(fp, wd);
294 		goto save;
295 	}
296 	nreqs++;
297 	if (needs == 0 && nreqs == 1)
298 		needs = ns(wd);
299 	if (isdup)
300 		goto invis;
301 	for (dp = dtab; dp != 0; save_dp = dp, dp = dp->d_next)
302 		if (eq(dp->d_name, wd)) {
303 			if (std &&
304 			    dp->d_type == PSEUDO_DEVICE && dp->d_slave <= 0)
305 				dp->d_slave = 1;
306 			goto nextparam;
307 		}
308 	if (std) {
309 		dp = (struct device *) malloc(sizeof *dp);
310 		init_dev(dp);
311 		dp->d_name = ns(wd);
312 		dp->d_type = PSEUDO_DEVICE;
313 		dp->d_slave = 1;
314 		save_dp->d_next = dp;
315 		goto nextparam;
316 	}
317 	for (op = opt; op != 0; op = op->op_next)
318 		if (op->op_value == 0 && opteq(op->op_name, wd)) {
319 			if (nreqs == 1) {
320 				free(needs);
321 				needs = 0;
322 			}
323 			goto nextparam;
324 		}
325 invis:
326 	while ((wd = get_word(fp)) != 0)
327 		;
328 	if (tp == 0)
329 		tp = new_fent();
330 	tp->f_fn = this;
331 	tp->f_type = INVISIBLE;
332 	tp->f_needs = needs;
333 	tp->f_flags = isdup;
334 	goto next;
335 
336 doneparam:
337 	if (std == 0 && nreqs == 0) {
338 		printf("%s: what is %s optional on?\n",
339 		    fname, this);
340 		exit(1);
341 	}
342 
343 save:
344 	if (wd) {
345 		printf("%s: syntax error describing %s\n",
346 		    fname, this);
347 		exit(1);
348 	}
349 	if (eq(devorprof, "profiling-routine") && profiling == 0)
350 		goto next;
351 	if (tp == 0)
352 		tp = new_fent();
353 	tp->f_fn = this;
354 	if (eq(devorprof, "device-driver"))
355 		tp->f_type = DRIVER;
356 	else if (eq(devorprof, "profiling-routine"))
357 		tp->f_type = PROFILING;
358 	else
359 		tp->f_type = NORMAL;
360 	tp->f_flags = 0;
361 	if (configdep)
362 		tp->f_flags |= CONFIGDEP;
363 	tp->f_needs = needs;
364 	if (pf && pf->f_type == INVISIBLE)
365 		pf->f_flags = 1;		/* mark as duplicate */
366 	goto next;
367 }
368 
369 opteq(cp, dp)
370 	char *cp, *dp;
371 {
372 	char c, d;
373 
374 	for (; ; cp++, dp++) {
375 		if (*cp != *dp) {
376 			c = isupper(*cp) ? tolower(*cp) : *cp;
377 			d = isupper(*dp) ? tolower(*dp) : *dp;
378 			if (c != d)
379 				return (0);
380 		}
381 		if (*cp == 0)
382 			return (1);
383 	}
384 }
385 
386 do_objs(fp)
387 	FILE *fp;
388 {
389 	register struct file_list *tp, *fl;
390 	register int lpos, len;
391 	register char *cp, och, *sp;
392 	char swapname[32];
393 
394 	fprintf(fp, "OBJS=");
395 	lpos = 6;
396 	for (tp = ftab; tp != 0; tp = tp->f_next) {
397 		if (tp->f_type == INVISIBLE)
398 			continue;
399 		sp = tail(tp->f_fn);
400 		for (fl = conf_list; fl; fl = fl->f_next) {
401 			if (fl->f_type != SWAPSPEC)
402 				continue;
403 			(void) sprintf(swapname, "swap%s.c", fl->f_fn);
404 			if (eq(sp, swapname))
405 				goto cont;
406 		}
407 		cp = sp + (len = strlen(sp)) - 1;
408 		och = *cp;
409 		*cp = 'o';
410 		if (len + lpos > 72) {
411 			lpos = 8;
412 			fprintf(fp, "\\\n\t");
413 		}
414 		fprintf(fp, "%s ", sp);
415 		lpos += len + 1;
416 		*cp = och;
417 cont:
418 		;
419 	}
420 	if (lpos != 8)
421 		putc('\n', fp);
422 }
423 
424 do_cfiles(fp)
425 	FILE *fp;
426 {
427 	register struct file_list *tp, *fl;
428 	register int lpos, len;
429 	char swapname[32];
430 
431 	fputs("CFILES=", fp);
432 	lpos = 8;
433 	for (tp = ftab; tp; tp = tp->f_next)
434 		if (tp->f_type != INVISIBLE) {
435 			len = strlen(tp->f_fn);
436 			if (tp->f_fn[len - 1] != 'c')
437 				continue;
438 			if ((len = 3 + len) + lpos > 72) {
439 				lpos = 8;
440 				fputs("\\\n\t", fp);
441 			}
442 			fprintf(fp, "../%s ", tp->f_fn);
443 			lpos += len + 1;
444 		}
445 	for (fl = conf_list; fl; fl = fl->f_next)
446 		if (fl->f_type == SYSTEMSPEC) {
447 			(void) sprintf(swapname, "swap%s.c", fl->f_fn);
448 			if ((len = 3 + strlen(swapname)) + lpos > 72) {
449 				lpos = 8;
450 				fputs("\\\n\t", fp);
451 			}
452 			if (eq(fl->f_fn, "generic"))
453 				fprintf(fp, "../%s/%s ", machinename, swapname);
454 			else
455 				fprintf(fp, "%s ", swapname);
456 			lpos += len + 1;
457 		}
458 	if (lpos != 8)
459 		putc('\n', fp);
460 }
461 
462 char *
463 tail(fn)
464 	char *fn;
465 {
466 	register char *cp;
467 
468 	cp = rindex(fn, '/');
469 	if (cp == 0)
470 		return (fn);
471 	return (cp+1);
472 }
473 
474 /*
475  * Create the makerules for each file
476  * which is part of the system.
477  * Devices are processed with the special c2 option -i
478  * which avoids any problem areas with i/o addressing
479  * (e.g. for the VAX); assembler files are processed by as.
480  */
481 do_rules(f)
482 	FILE *f;
483 {
484 	register char *cp, *np, och, *tp;
485 	register struct file_list *ftp;
486 	char *extras;
487 
488 for (ftp = ftab; ftp != 0; ftp = ftp->f_next) {
489 	if (ftp->f_type == INVISIBLE)
490 		continue;
491 	cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
492 	och = *cp;
493 	*cp = '\0';
494 	if (och == 'o') {
495 		fprintf(f, "%so:\n\t-cp ../%so .\n\n", tail(np), np);
496 		continue;
497 	}
498 	fprintf(f, "%so: ../%s%c\n", tail(np), np, och);
499 	tp = tail(np);
500 	if (och == 's') {
501 		fprintf(f, "\t-ln -s ../%ss %sc\n", np, tp);
502 		fprintf(f, "\t${CC} -E ${COPTS} %sc | ${AS} -o %so\n",
503 			tp, tp);
504 		fprintf(f, "\trm -f %sc\n\n", tp);
505 		continue;
506 	}
507 	if (ftp->f_flags & CONFIGDEP)
508 		extras = "${PARAM} ";
509 	else
510 		extras = "";
511 	switch (ftp->f_type) {
512 
513 	case NORMAL:
514 		switch (machine) {
515 
516 		case MACHINE_VAX:
517 		case MACHINE_TAHOE:
518 			fprintf(f, "\t${CC} -c -S ${COPTS} %s../%sc\n",
519 				extras, np);
520 			fprintf(f, "\t${C2} %ss | ${INLINE} | ${AS} -o %so\n",
521 			    tp, tp);
522 			fprintf(f, "\trm -f %ss\n\n", tp);
523 			break;
524 
525 		case MACHINE_HP300:
526 			fprintf(f, "\t${CC} -c ${CFLAGS} %s../%sc\n\n",
527 				extras, np);
528 			break;
529 		}
530 		break;
531 
532 	case DRIVER:
533 		switch (machine) {
534 
535 		case MACHINE_VAX:
536 		case MACHINE_TAHOE:
537 			fprintf(f, "\t${CC} -c -S ${COPTS} %s../%sc\n",
538 				extras, np);
539 			fprintf(f,"\t${C2} -i %ss | ${INLINE} | ${AS} -o %so\n",
540 			    tp, tp);
541 			fprintf(f, "\trm -f %ss\n\n", tp);
542 			break;
543 
544 		case MACHINE_HP300:
545 			fprintf(f, "\t${CC} -c ${CFLAGS} %s../%sc\n\n",
546 				extras, np);
547 			break;
548 		}
549 		break;
550 
551 	case PROFILING:
552 		if (!profiling)
553 			continue;
554 		if (COPTS == 0) {
555 			fprintf(stderr,
556 			    "config: COPTS undefined in generic makefile");
557 			COPTS = "";
558 		}
559 		switch (machine) {
560 
561 		case MACHINE_TAHOE:
562 			fprintf(f, "\t${CC} -c -S %s %s../%sc\n",
563 				COPTS, extras, np);
564 			fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp);
565 			fprintf(f,"\t${C2} %ss | ${INLINE} | ${AS} -o %so\n",
566 			    tp, tp);
567 			fprintf(f, "\trm -f %ss\n\n", tp);
568 			break;
569 
570 		case MACHINE_VAX:
571 			fprintf(f, "\t${CC} -c -S %s %s../%sc\n",
572 				COPTS, extras, np);
573 			fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp);
574 			fprintf(f, "\t${INLINE} %ss | ${AS} -o %so\n", tp, tp);
575 			fprintf(f, "\trm -f %ss\n\n", tp);
576 			break;
577 
578 		case MACHINE_HP300:
579 			fprintf(f, "\t${CC} -c -S %s %s../%sc\n",
580 				COPTS, extras, np);
581 			fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp);
582 			fprintf(f, "\t${AS} -o %so %ss\n", tp, tp);
583 			fprintf(f, "\trm -f %ss\n\n", tp);
584 			break;
585 		}
586 		break;
587 
588 	default:
589 		printf("Don't know rules for %s\n", np);
590 		break;
591 	}
592 	*cp = och;
593 }
594 }
595 
596 /*
597  * Create the load strings
598  */
599 do_load(f)
600 	register FILE *f;
601 {
602 	register struct file_list *fl;
603 	register int first;
604 	struct file_list *do_systemspec();
605 
606 	for (first = 1, fl = conf_list; fl; first = 0)
607 		fl = fl->f_type == SYSTEMSPEC ?
608 			do_systemspec(f, fl, first) : fl->f_next;
609 	fputs("all:", f);
610 	for (fl = conf_list; fl; fl = fl->f_next)
611 		if (fl->f_type == SYSTEMSPEC)
612 			fprintf(f, " %s", fl->f_needs);
613 	putc('\n', f);
614 }
615 
616 struct file_list *
617 do_systemspec(f, fl, first)
618 	FILE *f;
619 	register struct file_list *fl;
620 	int first;
621 {
622 
623 	fprintf(f, "%s: Makefile machine/symbols.sort", fl->f_needs);
624 	if (machine == MACHINE_VAX)
625 		fprintf(f, " ${INLINECMD} locore.o emulate.o");
626 	else if (machine == MACHINE_TAHOE)
627 		fprintf(f, " ${INLINE} locore.o");
628 	else
629 		fprintf(f, " locore.o");
630 	fprintf(f, " ${OBJS} param.o ioconf.o swap%s.o\n", fl->f_fn);
631 	fprintf(f, "\t@echo loading %s\n\t@rm -f %s\n",
632 	    fl->f_needs, fl->f_needs);
633 	if (first) {
634 		fprintf(f, "\t@sh ../conf/newvers.sh\n");
635 		fprintf(f, "\t@${CC} ${CFLAGS} -c vers.c\n");
636 	}
637 	switch (machine) {
638 
639 	case MACHINE_VAX:
640 		fprintf(f, "\t@${LD} -n -o %s -e start -%c -T 80000000 ",
641 			fl->f_needs, debugging ? 'X' : 'x');
642 		fprintf(f,
643 		    "locore.o emulate.o ${OBJS} vers.o ioconf.o param.o ");
644 		break;
645 
646 	case MACHINE_TAHOE:
647 		fprintf(f, "\t@${LD} -n -o %s -e start -%c -T C0000800 ",
648 			fl->f_needs, debugging ? 'X' : 'x');
649 		fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o ");
650 		break;
651 
652 	case MACHINE_HP300:
653 		fprintf(f, "\t@${LD} -n -o %s -e start -%c ",
654 			fl->f_needs, debugging ? 'X' : 'x');
655 		fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o ");
656 		break;
657 	}
658 	fprintf(f, "swap%s.o\n", fl->f_fn);
659 	fprintf(f, "\t@echo rearranging symbols\n");
660 	fprintf(f, "\t@-symorder machine/symbols.sort %s\n", fl->f_needs);
661 	fprintf(f, "\t@size %s\n", fl->f_needs);
662 	fprintf(f, "\t@chmod 755 %s\n\n", fl->f_needs);
663 	do_swapspec(f, fl->f_fn);
664 	for (fl = fl->f_next; fl->f_type == SWAPSPEC; fl = fl->f_next)
665 		;
666 	return (fl);
667 }
668 
669 do_swapspec(f, name)
670 	FILE *f;
671 	register char *name;
672 {
673 
674 	if (!eq(name, "generic")) {
675 		fprintf(f, "swap%s.o: swap%s.c\n", name, name);
676 		fprintf(f, "\t${CC} -c -O ${COPTS} swap%s.c\n\n", name);
677 		return;
678 	}
679 	fprintf(f, "swapgeneric.o: ../%s/swapgeneric.c\n", machinename);
680 	switch (machine) {
681 
682 	case MACHINE_VAX:
683 	case MACHINE_TAHOE:
684 		fprintf(f, "\t${CC} -c -S ${COPTS} ");
685 		fprintf(f, "../%s/swapgeneric.c\n", machinename);
686 		fprintf(f, "\t${C2} swapgeneric.s | ${INLINE}");
687 		fprintf(f, " | ${AS} -o swapgeneric.o\n");
688 		fprintf(f, "\trm -f swapgeneric.s\n\n");
689 		break;
690 
691 	case MACHINE_HP300:
692 		fprintf(f, "\t${CC} -c ${CFLAGS} ");
693 		fprintf(f, "../%s/swapgeneric.c\n\n", machinename);
694 		break;
695 	}
696 }
697 
698 char *
699 raise(str)
700 	register char *str;
701 {
702 	register char *cp = str;
703 
704 	while (*str) {
705 		if (islower(*str))
706 			*str = toupper(*str);
707 		str++;
708 	}
709 	return (cp);
710 }
711