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