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