]> git.saurik.com Git - apple/xnu.git/blob - SETUP/config/mkmakefile.c
xnu-2422.115.4.tar.gz
[apple/xnu.git] / SETUP / config / mkmakefile.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Mach Operating System
26 * Copyright (c) 1990 Carnegie-Mellon University
27 * Copyright (c) 1989 Carnegie-Mellon University
28 * Copyright (c) 1988 Carnegie-Mellon University
29 * Copyright (c) 1987 Carnegie-Mellon University
30 * All rights reserved. The CMU software License Agreement specifies
31 * the terms and conditions for use and redistribution.
32 */
33
34 /*
35 * Copyright (c) 1980 Regents of the University of California.
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms are permitted
39 * provided that the above copyright notice and this paragraph are
40 * duplicated in all such forms and that any documentation,
41 * advertising materials, and other materials related to such
42 * distribution and use acknowledge that the software was developed
43 * by the University of California, Berkeley. The name of the
44 * University may not be used to endorse or promote products derived
45 * from this software without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
48 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
49 */
50
51 #ifndef lint
52 static char sccsid[] __attribute__((used)) = "@(#)mkmakefile.c 5.21 (Berkeley) 6/18/88";
53 #endif /* not lint */
54
55 /*
56 * Build the makefile for the system, from
57 * the information in the files files and the
58 * additional files for the machine being compiled to.
59 */
60
61 #include <stdio.h>
62 #include <unistd.h> /* for unlink */
63 #include <ctype.h>
64 #include "parser.h"
65 #include "config.h"
66
67 void read_files(void);
68 void do_objs(FILE *fp, const char *msg, int ext);
69 void do_ordered(FILE *fp);
70 void do_files(FILE *fp, const char *msg, char ext);
71 void do_machdep(FILE *ofp);
72 void do_build(const char *name, void (*format)(FILE *));
73 void do_rules(FILE *f);
74 void do_load(FILE *f);
75 struct file_list *do_systemspec(FILE *f, struct file_list *fl, int first);
76 void do_swapspec(FILE *f, const char *name, char *sysname);
77 void copy_dependencies(FILE *makin, FILE *makout);
78
79 void build_cputypes(FILE *fp);
80 void build_confdep(FILE *fp);
81
82 struct file_list *fl_lookup(char *file);
83 struct file_list *fltail_lookup(char *file);
84 struct file_list *new_fent(void);
85
86 void put_source_file_name(FILE *fp, struct file_list *tp);
87
88
89 #define DO_SWAPFILE 0
90
91 #define next_word(fp, wd) \
92 { register const char *word = get_word(fp); \
93 if (word == (char *)EOF) \
94 return; \
95 else \
96 wd = word; \
97 }
98
99 static struct file_list *fcur;
100 const char *tail(const char *fn);
101 char *allCaps(char *str);
102
103 /*
104 * Lookup a file, by name.
105 */
106 struct file_list *
107 fl_lookup(char *file)
108 {
109 register struct file_list *fp;
110
111 for (fp = ftab ; fp != 0; fp = fp->f_next) {
112 if (eq(fp->f_fn, file))
113 return (fp);
114 }
115 return (0);
116 }
117
118 /*
119 * Lookup a file, by final component name.
120 */
121 struct file_list *
122 fltail_lookup(char *file)
123 {
124 register struct file_list *fp;
125
126 for (fp = ftab ; fp != 0; fp = fp->f_next) {
127 if (eq(tail(fp->f_fn), tail(file)))
128 return (fp);
129 }
130 return (0);
131 }
132
133 /*
134 * Make a new file list entry
135 */
136 struct file_list *
137 new_fent(void)
138 {
139 register struct file_list *fp;
140
141 fp = (struct file_list *) malloc(sizeof *fp);
142 fp->f_needs = 0;
143 fp->f_next = 0;
144 fp->f_flags = 0;
145 fp->f_type = 0;
146 fp->f_extra = (char *) 0;
147 if (fcur == 0)
148 fcur = ftab = fp;
149 else
150 fcur->f_next = fp;
151 fcur = fp;
152 return (fp);
153 }
154
155 char *COPTS;
156 static struct users {
157 int u_default;
158 int u_min;
159 int u_max;
160 } users[] = {
161 { 24, 2, 1024 }, /* MACHINE_VAX */
162 { 8, 2, 32 }, /* MACHINE_SUN */
163 { 16, 4, 32 }, /* MACHINE_ROMP */
164 { 8, 2, 32 }, /* MACHINE_SUN2 */
165 { 8, 2, 32 }, /* MACHINE_SUN3 */
166 { 24, 8, 1024}, /* MACHINE_MMAX */
167 { 32, 8, 1024}, /* MACHINE_SQT */
168 { 8, 2, 32 }, /* MACHINE_SUN4 */
169 { 2, 2, 1024 }, /* MACHINE_I386 */
170 { 32, 8, 1024 }, /* MACHINE_IX */
171 { 32, 8, 1024 }, /* MACHINE_MIPSY */
172 { 32, 8, 1024 }, /* MACHINE_MIPS*/
173 { 32, 8, 1024 }, /* MACHINE_I860*/
174 { 8, 2, 32 }, /* MACHINE_M68K */
175 { 8, 2, 32 }, /* MACHINE_M88K */
176 { 8, 2, 32 }, /* MACHINE_M98K */
177 { 8, 2, 32 }, /* MACHINE_HPPA */
178 { 8, 2, 32 }, /* MACHINE_SPARC */
179 { 8, 2, 32 }, /* MACHINE_PPC */
180 { 8, 2, 32 }, /* MACHINE_ARM */
181 { 8, 2, 32 }, /* MACHINE_X86_64 */
182 };
183 #define NUSERS (sizeof (users) / sizeof (users[0]))
184
185 const char *
186 get_VPATH(void)
187 {
188 static char *vpath = NULL;
189
190 if ((vpath == NULL) &&
191 ((vpath = getenv("VPATH")) != NULL) &&
192 (*vpath != ':')) {
193 register char *buf = malloc((unsigned)(strlen(vpath) + 2));
194
195 vpath = strcat(strcpy(buf, ":"), vpath);
196 }
197
198 return vpath ? vpath : "";
199 }
200
201
202 /*
203 * Build the makefile from the skeleton
204 */
205 void
206 makefile(void)
207 {
208 FILE *ifp, *ofp;
209 FILE *dfp;
210 char pname[BUFSIZ];
211 char line[BUFSIZ];
212 struct opt *op;
213 struct users *up;
214
215 read_files();
216 (void) sprintf(line, "%s/Makefile.template", config_directory);
217 ifp = fopenp(VPATH, line, pname, "r");
218 if (ifp == 0) {
219 perror(line);
220 exit(1);
221 }
222 dfp = fopen(path("Makefile"), "r");
223 rename(path("Makefile"), path("Makefile.old"));
224 unlink(path("Makefile.old"));
225 unlink(path("M.d"));
226 if ((ofp = fopen(path("M.d"), "w")) == NULL) {
227 perror(path("M.d"));
228 /* We'll let this error go */
229 }
230 else
231 fclose(ofp);
232 ofp = fopen(path("Makefile"), "w");
233 if (ofp == 0) {
234 perror(path("Makefile"));
235 exit(1);
236 }
237 fprintf(ofp, "SOURCE_DIR=%s\n", source_directory);
238
239 if (machine == MACHINE_SUN || machine == MACHINE_SUN2
240 || machine == MACHINE_SUN3 || machine == MACHINE_SUN4)
241 fprintf(ofp, "export IDENT=-D%s -D%s", machinename, allCaps(ident));
242 else
243 fprintf(ofp, "export IDENT=-D%s", allCaps(ident));
244 if (profiling)
245 fprintf(ofp, " -DGPROF");
246 if (cputype == 0) {
247 printf("cpu type must be specified\n");
248 exit(1);
249 }
250 do_build("cputypes.h", build_cputypes);
251 do_build("platforms.h", build_cputypes);
252
253 for (op = opt; op; op = op->op_next)
254 if (op->op_value)
255 fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value);
256 else
257 fprintf(ofp, " -D%s", op->op_name);
258 fprintf(ofp, "\n");
259 if ((unsigned)machine > NUSERS) {
260 printf("maxusers config info isn't present, using vax\n");
261 up = &users[MACHINE_VAX-1];
262 } else
263 up = &users[machine-1];
264 if (maxusers < up->u_min) {
265 maxusers = up->u_min;
266 } else if (maxusers > up->u_max)
267 printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers);
268 if (maxusers) {
269 do_build("confdep.h", build_confdep);
270 }
271 for (op = mkopt; op; op = op->op_next)
272 if (op->op_value)
273 fprintf(ofp, "%s=%s\n", op->op_name, op->op_value);
274 else
275 fprintf(ofp, "%s\n", op->op_name);
276
277 while (fgets(line, BUFSIZ, ifp) != 0) {
278 if (*line == '%')
279 goto percent;
280 if (profiling && strncmp(line, "COPTS=", 6) == 0) {
281 register char *cp;
282 if (machine != MACHINE_MMAX)
283 fprintf(ofp,
284 "GPROF.EX=$(SOURCE_DIR)/machdep/%s/gmon.ex\n", machinename);
285 cp = index(line, '\n');
286 if (cp)
287 *cp = 0;
288 cp = line + 6;
289 while (*cp && (*cp == ' ' || *cp == '\t'))
290 cp++;
291 COPTS = malloc((unsigned)(strlen(cp) + 1));
292 if (COPTS == 0) {
293 printf("config: out of memory\n");
294 exit(1);
295 }
296 strcpy(COPTS, cp);
297 if (machine == MACHINE_MIPSY || machine == MACHINE_MIPS) {
298 fprintf(ofp, "%s ${CCPROFOPT}\n", line);
299 fprintf(ofp, "PCOPTS=%s\n", cp);
300 } else if (machine == MACHINE_MMAX)
301 fprintf(ofp, "%s -p\n",line);
302 else
303 fprintf(ofp, "%s -pg\n", line);
304 continue;
305 }
306 fprintf(ofp, "%s", line);
307 continue;
308 percent:
309 if (eq(line, "%OBJS\n")) {
310 do_objs(ofp, "OBJS=", -1);
311 } else if (eq(line, "%CFILES\n")) {
312 do_files(ofp, "CFILES=", 'c');
313 do_objs(ofp, "COBJS=", 'c');
314 } else if (eq(line, "%SFILES\n")) {
315 do_files(ofp, "SFILES=", 's');
316 do_objs(ofp, "SOBJS=", 's');
317 } else if (eq(line, "%MACHDEP\n")) {
318 /*
319 * Move do_machdep() after the mkopt stuff.
320 */
321 for (op = mkopt; op; op = op->op_next)
322 fprintf(ofp, "%s=%s\n", op->op_name, op->op_value);
323 do_machdep(ofp);
324 } else if (eq(line, "%RULES\n"))
325 do_rules(ofp);
326 else if (eq(line, "%LOAD\n"))
327 do_load(ofp);
328 else
329 fprintf(stderr,
330 "Unknown %% construct in generic makefile: %s",
331 line);
332 }
333 if (dfp != NULL)
334 {
335 copy_dependencies(dfp, ofp);
336 (void) fclose(dfp);
337 }
338 (void) fclose(ifp);
339 (void) fclose(ofp);
340 }
341
342 /*
343 * Read in the information about files used in making the system.
344 * Store it in the ftab linked list.
345 */
346 void
347 read_files(void)
348 {
349 FILE *fp;
350 register struct file_list *tp, *pf;
351 register struct device *dp;
352 register struct opt *op;
353 const char *wd;
354 char *this, *needs;
355 const char *devorprof;
356 int options;
357 int not_option;
358 int ordered;
359 int sedit; /* SQT */
360 char pname[BUFSIZ];
361 char fname[1024];
362 char *rest = (char *) 0;
363 struct cputype *cp;
364 int nreqs, first = 1, isdup;
365
366 ftab = 0;
367 (void) sprintf(fname, "%s/files", config_directory);
368 openit:
369 fp = fopenp(VPATH, fname, pname, "r");
370 if (fp == 0) {
371 perror(fname);
372 exit(1);
373 }
374 next:
375 options = 0;
376 rest = (char *) 0;
377 /*
378 * filename [ standard | optional ]
379 * [ dev* | profiling-routine ] [ device-driver]
380 */
381 /*
382 * MACHINE_SQT ONLY:
383 *
384 * filename [ standard | optional ]
385 * [ ordered | sedit ]
386 * [ dev* | profiling-routine ] [ device-driver]
387 */
388 wd = get_word(fp);
389 if (wd == (char *)EOF) {
390 (void) fclose(fp);
391 if (first == 1) {
392 (void) sprintf(fname, "%s/files.%s", config_directory, machinename);
393 first++;
394 goto openit;
395 }
396 if (first == 2) {
397 (void) sprintf(fname, "files.%s", allCaps(ident));
398 first++;
399 fp = fopenp(VPATH, fname, pname, "r");
400 if (fp != 0)
401 goto next;
402 }
403 return;
404 }
405 if (wd == 0)
406 goto next;
407 /*
408 * Allow comment lines beginning witha '#' character.
409 */
410 if (*wd == '#')
411 {
412 while ((wd=get_word(fp)) && wd != (char *)EOF)
413 ;
414 goto next;
415 }
416
417 this = ns(wd);
418 next_word(fp, wd);
419 if (wd == 0) {
420 printf("%s: No type for %s.\n",
421 fname, this);
422 exit(1);
423 }
424 if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags))
425 isdup = 1;
426 else
427 isdup = 0;
428 tp = 0;
429 if (first == 3 && (tp = fltail_lookup(this)) != 0)
430 printf("%s: Local file %s overrides %s.\n",
431 fname, this, tp->f_fn);
432 nreqs = 0;
433 devorprof = "";
434 ordered = 0;
435 sedit = 1; /* SQT: assume sedit for now */
436 needs = 0;
437 if (eq(wd, "standard"))
438 goto checkdev;
439 if (!eq(wd, "optional")) {
440 printf("%s: %s must be optional or standard\n", fname, this);
441 exit(1);
442 }
443 if (strncmp(this, "OPTIONS/", 8) == 0)
444 options++;
445 not_option = 0;
446 nextopt:
447 next_word(fp, wd);
448 if (wd == 0)
449 goto doneopt;
450 if (eq(wd, "ordered")) {
451 ordered++;
452 goto nextopt;
453 }
454 if (machine == MACHINE_SQT && eq(wd, "sedit")) {
455 sedit++;
456 goto nextopt;
457 }
458 if (eq(wd, "not")) {
459 not_option = !not_option;
460 goto nextopt;
461 }
462 devorprof = wd;
463 if (eq(wd, "device-driver") || eq(wd, "profiling-routine")) {
464 next_word(fp, wd);
465 goto save;
466 }
467 nreqs++;
468 if (needs == 0 && nreqs == 1)
469 needs = ns(wd);
470 if (isdup)
471 goto invis;
472 if (options)
473 {
474 struct opt *lop = 0;
475 struct device tdev;
476
477 /*
478 * Allocate a pseudo-device entry which we will insert into
479 * the device list below. The flags field is set non-zero to
480 * indicate an internal entry rather than one generated from
481 * the configuration file. The slave field is set to define
482 * the corresponding symbol as 0 should we fail to find the
483 * option in the option list.
484 */
485 init_dev(&tdev);
486 tdev.d_name = ns(wd);
487 tdev.d_type = PSEUDO_DEVICE;
488 tdev.d_flags++;
489 tdev.d_slave = 0;
490
491 for (op=opt; op; lop=op, op=op->op_next)
492 {
493 char *od = allCaps(ns(wd));
494
495 /*
496 * Found an option which matches the current device
497 * dependency identifier. Set the slave field to
498 * define the option in the header file.
499 */
500 if (strcmp(op->op_name, od) == 0)
501 {
502 tdev.d_slave = 1;
503 if (lop == 0)
504 opt = op->op_next;
505 else
506 lop->op_next = op->op_next;
507 free(op);
508 op = 0;
509 }
510 free(od);
511 if (op == 0)
512 break;
513 }
514 newdev(&tdev);
515 }
516 for (dp = dtab; dp != 0; dp = dp->d_next) {
517 if (eq(dp->d_name, wd) && (dp->d_type != PSEUDO_DEVICE || dp->d_slave)) {
518 if (not_option)
519 goto invis; /* dont want file if option present */
520 else
521 goto nextopt;
522 }
523 }
524 if (not_option)
525 goto nextopt; /* want file if option missing */
526
527 for (op = opt; op != 0; op = op->op_next)
528 if (op->op_value == 0 && opteq(op->op_name, wd)) {
529 if (nreqs == 1) {
530 free(needs);
531 needs = 0;
532 }
533 goto nextopt;
534 }
535
536 for (cp = cputype; cp; cp = cp->cpu_next)
537 if (opteq(cp->cpu_name, wd)) {
538 if (nreqs == 1) {
539 free(needs);
540 needs = 0;
541 }
542 goto nextopt;
543 }
544
545 invis:
546 while ((wd = get_word(fp)) != 0)
547 ;
548 if (tp == 0)
549 tp = new_fent();
550 tp->f_fn = this;
551 tp->f_type = INVISIBLE;
552 tp->f_needs = needs;
553 tp->f_flags = isdup;
554 goto next;
555
556 doneopt:
557 if (nreqs == 0) {
558 printf("%s: what is %s optional on?\n",
559 fname, this);
560 exit(1);
561 }
562
563 checkdev:
564 if (wd) {
565 if (*wd == '|')
566 goto getrest;
567 next_word(fp, wd);
568 if (wd) {
569 if (eq(wd, "ordered")) {
570 ordered++;
571 goto checkdev;
572 }
573 if (machine == MACHINE_SQT && eq(wd, "sedit")) {
574 sedit++;
575 goto checkdev;
576 }
577 devorprof = wd;
578 next_word(fp, wd);
579 }
580 }
581
582 save:
583 getrest:
584 if (wd) {
585 if (*wd == '|') {
586 rest = ns(get_rest(fp));
587 } else {
588 printf("%s: syntax error describing %s\n",
589 fname, this);
590 exit(1);
591 }
592 }
593 if (eq(devorprof, "profiling-routine") && profiling == 0)
594 goto next;
595 if (tp == 0)
596 tp = new_fent();
597 tp->f_fn = this;
598 tp->f_extra = rest;
599 if (options)
600 tp->f_type = INVISIBLE;
601 else
602 if (eq(devorprof, "device-driver"))
603 tp->f_type = DRIVER;
604 else if (eq(devorprof, "profiling-routine"))
605 tp->f_type = PROFILING;
606 else
607 tp->f_type = NORMAL;
608 tp->f_flags = 0;
609 if (ordered)
610 tp->f_flags |= ORDERED;
611 if (sedit) /* SQT */
612 tp->f_flags |= SEDIT;
613 tp->f_needs = needs;
614 if (pf && pf->f_type == INVISIBLE)
615 pf->f_flags = 1; /* mark as duplicate */
616 goto next;
617 }
618
619 int
620 opteq(const char *cp, const char *dp)
621 {
622 char c, d;
623
624 for (; ; cp++, dp++) {
625 if (*cp != *dp) {
626 c = isupper(*cp) ? tolower(*cp) : *cp;
627 d = isupper(*dp) ? tolower(*dp) : *dp;
628 if (c != d)
629 return (0);
630 }
631 if (*cp == 0)
632 return (1);
633 }
634 }
635
636 void
637 put_source_file_name(FILE *fp, struct file_list *tp)
638 {
639 if ((tp->f_fn[0] == '.') && (tp->f_fn[1] == '/'))
640 fprintf(fp, "%s ", tp->f_fn);
641 else
642 fprintf(fp, "$(SOURCE_DIR)/%s ", tp->f_fn);
643 }
644
645 void
646 do_objs(FILE *fp, const char *msg, int ext)
647 {
648 register struct file_list *tp;
649 register int lpos, len;
650 char *cp;
651 char och;
652 const char *sp;
653 #if DO_SWAPFILE
654 register struct file_list *fl;
655 char swapname[32];
656 #endif /* DO_SWAPFILE */
657
658 fprintf(fp, "%s", msg);
659 lpos = strlen(msg);
660 for (tp = ftab; tp != 0; tp = tp->f_next) {
661 if (tp->f_type == INVISIBLE)
662 continue;
663
664 /*
665 * Check for '.o' file in list
666 */
667 cp = tp->f_fn + (len = strlen(tp->f_fn)) - 1;
668 if ((ext == -1 && tp->f_flags & ORDERED) || /* not in objs */
669 (ext != -1 && *cp != ext))
670 continue;
671 else if (*cp == 'o') {
672 if (len + lpos > 72) {
673 lpos = 8;
674 fprintf(fp, "\\\n\t");
675 }
676 put_source_file_name(fp, tp);
677 fprintf(fp, " ");
678 lpos += len + 1;
679 continue;
680 }
681 sp = tail(tp->f_fn);
682 #if DO_SWAPFILE
683 for (fl = conf_list; fl; fl = fl->f_next) {
684 if (fl->f_type != SWAPSPEC)
685 continue;
686 (void) sprintf(swapname, "swap%s.c", fl->f_fn);
687 if (eq(sp, swapname))
688 goto cont;
689 }
690 #endif /* DO_SWAPFILE */
691 cp = (char *)sp + (len = strlen(sp)) - 1;
692 och = *cp;
693 *cp = 'o';
694 if (len + lpos > 72) {
695 lpos = 8;
696 fprintf(fp, "\\\n\t");
697 }
698 fprintf(fp, "%s ", sp);
699 lpos += len + 1;
700 *cp = och;
701 #if DO_SWAPFILE
702 cont:
703 ;
704 #endif /* DO_SWAPFILE */
705 }
706 if (lpos != 8)
707 putc('\n', fp);
708 }
709
710 /* not presently used and probably broken, use ORDERED instead */
711 void
712 do_ordered(FILE *fp)
713 {
714 register struct file_list *tp;
715 register int lpos, len;
716 char *cp;
717 char och;
718 const char *sp;
719
720 fprintf(fp, "ORDERED=");
721 lpos = 10;
722 for (tp = ftab; tp != 0; tp = tp->f_next) {
723 if ((tp->f_flags & ORDERED) != ORDERED)
724 continue;
725 sp = tail(tp->f_fn);
726 cp = (char *)sp + (len = strlen(sp)) - 1;
727 och = *cp;
728 *cp = 'o';
729 if (len + lpos > 72) {
730 lpos = 8;
731 fprintf(fp, "\\\n\t");
732 }
733 fprintf(fp, "%s ", sp);
734 lpos += len + 1;
735 *cp = och;
736 }
737 if (lpos != 8)
738 putc('\n', fp);
739 }
740
741 void
742 do_files(FILE *fp, const char *msg, char ext)
743 {
744 register struct file_list *tp;
745 register int lpos, len=0; /* dvw: init to 0 */
746
747 fprintf(fp, "%s", msg);
748 lpos = 8;
749 for (tp = ftab; tp != 0; tp = tp->f_next) {
750 if (tp->f_type == INVISIBLE)
751 continue;
752 if (tp->f_fn[strlen(tp->f_fn)-1] != ext)
753 continue;
754 /*
755 * Always generate a newline.
756 * Our Makefile's aren't readable anyway.
757 */
758
759 lpos = 8;
760 fprintf(fp, "\\\n\t");
761 put_source_file_name(fp, tp);
762 lpos += len + 1;
763 }
764 if (lpos != 8)
765 putc('\n', fp);
766 }
767
768 /*
769 * Include machine dependent makefile in output
770 */
771
772 void
773 do_machdep(FILE *ofp)
774 {
775 FILE *ifp;
776 char pname[BUFSIZ];
777 char line[BUFSIZ];
778
779 (void) sprintf(line, "%s/Makefile.%s", config_directory, machinename);
780 ifp = fopenp(VPATH, line, pname, "r");
781 if (ifp == 0) {
782 perror(line);
783 exit(1);
784 }
785 while (fgets(line, BUFSIZ, ifp) != 0) {
786 if (profiling && (strncmp(line, "LIBS=", 5) == 0))
787 fprintf(ofp,"LIBS=${LIBS_P}\n");
788 else
789 fputs(line, ofp);
790 }
791 fclose(ifp);
792 }
793
794
795 /*
796 * Format configuration dependent parameter file.
797 */
798
799 void
800 build_confdep(FILE *fp)
801 {
802 fprintf(fp, "#define MAXUSERS %d\n", maxusers);
803 }
804
805 /*
806 * Format cpu types file.
807 */
808
809 void
810 build_cputypes(FILE *fp)
811 {
812 struct cputype *cp;
813
814 for (cp = cputype; cp; cp = cp->cpu_next)
815 fprintf(fp, "#define\t%s\t1\n", cp->cpu_name);
816 }
817
818
819
820 /*
821 * Build a define parameter file. Create it first in a temporary location and
822 * determine if this new contents differs from the old before actually
823 * replacing the original (so as not to introduce avoidable extraneous
824 * compilations).
825 */
826
827 void
828 do_build(const char *name, void (*format)(FILE *))
829 {
830 static char temp[]="#config.tmp";
831 FILE *tfp, *ofp;
832 int c;
833
834 unlink(path(temp));
835 tfp = fopen(path(temp), "w+");
836 if (tfp == 0) {
837 perror(path(temp));
838 exit(1);
839 }
840 unlink(path(temp));
841 (*format)(tfp);
842 ofp = fopen(path(name), "r");
843 if (ofp != 0)
844 {
845 fseek(tfp, 0, 0);
846 while ((c = fgetc(tfp)) != EOF)
847 if (fgetc(ofp) != c)
848 goto copy;
849 if (fgetc(ofp) == EOF)
850 goto same;
851
852 }
853 copy:
854 if (ofp)
855 fclose(ofp);
856 unlink(path(name));
857 ofp = fopen(path(name), "w");
858 if (ofp == 0) {
859 perror(path(name));
860 exit(1);
861 }
862 fseek(tfp, 0, 0);
863 while ((c = fgetc(tfp)) != EOF)
864 fputc(c, ofp);
865 same:
866 fclose(ofp);
867 fclose(tfp);
868 }
869
870 const char *
871 tail(const char *fn)
872 {
873 register const char *cp;
874
875 cp = rindex(fn, '/');
876 if (cp == 0)
877 return (fn);
878 return (cp+1);
879 }
880
881 /*
882 * Create the makerules for each file
883 * which is part of the system.
884 * Devices are processed with the special c2 option -i
885 * which avoids any problem areas with i/o addressing
886 * (e.g. for the VAX); assembler files are processed by as.
887 */
888 void
889 do_rules(FILE *f)
890 {
891 char *cp;
892 char *np, och;
893 const char *tp;
894 register struct file_list *ftp;
895 const char *extras = ""; /* dvw: init to "" */
896 char *source_dir;
897 char och_upper;
898 const char *nl = "";
899
900 for (ftp = ftab; ftp != 0; ftp = ftp->f_next) {
901 if (ftp->f_type == INVISIBLE)
902 continue;
903 cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
904 och = *cp;
905 /*
906 * Don't compile '.o' files
907 */
908 if (och == 'o')
909 continue;
910 /*
911 * Determine where sources should come from
912 */
913 if ((np[0] == '.') && (np[1] == '/')) {
914 source_dir = "";
915 np += 2;
916 } else
917 source_dir = "$(SOURCE_DIR)/";
918 *cp = '\0';
919 tp = tail(np); /* dvw: init tp before 'if' */
920 fprintf(f, "-include %sd\n", tp);
921 fprintf(f, "%so: %s%s%c\n", tp, source_dir, np, och);
922 if (och == 's') {
923 switch (machine) {
924 case MACHINE_MIPSY:
925 case MACHINE_MIPS:
926 break;
927 default:
928 fprintf(f, "\t${S_RULE_0}\n");
929 fprintf(f, "\t${S_RULE_1A}%s%.*s${S_RULE_1B}%s\n",
930 source_dir, (int)(tp-np), np, nl);
931 fprintf(f, "\t${S_RULE_2}%s\n", nl);
932 break;
933 }
934 continue;
935 }
936 extras = "";
937 switch (ftp->f_type) {
938
939 case NORMAL:
940 switch (machine) {
941
942 case MACHINE_MIPSY:
943 case MACHINE_MIPS:
944 break;
945 default:
946 goto common;
947 }
948 break;
949
950 case DRIVER:
951 switch (machine) {
952
953 case MACHINE_MIPSY:
954 case MACHINE_MIPS:
955 fprintf(f, "\t@${RM} %so\n", tp);
956 fprintf(f, "\t${CC} ${CCDFLAGS}%s %s%s%sc\n\n",
957 (ftp->f_extra?ftp->f_extra:""), extras, source_dir, np);
958 continue;
959 default:
960 extras = "_D";
961 goto common;
962 }
963 break;
964
965 case PROFILING:
966 if (!profiling)
967 continue;
968 if (COPTS == 0) {
969 fprintf(stderr,
970 "config: COPTS undefined in generic makefile");
971 COPTS = "";
972 }
973 switch (machine) {
974 case MACHINE_MIPSY:
975 case MACHINE_MIPS:
976 fprintf(f, "\t@${RM} %so\n", tp);
977 fprintf(f, "\t${CC} ${CCPFLAGS}%s %s../%sc\n\n",
978 (ftp->f_extra?ftp->f_extra:""), extras, np);
979 continue;
980 case MACHINE_VAX:
981 case MACHINE_ROMP:
982 case MACHINE_SQT:
983 case MACHINE_MMAX:
984 case MACHINE_SUN3:
985 case MACHINE_SUN4:
986 case MACHINE_I386:
987 case MACHINE_I860:
988 case MACHINE_HPPA:
989 case MACHINE_SPARC:
990 case MACHINE_PPC:
991 case MACHINE_ARM:
992 case MACHINE_X86_64:
993 extras = "_P";
994 goto common;
995 default:
996 fprintf(stderr,
997 "config: don't know how to profile kernel on this cpu\n");
998 break;
999 }
1000
1001 common:
1002 och_upper = och + 'A' - 'a';
1003 fprintf(f, "\t${%c_RULE_0%s}\n", och_upper, extras);
1004 fprintf(f, "\t${%c_RULE_1A%s}", och_upper, extras);
1005 if (ftp->f_extra)
1006 fprintf(f, "%s", ftp->f_extra);
1007 fprintf(f, "%s%.*s${%c_RULE_1B%s}%s\n",
1008 source_dir, (int)(tp-np), np, och_upper, extras, nl);
1009
1010 /* While we are still using CTF, any build that normally does not support CTF will
1011 * a "standard" compile done as well that we can harvest CTF information from; do
1012 * that here.
1013 */
1014 fprintf(f, "\t${%c_CTFRULE_1A%s}", och_upper, extras);
1015 if (ftp->f_extra)
1016 fprintf(f, "%s", ftp->f_extra);
1017 fprintf(f, "%s%.*s${%c_CTFRULE_1B%s}%s\n",
1018 source_dir, (int)(tp-np), np, och_upper, extras, nl);
1019
1020 fprintf(f, "\t${%c_RULE_2%s}%s\n", och_upper, extras, nl);
1021 fprintf(f, "\t${%c_CTFRULE_2%s}%s\n", och_upper, extras, nl);
1022 break;
1023
1024 default:
1025 printf("Don't know rules for %s\n", np);
1026 break;
1027 }
1028 *cp = och;
1029 }
1030 }
1031
1032 /*
1033 * Create the load strings
1034 */
1035 void
1036 do_load(FILE *f)
1037 {
1038 register struct file_list *fl;
1039 int first = 1;
1040
1041 fl = conf_list;
1042 while (fl) {
1043 if (fl->f_type != SYSTEMSPEC) {
1044 fl = fl->f_next;
1045 continue;
1046 }
1047 fl = do_systemspec(f, fl, first);
1048 if (first)
1049 first = 0;
1050 }
1051 fprintf(f, "LOAD =");
1052 for (fl = conf_list; fl != 0; fl = fl->f_next)
1053 if (fl->f_type == SYSTEMSPEC)
1054 fprintf(f, " %s", fl->f_needs);
1055 #ifdef multimax
1056 fprintf(f, "\n\nall .ORDER: includelinks ${LOAD}\n");
1057 #else /* multimax */
1058 fprintf(f, "\n\nall: includelinks ${LOAD}\n");
1059 #endif /* multimax */
1060 fprintf(f, "\n");
1061 }
1062
1063 struct file_list *
1064 do_systemspec(FILE *f, struct file_list *fl, __unused int first)
1065 {
1066 /*
1067 * Variable for kernel name.
1068 */
1069 fprintf(f, "KERNEL_NAME=%s\n", fl->f_needs);
1070
1071 fprintf(f, "%s .ORDER: %s.sys ${SYSDEPS}\n",
1072 fl->f_needs, fl->f_needs);
1073 fprintf(f, "\t${SYS_RULE_1}\n");
1074 fprintf(f, "\t${SYS_RULE_2}\n");
1075 fprintf(f, "\t${SYS_RULE_3}\n");
1076 fprintf(f, "\t${SYS_RULE_4}\n\n");
1077 do_swapspec(f, fl->f_fn, fl->f_needs);
1078 for (fl = fl->f_next; fl != NULL && fl->f_type == SWAPSPEC; fl = fl->f_next)
1079 continue;
1080 return (fl);
1081 }
1082
1083 void
1084 do_swapspec(__unused FILE *f, __unused const char *name, __unused char *sysname)
1085 {
1086
1087 #if DO_SWAPFILE
1088 char *gdir = eq(name, "generic")?"$(MACHINEDIR)/":"";
1089
1090 fprintf(f, "%s.sys:${P} ${PRELDDEPS} ${LDOBJS} ${LDDEPS}\n\n", sysname);
1091 fprintf(f, "%s.swap: swap%s.o\n", sysname, name);
1092 fprintf(f, "\t@rm -f $@\n");
1093 fprintf(f, "\t@cp swap%s.o $@\n\n", name);
1094 fprintf(f, "swap%s.o: %sswap%s.c ${SWAPDEPS}\n", name, gdir, name);
1095 if (machine == MACHINE_MIPSY || machine == MACHINE_MIPS) {
1096 fprintf(f, "\t@${RM} swap%s.o\n", name);
1097 fprintf(f, "\t${CC} ${CCNFLAGS} %sswap%s.c\n\n", gdir, name);
1098 } else {
1099 fprintf(f, "\t${C_RULE_1A}%s${C_RULE_1B}\n", gdir);
1100 fprintf(f, "\t${C_RULE_2}\n");
1101 fprintf(f, "\t${C_RULE_3}\n");
1102 fprintf(f, "\t${C_RULE_4}\n\n");
1103 }
1104 #endif /* DO_SWAPFILE */
1105 }
1106
1107 char *
1108 allCaps(str)
1109 register char *str;
1110 {
1111 register char *cp = str;
1112
1113 while (*str) {
1114 if (islower(*str))
1115 *str = toupper(*str);
1116 str++;
1117 }
1118 return (cp);
1119 }
1120
1121 #define OLDSALUTATION "# DO NOT DELETE THIS LINE"
1122
1123 #define LINESIZE 1024
1124 static char makbuf[LINESIZE]; /* one line buffer for makefile */
1125
1126 void
1127 copy_dependencies(FILE *makin, FILE *makout)
1128 {
1129 register int oldlen = (sizeof OLDSALUTATION - 1);
1130
1131 while (fgets(makbuf, LINESIZE, makin) != NULL) {
1132 if (! strncmp(makbuf, OLDSALUTATION, oldlen))
1133 break;
1134 }
1135 while (fgets(makbuf, LINESIZE, makin) != NULL) {
1136 if (oldlen != 0)
1137 {
1138 if (makbuf[0] == '\n')
1139 continue;
1140 else
1141 oldlen = 0;
1142 }
1143 fputs(makbuf, makout);
1144 }
1145 }