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