xref: /original-bsd/usr.sbin/config/mkmakefile.c (revision 68d9582f)
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.38 (Berkeley) 06/19/92";
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 
23 #define next_word(fp, wd) \
24 	{ register char *word = get_word(fp); \
25 	  if (word == (char *)EOF) \
26 		return; \
27 	  else \
28 		wd = word; \
29 	}
30 #define next_quoted_word(fp, wd) \
31 	{ register char *word = get_quoted_word(fp); \
32 	  if (word == (char *)EOF) \
33 		return; \
34 	  else \
35 		wd = word; \
36 	}
37 
38 static	struct file_list *fcur;
39 char *tail();
40 
41 /*
42  * Lookup a file, by name.
43  */
44 struct file_list *
45 fl_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(fp->f_fn, file))
52 			return (fp);
53 	}
54 	return (0);
55 }
56 
57 /*
58  * Lookup a file, by final component name.
59  */
60 struct file_list *
61 fltail_lookup(file)
62 	register char *file;
63 {
64 	register struct file_list *fp;
65 
66 	for (fp = ftab ; fp != 0; fp = fp->f_next) {
67 		if (eq(tail(fp->f_fn), tail(file)))
68 			return (fp);
69 	}
70 	return (0);
71 }
72 
73 /*
74  * Make a new file list entry
75  */
76 struct file_list *
77 new_fent()
78 {
79 	register struct file_list *fp;
80 
81 	fp = (struct file_list *) malloc(sizeof *fp);
82 	bzero(fp, sizeof *fp);
83 	if (fcur == 0)
84 		fcur = ftab = fp;
85 	else
86 		fcur->f_next = fp;
87 	fcur = fp;
88 	return (fp);
89 }
90 
91 static	struct users {
92 	int	u_default;
93 	int	u_min;
94 	int	u_max;
95 } users[] = {
96 	{ 24, 8, 1024 },		/* MACHINE_VAX */
97 	{ 4, 2, 128 },			/* MACHINE_TAHOE */
98 	{ 8, 2, 64 },			/* MACHINE_HP300 */
99 	{ 8, 2, 64 },			/* MACHINE_I386 */
100 	{ 8, 2, 64 },			/* MACHINE_MIPS */
101 	{ 8, 2, 64 },			/* MACHINE_PMAX */
102 	{ 8, 2, 64 },			/* MACHINE_LUNA68K */
103 };
104 #define	NUSERS	(sizeof (users) / sizeof (users[0]))
105 
106 /*
107  * Build the makefile from the skeleton
108  */
109 makefile()
110 {
111 	FILE *ifp, *ofp;
112 	char line[BUFSIZ];
113 	struct opt *op;
114 	struct users *up;
115 
116 	read_files();
117 	strcpy(line, "Makefile.");
118 	(void) strcat(line, machinename);
119 	ifp = fopen(line, "r");
120 	if (ifp == 0) {
121 		perror(line);
122 		exit(1);
123 	}
124 	ofp = fopen(path("Makefile"), "w");
125 	if (ofp == 0) {
126 		perror(path("Makefile"));
127 		exit(1);
128 	}
129 	fprintf(ofp, "IDENT=-D%s", raise(ident));
130 	if (profiling)
131 		fprintf(ofp, " -DGPROF");
132 	if (cputype == 0) {
133 		printf("cpu type must be specified\n");
134 		exit(1);
135 	}
136 	{ struct cputype *cp;
137 	  for (cp = cputype; cp; cp = cp->cpu_next)
138 		fprintf(ofp, " -D%s", cp->cpu_name);
139 	}
140 	for (op = opt; op; op = op->op_next)
141 		if (op->op_value)
142 			fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value);
143 		else
144 			fprintf(ofp, " -D%s", op->op_name);
145 	fprintf(ofp, "\n");
146 	if (hadtz == 0)
147 		printf("timezone not specified; gmt assumed\n");
148 	if ((unsigned)machine > NUSERS) {
149 		printf("maxusers config info isn't present, using vax\n");
150 		up = &users[MACHINE_VAX-1];
151 	} else
152 		up = &users[machine-1];
153 	if (maxusers == 0) {
154 		printf("maxusers not specified; %d assumed\n", up->u_default);
155 		maxusers = up->u_default;
156 	} else if (maxusers < up->u_min) {
157 		printf("minimum of %d maxusers assumed\n", up->u_min);
158 		maxusers = up->u_min;
159 	} else if (maxusers > up->u_max)
160 		printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers);
161 	fprintf(ofp, "PARAM=-DTIMEZONE=%d -DDST=%d -DMAXUSERS=%d",
162 	    zone, dst, maxusers);
163 	if (hz > 0)
164 		fprintf(ofp, " -DHZ=%d", hz);
165 	fprintf(ofp, "\n");
166 	for (op = mkopt; op; op = op->op_next)
167 		fprintf(ofp, "%s=%s\n", op->op_name, op->op_value);
168 	if (debugging)
169 		fprintf(ofp, "DEBUG=-g\n");
170 	if (profiling)
171 		fprintf(ofp, "PROF=-pg\n");
172 	while (fgets(line, BUFSIZ, ifp) != 0) {
173 		if (*line != '%') {
174 			fprintf(ofp, "%s", line);
175 			continue;
176 		}
177 		if (eq(line, "%OBJS\n"))
178 			do_objs(ofp);
179 		else if (eq(line, "%CFILES\n"))
180 			do_cfiles(ofp);
181 		else if (eq(line, "%RULES\n"))
182 			do_rules(ofp);
183 		else if (eq(line, "%LOAD\n"))
184 			do_load(ofp);
185 		else
186 			fprintf(stderr,
187 			    "Unknown %% construct in generic makefile: %s",
188 			    line);
189 	}
190 	(void) fclose(ifp);
191 	(void) fclose(ofp);
192 }
193 
194 /*
195  * Read in the information about files used in making the system.
196  * Store it in the ftab linked list.
197  */
198 read_files()
199 {
200 	FILE *fp;
201 	register struct file_list *tp, *pf;
202 	register struct device *dp;
203 	struct device *save_dp;
204 	register struct opt *op;
205 	char *wd, *this, *needs, *special;
206 	char fname[32];
207 	int nreqs, first = 1, configdep, isdup, std, filetype;
208 
209 	ftab = 0;
210 	(void) strcpy(fname, "../../conf/files");
211 openit:
212 	fp = fopen(fname, "r");
213 	if (fp == 0) {
214 		perror(fname);
215 		exit(1);
216 	}
217 next:
218 	/*
219 	 * filename	[ standard | optional ] [ config-dependent ]
220 	 *	[ dev* | profiling-routine ] [ device-driver]
221 	 *	[ compile-with "compile rule" ]
222 	 */
223 	wd = get_word(fp);
224 	if (wd == (char *)EOF) {
225 		(void) fclose(fp);
226 		if (first == 1) {
227 			(void) sprintf(fname, "files.%s", machinename);
228 			first++;
229 			goto openit;
230 		}
231 		if (first == 2) {
232 			(void) sprintf(fname, "files.%s", raise(ident));
233 			first++;
234 			fp = fopen(fname, "r");
235 			if (fp != 0)
236 				goto next;
237 		}
238 		return;
239 	}
240 	if (wd == 0)
241 		goto next;
242 	this = ns(wd);
243 	next_word(fp, wd);
244 	if (wd == 0) {
245 		printf("%s: No type for %s.\n",
246 		    fname, this);
247 		exit(1);
248 	}
249 	if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags))
250 		isdup = 1;
251 	else
252 		isdup = 0;
253 	tp = 0;
254 	if (first == 3 && (tp = fltail_lookup(this)) != 0)
255 		printf("%s: Local file %s overrides %s.\n",
256 		    fname, this, tp->f_fn);
257 	nreqs = 0;
258 	special = 0;
259 	configdep = 0;
260 	needs = 0;
261 	std = 0;
262 	filetype = NORMAL;
263 	if (eq(wd, "standard"))
264 		std = 1;
265 	else if (!eq(wd, "optional")) {
266 		printf("%s: %s must be optional or standard\n", fname, this);
267 		exit(1);
268 	}
269 nextparam:
270 	next_word(fp, wd);
271 	if (wd == 0)
272 		goto doneparam;
273 	if (eq(wd, "config-dependent")) {
274 		configdep++;
275 		goto nextparam;
276 	}
277 	if (eq(wd, "compile-with")) {
278 		next_quoted_word(fp, wd);
279 		if (wd == 0) {
280 			printf("%s: %s missing compile command string.\n",
281 			       fname);
282 			exit(1);
283 		}
284 		special = ns(wd);
285 		goto nextparam;
286 	}
287 	nreqs++;
288 	if (eq(wd, "device-driver")) {
289 		filetype = DRIVER;
290 		goto nextparam;
291 	}
292 	if (eq(wd, "profiling-routine")) {
293 		filetype = PROFILING;
294 		goto nextparam;
295 	}
296 	if (needs == 0 && nreqs == 1)
297 		needs = ns(wd);
298 	if (isdup)
299 		goto invis;
300 	for (dp = dtab; dp != 0; save_dp = dp, dp = dp->d_next)
301 		if (eq(dp->d_name, wd)) {
302 			if (std && dp->d_type == PSEUDO_DEVICE &&
303 			    dp->d_slave <= 0)
304 				dp->d_slave = 1;
305 			goto nextparam;
306 		}
307 	if (std) {
308 		dp = (struct device *) malloc(sizeof *dp);
309 		init_dev(dp);
310 		dp->d_name = ns(wd);
311 		dp->d_type = PSEUDO_DEVICE;
312 		dp->d_slave = 1;
313 		save_dp->d_next = dp;
314 		goto nextparam;
315 	}
316 	for (op = opt; op != 0; op = op->op_next)
317 		if (op->op_value == 0 && opteq(op->op_name, wd)) {
318 			if (nreqs == 1) {
319 				free(needs);
320 				needs = 0;
321 			}
322 			goto nextparam;
323 		}
324 invis:
325 	while ((wd = get_word(fp)) != 0)
326 		;
327 	if (tp == 0)
328 		tp = new_fent();
329 	tp->f_fn = this;
330 	tp->f_type = INVISIBLE;
331 	tp->f_needs = needs;
332 	tp->f_flags = isdup;
333 	tp->f_special = special;
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 (filetype == PROFILING && profiling == 0)
350 		goto next;
351 	if (tp == 0)
352 		tp = new_fent();
353 	tp->f_fn = this;
354 	tp->f_type = filetype;
355 	tp->f_flags = 0;
356 	if (configdep)
357 		tp->f_flags |= CONFIGDEP;
358 	tp->f_needs = needs;
359 	tp->f_special = special;
360 	if (pf && pf->f_type == INVISIBLE)
361 		pf->f_flags = 1;		/* mark as duplicate */
362 	goto next;
363 }
364 
365 opteq(cp, dp)
366 	char *cp, *dp;
367 {
368 	char c, d;
369 
370 	for (; ; cp++, dp++) {
371 		if (*cp != *dp) {
372 			c = isupper(*cp) ? tolower(*cp) : *cp;
373 			d = isupper(*dp) ? tolower(*dp) : *dp;
374 			if (c != d)
375 				return (0);
376 		}
377 		if (*cp == 0)
378 			return (1);
379 	}
380 }
381 
382 do_objs(fp)
383 	FILE *fp;
384 {
385 	register struct file_list *tp, *fl;
386 	register int lpos, len;
387 	register char *cp, och, *sp;
388 	char swapname[32];
389 
390 	fprintf(fp, "OBJS=");
391 	lpos = 6;
392 	for (tp = ftab; tp != 0; tp = tp->f_next) {
393 		if (tp->f_type == INVISIBLE)
394 			continue;
395 		sp = tail(tp->f_fn);
396 		for (fl = conf_list; fl; fl = fl->f_next) {
397 			if (fl->f_type != SWAPSPEC)
398 				continue;
399 			(void) sprintf(swapname, "swap%s.c", fl->f_fn);
400 			if (eq(sp, swapname))
401 				goto cont;
402 		}
403 		cp = sp + (len = strlen(sp)) - 1;
404 		och = *cp;
405 		*cp = 'o';
406 		if (len + lpos > 72) {
407 			lpos = 8;
408 			fprintf(fp, "\\\n\t");
409 		}
410 		fprintf(fp, "%s ", sp);
411 		lpos += len + 1;
412 		*cp = och;
413 cont:
414 		;
415 	}
416 	if (lpos != 8)
417 		putc('\n', fp);
418 }
419 
420 do_cfiles(fp)
421 	FILE *fp;
422 {
423 	register struct file_list *tp, *fl;
424 	register int lpos, len;
425 	char swapname[32];
426 
427 	fputs("CFILES=", fp);
428 	lpos = 8;
429 	for (tp = ftab; tp; tp = tp->f_next)
430 		if (tp->f_type != INVISIBLE) {
431 			len = strlen(tp->f_fn);
432 			if (tp->f_fn[len - 1] != 'c')
433 				continue;
434 			if ((len = 3 + len) + lpos > 72) {
435 				lpos = 8;
436 				fputs("\\\n\t", fp);
437 			}
438 			fprintf(fp, "$S/%s ", tp->f_fn);
439 			lpos += len + 1;
440 		}
441 	for (fl = conf_list; fl; fl = fl->f_next)
442 		if (fl->f_type == SYSTEMSPEC) {
443 			(void) sprintf(swapname, "swap%s.c", fl->f_fn);
444 			if ((len = 3 + strlen(swapname)) + lpos > 72) {
445 				lpos = 8;
446 				fputs("\\\n\t", fp);
447 			}
448 			if (eq(fl->f_fn, "generic"))
449 				fprintf(fp, "$S/%s/%s/%s ",
450 				    machinename, machinename, swapname);
451 			else
452 				fprintf(fp, "%s ", swapname);
453 			lpos += len + 1;
454 		}
455 	if (lpos != 8)
456 		putc('\n', fp);
457 }
458 
459 char *
460 tail(fn)
461 	char *fn;
462 {
463 	register char *cp;
464 
465 	cp = rindex(fn, '/');
466 	if (cp == 0)
467 		return (fn);
468 	return (cp+1);
469 }
470 
471 /*
472  * Create the makerules for each file
473  * which is part of the system.
474  * Devices are processed with the special c2 option -i
475  * which avoids any problem areas with i/o addressing
476  * (e.g. for the VAX); assembler files are processed by as.
477  */
478 do_rules(f)
479 	FILE *f;
480 {
481 	register char *cp, *np, och, *tp;
482 	register struct file_list *ftp;
483 	char *special;
484 
485 	for (ftp = ftab; ftp != 0; ftp = ftp->f_next) {
486 		if (ftp->f_type == INVISIBLE)
487 			continue;
488 		cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
489 		och = *cp;
490 		*cp = '\0';
491 		if (och == 'o') {
492 			fprintf(f, "%so:\n\t-cp $S/%so .\n\n", tail(np), np);
493 			continue;
494 		}
495 		fprintf(f, "%so: $S/%s%c\n", tail(np), np, och);
496 		tp = tail(np);
497 		special = ftp->f_special;
498 		if (special == 0) {
499 			char *ftype;
500 			static char cmd[128];
501 
502 			switch (ftp->f_type) {
503 
504 			case NORMAL:
505 				ftype = "NORMAL";
506 				break;
507 
508 			case DRIVER:
509 				ftype = "DRIVER";
510 				break;
511 
512 			case PROFILING:
513 				if (!profiling)
514 					continue;
515 				ftype = "PROFILE";
516 				break;
517 
518 			default:
519 				printf("config: don't know rules for %s\n", np);
520 				break;
521 			}
522 			(void)sprintf(cmd, "${%s_%c%s}", ftype, toupper(och),
523 				      ftp->f_flags & CONFIGDEP? "_C" : "");
524 			special = cmd;
525 		}
526 		*cp = och;
527 		fprintf(f, "\t%s\n\n", special);
528 	}
529 }
530 
531 /*
532  * Create the load strings
533  */
534 do_load(f)
535 	register FILE *f;
536 {
537 	register struct file_list *fl;
538 	register int first;
539 	struct file_list *do_systemspec();
540 
541 	for (first = 1, fl = conf_list; fl; first = 0)
542 		fl = fl->f_type == SYSTEMSPEC ?
543 			do_systemspec(f, fl, first) : fl->f_next;
544 	fputs("all:", f);
545 	for (fl = conf_list; fl; fl = fl->f_next)
546 		if (fl->f_type == SYSTEMSPEC)
547 			fprintf(f, " %s", fl->f_needs);
548 	putc('\n', f);
549 }
550 
551 struct file_list *
552 do_systemspec(f, fl, first)
553 	FILE *f;
554 	register struct file_list *fl;
555 	int first;
556 {
557 
558 	fprintf(f, "%s: ${SYSTEM_DEP} swap%s.o", fl->f_needs, fl->f_fn);
559 	if (first)
560 		fprintf(f, " newvers");
561 	fprintf(f, "\n\t${SYSTEM_LD_HEAD}\n");
562 	fprintf(f, "\t${SYSTEM_LD} swap%s.o\n", fl->f_fn);
563 	fprintf(f, "\t${SYSTEM_LD_TAIL}\n\n");
564 	do_swapspec(f, fl->f_fn);
565 	for (fl = fl->f_next; fl; fl = fl->f_next)
566 		if (fl->f_type != SWAPSPEC)
567 			break;
568 	return (fl);
569 }
570 
571 do_swapspec(f, name)
572 	FILE *f;
573 	register char *name;
574 {
575 
576 	if (!eq(name, "generic"))
577 		fprintf(f, "swap%s.o: swap%s.c\n", name, name);
578 	else
579 		fprintf(f, "swapgeneric.o: $S/%s/%s/swapgeneric.c\n",
580 			machinename, machinename);
581 	fprintf(f, "\t${NORMAL_C}\n\n");
582 }
583 
584 char *
585 raise(str)
586 	register char *str;
587 {
588 	register char *cp = str;
589 
590 	while (*str) {
591 		if (islower(*str))
592 			*str = toupper(*str);
593 		str++;
594 	}
595 	return (cp);
596 }
597