1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights 7 * Reserved. This file contains Original Code and/or Modifications of 8 * Original Code as defined in and that are subject to the Apple Public 9 * Source License Version 1.0 (the 'License'). You may not use this file 10 * except in compliance with the License. Please obtain a copy of the 11 * License at http://www.apple.com/publicsource and read it before using 12 * this file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 19 * License for the specific language governing rights and limitations 20 * under the License." 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24/* 25 * Mach Operating System 26 * Copyright (c) 1990 Carnegie-Mellon University 27 * Copyright (c) 1989 Carnegie-Mellon University 28 * Copyright (c) 1988 Carnegie-Mellon University 29 * Copyright (c) 1987 Carnegie-Mellon University 30 * All rights reserved. The CMU software License Agreement specifies 31 * the terms and conditions for use and redistribution. 32 */ 33 34/* 35 * Copyright (c) 1980 Regents of the University of California. 36 * All rights reserved. 37 * 38 * Redistribution and use in source and binary forms are permitted 39 * provided that the above copyright notice and this paragraph are 40 * duplicated in all such forms and that any documentation, 41 * advertising materials, and other materials related to such 42 * distribution and use acknowledge that the software was developed 43 * by the University of California, Berkeley. The name of the 44 * University may not be used to endorse or promote products derived 45 * from this software without specific prior written permission. 46 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 48 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 49 */ 50 51#ifndef lint 52static char sccsid[] __attribute__((used)) = "@(#)mkmakefile.c 5.21 (Berkeley) 6/18/88"; 53#endif /* not lint */ 54 55/* 56 * Build the makefile for the system, from 57 * the information in the files files and the 58 * additional files for the machine being compiled to. 59 */ 60 61#include <stdio.h> 62#include <unistd.h> /* for unlink */ 63#include <ctype.h> 64#include "parser.h" 65#include "config.h" 66 67void read_files(void); 68void do_objs(FILE *fp, const char *msg, int ext); 69void do_ordered(FILE *fp); 70void do_files(FILE *fp, const char *msg, char ext); 71void do_machdep(FILE *ofp); 72void do_build(const char *name, void (*format)(FILE *)); 73void do_rules(FILE *f); 74void do_load(FILE *f); 75struct file_list *do_systemspec(FILE *f, struct file_list *fl, int first); 76void do_swapspec(FILE *f, const char *name, char *sysname); 77void copy_dependencies(FILE *makin, FILE *makout); 78 79void build_cputypes(FILE *fp); 80void build_confdep(FILE *fp); 81 82struct file_list *fl_lookup(char *file); 83struct file_list *fltail_lookup(char *file); 84struct file_list *new_fent(void); 85 86void put_source_file_name(FILE *fp, struct file_list *tp); 87 88 89#define DO_SWAPFILE 0 90 91#define next_word(fp, wd) \ 92 { register const char *word = get_word(fp); \ 93 if (word == (char *)EOF) \ 94 return; \ 95 else \ 96 wd = word; \ 97 } 98 99static struct file_list *fcur; 100const char *tail(const char *fn); 101char *allCaps(char *str); 102 103/* 104 * Lookup a file, by name. 105 */ 106struct file_list * 107fl_lookup(char *file) 108{ 109 register struct file_list *fp; 110 111 for (fp = ftab ; fp != 0; fp = fp->f_next) { 112 if (eq(fp->f_fn, file)) 113 return (fp); 114 } 115 return (0); 116} 117 118/* 119 * Lookup a file, by final component name. 120 */ 121struct file_list * 122fltail_lookup(char *file) 123{ 124 register struct file_list *fp; 125 126 for (fp = ftab ; fp != 0; fp = fp->f_next) { 127 if (eq(tail(fp->f_fn), tail(file))) 128 return (fp); 129 } 130 return (0); 131} 132 133/* 134 * Make a new file list entry 135 */ 136struct file_list * 137new_fent(void) 138{ 139 register struct file_list *fp; 140 141 fp = (struct file_list *) malloc(sizeof *fp); 142 fp->f_needs = 0; 143 fp->f_next = 0; 144 fp->f_flags = 0; 145 fp->f_type = 0; 146 fp->f_extra = (char *) 0; 147 if (fcur == 0) 148 fcur = ftab = fp; 149 else 150 fcur->f_next = fp; 151 fcur = fp; 152 return (fp); 153} 154 155char *COPTS; 156static struct users { 157 int u_default; 158 int u_min; 159 int u_max; 160} users[] = { 161 { 24, 2, 1024 }, /* MACHINE_VAX */ 162 { 8, 2, 32 }, /* MACHINE_SUN */ 163 { 16, 4, 32 }, /* MACHINE_ROMP */ 164 { 8, 2, 32 }, /* MACHINE_SUN2 */ 165 { 8, 2, 32 }, /* MACHINE_SUN3 */ 166 { 24, 8, 1024}, /* MACHINE_MMAX */ 167 { 32, 8, 1024}, /* MACHINE_SQT */ 168 { 8, 2, 32 }, /* MACHINE_SUN4 */ 169 { 2, 2, 1024 }, /* MACHINE_I386 */ 170 { 32, 8, 1024 }, /* MACHINE_IX */ 171 { 32, 8, 1024 }, /* MACHINE_MIPSY */ 172 { 32, 8, 1024 }, /* MACHINE_MIPS*/ 173 { 32, 8, 1024 }, /* MACHINE_I860*/ 174 { 8, 2, 32 }, /* MACHINE_M68K */ 175 { 8, 2, 32 }, /* MACHINE_M88K */ 176 { 8, 2, 32 }, /* MACHINE_M98K */ 177 { 8, 2, 32 }, /* MACHINE_HPPA */ 178 { 8, 2, 32 }, /* MACHINE_SPARC */ 179 { 8, 2, 32 }, /* MACHINE_PPC */ 180 { 8, 2, 32 }, /* MACHINE_ARM */ 181 { 8, 2, 32 }, /* MACHINE_X86_64 */ 182}; 183#define NUSERS (sizeof (users) / sizeof (users[0])) 184 185const char * 186get_VPATH(void) 187{ 188 static char *vpath = NULL; 189 190 if ((vpath == NULL) && 191 ((vpath = getenv("VPATH")) != NULL) && 192 (*vpath != ':')) { 193 register char *buf = malloc((unsigned)(strlen(vpath) + 2)); 194 195 vpath = strcat(strcpy(buf, ":"), vpath); 196 } 197 198 return vpath ? vpath : ""; 199} 200 201 202/* 203 * Build the makefile from the skeleton 204 */ 205void 206makefile(void) 207{ 208 FILE *ifp, *ofp; 209 FILE *dfp; 210 char pname[BUFSIZ]; 211 char line[BUFSIZ]; 212 struct opt *op; 213 struct users *up; 214 215 read_files(); 216 (void) sprintf(line, "%s/Makefile.template", config_directory); 217 ifp = fopenp(VPATH, line, pname, "r"); 218 if (ifp == 0) { 219 perror(line); 220 exit(1); 221 } 222 dfp = fopen(path("Makefile"), "r"); 223 rename(path("Makefile"), path("Makefile.old")); 224 unlink(path("Makefile.old")); 225 unlink(path("M.d")); 226 if ((ofp = fopen(path("M.d"), "w")) == NULL) { 227 perror(path("M.d")); 228 /* We'll let this error go */ 229 } 230 else 231 fclose(ofp); 232 ofp = fopen(path("Makefile"), "w"); 233 if (ofp == 0) { 234 perror(path("Makefile")); 235 exit(1); 236 } 237 fprintf(ofp, "SOURCE_DIR=%s\n", source_directory); 238 239 if (machine == MACHINE_SUN || machine == MACHINE_SUN2 240 || machine == MACHINE_SUN3 || machine == MACHINE_SUN4) 241 fprintf(ofp, "export IDENT=-D%s -D%s", machinename, allCaps(ident)); 242 else 243 fprintf(ofp, "export IDENT=-D%s", allCaps(ident)); 244 if (profiling) 245 fprintf(ofp, " -DGPROF"); 246 if (cputype == 0) { 247 printf("cpu type must be specified\n"); 248 exit(1); 249 } 250 do_build("cputypes.h", build_cputypes); 251 do_build("platforms.h", build_cputypes); 252 253 for (op = opt; op; op = op->op_next) 254 if (op->op_value) 255 fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value); 256 else 257 fprintf(ofp, " -D%s", op->op_name); 258 fprintf(ofp, "\n"); 259 if ((unsigned)machine > NUSERS) { 260 printf("maxusers config info isn't present, using vax\n"); 261 up = &users[MACHINE_VAX-1]; 262 } else 263 up = &users[machine-1]; 264 if (maxusers < up->u_min) { 265 maxusers = up->u_min; 266 } else if (maxusers > up->u_max) 267 printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers); 268 if (maxusers) { 269 do_build("confdep.h", build_confdep); 270 } 271 for (op = mkopt; op; op = op->op_next) 272 if (op->op_value) 273 fprintf(ofp, "%s=%s\n", op->op_name, op->op_value); 274 else 275 fprintf(ofp, "%s\n", op->op_name); 276 277 while (fgets(line, BUFSIZ, ifp) != 0) { 278 if (*line == '%') 279 goto percent; 280 if (profiling && strncmp(line, "COPTS=", 6) == 0) { 281 register char *cp; 282 if (machine != MACHINE_MMAX) 283 fprintf(ofp, 284 "GPROF.EX=$(SOURCE_DIR)/machdep/%s/gmon.ex\n", machinename); 285 cp = index(line, '\n'); 286 if (cp) 287 *cp = 0; 288 cp = line + 6; 289 while (*cp && (*cp == ' ' || *cp == '\t')) 290 cp++; 291 COPTS = malloc((unsigned)(strlen(cp) + 1)); 292 if (COPTS == 0) { 293 printf("config: out of memory\n"); 294 exit(1); 295 } 296 strcpy(COPTS, cp); 297 if (machine == MACHINE_MIPSY || machine == MACHINE_MIPS) { 298 fprintf(ofp, "%s ${CCPROFOPT}\n", line); 299 fprintf(ofp, "PCOPTS=%s\n", cp); 300 } else if (machine == MACHINE_MMAX) 301 fprintf(ofp, "%s -p\n",line); 302 else 303 fprintf(ofp, "%s -pg\n", line); 304 continue; 305 } 306 fprintf(ofp, "%s", line); 307 continue; 308 percent: 309 if (eq(line, "%OBJS\n")) { 310 do_objs(ofp, "OBJS=", -1); 311 } else if (eq(line, "%CFILES\n")) { 312 do_files(ofp, "CFILES=", 'c'); 313 do_objs(ofp, "COBJS=", 'c'); 314 } else if (eq(line, "%SFILES\n")) { 315 do_files(ofp, "SFILES=", 's'); 316 do_objs(ofp, "SOBJS=", 's'); 317 } else if (eq(line, "%MACHDEP\n")) { 318 /* 319 * Move do_machdep() after the mkopt stuff. 320 */ 321 for (op = mkopt; op; op = op->op_next) 322 fprintf(ofp, "%s=%s\n", op->op_name, op->op_value); 323 do_machdep(ofp); 324 } else if (eq(line, "%RULES\n")) 325 do_rules(ofp); 326 else if (eq(line, "%LOAD\n")) 327 do_load(ofp); 328 else 329 fprintf(stderr, 330 "Unknown %% construct in generic makefile: %s", 331 line); 332 } 333 if (dfp != NULL) 334 { 335 copy_dependencies(dfp, ofp); 336 (void) fclose(dfp); 337 } 338 (void) fclose(ifp); 339 (void) fclose(ofp); 340} 341 342/* 343 * Read in the information about files used in making the system. 344 * Store it in the ftab linked list. 345 */ 346void 347read_files(void) 348{ 349 FILE *fp; 350 register struct file_list *tp, *pf; 351 register struct device *dp; 352 register struct opt *op; 353 const char *wd; 354 char *this, *needs; 355 const char *devorprof; 356 int options; 357 int not_option; 358 int ordered; 359 int sedit; /* SQT */ 360 char pname[BUFSIZ]; 361 char fname[1024]; 362 char *rest = (char *) 0; 363 struct cputype *cp; 364 int nreqs, first = 1, isdup; 365 366 ftab = 0; 367 (void) sprintf(fname, "%s/files", config_directory); 368openit: 369 fp = fopenp(VPATH, fname, pname, "r"); 370 if (fp == 0) { 371 perror(fname); 372 exit(1); 373 } 374next: 375 options = 0; 376 rest = (char *) 0; 377 /* 378 * filename [ standard | optional ] 379 * [ dev* | profiling-routine ] [ device-driver] 380 */ 381 /* 382 * MACHINE_SQT ONLY: 383 * 384 * filename [ standard | optional ] 385 * [ ordered | sedit ] 386 * [ dev* | profiling-routine ] [ device-driver] 387 */ 388 wd = get_word(fp); 389 if (wd == (char *)EOF) { 390 (void) fclose(fp); 391 if (first == 1) { 392 (void) sprintf(fname, "%s/files.%s", config_directory, machinename); 393 first++; 394 goto openit; 395 } 396 if (first == 2) { 397 (void) sprintf(fname, "files.%s", allCaps(ident)); 398 first++; 399 fp = fopenp(VPATH, fname, pname, "r"); 400 if (fp != 0) 401 goto next; 402 } 403 return; 404 } 405 if (wd == 0) 406 goto next; 407 /* 408 * Allow comment lines beginning witha '#' character. 409 */ 410 if (*wd == '#') 411 { 412 while ((wd=get_word(fp)) && wd != (char *)EOF) 413 ; 414 goto next; 415 } 416 417 this = ns(wd); 418 next_word(fp, wd); 419 if (wd == 0) { 420 printf("%s: No type for %s.\n", 421 fname, this); 422 exit(1); 423 } 424 if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags)) 425 isdup = 1; 426 else 427 isdup = 0; 428 tp = 0; 429 if (first == 3 && (tp = fltail_lookup(this)) != 0) 430 printf("%s: Local file %s overrides %s.\n", 431 fname, this, tp->f_fn); 432 nreqs = 0; 433 devorprof = ""; 434 ordered = 0; 435 sedit = 1; /* SQT: assume sedit for now */ 436 needs = 0; 437 if (eq(wd, "standard")) 438 goto checkdev; 439 if (!eq(wd, "optional")) { 440 printf("%s: %s must be optional or standard\n", fname, this); 441 exit(1); 442 } 443 if (strncmp(this, "OPTIONS/", 8) == 0) 444 options++; 445 not_option = 0; 446nextopt: 447 next_word(fp, wd); 448 if (wd == 0) 449 goto doneopt; 450 if (eq(wd, "ordered")) { 451 ordered++; 452 goto nextopt; 453 } 454 if (machine == MACHINE_SQT && eq(wd, "sedit")) { 455 sedit++; 456 goto nextopt; 457 } 458 if (eq(wd, "not")) { 459 not_option = !not_option; 460 goto nextopt; 461 } 462 devorprof = wd; 463 if (eq(wd, "device-driver") || eq(wd, "profiling-routine")) { 464 next_word(fp, wd); 465 goto save; 466 } 467 nreqs++; 468 if (needs == 0 && nreqs == 1) 469 needs = ns(wd); 470 if (isdup) 471 goto invis; 472 if (options) 473 { 474 struct opt *lop = 0; 475 struct device tdev; 476 477 /* 478 * Allocate a pseudo-device entry which we will insert into 479 * the device list below. The flags field is set non-zero to 480 * indicate an internal entry rather than one generated from 481 * the configuration file. The slave field is set to define 482 * the corresponding symbol as 0 should we fail to find the 483 * option in the option list. 484 */ 485 init_dev(&tdev); 486 tdev.d_name = ns(wd); 487 tdev.d_type = PSEUDO_DEVICE; 488 tdev.d_flags++; 489 tdev.d_slave = 0; 490 491 for (op=opt; op; lop=op, op=op->op_next) 492 { 493 char *od = allCaps(ns(wd)); 494 495 /* 496 * Found an option which matches the current device 497 * dependency identifier. Set the slave field to 498 * define the option in the header file. 499 */ 500 if (strcmp(op->op_name, od) == 0) 501 { 502 tdev.d_slave = 1; 503 if (lop == 0) 504 opt = op->op_next; 505 else 506 lop->op_next = op->op_next; 507 free(op); 508 op = 0; 509 } 510 free(od); 511 if (op == 0) 512 break; 513 } 514 newdev(&tdev); 515 } 516 for (dp = dtab; dp != 0; dp = dp->d_next) { 517 if (eq(dp->d_name, wd) && (dp->d_type != PSEUDO_DEVICE || dp->d_slave)) { 518 if (not_option) 519 goto invis; /* dont want file if option present */ 520 else 521 goto nextopt; 522 } 523 } 524 if (not_option) 525 goto nextopt; /* want file if option missing */ 526 527 for (op = opt; op != 0; op = op->op_next) 528 if (op->op_value == 0 && opteq(op->op_name, wd)) { 529 if (nreqs == 1) { 530 free(needs); 531 needs = 0; 532 } 533 goto nextopt; 534 } 535 536 for (cp = cputype; cp; cp = cp->cpu_next) 537 if (opteq(cp->cpu_name, wd)) { 538 if (nreqs == 1) { 539 free(needs); 540 needs = 0; 541 } 542 goto nextopt; 543 } 544 545invis: 546 while ((wd = get_word(fp)) != 0) 547 ; 548 if (tp == 0) 549 tp = new_fent(); 550 tp->f_fn = this; 551 tp->f_type = INVISIBLE; 552 tp->f_needs = needs; 553 tp->f_flags = isdup; 554 goto next; 555 556doneopt: 557 if (nreqs == 0) { 558 printf("%s: what is %s optional on?\n", 559 fname, this); 560 exit(1); 561 } 562 563checkdev: 564 if (wd) { 565 if (*wd == '|') 566 goto getrest; 567 next_word(fp, wd); 568 if (wd) { 569 if (eq(wd, "ordered")) { 570 ordered++; 571 goto checkdev; 572 } 573 if (machine == MACHINE_SQT && eq(wd, "sedit")) { 574 sedit++; 575 goto checkdev; 576 } 577 devorprof = wd; 578 next_word(fp, wd); 579 } 580 } 581 582save: 583getrest: 584 if (wd) { 585 if (*wd == '|') { 586 rest = ns(get_rest(fp)); 587 } else { 588 printf("%s: syntax error describing %s\n", 589 fname, this); 590 exit(1); 591 } 592 } 593 if (eq(devorprof, "profiling-routine") && profiling == 0) 594 goto next; 595 if (tp == 0) 596 tp = new_fent(); 597 tp->f_fn = this; 598 tp->f_extra = rest; 599 if (options) 600 tp->f_type = INVISIBLE; 601 else 602 if (eq(devorprof, "device-driver")) 603 tp->f_type = DRIVER; 604 else if (eq(devorprof, "profiling-routine")) 605 tp->f_type = PROFILING; 606 else 607 tp->f_type = NORMAL; 608 tp->f_flags = 0; 609 if (ordered) 610 tp->f_flags |= ORDERED; 611 if (sedit) /* SQT */ 612 tp->f_flags |= SEDIT; 613 tp->f_needs = needs; 614 if (pf && pf->f_type == INVISIBLE) 615 pf->f_flags = 1; /* mark as duplicate */ 616 goto next; 617} 618 619int 620opteq(const char *cp, const char *dp) 621{ 622 char c, d; 623 624 for (; ; cp++, dp++) { 625 if (*cp != *dp) { 626 c = isupper(*cp) ? tolower(*cp) : *cp; 627 d = isupper(*dp) ? tolower(*dp) : *dp; 628 if (c != d) 629 return (0); 630 } 631 if (*cp == 0) 632 return (1); 633 } 634} 635 636void 637put_source_file_name(FILE *fp, struct file_list *tp) 638{ 639 if ((tp->f_fn[0] == '.') && (tp->f_fn[1] == '/')) 640 fprintf(fp, "%s ", tp->f_fn); 641 else 642 fprintf(fp, "$(SOURCE_DIR)/%s ", tp->f_fn); 643} 644 645void 646do_objs(FILE *fp, const char *msg, int ext) 647{ 648 register struct file_list *tp; 649 register int lpos, len; 650 char *cp; 651 char och; 652 const char *sp; 653#if DO_SWAPFILE 654 register struct file_list *fl; 655 char swapname[32]; 656#endif /* DO_SWAPFILE */ 657 658 fprintf(fp, "%s", msg); 659 lpos = strlen(msg); 660 for (tp = ftab; tp != 0; tp = tp->f_next) { 661 if (tp->f_type == INVISIBLE) 662 continue; 663 664 /* 665 * Check for '.o' file in list 666 */ 667 cp = tp->f_fn + (len = strlen(tp->f_fn)) - 1; 668 if ((ext == -1 && tp->f_flags & ORDERED) || /* not in objs */ 669 (ext != -1 && *cp != ext)) 670 continue; 671 else if (*cp == 'o') { 672 if (len + lpos > 72) { 673 lpos = 8; 674 fprintf(fp, "\\\n\t"); 675 } 676 put_source_file_name(fp, tp); 677 fprintf(fp, " "); 678 lpos += len + 1; 679 continue; 680 } 681 sp = tail(tp->f_fn); 682#if DO_SWAPFILE 683 for (fl = conf_list; fl; fl = fl->f_next) { 684 if (fl->f_type != SWAPSPEC) 685 continue; 686 (void) sprintf(swapname, "swap%s.c", fl->f_fn); 687 if (eq(sp, swapname)) 688 goto cont; 689 } 690#endif /* DO_SWAPFILE */ 691 cp = (char *)sp + (len = strlen(sp)) - 1; 692 och = *cp; 693 *cp = 'o'; 694 if (len + lpos > 72) { 695 lpos = 8; 696 fprintf(fp, "\\\n\t"); 697 } 698 fprintf(fp, "%s ", sp); 699 lpos += len + 1; 700 *cp = och; 701#if DO_SWAPFILE 702cont: 703 ; 704#endif /* DO_SWAPFILE */ 705 } 706 if (lpos != 8) 707 putc('\n', fp); 708} 709 710/* not presently used and probably broken, use ORDERED instead */ 711void 712do_ordered(FILE *fp) 713{ 714 register struct file_list *tp; 715 register int lpos, len; 716 char *cp; 717 char och; 718 const char *sp; 719 720 fprintf(fp, "ORDERED="); 721 lpos = 10; 722 for (tp = ftab; tp != 0; tp = tp->f_next) { 723 if ((tp->f_flags & ORDERED) != ORDERED) 724 continue; 725 sp = tail(tp->f_fn); 726 cp = (char *)sp + (len = strlen(sp)) - 1; 727 och = *cp; 728 *cp = 'o'; 729 if (len + lpos > 72) { 730 lpos = 8; 731 fprintf(fp, "\\\n\t"); 732 } 733 fprintf(fp, "%s ", sp); 734 lpos += len + 1; 735 *cp = och; 736 } 737 if (lpos != 8) 738 putc('\n', fp); 739} 740 741void 742do_files(FILE *fp, const char *msg, char ext) 743{ 744 register struct file_list *tp; 745 register int lpos, len=0; /* dvw: init to 0 */ 746 747 fprintf(fp, "%s", msg); 748 lpos = 8; 749 for (tp = ftab; tp != 0; tp = tp->f_next) { 750 if (tp->f_type == INVISIBLE) 751 continue; 752 if (tp->f_fn[strlen(tp->f_fn)-1] != ext) 753 continue; 754 /* 755 * Always generate a newline. 756 * Our Makefile's aren't readable anyway. 757 */ 758 759 lpos = 8; 760 fprintf(fp, "\\\n\t"); 761 put_source_file_name(fp, tp); 762 lpos += len + 1; 763 } 764 if (lpos != 8) 765 putc('\n', fp); 766} 767 768/* 769 * Include machine dependent makefile in output 770 */ 771 772void 773do_machdep(FILE *ofp) 774{ 775 FILE *ifp; 776 char pname[BUFSIZ]; 777 char line[BUFSIZ]; 778 779 (void) sprintf(line, "%s/Makefile.%s", config_directory, machinename); 780 ifp = fopenp(VPATH, line, pname, "r"); 781 if (ifp == 0) { 782 perror(line); 783 exit(1); 784 } 785 while (fgets(line, BUFSIZ, ifp) != 0) { 786 if (profiling && (strncmp(line, "LIBS=", 5) == 0)) 787 fprintf(ofp,"LIBS=${LIBS_P}\n"); 788 else 789 fputs(line, ofp); 790 } 791 fclose(ifp); 792} 793 794 795/* 796 * Format configuration dependent parameter file. 797 */ 798 799void 800build_confdep(FILE *fp) 801{ 802 fprintf(fp, "#define MAXUSERS %d\n", maxusers); 803} 804 805/* 806 * Format cpu types file. 807 */ 808 809void 810build_cputypes(FILE *fp) 811{ 812 struct cputype *cp; 813 814 for (cp = cputype; cp; cp = cp->cpu_next) 815 fprintf(fp, "#define\t%s\t1\n", cp->cpu_name); 816} 817 818 819 820/* 821 * Build a define parameter file. Create it first in a temporary location and 822 * determine if this new contents differs from the old before actually 823 * replacing the original (so as not to introduce avoidable extraneous 824 * compilations). 825 */ 826 827void 828do_build(const char *name, void (*format)(FILE *)) 829{ 830 static char temp[]="#config.tmp"; 831 FILE *tfp, *ofp; 832 int c; 833 834 unlink(path(temp)); 835 tfp = fopen(path(temp), "w+"); 836 if (tfp == 0) { 837 perror(path(temp)); 838 exit(1); 839 } 840 unlink(path(temp)); 841 (*format)(tfp); 842 ofp = fopen(path(name), "r"); 843 if (ofp != 0) 844 { 845 fseek(tfp, 0, 0); 846 while ((c = fgetc(tfp)) != EOF) 847 if (fgetc(ofp) != c) 848 goto copy; 849 if (fgetc(ofp) == EOF) 850 goto same; 851 852 } 853copy: 854 if (ofp) 855 fclose(ofp); 856 unlink(path(name)); 857 ofp = fopen(path(name), "w"); 858 if (ofp == 0) { 859 perror(path(name)); 860 exit(1); 861 } 862 fseek(tfp, 0, 0); 863 while ((c = fgetc(tfp)) != EOF) 864 fputc(c, ofp); 865same: 866 fclose(ofp); 867 fclose(tfp); 868} 869 870const char * 871tail(const char *fn) 872{ 873 register const char *cp; 874 875 cp = rindex(fn, '/'); 876 if (cp == 0) 877 return (fn); 878 return (cp+1); 879} 880 881/* 882 * Create the makerules for each file 883 * which is part of the system. 884 * Devices are processed with the special c2 option -i 885 * which avoids any problem areas with i/o addressing 886 * (e.g. for the VAX); assembler files are processed by as. 887 */ 888void 889do_rules(FILE *f) 890{ 891 char *cp; 892 char *np, och; 893 const char *tp; 894 register struct file_list *ftp; 895 const char *extras = ""; /* dvw: init to "" */ 896 char *source_dir; 897 char och_upper; 898 const char *nl = ""; 899 900 for (ftp = ftab; ftp != 0; ftp = ftp->f_next) { 901 if (ftp->f_type == INVISIBLE) 902 continue; 903 cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1; 904 och = *cp; 905 /* 906 * Don't compile '.o' files 907 */ 908 if (och == 'o') 909 continue; 910 /* 911 * Determine where sources should come from 912 */ 913 if ((np[0] == '.') && (np[1] == '/')) { 914 source_dir = ""; 915 np += 2; 916 } else 917 source_dir = "$(SOURCE_DIR)/"; 918 *cp = '\0'; 919 tp = tail(np); /* dvw: init tp before 'if' */ 920 fprintf(f, "-include %sd\n", tp); 921 fprintf(f, "%so: %s%s%c\n", tp, source_dir, np, och); 922 if (och == 's') { 923 switch (machine) { 924 case MACHINE_MIPSY: 925 case MACHINE_MIPS: 926 break; 927 default: 928 fprintf(f, "\t${S_RULE_0}\n"); 929 fprintf(f, "\t${S_RULE_1A}%s%.*s${S_RULE_1B}%s\n", 930 source_dir, (int)(tp-np), np, nl); 931 fprintf(f, "\t${S_RULE_2}%s\n", nl); 932 break; 933 } 934 continue; 935 } 936 extras = ""; 937 switch (ftp->f_type) { 938 939 case NORMAL: 940 switch (machine) { 941 942 case MACHINE_MIPSY: 943 case MACHINE_MIPS: 944 break; 945 default: 946 goto common; 947 } 948 break; 949 950 case DRIVER: 951 switch (machine) { 952 953 case MACHINE_MIPSY: 954 case MACHINE_MIPS: 955 fprintf(f, "\t@${RM} %so\n", tp); 956 fprintf(f, "\t${CC} ${CCDFLAGS}%s %s%s%sc\n\n", 957 (ftp->f_extra?ftp->f_extra:""), extras, source_dir, np); 958 continue; 959 default: 960 extras = "_D"; 961 goto common; 962 } 963 break; 964 965 case PROFILING: 966 if (!profiling) 967 continue; 968 if (COPTS == 0) { 969 fprintf(stderr, 970 "config: COPTS undefined in generic makefile"); 971 COPTS = ""; 972 } 973 switch (machine) { 974 case MACHINE_MIPSY: 975 case MACHINE_MIPS: 976 fprintf(f, "\t@${RM} %so\n", tp); 977 fprintf(f, "\t${CC} ${CCPFLAGS}%s %s../%sc\n\n", 978 (ftp->f_extra?ftp->f_extra:""), extras, np); 979 continue; 980 case MACHINE_VAX: 981 case MACHINE_ROMP: 982 case MACHINE_SQT: 983 case MACHINE_MMAX: 984 case MACHINE_SUN3: 985 case MACHINE_SUN4: 986 case MACHINE_I386: 987 case MACHINE_I860: 988 case MACHINE_HPPA: 989 case MACHINE_SPARC: 990 case MACHINE_PPC: 991 case MACHINE_ARM: 992 case MACHINE_X86_64: 993 extras = "_P"; 994 goto common; 995 default: 996 fprintf(stderr, 997 "config: don't know how to profile kernel on this cpu\n"); 998 break; 999 } 1000 1001 common: 1002 och_upper = och + 'A' - 'a'; 1003 fprintf(f, "\t${%c_RULE_0%s}\n", och_upper, extras); 1004 fprintf(f, "\t${%c_RULE_1A%s}", och_upper, extras); 1005 if (ftp->f_extra) 1006 fprintf(f, "%s", ftp->f_extra); 1007 fprintf(f, "%s%.*s${%c_RULE_1B%s}%s\n", 1008 source_dir, (int)(tp-np), np, och_upper, extras, nl); 1009 1010 /* While we are still using CTF, any build that normally does not support CTF will 1011 * a "standard" compile done as well that we can harvest CTF information from; do 1012 * that here. 1013 */ 1014 fprintf(f, "\t${%c_CTFRULE_1A%s}", och_upper, extras); 1015 if (ftp->f_extra) 1016 fprintf(f, "%s", ftp->f_extra); 1017 fprintf(f, "%s%.*s${%c_CTFRULE_1B%s}%s\n", 1018 source_dir, (int)(tp-np), np, och_upper, extras, nl); 1019 1020 fprintf(f, "\t${%c_RULE_2%s}%s\n", och_upper, extras, nl); 1021 fprintf(f, "\t${%c_CTFRULE_2%s}%s\n", och_upper, extras, nl); 1022 break; 1023 1024 default: 1025 printf("Don't know rules for %s\n", np); 1026 break; 1027 } 1028 *cp = och; 1029 } 1030} 1031 1032/* 1033 * Create the load strings 1034 */ 1035void 1036do_load(FILE *f) 1037{ 1038 register struct file_list *fl; 1039 int first = 1; 1040 1041 fl = conf_list; 1042 while (fl) { 1043 if (fl->f_type != SYSTEMSPEC) { 1044 fl = fl->f_next; 1045 continue; 1046 } 1047 fl = do_systemspec(f, fl, first); 1048 if (first) 1049 first = 0; 1050 } 1051 fprintf(f, "LOAD ="); 1052 for (fl = conf_list; fl != 0; fl = fl->f_next) 1053 if (fl->f_type == SYSTEMSPEC) 1054 fprintf(f, " %s", fl->f_needs); 1055#ifdef multimax 1056 fprintf(f, "\n\nall .ORDER: includelinks ${LOAD}\n"); 1057#else /* multimax */ 1058 fprintf(f, "\n\nall: includelinks ${LOAD}\n"); 1059#endif /* multimax */ 1060 fprintf(f, "\n"); 1061} 1062 1063struct file_list * 1064do_systemspec(FILE *f, struct file_list *fl, __unused int first) 1065{ 1066 /* 1067 * Variable for kernel name. 1068 */ 1069 fprintf(f, "KERNEL_NAME=%s\n", fl->f_needs); 1070 1071 fprintf(f, "%s .ORDER: %s.sys ${SYSDEPS}\n", 1072 fl->f_needs, fl->f_needs); 1073 fprintf(f, "\t${SYS_RULE_1}\n"); 1074 fprintf(f, "\t${SYS_RULE_2}\n"); 1075 fprintf(f, "\t${SYS_RULE_3}\n"); 1076 fprintf(f, "\t${SYS_RULE_4}\n\n"); 1077 do_swapspec(f, fl->f_fn, fl->f_needs); 1078 for (fl = fl->f_next; fl != NULL && fl->f_type == SWAPSPEC; fl = fl->f_next) 1079 continue; 1080 return (fl); 1081} 1082 1083void 1084do_swapspec(__unused FILE *f, __unused const char *name, __unused char *sysname) 1085{ 1086 1087#if DO_SWAPFILE 1088 char *gdir = eq(name, "generic")?"$(MACHINEDIR)/":""; 1089 1090 fprintf(f, "%s.sys:${P} ${PRELDDEPS} ${LDOBJS} ${LDDEPS}\n\n", sysname); 1091 fprintf(f, "%s.swap: swap%s.o\n", sysname, name); 1092 fprintf(f, "\t@rm -f $@\n"); 1093 fprintf(f, "\t@cp swap%s.o $@\n\n", name); 1094 fprintf(f, "swap%s.o: %sswap%s.c ${SWAPDEPS}\n", name, gdir, name); 1095 if (machine == MACHINE_MIPSY || machine == MACHINE_MIPS) { 1096 fprintf(f, "\t@${RM} swap%s.o\n", name); 1097 fprintf(f, "\t${CC} ${CCNFLAGS} %sswap%s.c\n\n", gdir, name); 1098 } else { 1099 fprintf(f, "\t${C_RULE_1A}%s${C_RULE_1B}\n", gdir); 1100 fprintf(f, "\t${C_RULE_2}\n"); 1101 fprintf(f, "\t${C_RULE_3}\n"); 1102 fprintf(f, "\t${C_RULE_4}\n\n"); 1103 } 1104#endif /* DO_SWAPFILE */ 1105} 1106 1107char * 1108allCaps(str) 1109 register char *str; 1110{ 1111 register char *cp = str; 1112 1113 while (*str) { 1114 if (islower(*str)) 1115 *str = toupper(*str); 1116 str++; 1117 } 1118 return (cp); 1119} 1120 1121#define OLDSALUTATION "# DO NOT DELETE THIS LINE" 1122 1123#define LINESIZE 1024 1124static char makbuf[LINESIZE]; /* one line buffer for makefile */ 1125 1126void 1127copy_dependencies(FILE *makin, FILE *makout) 1128{ 1129 register int oldlen = (sizeof OLDSALUTATION - 1); 1130 1131 while (fgets(makbuf, LINESIZE, makin) != NULL) { 1132 if (! strncmp(makbuf, OLDSALUTATION, oldlen)) 1133 break; 1134 } 1135 while (fgets(makbuf, LINESIZE, makin) != NULL) { 1136 if (oldlen != 0) 1137 { 1138 if (makbuf[0] == '\n') 1139 continue; 1140 else 1141 oldlen = 0; 1142 } 1143 fputs(makbuf, makout); 1144 } 1145} 1146