1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This software was developed by the Computer Systems Engineering group
6  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7  * contributed to Berkeley.
8  *
9  * All advertising materials mentioning features or use of this software
10  * must display the following acknowledgement:
11  *	This product includes software developed by the University of
12  *	California, Lawrence Berkeley Laboratories.
13  *
14  * %sccs.include.redist.c%
15  *
16  *	@(#)mkmakefile.c	8.1 (Berkeley) 06/06/93
17  */
18 
19 #include <sys/param.h>
20 #include <ctype.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "config.h"
26 
27 /*
28  * Make the Makefile.
29  */
30 
31 static int emitdefs __P((FILE *));
32 static int emitobjs __P((FILE *));
33 static int emitcfiles __P((FILE *));
34 static int emitsfiles __P((FILE *));
35 static int emitfiles __P((FILE *, int));
36 static int emitrules __P((FILE *));
37 static int emitload __P((FILE *));
38 
39 int
40 mkmakefile()
41 {
42 	register FILE *ifp, *ofp;
43 	register int lineno;
44 	register int (*fn) __P((FILE *));
45 	register char *ofname;
46 	char line[BUFSIZ], ifname[200];
47 
48 	(void)sprintf(ifname, "Makefile.%s", machine);
49 	if ((ifp = fopen(ifname, "r")) == NULL) {
50 		(void)fprintf(stderr, "config: cannot read %s: %s\n",
51 		    ifname, strerror(errno));
52 		return (1);
53 	}
54 	ofname = path("Makefile");
55 	if ((ofp = fopen(ofname, "w")) == NULL) {
56 		(void)fprintf(stderr, "config: cannot write %s: %s\n",
57 		    ofname, strerror(errno));
58 		free(ofname);
59 		return (1);
60 	}
61 	if (emitdefs(ofp) != 0)
62 		goto wrerror;
63 	lineno = 0;
64 	while (fgets(line, sizeof(line), ifp) != NULL) {
65 		lineno++;
66 		if (line[0] != '%') {
67 			if (fputs(line, ofp) < 0)
68 				goto wrerror;
69 			continue;
70 		}
71 		if (strcmp(line, "%OBJS\n") == 0)
72 			fn = emitobjs;
73 		else if (strcmp(line, "%CFILES\n") == 0)
74 			fn = emitcfiles;
75 		else if (strcmp(line, "%SFILES\n") == 0)
76 			fn = emitsfiles;
77 		else if (strcmp(line, "%RULES\n") == 0)
78 			fn = emitrules;
79 		else if (strcmp(line, "%LOAD\n") == 0)
80 			fn = emitload;
81 		else {
82 			xerror(ifname, lineno,
83 			    "unknown %% construct ignored: %s", line);
84 			continue;
85 		}
86 		if ((*fn)(ofp))
87 			goto wrerror;
88 	}
89 	if (ferror(ifp)) {
90 		(void)fprintf(stderr,
91 		    "config: error reading %s (at line %d): %s\n",
92 		    ifname, lineno, strerror(errno));
93 		goto bad;
94 		/* (void)unlink(ofname); */
95 		free(ofname);
96 		return (1);
97 	}
98 	if (fclose(ofp)) {
99 		ofp = NULL;
100 		goto wrerror;
101 	}
102 	(void)fclose(ifp);
103 	free(ofname);
104 	return (0);
105 wrerror:
106 	(void)fprintf(stderr, "config: error writing %s: %s\n",
107 	    ofname, strerror(errno));
108 bad:
109 	if (ofp != NULL)
110 		(void)fclose(ofp);
111 	/* (void)unlink(ofname); */
112 	free(ofname);
113 	return (1);
114 }
115 
116 static int
117 emitdefs(fp)
118 	register FILE *fp;
119 {
120 	register struct nvlist *nv;
121 	register char *sp;
122 
123 	if (fputs("IDENT=", fp) < 0)
124 		return (1);
125 	sp = "";
126 	for (nv = options; nv != NULL; nv = nv->nv_next) {
127 		if (fprintf(fp, "%s-D%s%s%s", sp, nv->nv_name,
128 		    nv->nv_str ? "=" : "", nv->nv_str ? nv->nv_str : "") < 0)
129 			return (1);
130 		sp = " ";
131 	}
132 	if (putc('\n', fp) < 0)
133 		return (1);
134 	if (fprintf(fp, "PARAM=-DMAXUSERS=%d\n", maxusers) < 0)
135 		return (1);
136 	for (nv = mkoptions; nv != NULL; nv = nv->nv_next)
137 		if (fprintf(fp, "%s=%s\n", nv->nv_name, nv->nv_str) < 0)
138 			return (1);
139 	return (0);
140 }
141 
142 static int
143 emitobjs(fp)
144 	register FILE *fp;
145 {
146 	register struct files *fi;
147 	register int lpos, len, sp;
148 
149 	if (fputs("OBJS=", fp) < 0)
150 		return (1);
151 	sp = '\t';
152 	lpos = 7;
153 	for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
154 		if ((fi->fi_flags & FI_SEL) == 0)
155 			continue;
156 		len = strlen(fi->fi_base) + 2;
157 		if (lpos + len > 72) {
158 			if (fputs(" \\\n", fp) < 0)
159 				return (1);
160 			sp = '\t';
161 			lpos = 7;
162 		}
163 		if (fprintf(fp, "%c%s.o", sp, fi->fi_base) < 0)
164 			return (1);
165 		lpos += len + 1;
166 		sp = ' ';
167 	}
168 	if (lpos != 7 && putc('\n', fp) < 0)
169 		return (1);
170 	return (0);
171 }
172 
173 static int
174 emitcfiles(fp)
175 	FILE *fp;
176 {
177 
178 	return (emitfiles(fp, 'c'));
179 }
180 
181 static int
182 emitsfiles(fp)
183 	FILE *fp;
184 {
185 
186 	return (emitfiles(fp, 's'));
187 }
188 
189 static int
190 emitfiles(fp, suffix)
191 	register FILE *fp;
192 	int suffix;
193 {
194 	register struct files *fi;
195 	register struct config *cf;
196 	register int lpos, len, sp;
197 	char swapname[100];
198 
199 	if (fprintf(fp, "%cFILES=", toupper(suffix)) < 0)
200 		return (1);
201 	sp = '\t';
202 	lpos = 7;
203 	for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
204 		if ((fi->fi_flags & FI_SEL) == 0)
205 			continue;
206 		len = strlen(fi->fi_path);
207 		if (fi->fi_path[len - 1] != suffix)
208 			continue;
209 		if (*fi->fi_path != '/')
210 			len += 3;	/* "$S/" */
211 		if (lpos + len > 72) {
212 			if (fputs(" \\\n", fp) < 0)
213 				return (1);
214 			sp = '\t';
215 			lpos = 7;
216 		}
217 		if (fprintf(fp, "%c%s%s", sp, *fi->fi_path != '/' ? "$S/" : "",
218 		    fi->fi_path) < 0)
219 			return (1);
220 		lpos += len + 1;
221 		sp = ' ';
222 	}
223 	/*
224 	 * The allfiles list does not include the configuration-specific
225 	 * C source files.  These files should be eliminated someday, but
226 	 * for now, we have to add them to ${CFILES} (and only ${CFILES}).
227 	 */
228 	if (suffix == 'c') {
229 		for (cf = allcf; cf != NULL; cf = cf->cf_next) {
230 			if (cf->cf_root == NULL)
231 				(void)sprintf(swapname,
232 				    "$S/%s/%s/swapgeneric.c",
233 				    machine, machine);
234 			else
235 				(void)sprintf(swapname, "swap%s.c",
236 				    cf->cf_name);
237 			len = strlen(swapname);
238 			if (lpos + len > 72) {
239 				if (fputs(" \\\n", fp) < 0)
240 					return (1);
241 				sp = '\t';
242 				lpos = 7;
243 			}
244 			if (fprintf(fp, "%c%s", sp, swapname) < 0)
245 				return (1);
246 			lpos += len + 1;
247 			sp = ' ';
248 		}
249 	}
250 	if (lpos != 7 && putc('\n', fp) < 0)
251 		return (1);
252 	return (0);
253 }
254 
255 /*
256  * Emit the make-rules.
257  */
258 static int
259 emitrules(fp)
260 	register FILE *fp;
261 {
262 	register struct files *fi;
263 	register const char *cp;
264 	int ch;
265 	char buf[200];
266 
267 	for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
268 		if ((fi->fi_flags & FI_SEL) == 0)
269 			continue;
270 		if (fprintf(fp, "%s.o: %s%s\n", fi->fi_base,
271 		    *fi->fi_path != '/' ? "$S/" : "", fi->fi_path) < 0)
272 			return (1);
273 		if ((cp = fi->fi_mkrule) == NULL) {
274 			cp = fi->fi_flags & FI_DRIVER ? "DRIVER" : "NORMAL";
275 			ch = fi->fi_lastc;
276 			if (islower(ch))
277 				ch = toupper(ch);
278 			(void)sprintf(buf, "${%s_%c%s}", cp, ch,
279 			    fi->fi_flags & FI_CONFIGDEP ? "_C" : "");
280 			cp = buf;
281 		}
282 		if (fprintf(fp, "\t%s\n\n", cp) < 0)
283 			return (1);
284 	}
285 	return (0);
286 }
287 
288 /*
289  * Emit the load commands.
290  *
291  * This function is not to be called `spurt'.
292  */
293 static int
294 emitload(fp)
295 	register FILE *fp;
296 {
297 	register struct config *cf;
298 	register const char *nm, *swname;
299 	int first;
300 
301 	if (fputs("all:", fp) < 0)
302 		return (1);
303 	for (cf = allcf; cf != NULL; cf = cf->cf_next) {
304 		if (fprintf(fp, " %s", cf->cf_name) < 0)
305 			return (1);
306 	}
307 	if (fputs("\n\n", fp) < 0)
308 		return (1);
309 	for (first = 1, cf = allcf; cf != NULL; cf = cf->cf_next) {
310 		nm = cf->cf_name;
311 		swname = cf->cf_root != NULL ? cf->cf_name : "generic";
312 		if (fprintf(fp, "%s: ${SYSTEM_DEP} swap%s.o", nm, swname) < 0)
313 			return (1);
314 		if (first) {
315 			if (fputs(" newvers", fp) < 0)
316 				return (1);
317 			first = 0;
318 		}
319 		if (fprintf(fp, "\n\
320 \t${SYSTEM_LD_HEAD}\n\
321 \t${SYSTEM_LD} swap%s.o\n\
322 \t${SYSTEM_LD_TAIL}\n\
323 \n\
324 swap%s.o: ", swname, swname) < 0)
325 			return (1);
326 		if (cf->cf_root != NULL) {
327 			if (fprintf(fp, "swap%s.c\n", nm) < 0)
328 				return (1);
329 		} else {
330 			if (fprintf(fp, "$S/%s/%s/swapgeneric.c\n",
331 			    machine, machine) < 0)
332 				return (1);
333 		}
334 		if (fputs("\t${NORMAL_C}\n\n", fp) < 0)
335 			return (1);
336 	}
337 	return (0);
338 }
339