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