mkmakefile.c revision 152811
11573Srgrimes/*
21573Srgrimes * Copyright (c) 1993, 19801990
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes * 4. Neither the name of the University nor the names of its contributors
141573Srgrimes *    may be used to endorse or promote products derived from this software
151573Srgrimes *    without specific prior written permission.
161573Srgrimes *
171573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271573Srgrimes * SUCH DAMAGE.
281573Srgrimes */
291573Srgrimes
301573Srgrimes#ifndef lint
311573Srgrimes#if 0
321573Srgrimesstatic char sccsid[] = "@(#)mkmakefile.c	8.1 (Berkeley) 6/6/93";
331573Srgrimes#endif
341573Srgrimesstatic const char rcsid[] =
351573Srgrimes  "$FreeBSD: head/usr.sbin/config/mkmakefile.c 152811 2005-11-25 22:25:34Z ru $";
361573Srgrimes#endif /* not lint */
371573Srgrimes
3823668Speter/*
391573Srgrimes * Build the makefile for the system, from
4090041Sobrien * the information in the files files and the
4190041Sobrien * additional files for the machine being compiled to.
421573Srgrimes */
431573Srgrimes
441573Srgrimes#include <ctype.h>
457615Swpaul#include <err.h>
467615Swpaul#include <stdio.h>
471573Srgrimes#include <string.h>
487615Swpaul#include <sys/param.h>
499978Swpaul#include "y.tab.h"
509978Swpaul#include "config.h"
519978Swpaul#include "configvers.h"
529978Swpaul
539978Swpaul#define next_word(fp, wd) \
549978Swpaul	{ char *word = get_word(fp); \
559978Swpaul	  if (word == (char *)EOF) \
569978Swpaul		return; \
579978Swpaul	  else \
589978Swpaul		wd = word; \
599978Swpaul	}
609978Swpaul#define next_quoted_word(fp, wd) \
619978Swpaul	{ char *word = get_quoted_word(fp); \
629978Swpaul	  if (word == (char *)EOF) \
639978Swpaul		return; \
649978Swpaul	  else \
659978Swpaul		wd = word; \
669978Swpaul	}
679978Swpaul
689978Swpaulstatic char *tail(char *);
699978Swpaulstatic void do_clean(FILE *);
709978Swpaulstatic void do_rules(FILE *);
719978Swpaulstatic void do_xxfiles(char *, FILE *);
729978Swpaulstatic void do_objs(FILE *);
739978Swpaulstatic void do_before_depend(FILE *);
749978Swpaulstatic int opteq(const char *, const char *);
759978Swpaulstatic void read_files(void);
769978Swpaul
779978Swpaul/*
789978Swpaul * Lookup a file, by name.
799978Swpaul */
809978Swpaulstatic struct file_list *
819978Swpaulfl_lookup(char *file)
829978Swpaul{
839978Swpaul	struct file_list *fp;
849978Swpaul
859978Swpaul	STAILQ_FOREACH(fp, &ftab, f_next) {
869978Swpaul		if (eq(fp->f_fn, file))
8730288Swpaul			return (fp);
887615Swpaul	}
897615Swpaul	return (0);
907615Swpaul}
919978Swpaul
929978Swpaul/*
939978Swpaul * Make a new file list entry
949978Swpaul */
959978Swpaulstatic struct file_list *
9610521Swpaulnew_fent(void)
977615Swpaul{
989978Swpaul	struct file_list *fp;
997615Swpaul
1007615Swpaul	fp = (struct file_list *) malloc(sizeof *fp);
1019978Swpaul	bzero(fp, sizeof *fp);
1021573Srgrimes	STAILQ_INSERT_TAIL(&ftab, fp, f_next);
1039978Swpaul	return (fp);
1041573Srgrimes}
1051573Srgrimes
1061573Srgrimes/*
1071573Srgrimes * Build the makefile from the skeleton
1081573Srgrimes */
1091573Srgrimesvoid
1101573Srgrimesmakefile(void)
1111573Srgrimes{
1121573Srgrimes	FILE *ifp, *ofp;
1131573Srgrimes	char line[BUFSIZ];
1141573Srgrimes	struct opt *op;
1151573Srgrimes	int versreq;
1161573Srgrimes	char *s;
1171573Srgrimes
1181573Srgrimes	read_files();
1191573Srgrimes	snprintf(line, sizeof(line), "../../conf/Makefile.%s", machinename);
1201573Srgrimes	ifp = fopen(line, "r");
1211573Srgrimes	if (ifp == 0) {
1221573Srgrimes		snprintf(line, sizeof(line), "Makefile.%s", machinename);
1231573Srgrimes		ifp = fopen(line, "r");
1241573Srgrimes	}
1251573Srgrimes	if (ifp == 0)
1261573Srgrimes		err(1, "%s", line);
1271573Srgrimes
1281573Srgrimes	/* XXX this check seems to be misplaced. */
1291573Srgrimes	if (SLIST_EMPTY(&cputype)) {
1301573Srgrimes		printf("cpu type must be specified\n");
1311573Srgrimes		exit(1);
1321573Srgrimes	}
1331573Srgrimes
1341573Srgrimes	ofp = fopen(path("Makefile.new"), "w");
1351573Srgrimes	if (ofp == 0)
1361573Srgrimes		err(1, "%s", path("Makefile.new"));
1371573Srgrimes	fprintf(ofp, "KERN_IDENT=%s\n", ident);
1381573Srgrimes	SLIST_FOREACH(op, &mkopt, op_next)
1391573Srgrimes		fprintf(ofp, "%s=%s\n", op->op_name, op->op_value);
1401573Srgrimes	if (debugging)
1411573Srgrimes		fprintf(ofp, "DEBUG=-g\n");
1421573Srgrimes	if (profiling)
1431573Srgrimes		fprintf(ofp, "PROFLEVEL=%d\n", profiling);
1441573Srgrimes	if (*srcdir != '\0')
1451573Srgrimes		fprintf(ofp,"S=%s\n", srcdir);
1461573Srgrimes	while (fgets(line, BUFSIZ, ifp) != 0) {
1471573Srgrimes		if (*line != '%') {
1481573Srgrimes			fprintf(ofp, "%s", line);
1491573Srgrimes			continue;
1501573Srgrimes		}
1511573Srgrimes		if (eq(line, "%BEFORE_DEPEND\n"))
1521573Srgrimes			do_before_depend(ofp);
1531573Srgrimes		else if (eq(line, "%OBJS\n"))
1541573Srgrimes			do_objs(ofp);
1559978Swpaul		else if (strncmp(line, "%FILES.", 7) == 0)
1569978Swpaul			do_xxfiles(line, ofp);
1579978Swpaul		else if (eq(line, "%RULES\n"))
1589978Swpaul			do_rules(ofp);
1599978Swpaul		else if (eq(line, "%CLEAN\n"))
1607336Swpaul			do_clean(ofp);
1617289Swpaul		else if (strncmp(line, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) {
1627336Swpaul			versreq = atoi(line + sizeof("%VERSREQ=") - 1);
1637289Swpaul			if (versreq != CONFIGVERS) {
1647336Swpaul				fprintf(stderr, "ERROR: version of config(8) does not match kernel!\n");
1651573Srgrimes				fprintf(stderr, "config version = %d, ", CONFIGVERS);
1661573Srgrimes				fprintf(stderr, "version required = %d\n\n", versreq);
1671573Srgrimes				fprintf(stderr, "Make sure that /usr/src/usr.sbin/config is in sync\n");
1689978Swpaul				fprintf(stderr, "with your /usr/src/sys and install a new config binary\n");
16910521Swpaul				fprintf(stderr, "before trying this again.\n\n");
17010521Swpaul				fprintf(stderr, "If running the new config fails check your config\n");
1719978Swpaul				fprintf(stderr, "file against the GENERIC or LINT config files for\n");
17215264Swpaul				fprintf(stderr, "changes in config syntax, or option/device naming\n");
1739978Swpaul				fprintf(stderr, "conventions\n\n");
1749978Swpaul				exit(1);
1759978Swpaul			}
1769978Swpaul		} else
1779978Swpaul			fprintf(stderr,
1789978Swpaul			    "Unknown %% construct in generic makefile: %s",
1799978Swpaul			    line);
1809978Swpaul	}
1819978Swpaul	(void) fclose(ifp);
1829978Swpaul	(void) fclose(ofp);
1839978Swpaul	moveifchanged(path("Makefile.new"), path("Makefile"));
1849978Swpaul
1859978Swpaul	/* XXX makefile() should make the Makefile, not hints.c. */
1869978Swpaul	if (hints) {
1879978Swpaul		ifp = fopen(hints, "r");
1889978Swpaul		if (ifp == NULL)
1899978Swpaul			err(1, "%s", hints);
1909978Swpaul	} else {
1919978Swpaul		ifp = NULL;
1929978Swpaul	}
1939978Swpaul	ofp = fopen(path("hints.c.new"), "w");
1949978Swpaul	if (ofp == NULL)
19510521Swpaul		err(1, "%s", path("hints.c.new"));
19610521Swpaul	fprintf(ofp, "#include <sys/types.h>\n");
19712585Swpaul	fprintf(ofp, "#include <sys/systm.h>\n");
19812585Swpaul	fprintf(ofp, "\n");
1999978Swpaul	fprintf(ofp, "int hintmode = %d;\n", hintmode);
20010521Swpaul	fprintf(ofp, "char static_hints[] = {\n");
2019978Swpaul	if (ifp) {
2021573Srgrimes		while (fgets(line, BUFSIZ, ifp) != 0) {
2039978Swpaul			/* zap trailing CR and/or LF */
2041573Srgrimes			while ((s = rindex(line, '\n')) != NULL)
2051573Srgrimes				*s = '\0';
2061573Srgrimes			while ((s = rindex(line, '\r')) != NULL)
2071573Srgrimes				*s = '\0';
2081573Srgrimes			/* remove # comments */
2091573Srgrimes			s = index(line, '#');
2101573Srgrimes			if (s)
2119978Swpaul				*s = '\0';
2129978Swpaul			/* remove any whitespace and " characters */
2131573Srgrimes			s = line;
2141573Srgrimes			while (*s) {
2151573Srgrimes				if (*s == ' ' || *s == '\t' || *s == '"') {
2161573Srgrimes					while (*s) {
2171573Srgrimes						s[0] = s[1];
2181573Srgrimes						s++;
2191573Srgrimes					}
2201573Srgrimes					/* start over */
2211573Srgrimes					s = line;
2221573Srgrimes					continue;
2231573Srgrimes				}
2241573Srgrimes				s++;
2259978Swpaul			}
2269978Swpaul			/* anything left? */
2279978Swpaul			if (*line == '\0')
2281573Srgrimes				continue;
2291573Srgrimes			fprintf(ofp, "\"%s\\0\"\n", line);
2301573Srgrimes		}
2311573Srgrimes	}
2321573Srgrimes	fprintf(ofp, "\"\\0\"\n};\n");
2331573Srgrimes	if (ifp)
2341573Srgrimes		fclose(ifp);
2351573Srgrimes	fclose(ofp);
2361573Srgrimes	moveifchanged(path("hints.c.new"), path("hints.c"));
2371573Srgrimes
2381573Srgrimes	/* XXX makefile() should make the Makefile, not env.c. */
2391573Srgrimes	if (env) {
2401573Srgrimes		ifp = fopen(env, "r");
2411573Srgrimes		if (ifp == NULL)
2421573Srgrimes			err(1, "%s", env);
2431573Srgrimes	} else {
2441573Srgrimes		ifp = NULL;
24590041Sobrien	}
24690041Sobrien	ofp = fopen(path("env.c.new"), "w");
2471573Srgrimes	if (ofp == NULL)
2481573Srgrimes		err(1, "%s", path("env.c.new"));
2491573Srgrimes	fprintf(ofp, "#include <sys/types.h>\n");
2501573Srgrimes	fprintf(ofp, "#include <sys/systm.h>\n");
2511573Srgrimes	fprintf(ofp, "\n");
2521573Srgrimes	fprintf(ofp, "int envmode = %d;\n", envmode);
2531573Srgrimes	fprintf(ofp, "char static_env[] = {\n");
2541573Srgrimes	if (ifp) {
2551573Srgrimes		while (fgets(line, BUFSIZ, ifp) != 0) {
2561573Srgrimes			/* zap trailing CR and/or LF */
2571573Srgrimes			while ((s = rindex(line, '\n')) != NULL)
2581573Srgrimes				*s = '\0';
2591573Srgrimes			while ((s = rindex(line, '\r')) != NULL)
2601573Srgrimes				*s = '\0';
2611573Srgrimes			/* remove # comments */
2621573Srgrimes			s = index(line, '#');
2631573Srgrimes			if (s)
2641573Srgrimes				*s = '\0';
2651573Srgrimes			/* remove any whitespace and " characters */
2661573Srgrimes			s = line;
2671573Srgrimes			while (*s) {
2681573Srgrimes				if (*s == ' ' || *s == '\t' || *s == '"') {
2691573Srgrimes					while (*s) {
2701573Srgrimes						s[0] = s[1];
2711573Srgrimes						s++;
2721573Srgrimes					}
2731573Srgrimes					/* start over */
2747149Swpaul					s = line;
2757223Swpaul					continue;
2767149Swpaul				}
2771573Srgrimes				s++;
2781573Srgrimes			}
2799978Swpaul			/* anything left? */
2809998Swpaul			if (*line == '\0')
28131180Swpaul				continue;
28231180Swpaul			fprintf(ofp, "\"%s\\0\"\n", line);
2839978Swpaul		}
28431180Swpaul	}
28531180Swpaul	fprintf(ofp, "\"\\0\"\n};\n");
2869978Swpaul	if (ifp)
28731180Swpaul		fclose(ifp);
28852856Sache	fclose(ofp);
28931180Swpaul	moveifchanged(path("env.c.new"), path("env.c"));
29015264Swpaul}
29133950Ssteve
29233950Sstevestatic void
29352856Sacheread_file(char *fname)
29433950Ssteve{
29533950Ssteve	FILE *fp;
29615839Swpaul	struct file_list *tp;
29752856Sache	struct device *dp;
29833950Ssteve	struct opt *op;
29915839Swpaul	char *wd, *this, *compilewith, *depends, *clean, *warning;
30015839Swpaul	int nreqs, devfound, std, filetype,
3019978Swpaul	    imp_rule, no_obj, before_depend, mandatory, nowerror;
3029978Swpaul
3039978Swpaul	fp = fopen(fname, "r");
3049978Swpaul	if (fp == 0)
3059978Swpaul		err(1, "%s", fname);
3069978Swpaulnext:
3079978Swpaul	/*
3089978Swpaul	 * filename    [ standard | mandatory | optional ]
3099978Swpaul	 *	[ dev* | profiling-routine ] [ no-obj ]
3109978Swpaul	 *	[ compile-with "compile rule" [no-implicit-rule] ]
3119978Swpaul	 *      [ dependency "dependency-list"] [ before-depend ]
3129978Swpaul	 *	[ clean "file-list"] [ warning "text warning" ]
3139978Swpaul	 */
3149978Swpaul	wd = get_word(fp);
3159978Swpaul	if (wd == (char *)EOF) {
3169978Swpaul		(void) fclose(fp);
3179978Swpaul		return;
3189978Swpaul	}
3199978Swpaul	if (wd == 0)
3209978Swpaul		goto next;
3219978Swpaul	if (wd[0] == '#')
3229978Swpaul	{
3239978Swpaul		while (((wd = get_word(fp)) != (char *)EOF) && wd)
3249978Swpaul			;
3251573Srgrimes		goto next;
3261573Srgrimes	}
3271573Srgrimes	this = ns(wd);
3281573Srgrimes	next_word(fp, wd);
3291573Srgrimes	if (wd == 0) {
33017141Sjkh		printf("%s: No type for %s.\n",
3311573Srgrimes		    fname, this);
3321573Srgrimes		exit(1);
3339978Swpaul	}
3349978Swpaul	tp = fl_lookup(this);
3359978Swpaul	nreqs = 0;
33615264Swpaul	compilewith = 0;
3379978Swpaul	depends = 0;
3387336Swpaul	clean = 0;
3399287Swpaul	warning = 0;
3407336Swpaul	std = mandatory = 0;
3417336Swpaul	imp_rule = 0;
3427336Swpaul	no_obj = 0;
3439978Swpaul	before_depend = 0;
3449978Swpaul	nowerror = 0;
3459978Swpaul	filetype = NORMAL;
3461573Srgrimes	if (eq(wd, "standard")) {
3479978Swpaul		std = 1;
34815264Swpaul	/*
3499978Swpaul	 * If an entry is marked "mandatory", config will abort if it's
3509978Swpaul	 * not called by a configuration line in the config file.  Apart
3519978Swpaul	 * from this, the device is handled like one marked "optional".
3529978Swpaul	 */
3539978Swpaul	} else if (eq(wd, "mandatory")) {
3549978Swpaul		mandatory = 1;
35530390Swpaul	} else if (!eq(wd, "optional")) {
3569978Swpaul		printf("%s: %s must be optional, mandatory or standard\n",
3579978Swpaul		       fname, this);
3589978Swpaul		exit(1);
35920161Sjkh	}
36030390Swpaulnextparam:
3619978Swpaul	next_word(fp, wd);
36230390Swpaul	if (wd == 0) {
36330390Swpaul		if (tp != NULL)
36430390Swpaul			goto next;
36530390Swpaul		goto doneparam;
36630390Swpaul	}
36730390Swpaul	if (eq(wd, "no-obj")) {
36830390Swpaul		no_obj++;
36930390Swpaul		goto nextparam;
37030390Swpaul	}
37130390Swpaul	if (eq(wd, "no-implicit-rule")) {
37215264Swpaul		if (compilewith == 0) {
37315264Swpaul			printf("%s: alternate rule required when "
37415264Swpaul			       "\"no-implicit-rule\" is specified.\n",
3759978Swpaul			       fname);
37615264Swpaul		}
37715264Swpaul		imp_rule++;
3789978Swpaul		goto nextparam;
3799978Swpaul	}
38030390Swpaul	if (eq(wd, "before-depend")) {
38130390Swpaul		before_depend++;
38230390Swpaul		goto nextparam;
38330390Swpaul	}
38430390Swpaul	if (eq(wd, "dependency")) {
38530390Swpaul		next_quoted_word(fp, wd);
38630390Swpaul		if (wd == 0) {
38730390Swpaul			printf("%s: %s missing compile command string.\n",
38830390Swpaul			       fname, this);
38930390Swpaul			exit(1);
39030390Swpaul		}
3919978Swpaul		depends = ns(wd);
39230390Swpaul		goto nextparam;
3939978Swpaul	}
3949978Swpaul	if (eq(wd, "clean")) {
39530390Swpaul		next_quoted_word(fp, wd);
3961573Srgrimes		if (wd == 0) {
3979978Swpaul			printf("%s: %s missing clean file list.\n",
3989978Swpaul			       fname, this);
3999978Swpaul			exit(1);
4001573Srgrimes		}
4011573Srgrimes		clean = ns(wd);
4021573Srgrimes		goto nextparam;
4031573Srgrimes	}
4041573Srgrimes	if (eq(wd, "compile-with")) {
4051573Srgrimes		next_quoted_word(fp, wd);
4061573Srgrimes		if (wd == 0) {
4071573Srgrimes			printf("%s: %s missing compile command string.\n",
4081573Srgrimes			       fname, this);
4091573Srgrimes			exit(1);
4101573Srgrimes		}
4111573Srgrimes		compilewith = ns(wd);
4121573Srgrimes		goto nextparam;
4131573Srgrimes	}
41490041Sobrien	if (eq(wd, "warning")) {
41590041Sobrien		next_quoted_word(fp, wd);
4169287Swpaul		if (wd == 0) {
41790041Sobrien			printf("%s: %s missing warning text string.\n",
4189287Swpaul				fname, this);
4191573Srgrimes			exit(1);
4201573Srgrimes		}
4211573Srgrimes		warning = ns(wd);
4221573Srgrimes		goto nextparam;
4231573Srgrimes	}
4241573Srgrimes	nreqs++;
4251573Srgrimes	if (eq(wd, "local")) {
4261573Srgrimes		filetype = LOCAL;
4271573Srgrimes		goto nextparam;
4281573Srgrimes	}
4291573Srgrimes	if (eq(wd, "no-depend")) {
4301573Srgrimes		filetype = NODEPEND;
4311573Srgrimes		goto nextparam;
4321573Srgrimes	}
4331573Srgrimes	if (eq(wd, "profiling-routine")) {
4341573Srgrimes		filetype = PROFILING;
4359287Swpaul		goto nextparam;
4369287Swpaul	}
4379287Swpaul	if (eq(wd, "nowerror")) {
4389287Swpaul		nowerror = 1;
4399287Swpaul		goto nextparam;
4409287Swpaul	}
4419287Swpaul	devfound = 0;		/* XXX duplicate device entries */
4421573Srgrimes	STAILQ_FOREACH(dp, &dtab, d_next)
4439287Swpaul		if (eq(dp->d_name, wd)) {
4441573Srgrimes			dp->d_done |= DEVDONE;
4451573Srgrimes			devfound = 1;
4461573Srgrimes		}
4471573Srgrimes	if (devfound)
4487149Swpaul		goto nextparam;
4497149Swpaul	if (tp != NULL)
4501573Srgrimes		goto skip;
4511573Srgrimes	if (mandatory) {
4521573Srgrimes		printf("%s: mandatory device \"%s\" not found\n",
4531573Srgrimes		       fname, wd);
4541573Srgrimes		exit(1);
4551573Srgrimes	}
4561573Srgrimes	if (std) {
4579287Swpaul		printf("standard entry %s has a device keyword - %s!\n",
4589287Swpaul		       this, wd);
4599287Swpaul		exit(1);
4601573Srgrimes	}
4619978Swpaul	SLIST_FOREACH(op, &opt, op_next)
4629287Swpaul		if (op->op_value == 0 && opteq(op->op_name, wd))
4639287Swpaul			goto nextparam;
4649287Swpaulskip:
4651573Srgrimes	while ((wd = get_word(fp)) != 0)
4661573Srgrimes		;
4679978Swpaul	goto next;
4681573Srgrimes
4691573Srgrimesdoneparam:
4701573Srgrimes	if (std == 0 && nreqs == 0) {
4711573Srgrimes		printf("%s: what is %s optional on?\n",
4721573Srgrimes		    fname, this);
4731573Srgrimes		exit(1);
4741573Srgrimes	}
4751573Srgrimes
4761573Srgrimes	if (wd) {
4771573Srgrimes		printf("%s: syntax error describing %s\n",
4789287Swpaul		    fname, this);
4799287Swpaul		exit(1);
4809287Swpaul	}
4819287Swpaul	if (filetype == PROFILING && profiling == 0)
4829287Swpaul		goto next;
4839287Swpaul	tp = new_fent();
4849287Swpaul	tp->f_fn = this;
4859287Swpaul	tp->f_type = filetype;
4869287Swpaul	if (imp_rule)
4871573Srgrimes		tp->f_flags |= NO_IMPLCT_RULE;
4889287Swpaul	if (no_obj)
4899287Swpaul		tp->f_flags |= NO_OBJ;
4909287Swpaul	if (before_depend)
4919287Swpaul		tp->f_flags |= BEFORE_DEPEND;
4929287Swpaul	if (nowerror)
4939287Swpaul		tp->f_flags |= NOWERROR;
4949287Swpaul	tp->f_compilewith = compilewith;
4959287Swpaul	tp->f_depends = depends;
4969287Swpaul	tp->f_clean = clean;
4979287Swpaul	tp->f_warn = warning;
4989287Swpaul	goto next;
4999287Swpaul}
5009287Swpaul
5019287Swpaul/*
5029287Swpaul * Read in the information about files used in making the system.
5039287Swpaul * Store it in the ftab linked list.
5041573Srgrimes */
5051573Srgrimesstatic void
5061573Srgrimesread_files(void)
5077175Swpaul{
5081573Srgrimes	char fname[MAXPATHLEN];
50923668Speter	struct files_name *nl, *tnl;
51023668Speter
51123668Speter	if (ident == NULL) {
51223668Speter		printf("no ident line specified\n");
5131573Srgrimes		exit(1);
5141573Srgrimes	}
5151573Srgrimes	(void) snprintf(fname, sizeof(fname), "../../conf/files");
5161573Srgrimes	read_file(fname);
5171573Srgrimes	(void) snprintf(fname, sizeof(fname),
5181573Srgrimes		       	"../../conf/files.%s", machinename);
5191573Srgrimes	read_file(fname);
5201573Srgrimes	for (nl = STAILQ_FIRST(&fntab); nl != NULL; nl = tnl) {
5211573Srgrimes		read_file(nl->f_name);
5221573Srgrimes		tnl = STAILQ_NEXT(nl, f_next);
5231573Srgrimes		free(nl->f_name);
5241573Srgrimes		free(nl);
52590041Sobrien	}
52690041Sobrien}
5271573Srgrimes
5281573Srgrimesstatic int
52920957Swpaulopteq(const char *cp, const char *dp)
5307149Swpaul{
5317149Swpaul	char c, d;
5327149Swpaul
5331573Srgrimes	for (; ; cp++, dp++) {
5347149Swpaul		if (*cp != *dp) {
5357149Swpaul			c = isupper(*cp) ? tolower(*cp) : *cp;
5367149Swpaul			d = isupper(*dp) ? tolower(*dp) : *dp;
5377223Swpaul			if (c != d)
5387149Swpaul				return (0);
5397223Swpaul		}
5407223Swpaul		if (*cp == 0)
5417223Swpaul			return (1);
5429978Swpaul	}
5439978Swpaul}
5449978Swpaul
5459978Swpaulstatic void
5469978Swpauldo_before_depend(FILE *fp)
5479978Swpaul{
5487149Swpaul	struct file_list *tp;
54920957Swpaul	int lpos, len;
5507149Swpaul
5517149Swpaul	fputs("BEFORE_DEPEND=", fp);
5527149Swpaul	lpos = 15;
5531573Srgrimes	STAILQ_FOREACH(tp, &ftab, f_next)
5547149Swpaul		if (tp->f_flags & BEFORE_DEPEND) {
5557149Swpaul			len = strlen(tp->f_fn);
5567149Swpaul			if ((len = 3 + len) + lpos > 72) {
5577149Swpaul				lpos = 8;
5587149Swpaul				fputs("\\\n\t", fp);
5597149Swpaul			}
5607149Swpaul			if (tp->f_flags & NO_IMPLCT_RULE)
5617149Swpaul				fprintf(fp, "%s ", tp->f_fn);
5621573Srgrimes			else
5631573Srgrimes				fprintf(fp, "$S/%s ", tp->f_fn);
5641573Srgrimes			lpos += len + 1;
5651573Srgrimes		}
5661573Srgrimes	if (lpos != 8)
5671573Srgrimes		putc('\n', fp);
5681573Srgrimes}
5691573Srgrimes
5701573Srgrimesstatic void
5711573Srgrimesdo_objs(FILE *fp)
5721573Srgrimes{
5731573Srgrimes	struct file_list *tp;
5741573Srgrimes	int lpos, len;
5751573Srgrimes	char *cp, och, *sp;
5761573Srgrimes
5771573Srgrimes	fprintf(fp, "OBJS=");
5781573Srgrimes	lpos = 6;
5791573Srgrimes	STAILQ_FOREACH(tp, &ftab, f_next) {
5801573Srgrimes		if (tp->f_flags & NO_OBJ)
5811573Srgrimes			continue;
5821573Srgrimes		sp = tail(tp->f_fn);
5831573Srgrimes		cp = sp + (len = strlen(sp)) - 1;
5841573Srgrimes		och = *cp;
5851573Srgrimes		*cp = 'o';
5861573Srgrimes		if (len + lpos > 72) {
5871573Srgrimes			lpos = 8;
5881573Srgrimes			fprintf(fp, "\\\n\t");
5891573Srgrimes		}
5901573Srgrimes		fprintf(fp, "%s ", sp);
5911573Srgrimes		lpos += len + 1;
5921573Srgrimes		*cp = och;
5931573Srgrimes	}
5941573Srgrimes	if (lpos != 8)
5951573Srgrimes		putc('\n', fp);
5961573Srgrimes}
5971573Srgrimes
5981573Srgrimesstatic void
5991573Srgrimesdo_xxfiles(char *tag, FILE *fp)
6001573Srgrimes{
6011573Srgrimes	struct file_list *tp;
6021573Srgrimes	int lpos, len, slen;
6031573Srgrimes	char *suff, *SUFF;
6041573Srgrimes
6051573Srgrimes	if (tag[strlen(tag) - 1] == '\n')
6061573Srgrimes		tag[strlen(tag) - 1] = '\0';
6071573Srgrimes
6081573Srgrimes	suff = ns(tag + 7);
6091573Srgrimes	SUFF = ns(suff);
6101573Srgrimes	raisestr(SUFF);
6111573Srgrimes	slen = strlen(suff);
6121573Srgrimes
6131573Srgrimes	fprintf(fp, "%sFILES=", SUFF);
6141573Srgrimes	lpos = 8;
6151573Srgrimes	STAILQ_FOREACH(tp, &ftab, f_next)
6161573Srgrimes		if (tp->f_type != NODEPEND) {
6171573Srgrimes			len = strlen(tp->f_fn);
6181573Srgrimes			if (tp->f_fn[len - slen - 1] != '.')
6191573Srgrimes				continue;
6201573Srgrimes			if (strcasecmp(&tp->f_fn[len - slen], suff) != 0)
6211573Srgrimes				continue;
6221573Srgrimes			if ((len = 3 + len) + lpos > 72) {
6239978Swpaul				lpos = 8;
6249978Swpaul				fputs("\\\n\t", fp);
6259978Swpaul			}
6269978Swpaul			if (tp->f_type != LOCAL)
6279978Swpaul				fprintf(fp, "$S/%s ", tp->f_fn);
6289978Swpaul			else
6299978Swpaul				fprintf(fp, "%s ", tp->f_fn);
6309978Swpaul			lpos += len + 1;
6319978Swpaul		}
6329978Swpaul	if (lpos != 8)
6331573Srgrimes		putc('\n', fp);
6341573Srgrimes}
635
636static char *
637tail(char *fn)
638{
639	char *cp;
640
641	cp = rindex(fn, '/');
642	if (cp == 0)
643		return (fn);
644	return (cp+1);
645}
646
647/*
648 * Create the makerules for each file
649 * which is part of the system.
650 */
651static void
652do_rules(FILE *f)
653{
654	char *cp, *np, och, *tp;
655	struct file_list *ftp;
656	char *compilewith;
657
658	STAILQ_FOREACH(ftp, &ftab, f_next) {
659		if (ftp->f_warn)
660			printf("WARNING: %s\n", ftp->f_warn);
661		cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
662		och = *cp;
663		if (ftp->f_flags & NO_IMPLCT_RULE) {
664			if (ftp->f_depends)
665				fprintf(f, "%s: %s\n", np, ftp->f_depends);
666			else
667				fprintf(f, "%s: \n", np);
668		}
669		else {
670			*cp = '\0';
671			if (och == 'o') {
672				fprintf(f, "%so:\n\t-cp $S/%so .\n\n",
673					tail(np), np);
674				continue;
675			}
676			if (ftp->f_depends) {
677				fprintf(f, "%sln: $S/%s%c %s\n", tail(np),
678					np, och, ftp->f_depends);
679				fprintf(f, "\t${NORMAL_LINT}\n\n");
680				fprintf(f, "%so: $S/%s%c %s\n", tail(np),
681					np, och, ftp->f_depends);
682			}
683			else {
684				fprintf(f, "%sln: $S/%s%c\n", tail(np),
685					np, och);
686				fprintf(f, "\t${NORMAL_LINT}\n\n");
687				fprintf(f, "%so: $S/%s%c\n", tail(np),
688					np, och);
689			}
690		}
691		tp = tail(np);
692		compilewith = ftp->f_compilewith;
693		if (compilewith == 0) {
694			const char *ftype = NULL;
695			static char cmd[128];
696
697			switch (ftp->f_type) {
698
699			case NORMAL:
700				ftype = "NORMAL";
701				break;
702
703			case PROFILING:
704				if (!profiling)
705					continue;
706				ftype = "PROFILE";
707				break;
708
709			default:
710				printf("config: don't know rules for %s\n", np);
711				break;
712			}
713			snprintf(cmd, sizeof(cmd), "${%s_%c%s}", ftype,
714			    toupper(och),
715			    ftp->f_flags & NOWERROR ? "_NOWERROR" : "");
716			compilewith = cmd;
717		}
718		*cp = och;
719		fprintf(f, "\t%s\n\n", compilewith);
720	}
721}
722
723static void
724do_clean(FILE *fp)
725{
726	struct file_list *tp;
727	int lpos, len;
728
729	fputs("CLEAN=", fp);
730	lpos = 7;
731	STAILQ_FOREACH(tp, &ftab, f_next)
732		if (tp->f_clean) {
733			len = strlen(tp->f_clean);
734			if (len + lpos > 72) {
735				lpos = 8;
736				fputs("\\\n\t", fp);
737			}
738			fprintf(fp, "%s ", tp->f_clean);
739			lpos += len + 1;
740		}
741	if (lpos != 8)
742		putc('\n', fp);
743}
744
745char *
746raisestr(char *str)
747{
748	char *cp = str;
749
750	while (*str) {
751		if (islower(*str))
752			*str = toupper(*str);
753		str++;
754	}
755	return (cp);
756}
757