xref: /dragonfly/usr.sbin/config/mkmakefile.c (revision 9348a738)
1 /*
2  * Copyright (c) 1993, 19801990
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * @(#)mkmakefile.c	8.1 (Berkeley) 6/6/93
30  * $FreeBSD: src/usr.sbin/config/mkmakefile.c,v 1.51.2.3 2001/01/23 00:09:32 peter Exp $
31  */
32 
33 /*
34  * Build the makefile for the system, from
35  * the information in the 'files' files and the
36  * additional files for the machine being compiled to.
37  */
38 
39 #include <ctype.h>
40 #include <err.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <sys/param.h>
44 #include "y.tab.h"
45 #include "config.h"
46 #include "configvers.h"
47 
48 #define next_word(fp, wd)						\
49 	{								\
50 		char *word;						\
51 									\
52 		word = get_word(fp);					\
53 		if (word == (char *)EOF)				\
54 			return;						\
55 		else							\
56 			wd = word;					\
57 	}
58 #define next_quoted_word(fp, wd)					\
59 	{								\
60 		char *word;						\
61 									\
62 		word = get_quoted_word(fp);				\
63 		if (word == (char *)EOF)				\
64 			return;						\
65 		else							\
66 			wd = word;					\
67 	}
68 
69 static struct file_list *fcur;
70 
71 static char *tail(char *);
72 static void do_clean(FILE *);
73 static void do_rules(FILE *);
74 static void do_sfiles(FILE *);
75 static void do_mfiles(FILE *);
76 static void do_cfiles(FILE *);
77 static void do_objs(FILE *);
78 static void do_before_depend(FILE *);
79 static int opteq(char *, char *);
80 static void read_files(void);
81 
82 /*
83  * Lookup a file, by name.
84  */
85 static struct file_list *
86 fl_lookup(char *file)
87 {
88 	struct file_list *fp;
89 
90 	for (fp = ftab; fp != NULL; fp = fp->f_next) {
91 		if (strcmp(fp->f_fn, file) == 0)
92 			return(fp);
93 	}
94 	return(0);
95 }
96 
97 /*
98  * Lookup a file, by final component name.
99  */
100 static struct file_list *
101 fltail_lookup(char *file)
102 {
103 	struct file_list *fp;
104 
105 	for (fp = ftab; fp != NULL; fp = fp->f_next) {
106 		if (strcmp(tail(fp->f_fn), tail(file)) == 0)
107 			return(fp);
108 	}
109 	return(0);
110 }
111 
112 /*
113  * Make a new file list entry
114  */
115 static struct file_list *
116 new_fent(void)
117 {
118 	struct file_list *fp;
119 
120 	fp = malloc(sizeof(*fp));
121 	bzero(fp, sizeof(*fp));
122 	if (fcur == NULL)
123 		fcur = ftab = fp;
124 	else
125 		fcur->f_next = fp;
126 	fcur = fp;
127 	return(fp);
128 }
129 
130 /*
131  * Build the makefile from the skeleton
132  */
133 void
134 makefile(void)
135 {
136 	FILE *ifp, *ofp;
137 	char line[BUFSIZ];
138 	struct opt *op;
139 	int versreq;
140 
141 	read_files();
142 	snprintf(line, sizeof(line), "../platform/%s/conf/Makefile",
143 		 platformname);
144 	ifp = fopen(line, "r");
145 	if (ifp == NULL) {
146 		snprintf(line, sizeof(line), "Makefile.%s", platformname);
147 		ifp = fopen(line, "r");
148 	}
149 	if (ifp == NULL)
150 		err(1, "%s", line);
151 	ofp = fopen(path("Makefile.new"), "w");
152 	if (ofp == NULL)
153 		err(1, "%s", path("Makefile.new"));
154 	fprintf(ofp, "KERN_IDENT=%s\n", raisestr(ident));
155 	fprintf(ofp, "MACHINE_PLATFORM=%s\n", platformname);
156 	fprintf(ofp, "MACHINE=%s\n", machinename);
157 	fprintf(ofp, "MACHINE_ARCH=%s\n", machinearchname);
158 	fprintf(ofp, ".export MACHINE_PLATFORM\n");
159 	fprintf(ofp, ".export MACHINE\n");
160 	fprintf(ofp, ".export MACHINE_ARCH\n");
161 	fprintf(ofp, "IDENT=");
162 	if (profiling) {
163 		/* Don't compile kernel profiling code for vkernel */
164 		if (strncmp(platformname, "vkernel", 6) != 0)
165 			fprintf(ofp, " -DGPROF");
166 	}
167 
168 	if (cputype == 0) {
169 		printf("cpu type must be specified\n");
170 		exit(1);
171 	}
172 	fprintf(ofp, "\n");
173 	for (op = mkopt; op != NULL; op = op->op_next)
174 		fprintf(ofp, "%s=%s\n", op->op_name, op->op_value);
175 	if (debugging)
176 		fprintf(ofp, "DEBUG=-g\n");
177 	if (profiling) {
178 		fprintf(ofp, "PROF=-pg\n");
179 		fprintf(ofp, "PROFLEVEL=%d\n", profiling);
180 	}
181 	if (*srcdir != '\0')
182 		fprintf(ofp,"S=%s\n", srcdir);
183 	while (fgets(line, BUFSIZ, ifp) != 0) {
184 		if (*line != '%') {
185 			fprintf(ofp, "%s", line);
186 			continue;
187 		}
188 		if (strcmp(line, "%BEFORE_DEPEND\n") == 0)
189 			do_before_depend(ofp);
190 		else if (strcmp(line, "%OBJS\n") == 0)
191 			do_objs(ofp);
192 		else if (strcmp(line, "%MFILES\n") == 0)
193 			do_mfiles(ofp);
194 		else if (strcmp(line, "%CFILES\n") == 0)
195 			do_cfiles(ofp);
196 		else if (strcmp(line, "%SFILES\n") == 0)
197 			do_sfiles(ofp);
198 		else if (strcmp(line, "%RULES\n") == 0)
199 			do_rules(ofp);
200 		else if (strcmp(line, "%CLEAN\n") == 0)
201 			do_clean(ofp);
202 		else if (strncmp(line, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) {
203 			versreq = atoi(line + sizeof("%VERSREQ=") - 1);
204 			if (versreq != CONFIGVERS) {
205 				fprintf(stderr, "ERROR: version of config(8) does not match kernel!\n");
206 				fprintf(stderr, "config version = %d, ", CONFIGVERS);
207 				fprintf(stderr, "version required = %d\n\n", versreq);
208 				fprintf(stderr, "Make sure that /usr/src/usr.sbin/config is in sync\n");
209 				fprintf(stderr, "with your /usr/src/sys and install a new config binary\n");
210 				fprintf(stderr, "before trying this again.\n\n");
211 				fprintf(stderr, "If running the new config fails check your config\n");
212 				fprintf(stderr, "file against the GENERIC or LINT config files for\n");
213 				fprintf(stderr, "changes in config syntax, or option/device naming\n");
214 				fprintf(stderr, "conventions\n\n");
215 				exit(1);
216 			}
217 		} else
218 			fprintf(stderr,
219 			    "Unknown %% construct in generic makefile: %s",
220 			    line);
221 	}
222 	fclose(ifp);
223 	fclose(ofp);
224 	moveifchanged(path("Makefile.new"), path("Makefile"));
225 }
226 
227 /*
228  * Read in the information about files used in making the system.
229  * Store it in the ftab linked list.
230  */
231 static void
232 read_files(void)
233 {
234 	FILE *fp;
235 	struct file_list *tp, *pf;
236 	struct device *dp;
237 	struct device *save_dp;
238 	struct opt *op;
239 	char *wd, *this, *needs, *special, *depends, *clean, *warning;
240 	char fname[MAXPATHLEN];
241 	int nonoptional;
242 	int nreqs, first = 1, configdep, isdup, std, filetype,
243 	    imp_rule, no_obj, before_depend, nowerror, mandatory;
244 
245 	ftab = 0;
246 	save_dp = NULL;
247 	if (ident == NULL) {
248 		printf("no ident line specified\n");
249 		exit(1);
250 	}
251 	snprintf(fname, sizeof(fname), "../conf/files");
252 openit:
253 	fp = fopen(fname, "r");
254 	if (fp == NULL)
255 		err(1, "%s", fname);
256 next:
257 	/*
258 	 * filename    [ standard | mandatory | optional ] [ config-dependent ]
259 	 *	[ dev* | profiling-routine ] [ no-obj ]
260 	 *	[ compile-with "compile rule" [no-implicit-rule] ]
261 	 *      [ dependency "dependency-list"] [ before-depend ]
262 	 *	[ clean "file-list"] [ warning "text warning" ]
263 	 */
264 	wd = get_word(fp);
265 	if (wd == (char *)EOF) {
266 		fclose(fp);
267 		if (first == 1) {
268 			first++;
269 			snprintf(fname, sizeof(fname),
270 			    "../platform/%s/conf/files",
271 			    platformname);
272 			fp = fopen(fname, "r");
273 			if (fp != NULL)
274 				goto next;
275 			snprintf(fname, sizeof(fname),
276 			    "files.%s", platformname);
277 			goto openit;
278 		}
279 		if (first == 2) {
280 			first++;
281 			snprintf(fname, sizeof(fname),
282 			    "files.%s", raisestr(ident));
283 			fp = fopen(fname, "r");
284 			if (fp != NULL)
285 				goto next;
286 		}
287 		return;
288 	}
289 	if (wd == NULL)
290 		goto next;
291 	if (wd[0] == '#')
292 	{
293 		while (((wd = get_word(fp)) != (char *)EOF) && wd)
294 			;
295 		goto next;
296 	}
297 	this = strdup(wd);
298 	next_word(fp, wd);
299 	if (wd == NULL) {
300 		printf("%s: No type for %s.\n",
301 		    fname, this);
302 		exit(1);
303 	}
304 	if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags))
305 		isdup = 1;
306 	else
307 		isdup = 0;
308 	tp = NULL;
309 	if (first == 3 && pf == NULL && (tp = fltail_lookup(this)) != NULL) {
310 		if (tp->f_type != INVISIBLE || tp->f_flags)
311 			printf("%s: Local file %s overrides %s.\n",
312 			    fname, this, tp->f_fn);
313 		else
314 			printf("%s: Local file %s could override %s"
315 			    " with a different kernel configuration.\n",
316 			    fname, this, tp->f_fn);
317 	}
318 	nreqs = 0;
319 	special = NULL;
320 	depends = NULL;
321 	clean = NULL;
322 	warning = NULL;
323 	configdep = 0;
324 	needs = NULL;
325 	std = mandatory = nonoptional = 0;
326 	imp_rule = 0;
327 	no_obj = 0;
328 	before_depend = 0;
329 	nowerror = 0;
330 	filetype = NORMAL;
331 	if (strcmp(wd, "standard") == 0) {
332 		std = 1;
333 	} else if (strcmp(wd, "mandatory") == 0) {
334 		/*
335 		 * If an entry is marked "mandatory", config will abort if
336 		 * it's not called by a configuration line in the config
337 		 * file.  Apart from this, the device is handled like one
338 		 * marked "optional".
339 		 */
340 		mandatory = 1;
341 	} else if (strcmp(wd, "nonoptional") == 0) {
342 		nonoptional = 1;
343 	} else if (strcmp(wd, "optional") == 0) {
344 		/* don't need to do anything */
345 	} else {
346 		printf("%s: %s must be optional, mandatory or standard\n",
347 		       fname, this);
348 		printf("Alternatively, your version of config(8) may be out of sync with your\nkernel source.\n");
349 		exit(1);
350 	}
351 nextparam:
352 	next_word(fp, wd);
353 	if (wd == NULL)
354 		goto doneparam;
355 	if (strcmp(wd, "config-dependent") == 0) {
356 		configdep++;
357 		goto nextparam;
358 	}
359 	if (strcmp(wd, "no-obj") == 0) {
360 		no_obj++;
361 		goto nextparam;
362 	}
363 	if (strcmp(wd, "no-implicit-rule") == 0) {
364 		if (special == NULL) {
365 			printf("%s: alternate rule required when "
366 			       "\"no-implicit-rule\" is specified.\n",
367 			       fname);
368 		}
369 		imp_rule++;
370 		goto nextparam;
371 	}
372 	if (strcmp(wd, "before-depend") == 0) {
373 		before_depend++;
374 		goto nextparam;
375 	}
376 	if (strcmp(wd, "dependency") == 0) {
377 		next_quoted_word(fp, wd);
378 		if (wd == NULL) {
379 			printf("%s: %s missing compile command string.\n",
380 			       fname, this);
381 			exit(1);
382 		}
383 		depends = strdup(wd);
384 		goto nextparam;
385 	}
386 	if (strcmp(wd, "clean") == 0) {
387 		next_quoted_word(fp, wd);
388 		if (wd == NULL) {
389 			printf("%s: %s missing clean file list.\n",
390 			       fname, this);
391 			exit(1);
392 		}
393 		clean = strdup(wd);
394 		goto nextparam;
395 	}
396 	if (strcmp(wd, "compile-with") == 0) {
397 		next_quoted_word(fp, wd);
398 		if (wd == NULL) {
399 			printf("%s: %s missing compile command string.\n",
400 			       fname, this);
401 			exit(1);
402 		}
403 		special = strdup(wd);
404 		goto nextparam;
405 	}
406 	if (strcmp(wd, "nowerror") == 0) {
407 		nowerror++;
408 		goto nextparam;
409 	}
410 	if (strcmp(wd, "warning") == 0) {
411 		next_quoted_word(fp, wd);
412 		if (wd == NULL) {
413 			printf("%s: %s missing warning text string.\n",
414 				fname, this);
415 			exit(1);
416 		}
417 		warning = strdup(wd);
418 		goto nextparam;
419 	}
420 	nreqs++;
421 	if (strcmp(wd, "local") == 0) {
422 		filetype = LOCAL;
423 		goto nextparam;
424 	}
425 	if (strcmp(wd, "no-depend") == 0) {
426 		filetype = NODEPEND;
427 		goto nextparam;
428 	}
429 	if (strcmp(wd, "device-driver") == 0) {
430 		printf("%s: `device-driver' flag obsolete.\n", fname);
431 		exit(1);
432 	}
433 	if (strcmp(wd, "profiling-routine") == 0) {
434 		filetype = PROFILING;
435 		goto nextparam;
436 	}
437 	if (needs == NULL && nreqs == 1)
438 		needs = strdup(wd);
439 	if (isdup)
440 		goto invis;
441 	for (dp = dtab; dp != NULL; save_dp = dp, dp = dp->d_next)
442 		if (strcmp(dp->d_name, wd) == 0) {
443 			if (std && dp->d_type == PSEUDO_DEVICE &&
444 			    dp->d_count <= 0)
445 				dp->d_count = 1;
446 			goto nextparam;
447 		}
448 	if (mandatory) {
449 		printf("%s: mandatory device \"%s\" not found\n",
450 		       fname, wd);
451 		exit(1);
452 	}
453 	if (std) {
454 		dp = malloc(sizeof(*dp));
455 		bzero(dp, sizeof(*dp));
456 		init_dev(dp);
457 		dp->d_name = strdup(wd);
458 		dp->d_type = PSEUDO_DEVICE;
459 		dp->d_count = 1;
460 		save_dp->d_next = dp;
461 		goto nextparam;
462 	}
463 	for (op = opt; op != NULL; op = op->op_next) {
464 		if (op->op_value == 0 && opteq(op->op_name, wd)) {
465 			if (nreqs == 1) {
466 				free(needs);
467 				needs = NULL;
468 			}
469 			goto nextparam;
470 		}
471 	}
472 	if (nonoptional) {
473 		printf("%s: the option \"%s\" MUST be specified\n",
474 			fname, wd);
475 		exit(1);
476 	}
477 invis:
478 	while ((wd = get_word(fp)) != NULL)
479 		;
480 	if (tp == NULL)
481 		tp = new_fent();
482 	tp->f_fn = this;
483 	tp->f_type = INVISIBLE;
484 	tp->f_needs = needs;
485 	tp->f_flags = isdup;
486 	tp->f_special = special;
487 	tp->f_depends = depends;
488 	tp->f_clean = clean;
489 	tp->f_warn = warning;
490 	goto next;
491 
492 doneparam:
493 	if (std == 0 && nreqs == 0) {
494 		printf("%s: what is %s optional on?\n",
495 		    fname, this);
496 		exit(1);
497 	}
498 
499 	if (wd != NULL) {
500 		printf("%s: syntax error describing %s\n",
501 		    fname, this);
502 		exit(1);
503 	}
504 	if (filetype == PROFILING && profiling == 0)
505 		goto next;
506 	if (tp == NULL)
507 		tp = new_fent();
508 	tp->f_fn = this;
509 	tp->f_type = filetype;
510 	tp->f_flags = 0;
511 	if (configdep)
512 		tp->f_flags |= CONFIGDEP;
513 	if (imp_rule)
514 		tp->f_flags |= NO_IMPLCT_RULE;
515 	if (no_obj)
516 		tp->f_flags |= NO_OBJ;
517 	if (before_depend)
518 		tp->f_flags |= BEFORE_DEPEND;
519 	if (nowerror)
520 		tp->f_flags |= NOWERROR;
521 	if (imp_rule)
522 		tp->f_flags |= NO_IMPLCT_RULE;
523 	if (no_obj)
524 		tp->f_flags |= NO_OBJ;
525 	tp->f_needs = needs;
526 	tp->f_special = special;
527 	tp->f_depends = depends;
528 	tp->f_clean = clean;
529 	tp->f_warn = warning;
530 	if (pf && pf->f_type == INVISIBLE)
531 		pf->f_flags = 1;		/* mark as duplicate */
532 	goto next;
533 }
534 
535 static int
536 opteq(char *cp, char *dp)
537 {
538 	char c, d;
539 
540 	for (;; cp++, dp++) {
541 		if (*cp != *dp) {
542 			c = isupper(*cp) ? tolower(*cp) : *cp;
543 			d = isupper(*dp) ? tolower(*dp) : *dp;
544 			if (c != d)
545 				return(0);
546 		}
547 		if (*cp == 0)
548 			return(1);
549 	}
550 }
551 
552 static void
553 do_before_depend(FILE *fp)
554 {
555 	struct file_list *tp;
556 	int lpos, len;
557 
558 	fputs("BEFORE_DEPEND=", fp);
559 	lpos = 15;
560 	for (tp = ftab; tp != NULL; tp = tp->f_next)
561 		if (tp->f_flags & BEFORE_DEPEND) {
562 			len = strlen(tp->f_fn);
563 			if ((len = 3 + len) + lpos > 72) {
564 				lpos = 8;
565 				fputs("\\\n\t", fp);
566 			}
567 			if (tp->f_flags & NO_IMPLCT_RULE)
568 				fprintf(fp, "%s ", tp->f_fn);
569 			else
570 				fprintf(fp, "$S/%s ", tp->f_fn);
571 			lpos += len + 1;
572 		}
573 	if (lpos != 8)
574 		putc('\n', fp);
575 }
576 
577 static void
578 do_objs(FILE *fp)
579 {
580 	struct file_list *tp;
581 	int lpos, len;
582 	char *cp, och, *sp;
583 
584 	fprintf(fp, "OBJS=");
585 	lpos = 6;
586 	for (tp = ftab; tp != NULL; tp = tp->f_next) {
587 		if (tp->f_type == INVISIBLE || tp->f_flags & NO_OBJ)
588 			continue;
589 		sp = tail(tp->f_fn);
590 		cp = sp + (len = strlen(sp)) - 1;
591 		och = *cp;
592 		*cp = 'o';
593 		if (len + lpos > 72) {
594 			lpos = 8;
595 			fprintf(fp, "\\\n\t");
596 		}
597 		fprintf(fp, "%s ", sp);
598 		lpos += len + 1;
599 		*cp = och;
600 	}
601 	if (lpos != 8)
602 		putc('\n', fp);
603 }
604 
605 static void
606 do_cfiles(FILE *fp)
607 {
608 	struct file_list *tp;
609 	int lpos, len;
610 
611 	fputs("CFILES=", fp);
612 	lpos = 8;
613 	for (tp = ftab; tp != NULL; tp = tp->f_next)
614 		if (tp->f_type != INVISIBLE && tp->f_type != NODEPEND) {
615 			len = strlen(tp->f_fn);
616 			if (tp->f_fn[len - 1] != 'c')
617 				continue;
618 			if ((len = 3 + len) + lpos > 72) {
619 				lpos = 8;
620 				fputs("\\\n\t", fp);
621 			}
622 			if (tp->f_type != LOCAL)
623 				fprintf(fp, "$S/%s ", tp->f_fn);
624 			else
625 				fprintf(fp, "%s ", tp->f_fn);
626 
627 			lpos += len + 1;
628 		}
629 	if (lpos != 8)
630 		putc('\n', fp);
631 }
632 
633 static void
634 do_mfiles(FILE *fp)
635 {
636 	struct file_list *tp;
637 	int lpos, len;
638 
639 	fputs("MFILES=", fp);
640 	lpos = 8;
641 	for (tp = ftab; tp != NULL; tp = tp->f_next)
642 		if (tp->f_type != INVISIBLE) {
643 			len = strlen(tp->f_fn);
644 			if (tp->f_fn[len - 1] != 'm' || tp->f_fn[len - 2] != '.')
645 				continue;
646 			if ((len = 3 + len) + lpos > 72) {
647 				lpos = 8;
648 				fputs("\\\n\t", fp);
649 			}
650 			fprintf(fp, "$S/%s ", tp->f_fn);
651 			lpos += len + 1;
652 		}
653 	if (lpos != 8)
654 		putc('\n', fp);
655 }
656 
657 static void
658 do_sfiles(FILE *fp)
659 {
660 	struct file_list *tp;
661 	int lpos, len;
662 
663 	fputs("SFILES=", fp);
664 	lpos = 8;
665 	for (tp = ftab; tp != NULL; tp = tp->f_next)
666 		if (tp->f_type != INVISIBLE) {
667 			len = strlen(tp->f_fn);
668 			if (tp->f_fn[len - 1] != 'S' && tp->f_fn[len - 1] != 's')
669 				continue;
670 			if ((len = 3 + len) + lpos > 72) {
671 				lpos = 8;
672 				fputs("\\\n\t", fp);
673 			}
674 			fprintf(fp, "$S/%s ", tp->f_fn);
675 			lpos += len + 1;
676 		}
677 	if (lpos != 8)
678 		putc('\n', fp);
679 }
680 
681 
682 static char *
683 tail(char *fn)
684 {
685 	char *cp;
686 
687 	cp = strrchr(fn, '/');
688 	if (cp == NULL)
689 		return(fn);
690 	return(cp + 1);
691 }
692 
693 /*
694  * Create the makerules for each file
695  * which is part of the system.
696  * Devices are processed with the special c2 option -i
697  * which avoids any problem areas with i/o addressing
698  * (e.g. for the VAX); assembler files are processed by as.
699  */
700 static void
701 do_rules(FILE *f)
702 {
703 	char *cp, *np, och;
704 	struct file_list *ftp;
705 	char *special;
706 
707 	for (ftp = ftab; ftp != NULL; ftp = ftp->f_next) {
708 		if (ftp->f_type == INVISIBLE)
709 			continue;
710 		if (ftp->f_warn != NULL)
711 			printf("WARNING: %s\n", ftp->f_warn);
712 		cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
713 		och = *cp;
714 		if (ftp->f_flags & NO_IMPLCT_RULE) {
715 			if (ftp->f_depends)
716 				fprintf(f, "%s: %s\n", np, ftp->f_depends);
717 			else
718 				fprintf(f, "%s: \n", np);
719 		}
720 		else {
721 			*cp = '\0';
722 			if (och == 'o') {
723 				fprintf(f, "%so:\n\t-cp $S/%so .\n\n",
724 					tail(np), np);
725 				continue;
726 			}
727 			if (ftp->f_depends)
728 				fprintf(f, "%so: $S/%s%c %s\n", tail(np),
729 					np, och, ftp->f_depends);
730 			else
731 				fprintf(f, "%so: $S/%s%c\n", tail(np),
732 					np, och);
733 		}
734 		special = ftp->f_special;
735 		if (special == NULL) {
736 			const char *ftype = NULL;
737 			static char cmd[128];
738 
739 			switch (ftp->f_type) {
740 
741 			case NORMAL:
742 				ftype = "NORMAL";
743 				break;
744 
745 			case PROFILING:
746 				if (!profiling)
747 					continue;
748 				ftype = "PROFILE";
749 				break;
750 
751 			default:
752 				printf("config: don't know rules for %s\n", np);
753 				break;
754 			}
755 			snprintf(cmd, sizeof(cmd), "${%s_%c%s}%s",
756 			    ftype, toupper(och),
757 			    ftp->f_flags & CONFIGDEP ? "_C" : "",
758 			    ftp->f_flags & NOWERROR ? "" : " ${WERROR}");
759 			special = cmd;
760 		}
761 		*cp = och;
762 		fprintf(f, "\t%s\n\n", special);
763 	}
764 }
765 
766 static void
767 do_clean(FILE *fp)
768 {
769 	struct file_list *tp;
770 	int lpos, len;
771 
772 	fputs("CLEAN=", fp);
773 	lpos = 7;
774 	for (tp = ftab; tp != NULL; tp = tp->f_next)
775 		if (tp->f_clean) {
776 			len = strlen(tp->f_clean);
777 			if (len + lpos > 72) {
778 				lpos = 8;
779 				fputs("\\\n\t", fp);
780 			}
781 			fprintf(fp, "%s ", tp->f_clean);
782 			lpos += len + 1;
783 		}
784 	if (lpos != 8)
785 		putc('\n', fp);
786 }
787 
788 char *
789 raisestr(char *str)
790 {
791 	char *cp = str;
792 
793 	while (*str) {
794 		if (islower(*str))
795 			*str = toupper(*str);
796 		str++;
797 	}
798 	return(cp);
799 }
800