1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)mkmakefile.c 5.8 (Berkeley) 05/03/86"; 9 #endif not lint 10 11 /* 12 * Build the makefile for the system, from 13 * the information in the files files and the 14 * additional files for the machine being compiled to. 15 */ 16 17 #include <stdio.h> 18 #include <ctype.h> 19 #include "y.tab.h" 20 #include "config.h" 21 22 #define next_word(fp, wd) \ 23 { register char *word = get_word(fp); \ 24 if (word == (char *)EOF) \ 25 return; \ 26 else \ 27 wd = word; \ 28 } 29 30 static struct file_list *fcur; 31 char *tail(); 32 33 /* 34 * Lookup a file, by name. 35 */ 36 struct file_list * 37 fl_lookup(file) 38 register char *file; 39 { 40 register struct file_list *fp; 41 42 for (fp = ftab ; fp != 0; fp = fp->f_next) { 43 if (eq(fp->f_fn, file)) 44 return (fp); 45 } 46 return (0); 47 } 48 49 /* 50 * Lookup a file, by final component name. 51 */ 52 struct file_list * 53 fltail_lookup(file) 54 register char *file; 55 { 56 register struct file_list *fp; 57 58 for (fp = ftab ; fp != 0; fp = fp->f_next) { 59 if (eq(tail(fp->f_fn), tail(file))) 60 return (fp); 61 } 62 return (0); 63 } 64 65 /* 66 * Make a new file list entry 67 */ 68 struct file_list * 69 new_fent() 70 { 71 register struct file_list *fp; 72 73 fp = (struct file_list *) malloc(sizeof *fp); 74 fp->f_needs = 0; 75 fp->f_next = 0; 76 fp->f_flags = 0; 77 fp->f_type = 0; 78 if (fcur == 0) 79 fcur = ftab = fp; 80 else 81 fcur->f_next = fp; 82 fcur = fp; 83 return (fp); 84 } 85 86 char *COPTS; 87 static struct users { 88 int u_default; 89 int u_min; 90 int u_max; 91 } users[] = { 92 { 24, 8, 1024 }, /* MACHINE_VAX */ 93 }; 94 #define NUSERS (sizeof (users) / sizeof (users[0])) 95 96 /* 97 * Build the makefile from the skeleton 98 */ 99 makefile() 100 { 101 FILE *ifp, *ofp; 102 char line[BUFSIZ]; 103 struct opt *op; 104 struct users *up; 105 106 read_files(); 107 strcpy(line, "../conf/Makefile."); 108 (void) strcat(line, machinename); 109 ifp = fopen(line, "r"); 110 if (ifp == 0) { 111 perror(line); 112 exit(1); 113 } 114 ofp = fopen(path("Makefile"), "w"); 115 if (ofp == 0) { 116 perror(path("Makefile")); 117 exit(1); 118 } 119 fprintf(ofp, "IDENT=-D%s", raise(ident)); 120 if (profiling) 121 fprintf(ofp, " -DGPROF"); 122 if (cputype == 0) { 123 printf("cpu type must be specified\n"); 124 exit(1); 125 } 126 { struct cputype *cp; 127 for (cp = cputype; cp; cp = cp->cpu_next) 128 fprintf(ofp, " -D%s", cp->cpu_name); 129 } 130 for (op = opt; op; op = op->op_next) 131 if (op->op_value) 132 fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value); 133 else 134 fprintf(ofp, " -D%s", op->op_name); 135 fprintf(ofp, "\n"); 136 if (hadtz == 0) 137 printf("timezone not specified; gmt assumed\n"); 138 if ((unsigned)machine > NUSERS) { 139 printf("maxusers config info isn't present, using vax\n"); 140 up = &users[MACHINE_VAX-1]; 141 } else 142 up = &users[machine-1]; 143 if (maxusers == 0) { 144 printf("maxusers not specified; %d assumed\n", up->u_default); 145 maxusers = up->u_default; 146 } else if (maxusers < up->u_min) { 147 printf("minimum of %d maxusers assumed\n", up->u_min); 148 maxusers = up->u_min; 149 } else if (maxusers > up->u_max) 150 printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers); 151 fprintf(ofp, "PARAM=-DTIMEZONE=%d -DDST=%d -DMAXUSERS=%d\n", 152 timezone, dst, maxusers); 153 for (op = mkopt; op; op = op->op_next) 154 fprintf(ofp, "%s=%s\n", op->op_name, op->op_value); 155 while (fgets(line, BUFSIZ, ifp) != 0) { 156 if (*line == '%') 157 goto percent; 158 if (profiling && strncmp(line, "COPTS=", 6) == 0) { 159 register char *cp; 160 161 fprintf(ofp, 162 "GPROF.EX=/usr/src/lib/libc/%s/csu/gmon.ex\n", 163 machinename); 164 cp = index(line, '\n'); 165 if (cp) 166 *cp = 0; 167 cp = line + 6; 168 while (*cp && (*cp == ' ' || *cp == '\t')) 169 cp++; 170 COPTS = malloc((unsigned)(strlen(cp) + 1)); 171 if (COPTS == 0) { 172 printf("config: out of memory\n"); 173 exit(1); 174 } 175 strcpy(COPTS, cp); 176 fprintf(ofp, "%s -pg\n", line); 177 continue; 178 } 179 fprintf(ofp, "%s", line); 180 continue; 181 percent: 182 if (eq(line, "%OBJS\n")) 183 do_objs(ofp); 184 else if (eq(line, "%CFILES\n")) 185 do_cfiles(ofp); 186 else if (eq(line, "%RULES\n")) 187 do_rules(ofp); 188 else if (eq(line, "%LOAD\n")) 189 do_load(ofp); 190 else 191 fprintf(stderr, 192 "Unknown %% construct in generic makefile: %s", 193 line); 194 } 195 (void) fclose(ifp); 196 (void) fclose(ofp); 197 } 198 199 /* 200 * Read in the information about files used in making the system. 201 * Store it in the ftab linked list. 202 */ 203 read_files() 204 { 205 FILE *fp; 206 register struct file_list *tp, *pf; 207 register struct device *dp; 208 register struct opt *op; 209 char *wd, *this, *needs, *devorprof; 210 char fname[32]; 211 int nreqs, first = 1, configdep, isdup; 212 213 ftab = 0; 214 (void) strcpy(fname, "files"); 215 openit: 216 fp = fopen(fname, "r"); 217 if (fp == 0) { 218 perror(fname); 219 exit(1); 220 } 221 next: 222 /* 223 * filename [ standard | optional ] [ config-dependent ] 224 * [ dev* | profiling-routine ] [ device-driver] 225 */ 226 wd = get_word(fp); 227 if (wd == (char *)EOF) { 228 (void) fclose(fp); 229 if (first == 1) { 230 (void) sprintf(fname, "files.%s", machinename); 231 first++; 232 goto openit; 233 } 234 if (first == 2) { 235 (void) sprintf(fname, "files.%s", raise(ident)); 236 first++; 237 fp = fopen(fname, "r"); 238 if (fp != 0) 239 goto next; 240 } 241 return; 242 } 243 if (wd == 0) 244 goto next; 245 this = ns(wd); 246 next_word(fp, wd); 247 if (wd == 0) { 248 printf("%s: No type for %s.\n", 249 fname, this); 250 exit(1); 251 } 252 if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags)) 253 isdup = 1; 254 else 255 isdup = 0; 256 tp = 0; 257 if (first == 3 && (tp = fltail_lookup(this)) != 0) 258 printf("%s: Local file %s overrides %s.\n", 259 fname, this, tp->f_fn); 260 nreqs = 0; 261 devorprof = ""; 262 configdep = 0; 263 needs = 0; 264 if (eq(wd, "standard")) 265 goto checkdev; 266 if (!eq(wd, "optional")) { 267 printf("%s: %s must be optional or standard\n", fname, this); 268 exit(1); 269 } 270 nextopt: 271 next_word(fp, wd); 272 if (wd == 0) 273 goto doneopt; 274 if (eq(wd, "config-dependent")) { 275 configdep++; 276 goto nextopt; 277 } 278 devorprof = wd; 279 if (eq(wd, "device-driver") || eq(wd, "profiling-routine")) { 280 next_word(fp, wd); 281 goto save; 282 } 283 nreqs++; 284 if (needs == 0 && nreqs == 1) 285 needs = ns(wd); 286 if (isdup) 287 goto invis; 288 for (dp = dtab; dp != 0; dp = dp->d_next) 289 if (eq(dp->d_name, wd)) 290 goto nextopt; 291 for (op = opt; op != 0; op = op->op_next) 292 if (op->op_value == 0 && opteq(op->op_name, wd)) { 293 if (nreqs == 1) { 294 free(needs); 295 needs = 0; 296 } 297 goto nextopt; 298 } 299 invis: 300 while ((wd = get_word(fp)) != 0) 301 ; 302 if (tp == 0) 303 tp = new_fent(); 304 tp->f_fn = this; 305 tp->f_type = INVISIBLE; 306 tp->f_needs = needs; 307 tp->f_flags = isdup; 308 goto next; 309 310 doneopt: 311 if (nreqs == 0) { 312 printf("%s: what is %s optional on?\n", 313 fname, this); 314 exit(1); 315 } 316 317 checkdev: 318 if (wd) { 319 next_word(fp, wd); 320 if (wd) { 321 if (eq(wd, "config-dependent")) { 322 configdep++; 323 goto checkdev; 324 } 325 devorprof = wd; 326 next_word(fp, wd); 327 } 328 } 329 330 save: 331 if (wd) { 332 printf("%s: syntax error describing %s\n", 333 fname, this); 334 exit(1); 335 } 336 if (eq(devorprof, "profiling-routine") && profiling == 0) 337 goto next; 338 if (tp == 0) 339 tp = new_fent(); 340 tp->f_fn = this; 341 if (eq(devorprof, "device-driver")) 342 tp->f_type = DRIVER; 343 else if (eq(devorprof, "profiling-routine")) 344 tp->f_type = PROFILING; 345 else 346 tp->f_type = NORMAL; 347 tp->f_flags = 0; 348 if (configdep) 349 tp->f_flags |= CONFIGDEP; 350 tp->f_needs = needs; 351 if (pf && pf->f_type == INVISIBLE) 352 pf->f_flags = 1; /* mark as duplicate */ 353 goto next; 354 } 355 356 opteq(cp, dp) 357 char *cp, *dp; 358 { 359 char c, d; 360 361 for (; ; cp++, dp++) { 362 if (*cp != *dp) { 363 c = isupper(*cp) ? tolower(*cp) : *cp; 364 d = isupper(*dp) ? tolower(*dp) : *dp; 365 if (c != d) 366 return (0); 367 } 368 if (*cp == 0) 369 return (1); 370 } 371 } 372 373 do_objs(fp) 374 FILE *fp; 375 { 376 register struct file_list *tp, *fl; 377 register int lpos, len; 378 register char *cp, och, *sp; 379 char swapname[32]; 380 381 fprintf(fp, "OBJS="); 382 lpos = 6; 383 for (tp = ftab; tp != 0; tp = tp->f_next) { 384 if (tp->f_type == INVISIBLE) 385 continue; 386 sp = tail(tp->f_fn); 387 for (fl = conf_list; fl; fl = fl->f_next) { 388 if (fl->f_type != SWAPSPEC) 389 continue; 390 sprintf(swapname, "swap%s.c", fl->f_fn); 391 if (eq(sp, swapname)) 392 goto cont; 393 } 394 cp = sp + (len = strlen(sp)) - 1; 395 och = *cp; 396 *cp = 'o'; 397 if (len + lpos > 72) { 398 lpos = 8; 399 fprintf(fp, "\\\n\t"); 400 } 401 fprintf(fp, "%s ", sp); 402 lpos += len + 1; 403 *cp = och; 404 cont: 405 ; 406 } 407 if (lpos != 8) 408 putc('\n', fp); 409 } 410 411 do_cfiles(fp) 412 FILE *fp; 413 { 414 register struct file_list *tp; 415 register int lpos, len; 416 417 fprintf(fp, "CFILES="); 418 lpos = 8; 419 for (tp = ftab; tp != 0; tp = tp->f_next) { 420 if (tp->f_type == INVISIBLE) 421 continue; 422 if (tp->f_fn[strlen(tp->f_fn)-1] != 'c') 423 continue; 424 if ((len = 3 + strlen(tp->f_fn)) + lpos > 72) { 425 lpos = 8; 426 fprintf(fp, "\\\n\t"); 427 } 428 fprintf(fp, "../%s ", tp->f_fn); 429 lpos += len + 1; 430 } 431 if (lpos != 8) 432 putc('\n', fp); 433 } 434 435 char * 436 tail(fn) 437 char *fn; 438 { 439 register char *cp; 440 441 cp = rindex(fn, '/'); 442 if (cp == 0) 443 return (fn); 444 return (cp+1); 445 } 446 447 /* 448 * Create the makerules for each file 449 * which is part of the system. 450 * Devices are processed with the special c2 option -i 451 * which avoids any problem areas with i/o addressing 452 * (e.g. for the VAX); assembler files are processed by as. 453 */ 454 do_rules(f) 455 FILE *f; 456 { 457 register char *cp, *np, och, *tp; 458 register struct file_list *ftp; 459 char *extras; 460 461 for (ftp = ftab; ftp != 0; ftp = ftp->f_next) { 462 if (ftp->f_type == INVISIBLE) 463 continue; 464 cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1; 465 och = *cp; 466 *cp = '\0'; 467 if (och == 'o') { 468 fprintf(f, "%so:\n\t-cp ../%so .\n", tail(np), np); 469 continue; 470 } 471 fprintf(f, "%so: ../%s%c\n", tail(np), np, och); 472 tp = tail(np); 473 if (och == 's') { 474 fprintf(f, "\t-ln -s ../%ss %sc\n", np, tp); 475 fprintf(f, "\t${CC} -E ${COPTS} %sc | ${AS} -o %so\n", 476 tp, tp); 477 fprintf(f, "\trm -f %sc\n\n", tp); 478 continue; 479 } 480 if (ftp->f_flags & CONFIGDEP) 481 extras = "${PARAM} "; 482 else 483 extras = ""; 484 switch (ftp->f_type) { 485 486 case NORMAL: 487 switch (machine) { 488 489 case MACHINE_VAX: 490 fprintf(f, "\t${CC} -c -S ${COPTS} %s../%sc\n", 491 extras, np); 492 fprintf(f, "\t${C2} %ss | ${INLINE} | ${AS} -o %so\n", 493 tp, tp); 494 fprintf(f, "\trm -f %ss\n\n", tp); 495 break; 496 } 497 break; 498 499 case DRIVER: 500 switch (machine) { 501 502 case MACHINE_VAX: 503 fprintf(f, "\t${CC} -c -S ${COPTS} %s../%sc\n", 504 extras, np); 505 fprintf(f,"\t${C2} -i %ss | ${INLINE} | ${AS} -o %so\n", 506 tp, tp); 507 fprintf(f, "\trm -f %ss\n\n", tp); 508 break; 509 } 510 break; 511 512 case PROFILING: 513 if (!profiling) 514 continue; 515 if (COPTS == 0) { 516 fprintf(stderr, 517 "config: COPTS undefined in generic makefile"); 518 COPTS = ""; 519 } 520 switch (machine) { 521 522 case MACHINE_VAX: 523 fprintf(f, "\t${CC} -c -S %s %s../%sc\n", 524 COPTS, extras, np); 525 fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp); 526 fprintf(f, "\t${INLINE} %ss | ${AS} -o %so\n", tp, tp); 527 fprintf(f, "\trm -f %ss\n\n", tp); 528 break; 529 } 530 break; 531 532 default: 533 printf("Don't know rules for %s\n", np); 534 break; 535 } 536 *cp = och; 537 } 538 } 539 540 /* 541 * Create the load strings 542 */ 543 do_load(f) 544 register FILE *f; 545 { 546 register struct file_list *fl; 547 int first = 1; 548 struct file_list *do_systemspec(); 549 550 fl = conf_list; 551 while (fl) { 552 if (fl->f_type != SYSTEMSPEC) { 553 fl = fl->f_next; 554 continue; 555 } 556 fl = do_systemspec(f, fl, first); 557 if (first) 558 first = 0; 559 } 560 fprintf(f, "all:"); 561 for (fl = conf_list; fl != 0; fl = fl->f_next) 562 if (fl->f_type == SYSTEMSPEC) 563 fprintf(f, " %s", fl->f_needs); 564 fprintf(f, "\n"); 565 } 566 567 struct file_list * 568 do_systemspec(f, fl, first) 569 FILE *f; 570 register struct file_list *fl; 571 int first; 572 { 573 574 fprintf(f, "%s: Makefile", fl->f_needs); 575 if (machine == MACHINE_VAX) 576 fprintf(f, " ${INLINECMD}", machinename); 577 fprintf(f, " locore.o ${OBJS} param.o ioconf.o swap%s.o\n", fl->f_fn); 578 fprintf(f, "\t@echo loading %s\n\t@rm -f %s\n", 579 fl->f_needs, fl->f_needs); 580 if (first) { 581 fprintf(f, "\t@sh ../conf/newvers.sh\n"); 582 fprintf(f, "\t@${CC} $(CFLAGS) -c vers.c\n"); 583 } 584 switch (machine) { 585 586 case MACHINE_VAX: 587 fprintf(f, "\t@${LD} -n -o %s -e start -x -T 80000000 ", 588 fl->f_needs); 589 break; 590 } 591 fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o "); 592 fprintf(f, "swap%s.o\n", fl->f_fn); 593 fprintf(f, "\t@echo rearranging symbols\n"); 594 fprintf(f, "\t@-symorder ../%s/symbols.sort %s\n", 595 machinename, fl->f_needs); 596 fprintf(f, "\t@size %s\n", fl->f_needs); 597 fprintf(f, "\t@chmod 755 %s\n\n", fl->f_needs); 598 do_swapspec(f, fl->f_fn); 599 for (fl = fl->f_next; fl->f_type == SWAPSPEC; fl = fl->f_next) 600 ; 601 return (fl); 602 } 603 604 do_swapspec(f, name) 605 FILE *f; 606 register char *name; 607 { 608 609 if (!eq(name, "generic")) { 610 fprintf(f, "swap%s.o: swap%s.c\n", name, name); 611 fprintf(f, "\t${CC} -c -O ${COPTS} swap%s.c\n\n", name); 612 return; 613 } 614 fprintf(f, "swapgeneric.o: ../%s/swapgeneric.c\n", machinename); 615 switch (machine) { 616 617 case MACHINE_VAX: 618 fprintf(f, "\t${CC} -c -S ${COPTS} "); 619 fprintf(f, "../%s/swapgeneric.c\n", machinename); 620 fprintf(f, "\t${C2} swapgeneric.s | ${INLINE}"); 621 fprintf(f, " | ${AS} -o swapgeneric.o\n"); 622 fprintf(f, "\trm -f swapgeneric.s\n\n"); 623 break; 624 } 625 } 626 627 char * 628 raise(str) 629 register char *str; 630 { 631 register char *cp = str; 632 633 while (*str) { 634 if (islower(*str)) 635 *str = toupper(*str); 636 str++; 637 } 638 return (cp); 639 } 640