mkmakefile.c revision 269825
1299425Smm/*
2299425Smm * Copyright (c) 1980, 1990, 1993
3299425Smm *	The Regents of the University of California.  All rights reserved.
4299425Smm *
5299425Smm * Redistribution and use in source and binary forms, with or without
6299425Smm * modification, are permitted provided that the following conditions
7299425Smm * are met:
8299425Smm * 1. Redistributions of source code must retain the above copyright
9299425Smm *    notice, this list of conditions and the following disclaimer.
10299425Smm * 2. Redistributions in binary form must reproduce the above copyright
11299425Smm *    notice, this list of conditions and the following disclaimer in the
12299425Smm *    documentation and/or other materials provided with the distribution.
13299425Smm * 4. Neither the name of the University nor the names of its contributors
14299425Smm *    may be used to endorse or promote products derived from this software
15299425Smm *    without specific prior written permission.
16299425Smm *
17299425Smm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18299425Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19299425Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20299425Smm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21299425Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22299425Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23299425Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24299425Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25299425Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26299425Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27299425Smm * SUCH DAMAGE.
28299425Smm */
29299425Smm
30299425Smm#ifndef lint
31299425Smm#if 0
32313571Smmstatic char sccsid[] = "@(#)mkmakefile.c	8.1 (Berkeley) 6/6/93";
33313571Smm#endif
34299425Smmstatic const char rcsid[] =
35299425Smm  "$FreeBSD: stable/10/usr.sbin/config/mkmakefile.c 269825 2014-08-11 18:42:20Z imp $";
36299425Smm#endif /* not lint */
37299425Smm
38299425Smm/*
39299425Smm * Build the makefile for the system, from
40299425Smm * the information in the files files and the
41299425Smm * additional files for the machine being compiled to.
42299425Smm */
43299425Smm
44299425Smm#include <ctype.h>
45299425Smm#include <err.h>
46299425Smm#include <stdarg.h>
47299425Smm#include <stdio.h>
48299425Smm#include <string.h>
49299425Smm#include <sys/param.h>
50299425Smm#include "y.tab.h"
51299425Smm#include "config.h"
52299425Smm#include "configvers.h"
53299425Smm
54299425Smmstatic char *tail(char *);
55299425Smmstatic void do_clean(FILE *);
56299425Smmstatic void do_rules(FILE *);
57299425Smmstatic void do_xxfiles(char *, FILE *);
58299425Smmstatic void do_objs(FILE *);
59299425Smmstatic void do_before_depend(FILE *);
60299425Smmstatic int opteq(const char *, const char *);
61299425Smmstatic void read_files(void);
62299425Smm
63299425Smmstatic void errout(const char *fmt, ...)
64313571Smm{
65299425Smm	va_list ap;
66299425Smm
67299425Smm	va_start(ap, fmt);
68299425Smm	vfprintf(stderr, fmt, ap);
69299425Smm	va_end(ap);
70299425Smm	exit(1);
71299425Smm}
72299425Smm
73299425Smm/*
74299425Smm * Lookup a file, by name.
75299425Smm */
76299425Smmstatic struct file_list *
77299425Smmfl_lookup(char *file)
78299425Smm{
79299425Smm	struct file_list *fp;
80299425Smm
81299425Smm	STAILQ_FOREACH(fp, &ftab, f_next) {
82299425Smm		if (eq(fp->f_fn, file))
83299425Smm			return (fp);
84299425Smm	}
85299425Smm	return (0);
86299425Smm}
87299425Smm
88299425Smm/*
89299425Smm * Make a new file list entry
90299425Smm */
91299425Smmstatic struct file_list *
92299425Smmnew_fent(void)
93299425Smm{
94299425Smm	struct file_list *fp;
95299425Smm
96299425Smm	fp = (struct file_list *) calloc(1, sizeof *fp);
97299425Smm	if (fp == NULL)
98299425Smm		err(EXIT_FAILURE, "calloc");
99299425Smm	STAILQ_INSERT_TAIL(&ftab, fp, f_next);
100299425Smm	return (fp);
101299425Smm}
102299425Smm
103299425Smm/*
104299425Smm * Open the correct Makefile and return it, or error out.
105299425Smm */
106299425SmmFILE *
107299425Smmopen_makefile_template(void)
108299425Smm{
109299425Smm	FILE *ifp;
110299425Smm	char line[BUFSIZ];
111299425Smm
112299425Smm	snprintf(line, sizeof(line), "../../conf/Makefile.%s", machinename);
113299425Smm	ifp = fopen(line, "r");
114299425Smm	if (ifp == 0) {
115299425Smm		snprintf(line, sizeof(line), "Makefile.%s", machinename);
116299425Smm		ifp = fopen(line, "r");
117299425Smm	}
118299425Smm	if (ifp == 0)
119299425Smm		err(1, "%s", line);
120299425Smm	return (ifp);
121299425Smm}
122299425Smm
123299425Smm/*
124299425Smm * Build the makefile from the skeleton
125299425Smm */
126299425Smmvoid
127299425Smmmakefile(void)
128299425Smm{
129299425Smm	FILE *ifp, *ofp;
130299425Smm	char line[BUFSIZ];
131299425Smm	struct opt *op, *t;
132299425Smm
133299425Smm	read_files();
134299425Smm	ifp = open_makefile_template();
135299425Smm	ofp = fopen(path("Makefile.new"), "w");
136299425Smm	if (ofp == 0)
137299425Smm		err(1, "%s", path("Makefile.new"));
138299425Smm	fprintf(ofp, "KERN_IDENT=%s\n", ident);
139299425Smm	fprintf(ofp, "MACHINE=%s\n", machinename);
140299425Smm	fprintf(ofp, "MACHINE_ARCH=%s\n", machinearch);
141299425Smm	SLIST_FOREACH_SAFE(op, &mkopt, op_next, t) {
142299425Smm		fprintf(ofp, "%s=%s", op->op_name, op->op_value);
143299425Smm		while ((op = SLIST_NEXT(op, op_append)) != NULL)
144299425Smm			fprintf(ofp, " %s", op->op_value);
145299425Smm		fprintf(ofp, "\n");
146299425Smm	}
147299425Smm	if (debugging)
148318483Smm		fprintf(ofp, "DEBUG=-g\n");
149299425Smm	if (profiling)
150318483Smm		fprintf(ofp, "PROFLEVEL=%d\n", profiling);
151318483Smm	if (*srcdir != '\0')
152318483Smm		fprintf(ofp,"S=%s\n", srcdir);
153318483Smm	while (fgets(line, BUFSIZ, ifp) != NULL) {
154318483Smm		if (*line != '%') {
155318483Smm			fprintf(ofp, "%s", line);
156318483Smm			continue;
157318483Smm		}
158299425Smm		if (eq(line, "%BEFORE_DEPEND\n"))
159299425Smm			do_before_depend(ofp);
160299425Smm		else if (eq(line, "%OBJS\n"))
161299425Smm			do_objs(ofp);
162299425Smm		else if (strncmp(line, "%FILES.", 7) == 0)
163299425Smm			do_xxfiles(line, ofp);
164299425Smm		else if (eq(line, "%RULES\n"))
165299425Smm			do_rules(ofp);
166299425Smm		else if (eq(line, "%CLEAN\n"))
167299425Smm			do_clean(ofp);
168299425Smm		else if (strncmp(line, "%VERSREQ=", 9) == 0)
169299425Smm			line[0] = '\0'; /* handled elsewhere */
170299425Smm		else
171299425Smm			fprintf(stderr,
172299425Smm			    "Unknown %% construct in generic makefile: %s",
173299425Smm			    line);
174299425Smm	}
175299425Smm	(void) fclose(ifp);
176299425Smm	(void) fclose(ofp);
177299425Smm	moveifchanged(path("Makefile.new"), path("Makefile"));
178299425Smm}
179299425Smm
180299425Smm/*
181299425Smm * Build hints.c from the skeleton
182299425Smm */
183299425Smmvoid
184299425Smmmakehints(void)
185299425Smm{
186299425Smm	FILE *ifp, *ofp;
187299425Smm	char line[BUFSIZ];
188299425Smm	char *s;
189299425Smm	struct hint *hint;
190299425Smm
191299425Smm	ofp = fopen(path("hints.c.new"), "w");
192299425Smm	if (ofp == NULL)
193299425Smm		err(1, "%s", path("hints.c.new"));
194299425Smm	fprintf(ofp, "#include <sys/types.h>\n");
195299425Smm	fprintf(ofp, "#include <sys/systm.h>\n");
196299425Smm	fprintf(ofp, "\n");
197299425Smm	fprintf(ofp, "int hintmode = %d;\n", hintmode);
198299425Smm	fprintf(ofp, "char static_hints[] = {\n");
199299425Smm	STAILQ_FOREACH(hint, &hints, hint_next) {
200299425Smm		ifp = fopen(hint->hint_name, "r");
201299425Smm		if (ifp == NULL)
202299425Smm			err(1, "%s", hint->hint_name);
203299425Smm		while (fgets(line, BUFSIZ, ifp) != NULL) {
204299425Smm			/* zap trailing CR and/or LF */
205299425Smm			while ((s = strrchr(line, '\n')) != NULL)
206299425Smm				*s = '\0';
207299425Smm			while ((s = strrchr(line, '\r')) != NULL)
208299425Smm				*s = '\0';
209299425Smm			/* remove # comments */
210299425Smm			s = strchr(line, '#');
211299425Smm			if (s)
212299425Smm				*s = '\0';
213299425Smm			/* remove any whitespace and " characters */
214299425Smm			s = line;
215299425Smm			while (*s) {
216299425Smm				if (*s == ' ' || *s == '\t' || *s == '"') {
217299425Smm					while (*s) {
218299425Smm						s[0] = s[1];
219299425Smm						s++;
220299425Smm					}
221299425Smm					/* start over */
222299425Smm					s = line;
223299425Smm					continue;
224299425Smm				}
225299425Smm				s++;
226299425Smm			}
227299425Smm			/* anything left? */
228299425Smm			if (*line == '\0')
229299425Smm				continue;
230299425Smm			fprintf(ofp, "\"%s\\0\"\n", line);
231299425Smm		}
232299425Smm		fclose(ifp);
233299425Smm	}
234299425Smm	fprintf(ofp, "\"\\0\"\n};\n");
235299425Smm	fclose(ofp);
236299425Smm	moveifchanged(path("hints.c.new"), path("hints.c"));
237299425Smm}
238299425Smm
239299425Smm/*
240299425Smm * Build env.c from the skeleton
241299425Smm */
242299425Smmvoid
243299425Smmmakeenv(void)
244299425Smm{
245299425Smm	FILE *ifp, *ofp;
246299425Smm	char line[BUFSIZ];
247299425Smm	char *s;
248299425Smm
249299425Smm	if (env) {
250299425Smm		ifp = fopen(env, "r");
251299425Smm		if (ifp == NULL)
252299425Smm			err(1, "%s", env);
253299425Smm	} else {
254299425Smm		ifp = NULL;
255299425Smm	}
256299425Smm	ofp = fopen(path("env.c.new"), "w");
257299425Smm	if (ofp == NULL)
258299425Smm		err(1, "%s", path("env.c.new"));
259299425Smm	fprintf(ofp, "#include <sys/types.h>\n");
260299425Smm	fprintf(ofp, "#include <sys/systm.h>\n");
261299425Smm	fprintf(ofp, "\n");
262299425Smm	fprintf(ofp, "int envmode = %d;\n", envmode);
263299425Smm	fprintf(ofp, "char static_env[] = {\n");
264299425Smm	if (ifp) {
265299425Smm		while (fgets(line, BUFSIZ, ifp) != NULL) {
266299425Smm			/* zap trailing CR and/or LF */
267299425Smm			while ((s = strrchr(line, '\n')) != NULL)
268299425Smm				*s = '\0';
269299425Smm			while ((s = strrchr(line, '\r')) != NULL)
270299425Smm				*s = '\0';
271299425Smm			/* remove # comments */
272299425Smm			s = strchr(line, '#');
273299425Smm			if (s)
274299425Smm				*s = '\0';
275299425Smm			/* remove any whitespace and " characters */
276299425Smm			s = line;
277299425Smm			while (*s) {
278299425Smm				if (*s == ' ' || *s == '\t' || *s == '"') {
279299425Smm					while (*s) {
280299425Smm						s[0] = s[1];
281299425Smm						s++;
282299425Smm					}
283299425Smm					/* start over */
284299425Smm					s = line;
285299425Smm					continue;
286299425Smm				}
287299425Smm				s++;
288299425Smm			}
289299425Smm			/* anything left? */
290299425Smm			if (*line == '\0')
291299425Smm				continue;
292299425Smm			fprintf(ofp, "\"%s\\0\"\n", line);
293299425Smm		}
294299425Smm	}
295299425Smm	fprintf(ofp, "\"\\0\"\n};\n");
296299425Smm	if (ifp)
297299425Smm		fclose(ifp);
298299425Smm	fclose(ofp);
299299425Smm	moveifchanged(path("env.c.new"), path("env.c"));
300299425Smm}
301299425Smm
302299425Smmstatic void
303299425Smmread_file(char *fname)
304299425Smm{
305299425Smm	char ifname[MAXPATHLEN];
306299425Smm	FILE *fp;
307299425Smm	struct file_list *tp;
308299425Smm	struct device *dp;
309299425Smm	struct opt *op;
310299425Smm	char *wd, *this, *compilewith, *depends, *clean, *warning;
311299425Smm	const char *objprefix;
312299425Smm	int compile, match, nreqs, std, filetype, not,
313299425Smm	    imp_rule, no_obj, before_depend, nowerror;
314299425Smm
315299425Smm	fp = fopen(fname, "r");
316299425Smm	if (fp == 0)
317299425Smm		err(1, "%s", fname);
318299425Smmnext:
319299425Smm	/*
320299425Smm	 * include "filename"
321299425Smm	 * filename    [ standard | optional ]
322299425Smm	 *	[ dev* [ | dev* ... ] | profiling-routine ] [ no-obj ]
323299425Smm	 *	[ compile-with "compile rule" [no-implicit-rule] ]
324299425Smm	 *      [ dependency "dependency-list"] [ before-depend ]
325299425Smm	 *	[ clean "file-list"] [ warning "text warning" ]
326299425Smm	 *	[ obj-prefix "file prefix"]
327299425Smm	 */
328299425Smm	wd = get_word(fp);
329299425Smm	if (wd == (char *)EOF) {
330299425Smm		(void) fclose(fp);
331299425Smm		return;
332299425Smm	}
333299425Smm	if (wd == 0)
334299425Smm		goto next;
335299425Smm	if (wd[0] == '#')
336299425Smm	{
337299425Smm		while (((wd = get_word(fp)) != (char *)EOF) && wd)
338299425Smm			;
339299425Smm		goto next;
340299425Smm	}
341299425Smm	if (eq(wd, "include")) {
342299425Smm		wd = get_quoted_word(fp);
343299425Smm		if (wd == (char *)EOF || wd == 0)
344299425Smm			errout("%s: missing include filename.\n", fname);
345299425Smm		(void) snprintf(ifname, sizeof(ifname), "../../%s", wd);
346299425Smm		read_file(ifname);
347299425Smm		while (((wd = get_word(fp)) != (char *)EOF) && wd)
348299425Smm			;
349299425Smm		goto next;
350299425Smm	}
351299425Smm	this = ns(wd);
352299425Smm	wd = get_word(fp);
353299425Smm	if (wd == (char *)EOF)
354299425Smm		return;
355299425Smm	if (wd == 0)
356299425Smm		errout("%s: No type for %s.\n", fname, this);
357299425Smm	tp = fl_lookup(this);
358299425Smm	compile = 0;
359299425Smm	match = 1;
360299425Smm	nreqs = 0;
361299425Smm	compilewith = 0;
362299425Smm	depends = 0;
363299425Smm	clean = 0;
364299425Smm	warning = 0;
365299425Smm	std = 0;
366299425Smm	imp_rule = 0;
367299425Smm	no_obj = 0;
368299425Smm	before_depend = 0;
369299425Smm	nowerror = 0;
370299425Smm	not = 0;
371299425Smm	filetype = NORMAL;
372299425Smm	objprefix = "";
373299425Smm	if (eq(wd, "standard"))
374299425Smm		std = 1;
375299425Smm	else if (!eq(wd, "optional"))
376299425Smm		errout("%s: \"%s\" %s must be optional or standard\n",
377299425Smm		    fname, wd, this);
378299425Smm	for (wd = get_word(fp); wd; wd = get_word(fp)) {
379299425Smm		if (wd == (char *)EOF)
380299425Smm			return;
381299425Smm		if (eq(wd, "!")) {
382299425Smm			not = 1;
383299425Smm			continue;
384299425Smm		}
385299425Smm		if (eq(wd, "|")) {
386299425Smm			if (nreqs == 0)
387299425Smm				errout("%s: syntax error describing %s\n",
388299425Smm				       fname, this);
389299425Smm			if (not)
390299425Smm				compile += !match;
391299425Smm			else
392299425Smm				compile += match;
393299425Smm			match = 1;
394299425Smm			nreqs = 0;
395299425Smm			not = 0;
396299425Smm			continue;
397299425Smm		}
398299425Smm		if (eq(wd, "no-obj")) {
399299425Smm			no_obj++;
400299425Smm			continue;
401299425Smm		}
402299425Smm		if (eq(wd, "no-implicit-rule")) {
403299425Smm			if (compilewith == 0)
404299425Smm				errout("%s: alternate rule required when "
405299425Smm				       "\"no-implicit-rule\" is specified for"
406299425Smm				       " %s.\n",
407299425Smm				       fname, this);
408299425Smm			imp_rule++;
409299425Smm			continue;
410299425Smm		}
411299425Smm		if (eq(wd, "before-depend")) {
412299425Smm			before_depend++;
413299425Smm			continue;
414299425Smm		}
415299425Smm		if (eq(wd, "dependency")) {
416299425Smm			wd = get_quoted_word(fp);
417299425Smm			if (wd == (char *)EOF || wd == 0)
418299425Smm				errout("%s: %s missing dependency string.\n",
419299425Smm				       fname, this);
420299425Smm			depends = ns(wd);
421299425Smm			continue;
422299425Smm		}
423299425Smm		if (eq(wd, "clean")) {
424299425Smm			wd = get_quoted_word(fp);
425299425Smm			if (wd == (char *)EOF || wd == 0)
426299425Smm				errout("%s: %s missing clean file list.\n",
427299425Smm				       fname, this);
428299425Smm			clean = ns(wd);
429299425Smm			continue;
430299425Smm		}
431299425Smm		if (eq(wd, "compile-with")) {
432299425Smm			wd = get_quoted_word(fp);
433299425Smm			if (wd == (char *)EOF || wd == 0)
434299425Smm				errout("%s: %s missing compile command string.\n",
435299425Smm				       fname, this);
436299425Smm			compilewith = ns(wd);
437299425Smm			continue;
438299425Smm		}
439299425Smm		if (eq(wd, "warning")) {
440299425Smm			wd = get_quoted_word(fp);
441299425Smm			if (wd == (char *)EOF || wd == 0)
442299425Smm				errout("%s: %s missing warning text string.\n",
443299425Smm				       fname, this);
444299425Smm			warning = ns(wd);
445299425Smm			continue;
446299425Smm		}
447299425Smm		if (eq(wd, "obj-prefix")) {
448299425Smm			wd = get_quoted_word(fp);
449299425Smm			if (wd == (char *)EOF || wd == 0)
450299425Smm				errout("%s: %s missing object prefix string.\n",
451299425Smm				       fname, this);
452299425Smm			objprefix = ns(wd);
453299425Smm			continue;
454299425Smm		}
455299425Smm		if (eq(wd, "nowerror")) {
456299425Smm			nowerror = 1;
457299425Smm			continue;
458299425Smm		}
459299425Smm		if (eq(wd, "local")) {
460299425Smm			filetype = LOCAL;
461299425Smm			continue;
462299425Smm		}
463299425Smm		if (eq(wd, "no-depend")) {
464299425Smm			filetype = NODEPEND;
465299425Smm			continue;
466299425Smm		}
467299425Smm		nreqs++;
468299425Smm		if (eq(wd, "profiling-routine")) {
469299425Smm			filetype = PROFILING;
470299425Smm			continue;
471299425Smm		}
472299425Smm		if (std)
473299425Smm			errout("standard entry %s has optional inclusion specifier %s!\n",
474299425Smm			       this, wd);
475299425Smm		STAILQ_FOREACH(dp, &dtab, d_next)
476299425Smm			if (eq(dp->d_name, wd)) {
477299425Smm				dp->d_done |= DEVDONE;
478299425Smm				goto nextparam;
479299425Smm			}
480299425Smm		SLIST_FOREACH(op, &opt, op_next)
481299425Smm			if (op->op_value == 0 && opteq(op->op_name, wd))
482299425Smm				goto nextparam;
483299425Smm		match = 0;
484299425Smmnextparam:;
485299425Smm	}
486299425Smm	if (not)
487299425Smm		compile += !match;
488299425Smm	else
489299425Smm		compile += match;
490299425Smm	if (compile && tp == NULL) {
491299425Smm		if (std == 0 && nreqs == 0)
492299425Smm			errout("%s: what is %s optional on?\n",
493299425Smm			       fname, this);
494299425Smm		if (filetype == PROFILING && profiling == 0)
495299425Smm			goto next;
496299425Smm		tp = new_fent();
497299425Smm		tp->f_fn = this;
498299425Smm		tp->f_type = filetype;
499299425Smm		if (imp_rule)
500299425Smm			tp->f_flags |= NO_IMPLCT_RULE;
501299425Smm		if (no_obj)
502299425Smm			tp->f_flags |= NO_OBJ;
503299425Smm		if (before_depend)
504299425Smm			tp->f_flags |= BEFORE_DEPEND;
505299425Smm		if (nowerror)
506299425Smm			tp->f_flags |= NOWERROR;
507299425Smm		tp->f_compilewith = compilewith;
508299425Smm		tp->f_depends = depends;
509299425Smm		tp->f_clean = clean;
510299425Smm		tp->f_warn = warning;
511299425Smm		tp->f_objprefix = objprefix;
512299425Smm	}
513299425Smm	goto next;
514299425Smm}
515299425Smm
516299425Smm/*
517299425Smm * Read in the information about files used in making the system.
518299425Smm * Store it in the ftab linked list.
519299425Smm */
520299425Smmstatic void
521299425Smmread_files(void)
522{
523	char fname[MAXPATHLEN];
524	struct files_name *nl, *tnl;
525
526	(void) snprintf(fname, sizeof(fname), "../../conf/files");
527	read_file(fname);
528	(void) snprintf(fname, sizeof(fname),
529		       	"../../conf/files.%s", machinename);
530	read_file(fname);
531	for (nl = STAILQ_FIRST(&fntab); nl != NULL; nl = tnl) {
532		read_file(nl->f_name);
533		tnl = STAILQ_NEXT(nl, f_next);
534		free(nl->f_name);
535		free(nl);
536	}
537}
538
539static int
540opteq(const char *cp, const char *dp)
541{
542	char c, d;
543
544	for (; ; cp++, dp++) {
545		if (*cp != *dp) {
546			c = isupper(*cp) ? tolower(*cp) : *cp;
547			d = isupper(*dp) ? tolower(*dp) : *dp;
548			if (c != d)
549				return (0);
550		}
551		if (*cp == 0)
552			return (1);
553	}
554}
555
556static void
557do_before_depend(FILE *fp)
558{
559	struct file_list *tp;
560	int lpos, len;
561
562	fputs("BEFORE_DEPEND=", fp);
563	lpos = 15;
564	STAILQ_FOREACH(tp, &ftab, f_next)
565		if (tp->f_flags & BEFORE_DEPEND) {
566			len = strlen(tp->f_fn);
567			if ((len = 3 + len) + lpos > 72) {
568				lpos = 8;
569				fputs("\\\n\t", fp);
570			}
571			if (tp->f_flags & NO_IMPLCT_RULE)
572				fprintf(fp, "%s ", tp->f_fn);
573			else
574				fprintf(fp, "$S/%s ", tp->f_fn);
575			lpos += len + 1;
576		}
577	if (lpos != 8)
578		putc('\n', fp);
579}
580
581static void
582do_objs(FILE *fp)
583{
584	struct file_list *tp;
585	int lpos, len;
586	char *cp, och, *sp;
587
588	fprintf(fp, "OBJS=");
589	lpos = 6;
590	STAILQ_FOREACH(tp, &ftab, f_next) {
591		if (tp->f_flags & NO_OBJ)
592			continue;
593		sp = tail(tp->f_fn);
594		cp = sp + (len = strlen(sp)) - 1;
595		och = *cp;
596		*cp = 'o';
597		len += strlen(tp->f_objprefix);
598		if (len + lpos > 72) {
599			lpos = 8;
600			fprintf(fp, "\\\n\t");
601		}
602		fprintf(fp, "%s%s ", tp->f_objprefix, sp);
603		lpos += len + 1;
604		*cp = och;
605	}
606	if (lpos != 8)
607		putc('\n', fp);
608}
609
610static void
611do_xxfiles(char *tag, FILE *fp)
612{
613	struct file_list *tp;
614	int lpos, len, slen;
615	char *suff, *SUFF;
616
617	if (tag[strlen(tag) - 1] == '\n')
618		tag[strlen(tag) - 1] = '\0';
619
620	suff = ns(tag + 7);
621	SUFF = ns(suff);
622	raisestr(SUFF);
623	slen = strlen(suff);
624
625	fprintf(fp, "%sFILES=", SUFF);
626	lpos = 8;
627	STAILQ_FOREACH(tp, &ftab, f_next)
628		if (tp->f_type != NODEPEND) {
629			len = strlen(tp->f_fn);
630			if (tp->f_fn[len - slen - 1] != '.')
631				continue;
632			if (strcasecmp(&tp->f_fn[len - slen], suff) != 0)
633				continue;
634			if ((len = 3 + len) + lpos > 72) {
635				lpos = 8;
636				fputs("\\\n\t", fp);
637			}
638			if (tp->f_type != LOCAL)
639				fprintf(fp, "$S/%s ", tp->f_fn);
640			else
641				fprintf(fp, "%s ", tp->f_fn);
642			lpos += len + 1;
643		}
644	if (lpos != 8)
645		putc('\n', fp);
646}
647
648static char *
649tail(char *fn)
650{
651	char *cp;
652
653	cp = strrchr(fn, '/');
654	if (cp == 0)
655		return (fn);
656	return (cp+1);
657}
658
659/*
660 * Create the makerules for each file
661 * which is part of the system.
662 */
663static void
664do_rules(FILE *f)
665{
666	char *cp, *np, och;
667	struct file_list *ftp;
668	char *compilewith;
669	char cmd[128];
670
671	STAILQ_FOREACH(ftp, &ftab, f_next) {
672		if (ftp->f_warn)
673			fprintf(stderr, "WARNING: %s\n", ftp->f_warn);
674		cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
675		och = *cp;
676		if (ftp->f_flags & NO_IMPLCT_RULE) {
677			if (ftp->f_depends)
678				fprintf(f, "%s%s: %s\n",
679					ftp->f_objprefix, np, ftp->f_depends);
680			else
681				fprintf(f, "%s%s: \n", ftp->f_objprefix, np);
682		}
683		else {
684			*cp = '\0';
685			if (och == 'o') {
686				fprintf(f, "%s%so:\n\t-cp $S/%so .\n\n",
687					ftp->f_objprefix, tail(np), np);
688				continue;
689			}
690			if (ftp->f_depends) {
691				fprintf(f, "%s%sln: $S/%s%c %s\n",
692					ftp->f_objprefix, tail(np), np, och,
693					ftp->f_depends);
694				fprintf(f, "\t${NORMAL_LINT}\n\n");
695				fprintf(f, "%s%so: $S/%s%c %s\n",
696					ftp->f_objprefix, tail(np), np, och,
697					ftp->f_depends);
698			}
699			else {
700				fprintf(f, "%s%sln: $S/%s%c\n",
701					ftp->f_objprefix, tail(np), np, och);
702				fprintf(f, "\t${NORMAL_LINT}\n\n");
703				fprintf(f, "%s%so: $S/%s%c\n",
704					ftp->f_objprefix, tail(np), np, och);
705			}
706		}
707		compilewith = ftp->f_compilewith;
708		if (compilewith == 0) {
709			const char *ftype = NULL;
710
711			switch (ftp->f_type) {
712			case NORMAL:
713				ftype = "NORMAL";
714				break;
715			case PROFILING:
716				if (!profiling)
717					continue;
718				ftype = "PROFILE";
719				break;
720			default:
721				fprintf(stderr,
722				    "config: don't know rules for %s\n", np);
723				break;
724			}
725			snprintf(cmd, sizeof(cmd),
726			    "${%s_%c%s}", ftype,
727			    toupper(och),
728			    ftp->f_flags & NOWERROR ? "_NOWERROR" : "");
729			compilewith = cmd;
730		}
731		*cp = och;
732		if (strlen(ftp->f_objprefix))
733			fprintf(f, "\t%s $S/%s\n", compilewith, np);
734		else
735			fprintf(f, "\t%s\n", compilewith);
736
737		if (!(ftp->f_flags & NO_OBJ))
738			fprintf(f, "\t${NORMAL_CTFCONVERT}\n\n");
739		else
740			fprintf(f, "\n");
741	}
742}
743
744static void
745do_clean(FILE *fp)
746{
747	struct file_list *tp;
748	int lpos, len;
749
750	fputs("CLEAN=", fp);
751	lpos = 7;
752	STAILQ_FOREACH(tp, &ftab, f_next)
753		if (tp->f_clean) {
754			len = strlen(tp->f_clean);
755			if (len + lpos > 72) {
756				lpos = 8;
757				fputs("\\\n\t", fp);
758			}
759			fprintf(fp, "%s ", tp->f_clean);
760			lpos += len + 1;
761		}
762	if (lpos != 8)
763		putc('\n', fp);
764}
765
766char *
767raisestr(char *str)
768{
769	char *cp = str;
770
771	while (*str) {
772		if (islower(*str))
773			*str = toupper(*str);
774		str++;
775	}
776	return (cp);
777}
778