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