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