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