Replace legacy make with bmake
[dragonfly.git] / usr.sbin / config / mkmakefile.c
1 /*
2  * Copyright (c) 1993, 19801990
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)mkmakefile.c     8.1 (Berkeley) 6/6/93
34  * $FreeBSD: src/usr.sbin/config/mkmakefile.c,v 1.51.2.3 2001/01/23 00:09:32 peter Exp $
35  */
36
37 /*
38  * Build the makefile for the system, from
39  * the information in the 'files' files and the
40  * additional files for the machine being compiled to.
41  */
42
43 #include <ctype.h>
44 #include <err.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <sys/param.h>
48 #include "y.tab.h"
49 #include "config.h"
50 #include "configvers.h"
51
52 #define next_word(fp, wd)                                               \
53         {                                                               \
54                 char *word;                                             \
55                                                                         \
56                 word = get_word(fp);                                    \
57                 if (word == (char *)EOF)                                \
58                         return;                                         \
59                 else                                                    \
60                         wd = word;                                      \
61         }
62 #define next_quoted_word(fp, wd)                                        \
63         {                                                               \
64                 char *word;                                             \
65                                                                         \
66                 word = get_quoted_word(fp);                             \
67                 if (word == (char *)EOF)                                \
68                         return;                                         \
69                 else                                                    \
70                         wd = word;                                      \
71         }
72
73 static struct file_list *fcur;
74
75 static char *tail(char *);
76 static void do_clean(FILE *);
77 static void do_rules(FILE *);
78 static void do_sfiles(FILE *);
79 static void do_mfiles(FILE *);
80 static void do_cfiles(FILE *);
81 static void do_objs(FILE *);
82 static void do_before_depend(FILE *);
83 static int opteq(char *, char *);
84 static void read_files(void);
85
86 /*
87  * Lookup a file, by name.
88  */
89 static struct file_list *
90 fl_lookup(char *file)
91 {
92         struct file_list *fp;
93
94         for (fp = ftab; fp != NULL; fp = fp->f_next) {
95                 if (strcmp(fp->f_fn, file) == 0)
96                         return(fp);
97         }
98         return(0);
99 }
100
101 /*
102  * Lookup a file, by final component name.
103  */
104 static struct file_list *
105 fltail_lookup(char *file)
106 {
107         struct file_list *fp;
108
109         for (fp = ftab; fp != NULL; fp = fp->f_next) {
110                 if (strcmp(tail(fp->f_fn), tail(file)) == 0)
111                         return(fp);
112         }
113         return(0);
114 }
115
116 /*
117  * Make a new file list entry
118  */
119 static struct file_list *
120 new_fent(void)
121 {
122         struct file_list *fp;
123
124         fp = malloc(sizeof(*fp));
125         bzero(fp, sizeof(*fp));
126         if (fcur == NULL)
127                 fcur = ftab = fp;
128         else
129                 fcur->f_next = fp;
130         fcur = fp;
131         return(fp);
132 }
133
134 /*
135  * Build the makefile from the skeleton
136  */
137 void
138 makefile(void)
139 {
140         FILE *ifp, *ofp;
141         char line[BUFSIZ];
142         struct opt *op;
143         int versreq;
144
145         read_files();
146         snprintf(line, sizeof(line), "../platform/%s/conf/Makefile",
147                  platformname);
148         ifp = fopen(line, "r");
149         if (ifp == NULL) {
150                 snprintf(line, sizeof(line), "Makefile.%s", platformname);
151                 ifp = fopen(line, "r");
152         }
153         if (ifp == NULL)
154                 err(1, "%s", line);
155         ofp = fopen(path("Makefile.new"), "w");
156         if (ofp == NULL)
157                 err(1, "%s", path("Makefile.new"));
158         fprintf(ofp, "KERN_IDENT=%s\n", raisestr(ident));
159         fprintf(ofp, "MACHINE_PLATFORM=%s\n", platformname);
160         fprintf(ofp, "MACHINE=%s\n", machinename);
161         fprintf(ofp, "MACHINE_ARCH=%s\n", machinearchname);
162         fprintf(ofp, ".if defined(.PARSEDIR)\n");
163         fprintf(ofp, ".export MACHINE_PLATFORM\n");
164         fprintf(ofp, ".export MACHINE\n");
165         fprintf(ofp, ".export MACHINE_ARCH\n");
166         fprintf(ofp, ".else\n");
167         fprintf(ofp, ".makeenv MACHINE_PLATFORM\n");
168         fprintf(ofp, ".makeenv MACHINE\n");
169         fprintf(ofp, ".makeenv MACHINE_ARCH\n");
170         fprintf(ofp, ".endif\n");
171         fprintf(ofp, "IDENT=");
172         if (profiling) {
173                 /* Don't compile kernel profiling code for vkernel */
174                 if (strncmp(platformname, "vkernel", 6) != 0)
175                         fprintf(ofp, " -DGPROF");
176         }
177
178         if (cputype == 0) {
179                 printf("cpu type must be specified\n");
180                 exit(1);
181         }
182         fprintf(ofp, "\n");
183         for (op = mkopt; op != NULL; op = op->op_next)
184                 fprintf(ofp, "%s=%s\n", op->op_name, op->op_value);
185         if (debugging)
186                 fprintf(ofp, "DEBUG=-g\n");
187         if (profiling) {
188                 fprintf(ofp, "PROF=-pg\n");
189                 fprintf(ofp, "PROFLEVEL=%d\n", profiling);
190         }
191         if (*srcdir != '\0')
192                 fprintf(ofp,"S=%s\n", srcdir);
193         while (fgets(line, BUFSIZ, ifp) != 0) {
194                 if (*line != '%') {
195                         fprintf(ofp, "%s", line);
196                         continue;
197                 }
198                 if (strcmp(line, "%BEFORE_DEPEND\n") == 0)
199                         do_before_depend(ofp);
200                 else if (strcmp(line, "%OBJS\n") == 0)
201                         do_objs(ofp);
202                 else if (strcmp(line, "%MFILES\n") == 0)
203                         do_mfiles(ofp);
204                 else if (strcmp(line, "%CFILES\n") == 0)
205                         do_cfiles(ofp);
206                 else if (strcmp(line, "%SFILES\n") == 0)
207                         do_sfiles(ofp);
208                 else if (strcmp(line, "%RULES\n") == 0)
209                         do_rules(ofp);
210                 else if (strcmp(line, "%CLEAN\n") == 0)
211                         do_clean(ofp);
212                 else if (strncmp(line, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) {
213                         versreq = atoi(line + sizeof("%VERSREQ=") - 1);
214                         if (versreq != CONFIGVERS) {
215                                 fprintf(stderr, "ERROR: version of config(8) does not match kernel!\n");
216                                 fprintf(stderr, "config version = %d, ", CONFIGVERS);
217                                 fprintf(stderr, "version required = %d\n\n", versreq);
218                                 fprintf(stderr, "Make sure that /usr/src/usr.sbin/config is in sync\n");
219                                 fprintf(stderr, "with your /usr/src/sys and install a new config binary\n");
220                                 fprintf(stderr, "before trying this again.\n\n");
221                                 fprintf(stderr, "If running the new config fails check your config\n");
222                                 fprintf(stderr, "file against the GENERIC or LINT config files for\n");
223                                 fprintf(stderr, "changes in config syntax, or option/device naming\n");
224                                 fprintf(stderr, "conventions\n\n");
225                                 exit(1);
226                         }
227                 } else
228                         fprintf(stderr,
229                             "Unknown %% construct in generic makefile: %s",
230                             line);
231         }
232         fclose(ifp);
233         fclose(ofp);
234         moveifchanged(path("Makefile.new"), path("Makefile"));
235 }
236
237 /*
238  * Read in the information about files used in making the system.
239  * Store it in the ftab linked list.
240  */
241 static void
242 read_files(void)
243 {
244         FILE *fp;
245         struct file_list *tp, *pf;
246         struct device *dp;
247         struct device *save_dp;
248         struct opt *op;
249         char *wd, *this, *needs, *special, *depends, *clean, *warning;
250         char fname[MAXPATHLEN];
251         int nonoptional;
252         int nreqs, first = 1, configdep, isdup, std, filetype,
253             imp_rule, no_obj, before_depend, nowerror, mandatory;
254
255         ftab = 0;
256         save_dp = NULL;
257         if (ident == NULL) {
258                 printf("no ident line specified\n");
259                 exit(1);
260         }
261         snprintf(fname, sizeof(fname), "../conf/files");
262 openit:
263         fp = fopen(fname, "r");
264         if (fp == NULL)
265                 err(1, "%s", fname);
266 next:
267         /*
268          * filename    [ standard | mandatory | optional ] [ config-dependent ]
269          *      [ dev* | profiling-routine ] [ no-obj ]
270          *      [ compile-with "compile rule" [no-implicit-rule] ]
271          *      [ dependency "dependency-list"] [ before-depend ]
272          *      [ clean "file-list"] [ warning "text warning" ]
273          */
274         wd = get_word(fp);
275         if (wd == (char *)EOF) {
276                 fclose(fp);
277                 if (first == 1) {
278                         first++;
279                         snprintf(fname, sizeof(fname),
280                             "../platform/%s/conf/files",
281                             platformname);
282                         fp = fopen(fname, "r");
283                         if (fp != NULL)
284                                 goto next;
285                         snprintf(fname, sizeof(fname),
286                             "files.%s", platformname);
287                         goto openit;
288                 }
289                 if (first == 2) {
290                         first++;
291                         snprintf(fname, sizeof(fname),
292                             "files.%s", raisestr(ident));
293                         fp = fopen(fname, "r");
294                         if (fp != NULL)
295                                 goto next;
296                 }
297                 return;
298         }
299         if (wd == NULL)
300                 goto next;
301         if (wd[0] == '#')
302         {
303                 while (((wd = get_word(fp)) != (char *)EOF) && wd)
304                         ;
305                 goto next;
306         }
307         this = strdup(wd);
308         next_word(fp, wd);
309         if (wd == NULL) {
310                 printf("%s: No type for %s.\n",
311                     fname, this);
312                 exit(1);
313         }
314         if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags))
315                 isdup = 1;
316         else
317                 isdup = 0;
318         tp = NULL;
319         if (first == 3 && pf == NULL && (tp = fltail_lookup(this)) != NULL) {
320                 if (tp->f_type != INVISIBLE || tp->f_flags)
321                         printf("%s: Local file %s overrides %s.\n",
322                             fname, this, tp->f_fn);
323                 else
324                         printf("%s: Local file %s could override %s"
325                             " with a different kernel configuration.\n",
326                             fname, this, tp->f_fn);
327         }
328         nreqs = 0;
329         special = NULL;
330         depends = NULL;
331         clean = NULL;
332         warning = NULL;
333         configdep = 0;
334         needs = NULL;
335         std = mandatory = nonoptional = 0;
336         imp_rule = 0;
337         no_obj = 0;
338         before_depend = 0;
339         nowerror = 0;
340         filetype = NORMAL;
341         if (strcmp(wd, "standard") == 0) {
342                 std = 1;
343         } else if (strcmp(wd, "mandatory") == 0) {
344                 /*
345                  * If an entry is marked "mandatory", config will abort if 
346                  * it's not called by a configuration line in the config
347                  * file.  Apart from this, the device is handled like one
348                  * marked "optional".
349                  */
350                 mandatory = 1;
351         } else if (strcmp(wd, "nonoptional") == 0) {
352                 nonoptional = 1;
353         } else if (strcmp(wd, "optional") == 0) {
354                 /* don't need to do anything */
355         } else {
356                 printf("%s: %s must be optional, mandatory or standard\n",
357                        fname, this);
358                 printf("Alternatively, your version of config(8) may be out of sync with your\nkernel source.\n");
359                 exit(1);
360         }
361 nextparam:
362         next_word(fp, wd);
363         if (wd == NULL)
364                 goto doneparam;
365         if (strcmp(wd, "config-dependent") == 0) {
366                 configdep++;
367                 goto nextparam;
368         }
369         if (strcmp(wd, "no-obj") == 0) {
370                 no_obj++;
371                 goto nextparam;
372         }
373         if (strcmp(wd, "no-implicit-rule") == 0) {
374                 if (special == NULL) {
375                         printf("%s: alternate rule required when "
376                                "\"no-implicit-rule\" is specified.\n",
377                                fname);
378                 }
379                 imp_rule++;
380                 goto nextparam;
381         }
382         if (strcmp(wd, "before-depend") == 0) {
383                 before_depend++;
384                 goto nextparam;
385         }
386         if (strcmp(wd, "dependency") == 0) {
387                 next_quoted_word(fp, wd);
388                 if (wd == NULL) {
389                         printf("%s: %s missing compile command string.\n",
390                                fname, this);
391                         exit(1);
392                 }
393                 depends = strdup(wd);
394                 goto nextparam;
395         }
396         if (strcmp(wd, "clean") == 0) {
397                 next_quoted_word(fp, wd);
398                 if (wd == NULL) {
399                         printf("%s: %s missing clean file list.\n",
400                                fname, this);
401                         exit(1);
402                 }
403                 clean = strdup(wd);
404                 goto nextparam;
405         }
406         if (strcmp(wd, "compile-with") == 0) {
407                 next_quoted_word(fp, wd);
408                 if (wd == NULL) {
409                         printf("%s: %s missing compile command string.\n",
410                                fname, this);
411                         exit(1);
412                 }
413                 special = strdup(wd);
414                 goto nextparam;
415         }
416         if (strcmp(wd, "nowerror") == 0) {
417                 nowerror++;
418                 goto nextparam;
419         }
420         if (strcmp(wd, "warning") == 0) {
421                 next_quoted_word(fp, wd);
422                 if (wd == NULL) {
423                         printf("%s: %s missing warning text string.\n",
424                                 fname, this);
425                         exit(1);
426                 }
427                 warning = strdup(wd);
428                 goto nextparam;
429         }
430         nreqs++;
431         if (strcmp(wd, "local") == 0) {
432                 filetype = LOCAL;
433                 goto nextparam;
434         }
435         if (strcmp(wd, "no-depend") == 0) {
436                 filetype = NODEPEND;
437                 goto nextparam;
438         }
439         if (strcmp(wd, "device-driver") == 0) {
440                 printf("%s: `device-driver' flag obsolete.\n", fname);
441                 exit(1);
442         }
443         if (strcmp(wd, "profiling-routine") == 0) {
444                 filetype = PROFILING;
445                 goto nextparam;
446         }
447         if (needs == NULL && nreqs == 1)
448                 needs = strdup(wd);
449         if (isdup)
450                 goto invis;
451         for (dp = dtab; dp != NULL; save_dp = dp, dp = dp->d_next)
452                 if (strcmp(dp->d_name, wd) == 0) {
453                         if (std && dp->d_type == PSEUDO_DEVICE &&
454                             dp->d_count <= 0)
455                                 dp->d_count = 1;
456                         goto nextparam;
457                 }
458         if (mandatory) {
459                 printf("%s: mandatory device \"%s\" not found\n",
460                        fname, wd);
461                 exit(1);
462         }
463         if (std) {
464                 dp = malloc(sizeof(*dp));
465                 bzero(dp, sizeof(*dp));
466                 init_dev(dp);
467                 dp->d_name = strdup(wd);
468                 dp->d_type = PSEUDO_DEVICE;
469                 dp->d_count = 1;
470                 save_dp->d_next = dp;
471                 goto nextparam;
472         }
473         for (op = opt; op != NULL; op = op->op_next) {
474                 if (op->op_value == 0 && opteq(op->op_name, wd)) {
475                         if (nreqs == 1) {
476                                 free(needs);
477                                 needs = NULL;
478                         }
479                         goto nextparam;
480                 }
481         }
482         if (nonoptional) {
483                 printf("%s: the option \"%s\" MUST be specified\n",
484                         fname, wd);
485                 exit(1);
486         }
487 invis:
488         while ((wd = get_word(fp)) != NULL)
489                 ;
490         if (tp == NULL)
491                 tp = new_fent();
492         tp->f_fn = this;
493         tp->f_type = INVISIBLE;
494         tp->f_needs = needs;
495         tp->f_flags = isdup;
496         tp->f_special = special;
497         tp->f_depends = depends;
498         tp->f_clean = clean;
499         tp->f_warn = warning;
500         goto next;
501
502 doneparam:
503         if (std == 0 && nreqs == 0) {
504                 printf("%s: what is %s optional on?\n",
505                     fname, this);
506                 exit(1);
507         }
508
509         if (wd != NULL) {
510                 printf("%s: syntax error describing %s\n",
511                     fname, this);
512                 exit(1);
513         }
514         if (filetype == PROFILING && profiling == 0)
515                 goto next;
516         if (tp == NULL)
517                 tp = new_fent();
518         tp->f_fn = this;
519         tp->f_type = filetype;
520         tp->f_flags = 0;
521         if (configdep)
522                 tp->f_flags |= CONFIGDEP;
523         if (imp_rule)
524                 tp->f_flags |= NO_IMPLCT_RULE;
525         if (no_obj)
526                 tp->f_flags |= NO_OBJ;
527         if (before_depend)
528                 tp->f_flags |= BEFORE_DEPEND;
529         if (nowerror)
530                 tp->f_flags |= NOWERROR;
531         if (imp_rule)
532                 tp->f_flags |= NO_IMPLCT_RULE;
533         if (no_obj)
534                 tp->f_flags |= NO_OBJ;
535         tp->f_needs = needs;
536         tp->f_special = special;
537         tp->f_depends = depends;
538         tp->f_clean = clean;
539         tp->f_warn = warning;
540         if (pf && pf->f_type == INVISIBLE)
541                 pf->f_flags = 1;                /* mark as duplicate */
542         goto next;
543 }
544
545 static int
546 opteq(char *cp, char *dp)
547 {
548         char c, d;
549
550         for (;; cp++, dp++) {
551                 if (*cp != *dp) {
552                         c = isupper(*cp) ? tolower(*cp) : *cp;
553                         d = isupper(*dp) ? tolower(*dp) : *dp;
554                         if (c != d)
555                                 return(0);
556                 }
557                 if (*cp == 0)
558                         return(1);
559         }
560 }
561
562 static void
563 do_before_depend(FILE *fp)
564 {
565         struct file_list *tp;
566         int lpos, len;
567
568         fputs("BEFORE_DEPEND=", fp);
569         lpos = 15;
570         for (tp = ftab; tp != NULL; tp = tp->f_next)
571                 if (tp->f_flags & BEFORE_DEPEND) {
572                         len = strlen(tp->f_fn);
573                         if ((len = 3 + len) + lpos > 72) {
574                                 lpos = 8;
575                                 fputs("\\\n\t", fp);
576                         }
577                         if (tp->f_flags & NO_IMPLCT_RULE)
578                                 fprintf(fp, "%s ", tp->f_fn);
579                         else
580                                 fprintf(fp, "$S/%s ", tp->f_fn);
581                         lpos += len + 1;
582                 }
583         if (lpos != 8)
584                 putc('\n', fp);
585 }
586
587 static void
588 do_objs(FILE *fp)
589 {
590         struct file_list *tp;
591         int lpos, len;
592         char *cp, och, *sp;
593
594         fprintf(fp, "OBJS=");
595         lpos = 6;
596         for (tp = ftab; tp != NULL; tp = tp->f_next) {
597                 if (tp->f_type == INVISIBLE || tp->f_flags & NO_OBJ)
598                         continue;
599                 sp = tail(tp->f_fn);
600                 cp = sp + (len = strlen(sp)) - 1;
601                 och = *cp;
602                 *cp = 'o';
603                 if (len + lpos > 72) {
604                         lpos = 8;
605                         fprintf(fp, "\\\n\t");
606                 }
607                 fprintf(fp, "%s ", sp);
608                 lpos += len + 1;
609                 *cp = och;
610         }
611         if (lpos != 8)
612                 putc('\n', fp);
613 }
614
615 static void
616 do_cfiles(FILE *fp)
617 {
618         struct file_list *tp;
619         int lpos, len;
620
621         fputs("CFILES=", fp);
622         lpos = 8;
623         for (tp = ftab; tp != NULL; tp = tp->f_next)
624                 if (tp->f_type != INVISIBLE && tp->f_type != NODEPEND) {
625                         len = strlen(tp->f_fn);
626                         if (tp->f_fn[len - 1] != 'c')
627                                 continue;
628                         if ((len = 3 + len) + lpos > 72) {
629                                 lpos = 8;
630                                 fputs("\\\n\t", fp);
631                         }
632                         if (tp->f_type != LOCAL)
633                                 fprintf(fp, "$S/%s ", tp->f_fn);
634                         else
635                                 fprintf(fp, "%s ", tp->f_fn);
636
637                         lpos += len + 1;
638                 }
639         if (lpos != 8)
640                 putc('\n', fp);
641 }
642
643 static void
644 do_mfiles(FILE *fp)
645 {
646         struct file_list *tp;
647         int lpos, len;
648
649         fputs("MFILES=", fp);
650         lpos = 8;
651         for (tp = ftab; tp != NULL; tp = tp->f_next)
652                 if (tp->f_type != INVISIBLE) {
653                         len = strlen(tp->f_fn);
654                         if (tp->f_fn[len - 1] != 'm' || tp->f_fn[len - 2] != '.')
655                                 continue;
656                         if ((len = 3 + len) + lpos > 72) {
657                                 lpos = 8;
658                                 fputs("\\\n\t", fp);
659                         }
660                         fprintf(fp, "$S/%s ", tp->f_fn);
661                         lpos += len + 1;
662                 }
663         if (lpos != 8)
664                 putc('\n', fp);
665 }
666
667 static void
668 do_sfiles(FILE *fp)
669 {
670         struct file_list *tp;
671         int lpos, len;
672
673         fputs("SFILES=", fp);
674         lpos = 8;
675         for (tp = ftab; tp != NULL; tp = tp->f_next)
676                 if (tp->f_type != INVISIBLE) {
677                         len = strlen(tp->f_fn);
678                         if (tp->f_fn[len - 1] != 'S' && tp->f_fn[len - 1] != 's')
679                                 continue;
680                         if ((len = 3 + len) + lpos > 72) {
681                                 lpos = 8;
682                                 fputs("\\\n\t", fp);
683                         }
684                         fprintf(fp, "$S/%s ", tp->f_fn);
685                         lpos += len + 1;
686                 }
687         if (lpos != 8)
688                 putc('\n', fp);
689 }
690
691
692 static char *
693 tail(char *fn)
694 {
695         char *cp;
696
697         cp = strrchr(fn, '/');
698         if (cp == NULL)
699                 return(fn);
700         return(cp + 1);
701 }
702
703 /*
704  * Create the makerules for each file
705  * which is part of the system.
706  * Devices are processed with the special c2 option -i
707  * which avoids any problem areas with i/o addressing
708  * (e.g. for the VAX); assembler files are processed by as.
709  */
710 static void
711 do_rules(FILE *f)
712 {
713         char *cp, *np, och;
714         struct file_list *ftp;
715         char *special;
716
717         for (ftp = ftab; ftp != NULL; ftp = ftp->f_next) {
718                 if (ftp->f_type == INVISIBLE)
719                         continue;
720                 if (ftp->f_warn != NULL)
721                         printf("WARNING: %s\n", ftp->f_warn);
722                 cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
723                 och = *cp;
724                 if (ftp->f_flags & NO_IMPLCT_RULE) {
725                         if (ftp->f_depends)
726                                 fprintf(f, "%s: %s\n", np, ftp->f_depends);
727                         else
728                                 fprintf(f, "%s: \n", np);
729                 }
730                 else {
731                         *cp = '\0';
732                         if (och == 'o') {
733                                 fprintf(f, "%so:\n\t-cp $S/%so .\n\n",
734                                         tail(np), np);
735                                 continue;
736                         }
737                         if (ftp->f_depends)
738                                 fprintf(f, "%so: $S/%s%c %s\n", tail(np),
739                                         np, och, ftp->f_depends);
740                         else
741                                 fprintf(f, "%so: $S/%s%c\n", tail(np),
742                                         np, och);
743                 }
744                 special = ftp->f_special;
745                 if (special == NULL) {
746                         const char *ftype = NULL;
747                         static char cmd[128];
748
749                         switch (ftp->f_type) {
750
751                         case NORMAL:
752                                 ftype = "NORMAL";
753                                 break;
754
755                         case PROFILING:
756                                 if (!profiling)
757                                         continue;
758                                 ftype = "PROFILE";
759                                 break;
760
761                         default:
762                                 printf("config: don't know rules for %s\n", np);
763                                 break;
764                         }
765                         snprintf(cmd, sizeof(cmd), "${%s_%c%s}%s",
766                             ftype, toupper(och),
767                             ftp->f_flags & CONFIGDEP ? "_C" : "",
768                             ftp->f_flags & NOWERROR ? "" : " ${WERROR}");
769                         special = cmd;
770                 }
771                 *cp = och;
772                 fprintf(f, "\t%s\n\n", special);
773         }
774 }
775
776 static void
777 do_clean(FILE *fp)
778 {
779         struct file_list *tp;
780         int lpos, len;
781
782         fputs("CLEAN=", fp);
783         lpos = 7;
784         for (tp = ftab; tp != NULL; tp = tp->f_next)
785                 if (tp->f_clean) {
786                         len = strlen(tp->f_clean);
787                         if (len + lpos > 72) {
788                                 lpos = 8;
789                                 fputs("\\\n\t", fp);
790                         }
791                         fprintf(fp, "%s ", tp->f_clean);
792                         lpos += len + 1;
793                 }
794         if (lpos != 8)
795                 putc('\n', fp);
796 }
797
798 char *
799 raisestr(char *str)
800 {
801         char *cp = str;
802
803         while (*str) {
804                 if (islower(*str))
805                         *str = toupper(*str);
806                 str++;
807         }
808         return(cp);
809 }