mkmakefile.c revision 5325
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 214 fprintf(stderr, 215 "Unknown %% construct in generic makefile: %s", 216 line); 217 } 218 (void) fclose(ifp); 219 (void) fclose(ofp); 220} 221 222/* 223 * Read in the information about files used in making the system. 224 * Store it in the ftab linked list. 225 */ 226read_files() 227{ 228 FILE *fp; 229 register struct file_list *tp, *pf; 230 register struct device *dp; 231 struct device *save_dp; 232 register struct opt *op; 233 char *wd, *this, *needs, *special, *depends; 234 char fname[32]; 235 int nreqs, first = 1, configdep, isdup, std, filetype, 236 imp_rule, no_obj, before_depend; 237 238 ftab = 0; 239 (void) strcpy(fname, "../../conf/files"); 240openit: 241 fp = fopen(fname, "r"); 242 if (fp == 0) { 243 perror(fname); 244 exit(1); 245 } 246 if(ident == NULL) { 247 printf("no ident line specified\n"); 248 exit(1); 249 } 250next: 251 /* 252 * filename [ standard | optional ] [ config-dependent ] 253 * [ dev* | profiling-routine ] [ device-driver] [ no-obj ] 254 * [ compile-with "compile rule" [no-implicit-rule] ] 255 * [ dependancy "dependancy-list"] [ before-depend ] 256 */ 257 wd = get_word(fp); 258 if (wd == (char *)EOF) { 259 (void) fclose(fp); 260 if (first == 1) { 261 (void) sprintf(fname, "files.%s", machinename); 262 first++; 263 goto openit; 264 } 265 if (first == 2) { 266 (void) sprintf(fname, "files.%s", raise(ident)); 267 first++; 268 fp = fopen(fname, "r"); 269 if (fp != 0) 270 goto next; 271 } 272 return; 273 } 274 if (wd == 0) 275 goto next; 276 /*************************************************\ 277 * If it's a comment ignore to the end of the line * 278 \*************************************************/ 279 if(wd[0] == '#') 280 { 281 while( ((wd = get_word(fp)) != (char *)EOF) && wd) 282 ; 283 goto next; 284 } 285 this = ns(wd); 286 next_word(fp, wd); 287 if (wd == 0) { 288 printf("%s: No type for %s.\n", 289 fname, this); 290 exit(1); 291 } 292 if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags)) 293 isdup = 1; 294 else 295 isdup = 0; 296 tp = 0; 297 if (first == 3 && (tp = fltail_lookup(this)) != 0) 298 printf("%s: Local file %s overrides %s.\n", 299 fname, this, tp->f_fn); 300 nreqs = 0; 301 special = 0; 302 depends = 0; 303 configdep = 0; 304 needs = 0; 305 std = 0; 306 imp_rule = 0; 307 no_obj = 0; 308 before_depend = 0; 309 filetype = NORMAL; 310 if (eq(wd, "standard")) 311 std = 1; 312 else if (!eq(wd, "optional")) { 313 printf("%s: %s must be optional or standard\n", fname, this); 314 exit(1); 315 } 316nextparam: 317 next_word(fp, wd); 318 if (wd == 0) 319 goto doneparam; 320 if (eq(wd, "config-dependent")) { 321 configdep++; 322 goto nextparam; 323 } 324 if (eq(wd, "no-obj")) { 325 no_obj++; 326 goto nextparam; 327 } 328 if (eq(wd, "no-implicit-rule")) { 329 if (special == 0) { 330 printf("%s: alternate rule required when " 331 "\"no-implicit-rule\" is specified.\n", 332 fname); 333 } 334 imp_rule++; 335 goto nextparam; 336 } 337 if (eq(wd, "before-depend")) { 338 before_depend++; 339 goto nextparam; 340 } 341 if (eq(wd, "dependancy")) { 342 next_quoted_word(fp, wd); 343 if (wd == 0) { 344 printf("%s: %s missing compile command string.\n", 345 fname); 346 exit(1); 347 } 348 depends = ns(wd); 349 goto nextparam; 350 } 351 if (eq(wd, "no-obj")) { 352 no_obj++; 353 goto nextparam; 354 } 355 if (eq(wd, "no-implicit-rule")) { 356 if (special == 0) { 357 printf("%s: alternate rule required when " 358 "\"no-implicit-rule\" is specified.\n", 359 fname); 360 } 361 imp_rule++; 362 goto nextparam; 363 } 364 if (eq(wd, "dependancy")) { 365 next_quoted_word(fp, wd); 366 if (wd == 0) { 367 printf("%s: %s missing compile command string.\n", 368 fname); 369 exit(1); 370 } 371 depends = ns(wd); 372 goto nextparam; 373 } 374 if (eq(wd, "compile-with")) { 375 next_quoted_word(fp, wd); 376 if (wd == 0) { 377 printf("%s: %s missing compile command string.\n", 378 fname); 379 exit(1); 380 } 381 special = ns(wd); 382 goto nextparam; 383 } 384 nreqs++; 385 if (eq(wd, "device-driver")) { 386 filetype = DRIVER; 387 goto nextparam; 388 } 389 if (eq(wd, "profiling-routine")) { 390 filetype = PROFILING; 391 goto nextparam; 392 } 393 if (needs == 0 && nreqs == 1) 394 needs = ns(wd); 395 if (isdup) 396 goto invis; 397 for (dp = dtab; dp != 0; save_dp = dp, dp = dp->d_next) 398 if (eq(dp->d_name, wd)) { 399 if (std && dp->d_type == PSEUDO_DEVICE && 400 dp->d_slave <= 0) 401 dp->d_slave = 1; 402 goto nextparam; 403 } 404 if (std) { 405 dp = (struct device *) malloc(sizeof *dp); 406 init_dev(dp); 407 dp->d_name = ns(wd); 408 dp->d_type = PSEUDO_DEVICE; 409 dp->d_slave = 1; 410 save_dp->d_next = dp; 411 goto nextparam; 412 } 413 for (op = opt; op != 0; op = op->op_next) 414 if (op->op_value == 0 && opteq(op->op_name, wd)) { 415 if (nreqs == 1) { 416 free(needs); 417 needs = 0; 418 } 419 goto nextparam; 420 } 421invis: 422 while ((wd = get_word(fp)) != 0) 423 ; 424 if (tp == 0) 425 tp = new_fent(); 426 tp->f_fn = this; 427 tp->f_type = INVISIBLE; 428 tp->f_needs = needs; 429 tp->f_flags = isdup; 430 tp->f_special = special; 431 tp->f_depends = depends; 432 goto next; 433 434doneparam: 435 if (std == 0 && nreqs == 0) { 436 printf("%s: what is %s optional on?\n", 437 fname, this); 438 exit(1); 439 } 440 441save: 442 if (wd) { 443 printf("%s: syntax error describing %s\n", 444 fname, this); 445 exit(1); 446 } 447 if (filetype == PROFILING && profiling == 0) 448 goto next; 449 if (tp == 0) 450 tp = new_fent(); 451 tp->f_fn = this; 452 tp->f_type = filetype; 453 tp->f_flags = 0; 454 if (configdep) 455 tp->f_flags |= CONFIGDEP; 456 if (imp_rule) 457 tp->f_flags |= NO_IMPLCT_RULE; 458 if (no_obj) 459 tp->f_flags |= NO_OBJ; 460 if (before_depend) 461 tp->f_flags |= BEFORE_DEPEND; 462 if (imp_rule) 463 tp->f_flags |= NO_IMPLCT_RULE; 464 if (no_obj) 465 tp->f_flags |= NO_OBJ; 466 tp->f_needs = needs; 467 tp->f_special = special; 468 tp->f_depends = depends; 469 if (pf && pf->f_type == INVISIBLE) 470 pf->f_flags = 1; /* mark as duplicate */ 471 goto next; 472} 473 474opteq(cp, dp) 475 char *cp, *dp; 476{ 477 char c, d; 478 479 for (; ; cp++, dp++) { 480 if (*cp != *dp) { 481 c = isupper(*cp) ? tolower(*cp) : *cp; 482 d = isupper(*dp) ? tolower(*dp) : *dp; 483 if (c != d) 484 return (0); 485 } 486 if (*cp == 0) 487 return (1); 488 } 489} 490 491 492do_before_depend(fp) 493 FILE *fp; 494{ 495 register struct file_list *tp, *fl; 496 register int lpos, len; 497 char swapname[32]; 498 499 fputs("BEFORE_DEPEND=", fp); 500 lpos = 15; 501 for (tp = ftab; tp; tp = tp->f_next) 502 if (tp->f_flags & BEFORE_DEPEND) { 503 len = strlen(tp->f_fn); 504 if ((len = 3 + len) + lpos > 72) { 505 lpos = 8; 506 fputs("\\\n\t", fp); 507 } 508 if (tp->f_flags & NO_IMPLCT_RULE) 509 fprintf(fp, "%s ", tp->f_fn); 510 else 511 fprintf(fp, "$S/%s ", tp->f_fn); 512 lpos += len + 1; 513 } 514 if (lpos != 8) 515 putc('\n', fp); 516} 517 518do_objs(fp) 519 FILE *fp; 520{ 521 register struct file_list *tp, *fl; 522 register int lpos, len; 523 register char *cp, och, *sp; 524 char swapname[32]; 525 526 fprintf(fp, "OBJS="); 527 lpos = 6; 528 for (tp = ftab; tp != 0; tp = tp->f_next) { 529 if (tp->f_type == INVISIBLE || tp->f_flags & NO_OBJ) 530 continue; 531 sp = tail(tp->f_fn); 532 for (fl = conf_list; fl; fl = fl->f_next) { 533 if (fl->f_type != SWAPSPEC) 534 continue; 535 (void) sprintf(swapname, "swap%s.c", fl->f_fn); 536 if (eq(sp, swapname)) 537 goto cont; 538 } 539 cp = sp + (len = strlen(sp)) - 1; 540 och = *cp; 541 *cp = 'o'; 542 if (len + lpos > 72) { 543 lpos = 8; 544 fprintf(fp, "\\\n\t"); 545 } 546 fprintf(fp, "%s ", sp); 547 lpos += len + 1; 548 *cp = och; 549cont: 550 ; 551 } 552 if (lpos != 8) 553 putc('\n', fp); 554} 555 556do_cfiles(fp) 557 FILE *fp; 558{ 559 register struct file_list *tp, *fl; 560 register int lpos, len; 561 char swapname[32]; 562 563 fputs("CFILES=", fp); 564 lpos = 8; 565 for (tp = ftab; tp; tp = tp->f_next) 566 if (tp->f_type != INVISIBLE) { 567 len = strlen(tp->f_fn); 568 if (tp->f_fn[len - 1] != 'c') 569 continue; 570 if ((len = 3 + len) + lpos > 72) { 571 lpos = 8; 572 fputs("\\\n\t", fp); 573 } 574 fprintf(fp, "$S/%s ", tp->f_fn); 575 lpos += len + 1; 576 } 577 for (fl = conf_list; fl; fl = fl->f_next) 578 if (fl->f_type == SYSTEMSPEC) { 579 (void) sprintf(swapname, "swap%s.c", fl->f_fn); 580 if ((len = 3 + strlen(swapname)) + lpos > 72) { 581 lpos = 8; 582 fputs("\\\n\t", fp); 583 } 584 if (eq(fl->f_fn, "generic")) 585 fprintf(fp, "$S/%s/%s/%s ", 586 machinename, machinename, swapname); 587 else 588 fprintf(fp, "%s ", swapname); 589 lpos += len + 1; 590 } 591 if (lpos != 8) 592 putc('\n', fp); 593} 594 595char * 596tail(fn) 597 char *fn; 598{ 599 register char *cp; 600 601 cp = rindex(fn, '/'); 602 if (cp == 0) 603 return (fn); 604 return (cp+1); 605} 606 607/* 608 * Create the makerules for each file 609 * which is part of the system. 610 * Devices are processed with the special c2 option -i 611 * which avoids any problem areas with i/o addressing 612 * (e.g. for the VAX); assembler files are processed by as. 613 */ 614do_rules(f) 615 FILE *f; 616{ 617 register char *cp, *np, och, *tp; 618 register struct file_list *ftp; 619 char *special; 620 621 for (ftp = ftab; ftp != 0; ftp = ftp->f_next) { 622 if (ftp->f_type == INVISIBLE) 623 continue; 624 cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1; 625 och = *cp; 626 if (ftp->f_flags & NO_IMPLCT_RULE) { 627 if (ftp->f_depends) 628 fprintf(f, "%s: %s\n", np, ftp->f_depends ); 629 else 630 fprintf(f, "%s: \n", np ); 631 } 632 else { 633 *cp = '\0'; 634 if (och == 'o') { 635 fprintf(f, "%so:\n\t-cp $S/%so .\n\n", 636 tail(np), np); 637 continue; 638 } 639 if (ftp->f_depends) 640 fprintf(f, "%so: $S/%s%c %s\n", tail(np), 641 np, och, ftp->f_depends); 642 else 643 fprintf(f, "%so: $S/%s%c\n", tail(np), 644 np, och); 645 } 646 tp = tail(np); 647 special = ftp->f_special; 648 if (special == 0) { 649 char *ftype; 650 static char cmd[128]; 651 652 switch (ftp->f_type) { 653 654 case NORMAL: 655 ftype = "NORMAL"; 656 break; 657 658 case DRIVER: 659 ftype = "DRIVER"; 660 break; 661 662 case PROFILING: 663 if (!profiling) 664 continue; 665 ftype = "PROFILE"; 666 break; 667 668 default: 669 printf("config: don't know rules for %s\n", np); 670 break; 671 } 672 (void)sprintf(cmd, "${%s_%c%s}", ftype, toupper(och), 673 ftp->f_flags & CONFIGDEP? "_C" : ""); 674 special = cmd; 675 } 676 *cp = och; 677 fprintf(f, "\t%s\n\n", special); 678 } 679} 680 681/* 682 * Create the load strings 683 */ 684do_load(f) 685 register FILE *f; 686{ 687 register struct file_list *fl; 688 register int first; 689 struct file_list *do_systemspec(); 690 691 for (first = 1, fl = conf_list; fl; first = 0) 692 fl = fl->f_type == SYSTEMSPEC ? 693 do_systemspec(f, fl, first) : fl->f_next; 694 fputs("all:", f); 695 for (fl = conf_list; fl; fl = fl->f_next) 696 if (fl->f_type == SYSTEMSPEC) 697 fprintf(f, " %s", fl->f_needs); 698 putc('\n', f); 699} 700 701struct file_list * 702do_systemspec(f, fl, first) 703 FILE *f; 704 register struct file_list *fl; 705 int first; 706{ 707 708 fprintf(f, "%s: ${SYSTEM_DEP} swap%s.o", fl->f_needs, fl->f_fn); 709 if (first) 710 fprintf(f, " vers.o"); 711 fprintf(f, "\n\t${SYSTEM_LD_HEAD}\n"); 712 fprintf(f, "\t${SYSTEM_LD} swap%s.o\n", fl->f_fn); 713 fprintf(f, "\t${SYSTEM_LD_TAIL}\n\n"); 714 do_swapspec(f, fl->f_fn); 715 for (fl = fl->f_next; fl; fl = fl->f_next) 716 if (fl->f_type != SWAPSPEC) 717 break; 718 return (fl); 719} 720 721do_swapspec(f, name) 722 FILE *f; 723 register char *name; 724{ 725 726 if (!eq(name, "generic")) 727 fprintf(f, "swap%s.o: swap%s.c\n", name, name); 728 else 729 fprintf(f, "swapgeneric.o: $S/%s/%s/swapgeneric.c\n", 730 machinename, machinename); 731 fprintf(f, "\t${NORMAL_C}\n\n"); 732} 733 734char * 735raise(str) 736 register char *str; 737{ 738 register char *cp = str; 739 740 while (*str) { 741 if (islower(*str)) 742 *str = toupper(*str); 743 str++; 744 } 745 return (cp); 746} 747 748