1 /* mkmakefile.c 1.26 83/04/24 */ 2 3 /* 4 * Build the makefile for the system, from 5 * the information in the files files and the 6 * additional files for the machine being compiled to. 7 */ 8 9 #include <stdio.h> 10 #include <ctype.h> 11 #include "y.tab.h" 12 #include "config.h" 13 14 #define next_word(fp, wd) \ 15 { register char *word = get_word(fp); \ 16 if (word == (char *)EOF) \ 17 return; \ 18 else \ 19 wd = word; \ 20 } 21 22 static struct file_list *fcur; 23 char *tail(); 24 25 /* 26 * Lookup a file, by make. 27 */ 28 struct file_list * 29 fl_lookup(file) 30 register char *file; 31 { 32 register struct file_list *fp; 33 34 for (fp = ftab ; fp != 0; fp = fp->f_next) { 35 if (eq(fp->f_fn, file)) 36 return (fp); 37 } 38 return (0); 39 } 40 41 /* 42 * Lookup a file, by final component name. 43 */ 44 struct file_list * 45 fltail_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(tail(fp->f_fn), tail(file))) 52 return (fp); 53 } 54 return (0); 55 } 56 57 /* 58 * Make a new file list entry 59 */ 60 struct file_list * 61 new_fent() 62 { 63 register struct file_list *fp; 64 65 fp = (struct file_list *) malloc(sizeof *fp); 66 fp->f_needs = 0; 67 fp->f_next = 0; 68 if (fcur == 0) 69 fcur = ftab = fp; 70 else 71 fcur->f_next = fp; 72 fcur = fp; 73 return (fp); 74 } 75 76 char *COPTS; 77 78 /* 79 * Build the makefile from the skeleton 80 */ 81 makefile() 82 { 83 FILE *ifp, *ofp; 84 char line[BUFSIZ]; 85 struct opt *op; 86 87 read_files(); 88 strcpy(line, "../conf/makefile."); 89 (void) strcat(line, machinename); 90 ifp = fopen(line, "r"); 91 if (ifp == 0) { 92 perror(line); 93 exit(1); 94 } 95 ofp = fopen(path("makefile"), "w"); 96 if (ofp == 0) { 97 perror(path("makefile")); 98 exit(1); 99 } 100 fprintf(ofp, "IDENT=-D%s", raise(ident)); 101 if (profiling) 102 fprintf(ofp, " -DGPROF"); 103 if (cputype == 0) { 104 printf("cpu type must be specified\n"); 105 exit(1); 106 } 107 { struct cputype *cp; 108 for (cp = cputype; cp; cp = cp->cpu_next) 109 fprintf(ofp, " -D%s", cp->cpu_name); 110 } 111 for (op = opt; op; op = op->op_next) 112 if (op->op_value) 113 fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value); 114 else 115 fprintf(ofp, " -D%s", op->op_name); 116 fprintf(ofp, "\n"); 117 if (hadtz == 0) 118 printf("timezone not specified; gmt assumed\n"); 119 #ifdef vax 120 if (maxusers == 0) { 121 printf("maxusers not specified; 24 assumed\n"); 122 maxusers = 24; 123 } else if (maxusers < 8) { 124 printf("minimum of 8 maxusers assumed\n"); 125 maxusers = 8; 126 } else if (maxusers > 128) { 127 printf("maxusers truncated to 128\n"); 128 maxusers = 128; 129 } 130 #endif 131 #ifdef sun 132 if (maxusers == 0) { 133 printf("maxusers not specified; 8 assumed\n"); 134 maxusers = 8; 135 } else if (maxusers < 2) { 136 printf("minimum of 2 maxusers assumed\n"); 137 maxusers = 2; 138 } else if (maxusers > 32) { 139 printf("maxusers truncated to 32\n"); 140 maxusers = 32; 141 } 142 #endif 143 fprintf(ofp, "PARAM=-DTIMEZONE=%d -DDST=%d -DMAXUSERS=%d\n", 144 timezone, dst, maxusers); 145 while (fgets(line, BUFSIZ, ifp) != 0) { 146 if (*line == '%') 147 goto percent; 148 if (profiling && strncmp(line, "COPTS=", 6) == 0) { 149 register char *cp; 150 151 fprintf(ofp, "GPROF.EX=/usr/src/lib/libc/csu/gmon.ex\n"); 152 cp = index(line, '\n'); 153 if (cp) 154 *cp = 0; 155 cp = line + 6; 156 while (*cp && (*cp == ' ' || *cp == '\t')) 157 cp++; 158 COPTS = malloc((unsigned)(strlen(cp) + 1)); 159 if (COPTS == 0) { 160 printf("config: out of memory\n"); 161 exit(1); 162 } 163 strcpy(COPTS, cp); 164 fprintf(ofp, "%s -pg\n", line); 165 continue; 166 } 167 fprintf(ofp, "%s", line); 168 continue; 169 percent: 170 if (eq(line, "%OBJS\n")) 171 do_objs(ofp); 172 else if (eq(line, "%CFILES\n")) 173 do_cfiles(ofp); 174 else if (eq(line, "%RULES\n")) 175 do_rules(ofp); 176 else if (eq(line, "%LOAD\n")) 177 do_load(ofp); 178 else 179 fprintf(stderr, 180 "Unknown %% construct in generic makefile: %s", 181 line); 182 } 183 (void) fclose(ifp); 184 (void) fclose(ofp); 185 } 186 187 /* 188 * Read in the information about files used in making the system. 189 * Store it in the ftab linked list. 190 */ 191 read_files() 192 { 193 FILE *fp; 194 register struct file_list *tp; 195 register struct device *dp; 196 char *wd, *this, *needs, *devorprof; 197 char fname[32]; 198 int nreqs; 199 int first = 1; 200 201 ftab = 0; 202 (void) strcpy(fname, "files"); 203 openit: 204 fp = fopen(fname, "r"); 205 if (fp == 0) { 206 perror(fname); 207 exit(1); 208 } 209 next: 210 /* filename [ standard | optional dev* ] [ device-driver ] */ 211 wd = get_word(fp); 212 if (wd == (char *)EOF) { 213 (void) fclose(fp); 214 if (first == 1) { 215 (void) sprintf(fname, "files.%s", machinename); 216 first++; 217 goto openit; 218 } 219 if (first == 2) { 220 (void) sprintf(fname, "files.%s", raise(ident)); 221 first++; 222 fp = fopen(fname, "r"); 223 if (fp != 0) 224 goto next; 225 } 226 return; 227 } 228 if (wd == 0) 229 goto next; 230 this = ns(wd); 231 next_word(fp, wd); 232 if (wd == 0) { 233 printf("%s: No type for %s.\n", 234 fname, this); 235 exit(1); 236 } 237 if (fl_lookup(this)) { 238 printf("%s: Duplicate file %s.\n", 239 fname, this); 240 exit(1); 241 } 242 tp = 0; 243 if (first == 3 && (tp = fltail_lookup(this)) != 0) 244 printf("%s: Local file %s overrides %s.\n", 245 fname, this, tp->f_fn); 246 nreqs = 0; 247 devorprof = ""; 248 needs = 0; 249 if (eq(wd, "standard")) 250 goto checkdev; 251 if (!eq(wd, "optional")) { 252 printf("%s: %s must be optional or standard\n", 253 fname, this); 254 exit(1); 255 } 256 nextopt: 257 next_word(fp, wd); 258 if (wd == 0) 259 goto doneopt; 260 devorprof = wd; 261 if (eq(wd, "device-driver") || eq(wd, "profiling-routine")) { 262 next_word(fp, wd); 263 goto save; 264 } 265 nreqs++; 266 if (needs == 0) 267 needs = ns(wd); 268 for (dp = dtab; dp != 0; dp = dp->d_next) 269 if (eq(dp->d_name, wd)) 270 goto nextopt; 271 while ((wd = get_word(fp)) != 0) 272 ; 273 if (tp == 0) 274 tp = new_fent(); 275 tp->f_fn = this; 276 tp->f_type = INVISIBLE; 277 tp->f_needs = needs; 278 goto next; 279 doneopt: 280 if (nreqs == 0) { 281 printf("%s: what is %s optional on?\n", 282 fname, this); 283 exit(1); 284 } 285 checkdev: 286 if (wd) { 287 next_word(fp, wd); 288 if (wd != 0) { 289 devorprof = wd; 290 next_word(fp, wd); 291 } 292 } 293 save: 294 if (wd != 0) { 295 printf("%s: syntax error describing %s\n", 296 fname, this); 297 exit(1); 298 } 299 if (eq(devorprof, "profiling-routine") && profiling == 0) 300 goto next; 301 if (tp == 0) 302 tp = new_fent(); 303 tp->f_fn = this; 304 if (eq(devorprof, "device-driver")) 305 tp->f_type = DEVICE; 306 else if (eq(devorprof, "profiling-routine")) 307 tp->f_type = PROFILING; 308 else 309 tp->f_type = NORMAL; 310 tp->f_needs = needs; 311 goto next; 312 } 313 314 do_objs(fp) 315 FILE *fp; 316 { 317 register struct file_list *tp, *fl; 318 register int lpos, len; 319 register char *cp, och, *sp; 320 char swapname[32]; 321 322 fprintf(fp, "OBJS="); 323 lpos = 6; 324 for (tp = ftab; tp != 0; tp = tp->f_next) { 325 if (tp->f_type == INVISIBLE) 326 continue; 327 sp = tail(tp->f_fn); 328 for (fl = conf_list; fl != 0; fl = fl->f_next) { 329 (void) sprintf(swapname, "swap%s.c", fl->f_fn); 330 if (eq(sp, swapname)) 331 goto cont; 332 } 333 cp = sp + (len = strlen(sp)) - 1; 334 och = *cp; 335 *cp = 'o'; 336 if (len + lpos > 72) { 337 lpos = 8; 338 fprintf(fp, "\\\n\t"); 339 } 340 fprintf(fp, "%s ", sp); 341 lpos += len + 1; 342 *cp = och; 343 cont:; 344 } 345 if (lpos != 8) 346 putc('\n', fp); 347 } 348 349 do_cfiles(fp) 350 FILE *fp; 351 { 352 register struct file_list *tp; 353 register int lpos, len; 354 355 fprintf(fp, "CFILES="); 356 lpos = 8; 357 for (tp = ftab; tp != 0; tp = tp->f_next) { 358 if (tp->f_type == INVISIBLE) 359 continue; 360 if (tp->f_fn[strlen(tp->f_fn)-1] != 'c') 361 continue; 362 if ((len = 3 + strlen(tp->f_fn)) + lpos > 72) { 363 lpos = 8; 364 fprintf(fp, "\\\n\t"); 365 } 366 fprintf(fp, "../%s ", tp->f_fn); 367 lpos += len + 1; 368 } 369 if (lpos != 8) 370 putc('\n', fp); 371 } 372 373 char * 374 tail(fn) 375 char *fn; 376 { 377 register char *cp; 378 379 cp = rindex(fn, '/'); 380 if (cp == 0) 381 return (fn); 382 return (cp+1); 383 } 384 385 /* 386 * Create the makerules for each file 387 * which is part of the system. 388 * Devices are processed with the special c2 option -i 389 * which avoids any problem areas with i/o addressing 390 * (e.g. for the VAX); assembler files are processed by as. 391 */ 392 do_rules(f) 393 FILE *f; 394 { 395 register char *cp, *np, och, *tp; 396 register struct file_list *ftp; 397 398 for (ftp = ftab; ftp != 0; ftp = ftp->f_next) { 399 if (ftp->f_type == INVISIBLE) 400 continue; 401 cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1; 402 och = *cp; 403 *cp = '\0'; 404 fprintf(f, "%so: ../%s%c\n", tail(np), np, och); 405 tp = tail(np); 406 if (och == 's') { 407 fprintf(f, "\t${AS} -o %so ../%ss\n\n", tp, np); 408 continue; 409 } 410 switch (ftp->f_type) { 411 412 case NORMAL: 413 switch (machine) { 414 415 case MACHINE_VAX: 416 fprintf(f, "\t${CC} -I. -c -S ${COPTS} ../%sc\n", np); 417 fprintf(f, "\t${C2} %ss | sed -f ../%s/asm.sed |", 418 tp, machinename); 419 fprintf(f, " ${AS} -o %so\n", tp); 420 fprintf(f, "\trm -f %ss\n\n", tp); 421 break; 422 423 case MACHINE_SUN: 424 fprintf(f, "\t${CC} -I. -c -O ${COPTS} ../%sc\n\n", np); 425 break; 426 } 427 break; 428 429 case DEVICE: 430 switch (machine) { 431 432 case MACHINE_VAX: 433 fprintf(f, "\t${CC} -I. -c -S ${COPTS} ../%sc\n", np); 434 fprintf(f,"\t${C2} -i %ss | sed -f ../%s/asm.sed |", 435 tp, machinename); 436 fprintf(f, " ${AS} -o %so\n", tp); 437 fprintf(f, "\trm -f %ss\n\n", tp); 438 break; 439 440 case MACHINE_SUN: 441 fprintf(f, "\t${CC} -I. -c -O ${COPTS} ../%sc\n\n", np); 442 } 443 break; 444 445 case PROFILING: 446 if (!profiling) 447 continue; 448 if (COPTS == 0) { 449 fprintf(stderr, 450 "config: COPTS undefined in generic makefile"); 451 COPTS = ""; 452 } 453 switch (machine) { 454 455 case MACHINE_VAX: 456 fprintf(f, "\t${CC} -I. -c -S %s ../%sc\n", COPTS, np); 457 fprintf(f, "\tex - %ss < ${GPROF.EX}\n", tp); 458 fprintf(f, 459 "\tsed -f ../vax/asm.sed %ss | ${AS} -o %so\n", 460 tp, tp); 461 fprintf(f, "\trm -f %ss\n\n", tp); 462 break; 463 464 case MACHINE_SUN: 465 fprintf(stderr, 466 "config: don't know how to profile kernel on sun\n"); 467 break; 468 } 469 break; 470 471 default: 472 printf("Don't know rules for %s", np); 473 break; 474 } 475 *cp = och; 476 } 477 } 478 479 /* 480 * Create the load strings 481 */ 482 do_load(f) 483 register FILE *f; 484 { 485 register struct file_list *fl; 486 int first = 1; 487 char swapname[32]; 488 489 for (fl = conf_list; fl != 0; fl = fl->f_next) { 490 fprintf(f, "%s: makefile locore.o ${OBJS} param.o", 491 fl->f_needs); 492 fprintf(f, " ioconf.o swap%s.o\n", fl->f_fn); 493 fprintf(f, "\t@echo loading %s\n\t@rm -f %s\n", 494 fl->f_needs, fl->f_needs); 495 if (first) { 496 first = 0; 497 fprintf(f, "\t@sh ../conf/newvers.sh\n"); 498 fprintf(f, "\t@${CC} $(CFLAGS) -c vers.c\n"); 499 } 500 switch (machine) { 501 502 case MACHINE_VAX: 503 fprintf(f, "\t@${LD} -n -o %s -e start -x -T 80000000 ", 504 fl->f_needs); 505 fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o "); 506 fprintf(f, "swap%s.o\n", fl->f_fn); 507 break; 508 509 case MACHINE_SUN: 510 fprintf(f, "\t@${LD} -o %s -e start -x -T 4000 ", 511 fl->f_needs); 512 fprintf(f, "locore.o ${OBJS} vers.o ioconf.o param.o "); 513 fprintf(f, "swap%s.o\n", fl->f_fn); 514 break; 515 } 516 fprintf(f, "\t@echo rearranging symbols\n"); 517 fprintf(f, "\t@-symorder ../%s/symbols.sort %s\n", 518 machinename, fl->f_needs); 519 fprintf(f, "\t@size %s\n", fl->f_needs); 520 fprintf(f, "\t@chmod 755 %s\n\n", fl->f_needs); 521 } 522 for (fl = conf_list; fl != 0; fl = fl->f_next) { 523 (void) sprintf(swapname, "swap%s.c", fl->f_fn); 524 if (fltail_lookup(swapname) != 0) 525 continue; 526 fprintf(f, "swap%s.o: ../%s/swap%s.c\n", 527 fl->f_fn, machinename, fl->f_fn); 528 switch (machine) { 529 530 case MACHINE_VAX: 531 fprintf(f, "\t${CC} -I. -c -S ${COPTS}"); 532 fprintf(f, " ../%s/swap%s.c\n", machinename, fl->f_fn); 533 fprintf(f, "\t${C2} swap%s.s | sed -f ../%s/asm.sed", 534 fl->f_fn, machinename); 535 fprintf(f, " | ${AS} -o swap%s.o\n", 536 fl->f_fn); 537 fprintf(f, "\trm -f swap%s.s\n\n", fl->f_fn); 538 break; 539 540 case MACHINE_SUN: 541 fprintf(f, "\t${CC} -I. -c -O ${COPTS} "); 542 fprintf(f, "../%s/swap%s.c\n\n", machinename, fl->f_fn); 543 break; 544 } 545 } 546 fprintf(f, "all:"); 547 for (fl = conf_list; fl != 0; fl = fl->f_next) 548 fprintf(f, " %s", fl->f_needs); 549 fprintf(f, "\n"); 550 } 551 552 char * 553 raise(str) 554 register char *str; 555 { 556 register char *cp = str; 557 558 while (*str) { 559 if (islower(*str)) 560 *str = toupper(*str); 561 str++; 562 } 563 return (cp); 564 } 565