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.38 (Berkeley) 06/19/92"; 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 23 #define next_word(fp, wd) \ 24 { register char *word = get_word(fp); \ 25 if (word == (char *)EOF) \ 26 return; \ 27 else \ 28 wd = word; \ 29 } 30 #define next_quoted_word(fp, wd) \ 31 { register char *word = get_quoted_word(fp); \ 32 if (word == (char *)EOF) \ 33 return; \ 34 else \ 35 wd = word; \ 36 } 37 38 static struct file_list *fcur; 39 char *tail(); 40 41 /* 42 * Lookup a file, by name. 43 */ 44 struct file_list * 45 fl_lookup(file) 46 register char *file; 47 { 48 register struct file_list *fp; 49 50 for (fp = ftab ; fp != 0; fp = fp->f_next) { 51 if (eq(fp->f_fn, file)) 52 return (fp); 53 } 54 return (0); 55 } 56 57 /* 58 * Lookup a file, by final component name. 59 */ 60 struct file_list * 61 fltail_lookup(file) 62 register char *file; 63 { 64 register struct file_list *fp; 65 66 for (fp = ftab ; fp != 0; fp = fp->f_next) { 67 if (eq(tail(fp->f_fn), tail(file))) 68 return (fp); 69 } 70 return (0); 71 } 72 73 /* 74 * Make a new file list entry 75 */ 76 struct file_list * 77 new_fent() 78 { 79 register struct file_list *fp; 80 81 fp = (struct file_list *) malloc(sizeof *fp); 82 bzero(fp, sizeof *fp); 83 if (fcur == 0) 84 fcur = ftab = fp; 85 else 86 fcur->f_next = fp; 87 fcur = fp; 88 return (fp); 89 } 90 91 static struct users { 92 int u_default; 93 int u_min; 94 int u_max; 95 } users[] = { 96 { 24, 8, 1024 }, /* MACHINE_VAX */ 97 { 4, 2, 128 }, /* MACHINE_TAHOE */ 98 { 8, 2, 64 }, /* MACHINE_HP300 */ 99 { 8, 2, 64 }, /* MACHINE_I386 */ 100 { 8, 2, 64 }, /* MACHINE_MIPS */ 101 { 8, 2, 64 }, /* MACHINE_PMAX */ 102 { 8, 2, 64 }, /* MACHINE_LUNA68K */ 103 }; 104 #define NUSERS (sizeof (users) / sizeof (users[0])) 105 106 /* 107 * Build the makefile from the skeleton 108 */ 109 makefile() 110 { 111 FILE *ifp, *ofp; 112 char line[BUFSIZ]; 113 struct opt *op; 114 struct users *up; 115 116 read_files(); 117 strcpy(line, "Makefile."); 118 (void) strcat(line, machinename); 119 ifp = fopen(line, "r"); 120 if (ifp == 0) { 121 perror(line); 122 exit(1); 123 } 124 ofp = fopen(path("Makefile"), "w"); 125 if (ofp == 0) { 126 perror(path("Makefile")); 127 exit(1); 128 } 129 fprintf(ofp, "IDENT=-D%s", raise(ident)); 130 if (profiling) 131 fprintf(ofp, " -DGPROF"); 132 if (cputype == 0) { 133 printf("cpu type must be specified\n"); 134 exit(1); 135 } 136 { struct cputype *cp; 137 for (cp = cputype; cp; cp = cp->cpu_next) 138 fprintf(ofp, " -D%s", cp->cpu_name); 139 } 140 for (op = opt; op; op = op->op_next) 141 if (op->op_value) 142 fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value); 143 else 144 fprintf(ofp, " -D%s", op->op_name); 145 fprintf(ofp, "\n"); 146 if (hadtz == 0) 147 printf("timezone not specified; gmt assumed\n"); 148 if ((unsigned)machine > NUSERS) { 149 printf("maxusers config info isn't present, using vax\n"); 150 up = &users[MACHINE_VAX-1]; 151 } else 152 up = &users[machine-1]; 153 if (maxusers == 0) { 154 printf("maxusers not specified; %d assumed\n", up->u_default); 155 maxusers = up->u_default; 156 } else if (maxusers < up->u_min) { 157 printf("minimum of %d maxusers assumed\n", up->u_min); 158 maxusers = up->u_min; 159 } else if (maxusers > up->u_max) 160 printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers); 161 fprintf(ofp, "PARAM=-DTIMEZONE=%d -DDST=%d -DMAXUSERS=%d", 162 zone, dst, maxusers); 163 if (hz > 0) 164 fprintf(ofp, " -DHZ=%d", hz); 165 fprintf(ofp, "\n"); 166 for (op = mkopt; op; op = op->op_next) 167 fprintf(ofp, "%s=%s\n", op->op_name, op->op_value); 168 if (debugging) 169 fprintf(ofp, "DEBUG=-g\n"); 170 if (profiling) 171 fprintf(ofp, "PROF=-pg\n"); 172 while (fgets(line, BUFSIZ, ifp) != 0) { 173 if (*line != '%') { 174 fprintf(ofp, "%s", line); 175 continue; 176 } 177 if (eq(line, "%OBJS\n")) 178 do_objs(ofp); 179 else if (eq(line, "%CFILES\n")) 180 do_cfiles(ofp); 181 else if (eq(line, "%RULES\n")) 182 do_rules(ofp); 183 else if (eq(line, "%LOAD\n")) 184 do_load(ofp); 185 else 186 fprintf(stderr, 187 "Unknown %% construct in generic makefile: %s", 188 line); 189 } 190 (void) fclose(ifp); 191 (void) fclose(ofp); 192 } 193 194 /* 195 * Read in the information about files used in making the system. 196 * Store it in the ftab linked list. 197 */ 198 read_files() 199 { 200 FILE *fp; 201 register struct file_list *tp, *pf; 202 register struct device *dp; 203 struct device *save_dp; 204 register struct opt *op; 205 char *wd, *this, *needs, *special; 206 char fname[32]; 207 int nreqs, first = 1, configdep, isdup, std, filetype; 208 209 ftab = 0; 210 (void) strcpy(fname, "../../conf/files"); 211 openit: 212 fp = fopen(fname, "r"); 213 if (fp == 0) { 214 perror(fname); 215 exit(1); 216 } 217 next: 218 /* 219 * filename [ standard | optional ] [ config-dependent ] 220 * [ dev* | profiling-routine ] [ device-driver] 221 * [ compile-with "compile rule" ] 222 */ 223 wd = get_word(fp); 224 if (wd == (char *)EOF) { 225 (void) fclose(fp); 226 if (first == 1) { 227 (void) sprintf(fname, "files.%s", machinename); 228 first++; 229 goto openit; 230 } 231 if (first == 2) { 232 (void) sprintf(fname, "files.%s", raise(ident)); 233 first++; 234 fp = fopen(fname, "r"); 235 if (fp != 0) 236 goto next; 237 } 238 return; 239 } 240 if (wd == 0) 241 goto next; 242 this = ns(wd); 243 next_word(fp, wd); 244 if (wd == 0) { 245 printf("%s: No type for %s.\n", 246 fname, this); 247 exit(1); 248 } 249 if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags)) 250 isdup = 1; 251 else 252 isdup = 0; 253 tp = 0; 254 if (first == 3 && (tp = fltail_lookup(this)) != 0) 255 printf("%s: Local file %s overrides %s.\n", 256 fname, this, tp->f_fn); 257 nreqs = 0; 258 special = 0; 259 configdep = 0; 260 needs = 0; 261 std = 0; 262 filetype = NORMAL; 263 if (eq(wd, "standard")) 264 std = 1; 265 else if (!eq(wd, "optional")) { 266 printf("%s: %s must be optional or standard\n", fname, this); 267 exit(1); 268 } 269 nextparam: 270 next_word(fp, wd); 271 if (wd == 0) 272 goto doneparam; 273 if (eq(wd, "config-dependent")) { 274 configdep++; 275 goto nextparam; 276 } 277 if (eq(wd, "compile-with")) { 278 next_quoted_word(fp, wd); 279 if (wd == 0) { 280 printf("%s: %s missing compile command string.\n", 281 fname); 282 exit(1); 283 } 284 special = ns(wd); 285 goto nextparam; 286 } 287 nreqs++; 288 if (eq(wd, "device-driver")) { 289 filetype = DRIVER; 290 goto nextparam; 291 } 292 if (eq(wd, "profiling-routine")) { 293 filetype = PROFILING; 294 goto nextparam; 295 } 296 if (needs == 0 && nreqs == 1) 297 needs = ns(wd); 298 if (isdup) 299 goto invis; 300 for (dp = dtab; dp != 0; save_dp = dp, dp = dp->d_next) 301 if (eq(dp->d_name, wd)) { 302 if (std && dp->d_type == PSEUDO_DEVICE && 303 dp->d_slave <= 0) 304 dp->d_slave = 1; 305 goto nextparam; 306 } 307 if (std) { 308 dp = (struct device *) malloc(sizeof *dp); 309 init_dev(dp); 310 dp->d_name = ns(wd); 311 dp->d_type = PSEUDO_DEVICE; 312 dp->d_slave = 1; 313 save_dp->d_next = dp; 314 goto nextparam; 315 } 316 for (op = opt; op != 0; op = op->op_next) 317 if (op->op_value == 0 && opteq(op->op_name, wd)) { 318 if (nreqs == 1) { 319 free(needs); 320 needs = 0; 321 } 322 goto nextparam; 323 } 324 invis: 325 while ((wd = get_word(fp)) != 0) 326 ; 327 if (tp == 0) 328 tp = new_fent(); 329 tp->f_fn = this; 330 tp->f_type = INVISIBLE; 331 tp->f_needs = needs; 332 tp->f_flags = isdup; 333 tp->f_special = special; 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 (filetype == PROFILING && profiling == 0) 350 goto next; 351 if (tp == 0) 352 tp = new_fent(); 353 tp->f_fn = this; 354 tp->f_type = filetype; 355 tp->f_flags = 0; 356 if (configdep) 357 tp->f_flags |= CONFIGDEP; 358 tp->f_needs = needs; 359 tp->f_special = special; 360 if (pf && pf->f_type == INVISIBLE) 361 pf->f_flags = 1; /* mark as duplicate */ 362 goto next; 363 } 364 365 opteq(cp, dp) 366 char *cp, *dp; 367 { 368 char c, d; 369 370 for (; ; cp++, dp++) { 371 if (*cp != *dp) { 372 c = isupper(*cp) ? tolower(*cp) : *cp; 373 d = isupper(*dp) ? tolower(*dp) : *dp; 374 if (c != d) 375 return (0); 376 } 377 if (*cp == 0) 378 return (1); 379 } 380 } 381 382 do_objs(fp) 383 FILE *fp; 384 { 385 register struct file_list *tp, *fl; 386 register int lpos, len; 387 register char *cp, och, *sp; 388 char swapname[32]; 389 390 fprintf(fp, "OBJS="); 391 lpos = 6; 392 for (tp = ftab; tp != 0; tp = tp->f_next) { 393 if (tp->f_type == INVISIBLE) 394 continue; 395 sp = tail(tp->f_fn); 396 for (fl = conf_list; fl; fl = fl->f_next) { 397 if (fl->f_type != SWAPSPEC) 398 continue; 399 (void) sprintf(swapname, "swap%s.c", fl->f_fn); 400 if (eq(sp, swapname)) 401 goto cont; 402 } 403 cp = sp + (len = strlen(sp)) - 1; 404 och = *cp; 405 *cp = 'o'; 406 if (len + lpos > 72) { 407 lpos = 8; 408 fprintf(fp, "\\\n\t"); 409 } 410 fprintf(fp, "%s ", sp); 411 lpos += len + 1; 412 *cp = och; 413 cont: 414 ; 415 } 416 if (lpos != 8) 417 putc('\n', fp); 418 } 419 420 do_cfiles(fp) 421 FILE *fp; 422 { 423 register struct file_list *tp, *fl; 424 register int lpos, len; 425 char swapname[32]; 426 427 fputs("CFILES=", fp); 428 lpos = 8; 429 for (tp = ftab; tp; tp = tp->f_next) 430 if (tp->f_type != INVISIBLE) { 431 len = strlen(tp->f_fn); 432 if (tp->f_fn[len - 1] != 'c') 433 continue; 434 if ((len = 3 + len) + lpos > 72) { 435 lpos = 8; 436 fputs("\\\n\t", fp); 437 } 438 fprintf(fp, "$S/%s ", tp->f_fn); 439 lpos += len + 1; 440 } 441 for (fl = conf_list; fl; fl = fl->f_next) 442 if (fl->f_type == SYSTEMSPEC) { 443 (void) sprintf(swapname, "swap%s.c", fl->f_fn); 444 if ((len = 3 + strlen(swapname)) + lpos > 72) { 445 lpos = 8; 446 fputs("\\\n\t", fp); 447 } 448 if (eq(fl->f_fn, "generic")) 449 fprintf(fp, "$S/%s/%s/%s ", 450 machinename, machinename, swapname); 451 else 452 fprintf(fp, "%s ", swapname); 453 lpos += len + 1; 454 } 455 if (lpos != 8) 456 putc('\n', fp); 457 } 458 459 char * 460 tail(fn) 461 char *fn; 462 { 463 register char *cp; 464 465 cp = rindex(fn, '/'); 466 if (cp == 0) 467 return (fn); 468 return (cp+1); 469 } 470 471 /* 472 * Create the makerules for each file 473 * which is part of the system. 474 * Devices are processed with the special c2 option -i 475 * which avoids any problem areas with i/o addressing 476 * (e.g. for the VAX); assembler files are processed by as. 477 */ 478 do_rules(f) 479 FILE *f; 480 { 481 register char *cp, *np, och, *tp; 482 register struct file_list *ftp; 483 char *special; 484 485 for (ftp = ftab; ftp != 0; ftp = ftp->f_next) { 486 if (ftp->f_type == INVISIBLE) 487 continue; 488 cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1; 489 och = *cp; 490 *cp = '\0'; 491 if (och == 'o') { 492 fprintf(f, "%so:\n\t-cp $S/%so .\n\n", tail(np), np); 493 continue; 494 } 495 fprintf(f, "%so: $S/%s%c\n", tail(np), np, och); 496 tp = tail(np); 497 special = ftp->f_special; 498 if (special == 0) { 499 char *ftype; 500 static char cmd[128]; 501 502 switch (ftp->f_type) { 503 504 case NORMAL: 505 ftype = "NORMAL"; 506 break; 507 508 case DRIVER: 509 ftype = "DRIVER"; 510 break; 511 512 case PROFILING: 513 if (!profiling) 514 continue; 515 ftype = "PROFILE"; 516 break; 517 518 default: 519 printf("config: don't know rules for %s\n", np); 520 break; 521 } 522 (void)sprintf(cmd, "${%s_%c%s}", ftype, toupper(och), 523 ftp->f_flags & CONFIGDEP? "_C" : ""); 524 special = cmd; 525 } 526 *cp = och; 527 fprintf(f, "\t%s\n\n", special); 528 } 529 } 530 531 /* 532 * Create the load strings 533 */ 534 do_load(f) 535 register FILE *f; 536 { 537 register struct file_list *fl; 538 register int first; 539 struct file_list *do_systemspec(); 540 541 for (first = 1, fl = conf_list; fl; first = 0) 542 fl = fl->f_type == SYSTEMSPEC ? 543 do_systemspec(f, fl, first) : fl->f_next; 544 fputs("all:", f); 545 for (fl = conf_list; fl; fl = fl->f_next) 546 if (fl->f_type == SYSTEMSPEC) 547 fprintf(f, " %s", fl->f_needs); 548 putc('\n', f); 549 } 550 551 struct file_list * 552 do_systemspec(f, fl, first) 553 FILE *f; 554 register struct file_list *fl; 555 int first; 556 { 557 558 fprintf(f, "%s: ${SYSTEM_DEP} swap%s.o", fl->f_needs, fl->f_fn); 559 if (first) 560 fprintf(f, " newvers"); 561 fprintf(f, "\n\t${SYSTEM_LD_HEAD}\n"); 562 fprintf(f, "\t${SYSTEM_LD} swap%s.o\n", fl->f_fn); 563 fprintf(f, "\t${SYSTEM_LD_TAIL}\n\n"); 564 do_swapspec(f, fl->f_fn); 565 for (fl = fl->f_next; fl; fl = fl->f_next) 566 if (fl->f_type != SWAPSPEC) 567 break; 568 return (fl); 569 } 570 571 do_swapspec(f, name) 572 FILE *f; 573 register char *name; 574 { 575 576 if (!eq(name, "generic")) 577 fprintf(f, "swap%s.o: swap%s.c\n", name, name); 578 else 579 fprintf(f, "swapgeneric.o: $S/%s/%s/swapgeneric.c\n", 580 machinename, machinename); 581 fprintf(f, "\t${NORMAL_C}\n\n"); 582 } 583 584 char * 585 raise(str) 586 register char *str; 587 { 588 register char *cp = str; 589 590 while (*str) { 591 if (islower(*str)) 592 *str = toupper(*str); 593 str++; 594 } 595 return (cp); 596 } 597