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