xref: /original-bsd/usr.sbin/config/mkmakefile.c (revision dd262573)
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.29 (Berkeley) 12/11/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, "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, "../../conf/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/%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/%s/%s ",
454 				    machinename, machinename, swapname);
455 			else
456 				fprintf(fp, "%s ", swapname);
457 			lpos += len + 1;
458 		}
459 	if (lpos != 8)
460 		putc('\n', fp);
461 }
462 
463 char *
464 tail(fn)
465 	char *fn;
466 {
467 	register char *cp;
468 
469 	cp = rindex(fn, '/');
470 	if (cp == 0)
471 		return (fn);
472 	return (cp+1);
473 }
474 
475 /*
476  * Create the makerules for each file
477  * which is part of the system.
478  * Devices are processed with the special c2 option -i
479  * which avoids any problem areas with i/o addressing
480  * (e.g. for the VAX); assembler files are processed by as.
481  */
482 do_rules(f)
483 	FILE *f;
484 {
485 	register char *cp, *np, och, *tp;
486 	register struct file_list *ftp;
487 	char *extras;
488 
489 for (ftp = ftab; ftp != 0; ftp = ftp->f_next) {
490 	if (ftp->f_type == INVISIBLE)
491 		continue;
492 	cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
493 	och = *cp;
494 	*cp = '\0';
495 	if (och == 'o') {
496 		fprintf(f, "%so:\n\t-cp $S/%so .\n\n", tail(np), np);
497 		continue;
498 	}
499 	fprintf(f, "%so: $S/%s%c\n", tail(np), np, och);
500 	tp = tail(np);
501 	if (och == 's') {
502 		fprintf(f, "\t-ln -s $S/%ss %sc\n", np, tp);
503 		fprintf(f, "\t${CC} -E ${COPTS} %sc | ${AS} -o %so\n",
504 			tp, tp);
505 		fprintf(f, "\trm -f %sc\n\n", tp);
506 		continue;
507 	}
508 	if (ftp->f_flags & CONFIGDEP)
509 		extras = "${PARAM} ";
510 	else
511 		extras = "";
512 	switch (ftp->f_type) {
513 
514 	case NORMAL:
515 		switch (machine) {
516 
517 		case MACHINE_VAX:
518 		case MACHINE_TAHOE:
519 			fprintf(f, "\t${CC} -c -S ${COPTS} %s$S/%sc\n",
520 				extras, np);
521 			fprintf(f, "\t${C2} %ss | ${INLINE} | ${AS} -o %so\n",
522 			    tp, tp);
523 			fprintf(f, "\trm -f %ss\n\n", tp);
524 			break;
525 
526 		case MACHINE_HP300:
527 			fprintf(f, "\t${CC} -c ${CFLAGS} %s$S/%sc\n\n",
528 				extras, np);
529 			break;
530 		}
531 		break;
532 
533 	case DRIVER:
534 		switch (machine) {
535 
536 		case MACHINE_VAX:
537 		case MACHINE_TAHOE:
538 			fprintf(f, "\t${CC} -c -S ${COPTS} %s$S/%sc\n",
539 				extras, np);
540 			fprintf(f,"\t${C2} -i %ss | ${INLINE} | ${AS} -o %so\n",
541 			    tp, tp);
542 			fprintf(f, "\trm -f %ss\n\n", tp);
543 			break;
544 
545 		case MACHINE_HP300:
546 			fprintf(f, "\t${CC} -c ${CFLAGS} %s$S/%sc\n\n",
547 				extras, np);
548 			break;
549 		}
550 		break;
551 
552 	case PROFILING:
553 		if (!profiling)
554 			continue;
555 		if (COPTS == 0) {
556 			fprintf(stderr,
557 			    "config: COPTS undefined in generic makefile");
558 			COPTS = "";
559 		}
560 		switch (machine) {
561 
562 		case MACHINE_TAHOE:
563 			fprintf(f, "\t${CC} -c -S %s %s$S/%sc\n",
564 				COPTS, extras, np);
565 			fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp);
566 			fprintf(f,"\t${C2} %ss | ${INLINE} | ${AS} -o %so\n",
567 			    tp, tp);
568 			fprintf(f, "\trm -f %ss\n\n", tp);
569 			break;
570 
571 		case MACHINE_VAX:
572 			fprintf(f, "\t${CC} -c -S %s %s$S/%sc\n",
573 				COPTS, extras, np);
574 			fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp);
575 			fprintf(f, "\t${INLINE} %ss | ${AS} -o %so\n", tp, tp);
576 			fprintf(f, "\trm -f %ss\n\n", tp);
577 			break;
578 
579 		case MACHINE_HP300:
580 			fprintf(f, "\t${CC} -c -S %s %s$S/%sc\n",
581 				COPTS, extras, np);
582 			fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp);
583 			fprintf(f, "\t${AS} -o %so %ss\n", tp, tp);
584 			fprintf(f, "\trm -f %ss\n\n", tp);
585 			break;
586 		}
587 		break;
588 
589 	default:
590 		printf("Don't know rules for %s\n", np);
591 		break;
592 	}
593 	*cp = och;
594 }
595 }
596 
597 /*
598  * Create the load strings
599  */
600 do_load(f)
601 	register FILE *f;
602 {
603 	register struct file_list *fl;
604 	register int first;
605 	struct file_list *do_systemspec();
606 
607 	for (first = 1, fl = conf_list; fl; first = 0)
608 		fl = fl->f_type == SYSTEMSPEC ?
609 			do_systemspec(f, fl, first) : fl->f_next;
610 	fputs("all:", f);
611 	for (fl = conf_list; fl; fl = fl->f_next)
612 		if (fl->f_type == SYSTEMSPEC)
613 			fprintf(f, " %s", fl->f_needs);
614 	putc('\n', f);
615 }
616 
617 struct file_list *
618 do_systemspec(f, fl, first)
619 	FILE *f;
620 	register struct file_list *fl;
621 	int first;
622 {
623 
624 	fprintf(f, "%s: Makefile symbols.sort", fl->f_needs);
625 	if (machine == MACHINE_VAX)
626 		fprintf(f, " ${INLINECMD} locore.o emulate.o");
627 	else if (machine == MACHINE_TAHOE)
628 		fprintf(f, " ${INLINE} locore.o");
629 	else
630 		fprintf(f, " locore.o");
631 	fprintf(f, " ${OBJS} param.o ioconf.o swap%s.o\n", fl->f_fn);
632 	fprintf(f, "\t@echo loading %s\n\t@rm -f %s\n",
633 	    fl->f_needs, fl->f_needs);
634 	if (first) {
635 		fprintf(f, "\t@sh $S/conf/newvers.sh\n");
636 		fprintf(f, "\t@${CC} ${CFLAGS} -c vers.c\n");
637 	}
638 	switch (machine) {
639 
640 	case MACHINE_VAX:
641 		fprintf(f, "\t@${LD} -n -o %s -e start -%c -T 80000000 ",
642 			fl->f_needs, debugging ? 'X' : 'x');
643 		fprintf(f,
644 		    "locore.o emulate.o ${OBJS} vers.o ioconf.o param.o ");
645 		break;
646 
647 	case MACHINE_TAHOE:
648 		fprintf(f, "\t@${LD} -n -o %s -e start -%c -T C0000800 ",
649 			fl->f_needs, debugging ? 'X' : 'x');
650 		fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o ");
651 		break;
652 
653 	case MACHINE_HP300:
654 		fprintf(f, "\t@${LD} -n -o %s -e start -%c ",
655 			fl->f_needs, debugging ? 'X' : 'x');
656 		fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o ");
657 		break;
658 	}
659 	fprintf(f, "swap%s.o\n", fl->f_fn);
660 	fprintf(f, "\t@echo rearranging symbols\n");
661 	fprintf(f, "\t@-symorder symbols.sort %s\n", fl->f_needs);
662 	fprintf(f, "\t@size %s\n", fl->f_needs);
663 	fprintf(f, "\t@chmod 755 %s\n\n", fl->f_needs);
664 	do_swapspec(f, fl->f_fn);
665 	for (fl = fl->f_next; fl->f_type == SWAPSPEC; fl = fl->f_next)
666 		;
667 	return (fl);
668 }
669 
670 do_swapspec(f, name)
671 	FILE *f;
672 	register char *name;
673 {
674 
675 	if (!eq(name, "generic")) {
676 		fprintf(f, "swap%s.o: swap%s.c\n", name, name);
677 		fprintf(f, "\t${CC} -c -O ${COPTS} swap%s.c\n\n", name);
678 		return;
679 	}
680 	fprintf(f, "swapgeneric.o: $S/%s/%s/swapgeneric.c\n",
681 	    machinename, machinename);
682 	switch (machine) {
683 
684 	case MACHINE_VAX:
685 	case MACHINE_TAHOE:
686 		fprintf(f, "\t${CC} -c -S ${COPTS} ");
687 		fprintf(f, "$S/%s/%s/swapgeneric.c\n",
688 		    machinename, machinename);
689 		fprintf(f, "\t${C2} swapgeneric.s | ${INLINE}");
690 		fprintf(f, " | ${AS} -o swapgeneric.o\n");
691 		fprintf(f, "\trm -f swapgeneric.s\n\n");
692 		break;
693 
694 	case MACHINE_HP300:
695 		fprintf(f, "\t${CC} -c ${CFLAGS} ");
696 		fprintf(f, "$S/%s/%s/swapgeneric.c\n\n",
697 		    machinename, machinename);
698 		break;
699 	}
700 }
701 
702 char *
703 raise(str)
704 	register char *str;
705 {
706 	register char *cp = str;
707 
708 	while (*str) {
709 		if (islower(*str))
710 			*str = toupper(*str);
711 		str++;
712 	}
713 	return (cp);
714 }
715