Index: head/usr.sbin/config/config.h =================================================================== --- head/usr.sbin/config/config.h (revision 163637) +++ head/usr.sbin/config/config.h (revision 163638) @@ -1,171 +1,177 @@ /* * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)config.h 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ /* * Config. */ #include #include #include #include struct file_list { STAILQ_ENTRY(file_list) f_next; char *f_fn; /* the name */ int f_type; /* type */ u_char f_flags; /* see below */ char *f_compilewith; /* special make rule if present */ char *f_depends; /* additional dependancies */ char *f_clean; /* File list to add to clean rule */ char *f_warn; /* warning message */ }; struct files_name { char *f_name; STAILQ_ENTRY(files_name) f_next; }; /* * Types. */ #define NORMAL 1 #define PROFILING 3 #define NODEPEND 4 #define LOCAL 5 #define DEVDONE 0x80000000 #define TYPEMASK 0x7fffffff /* * Attributes (flags). */ #define NO_IMPLCT_RULE 1 #define NO_OBJ 2 #define BEFORE_DEPEND 4 #define NOWERROR 16 struct device { int d_done; /* processed */ char *d_name; /* name of device (e.g. rk11) */ #define UNKNOWN -2 /* -2 means not set yet */ STAILQ_ENTRY(device) d_next; /* Next one in list */ }; struct config { char *s_sysname; }; /* * Config has a global notion of which machine type is * being used. It uses the name of the machine in choosing * files and directories. Thus if the name of the machine is ``i386'', * it will build from ``Makefile.i386'' and use ``../i386/inline'' * in the makerules, etc. machinearch is the global notion of the * MACHINE_ARCH for this MACHINE. */ char *machinename; char *machinearch; /* * For each machine, a set of CPU's may be specified as supported. * These and the options (below) are put in the C flags in the makefile. */ struct cputype { char *cpu_name; SLIST_ENTRY(cputype) cpu_next; }; SLIST_HEAD(, cputype) cputype; /* * A set of options may also be specified which are like CPU types, * but which may also specify values for the options. * A separate set of options may be defined for make-style options. */ struct opt { char *op_name; char *op_value; int op_ownfile; /* true = own file, false = makefile */ SLIST_ENTRY(opt) op_next; }; SLIST_HEAD(opt_head, opt) opt, mkopt; struct opt_list { char *o_name; char *o_file; SLIST_ENTRY(opt_list) o_next; }; SLIST_HEAD(, opt_list) otab; +struct hint { + char *hint_name; + STAILQ_ENTRY(hint) hint_next; +}; + +STAILQ_HEAD(hint_head, hint) hints; + extern char *ident; extern char *env; -extern char *hints; extern int do_trace; extern int envmode; extern int hintmode; char *get_word(FILE *); char *get_quoted_word(FILE *); char *path(const char *); char *raisestr(char *); void remember(const char *); void moveifchanged(const char *, const char *); int yyparse(void); int yylex(void); void options(void); void makefile(void); void makeenv(void); void makehints(void); void headers(void); extern STAILQ_HEAD(device_head, device) dtab; extern char errbuf[80]; extern int yyline; extern const char *yyfile; extern STAILQ_HEAD(file_list_head, file_list) ftab; extern STAILQ_HEAD(files_name_head, files_name) fntab; extern int profiling; extern int debugging; extern int found_defaults; extern int maxusers; extern char *PREFIX; /* Config file name - for error messages */ extern char srcdir[]; /* root of the kernel source tree */ #define eq(a,b) (!strcmp(a,b)) #define ns(s) strdup(s) Index: head/usr.sbin/config/config.y =================================================================== --- head/usr.sbin/config/config.y (revision 163637) +++ head/usr.sbin/config/config.y (revision 163638) @@ -1,444 +1,444 @@ %union { char *str; int val; struct file_list *file; } %token ARCH %token COMMA %token CONFIG %token CPU %token NOCPU %token DEVICE %token NODEVICE %token ENV %token EQUALS %token HINTS %token IDENT %token MAXUSERS %token PROFILE %token OPTIONS %token NOOPTION %token MAKEOPTIONS %token NOMAKEOPTION %token SEMICOLON %token INCLUDE %token FILES %token ID %token NUMBER %type Save_id %type Opt_value %type Dev %{ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)config.y 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ #include #include #include #include #include "config.h" struct device_head dtab; char *ident; char *env; int envmode; -char *hints; int hintmode; int yyline; const char *yyfile; struct file_list_head ftab; struct files_name_head fntab; char errbuf[80]; int maxusers; #define ns(s) strdup(s) int include(const char *, int); void yyerror(const char *s); int yywrap(void); static char * devopt(char *dev) { char *ret = malloc(strlen(dev) + 5); sprintf(ret, "DEV_%s", dev); raisestr(ret); return ret; } %} %% Configuration: Many_specs ; Many_specs: Many_specs Spec | /* lambda */ ; Spec: Device_spec SEMICOLON | Config_spec SEMICOLON | INCLUDE ID SEMICOLON = { include($2, 0); }; | FILES ID SEMICOLON = { newfile($2); }; | SEMICOLON | error SEMICOLON ; Config_spec: ARCH Save_id = { if (machinename != NULL && !eq($2, machinename)) errx(1, "%s:%d: only one machine directive is allowed", yyfile, yyline); machinename = $2; machinearch = $2; } | ARCH Save_id Save_id = { if (machinename != NULL && !(eq($2, machinename) && eq($3, machinearch))) errx(1, "%s:%d: only one machine directive is allowed", yyfile, yyline); machinename = $2; machinearch = $3; } | CPU Save_id = { struct cputype *cp = (struct cputype *)calloc(1, sizeof (struct cputype)); cp->cpu_name = $2; SLIST_INSERT_HEAD(&cputype, cp, cpu_next); } | NOCPU Save_id = { struct cputype *cp, *cp2; SLIST_FOREACH_SAFE(cp, &cputype, cpu_next, cp2) { if (eq(cp->cpu_name, $2)) { SLIST_REMOVE(&cputype, cp, cputype, cpu_next); free(cp); } } } | OPTIONS Opt_list | NOOPTION Save_id = { rmopt(&opt, $2); } | MAKEOPTIONS Mkopt_list | NOMAKEOPTION Save_id = { rmopt(&mkopt, $2); } | IDENT ID = { ident = $2; } | System_spec | MAXUSERS NUMBER = { maxusers = $2; } | PROFILE NUMBER = { profiling = $2; } | ENV ID = { env = $2; envmode = 1; } | HINTS ID = { - if (hints != NULL) - errx(1, "More than one 'hints' line at %s:%d", yyfile, - yyline); - hints = $2; + struct hint *hint; + + hint = (struct hint *)calloc(1, sizeof (struct hint)); + hint->hint_name = $2; + STAILQ_INSERT_TAIL(&hints, hint, hint_next); hintmode = 1; } System_spec: CONFIG System_id System_parameter_list = { errx(1, "%s:%d: root/dump/swap specifications obsolete", yyfile, yyline);} | CONFIG System_id ; System_id: Save_id = { newopt(&mkopt, ns("KERNEL"), $1); }; System_parameter_list: System_parameter_list ID | ID ; Opt_list: Opt_list COMMA Option | Option ; Option: Save_id = { newopt(&opt, $1, NULL); if (strchr($1, '=') != NULL) errx(1, "%s:%d: The `=' in options should not be " "quoted", yyfile, yyline); } | Save_id EQUALS Opt_value = { newopt(&opt, $1, $3); } ; Opt_value: ID = { $$ = $1; } | NUMBER = { char buf[80]; (void) snprintf(buf, sizeof(buf), "%d", $1); $$ = ns(buf); } ; Save_id: ID = { $$ = $1; } ; Mkopt_list: Mkopt_list COMMA Mkoption | Mkoption ; Mkoption: Save_id = { newopt(&mkopt, $1, ns("")); } | Save_id EQUALS Opt_value = { newopt(&mkopt, $1, $3); } ; Dev: ID = { $$ = $1; } ; Device_spec: DEVICE Dev_list | NODEVICE NoDev_list ; Dev_list: Dev_list COMMA Device | Device ; NoDev_list: NoDev_list COMMA NoDevice | NoDevice ; Device: Dev = { newopt(&opt, devopt($1), ns("1")); /* and the device part */ newdev($1); } NoDevice: Dev = { char *s = devopt($1); rmopt(&opt, s); free(s); /* and the device part */ rmdev($1); } ; %% void yyerror(const char *s) { errx(1, "%s:%d: %s", yyfile, yyline + 1, s); } int yywrap(void) { if (found_defaults) { if (freopen(PREFIX, "r", stdin) == NULL) err(2, "%s", PREFIX); yyfile = PREFIX; yyline = 0; found_defaults = 0; return 0; } return 1; } /* * Add a new file to the list of files. */ static void newfile(char *name) { struct files_name *nl; nl = (struct files_name *) calloc(1, sizeof *nl); nl->f_name = name; STAILQ_INSERT_TAIL(&fntab, nl, f_next); } /* * Find a device in the list of devices. */ static struct device * finddev(char *name) { struct device *dp; STAILQ_FOREACH(dp, &dtab, d_next) if (eq(dp->d_name, name)) return (dp); return (NULL); } /* * Add a device to the list of devices. */ static void newdev(char *name) { struct device *np; if (finddev(name)) { printf("WARNING: duplicate device `%s' encountered.\n", name); return; } np = (struct device *) calloc(1, sizeof *np); np->d_name = name; STAILQ_INSERT_TAIL(&dtab, np, d_next); } /* * Remove a device from the list of devices. */ static void rmdev(char *name) { struct device *dp; dp = finddev(name); if (dp != NULL) { STAILQ_REMOVE(&dtab, dp, device, d_next); free(dp->d_name); free(dp); } } /* * Find an option in the list of options. */ static struct opt * findopt(struct opt_head *list, char *name) { struct opt *op; SLIST_FOREACH(op, list, op_next) if (eq(op->op_name, name)) return (op); return (NULL); } /* * Add an option to the list of options. */ static void newopt(struct opt_head *list, char *name, char *value) { struct opt *op; if (findopt(list, name)) { printf("WARNING: duplicate option `%s' encountered.\n", name); return; } op = (struct opt *)calloc(1, sizeof (struct opt)); op->op_name = name; op->op_ownfile = 0; op->op_value = value; SLIST_INSERT_HEAD(list, op, op_next); } /* * Remove an option from the list of options. */ static void rmopt(struct opt_head *list, char *name) { struct opt *op; op = findopt(list, name); if (op != NULL) { SLIST_REMOVE(list, op, opt, op_next); free(op->op_name); if (op->op_value != NULL) free(op->op_value); free(op); } } Index: head/usr.sbin/config/main.c =================================================================== --- head/usr.sbin/config/main.c (revision 163637) +++ head/usr.sbin/config/main.c (revision 163638) @@ -1,525 +1,526 @@ /* * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include "y.tab.h" #include "config.h" #include "configvers.h" #ifndef TRUE #define TRUE (1) #endif #ifndef FALSE #define FALSE (0) #endif #define CDIR "../compile/" char * PREFIX; char destdir[MAXPATHLEN]; char srcdir[MAXPATHLEN]; int debugging; int profiling; int found_defaults; static void configfile(void); static void get_srcdir(void); static void usage(void); static void cleanheaders(char *); struct hdr_list { char *h_name; struct hdr_list *h_next; } *htab; /* * Config builds a set of files for building a UNIX * system given a description of the desired system. */ int main(int argc, char **argv) { struct stat buf; int ch, len; char *p; char xxx[MAXPATHLEN]; FILE *fp; while ((ch = getopt(argc, argv, "d:gpV")) != -1) switch (ch) { case 'V': printf("%d\n", CONFIGVERS); exit(0); case 'd': if (*destdir == '\0') strlcpy(destdir, optarg, sizeof(destdir)); else errx(2, "directory already set"); break; case 'g': debugging++; break; case 'p': profiling++; break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc != 1) usage(); PREFIX = *argv; fp = fopen(PREFIX, "r"); if (fp == NULL) err(2, "%s", PREFIX); fclose(fp); if (freopen("DEFAULTS", "r", stdin) != NULL) { found_defaults = 1; yyfile = "DEFAULTS"; } else { if (freopen(PREFIX, "r", stdin) == NULL) err(2, "%s", PREFIX); yyfile = PREFIX; } if (*destdir != '\0') { len = strlen(destdir); while (len > 1 && destdir[len - 1] == '/') destdir[--len] = '\0'; get_srcdir(); } else { strlcpy(destdir, CDIR, sizeof(destdir)); strlcat(destdir, PREFIX, sizeof(destdir)); } p = path((char *)NULL); if (stat(p, &buf)) { if (mkdir(p, 0777)) err(2, "%s", p); } else if (!S_ISDIR(buf.st_mode)) errx(2, "%s isn't a directory", p); STAILQ_INIT(&dtab); STAILQ_INIT(&fntab); SLIST_INIT(&cputype); STAILQ_INIT(&ftab); + STAILQ_INIT(&hints); if (yyparse()) exit(3); /* * Ensure that required elements (machine, cpu, ident) are present. */ if (machinename == NULL) { printf("Specify machine type, e.g. ``machine i386''\n"); exit(1); } if (ident == NULL) { printf("no ident line specified\n"); exit(1); } if (SLIST_EMPTY(&cputype)) { printf("cpu type must be specified\n"); exit(1); } /* * make symbolic links in compilation directory * for "sys" (to make genassym.c work along with #include ) * and similarly for "machine". */ if (*srcdir == '\0') (void)snprintf(xxx, sizeof(xxx), "../../include"); else (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", srcdir, machinename); (void) unlink(path("machine")); (void) symlink(xxx, path("machine")); if (strcmp(machinename, machinearch) != 0) { /* * make symbolic links in compilation directory for * machinearch, if it is different than machinename. */ if (*srcdir == '\0') (void)snprintf(xxx, sizeof(xxx), "../../../%s/include", machinearch); else (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", srcdir, machinearch); (void) unlink(path(machinearch)); (void) symlink(xxx, path(machinearch)); } options(); /* make options .h files */ makefile(); /* build Makefile */ makeenv(); /* build env.c */ makehints(); /* build hints.c */ headers(); /* make a lot of .h files */ configfile(); /* put config file into kernel*/ cleanheaders(p); printf("Kernel build directory is %s\n", p); printf("Don't forget to do ``make cleandepend && make depend''\n"); exit(0); } /* * get_srcdir * determine the root of the kernel source tree * and save that in srcdir. */ static void get_srcdir(void) { if (realpath("../..", srcdir) == NULL) errx(2, "Unable to find root of source tree"); } static void usage(void) { fprintf(stderr, "usage: config [-Vgp] [-d destdir] sysname\n"); exit(1); } /* * get_word * returns EOF on end of file * NULL on end of line * pointer to the word otherwise */ char * get_word(FILE *fp) { static char line[80]; int ch; char *cp; int escaped_nl = 0; begin: while ((ch = getc(fp)) != EOF) if (ch != ' ' && ch != '\t') break; if (ch == EOF) return ((char *)EOF); if (ch == '\\'){ escaped_nl = 1; goto begin; } if (ch == '\n') { if (escaped_nl){ escaped_nl = 0; goto begin; } else return (NULL); } cp = line; *cp++ = ch; while ((ch = getc(fp)) != EOF) { if (isspace(ch)) break; *cp++ = ch; } *cp = 0; if (ch == EOF) return ((char *)EOF); (void) ungetc(ch, fp); return (line); } /* * get_quoted_word * like get_word but will accept something in double or single quotes * (to allow embedded spaces). */ char * get_quoted_word(FILE *fp) { static char line[256]; int ch; char *cp; int escaped_nl = 0; begin: while ((ch = getc(fp)) != EOF) if (ch != ' ' && ch != '\t') break; if (ch == EOF) return ((char *)EOF); if (ch == '\\'){ escaped_nl = 1; goto begin; } if (ch == '\n') { if (escaped_nl){ escaped_nl = 0; goto begin; } else return (NULL); } cp = line; if (ch == '"' || ch == '\'') { int quote = ch; while ((ch = getc(fp)) != EOF) { if (ch == quote) break; if (ch == '\n') { *cp = 0; printf("config: missing quote reading `%s'\n", line); exit(2); } *cp++ = ch; } } else { *cp++ = ch; while ((ch = getc(fp)) != EOF) { if (isspace(ch)) break; *cp++ = ch; } if (ch != EOF) (void) ungetc(ch, fp); } *cp = 0; if (ch == EOF) return ((char *)EOF); return (line); } /* * prepend the path to a filename */ char * path(const char *file) { char *cp = NULL; if (file) asprintf(&cp, "%s/%s", destdir, file); else cp = strdup(destdir); return (cp); } static void configfile(void) { FILE *fi, *fo; char *p; int i; fi = fopen(PREFIX, "r"); if (!fi) err(2, "%s", PREFIX); fo = fopen(p=path("config.c.new"), "w"); if (!fo) err(2, "%s", p); fprintf(fo, "#include \"opt_config.h\"\n"); fprintf(fo, "#ifdef INCLUDE_CONFIG_FILE \n"); fprintf(fo, "const char config[] = \"\\\n"); fprintf(fo, "START CONFIG FILE %s\\n\\\n___", PREFIX); while (EOF != (i=getc(fi))) { if (i == '\n') { fprintf(fo, "\\n\\\n___"); } else if (i == '\"') { fprintf(fo, "\\\""); } else if (i == '\\') { fprintf(fo, "\\\\"); } else { putc(i, fo); } } fprintf(fo, "\\n\\\nEND CONFIG FILE %s\\n\\\n", PREFIX); fprintf(fo, "\";\n"); fprintf(fo, "\n#endif /* INCLUDE_CONFIG_FILE */\n"); fclose(fi); fclose(fo); moveifchanged(path("config.c.new"), path("config.c")); } /* * moveifchanged -- * compare two files; rename if changed. */ void moveifchanged(const char *from_name, const char *to_name) { char *p, *q; int changed; size_t tsize; struct stat from_sb, to_sb; int from_fd, to_fd; changed = 0; if ((from_fd = open(from_name, O_RDONLY)) < 0) err(EX_OSERR, "moveifchanged open(%s)", from_name); if ((to_fd = open(to_name, O_RDONLY)) < 0) changed++; if (!changed && fstat(from_fd, &from_sb) < 0) err(EX_OSERR, "moveifchanged fstat(%s)", from_name); if (!changed && fstat(to_fd, &to_sb) < 0) err(EX_OSERR, "moveifchanged fstat(%s)", to_name); if (!changed && from_sb.st_size != to_sb.st_size) changed++; tsize = (size_t)from_sb.st_size; if (!changed) { p = mmap(NULL, tsize, PROT_READ, MAP_SHARED, from_fd, (off_t)0); #ifndef MAP_FAILED #define MAP_FAILED ((caddr_t) -1) #endif if (p == MAP_FAILED) err(EX_OSERR, "mmap %s", from_name); q = mmap(NULL, tsize, PROT_READ, MAP_SHARED, to_fd, (off_t)0); if (q == MAP_FAILED) err(EX_OSERR, "mmap %s", to_name); changed = memcmp(p, q, tsize); munmap(p, tsize); munmap(q, tsize); } if (changed) { if (rename(from_name, to_name) < 0) err(EX_OSERR, "rename(%s, %s)", from_name, to_name); } else { if (unlink(from_name) < 0) err(EX_OSERR, "unlink(%s)", from_name); } } static void cleanheaders(char *p) { DIR *dirp; struct dirent *dp; struct file_list *fl; struct hdr_list *hl; int i; remember("y.tab.h"); remember("setdefs.h"); STAILQ_FOREACH(fl, &ftab, f_next) remember(fl->f_fn); /* * Scan the build directory and clean out stuff that looks like * it might have been a leftover NFOO header, etc. */ if ((dirp = opendir(p)) == NULL) err(EX_OSERR, "opendir %s", p); while ((dp = readdir(dirp)) != NULL) { i = dp->d_namlen - 2; /* Skip non-headers */ if (dp->d_name[i] != '.' || dp->d_name[i + 1] != 'h') continue; /* Skip special stuff, eg: bus_if.h, but check opt_*.h */ if (index(dp->d_name, '_') && strncmp(dp->d_name, "opt_", 4) != 0) continue; /* Check if it is a target file */ for (hl = htab; hl != NULL; hl = hl->h_next) { if (eq(dp->d_name, hl->h_name)) { break; } } if (hl) continue; printf("Removing stale header: %s\n", dp->d_name); if (unlink(path(dp->d_name)) == -1) warn("unlink %s", dp->d_name); } (void)closedir(dirp); } void remember(const char *file) { char *s; struct hdr_list *hl; if ((s = strrchr(file, '/')) != NULL) s = ns(s + 1); else s = ns(file); if (index(s, '_') && strncmp(s, "opt_", 4) != 0) { free(s); return; } for (hl = htab; hl != NULL; hl = hl->h_next) { if (eq(s, hl->h_name)) { free(s); return; } } hl = calloc(1, sizeof(*hl)); hl->h_name = s; hl->h_next = htab; htab = hl; } Index: head/usr.sbin/config/mkmakefile.c =================================================================== --- head/usr.sbin/config/mkmakefile.c (revision 163637) +++ head/usr.sbin/config/mkmakefile.c (revision 163638) @@ -1,785 +1,782 @@ /* * Copyright (c) 1993, 19801990 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static char sccsid[] = "@(#)mkmakefile.c 8.1 (Berkeley) 6/6/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ /* * Build the makefile for the system, from * the information in the files files and the * additional files for the machine being compiled to. */ #include #include #include #include #include #include "y.tab.h" #include "config.h" #include "configvers.h" #define next_word(fp, wd) \ { char *word = get_word(fp); \ if (word == (char *)EOF) \ return; \ else \ wd = word; \ } #define next_quoted_word(fp, wd) \ { char *word = get_quoted_word(fp); \ if (word == (char *)EOF) \ return; \ else \ wd = word; \ } static char *tail(char *); static void do_clean(FILE *); static void do_rules(FILE *); static void do_xxfiles(char *, FILE *); static void do_objs(FILE *); static void do_before_depend(FILE *); static int opteq(const char *, const char *); static void read_files(void); /* * Lookup a file, by name. */ static struct file_list * fl_lookup(char *file) { struct file_list *fp; STAILQ_FOREACH(fp, &ftab, f_next) { if (eq(fp->f_fn, file)) return (fp); } return (0); } /* * Make a new file list entry */ static struct file_list * new_fent(void) { struct file_list *fp; fp = (struct file_list *) calloc(1, sizeof *fp); STAILQ_INSERT_TAIL(&ftab, fp, f_next); return (fp); } /* * Build the makefile from the skeleton */ void makefile(void) { FILE *ifp, *ofp; char line[BUFSIZ]; struct opt *op; int versreq; read_files(); snprintf(line, sizeof(line), "../../conf/Makefile.%s", machinename); ifp = fopen(line, "r"); if (ifp == 0) { snprintf(line, sizeof(line), "Makefile.%s", machinename); ifp = fopen(line, "r"); } if (ifp == 0) err(1, "%s", line); ofp = fopen(path("Makefile.new"), "w"); if (ofp == 0) err(1, "%s", path("Makefile.new")); fprintf(ofp, "KERN_IDENT=%s\n", ident); SLIST_FOREACH(op, &mkopt, op_next) fprintf(ofp, "%s=%s\n", op->op_name, op->op_value); if (debugging) fprintf(ofp, "DEBUG=-g\n"); if (profiling) fprintf(ofp, "PROFLEVEL=%d\n", profiling); if (*srcdir != '\0') fprintf(ofp,"S=%s\n", srcdir); while (fgets(line, BUFSIZ, ifp) != 0) { if (*line != '%') { fprintf(ofp, "%s", line); continue; } if (eq(line, "%BEFORE_DEPEND\n")) do_before_depend(ofp); else if (eq(line, "%OBJS\n")) do_objs(ofp); else if (strncmp(line, "%FILES.", 7) == 0) do_xxfiles(line, ofp); else if (eq(line, "%RULES\n")) do_rules(ofp); else if (eq(line, "%CLEAN\n")) do_clean(ofp); else if (strncmp(line, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) { versreq = atoi(line + sizeof("%VERSREQ=") - 1); if (MAJOR_VERS(versreq) != MAJOR_VERS(CONFIGVERS) || versreq > CONFIGVERS) { fprintf(stderr, "ERROR: version of config(8) does not match kernel!\n"); fprintf(stderr, "config version = %d, ", CONFIGVERS); fprintf(stderr, "version required = %d\n\n", versreq); fprintf(stderr, "Make sure that /usr/src/usr.sbin/config is in sync\n"); fprintf(stderr, "with your /usr/src/sys and install a new config binary\n"); fprintf(stderr, "before trying this again.\n\n"); fprintf(stderr, "If running the new config fails check your config\n"); fprintf(stderr, "file against the GENERIC or LINT config files for\n"); fprintf(stderr, "changes in config syntax, or option/device naming\n"); fprintf(stderr, "conventions\n\n"); exit(1); } } else fprintf(stderr, "Unknown %% construct in generic makefile: %s", line); } (void) fclose(ifp); (void) fclose(ofp); moveifchanged(path("Makefile.new"), path("Makefile")); } /* * Build hints.c from the skeleton */ void makehints(void) { - FILE *ifp, *ofp; + FILE *ifp = NULL, *ofp; char line[BUFSIZ]; char *s; + struct hint *hint; - if (hints) { - ifp = fopen(hints, "r"); - if (ifp == NULL) - err(1, "%s", hints); - } else { - ifp = NULL; - } ofp = fopen(path("hints.c.new"), "w"); if (ofp == NULL) err(1, "%s", path("hints.c.new")); fprintf(ofp, "#include \n"); fprintf(ofp, "#include \n"); fprintf(ofp, "\n"); fprintf(ofp, "int hintmode = %d;\n", hintmode); fprintf(ofp, "char static_hints[] = {\n"); - if (ifp) { + STAILQ_FOREACH(hint, &hints, hint_next) { + ifp = fopen(hint->hint_name, "r"); + if (ifp == NULL) + err(1, "%s", hint->hint_name); while (fgets(line, BUFSIZ, ifp) != 0) { /* zap trailing CR and/or LF */ while ((s = rindex(line, '\n')) != NULL) *s = '\0'; while ((s = rindex(line, '\r')) != NULL) *s = '\0'; /* remove # comments */ s = index(line, '#'); if (s) *s = '\0'; /* remove any whitespace and " characters */ s = line; while (*s) { if (*s == ' ' || *s == '\t' || *s == '"') { while (*s) { s[0] = s[1]; s++; } /* start over */ s = line; continue; } s++; } /* anything left? */ if (*line == '\0') continue; fprintf(ofp, "\"%s\\0\"\n", line); } } fprintf(ofp, "\"\\0\"\n};\n"); if (ifp) fclose(ifp); fclose(ofp); moveifchanged(path("hints.c.new"), path("hints.c")); } /* * Build env.c from the skeleton */ void makeenv(void) { FILE *ifp, *ofp; char line[BUFSIZ]; char *s; if (env) { ifp = fopen(env, "r"); if (ifp == NULL) err(1, "%s", env); } else { ifp = NULL; } ofp = fopen(path("env.c.new"), "w"); if (ofp == NULL) err(1, "%s", path("env.c.new")); fprintf(ofp, "#include \n"); fprintf(ofp, "#include \n"); fprintf(ofp, "\n"); fprintf(ofp, "int envmode = %d;\n", envmode); fprintf(ofp, "char static_env[] = {\n"); if (ifp) { while (fgets(line, BUFSIZ, ifp) != 0) { /* zap trailing CR and/or LF */ while ((s = rindex(line, '\n')) != NULL) *s = '\0'; while ((s = rindex(line, '\r')) != NULL) *s = '\0'; /* remove # comments */ s = index(line, '#'); if (s) *s = '\0'; /* remove any whitespace and " characters */ s = line; while (*s) { if (*s == ' ' || *s == '\t' || *s == '"') { while (*s) { s[0] = s[1]; s++; } /* start over */ s = line; continue; } s++; } /* anything left? */ if (*line == '\0') continue; fprintf(ofp, "\"%s\\0\"\n", line); } } fprintf(ofp, "\"\\0\"\n};\n"); if (ifp) fclose(ifp); fclose(ofp); moveifchanged(path("env.c.new"), path("env.c")); } static void read_file(char *fname) { char ifname[MAXPATHLEN]; FILE *fp; struct file_list *tp; struct device *dp; struct opt *op; char *wd, *this, *compilewith, *depends, *clean, *warning; int compile, match, nreqs, std, filetype, imp_rule, no_obj, before_depend, mandatory, nowerror; fp = fopen(fname, "r"); if (fp == 0) err(1, "%s", fname); next: /* * include "filename" * filename [ standard | mandatory | optional ] * [ dev* [ | dev* ... ] | profiling-routine ] [ no-obj ] * [ compile-with "compile rule" [no-implicit-rule] ] * [ dependency "dependency-list"] [ before-depend ] * [ clean "file-list"] [ warning "text warning" ] */ wd = get_word(fp); if (wd == (char *)EOF) { (void) fclose(fp); return; } if (wd == 0) goto next; if (wd[0] == '#') { while (((wd = get_word(fp)) != (char *)EOF) && wd) ; goto next; } if (eq(wd, "include")) { next_quoted_word(fp, wd); if (wd == 0) { printf("%s: missing include filename.\n", fname); exit(1); } (void) snprintf(ifname, sizeof(ifname), "../../%s", wd); read_file(ifname); while (((wd = get_word(fp)) != (char *)EOF) && wd) ; goto next; } this = ns(wd); next_word(fp, wd); if (wd == 0) { printf("%s: No type for %s.\n", fname, this); exit(1); } tp = fl_lookup(this); compile = 0; match = 1; nreqs = 0; compilewith = 0; depends = 0; clean = 0; warning = 0; std = mandatory = 0; imp_rule = 0; no_obj = 0; before_depend = 0; nowerror = 0; filetype = NORMAL; if (eq(wd, "standard")) { std = 1; /* * If an entry is marked "mandatory", config will abort if it's * not called by a configuration line in the config file. Apart * from this, the device is handled like one marked "optional". */ } else if (eq(wd, "mandatory")) { mandatory = 1; } else if (!eq(wd, "optional")) { printf("%s: %s must be optional, mandatory or standard\n", fname, this); exit(1); } nextparam: next_word(fp, wd); if (wd == 0) { compile += match; if (compile && tp == NULL) goto doneparam; goto next; } if (eq(wd, "|")) { if (nreqs == 0) { printf("%s: syntax error describing %s\n", fname, this); exit(1); } compile += match; match = 1; nreqs = 0; goto nextparam; } if (eq(wd, "no-obj")) { no_obj++; goto nextparam; } if (eq(wd, "no-implicit-rule")) { if (compilewith == 0) { printf("%s: alternate rule required when " "\"no-implicit-rule\" is specified.\n", fname); } imp_rule++; goto nextparam; } if (eq(wd, "before-depend")) { before_depend++; goto nextparam; } if (eq(wd, "dependency")) { next_quoted_word(fp, wd); if (wd == 0) { printf("%s: %s missing compile command string.\n", fname, this); exit(1); } depends = ns(wd); goto nextparam; } if (eq(wd, "clean")) { next_quoted_word(fp, wd); if (wd == 0) { printf("%s: %s missing clean file list.\n", fname, this); exit(1); } clean = ns(wd); goto nextparam; } if (eq(wd, "compile-with")) { next_quoted_word(fp, wd); if (wd == 0) { printf("%s: %s missing compile command string.\n", fname, this); exit(1); } compilewith = ns(wd); goto nextparam; } if (eq(wd, "warning")) { next_quoted_word(fp, wd); if (wd == 0) { printf("%s: %s missing warning text string.\n", fname, this); exit(1); } warning = ns(wd); goto nextparam; } nreqs++; if (eq(wd, "local")) { filetype = LOCAL; goto nextparam; } if (eq(wd, "no-depend")) { filetype = NODEPEND; goto nextparam; } if (eq(wd, "profiling-routine")) { filetype = PROFILING; goto nextparam; } if (eq(wd, "nowerror")) { nowerror = 1; goto nextparam; } STAILQ_FOREACH(dp, &dtab, d_next) if (eq(dp->d_name, wd)) { dp->d_done |= DEVDONE; goto nextparam; } if (mandatory) { printf("%s: mandatory device \"%s\" not found\n", fname, wd); exit(1); } if (std) { printf("standard entry %s has a device keyword - %s!\n", this, wd); exit(1); } SLIST_FOREACH(op, &opt, op_next) if (op->op_value == 0 && opteq(op->op_name, wd)) goto nextparam; match = 0; goto nextparam; doneparam: if (std == 0 && nreqs == 0) { printf("%s: what is %s optional on?\n", fname, this); exit(1); } if (wd) { printf("%s: syntax error describing %s\n", fname, this); exit(1); } if (filetype == PROFILING && profiling == 0) goto next; tp = new_fent(); tp->f_fn = this; tp->f_type = filetype; if (imp_rule) tp->f_flags |= NO_IMPLCT_RULE; if (no_obj) tp->f_flags |= NO_OBJ; if (before_depend) tp->f_flags |= BEFORE_DEPEND; if (nowerror) tp->f_flags |= NOWERROR; tp->f_compilewith = compilewith; tp->f_depends = depends; tp->f_clean = clean; tp->f_warn = warning; goto next; } /* * Read in the information about files used in making the system. * Store it in the ftab linked list. */ static void read_files(void) { char fname[MAXPATHLEN]; struct files_name *nl, *tnl; (void) snprintf(fname, sizeof(fname), "../../conf/files"); read_file(fname); (void) snprintf(fname, sizeof(fname), "../../conf/files.%s", machinename); read_file(fname); for (nl = STAILQ_FIRST(&fntab); nl != NULL; nl = tnl) { read_file(nl->f_name); tnl = STAILQ_NEXT(nl, f_next); free(nl->f_name); free(nl); } } static int opteq(const char *cp, const char *dp) { char c, d; for (; ; cp++, dp++) { if (*cp != *dp) { c = isupper(*cp) ? tolower(*cp) : *cp; d = isupper(*dp) ? tolower(*dp) : *dp; if (c != d) return (0); } if (*cp == 0) return (1); } } static void do_before_depend(FILE *fp) { struct file_list *tp; int lpos, len; fputs("BEFORE_DEPEND=", fp); lpos = 15; STAILQ_FOREACH(tp, &ftab, f_next) if (tp->f_flags & BEFORE_DEPEND) { len = strlen(tp->f_fn); if ((len = 3 + len) + lpos > 72) { lpos = 8; fputs("\\\n\t", fp); } if (tp->f_flags & NO_IMPLCT_RULE) fprintf(fp, "%s ", tp->f_fn); else fprintf(fp, "$S/%s ", tp->f_fn); lpos += len + 1; } if (lpos != 8) putc('\n', fp); } static void do_objs(FILE *fp) { struct file_list *tp; int lpos, len; char *cp, och, *sp; fprintf(fp, "OBJS="); lpos = 6; STAILQ_FOREACH(tp, &ftab, f_next) { if (tp->f_flags & NO_OBJ) continue; sp = tail(tp->f_fn); cp = sp + (len = strlen(sp)) - 1; och = *cp; *cp = 'o'; if (len + lpos > 72) { lpos = 8; fprintf(fp, "\\\n\t"); } fprintf(fp, "%s ", sp); lpos += len + 1; *cp = och; } if (lpos != 8) putc('\n', fp); } static void do_xxfiles(char *tag, FILE *fp) { struct file_list *tp; int lpos, len, slen; char *suff, *SUFF; if (tag[strlen(tag) - 1] == '\n') tag[strlen(tag) - 1] = '\0'; suff = ns(tag + 7); SUFF = ns(suff); raisestr(SUFF); slen = strlen(suff); fprintf(fp, "%sFILES=", SUFF); lpos = 8; STAILQ_FOREACH(tp, &ftab, f_next) if (tp->f_type != NODEPEND) { len = strlen(tp->f_fn); if (tp->f_fn[len - slen - 1] != '.') continue; if (strcasecmp(&tp->f_fn[len - slen], suff) != 0) continue; if ((len = 3 + len) + lpos > 72) { lpos = 8; fputs("\\\n\t", fp); } if (tp->f_type != LOCAL) fprintf(fp, "$S/%s ", tp->f_fn); else fprintf(fp, "%s ", tp->f_fn); lpos += len + 1; } if (lpos != 8) putc('\n', fp); } static char * tail(char *fn) { char *cp; cp = rindex(fn, '/'); if (cp == 0) return (fn); return (cp+1); } /* * Create the makerules for each file * which is part of the system. */ static void do_rules(FILE *f) { char *cp, *np, och; struct file_list *ftp; char *compilewith; STAILQ_FOREACH(ftp, &ftab, f_next) { if (ftp->f_warn) printf("WARNING: %s\n", ftp->f_warn); cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1; och = *cp; if (ftp->f_flags & NO_IMPLCT_RULE) { if (ftp->f_depends) fprintf(f, "%s: %s\n", np, ftp->f_depends); else fprintf(f, "%s: \n", np); } else { *cp = '\0'; if (och == 'o') { fprintf(f, "%so:\n\t-cp $S/%so .\n\n", tail(np), np); continue; } if (ftp->f_depends) { fprintf(f, "%sln: $S/%s%c %s\n", tail(np), np, och, ftp->f_depends); fprintf(f, "\t${NORMAL_LINT}\n\n"); fprintf(f, "%so: $S/%s%c %s\n", tail(np), np, och, ftp->f_depends); } else { fprintf(f, "%sln: $S/%s%c\n", tail(np), np, och); fprintf(f, "\t${NORMAL_LINT}\n\n"); fprintf(f, "%so: $S/%s%c\n", tail(np), np, och); } } compilewith = ftp->f_compilewith; if (compilewith == 0) { const char *ftype = NULL; static char cmd[128]; switch (ftp->f_type) { case NORMAL: ftype = "NORMAL"; break; case PROFILING: if (!profiling) continue; ftype = "PROFILE"; break; default: printf("config: don't know rules for %s\n", np); break; } snprintf(cmd, sizeof(cmd), "${%s_%c%s}", ftype, toupper(och), ftp->f_flags & NOWERROR ? "_NOWERROR" : ""); compilewith = cmd; } *cp = och; fprintf(f, "\t%s\n\n", compilewith); } } static void do_clean(FILE *fp) { struct file_list *tp; int lpos, len; fputs("CLEAN=", fp); lpos = 7; STAILQ_FOREACH(tp, &ftab, f_next) if (tp->f_clean) { len = strlen(tp->f_clean); if (len + lpos > 72) { lpos = 8; fputs("\\\n\t", fp); } fprintf(fp, "%s ", tp->f_clean); lpos += len + 1; } if (lpos != 8) putc('\n', fp); } char * raisestr(char *str) { char *cp = str; while (*str) { if (islower(*str)) *str = toupper(*str); str++; } return (cp); }