main.c revision 20940
1/*
2 * Copyright (c) 1980, 1993
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
35static char copyright[] =
36"@(#) Copyright (c) 1980, 1993\n\
37	The Regents of the University of California.  All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/6/93";
42#endif /* not lint */
43
44#include <sys/types.h>
45#include <sys/stat.h>
46#include <sys/file.h>
47#include <sys/mman.h>
48#include <stdio.h>
49#include <ctype.h>
50#include <err.h>
51#include <sysexits.h>
52#include "y.tab.h"
53#include "config.h"
54
55#ifndef TRUE
56#define TRUE	(1)
57#endif
58
59#ifndef FALSE
60#define FALSE	(0)
61#endif
62
63static char *PREFIX;
64static int no_config_clobber = FALSE;
65int old_config_present;
66
67/*
68 * Config builds a set of files for building a UNIX
69 * system given a description of the desired system.
70 */
71main(argc, argv)
72	int argc;
73	char **argv;
74{
75
76	extern char *optarg;
77	extern int optind;
78	struct stat buf;
79	int ch;
80	char *p;
81
82	while ((ch = getopt(argc, argv, "gpn")) != EOF)
83		switch (ch) {
84		case 'g':
85			debugging++;
86			break;
87		case 'p':
88			profiling++;
89			break;
90		case 'n':
91			no_config_clobber = TRUE;
92			break;
93		case '?':
94		default:
95			goto usage;
96		}
97	argc -= optind;
98	argv += optind;
99
100	if (argc != 1) {
101usage:		fputs("usage: config [-gpn] sysname\n", stderr);
102		exit(1);
103	}
104
105	if (freopen(PREFIX = *argv, "r", stdin) == NULL) {
106		perror(PREFIX);
107		exit(2);
108	}
109	if (getenv("NO_CONFIG_CLOBBER"))
110		no_config_clobber = TRUE;
111
112	p = path((char *)NULL);
113	if (stat(p, &buf)) {
114		if (mkdir(p, 0777)) {
115			perror(p);
116			exit(2);
117		}
118	}
119	else if ((buf.st_mode & S_IFMT) != S_IFDIR) {
120		fprintf(stderr, "config: %s isn't a directory.\n", p);
121		exit(2);
122	}
123#ifndef NO_CLOBBER_EVER
124	else if (!no_config_clobber) {
125		char tmp[strlen(p) + 8];
126
127		fprintf(stderr, "Removing old directory %s:  ", p);
128		fflush(stderr);
129		sprintf(tmp, "rm -rf %s", p);
130		if (system(tmp)) {
131			fprintf(stderr, "Failed!\n");
132			perror(tmp);
133			exit(2);
134		}
135		fprintf(stderr, "Done.\n");
136		if (mkdir(p, 0777)) {
137			perror(p);
138			exit(2);
139		}
140	}
141#endif
142	else
143		old_config_present++;
144
145	loadaddress = -1;
146	dtab = NULL;
147	confp = &conf_list;
148	compp = &comp_list;
149	if (yyparse())
150		exit(3);
151	switch (machine) {
152
153	case MACHINE_VAX:
154		vax_ioconf();		/* Print ioconf.c */
155		ubglue();		/* Create ubglue.s */
156		break;
157
158	case MACHINE_TAHOE:
159		tahoe_ioconf();
160		vbglue();
161		break;
162
163	case MACHINE_HP300:
164	case MACHINE_LUNA68K:
165		hp300_ioconf();
166		hpglue();
167		break;
168
169	case MACHINE_I386:
170		i386_ioconf();		/* Print ioconf.c */
171		vector();		/* Create vector.s */
172		break;
173
174	case MACHINE_MIPS:
175	case MACHINE_PMAX:
176		pmax_ioconf();
177		break;
178
179	case MACHINE_NEWS3400:
180		news_ioconf();
181		break;
182
183	default:
184		printf("Specify machine type, e.g. ``machine vax''\n");
185		exit(1);
186	}
187	/*
188	 * make symbolic links in compilation directory
189	 * for "sys" (to make genassym.c work along with #include <sys/xxx>)
190	 * and similarly for "machine".
191	 */
192	{
193	char xxx[80];
194
195	(void) sprintf(xxx, "../../%s/include", machinename);
196	(void) symlink(xxx, path("machine"));
197	}
198	options();			/* make options .h files */
199	makefile();			/* build Makefile */
200	headers();			/* make a lot of .h files */
201	swapconf();			/* swap config files */
202	configfile();			/* put config file into kernel*/
203	printf("Kernel build directory is %s\n", p);
204	exit(0);
205}
206
207/*
208 * get_word
209 *	returns EOF on end of file
210 *	NULL on end of line
211 *	pointer to the word otherwise
212 */
213char *
214get_word(fp)
215	register FILE *fp;
216{
217	static char line[80];
218	register int ch;
219	register char *cp;
220	int escaped_nl = 0;
221
222begin:
223	while ((ch = getc(fp)) != EOF)
224		if (ch != ' ' && ch != '\t')
225			break;
226	if (ch == EOF)
227		return ((char *)EOF);
228	if (ch == '\\'){
229		escaped_nl = 1;
230		goto begin;
231	}
232	if (ch == '\n')
233		if (escaped_nl){
234			escaped_nl = 0;
235			goto begin;
236		}
237		else
238			return (NULL);
239	cp = line;
240	*cp++ = ch;
241	while ((ch = getc(fp)) != EOF) {
242		if (isspace(ch))
243			break;
244		*cp++ = ch;
245	}
246	*cp = 0;
247	if (ch == EOF)
248		return ((char *)EOF);
249	(void) ungetc(ch, fp);
250	return (line);
251}
252
253/*
254 * get_quoted_word
255 *	like get_word but will accept something in double or single quotes
256 *	(to allow embedded spaces).
257 */
258char *
259get_quoted_word(fp)
260	register FILE *fp;
261{
262	static char line[256];
263	register int ch;
264	register char *cp;
265	int escaped_nl = 0;
266
267begin:
268	while ((ch = getc(fp)) != EOF)
269		if (ch != ' ' && ch != '\t')
270			break;
271	if (ch == EOF)
272		return ((char *)EOF);
273	if (ch == '\\'){
274		escaped_nl = 1;
275		goto begin;
276	}
277	if (ch == '\n')
278		if (escaped_nl){
279			escaped_nl = 0;
280			goto begin;
281		}
282		else
283			return (NULL);
284	cp = line;
285	if (ch == '"' || ch == '\'') {
286		register int quote = ch;
287
288		while ((ch = getc(fp)) != EOF) {
289			if (ch == quote)
290				break;
291			if (ch == '\n') {
292				*cp = 0;
293				printf("config: missing quote reading `%s'\n",
294					line);
295				exit(2);
296			}
297			*cp++ = ch;
298		}
299	} else {
300		*cp++ = ch;
301		while ((ch = getc(fp)) != EOF) {
302			if (isspace(ch))
303				break;
304			*cp++ = ch;
305		}
306		if (ch != EOF)
307			(void) ungetc(ch, fp);
308	}
309	*cp = 0;
310	if (ch == EOF)
311		return ((char *)EOF);
312	return (line);
313}
314
315/*
316 * prepend the path to a filename
317 */
318char *
319path(file)
320	char *file;
321{
322	register char *cp;
323
324#define	CDIR	"../../compile/"
325	cp = malloc((unsigned int)(sizeof(CDIR) + strlen(PREFIX) +
326	    (file ? strlen(file) : 0) + 2));
327	(void) strcpy(cp, CDIR);
328	(void) strcat(cp, PREFIX);
329	if (file) {
330		(void) strcat(cp, "/");
331		(void) strcat(cp, file);
332	}
333	return (cp);
334}
335
336configfile()
337{
338	FILE *fi, *fo;
339	char *p;
340	int i;
341
342	fi = fopen(PREFIX,"r");
343	if(!fi) {
344		perror(PREFIX);
345		exit(2);
346	}
347	fo = fopen(p=path("config.c.new"),"w");
348	if(!fo) {
349		perror(p);
350		exit(2);
351	}
352	fprintf(fo,"#include \"opt_config.h\"\n");
353	fprintf(fo,"#ifdef INCLUDE_CONFIG_FILE \n");
354	fprintf(fo,"static char *config = \"\n");
355	fprintf(fo,"START CONFIG FILE %s\n___",PREFIX);
356	while (EOF != (i=getc(fi))) {
357		if(i == '\n') {
358			fprintf(fo,"\n___");
359		} else if(i == '\"') {
360			fprintf(fo,"\\\"");
361		} else if(i == '\\') {
362			fprintf(fo,"\\\\");
363		} else {
364			putc(i,fo);
365		}
366	}
367	fprintf(fo,"\nEND CONFIG FILE %s\n",PREFIX);
368	fprintf(fo,"\";\n");
369	fprintf(fo,"\n#endif /* INCLUDE_CONFIG_FILE */\n");
370	fclose(fi);
371	fclose(fo);
372	moveifchanged(path("config.c.new"), path("config.c"));
373}
374
375/*
376 * moveifchanged --
377 *	compare two files; rename if changed.
378 */
379void
380moveifchanged(const char *from_name, const char *to_name)
381{
382	char *p, *q;
383	int changed;
384	size_t tsize;
385	struct stat from_sb, to_sb;
386	int from_fd, to_fd;
387
388	changed = 0;
389
390	if ((from_fd = open(from_name, O_RDONLY)) < 0)
391		err(EX_OSERR, "moveifchanged open(%s)", from_name);
392
393	if ((to_fd = open(to_name, O_RDONLY)) < 0)
394		changed++;
395
396	if (!changed && fstat(from_fd, &from_sb) < 0)
397		err(EX_OSERR, "moveifchanged fstat(%s)", from_name);
398
399	if (!changed && fstat(to_fd, &to_sb) < 0)
400		err(EX_OSERR, "moveifchanged fstat(%s)", to_name);
401
402	if (!changed && from_sb.st_size != to_sb.st_size)
403		changed++;
404
405	tsize = (size_t)from_sb.st_size;
406
407	if (!changed) {
408		p = mmap(NULL, tsize, PROT_READ, 0, from_fd, (off_t)0);
409		if ((long)p == -1)
410			err(EX_OSERR, "mmap %s", from_name);
411		q = mmap(NULL, tsize, PROT_READ, 0, to_fd, (off_t)0);
412		if ((long)q == -1)
413			err(EX_OSERR, "mmap %s", to_name);
414
415		changed = memcmp(p, q, tsize);
416		munmap(p, tsize);
417		munmap(q, tsize);
418	}
419	if (changed) {
420		if (rename(from_name, to_name) < 0)
421			err(EX_OSERR, "rename(%s, %s)", from_name, to_name);
422	} else {
423		if (unlink(from_name) < 0)
424			err(EX_OSERR, "unlink(%s, %s)", from_name);
425	}
426
427#ifdef DIAG
428	if (changed)
429		printf("CHANGED! rename (%s, %s)\n", from_name, to_name);
430	else
431		printf("SAME! unlink (%s)\n", from_name);
432#endif
433
434	return;
435}
436