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