11553Srgrimes/*
2230051Skevlo * Copyright (c) 1980, 1990, 1993
31553Srgrimes *	The Regents of the University of California.  All rights reserved.
41553Srgrimes *
51553Srgrimes * Redistribution and use in source and binary forms, with or without
61553Srgrimes * modification, are permitted provided that the following conditions
71553Srgrimes * are met:
81553Srgrimes * 1. Redistributions of source code must retain the above copyright
91553Srgrimes *    notice, this list of conditions and the following disclaimer.
101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111553Srgrimes *    notice, this list of conditions and the following disclaimer in the
121553Srgrimes *    documentation and/or other materials provided with the distribution.
131553Srgrimes * 4. Neither the name of the University nor the names of its contributors
141553Srgrimes *    may be used to endorse or promote products derived from this software
151553Srgrimes *    without specific prior written permission.
161553Srgrimes *
171553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271553Srgrimes * SUCH DAMAGE.
281553Srgrimes */
291553Srgrimes
301553Srgrimes#ifndef lint
3129451Scharnier#if 0
321553Srgrimesstatic char sccsid[] = "@(#)mkmakefile.c	8.1 (Berkeley) 6/6/93";
3329451Scharnier#endif
3429451Scharnierstatic const char rcsid[] =
3550479Speter  "$FreeBSD$";
361553Srgrimes#endif /* not lint */
371553Srgrimes
381553Srgrimes/*
391553Srgrimes * Build the makefile for the system, from
401553Srgrimes * the information in the files files and the
411553Srgrimes * additional files for the machine being compiled to.
421553Srgrimes */
431553Srgrimes
4429451Scharnier#include <ctype.h>
4529451Scharnier#include <err.h>
46269825Simp#include <stdarg.h>
471553Srgrimes#include <stdio.h>
4820458Sjoerg#include <string.h>
4969004Simp#include <sys/param.h>
5016073Sphk#include "y.tab.h"
511553Srgrimes#include "config.h"
5230638Speter#include "configvers.h"
531553Srgrimes
5461640Speterstatic char *tail(char *);
5561640Speterstatic void do_clean(FILE *);
5661640Speterstatic void do_rules(FILE *);
5769135Speterstatic void do_xxfiles(char *, FILE *);
5861640Speterstatic void do_objs(FILE *);
5961640Speterstatic void do_before_depend(FILE *);
6072684Speterstatic int opteq(const char *, const char *);
6161640Speterstatic void read_files(void);
6229451Scharnier
63269825Simpstatic void errout(const char *fmt, ...)
64269825Simp{
65269825Simp	va_list ap;
66269825Simp
67269825Simp	va_start(ap, fmt);
68269825Simp	vfprintf(stderr, fmt, ap);
69269825Simp	va_end(ap);
70269825Simp	exit(1);
71269825Simp}
72269825Simp
731553Srgrimes/*
741553Srgrimes * Lookup a file, by name.
751553Srgrimes */
7645744Speterstatic struct file_list *
7761640Speterfl_lookup(char *file)
781553Srgrimes{
7961640Speter	struct file_list *fp;
801553Srgrimes
81110895Sru	STAILQ_FOREACH(fp, &ftab, f_next) {
821553Srgrimes		if (eq(fp->f_fn, file))
831553Srgrimes			return (fp);
841553Srgrimes	}
851553Srgrimes	return (0);
861553Srgrimes}
871553Srgrimes
881553Srgrimes/*
891553Srgrimes * Make a new file list entry
901553Srgrimes */
9145744Speterstatic struct file_list *
9261640Speternew_fent(void)
931553Srgrimes{
9461640Speter	struct file_list *fp;
951553Srgrimes
96159362Sdelphij	fp = (struct file_list *) calloc(1, sizeof *fp);
97205880Sru	if (fp == NULL)
98205880Sru		err(EXIT_FAILURE, "calloc");
99110895Sru	STAILQ_INSERT_TAIL(&ftab, fp, f_next);
1001553Srgrimes	return (fp);
1011553Srgrimes}
1021553Srgrimes
1031553Srgrimes/*
104207260Simp * Open the correct Makefile and return it, or error out.
1051553Srgrimes */
106207260SimpFILE *
107207260Simpopen_makefile_template(void)
1081553Srgrimes{
109207260Simp	FILE *ifp;
1101553Srgrimes	char line[BUFSIZ];
1111553Srgrimes
11255614Speter	snprintf(line, sizeof(line), "../../conf/Makefile.%s", machinename);
1131553Srgrimes	ifp = fopen(line, "r");
11455614Speter	if (ifp == 0) {
11555614Speter		snprintf(line, sizeof(line), "Makefile.%s", machinename);
11655614Speter		ifp = fopen(line, "r");
11755614Speter	}
11829451Scharnier	if (ifp == 0)
11929451Scharnier		err(1, "%s", line);
120207260Simp	return (ifp);
121207260Simp}
12212772Speter
123207260Simp/*
124207260Simp * Build the makefile from the skeleton
125207260Simp */
126207260Simpvoid
127207260Simpmakefile(void)
128207260Simp{
129207260Simp	FILE *ifp, *ofp;
130207260Simp	char line[BUFSIZ];
131207260Simp	struct opt *op, *t;
132207260Simp
133207260Simp	read_files();
134207260Simp	ifp = open_makefile_template();
13599923Sbde	ofp = fopen(path("Makefile.new"), "w");
13699923Sbde	if (ofp == 0)
13799923Sbde		err(1, "%s", path("Makefile.new"));
138113951Sdes	fprintf(ofp, "KERN_IDENT=%s\n", ident);
139218544Simp	fprintf(ofp, "MACHINE=%s\n", machinename);
140218544Simp	fprintf(ofp, "MACHINE_ARCH=%s\n", machinearch);
141185186Sthompsa	SLIST_FOREACH_SAFE(op, &mkopt, op_next, t) {
142185186Sthompsa		fprintf(ofp, "%s=%s", op->op_name, op->op_value);
143185186Sthompsa		while ((op = SLIST_NEXT(op, op_append)) != NULL)
144185186Sthompsa			fprintf(ofp, " %s", op->op_value);
145185186Sthompsa		fprintf(ofp, "\n");
146185186Sthompsa	}
1471553Srgrimes	if (debugging)
1481553Srgrimes		fprintf(ofp, "DEBUG=-g\n");
14999923Sbde	if (profiling)
15020395Sbde		fprintf(ofp, "PROFLEVEL=%d\n", profiling);
15152653Smarcel	if (*srcdir != '\0')
15252653Smarcel		fprintf(ofp,"S=%s\n", srcdir);
153230044Skevlo	while (fgets(line, BUFSIZ, ifp) != NULL) {
1541553Srgrimes		if (*line != '%') {
1551553Srgrimes			fprintf(ofp, "%s", line);
1561553Srgrimes			continue;
1571553Srgrimes		}
1585325Sgibbs		if (eq(line, "%BEFORE_DEPEND\n"))
1595325Sgibbs			do_before_depend(ofp);
1605325Sgibbs		else if (eq(line, "%OBJS\n"))
1611553Srgrimes			do_objs(ofp);
16269135Speter		else if (strncmp(line, "%FILES.", 7) == 0)
16369135Speter			do_xxfiles(line, ofp);
1641553Srgrimes		else if (eq(line, "%RULES\n"))
1651553Srgrimes			do_rules(ofp);
1666803Sgibbs		else if (eq(line, "%CLEAN\n"))
1676803Sgibbs			do_clean(ofp);
168207260Simp		else if (strncmp(line, "%VERSREQ=", 9) == 0)
169207260Simp			line[0] = '\0'; /* handled elsewhere */
170207260Simp		else
1711553Srgrimes			fprintf(stderr,
1721553Srgrimes			    "Unknown %% construct in generic makefile: %s",
1731553Srgrimes			    line);
1741553Srgrimes	}
1751553Srgrimes	(void) fclose(ifp);
1761553Srgrimes	(void) fclose(ofp);
17713400Speter	moveifchanged(path("Makefile.new"), path("Makefile"));
178153888Sru}
17934619Seivind
180153888Sru/*
181153888Sru * Build hints.c from the skeleton
182153888Sru */
183153888Sruvoid
184153888Srumakehints(void)
185153888Sru{
186163640Simp	FILE *ifp, *ofp;
187153888Sru	char line[BUFSIZ];
188153888Sru	char *s;
189163638Simp	struct hint *hint;
190153888Sru
19161640Speter	ofp = fopen(path("hints.c.new"), "w");
19261640Speter	if (ofp == NULL)
19361640Speter		err(1, "%s", path("hints.c.new"));
19483594Speter	fprintf(ofp, "#include <sys/types.h>\n");
19583594Speter	fprintf(ofp, "#include <sys/systm.h>\n");
19683594Speter	fprintf(ofp, "\n");
19765091Speter	fprintf(ofp, "int hintmode = %d;\n", hintmode);
19861640Speter	fprintf(ofp, "char static_hints[] = {\n");
199163638Simp	STAILQ_FOREACH(hint, &hints, hint_next) {
200163638Simp		ifp = fopen(hint->hint_name, "r");
201163638Simp		if (ifp == NULL)
202163638Simp			err(1, "%s", hint->hint_name);
203230044Skevlo		while (fgets(line, BUFSIZ, ifp) != NULL) {
20461640Speter			/* zap trailing CR and/or LF */
205229403Sed			while ((s = strrchr(line, '\n')) != NULL)
20661640Speter				*s = '\0';
207229403Sed			while ((s = strrchr(line, '\r')) != NULL)
20861640Speter				*s = '\0';
20961640Speter			/* remove # comments */
210229403Sed			s = strchr(line, '#');
21161640Speter			if (s)
21261640Speter				*s = '\0';
21361640Speter			/* remove any whitespace and " characters */
21461640Speter			s = line;
21561640Speter			while (*s) {
21661640Speter				if (*s == ' ' || *s == '\t' || *s == '"') {
21761640Speter					while (*s) {
21861640Speter						s[0] = s[1];
21961640Speter						s++;
22061640Speter					}
22161640Speter					/* start over */
22261640Speter					s = line;
22361640Speter					continue;
22461640Speter				}
22561640Speter				s++;
22661640Speter			}
22761640Speter			/* anything left? */
22861640Speter			if (*line == '\0')
22961652Speter				continue;
23061640Speter			fprintf(ofp, "\"%s\\0\"\n", line);
23161640Speter		}
232163640Simp		fclose(ifp);
23361640Speter	}
23461640Speter	fprintf(ofp, "\"\\0\"\n};\n");
23561640Speter	fclose(ofp);
23661640Speter	moveifchanged(path("hints.c.new"), path("hints.c"));
237153888Sru}
23882393Speter
239153888Sru/*
240153888Sru * Build env.c from the skeleton
241153888Sru */
242153888Sruvoid
243153888Srumakeenv(void)
244153888Sru{
245153888Sru	FILE *ifp, *ofp;
246153888Sru	char line[BUFSIZ];
247153888Sru	char *s;
248153888Sru
24982393Speter	if (env) {
25082393Speter		ifp = fopen(env, "r");
25182393Speter		if (ifp == NULL)
25282393Speter			err(1, "%s", env);
25382393Speter	} else {
25482393Speter		ifp = NULL;
25582393Speter	}
25682393Speter	ofp = fopen(path("env.c.new"), "w");
25782393Speter	if (ofp == NULL)
25882393Speter		err(1, "%s", path("env.c.new"));
25983594Speter	fprintf(ofp, "#include <sys/types.h>\n");
26083594Speter	fprintf(ofp, "#include <sys/systm.h>\n");
26183594Speter	fprintf(ofp, "\n");
26282393Speter	fprintf(ofp, "int envmode = %d;\n", envmode);
26382393Speter	fprintf(ofp, "char static_env[] = {\n");
26482393Speter	if (ifp) {
265230044Skevlo		while (fgets(line, BUFSIZ, ifp) != NULL) {
26682393Speter			/* zap trailing CR and/or LF */
267229403Sed			while ((s = strrchr(line, '\n')) != NULL)
26882393Speter				*s = '\0';
269229403Sed			while ((s = strrchr(line, '\r')) != NULL)
27082393Speter				*s = '\0';
27182393Speter			/* remove # comments */
272229403Sed			s = strchr(line, '#');
27382393Speter			if (s)
27482393Speter				*s = '\0';
27582393Speter			/* remove any whitespace and " characters */
27682393Speter			s = line;
27782393Speter			while (*s) {
27882393Speter				if (*s == ' ' || *s == '\t' || *s == '"') {
27982393Speter					while (*s) {
28082393Speter						s[0] = s[1];
28182393Speter						s++;
28282393Speter					}
28382393Speter					/* start over */
28482393Speter					s = line;
28582393Speter					continue;
28682393Speter				}
28782393Speter				s++;
28882393Speter			}
28982393Speter			/* anything left? */
29082393Speter			if (*line == '\0')
29182393Speter				continue;
29282393Speter			fprintf(ofp, "\"%s\\0\"\n", line);
29382393Speter		}
29482393Speter	}
29582393Speter	fprintf(ofp, "\"\\0\"\n};\n");
29682393Speter	if (ifp)
29782393Speter		fclose(ifp);
29882393Speter	fclose(ofp);
29982393Speter	moveifchanged(path("env.c.new"), path("env.c"));
3001553Srgrimes}
3011553Srgrimes
302129119Scognetstatic void
303129073Scognetread_file(char *fname)
3041553Srgrimes{
305162936Sru	char ifname[MAXPATHLEN];
3061553Srgrimes	FILE *fp;
307152811Sru	struct file_list *tp;
30861640Speter	struct device *dp;
30961640Speter	struct opt *op;
310152811Sru	char *wd, *this, *compilewith, *depends, *clean, *warning;
311219819Sjeff	const char *objprefix;
312269825Simp	int compile, match, nreqs, std, filetype, not,
313269825Simp	    imp_rule, no_obj, before_depend, nowerror;
3141553Srgrimes
3151553Srgrimes	fp = fopen(fname, "r");
31629451Scharnier	if (fp == 0)
31729451Scharnier		err(1, "%s", fname);
3181553Srgrimesnext:
3191553Srgrimes	/*
320162936Sru	 * include "filename"
321269825Simp	 * filename    [ standard | optional ]
322152862Sru	 *	[ dev* [ | dev* ... ] | profiling-routine ] [ no-obj ]
3238857Srgrimes	 *	[ compile-with "compile rule" [no-implicit-rule] ]
3246803Sgibbs	 *      [ dependency "dependency-list"] [ before-depend ]
32554490Speter	 *	[ clean "file-list"] [ warning "text warning" ]
326219819Sjeff	 *	[ obj-prefix "file prefix"]
3271553Srgrimes	 */
3281553Srgrimes	wd = get_word(fp);
3291553Srgrimes	if (wd == (char *)EOF) {
3301553Srgrimes		(void) fclose(fp);
3311553Srgrimes		return;
332129073Scognet	}
3331553Srgrimes	if (wd == 0)
3341553Srgrimes		goto next;
33552098Speter	if (wd[0] == '#')
3361566Srgrimes	{
33752098Speter		while (((wd = get_word(fp)) != (char *)EOF) && wd)
33852098Speter			;
3391566Srgrimes		goto next;
3401566Srgrimes	}
341162936Sru	if (eq(wd, "include")) {
342269825Simp		wd = get_quoted_word(fp);
343269825Simp		if (wd == (char *)EOF || wd == 0)
344269825Simp			errout("%s: missing include filename.\n", fname);
345162936Sru		(void) snprintf(ifname, sizeof(ifname), "../../%s", wd);
346162936Sru		read_file(ifname);
347162936Sru		while (((wd = get_word(fp)) != (char *)EOF) && wd)
348162936Sru			;
349162936Sru		goto next;
350162936Sru	}
3511553Srgrimes	this = ns(wd);
352269825Simp	wd = get_word(fp);
353269825Simp	if (wd == (char *)EOF)
354269825Simp		return;
355269825Simp	if (wd == 0)
356269825Simp		errout("%s: No type for %s.\n", fname, this);
357152811Sru	tp = fl_lookup(this);
358152862Sru	compile = 0;
359152862Sru	match = 1;
3601553Srgrimes	nreqs = 0;
36173199Speter	compilewith = 0;
3624571Sgibbs	depends = 0;
3636803Sgibbs	clean = 0;
36472684Speter	warning = 0;
365269825Simp	std = 0;
3664571Sgibbs	imp_rule = 0;
3674571Sgibbs	no_obj = 0;
3685325Sgibbs	before_depend = 0;
36991002Speter	nowerror = 0;
370269825Simp	not = 0;
3711553Srgrimes	filetype = NORMAL;
372219819Sjeff	objprefix = "";
373269825Simp	if (eq(wd, "standard"))
3741553Srgrimes		std = 1;
375269825Simp	else if (!eq(wd, "optional"))
376269825Simp		errout("%s: \"%s\" %s must be optional or standard\n",
377214654Sobrien		    fname, wd, this);
378269825Simp	for (wd = get_word(fp); wd; wd = get_word(fp)) {
379269825Simp		if (wd == (char *)EOF)
380269825Simp			return;
381269825Simp		if (eq(wd, "!")) {
382269825Simp			not = 1;
383269825Simp			continue;
384152862Sru		}
385269825Simp		if (eq(wd, "|")) {
386269825Simp			if (nreqs == 0)
387269825Simp				errout("%s: syntax error describing %s\n",
388269825Simp				       fname, this);
389269825Simp			if (not)
390269825Simp				compile += !match;
391269825Simp			else
392269825Simp				compile += match;
393269825Simp			match = 1;
394269825Simp			nreqs = 0;
395269825Simp			not = 0;
396269825Simp			continue;
3974571Sgibbs		}
398269825Simp		if (eq(wd, "no-obj")) {
399269825Simp			no_obj++;
400269825Simp			continue;
4014571Sgibbs		}
402269825Simp		if (eq(wd, "no-implicit-rule")) {
403269825Simp			if (compilewith == 0)
404269825Simp				errout("%s: alternate rule required when "
405269825Simp				       "\"no-implicit-rule\" is specified for"
406269825Simp				       " %s.\n",
407269825Simp				       fname, this);
408269825Simp			imp_rule++;
409269825Simp			continue;
4105325Sgibbs		}
411269825Simp		if (eq(wd, "before-depend")) {
412269825Simp			before_depend++;
413269825Simp			continue;
4141553Srgrimes		}
415269825Simp		if (eq(wd, "dependency")) {
416269825Simp			wd = get_quoted_word(fp);
417269825Simp			if (wd == (char *)EOF || wd == 0)
418269825Simp				errout("%s: %s missing dependency string.\n",
419269825Simp				       fname, this);
420269825Simp			depends = ns(wd);
421269825Simp			continue;
42254490Speter		}
423269825Simp		if (eq(wd, "clean")) {
424269825Simp			wd = get_quoted_word(fp);
425269825Simp			if (wd == (char *)EOF || wd == 0)
426269825Simp				errout("%s: %s missing clean file list.\n",
427269825Simp				       fname, this);
428269825Simp			clean = ns(wd);
429269825Simp			continue;
430219819Sjeff		}
431269825Simp		if (eq(wd, "compile-with")) {
432269825Simp			wd = get_quoted_word(fp);
433269825Simp			if (wd == (char *)EOF || wd == 0)
434269825Simp				errout("%s: %s missing compile command string.\n",
435269825Simp				       fname, this);
436269825Simp			compilewith = ns(wd);
437269825Simp			continue;
438152811Sru		}
439269825Simp		if (eq(wd, "warning")) {
440269825Simp			wd = get_quoted_word(fp);
441269825Simp			if (wd == (char *)EOF || wd == 0)
442269825Simp				errout("%s: %s missing warning text string.\n",
443269825Simp				       fname, this);
444269825Simp			warning = ns(wd);
445269825Simp			continue;
446269825Simp		}
447269825Simp		if (eq(wd, "obj-prefix")) {
448269825Simp			wd = get_quoted_word(fp);
449269825Simp			if (wd == (char *)EOF || wd == 0)
450269825Simp				errout("%s: %s missing object prefix string.\n",
451269825Simp				       fname, this);
452269825Simp			objprefix = ns(wd);
453269825Simp			continue;
454269825Simp		}
455269825Simp		if (eq(wd, "nowerror")) {
456269825Simp			nowerror = 1;
457269825Simp			continue;
458269825Simp		}
459269825Simp		if (eq(wd, "local")) {
460269825Simp			filetype = LOCAL;
461269825Simp			continue;
462269825Simp		}
463269825Simp		if (eq(wd, "no-depend")) {
464269825Simp			filetype = NODEPEND;
465269825Simp			continue;
466269825Simp		}
467269825Simp		nreqs++;
468269825Simp		if (eq(wd, "profiling-routine")) {
469269825Simp			filetype = PROFILING;
470269825Simp			continue;
471269825Simp		}
472269825Simp		if (std)
473269825Simp			errout("standard entry %s has optional inclusion specifier %s!\n",
474269825Simp			       this, wd);
475269825Simp		STAILQ_FOREACH(dp, &dtab, d_next)
476269825Simp			if (eq(dp->d_name, wd)) {
477269825Simp				dp->d_done |= DEVDONE;
478269825Simp				goto nextparam;
479269825Simp			}
480269825Simp		SLIST_FOREACH(op, &opt, op_next)
481269825Simp			if (op->op_value == 0 && opteq(op->op_name, wd))
482269825Simp				goto nextparam;
483269825Simp		match = 0;
484269825Simpnextparam:;
48530796Sjoerg	}
486269825Simp	if (not)
487269825Simp		compile += !match;
488269825Simp	else
489269825Simp		compile += match;
490269825Simp	if (compile && tp == NULL) {
491269825Simp		if (std == 0 && nreqs == 0)
492269825Simp			errout("%s: what is %s optional on?\n",
493269825Simp			       fname, this);
494269825Simp		if (filetype == PROFILING && profiling == 0)
495269825Simp			goto next;
496269825Simp		tp = new_fent();
497269825Simp		tp->f_fn = this;
498269825Simp		tp->f_type = filetype;
499269825Simp		if (imp_rule)
500269825Simp			tp->f_flags |= NO_IMPLCT_RULE;
501269825Simp		if (no_obj)
502269825Simp			tp->f_flags |= NO_OBJ;
503269825Simp		if (before_depend)
504269825Simp			tp->f_flags |= BEFORE_DEPEND;
505269825Simp		if (nowerror)
506269825Simp			tp->f_flags |= NOWERROR;
507269825Simp		tp->f_compilewith = compilewith;
508269825Simp		tp->f_depends = depends;
509269825Simp		tp->f_clean = clean;
510269825Simp		tp->f_warn = warning;
511269825Simp		tp->f_objprefix = objprefix;
5121553Srgrimes	}
5131553Srgrimes	goto next;
5141553Srgrimes}
5151553Srgrimes
516129073Scognet/*
517129073Scognet * Read in the information about files used in making the system.
518129073Scognet * Store it in the ftab linked list.
519129073Scognet */
520129073Scognetstatic void
521129073Scognetread_files(void)
522129073Scognet{
523129073Scognet	char fname[MAXPATHLEN];
524129073Scognet	struct files_name *nl, *tnl;
525129073Scognet
526129073Scognet	(void) snprintf(fname, sizeof(fname), "../../conf/files");
527129073Scognet	read_file(fname);
528129073Scognet	(void) snprintf(fname, sizeof(fname),
529129073Scognet		       	"../../conf/files.%s", machinename);
530129073Scognet	read_file(fname);
531129073Scognet	for (nl = STAILQ_FIRST(&fntab); nl != NULL; nl = tnl) {
532129073Scognet		read_file(nl->f_name);
533129073Scognet		tnl = STAILQ_NEXT(nl, f_next);
534129073Scognet		free(nl->f_name);
535129073Scognet		free(nl);
536129073Scognet	}
537129073Scognet}
538129073Scognet
53945744Speterstatic int
54072684Speteropteq(const char *cp, const char *dp)
5411553Srgrimes{
5421553Srgrimes	char c, d;
5431553Srgrimes
5441553Srgrimes	for (; ; cp++, dp++) {
5451553Srgrimes		if (*cp != *dp) {
5461553Srgrimes			c = isupper(*cp) ? tolower(*cp) : *cp;
5471553Srgrimes			d = isupper(*dp) ? tolower(*dp) : *dp;
5481553Srgrimes			if (c != d)
5491553Srgrimes				return (0);
5501553Srgrimes		}
5511553Srgrimes		if (*cp == 0)
5521553Srgrimes			return (1);
5531553Srgrimes	}
5541553Srgrimes}
5551553Srgrimes
55645744Speterstatic void
55761640Speterdo_before_depend(FILE *fp)
5585325Sgibbs{
55961640Speter	struct file_list *tp;
56061640Speter	int lpos, len;
5615325Sgibbs
5625325Sgibbs	fputs("BEFORE_DEPEND=", fp);
5635325Sgibbs	lpos = 15;
564110895Sru	STAILQ_FOREACH(tp, &ftab, f_next)
5655325Sgibbs		if (tp->f_flags & BEFORE_DEPEND) {
5665325Sgibbs			len = strlen(tp->f_fn);
5675325Sgibbs			if ((len = 3 + len) + lpos > 72) {
5685325Sgibbs				lpos = 8;
5695325Sgibbs				fputs("\\\n\t", fp);
5705325Sgibbs			}
5715325Sgibbs			if (tp->f_flags & NO_IMPLCT_RULE)
5725325Sgibbs				fprintf(fp, "%s ", tp->f_fn);
5735325Sgibbs			else
5745325Sgibbs				fprintf(fp, "$S/%s ", tp->f_fn);
5755325Sgibbs			lpos += len + 1;
5765325Sgibbs		}
5775325Sgibbs	if (lpos != 8)
5785325Sgibbs		putc('\n', fp);
5795325Sgibbs}
5805325Sgibbs
58145744Speterstatic void
58261640Speterdo_objs(FILE *fp)
5831553Srgrimes{
58461640Speter	struct file_list *tp;
58561640Speter	int lpos, len;
58661640Speter	char *cp, och, *sp;
5871553Srgrimes
5881553Srgrimes	fprintf(fp, "OBJS=");
5891553Srgrimes	lpos = 6;
590110895Sru	STAILQ_FOREACH(tp, &ftab, f_next) {
591152811Sru		if (tp->f_flags & NO_OBJ)
5921553Srgrimes			continue;
5931553Srgrimes		sp = tail(tp->f_fn);
5941553Srgrimes		cp = sp + (len = strlen(sp)) - 1;
5951553Srgrimes		och = *cp;
5961553Srgrimes		*cp = 'o';
597219819Sjeff		len += strlen(tp->f_objprefix);
5981553Srgrimes		if (len + lpos > 72) {
5991553Srgrimes			lpos = 8;
6001553Srgrimes			fprintf(fp, "\\\n\t");
6011553Srgrimes		}
602219819Sjeff		fprintf(fp, "%s%s ", tp->f_objprefix, sp);
6031553Srgrimes		lpos += len + 1;
6041553Srgrimes		*cp = och;
6051553Srgrimes	}
6061553Srgrimes	if (lpos != 8)
6071553Srgrimes		putc('\n', fp);
6081553Srgrimes}
6091553Srgrimes
61045744Speterstatic void
61169135Speterdo_xxfiles(char *tag, FILE *fp)
6121553Srgrimes{
61361640Speter	struct file_list *tp;
61469135Speter	int lpos, len, slen;
61569135Speter	char *suff, *SUFF;
6161553Srgrimes
61769135Speter	if (tag[strlen(tag) - 1] == '\n')
61869135Speter		tag[strlen(tag) - 1] = '\0';
61969135Speter
62069135Speter	suff = ns(tag + 7);
62169135Speter	SUFF = ns(suff);
62269135Speter	raisestr(SUFF);
62369135Speter	slen = strlen(suff);
62469135Speter
62569135Speter	fprintf(fp, "%sFILES=", SUFF);
6261553Srgrimes	lpos = 8;
627110895Sru	STAILQ_FOREACH(tp, &ftab, f_next)
628152811Sru		if (tp->f_type != NODEPEND) {
6291553Srgrimes			len = strlen(tp->f_fn);
63069135Speter			if (tp->f_fn[len - slen - 1] != '.')
6311553Srgrimes				continue;
63269135Speter			if (strcasecmp(&tp->f_fn[len - slen], suff) != 0)
63369135Speter				continue;
6341553Srgrimes			if ((len = 3 + len) + lpos > 72) {
6351553Srgrimes				lpos = 8;
6361553Srgrimes				fputs("\\\n\t", fp);
6371553Srgrimes			}
63838782Snsouch			if (tp->f_type != LOCAL)
63938782Snsouch				fprintf(fp, "$S/%s ", tp->f_fn);
64038782Snsouch			else
64138782Snsouch				fprintf(fp, "%s ", tp->f_fn);
6421553Srgrimes			lpos += len + 1;
6431553Srgrimes		}
6441553Srgrimes	if (lpos != 8)
6451553Srgrimes		putc('\n', fp);
6461553Srgrimes}
6471553Srgrimes
64845744Speterstatic char *
64961640Spetertail(char *fn)
6501553Srgrimes{
65161640Speter	char *cp;
6521553Srgrimes
653229403Sed	cp = strrchr(fn, '/');
6541553Srgrimes	if (cp == 0)
6551553Srgrimes		return (fn);
6561553Srgrimes	return (cp+1);
6571553Srgrimes}
6581553Srgrimes
6591553Srgrimes/*
6601553Srgrimes * Create the makerules for each file
6611553Srgrimes * which is part of the system.
6621553Srgrimes */
66345744Speterstatic void
66461640Speterdo_rules(FILE *f)
6651553Srgrimes{
666160495Sstefanf	char *cp, *np, och;
66761640Speter	struct file_list *ftp;
66873199Speter	char *compilewith;
669209135Simp	char cmd[128];
6701553Srgrimes
671110895Sru	STAILQ_FOREACH(ftp, &ftab, f_next) {
67254490Speter		if (ftp->f_warn)
673210144Simp			fprintf(stderr, "WARNING: %s\n", ftp->f_warn);
6741553Srgrimes		cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
6751553Srgrimes		och = *cp;
6764571Sgibbs		if (ftp->f_flags & NO_IMPLCT_RULE) {
6774571Sgibbs			if (ftp->f_depends)
678219819Sjeff				fprintf(f, "%s%s: %s\n",
679219819Sjeff					ftp->f_objprefix, np, ftp->f_depends);
6804571Sgibbs			else
681219819Sjeff				fprintf(f, "%s%s: \n", ftp->f_objprefix, np);
6821553Srgrimes		}
6834571Sgibbs		else {
6844571Sgibbs			*cp = '\0';
6854571Sgibbs			if (och == 'o') {
686219819Sjeff				fprintf(f, "%s%so:\n\t-cp $S/%so .\n\n",
687219819Sjeff					ftp->f_objprefix, tail(np), np);
6884571Sgibbs				continue;
6894571Sgibbs			}
690116450Smarkm			if (ftp->f_depends) {
691219819Sjeff				fprintf(f, "%s%sln: $S/%s%c %s\n",
692219819Sjeff					ftp->f_objprefix, tail(np), np, och,
693219819Sjeff					ftp->f_depends);
694116450Smarkm				fprintf(f, "\t${NORMAL_LINT}\n\n");
695219819Sjeff				fprintf(f, "%s%so: $S/%s%c %s\n",
696219819Sjeff					ftp->f_objprefix, tail(np), np, och,
697219819Sjeff					ftp->f_depends);
698116450Smarkm			}
699116450Smarkm			else {
700219819Sjeff				fprintf(f, "%s%sln: $S/%s%c\n",
701219819Sjeff					ftp->f_objprefix, tail(np), np, och);
702116450Smarkm				fprintf(f, "\t${NORMAL_LINT}\n\n");
703219819Sjeff				fprintf(f, "%s%so: $S/%s%c\n",
704219819Sjeff					ftp->f_objprefix, tail(np), np, och);
705116450Smarkm			}
7064571Sgibbs		}
70773199Speter		compilewith = ftp->f_compilewith;
70873199Speter		if (compilewith == 0) {
70972684Speter			const char *ftype = NULL;
7101553Srgrimes
7111553Srgrimes			switch (ftp->f_type) {
7121553Srgrimes			case NORMAL:
7131553Srgrimes				ftype = "NORMAL";
7141553Srgrimes				break;
7151553Srgrimes			case PROFILING:
7161553Srgrimes				if (!profiling)
7171553Srgrimes					continue;
7181553Srgrimes				ftype = "PROFILE";
7191553Srgrimes				break;
7201553Srgrimes			default:
721210144Simp				fprintf(stderr,
722210144Simp				    "config: don't know rules for %s\n", np);
7231553Srgrimes				break;
7241553Srgrimes			}
725209135Simp			snprintf(cmd, sizeof(cmd),
726241395Sjhb			    "${%s_%c%s}", ftype,
72791002Speter			    toupper(och),
72891002Speter			    ftp->f_flags & NOWERROR ? "_NOWERROR" : "");
72973199Speter			compilewith = cmd;
7301553Srgrimes		}
7311553Srgrimes		*cp = och;
732219819Sjeff		if (strlen(ftp->f_objprefix))
733227429Srstone			fprintf(f, "\t%s $S/%s\n", compilewith, np);
734219819Sjeff		else
735227429Srstone			fprintf(f, "\t%s\n", compilewith);
736227429Srstone
737227429Srstone		if (!(ftp->f_flags & NO_OBJ))
738228153Sfjoe			fprintf(f, "\t${NORMAL_CTFCONVERT}\n\n");
739227429Srstone		else
740227429Srstone			fprintf(f, "\n");
7411553Srgrimes	}
7421553Srgrimes}
7431553Srgrimes
74445744Speterstatic void
74561640Speterdo_clean(FILE *fp)
7466803Sgibbs{
74761640Speter	struct file_list *tp;
74861640Speter	int lpos, len;
7496803Sgibbs
7506803Sgibbs	fputs("CLEAN=", fp);
7516803Sgibbs	lpos = 7;
752110895Sru	STAILQ_FOREACH(tp, &ftab, f_next)
7536803Sgibbs		if (tp->f_clean) {
7546803Sgibbs			len = strlen(tp->f_clean);
7556803Sgibbs			if (len + lpos > 72) {
7566803Sgibbs				lpos = 8;
7576803Sgibbs				fputs("\\\n\t", fp);
7586803Sgibbs			}
7596803Sgibbs			fprintf(fp, "%s ", tp->f_clean);
7606803Sgibbs			lpos += len + 1;
7616803Sgibbs		}
7626803Sgibbs	if (lpos != 8)
7636803Sgibbs		putc('\n', fp);
7646803Sgibbs}
7656803Sgibbs
7661553Srgrimeschar *
76761640Speterraisestr(char *str)
7681553Srgrimes{
76961640Speter	char *cp = str;
7701553Srgrimes
7711553Srgrimes	while (*str) {
7721553Srgrimes		if (islower(*str))
7731553Srgrimes			*str = toupper(*str);
7741553Srgrimes		str++;
7751553Srgrimes	}
7761553Srgrimes	return (cp);
7771553Srgrimes}
778