diff --git a/usr.sbin/config/configvers.h b/usr.sbin/config/configvers.h --- a/usr.sbin/config/configvers.h +++ b/usr.sbin/config/configvers.h @@ -49,7 +49,7 @@ * * $FreeBSD$ */ -#define CONFIGVERS 600019 +#define CONFIGVERS 600020 #define MAJOR_VERS(x) ((x) / 100000) /* Last config(8) version to require envmode/hintmode */ diff --git a/usr.sbin/config/mkmakefile.c b/usr.sbin/config/mkmakefile.c --- a/usr.sbin/config/mkmakefile.c +++ b/usr.sbin/config/mkmakefile.c @@ -71,6 +71,15 @@ static const char keywords[] = { "!|()" }; +struct files; +typedef STAILQ_HEAD(,files) files_head_t; +typedef STAILQ_ENTRY(files) files_entry_t; + +struct files { + files_entry_t entry; + char *this; +}; + static void errout(const char *fmt, ...) { va_list ap; @@ -96,6 +105,38 @@ return (0); } +/* + * Add new file entry. + */ +static char * +fe_new(const char *fname, files_head_t *phead) +{ + struct files *pfe; + + pfe = malloc(sizeof(*pfe)); + pfe->this = ns(fname); + STAILQ_INSERT_TAIL(phead, pfe, entry); + return (pfe->this); +} + +/* + * Remove file entry. + */ +static char * +fe_get(files_head_t *phead) +{ + struct files *pfe; + char *retval; + + pfe = STAILQ_FIRST(phead); + if (pfe == NULL) + return (NULL); + STAILQ_REMOVE_HEAD(phead, entry); + retval = pfe->this; + free(pfe); + return (retval); +} + /* * Make a new file list entry */ @@ -392,12 +433,13 @@ read_file(char *fname) { char ifname[MAXPATHLEN]; - FILE *fp; + files_head_t fhead; struct file_list *tp; + FILE *fp; struct device *dp; struct opt *op; char *wd, *this, *compilewith, *depends, *clean, *warning; - const char *objprefix; + char *objprefix; int level; int filetype; bool std; @@ -414,8 +456,11 @@ fp = fopen(fname, "r"); if (fp == NULL) err(1, "%s", fname); + + STAILQ_INIT(&fhead); next: /* + * # this is a comment * include "filename" * filename [ standard | optional ] * [ dev* [ | dev* ... ] | [ no-obj ] @@ -452,13 +497,19 @@ ; goto next; } - this = ns(wd); +nextfile: + this = fe_new(wd, &fhead); wd = get_word(fp, keywords); if (wd == (char *)EOF) return; if (wd == NULL) errout("%s: No type for %s.\n", fname, this); - tp = fl_lookup(this); + if (eq(wd, "|")) { + wd = get_word(fp, NULL); + if (wd == (char *)EOF || wd == NULL) + errout("%s: No additional filename after %s.\n", fname, this); + goto nextfile; + } level = 0; /* reset logic state */ compile[level] = false; @@ -476,7 +527,7 @@ before_depend = false; nowerror = false; filetype = NORMAL; - objprefix = ""; + objprefix = NULL; if (eq(wd, "standard")) std = true; else if (!eq(wd, "optional")) @@ -624,32 +675,49 @@ errout("%s: unbalanced use of parenthesis\n", fname); compile[level] |= match[level]; - if (compile[level] && tp == NULL) { + if (compile[level]) { if (std == false && anyreqs[level] == false) errout("%s: what is %s optional on?\n", fname, this); - tp = new_fent(); - tp->f_fn = this; - tp->f_type = filetype; - if (filetype == LOCAL) - tp->f_srcprefix = ""; - else - tp->f_srcprefix = "$S/"; - if (imp_rule) - tp->f_flags |= NO_IMPLCT_RULE; - if (no_ctfconvert) - tp->f_flags |= NO_CTFCONVERT; - if (no_obj) - tp->f_flags |= NO_OBJ | NO_CTFCONVERT; - 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; - tp->f_objprefix = objprefix; + + while ((this = fe_get(&fhead)) != NULL) { + if (fl_lookup(this) != NULL) { + fprintf(stderr, "WARNING: %s is enabled more than once. Ignored line from %s\n", this, fname); + free(this); + continue; + } + tp = new_fent(); + tp->f_fn = this; + tp->f_type = filetype; + if (filetype == LOCAL) + tp->f_srcprefix = ""; + else + tp->f_srcprefix = "$S/"; + if (imp_rule) + tp->f_flags |= NO_IMPLCT_RULE; + if (no_ctfconvert) + tp->f_flags |= NO_CTFCONVERT; + if (no_obj) + tp->f_flags |= NO_OBJ | NO_CTFCONVERT; + 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; + tp->f_objprefix = objprefix ? objprefix : ""; + } + } else { + free(compilewith); + free(depends); + free(clean); + free(warning); + free(objprefix); + + while ((this = fe_get(&fhead)) != NULL) + free(this); } goto next; }