diff --git a/usr.sbin/config/config.h b/usr.sbin/config/config.h index 25a81cae768a..8b6606fabc46 100644 --- a/usr.sbin/config/config.h +++ b/usr.sbin/config/config.h @@ -1,157 +1,158 @@ /* * 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. * 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.h 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ /* * Config. */ #include #include #include struct file_list { struct file_list *f_next; char *f_fn; /* the name */ int f_type; /* type or count */ 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_needs; char *f_warn; /* warning message */ }; /* * Types. */ #define NORMAL 1 #define INVISIBLE 2 #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 NEED_COUNT 8 #define ISDUP 16 struct device { int d_done; /* processed */ char *d_name; /* name of device (e.g. rk11) */ int d_count; /* device count */ #define UNKNOWN -2 /* -2 means not set yet */ struct 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. */ char *machinename; /* * 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; struct cputype *cpu_next; } *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 */ struct opt *op_next; } *opt, *mkopt; struct opt_list { char *o_name; char *o_file; struct opt_list *o_next; } *otab; extern char *ident; extern char *hints; extern int do_trace; 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 headers(void); extern struct device *dtab; extern char errbuf[80]; extern int yyline; +extern const char *yyfile; extern struct file_list *ftab; extern int profiling; extern int debugging; 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) diff --git a/usr.sbin/config/config.y b/usr.sbin/config/config.y index 96e57d90c8f3..5f1577471ac5 100644 --- a/usr.sbin/config/config.y +++ b/usr.sbin/config/config.y @@ -1,276 +1,283 @@ %union { char *str; int val; struct file_list *file; } %token ARCH %token COMMA %token CONFIG %token CPU %token DEVICE %token EQUALS %token HINTS %token IDENT %token MAXUSERS %token PROFILE %token OPTIONS %token MAKEOPTIONS %token SEMICOLON +%token INCLUDE %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" static struct device *curp = 0; struct device *dtab; char *ident; char *hints; int hintmode; int yyline; +const char *yyfile; struct file_list *ftab; char errbuf[80]; int maxusers; #define ns(s) strdup(s) - -static void yyerror(const char *s); +int include(const char *, int); +void yyerror(const char *s); 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 | SEMICOLON | error SEMICOLON ; Config_spec: ARCH Save_id = { machinename = $2; } | CPU Save_id = { struct cputype *cp = (struct cputype *)malloc(sizeof (struct cputype)); memset(cp, 0, sizeof(*cp)); cp->cpu_name = $2; cp->cpu_next = cputype; cputype = cp; } | OPTIONS Opt_list | MAKEOPTIONS Mkopt_list | IDENT ID = { ident = $2; } | System_spec | MAXUSERS NUMBER = { maxusers = $2; } | PROFILE NUMBER = { profiling = $2; } | HINTS ID = { hints = $2; hintmode = 1; - }; + } | + INCLUDE ID + = { include($2, 0); }; System_spec: CONFIG System_id System_parameter_list - = { errx(1, "line %d: root/dump/swap specifications obsolete", yyline);} + = { 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 = { char *s; newopt(&opt, $1, NULL); if ((s = strchr($1, '='))) - errx(1, "line %d: The `=' in options should not be quoted", yyline); + 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 EQUALS Opt_value = { newopt(&mkopt, $1, $3); } ; Dev: ID = { $$ = $1; } ; Device_spec: DEVICE Dev = { newopt(&opt, devopt($2), ns("1")); /* and the device part */ newdev($2, UNKNOWN); } | DEVICE Dev NUMBER = { newopt(&opt, devopt($2), ns("1")); /* and the device part */ newdev($2, $3); if ($3 == 0) - errx(1, "line %d: devices with zero units are not likely to be correct", yyline); + errx(1, "%s:%d: devices with zero units are not " + "likely to be correct", yyfile, yyline); } ; %% -static void +void yyerror(const char *s) { - errx(1, "line %d: %s", yyline + 1, s); + errx(1, "%s:%d: %s", yyfile, yyline + 1, s); } /* * add a device to the list of devices */ static void newdev(char *name, int count) { struct device *np; np = (struct device *) malloc(sizeof *np); memset(np, 0, sizeof(*np)); np->d_name = name; np->d_count = count; np->d_next = 0; if (curp == 0) dtab = np; else curp->d_next = np; curp = np; } static void newopt(struct opt **list, char *name, char *value) { struct opt *op; op = (struct opt *)malloc(sizeof (struct opt)); memset(op, 0, sizeof(*op)); op->op_name = name; op->op_ownfile = 0; op->op_value = value; op->op_next = *list; *list = op; } diff --git a/usr.sbin/config/lang.l b/usr.sbin/config/lang.l index b96877231a61..63e46e4823c3 100644 --- a/usr.sbin/config/lang.l +++ b/usr.sbin/config/lang.l @@ -1,188 +1,273 @@ %{ /*- * 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. * 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. * * @(#)lang.l 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ +#include #include #include #include "y.tab.h" #include "config.h" #define YY_NO_UNPUT +/* + * Data for returning to previous files from include files. + */ +struct incl { + struct incl *in_prev; /* previous includes in effect, if any */ + YY_BUFFER_STATE in_buf; /* previous lex state */ + const char *in_fname; /* previous file name */ + int in_lineno; /* previous line number */ + int in_ateof; /* token to insert at EOF */ +}; +static struct incl *inclp; +static const char *lastfile; + /* * Key word table */ struct kt { const char *kt_name; int kt_val; } key_words[] = { { "config", CONFIG }, { "cpu", CPU }, { "device", DEVICE }, { "hints", HINTS }, { "ident", IDENT }, { "machine", ARCH }, /* MACHINE is defined in /sys/param.h */ { "makeoptions", MAKEOPTIONS }, { "maxusers", MAXUSERS }, { "profile", PROFILE }, { "option", OPTIONS }, { "options", OPTIONS }, + { "include", INCLUDE }, { 0, 0 }, }; +static int endinclude(void); +int include(const char *, int); int kw_lookup(char *); int octal(char *); int hex(char *); +int yyerror(const char *); %} WORD [A-Za-z_][-A-Za-z_]* ID [A-Za-z_][-A-Za-z_0-9]* %START NONUM TOEOL %% {WORD} { int i; BEGIN 0; if ((i = kw_lookup(yytext)) == -1) { yylval.str = strdup(yytext); return ID; } return i; } {WORD}/[0-9]* { int i; if ((i = kw_lookup(yytext)) == -1) REJECT; if (i == DEVICE) BEGIN NONUM; return i; } {ID} { BEGIN 0; yylval.str = strdup(yytext); return ID; } \\\"[^"]+\\\" { BEGIN 0; yytext[yyleng-2] = '"'; yytext[yyleng-1] = '\0'; yylval.str = strdup(yytext + 1); return ID; } \"[^"]+\" { BEGIN 0; yytext[yyleng-1] = '\0'; yylval.str = strdup(yytext + 1); return ID; } [^# \t\n]* { BEGIN 0; yylval.str = strdup(yytext); return ID; } 0[0-7]* { yylval.val = octal(yytext); return NUMBER; } 0x[0-9a-fA-F]+ { yylval.val = hex(yytext); return NUMBER; } -?[1-9][0-9]* { yylval.val = atoi(yytext); return NUMBER; } "?" { yylval.val = -1; return NUMBER; } \n/[ \t] { yyline++; } \n { yyline++; return SEMICOLON; } #.* { /* Ignored (comment) */; } [ \t\f]* { /* Ignored (white space) */; } ";" { return SEMICOLON; } "," { return COMMA; } "=" { BEGIN TOEOL; return EQUALS; } +<> { + int tok; + + if (inclp == NULL) + return YY_NULL; + tok = endinclude(); + if (tok != 0) + return tok; + /* otherwise continue scanning */ + } . { return yytext[0]; } %% /* * kw_lookup * Look up a string in the keyword table. Returns a -1 if the * string is not a keyword otherwise it returns the keyword number */ int kw_lookup(char *word) { struct kt *kp; for (kp = key_words; kp->kt_name != 0; kp++) if (eq(word, kp->kt_name)) return kp->kt_val; return -1; } /* * Number conversion routines */ int octal(char *str) { int num; (void) sscanf(str, "%o", &num); return num; } int hex(char *str) { int num; (void) sscanf(str+2, "%x", &num); return num; } + + +/* + * Open the named file for inclusion at the current point. Returns 0 on + * success (file opened and previous state pushed), nonzero on failure + * (fopen failed, complaint made). The `ateof' parameter controls the + * token to be inserted at the end of the include file. If ateof == 0, + * then nothing is inserted. + */ +int +include(const char *fname, int ateof) +{ + FILE *fp; + struct incl *in; + + fp = fopen(fname, "r"); + if (fp == NULL) { + yyerror("cannot open file"); + return (-1); + } + in = malloc(sizeof(*in)); + assert(in != NULL); + in->in_prev = inclp; + in->in_buf = YY_CURRENT_BUFFER; + in->in_fname = yyfile; + in->in_lineno = yyline; + in->in_ateof = ateof; + inclp = in; + yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + yyfile = fname; + yyline = 0; + return (0); +} + +/* + * Terminate the most recent inclusion. + */ +static int +endinclude() +{ + struct incl *in; + int ateof; + + in = inclp; + assert(in != NULL); + inclp = in->in_prev; + lastfile = yyfile; + yy_delete_buffer(YY_CURRENT_BUFFER); + (void)fclose(yyin); + yy_switch_to_buffer(in->in_buf); + yyfile = in->in_fname; + yyline = in->in_lineno; + ateof = in->in_ateof; + free(in); + + return (ateof); +} diff --git a/usr.sbin/config/main.c b/usr.sbin/config/main.c index 3a0fff562687..2e528464db81 100644 --- a/usr.sbin/config/main.c +++ b/usr.sbin/config/main.c @@ -1,480 +1,481 @@ /* * 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. * 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. */ #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" #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; 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; while ((ch = getopt(argc, argv, "d:gp")) != -1) switch (ch) { 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(); if (freopen(PREFIX = *argv, "r", stdin) == NULL) err(2, "%s", 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 ((buf.st_mode & S_IFMT) != S_IFDIR) errx(2, "%s isn't a directory", p); dtab = NULL; + yyfile = *argv; if (yyparse()) exit(3); if (machinename == NULL) { printf("Specify machine type, e.g. ``machine i386''\n"); exit(1); } /* * make symbolic links in compilation directory * for "sys" (to make genassym.c work along with #include ) * and similarly for "machine". */ { char xxx[MAXPATHLEN]; if (*srcdir == '\0') (void)snprintf(xxx, sizeof(xxx), "../../include"); else (void)snprintf(xxx, sizeof(xxx), "%s/%s/include", srcdir, machinename); (void) symlink(xxx, path("machine")); } options(); /* make options .h files */ makefile(); /* build Makefile */ 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 a ``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 [-gp] [-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, "static 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"); for (fl = ftab; fl != NULL; fl = fl->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. */ dirp = opendir(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 (strcmp(dp->d_name, hl->h_name) == 0) { break; } } if (hl) continue; printf("Removing stale header: %s\n", dp->d_name); unlink(path(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 (strcmp(s, hl->h_name) == 0) { free(s); return; } } hl = malloc(sizeof(*hl)); bzero(hl, sizeof(*hl)); hl->h_name = s; hl->h_next = htab; htab = hl; }