diff --git a/usr.bin/config/Makefile b/usr.bin/config/Makefile index e758b5a151bd..15a16cf6cc46 100644 --- a/usr.bin/config/Makefile +++ b/usr.bin/config/Makefile @@ -1,7 +1,8 @@ -# $NetBSD: Makefile,v 1.8 2007/05/13 20:22:45 veego Exp $ +# $NetBSD: Makefile,v 1.8.54.1 2015/03/06 21:00:23 snj Exp $ # from: @(#)Makefile 8.2 (Berkeley) 4/19/94 .include +WARNS=6 PROG= config SRCS= files.c gram.y hash.c lint.c main.c mkdevsw.c mkheaders.c mkioconf.c \ diff --git a/usr.bin/config/TODO b/usr.bin/config/TODO new file mode 100644 index 000000000000..cd65f6fc89d1 --- /dev/null +++ b/usr.bin/config/TODO @@ -0,0 +1,264 @@ +o Call module as module. + + Until now, everything is called as attribute. Separate module from it: + + - Module is a collection of code (*.[cSo]), and provides a function. + Module can depend on other modules. + + - Attribute provides metadata for modules. One module can have + multiple attributes. Attribute doesn't generate a module (*.o, + *.ko). + +o Emit everything (ioconf.*, Makefile, ...) per-attribute. + + config(9) related metadata (cfdriver, cfattach, cfdata, ...) should be + collected using linker. Create ELF sections like + .{rodata,data}.config.{cfdriver,cfattach,cfdata}. Provide reference + symbols (e.g. cfdriverinit[]) using linker script. Sort entries by name + to lookup entries by binary search in kernel. + +o Generate modular(9) related information. Especially module dependency. + + At this moment modular(9) modules hardcode dependency in *.c using the + MODULE() macro: + + MODULE(MODULE_CLASS_DRIVER, hdaudio, "pci"); + + This information already exists in config(5) definitions (files.*). + Extend config(5) to be able to specify module's class. + + Ideally these module metadata are kept somewhere in ELF headers, so that + loaders (e.g. boot(8)) can easily read. One idea is to abuse DYNAMIC + sections to record dependency, as shared library does. (Feasibility + unknown.) + +o Rename "interface attribute" to "bus". + + Instead of + + define audiobus {} + attach audio at audiobus + + Do like this + + defbus audiobus {} + attach audio at audiobus + +o Retire "attach foo at bar with foo_bar.c" + + Most of these should be rewritten by defining a common interface attribute + "foobus", instead of writing multiple attachments. com(4), ld(4), ehci(4) + are typical examples. For ehci(4), EHCI-capable controller drivers implement + "ehcibus" interface, like: + + defne ehcibus {} + device imxehci: ehcibus + + These drivers' attach functions call config_found() to attach ehci(4) via + the "ehcibus" interface attribute, instead of calling ehci_init() directly. + Same for com(4) (com_attach_subr()) and ld(4) (ldattach()). + +o Sort objects in more reasonable order. + + Put machdep.ko in the lowest address. uvm.ko and kern.ko follow. + + Kill alphabetical sort (${OBJS:O} in sys/conf/Makefile.inc.kern. + + Use ldscript. Do like this + + .text : + AT (ADDR(.text) & 0x0fffffff) + { + *(.text.machdep.locore.entry) + *(.text.machdep.locore) + *(.text.machdep) + *(.text) + *(.text.*) + : + + Kill linker definitions in sys/conf/Makefile.inc.kern. + +o Differentiate "options" and "flags"/"params". + + "options" enables features by adding *.c files (via attributes). + + "flags" and "params" are to change contents of *.c files. These don't add + *.c files to the result kernel, or don't build attributes (modules). + +o Make flags/params per attributes (modules). + + Basically flags and params are cpp(1) #define's generated in opt_*.h. Make + them local to one attributes (modules). Flags/params which affects files + across attributes (modules) are possible, but should be discouraged. + +o Generate things only by definitions. + + In the ideal dynamically modular world, "selection" will be done not at + compile time but at runtime. Users select their wanted modules, by + dynamically loading them. + + This means that the system provides all choices; that is, build all modules + in the source tree. Necessary information is defined in the "definition" + part. + +o Split cfdata. + + cfdata is a set of pattern matching rules to enable devices at runtime device + auto-configuration. It is pure data and can (should) be generated separately + from the code. + +o Allow easier adding and removing of options. + + It should be possible to add or remove options, flags, etc., + without regard to whether or not they are already defined. + For example, a configuration like this: + + include GENERIC + options FOO + no options BAR + + should work regardless of whether or not options FOO and/or + options BAR were defined in GENERIC. It should not give + errors like "options BAR was already defined" or "options FOO + was not defined". + +o Introduce "class". + + Every module should be classified as at least one class, as modular(9) + modules already do. For example, file systems are marked as "vfs", network + protocols are "netproto". + + Consider to merge "devclass" into "class". + + For syntax clarity, class names could be used as a keyword to select the + class's instance module: + + # Define net80211 module as netproto class + class netproto + define net80211: netproto + + # Select net80211 to be builtin + netproto net80211 + + Accordingly device/attach selection syntax should be revisited. + +o Support kernel constructor/destructor (.kctors/.kdtors) + + Initialization and finalization should be called via constructors and + destructors. Don't hardcode those sequences as sys/kern/init_main.c:main() + does. + + The order of .kctors/.kdtors is resolved by dependency. The difference from + userland is that in kernel depended ones are located in lower addresses; + "machdep" module is the lowest. Thus the lowest entry in .ctors must be + executed the first. + + The .kctors/.kdtors entries are executed by kernel's main() function, unlike + userland where start code executes .ctors/.dtors before main(). The hardcoded + sequence of various subsystem initializations in init_main.c:main() will be + replaced by an array of .kctors invocations, and #ifdef's there will be gone. + +o Hide link-set in the final kernel. + + Link-set is used to collect references (pointers) at link time. It relys on + the ld(1) behavior that it automatically generates `__start_X' and `__stop_X' + symbols for the section `X' to reduce coding. + + Don't allow kernel subsystems create random ELF sections. + + Pre-define all the available link-set names and pre-generate a linker script + to merge them into .rodata. + + (For modular(9) modules, `link_set_modules' is looked up by kernel loader. + Provide only it.) + + Provide a way for 3rd party modules to declare extra link-set. + +o Shared kernel objects. + + Since NetBSD has not established a clear kernel ABI, every single kernel + has to build all the objects by their own. As a result, similar kernels + (e.g. evbarm kernels) repeatedly compile similar objects, that is waste of + energy & space. + + Share them if possible. For evb* ports, ideally everything except machdep.ko + should be shared. + + While leaving optimizations as options (CPU specific optimizations, inlined + bus_space(9) operations, etc.) for users, the official binaries build + provided by TNF should be as portable as possible. + +o Control ELF sections using linker script. + + Now kernel is linked and built directly from object files (*.o). Each port + has an MD linker script, which does everything needed to be done at link + time. As a result, they do from MI alignment restriction (read_mostly, + cacheline_aligned) to load address specification for external boot loaders. + + Make this into multiple stages to make linkage more structural. Especially, + reserve the final link for purely MD purpose. Note that in modular build, + *.ko are shared between build of kernel and modular(9) modules (*.kmod). + + Monolithic build: + *.o ---> netbsd.ko Generic MI linkage + netbsd.ko ---> netbsd.ro Kernel MI linkage + netbsd.ro ---> netbsd Kernel MD linkage + + Modular build (kernel): + *.o ---> *.ko Generic + Per-module MI linkage + *.ko ---> netbsd.ro Kernel MI linkage + netbsd.ro ---> netbsd Kernel MD linkage + + Modular build (module): + *.o ---> *.ko Generic + Per-module MI linkage + *.ko ---> *.ro Modular MI linkage + *.ro ---> *.kmod Modular MD linkage + + Genric MI linkage is for processing MI linkage that can be applied generally. + Data section alignment (.data.read_mostly and .data.cacheline_aligned) is + processed here. + + Per-module MI linkage is for modules that want some ordering. For example, + machdep.ko wants to put entry code at the top of .text and .data. + + Kernel MI linkage is for collecting kernel global section data, that is what + link-set is used for now. Once they are collected and symbols to the ranges + are assigned, those sections are merged into the pre-existing sections + (.rodata) because link-set sections in "netbsd" will never be interpreted by + external loaders. + + Kernel MD linkage is used purely for MD purposes, that is, how kernels are + loaded by external loaders. It might be possible that one kernel relocatable + (netbsd.ro) is linked into multiple final kernel image (netbsd) for diferent + load addresses. + + Modular MI linkage is to prepare a module to be loadable as modular(9). This + may add some extra sections and/or symbols. + + Modular MD linkage is again for pure MD purposes like kernel MD linkage. + Adjustment and/or optimization may be done. + + Kernel and modular MI linkages may change behavior depending on existence + of debug information. In the future .symtab will be copied using linker + during this stage. + +o Redesign swapnetbsd.c (root/swap device specification) + + Don't build a whole kernel only to specify root/swap devices. + + Make these parameter re-configurable afterwards. + +o Namespace. + + Investigate namespace of attributes/modules/options. Figure out the hidden + design about these, document it, then re-design it. + + At this moment, all of them share the single "selecttab", which means their + namespaces are common, but they also have respective tables (attrtab, + opttab, etc.). + + Selecting an option (addoption()), that is also a module name, works only if + the module doesn't depend on anything, because addoption() doesn't select + module and its dependencies (selectattr()). In other words, an option is + only safely converted to a module (define), only if it doesn't depend on + anything. (One example is DDB.) diff --git a/usr.bin/config/config.1 b/usr.bin/config/config.1 index 288fe51417c8..957671561b98 100644 --- a/usr.bin/config/config.1 +++ b/usr.bin/config/config.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: config.1,v 1.15 2014/05/05 20:52:45 wiz Exp $ +.\" $NetBSD: config.1,v 1.15.2.1 2015/03/06 21:00:23 snj Exp $ .\" .\" Copyright (c) 1980, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)config.8 8.2 (Berkeley) 4/19/94 .\" -.Dd May 5, 2014 +.Dd October 10, 2014 .Dt CONFIG 1 .Os .Sh NAME @@ -37,7 +37,7 @@ .Nd build kernel compilation directories .Sh SYNOPSIS .Nm -.Op Fl Ppv +.Op Fl MPpv .Op Fl b Ar builddir .Op Fl D Ar var=value .Op Fl s Ar srcdir @@ -121,6 +121,12 @@ Generate a lint configuration. See section .Sx LINT CONFIGURATION for details. +.It Fl M +Do modular build (experimental). +Instead of linking all object files (*.o) at once, collect related object +files into an intermediate relocatable object (*.ko), then link those *.ko +files into the final kernel. +This changes the order of objects in the kernel binary. .It Fl P Pack locators to save space in the resulting kernel binary. The amount of space saved that way is so small that this option should diff --git a/usr.bin/config/config.5 b/usr.bin/config/config.5 index 1278d8d5bc4f..f2ca420869a6 100644 --- a/usr.bin/config/config.5 +++ b/usr.bin/config/config.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: config.5,v 1.24 2014/05/29 08:13:17 wiz Exp $ +.\" $NetBSD: config.5,v 1.24.2.1 2015/03/06 21:00:23 snj Exp $ .\" .\" Copyright (c) 2006, 2007 The NetBSD Foundation. .\" All rights reserved. @@ -24,7 +24,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd May 29, 2014 +.Dd October 30, 2014 .Dt CONFIG 5 .Os .Sh NAME @@ -620,8 +620,10 @@ Un-selects the option If option .Ar name has not been previously selected, the statement produces an error. -.It Oo Ic no Oc Ic file-system Ar name Op , Ar name Op , Ar ... -Adds or removes support for all the listed file-systems. +.It Ic file-system Ar name Op , Ar name Op , Ar ... +Adds support for all the listed file-systems. +.It Ic no file-system Ar name Op , Ar name Op , Ar ... +Removes support for all the listed file-systems. .It Ic config Ar name Ic root on Ar device Oo Ic type Ar fs Oc Op Ic dumps on \ Ar device Adds @@ -696,6 +698,10 @@ again. .It Ic no makeoptions Ar name Op , Ar name Op , Ar ... Removes one or more definitions from the generated .Pa Makefile . +.It Ic select Ar name +Adds the specified attribute and its dependencies. +.It Ic no select Ar name +Removes the specified attribute and all the attributes which depend on it. .El .Sh FILES The files are relative to the kernel source top directory (e.g., diff --git a/usr.bin/config/defs.h b/usr.bin/config/defs.h index 412a53dc3d83..7ba8606d7eee 100644 --- a/usr.bin/config/defs.h +++ b/usr.bin/config/defs.h @@ -1,4 +1,4 @@ -/* $NetBSD: defs.h,v 1.45 2014/05/05 19:08:13 martin Exp $ */ +/* $NetBSD: defs.h,v 1.45.2.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -107,7 +107,7 @@ extern const char *progname; * The next two lines define the current version of the config(1) binary, * and the minimum version of the configuration files it supports. */ -#define CONFIG_VERSION 20140502 +#define CONFIG_VERSION 20141030 #define CONFIG_MINVERSION 0 /* @@ -149,6 +149,19 @@ struct defoptlist { struct nvlist *dl_depends; }; +struct module { + const char *m_name; +#if 1 + struct attrlist *m_deps; +#else + struct attrlist *m_attrs; + struct modulelist *m_deps; +#endif + int m_expanding; + TAILQ_HEAD(, files) m_files; + int m_weight; +}; + /* * Attributes. These come in three flavors: "plain", "device class," * and "interface". Plain attributes (e.g., "ether") simply serve @@ -165,15 +178,23 @@ struct defoptlist { * SCSI host adapter drivers such as the SPARC "esp"). */ struct attr { - const char *a_name; /* name of this attribute */ + /* XXX */ + struct module a_m; +#define a_name a_m.m_name +#define a_deps a_m.m_deps +#define a_expanding a_m.m_expanding +#define a_files a_m.m_files +#define a_weight a_m.m_weight + + /* "interface attribute" */ int a_iattr; /* true => allows children */ - const char *a_devclass; /* device class described */ struct loclist *a_locs; /* locators required */ int a_loclen; /* length of above list */ struct nvlist *a_devs; /* children */ struct nvlist *a_refs; /* parents */ - struct attrlist *a_deps; /* we depend on these other attrs */ - int a_expanding; /* to detect cycles in attr graph */ + + /* "device class" */ + const char *a_devclass; /* device class described */ }; /* @@ -299,8 +320,8 @@ struct devi { /* created during packing or ioconf.c generation */ short i_collapsed; /* set => this alias no longer needed */ - short i_cfindex; /* our index in cfdata */ - short i_locoff; /* offset in locators.vec */ + u_short i_cfindex; /* our index in cfdata */ + int i_locoff; /* offset in locators.vec */ }; /* special units */ @@ -319,10 +340,12 @@ struct filetype char fit_lastc; /* last char from path */ const char *fit_path; /* full file path */ const char *fit_prefix; /* any file prefix */ + size_t fit_len; /* path string length */ + int fit_suffix; /* single char suffix */ + struct attr *fit_attr; /* owner attr */ + TAILQ_ENTRY(files) fit_anext; /* next file in attr */ }; /* Anything less than 0x10 is sub-type specific */ -#define FIT_NOPROLOGUE 0x10 /* Don't prepend $S/ */ -#define FIT_FORCESELECT 0x20 /* Always include this file */ /* * Files. Each file is either standard (always included) or optional, @@ -350,6 +373,10 @@ struct files { #define fi_lastc fi_fit.fit_lastc #define fi_path fi_fit.fit_path #define fi_prefix fi_fit.fit_prefix +#define fi_suffix fi_fit.fit_suffix +#define fi_len fi_fit.fit_len +#define fi_attr fi_fit.fit_attr +#define fi_anext fi_fit.fit_anext /* flags */ #define FI_SEL 0x01 /* selected */ @@ -476,6 +503,7 @@ struct dlhash *defoptlint; /* lint values for options */ struct nvhash *deffstab; /* defined file systems */ struct dlhash *optfiletab; /* "defopt"'d option .h files */ struct hashtab *attrtab; /* attributes (locators, etc.) */ +struct hashtab *attrdeptab; /* attribute dependencies */ struct hashtab *bdevmtab; /* block devm lookup */ struct hashtab *cdevmtab; /* character devm lookup */ @@ -502,6 +530,7 @@ SLIST_HEAD(, prefix) prefixes, /* prefix stack */ allprefixes; /* all prefixes used (after popped) */ SLIST_HEAD(, prefix) curdirs; /* curdir stack */ +extern struct attr allattr; struct devi **packed; /* arrayified table for packed devi's */ size_t npacked; /* size of packed table, <= ndevi */ @@ -521,21 +550,27 @@ void checkfiles(void); int fixfiles(void); /* finalize */ int fixobjects(void); int fixdevsw(void); -void addfile(const char *, struct condexpr *, int, const char *); -void addobject(const char *, struct condexpr *, int); +void addfile(const char *, struct condexpr *, u_char, const char *); +void addobject(const char *, struct condexpr *, u_char); int expr_eval(struct condexpr *, int (*)(const char *, void *), void *); /* hash.c */ struct hashtab *ht_new(void); void ht_free(struct hashtab *); +int ht_insrep2(struct hashtab *, const char *, const char *, void *, int); int ht_insrep(struct hashtab *, const char *, void *, int); +#define ht_insert2(ht, nam1, nam2, val) ht_insrep2(ht, nam1, nam2, val, 0) #define ht_insert(ht, nam, val) ht_insrep(ht, nam, val, 0) #define ht_replace(ht, nam, val) ht_insrep(ht, nam, val, 1) +int ht_remove2(struct hashtab *, const char *, const char *); int ht_remove(struct hashtab *, const char *); +void *ht_lookup2(struct hashtab *, const char *, const char *); void *ht_lookup(struct hashtab *, const char *); void initintern(void); const char *intern(const char *); +typedef int (*ht_callback2)(const char *, const char *, void *, void *); typedef int (*ht_callback)(const char *, void *, void *); +int ht_enumerate2(struct hashtab *, ht_callback2, void *); int ht_enumerate(struct hashtab *, ht_callback, void *); /* typed hash, named struct HT, whose type is string -> struct VT */ @@ -558,6 +593,7 @@ void emit_options(void); void emit_params(void); /* main.c */ +extern int Mflag; void addoption(const char *, const char *); void addfsoption(const char *); void addmkoption(const char *, const char *); @@ -609,7 +645,7 @@ int mkswap(void); void pack(void); /* scan.l */ -int currentline(void); +u_short currentline(void); int firstfile(const char *); void package(const char *); int include(const char *, int, int, int); @@ -622,6 +658,11 @@ int onlist(struct nvlist *, void *); void prefix_push(const char *); void prefix_pop(void); char *sourcepath(const char *); +extern int dflag; +#define CFGDBG(n, ...) \ + do { if ((dflag) >= (n)) cfgdbg(__VA_ARGS__); } while (0) +void cfgdbg(const char *, ...) /* debug info */ + __printflike(1, 2); void cfgwarn(const char *, ...) /* immediate warns */ __printflike(1, 2); void cfgxwarn(const char *, int, const char *, ...) /* delayed warns */ diff --git a/usr.bin/config/files.c b/usr.bin/config/files.c index bbddfb3723d0..a2eea37e718f 100644 --- a/usr.bin/config/files.c +++ b/usr.bin/config/files.c @@ -1,4 +1,4 @@ -/* $NetBSD: files.c,v 1.12 2014/05/21 05:25:34 dholland Exp $ */ +/* $NetBSD: files.c,v 1.12.2.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,6 +44,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: files.c,v 1.12.2.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -65,6 +68,7 @@ static struct hashtab *pathtab; /* full path names */ static struct files **unchecked; +static void addfiletoattr(const char *, struct files *); static int checkaux(const char *, void *); static int fixcount(const char *, void *); static int fixfsel(const char *, void *); @@ -82,7 +86,7 @@ initfiles(void) } void -addfile(const char *path, struct condexpr *optx, int flags, const char *rule) +addfile(const char *path, struct condexpr *optx, u_char flags, const char *rule) { struct files *fi; const char *dotp, *tail; @@ -111,7 +115,7 @@ addfile(const char *path, struct condexpr *optx, int flags, const char *rule) tail++; dotp = strrchr(tail, '.'); if (dotp == NULL || dotp[1] == 0 || - (baselen = dotp - tail) >= sizeof(base)) { + (baselen = (size_t)(dotp - tail)) >= sizeof(base)) { cfgerror("invalid pathname `%s'", path); goto bad; } @@ -154,9 +158,12 @@ addfile(const char *path, struct condexpr *optx, int flags, const char *rule) fi->fi_base = intern(base); fi->fi_prefix = SLIST_EMPTY(&prefixes) ? NULL : SLIST_FIRST(&prefixes)->pf_prefix; + fi->fi_len = strlen(path); + fi->fi_suffix = path[fi->fi_len - 1]; fi->fi_optx = optx; fi->fi_optf = NULL; fi->fi_mkrule = rule; + fi->fi_attr = NULL; TAILQ_INSERT_TAIL(&allfiles, fi, fi_next); return; bad: @@ -166,7 +173,7 @@ addfile(const char *path, struct condexpr *optx, int flags, const char *rule) } void -addobject(const char *path, struct condexpr *optx, int flags) +addobject(const char *path, struct condexpr *optx, u_char flags) { struct objects *oi; @@ -195,6 +202,20 @@ addobject(const char *path, struct condexpr *optx, int flags) return; } +static void +addfiletoattr(const char *name, struct files *fi) +{ + struct attr *a; + + a = ht_lookup(attrtab, name); + if (a == NULL) { + CFGDBG(1, "attr `%s' not found", name); + } else { + fi->fi_attr = a; + TAILQ_INSERT_TAIL(&a->a_files, fi, fi_anext); + } +} + /* * We have finished reading some "files" file, either ../../conf/files * or ./files.$machine. Make sure that everything that is flagged as @@ -254,12 +275,10 @@ fixfiles(void) if (fi->fi_flags & FI_HIDDEN) continue; - /* Optional: see if it is to be included. */ - if (fi->fi_flags & FIT_FORCESELECT) - { - /* include it */ ; - } - else if (fi->fi_optx != NULL) { + if (fi->fi_optx != NULL) { + if (fi->fi_optx->cx_type == CX_ATOM) { + addfiletoattr(fi->fi_optx->cx_u.atom, fi); + } flathead = NULL; flatp = &flathead; sel = expr_eval(fi->fi_optx, @@ -284,7 +303,7 @@ fixfiles(void) if (ht_replace(basetab, fi->fi_base, fi) != 1) panic("fixfiles ht_replace(%s)", fi->fi_base); - ofi->fi_flags &= ~FI_SEL; + ofi->fi_flags &= (u_char)~FI_SEL; ofi->fi_flags |= FI_HIDDEN; } else { cfgxerror(fi->fi_srcfile, fi->fi_srcline, @@ -297,6 +316,14 @@ fixfiles(void) } } fi->fi_flags |= FI_SEL; + CFGDBG(3, "file selected `%s'", fi->fi_path); + + /* Add other files to the default "netbsd" attribute. */ + if (fi->fi_attr == NULL) { + addfiletoattr(allattr.a_name, fi); + } + CFGDBG(3, "file `%s' belongs to attr `%s'", fi->fi_path, + fi->fi_attr->a_name); } return (err); } diff --git a/usr.bin/config/gram.y b/usr.bin/config/gram.y index 6f8cc4af534e..b4981995b09b 100644 --- a/usr.bin/config/gram.y +++ b/usr.bin/config/gram.y @@ -1,5 +1,5 @@ %{ -/* $NetBSD: gram.y,v 1.39 2014/05/29 07:47:45 mrg Exp $ */ +/* $NetBSD: gram.y,v 1.39.2.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -41,6 +41,9 @@ * from: @(#)gram.y 8.1 (Berkeley) 6/6/93 */ +#include +__RCSID("$NetBSD: gram.y,v 1.39.2.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -159,6 +162,9 @@ static struct loclist *namelocvals(const char *, struct loclist *); const char *str; struct numconst num; int64_t val; + u_char flag; + devmajor_t devmajor; + int32_t i32; } %token AND AT ATTACH @@ -175,7 +181,7 @@ static struct loclist *namelocvals(const char *, struct loclist *); %token XOBJECT OBSOLETE ON OPTIONS %token PACKAGE PLUSEQ PREFIX PSEUDO_DEVICE PSEUDO_ROOT %token ROOT -%token SINGLE SOURCE +%token SELECT SINGLE SOURCE %token TYPE %token VECTOR VERSION %token WITH @@ -187,7 +193,7 @@ static struct loclist *namelocvals(const char *, struct loclist *); %type cond_or_expr cond_and_expr cond_prefix_expr %type cond_base_expr %type fs_spec -%type fflags fflag oflags oflag +%type fflags fflag oflags oflag %type rule %type depend %type devbase @@ -204,9 +210,9 @@ static struct loclist *namelocvals(const char *, struct loclist *); %type device_instance %type attachment %type value -%type major_minor npseudo +%type major_minor %type signed_number -%type device_flags +%type int32 npseudo device_flags %type deffs %type deffses %type defopt @@ -217,13 +223,13 @@ static struct loclist *namelocvals(const char *, struct loclist *); %type optfile_opt %type subarches %type filename stringvalue locname mkvarname -%type device_major_block device_major_char +%type device_major_block device_major_char %type devnodes devnodetype devnodeflags devnode_dims %% /* - * A complete configuration consists of both the configuration part (a + * A complete configuration consists of both the selection part (a * kernel config such as GENERIC or SKYNET, plus also the various * std.* files), which selects the material to be in the kernel, and * also the definition part (files, files.*, etc.) that declares what @@ -254,7 +260,7 @@ static struct loclist *namelocvals(const char *, struct loclist *); /* Complete configuration. */ configuration: - topthings machine_spec definition_part configuration_part + topthings machine_spec definition_part selection_part ; /* Sequence of zero or more topthings. */ @@ -307,46 +313,134 @@ definitions: /* A single definition. */ definition: - file - | object - | device_major { do_devsw = 1; } - | prefix - | DEVCLASS WORD { (void)defattr($2, NULL, NULL, 1); } - | DEFFS deffses optdepend_list { deffilesystem($2, $3); } - | DEFINE WORD interface_opt depend_list - { (void)defattr($2, $3, $4, 0); } - | DEFOPT optfile_opt defopts optdepend_list - { defoption($2, $3, $4); } - | DEFFLAG optfile_opt defopts optdepend_list - { defflag($2, $3, $4, 0); } - | OBSOLETE DEFFLAG optfile_opt defopts - { defflag($3, $4, NULL, 1); } - | DEFPARAM optfile_opt defopts optdepend_list - { defparam($2, $3, $4, 0); } - | OBSOLETE DEFPARAM optfile_opt defopts - { defparam($3, $4, NULL, 1); } - | DEVICE devbase interface_opt depend_list - { defdev($2, $3, $4, 0); } - | ATTACH devbase AT atlist devattach_opt depend_list - { defdevattach($5, $2, $4, $6); } - | MAXPARTITIONS NUMBER { maxpartitions = $2.val; } - | MAXUSERS NUMBER NUMBER NUMBER - { setdefmaxusers($2.val, $3.val, $4.val); } - | MAKEOPTIONS condmkopt_list - /* interface_opt in DEFPSEUDO is for backwards compatibility */ - | DEFPSEUDO devbase interface_opt depend_list - { defdev($2, $3, $4, 1); } - | DEFPSEUDODEV devbase interface_opt depend_list - { defdev($2, $3, $4, 2); } - | MAJOR '{' majorlist '}' - | VERSION NUMBER { setversion($2.val); } + define_file + | define_object + | define_device_major + | define_prefix + | define_devclass + | define_filesystems + | define_attribute + | define_option + | define_flag + | define_obsolete_flag + | define_param + | define_obsolete_param + | define_device + | define_device_attachment + | define_maxpartitions + | define_maxusers + | define_makeoptions + | define_pseudo + | define_pseudodev + | define_major + | define_version ; /* source file: file foo/bar.c bar|baz needs-flag compile-with blah */ -file: +define_file: XFILE filename fopts fflags rule { addfile($2, $3, $4, $5); } ; +/* object file: object zot.o foo|zot needs-flag */ +define_object: + XOBJECT filename fopts oflags { addobject($2, $3, $4); } +; + +/* device major declaration */ +define_device_major: + DEVICE_MAJOR WORD device_major_char device_major_block fopts devnodes + { + adddevm($2, $3, $4, $5, $6); + do_devsw = 1; + } +; + +/* prefix delimiter */ +define_prefix: + PREFIX filename { prefix_push($2); } + | PREFIX { prefix_pop(); } +; + +define_devclass: + DEVCLASS WORD { (void)defdevclass($2, NULL, NULL, 1); } +; + +define_filesystems: + DEFFS deffses optdepend_list { deffilesystem($2, $3); } +; + +define_attribute: + DEFINE WORD interface_opt depend_list + { (void)defattr0($2, $3, $4, 0); } +; + +define_option: + DEFOPT optfile_opt defopts optdepend_list + { defoption($2, $3, $4); } +; + +define_flag: + DEFFLAG optfile_opt defopts optdepend_list + { defflag($2, $3, $4, 0); } +; + +define_obsolete_flag: + OBSOLETE DEFFLAG optfile_opt defopts + { defflag($3, $4, NULL, 1); } +; + +define_param: + DEFPARAM optfile_opt defopts optdepend_list + { defparam($2, $3, $4, 0); } +; + +define_obsolete_param: + OBSOLETE DEFPARAM optfile_opt defopts + { defparam($3, $4, NULL, 1); } +; + +define_device: + DEVICE devbase interface_opt depend_list + { defdev($2, $3, $4, 0); } +; + +define_device_attachment: + ATTACH devbase AT atlist devattach_opt depend_list + { defdevattach($5, $2, $4, $6); } +; + +define_maxpartitions: + MAXPARTITIONS int32 { maxpartitions = $2; } +; + +define_maxusers: + MAXUSERS int32 int32 int32 + { setdefmaxusers($2, $3, $4); } +; + +define_makeoptions: + MAKEOPTIONS condmkopt_list +; + +define_pseudo: + /* interface_opt in DEFPSEUDO is for backwards compatibility */ + DEFPSEUDO devbase interface_opt depend_list + { defdev($2, $3, $4, 1); } +; + +define_pseudodev: + DEFPSEUDODEV devbase interface_opt depend_list + { defdev($2, $3, $4, 2); } +; + +define_major: + MAJOR '{' majorlist '}' +; + +define_version: + VERSION int32 { setversion($2); } +; + /* file options: optional expression of conditions */ fopts: /* empty */ { $$ = NULL; } @@ -371,11 +465,6 @@ rule: | COMPILE_WITH stringvalue { $$ = $2; } ; -/* object file: object zot.o foo|zot needs-flag */ -object: - XOBJECT filename fopts oflags { addobject($2, $3, $4); } -; - /* zero or more flags for an object file */ oflags: /* empty */ { $$ = 0; } @@ -387,22 +476,16 @@ oflag: NEEDS_FLAG { $$ = OI_NEEDSFLAG; } ; -/* device major declaration */ -device_major: - DEVICE_MAJOR WORD device_major_char device_major_block fopts devnodes - { adddevm($2, $3, $4, $5, $6); } -; - /* char 55 */ device_major_char: /* empty */ { $$ = -1; } - | CHAR NUMBER { $$ = $2.val; } + | CHAR int32 { $$ = $2; } ; /* block 33 */ device_major_block: /* empty */ { $$ = -1; } - | BLOCK NUMBER { $$ = $2.val; } + | BLOCK int32 { $$ = $2; } ; /* device node specification */ @@ -435,12 +518,6 @@ devnodeflags: LINKZERO { $$ = new_s("DEVNODE_FLAG_LINKZERO");} ; -/* prefix delimiter */ -prefix: - PREFIX filename { prefix_push($2); } - | PREFIX { prefix_pop(); } -; - /* one or more file system names */ deffses: deffs { $$ = new_n($1); } @@ -479,11 +556,11 @@ locdef: locname locdefault { $$ = MK3(loc, $1, $2, 0); } | locname { $$ = MK3(loc, $1, NULL, 0); } | '[' locname locdefault ']' { $$ = MK3(loc, $2, $3, 1); } - | locname '[' NUMBER ']' { $$ = locarray($1, $3.val, NULL, 0); } - | locname '[' NUMBER ']' locdefaults - { $$ = locarray($1, $3.val, $5, 0); } - | '[' locname '[' NUMBER ']' locdefaults ']' - { $$ = locarray($2, $4.val, $6, 1); } + | locname '[' int32 ']' { $$ = locarray($1, $3, NULL, 0); } + | locname '[' int32 ']' locdefaults + { $$ = locarray($1, $3, $5, 0); } + | '[' locname '[' int32 ']' locdefaults ']' + { $$ = locarray($2, $4, $6, 1); } ; /* locator name */ @@ -516,7 +593,7 @@ depends: /* one depend item (which is an attribute) */ depend: - WORD { $$ = getattr($1); } + WORD { $$ = refattr($1); } ; /* list of option depends, may be empty */ @@ -594,51 +671,142 @@ majorlist: /* one major number */ majordef: - devbase '=' NUMBER { setmajor($1, $3.val); } + devbase '=' int32 { setmajor($1, $3); } +; + +int32: + NUMBER { + if ($1.val > INT_MAX || $1.val < INT_MIN) + cfgerror("overflow %" PRId64, $1.val); + else + $$ = (int32_t)$1.val; + } ; /************************************************************/ /* - * The configuration grammar. + * The selection grammar. */ -/* Complete configuration part: all std.* files plus selected config. */ -configuration_part: - config_items +/* Complete selection part: all std.* files plus selected config. */ +selection_part: + selections ; /* Zero or more config items. Trap errors. */ -config_items: +selections: /* empty */ - | config_items '\n' - | config_items config_item '\n' { wrap_continue(); } - | config_items error '\n' { wrap_cleanup(); } + | selections '\n' + | selections selection '\n' { wrap_continue(); } + | selections error '\n' { wrap_cleanup(); } ; /* One config item. */ -config_item: +selection: definition - | NO FILE_SYSTEM no_fs_list - | FILE_SYSTEM fs_list - | NO MAKEOPTIONS no_mkopt_list - | MAKEOPTIONS mkopt_list - | NO OPTIONS no_opt_list - | OPTIONS opt_list - | MAXUSERS NUMBER { setmaxusers($2.val); } - | IDENT stringvalue { setident($2); } - | NO IDENT { setident(NULL); } - | CONFIG conf root_spec sysparam_list + | select_attr + | select_no_attr + | select_no_filesystems + | select_filesystems + | select_no_makeoptions + | select_makeoptions + | select_no_options + | select_options + | select_maxusers + | select_ident + | select_no_ident + | select_config + | select_no_config + | select_no_pseudodev + | select_pseudodev + | select_pseudoroot + | select_no_device_instance_attachment + | select_no_device_attachment + | select_no_device_instance + | select_device_instance +; + +select_attr: + SELECT WORD { addattr($2); } +; + +select_no_attr: + NO SELECT WORD { delattr($3); } +; + +select_no_filesystems: + NO FILE_SYSTEM no_fs_list +; + +select_filesystems: + FILE_SYSTEM fs_list +; + +select_no_makeoptions: + NO MAKEOPTIONS no_mkopt_list +; + +select_makeoptions: + MAKEOPTIONS mkopt_list +; + +select_no_options: + NO OPTIONS no_opt_list +; + +select_options: + OPTIONS opt_list +; + +select_maxusers: + MAXUSERS int32 { setmaxusers($2); } +; + +select_ident: + IDENT stringvalue { setident($2); } +; + +select_no_ident: + NO IDENT { setident(NULL); } +; + +select_config: + CONFIG conf root_spec sysparam_list { addconf(&conf); } - | NO CONFIG WORD { delconf($3); } - | NO PSEUDO_DEVICE WORD { delpseudo($3); } - | PSEUDO_DEVICE WORD npseudo { addpseudo($2, $3); } - | PSEUDO_ROOT device_instance { addpseudoroot($2); } - | NO device_instance AT attachment +; + +select_no_config: + NO CONFIG WORD { delconf($3); } +; + +select_no_pseudodev: + NO PSEUDO_DEVICE WORD { delpseudo($3); } +; + +select_pseudodev: + PSEUDO_DEVICE WORD npseudo { addpseudo($2, $3); } +; + +select_pseudoroot: + PSEUDO_ROOT device_instance { addpseudoroot($2); } +; + +select_no_device_instance_attachment: + NO device_instance AT attachment { deldevi($2, $4); } - | NO DEVICE AT attachment { deldeva($4); } - | NO device_instance { deldev($2); } - | device_instance AT attachment locators device_flags +; + +select_no_device_attachment: + NO DEVICE AT attachment { deldeva($4); } +; + +select_no_device_instance: + NO device_instance { deldev($2); } +; + +select_device_instance: + device_instance AT attachment locators device_flags { adddev($1, $3, $4, $5); } ; @@ -731,14 +899,16 @@ root_spec: /* device for root fs or dump */ dev_spec: - '?' { $$ = new_si(intern("?"), NODEV); } - | WORD { $$ = new_si($1, NODEV); } + '?' { $$ = new_si(intern("?"), + (long long)NODEV); } + | WORD { $$ = new_si($1, + (long long)NODEV); } | major_minor { $$ = new_si(NULL, $1); } ; /* major and minor device number */ major_minor: - MAJOR NUMBER MINOR NUMBER { $$ = makedev($2.val, $4.val); } + MAJOR NUMBER MINOR NUMBER { $$ = (int64_t)makedev($2.val, $4.val); } ; /* filesystem type for root fs specification */ @@ -761,7 +931,7 @@ sysparam: /* number of pseudo devices to configure (which is optional) */ npseudo: /* empty */ { $$ = 1; } - | NUMBER { $$ = $1.val; } + | int32 { $$ = $1; } ; /* name of a device to configure */ @@ -792,7 +962,7 @@ locator: /* optional device flags */ device_flags: /* empty */ { $$ = 0; } - | FLAGS NUMBER { $$ = $2.val; } + | FLAGS int32 { $$ = $2; } ; /************************************************************/ diff --git a/usr.bin/config/hash.c b/usr.bin/config/hash.c index c19880057b3d..04e926cd7521 100644 --- a/usr.bin/config/hash.c +++ b/usr.bin/config/hash.c @@ -1,4 +1,4 @@ -/* $NetBSD: hash.c,v 1.8 2012/03/12 02:58:55 dholland Exp $ */ +/* $NetBSD: hash.c,v 1.8.10.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,6 +44,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: hash.c,v 1.8.10.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -58,15 +61,18 @@ struct hashent { // XXXLUKEM: a SIMPLEQ might be more appropriate TAILQ_ENTRY(hashent) h_next; - const char *h_name; /* the string */ + const char *h_names[2]; /* the string */ +#define h_name1 h_names[0] +#define h_name2 h_names[1] +#define h_name h_name1 u_int h_hash; /* its hash value */ void *h_value; /* other values (for name=value) */ }; struct hashtab { size_t ht_size; /* size (power of 2) */ - u_int ht_mask; /* == ht_size - 1 */ - u_int ht_used; /* number of entries used */ - u_int ht_lim; /* when to expand */ + size_t ht_mask; /* == ht_size - 1 */ + size_t ht_used; /* number of entries used */ + size_t ht_lim; /* when to expand */ TAILQ_HEAD(hashenthead, hashent) *ht_tab; }; @@ -81,7 +87,8 @@ static struct hashtab strings; static void ht_expand(struct hashtab *); static void ht_init(struct hashtab *, size_t); -static inline u_int hash(const char *); +static inline u_int hash(u_int, const char *); +static inline u_int hash2(u_int, const char *, const char *); static inline struct hashent *newhashent(const char *, u_int); /* @@ -109,7 +116,7 @@ ht_expand(struct hashtab *ht) { struct hashenthead *h, *oldh; struct hashent *p; - u_int n, i; + size_t n, i; n = ht->ht_size * 2; h = emalloc(n * sizeof *h); @@ -137,27 +144,51 @@ ht_expand(struct hashtab *ht) * otherwise allocate a new entry. */ static inline struct hashent * -newhashent(const char *name, u_int h) +newhashent2(const char *name1, const char *name2, u_int h) { struct hashent *hp; hp = ecalloc(1, sizeof(*hp)); - hp->h_name = name; + hp->h_name1 = name1; + hp->h_name2 = name2; hp->h_hash = h; return (hp); } +static inline struct hashent * +newhashent(const char *name, u_int h) +{ + return newhashent2(name, NULL, h); +} + +static inline u_int +hv(u_int h, char c) +{ + return (h << 5) + h + (unsigned char)c; +} + /* * Hash a string. */ static inline u_int -hash(const char *str) +hash(u_int h, const char *str) { - u_int h; - for (h = 0; *str;) - h = (h << 5) + h + *str++; + while (str && *str) + h = hv(h, *str++); + return (h); +} + +#define HASH2DELIM ' ' + +static inline u_int +hash2(u_int h, const char *str1, const char *str2) +{ + + h = hash(h, str1); + h = hv(h, HASH2DELIM); + h = hash(h, str2); return (h); } @@ -182,7 +213,7 @@ intern(const char *s) char *p; ht = &strings; - h = hash(s); + h = hash2(0, s, NULL); hpp = &ht->ht_tab[h & ht->ht_mask]; TAILQ_FOREACH(hp, hpp, h_next) { if (hp->h_hash == h && strcmp(hp->h_name, s) == 0) @@ -231,22 +262,23 @@ ht_free(struct hashtab *ht) * Insert and/or replace. */ int -ht_insrep(struct hashtab *ht, const char *nam, void *val, int replace) +ht_insrep2(struct hashtab *ht, const char *nam1, const char *nam2, void *val, int replace) { struct hashent *hp; struct hashenthead *hpp; u_int h; - h = hash(nam); + h = hash2(0, nam1, nam2); hpp = &ht->ht_tab[h & ht->ht_mask]; TAILQ_FOREACH(hp, hpp, h_next) { - if (hp->h_name == nam) { + if (hp->h_name1 == nam1 && + hp->h_name2 == nam2) { if (replace) hp->h_value = val; return (1); } } - hp = newhashent(nam, h); + hp = newhashent2(nam1, nam2, h); TAILQ_INSERT_TAIL(hpp, hp, h_next); hp->h_value = val; if (++ht->ht_used > ht->ht_lim) @@ -254,21 +286,27 @@ ht_insrep(struct hashtab *ht, const char *nam, void *val, int replace) return (0); } +int +ht_insrep(struct hashtab *ht, const char *nam, void *val, int replace) +{ + return ht_insrep2(ht, nam, NULL, val, replace); +} + /* * Remove. */ int -ht_remove(struct hashtab *ht, const char *name) +ht_remove2(struct hashtab *ht, const char *name1, const char *name2) { struct hashent *hp; struct hashenthead *hpp; u_int h; - h = hash(name); + h = hash2(0, name1, name2); hpp = &ht->ht_tab[h & ht->ht_mask]; TAILQ_FOREACH(hp, hpp, h_next) { - if (hp->h_name != name) + if (hp->h_name1 != name1 || hp->h_name2 != name2) continue; TAILQ_REMOVE(hpp, hp, h_next); @@ -279,27 +317,55 @@ ht_remove(struct hashtab *ht, const char *name) return (1); } +int +ht_remove(struct hashtab *ht, const char *name) +{ + return ht_remove2(ht, name, NULL); +} + void * -ht_lookup(struct hashtab *ht, const char *nam) +ht_lookup2(struct hashtab *ht, const char *nam1, const char *nam2) { struct hashent *hp; struct hashenthead *hpp; u_int h; - h = hash(nam); + h = hash2(0, nam1, nam2); hpp = &ht->ht_tab[h & ht->ht_mask]; TAILQ_FOREACH(hp, hpp, h_next) - if (hp->h_name == nam) + if (hp->h_name == nam1) return (hp->h_value); return (NULL); } +void * +ht_lookup(struct hashtab *ht, const char *nam) +{ + return ht_lookup2(ht, nam, NULL); +} + /* * first parameter to callback is the entry name from the hash table * second parameter is the value from the hash table * third argument is passed through from the "arg" parameter to ht_enumerate() */ +int +ht_enumerate2(struct hashtab *ht, ht_callback2 cbfunc2, void *arg) +{ + struct hashent *hp; + struct hashenthead *hpp; + size_t i; + int rval = 0; + + for (i = 0; i < ht->ht_size; i++) { + hpp = &ht->ht_tab[i]; + TAILQ_FOREACH(hp, hpp, h_next) + rval += (*cbfunc2)(hp->h_name1, hp->h_name2, hp->h_value, arg); + } + return rval; +} + int ht_enumerate(struct hashtab *ht, ht_callback cbfunc, void *arg) { diff --git a/usr.bin/config/lint.c b/usr.bin/config/lint.c index 4ac7c1a7bcda..cacfb162ba82 100644 --- a/usr.bin/config/lint.c +++ b/usr.bin/config/lint.c @@ -1,4 +1,4 @@ -/* $NetBSD: lint.c,v 1.14 2012/03/20 20:34:57 matt Exp $ */ +/* $NetBSD: lint.c,v 1.14.10.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 2007 The NetBSD Foundation. @@ -30,6 +30,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: lint.c,v 1.14.10.1 2015/03/06 21:00:23 snj Exp $"); + #include #include diff --git a/usr.bin/config/main.c b/usr.bin/config/main.c index efe690bc50f5..e26e7c6e7f1b 100644 --- a/usr.bin/config/main.c +++ b/usr.bin/config/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.54 2014/08/09 12:40:14 bad Exp $ */ +/* $NetBSD: main.c,v 1.54.2.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,6 +44,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: main.c,v 1.54.2.1 2015/03/06 21:00:23 snj Exp $"); + #ifndef MAKE_BOOTSTRAP #include #define COPYRIGHT(x) __COPYRIGHT(x) @@ -86,6 +89,7 @@ COPYRIGHT("@(#) Copyright (c) 1992, 1993\ int vflag; /* verbose output */ int Pflag; /* pack locators */ int Lflag; /* lint config generation */ +int Mflag; /* modular build */ int handling_cmdlineopts; /* currently processing -D/-U options */ int yyparse(void); @@ -93,6 +97,7 @@ int yyparse(void); #ifndef MAKE_BOOTSTRAP extern int yydebug; #endif +int dflag; static struct dlhash *obsopttab; static struct hashtab *mkopttab; @@ -148,6 +153,7 @@ static int extract_config(const char *, const char *, int); int badfilename(const char *fname); const char *progname; +extern const char *yyfile; int main(int argc, char **argv) @@ -160,14 +166,19 @@ main(int argc, char **argv) pflag = 0; xflag = 0; - while ((ch = getopt(argc, argv, "D:LPU:dgpvb:s:x")) != -1) { + while ((ch = getopt(argc, argv, "D:LMPU:dgpvb:s:x")) != -1) { switch (ch) { -#ifndef MAKE_BOOTSTRAP case 'd': +#ifndef MAKE_BOOTSTRAP yydebug = 1; - break; #endif + dflag++; + break; + + case 'M': + Mflag = 1; + break; case 'L': Lflag = 1; @@ -281,8 +292,6 @@ main(int argc, char **argv) minmaxusers = 1; maxmaxusers = 10000; initintern(); - initfiles(); - initsem(); ident = NULL; devbasetab = ht_new(); devroottab = ht_new(); @@ -310,6 +319,8 @@ main(int argc, char **argv) nextappmkopt = &appmkoptions; nextcndmkopt = &condmkoptions; nextfsopt = &fsoptions; + initfiles(); + initsem(); /* * Handle profiling (must do this before we try to create any @@ -401,16 +412,19 @@ main(int argc, char **argv) /* * Handle command line overrides */ + yyfile = "handle_cmdline_makeoptions"; handle_cmdline_makeoptions(); /* * Detect and properly ignore orphaned devices */ + yyfile = "kill_orphans"; kill_orphans(); /* * Select devices and pseudo devices and their attributes */ + yyfile = "fixdevis"; if (fixdevis()) stop(); @@ -418,33 +432,44 @@ main(int argc, char **argv) * If working on an ioconf-only config, process here and exit */ if (ioconfname) { + yyfile = "pack"; pack(); + yyfile = "mkioconf"; mkioconf(); + yyfile = "emitlocs"; emitlocs(); + yyfile = "emitioconfh"; emitioconfh(); return 0; } + yyfile = "dependattrs"; + dependattrs(); + /* * Deal with option dependencies. */ + yyfile = "dependopts"; dependopts(); /* * Fix (as in `set firmly in place') files. */ + yyfile = "fixfiles"; if (fixfiles()) stop(); /* * Fix objects and libraries. */ + yyfile = "fixobjects"; if (fixobjects()) stop(); /* * Fix device-majors. */ + yyfile = "fixdevsw"; if (fixdevsw()) stop(); @@ -468,10 +493,13 @@ main(int argc, char **argv) * Squeeze things down and finish cross-checks (STAR checks must * run after packing). */ + yyfile = "pack"; pack(); + yyfile = "badstar"; if (badstar()) stop(); + yyfile = NULL; /* * Ready to go. Build all the various files. */ @@ -525,6 +553,8 @@ dependopts_one(const char *name) if (fs != NULL) { do_depends(fs->nv_ptr); } + + CFGDBG(3, "depend `%s' searched", name); } static void @@ -548,6 +578,7 @@ do_depend(struct nvlist *nv) * If the dependency is an attribute, then just add * it to the selecttab. */ + CFGDBG(3, "depend attr `%s'", nv->nv_name); if ((a = ht_lookup(attrtab, nv->nv_name)) != NULL) { if (a->a_iattr) panic("do_depend(%s): dep `%s' is an iattr", @@ -692,6 +723,13 @@ deffilesystem(struct nvlist *fses, struct nvlist *deps) nv->nv_name); add_fs_dependencies(nv, deps); + + /* + * Implicit attribute definition for filesystem. + */ + const char *n; + n = strtolower(nv->nv_name); + refattr(n); } } @@ -954,12 +992,14 @@ addoption(const char *name, const char *value) /* make lowercase, then add to select table */ n = strtolower(name); (void)ht_insert(selecttab, n, (void *)__UNCONST(n)); + CFGDBG(3, "option selected `%s'", n); } void deloption(const char *name) { + CFGDBG(4, "deselecting opt `%s'", name); if (undo_option(opttab, &options, &nextopt, name, "options")) return; if (undo_option(selecttab, NULL, NULL, strtolower(name), "options")) @@ -993,6 +1033,14 @@ addfsoption(const char *name) /* Add to select table. */ (void)ht_insert(selecttab, n, __UNCONST(n)); + CFGDBG(3, "fs selected `%s'", name); + + /* + * Select attribute if one exists. + */ + struct attr *a; + if ((a = ht_lookup(attrtab, n)) != NULL) + selectattr(a); } void @@ -1000,6 +1048,7 @@ delfsoption(const char *name) { const char *n; + CFGDBG(4, "deselecting fs `%s'", name); n = strtolower(name); if (undo_option(fsopttab, &fsoptions, &nextfsopt, name, "file-system")) return; @@ -1021,6 +1070,7 @@ void delmkoption(const char *name) { + CFGDBG(4, "deselecting mkopt `%s'", name); (void)undo_option(mkopttab, &mkoptions, &nextmkopt, name, "makeoptions"); } @@ -1097,8 +1147,10 @@ undo_option(struct hashtab *ht, struct nvlist **npp, cfgwarn("%s `%s' is not defined", type, name); return (1); } - if (npp == NULL) + if (npp == NULL) { + CFGDBG(2, "opt `%s' deselected", name); return (0); + } for ( ; *npp != NULL; npp = &(*npp)->nv_next) { if ((*npp)->nv_name != name) @@ -1106,6 +1158,7 @@ undo_option(struct hashtab *ht, struct nvlist **npp, if (next != NULL && *next == &(*npp)->nv_next) *next = npp; nv = (*npp)->nv_next; + CFGDBG(2, "opt `%s' deselected", (*npp)->nv_name); nvfree(*npp); *npp = nv; return (0); @@ -1501,11 +1554,11 @@ strtolower(const char *name) { const char *n; char *p, low[500]; - unsigned char c; + char c; for (n = name, p = low; (c = *n) != '\0'; n++) - *p++ = isupper(c) ? tolower(c) : c; - *p = 0; + *p++ = (char)(isupper((u_char)c) ? tolower((u_char)c) : c); + *p = '\0'; return (intern(low)); } @@ -1529,8 +1582,9 @@ static int extract_config(const char *kname, const char *cname, int cfd) { char *ptr; - int found, kfd, i; + int found, kfd; struct stat st; + off_t i; found = 0; @@ -1540,7 +1594,7 @@ extract_config(const char *kname, const char *cname, int cfd) err(EXIT_FAILURE, "cannot open %s", kname); if (fstat(kfd, &st) == -1) err(EXIT_FAILURE, "cannot stat %s", kname); - ptr = mmap(0, st.st_size, PROT_READ, MAP_FILE | MAP_SHARED, + ptr = mmap(0, (size_t)st.st_size, PROT_READ, MAP_FILE | MAP_SHARED, kfd, 0); if (ptr == MAP_FAILED) err(EXIT_FAILURE, "cannot mmap %s", kname); diff --git a/usr.bin/config/mkdevsw.c b/usr.bin/config/mkdevsw.c index 2ff890411cf2..d3b0739f1ad5 100644 --- a/usr.bin/config/mkdevsw.c +++ b/usr.bin/config/mkdevsw.c @@ -1,4 +1,4 @@ -/* $NetBSD: mkdevsw.c,v 1.10 2010/07/30 16:23:49 cube Exp $ */ +/* $NetBSD: mkdevsw.c,v 1.10.24.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -33,6 +33,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: mkdevsw.c,v 1.10.24.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -86,37 +89,54 @@ emitheader(FILE *fp) "#include \n", fp); } +static void +dentry(FILE *fp, struct hashtab *t, devmajor_t i, char p) +{ + const struct devm *dm; + char mstr[16]; + + (void)snprintf(mstr, sizeof(mstr), "%d", i); + if ((dm = ht_lookup(t, intern(mstr))) == NULL) + return; + + fprintf(fp, "extern const struct %cdevsw %s_%cdevsw;\n", + p, dm->dm_name, p); +} + +static void +pentry(FILE *fp, struct hashtab *t, devmajor_t i, char p) +{ + const struct devm *dm; + char mstr[16]; + + (void)snprintf(mstr, sizeof(mstr), "%d", i); + dm = ht_lookup(t, intern(mstr)); + + if (dm) + fprintf(fp, "\t&%s_%cdevsw", dm->dm_name, p); + else + fputs("\tNULL", fp); + + fprintf(fp, ",\t// %3d\n", i); +} + /* * Emit device switch table for character/block device. */ static void emitdevm(FILE *fp) { - struct devm *dm; - char mstr[16]; devmajor_t i; fputs("\n/* device switch table for block device */\n", fp); - for (i = 0 ; i <= maxbdevm ; i++) { - (void)snprintf(mstr, sizeof(mstr), "%d", i); - if ((dm = ht_lookup(bdevmtab, intern(mstr))) == NULL) - continue; - - fprintf(fp, "extern const struct bdevsw %s_bdevsw;\n", - dm->dm_name); - } + for (i = 0; i <= maxbdevm ; i++) + dentry(fp, cdevmtab, i, 'b'); fputs("\nconst struct bdevsw *bdevsw0[] = {\n", fp); - for (i = 0 ; i <= maxbdevm ; i++) { - (void)snprintf(mstr, sizeof(mstr), "%d", i); - if ((dm = ht_lookup(bdevmtab, intern(mstr))) == NULL) { - fprintf(fp, "\tNULL,\n"); - } else { - fprintf(fp, "\t&%s_bdevsw,\n", dm->dm_name); - } - } + for (i = 0; i <= maxbdevm; i++) + pentry(fp, bdevmtab, i, 'b'); fputs("};\n\nconst struct bdevsw **bdevsw = bdevsw0;\n", fp); @@ -125,25 +145,13 @@ emitdevm(FILE *fp) fputs("\n/* device switch table for character device */\n", fp); - for (i = 0 ; i <= maxcdevm ; i++) { - (void)snprintf(mstr, sizeof(mstr), "%d", i); - if ((dm = ht_lookup(cdevmtab, intern(mstr))) == NULL) - continue; - - fprintf(fp, "extern const struct cdevsw %s_cdevsw;\n", - dm->dm_name); - } + for (i = 0; i <= maxcdevm; i++) + dentry(fp, cdevmtab, i, 'c'); fputs("\nconst struct cdevsw *cdevsw0[] = {\n", fp); - for (i = 0 ; i <= maxcdevm ; i++) { - (void)snprintf(mstr, sizeof(mstr), "%d", i); - if ((dm = ht_lookup(cdevmtab, intern(mstr))) == NULL) { - fprintf(fp, "\tNULL,\n"); - } else { - fprintf(fp, "\t&%s_cdevsw,\n", dm->dm_name); - } - } + for (i = 0; i <= maxcdevm; i++) + pentry(fp, cdevmtab, i, 'c'); fputs("};\n\nconst struct cdevsw **cdevsw = cdevsw0;\n", fp); @@ -189,7 +197,9 @@ emitconv(FILE *fp) d_flags = nv->nv_str; break; } - d_vec[i++] = nv->nv_num; + if (nv->nv_num > INT_MAX || nv->nv_num < INT_MIN) + panic("out of range devnode definition"); + d_vec[i++] = (int)nv->nv_num; } fprintf(fp, "\t{ \"%s\", %d, %d, %s, %s, { %d, %d }},\n", diff --git a/usr.bin/config/mkheaders.c b/usr.bin/config/mkheaders.c index 2cb267c7f2e3..42ff5f5d9932 100644 --- a/usr.bin/config/mkheaders.c +++ b/usr.bin/config/mkheaders.c @@ -1,4 +1,4 @@ -/* $NetBSD: mkheaders.c,v 1.21 2012/03/12 02:58:55 dholland Exp $ */ +/* $NetBSD: mkheaders.c,v 1.21.10.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,6 +44,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: mkheaders.c,v 1.21.10.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -137,10 +140,14 @@ fprint_global(FILE *fp, const char *name, long long value) static unsigned int global_hash(const char *str) { - unsigned int h; + unsigned long h; char *ep; - /* If the value is a valid numeric, just use it */ + /* + * If the value is a valid numeric, just use it + * We don't care about negative values here, we + * just use the value as a hash. + */ h = strtoul(str, &ep, 0); if (*ep != 0) /* Otherwise shove through a 32bit CRC function */ @@ -148,7 +155,7 @@ global_hash(const char *str) /* Avoid colliding with the value used for undefined options. */ /* At least until I stop any options being set to zero */ - return h != UNDEFINED ? h : DEFINED; + return (unsigned int)(h != UNDEFINED ? h : DEFINED); } static void @@ -316,7 +323,7 @@ locators_print(const char *name, void *value, void *arg) locdup = estrdup(name); for (cp = locdup; *cp; cp++) if (islower((unsigned char)*cp)) - *cp = toupper((unsigned char)*cp); + *cp = (char)toupper((unsigned char)*cp); for (i = 0, ll = a->a_locs; ll; ll = ll->ll_next, i++) { if (strchr(ll->ll_name, ' ') != NULL || strchr(ll->ll_name, '\t') != NULL) @@ -328,7 +335,7 @@ locators_print(const char *name, void *value, void *arg) namedup = estrdup(ll->ll_name); for (cp = namedup; *cp; cp++) if (islower((unsigned char)*cp)) - *cp = toupper((unsigned char)*cp); + *cp = (char)toupper((unsigned char)*cp); else if (*cp == ARRCHR) *cp = '_'; fprintf(fp, "#define %sCF_%s %d\n", locdup, namedup, i); @@ -520,13 +527,13 @@ static char * cntname(const char *src) { char *dst; - unsigned char c; + char c; static char buf[100]; dst = buf; *dst++ = 'N'; while ((c = *src++) != 0) - *dst++ = islower(c) ? toupper(c) : c; + *dst++ = (char)(islower((u_char)c) ? toupper((u_char)c) : c); *dst = 0; return (buf); } diff --git a/usr.bin/config/mkioconf.c b/usr.bin/config/mkioconf.c index 387022ed7e22..acfd3c0a0002 100644 --- a/usr.bin/config/mkioconf.c +++ b/usr.bin/config/mkioconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: mkioconf.c,v 1.21 2012/03/11 21:16:08 dholland Exp $ */ +/* $NetBSD: mkioconf.c,v 1.21.10.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,6 +44,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: mkioconf.c,v 1.21.10.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -136,7 +139,7 @@ static void emithdr(FILE *ofp) { FILE *ifp; - int n; + size_t n; char ifnbuf[200], buf[BUFSIZ]; char *ifn; @@ -174,12 +177,14 @@ cf_locators_print(const char *name, void *value, void *arg) a = value; if (!a->a_iattr) return (0); + if (ht_lookup(selecttab, name) == NULL) + return (0); if (a->a_locs) { fprintf(fp, "static const struct cfiattrdata %scf_iattrdata = {\n", name); - fprintf(fp, "\t\"%s\", %d,\n\t{\n", name, a->a_loclen); + fprintf(fp, "\t\"%s\", %d, {\n", name, a->a_loclen); for (ll = a->a_locs; ll; ll = ll->ll_next) fprintf(fp, "\t\t{ \"%s\", \"%s\", %s },\n", ll->ll_name, @@ -319,10 +324,6 @@ emitloc(FILE *fp) for (i = 0; i < locators.used; i++) fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]); fprintf(fp, "\n};\n"); - } else if (*packed != NULL) { - /* We need to have *something*. */ - fprintf(fp, "\n/* locators */\n" - "static int loc[1] = { -1 };\n"); } } @@ -375,7 +376,7 @@ emitcfdata(FILE *fp) "\n" "%sstruct cfdata cfdata%s%s[] = {\n" " /* driver attachment unit state " - "loc flags pspec */\n", + " loc flags pspec */\n", ioconfname ? "static " : "", ioconfname ? "_ioconf_" : "", ioconfname ? ioconfname : ""); @@ -428,9 +429,9 @@ emitcfdata(FILE *fp) i->i_locoff); loc = locbuf; } else - loc = "loc"; + loc = "NULL"; fprintf(fp, " { \"%s\",%s\"%s\",%s%2d, %s, %7s, %#6x, ", - basename, strlen(basename) < 8 ? "\t\t" + basename, strlen(basename) < 7 ? "\t\t" : "\t", attachment, strlen(attachment) < 5 ? "\t\t" : "\t", @@ -441,7 +442,7 @@ emitcfdata(FILE *fp) fputs("NULL },\n", fp); } fprintf(fp, " { %s,%s%s,%s%2d, %s, %7s, %#6x, %s }\n};\n", - "NULL", "\t\t", "NULL", "\t\t", 0, "0", "NULL", 0, "NULL"); + "NULL", "\t\t", "NULL", "\t\t", 0, " 0", "NULL", 0, "NULL"); } /* @@ -479,7 +480,7 @@ emitpseudo(FILE *fp) fprintf(fp, "void %sattach(int);\n", i->i_base->d_name); } - fputs("\nstruct pdevinit pdevinit[] = {\n", fp); + fputs("\nconst struct pdevinit pdevinit[] = {\n", fp); TAILQ_FOREACH(i, &allpseudo, i_next) { d = i->i_base; fprintf(fp, "\t{ %sattach, %d },\n", diff --git a/usr.bin/config/mkmakefile.c b/usr.bin/config/mkmakefile.c index 16b1e240bffa..0622ede337ea 100644 --- a/usr.bin/config/mkmakefile.c +++ b/usr.bin/config/mkmakefile.c @@ -1,4 +1,4 @@ -/* $NetBSD: mkmakefile.c,v 1.15 2012/06/08 08:56:45 martin Exp $ */ +/* $NetBSD: mkmakefile.c,v 1.15.10.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,6 +44,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: mkmakefile.c,v 1.15.10.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -51,6 +54,7 @@ #include #include #include +#include #include "defs.h" #include "sem.h" @@ -68,6 +72,11 @@ static void emitdefs(FILE *); static void emitfiles(FILE *, int, int); static void emitobjs(FILE *); +static void emitallkobjs(FILE *); +static int emitallkobjscb(const char *, void *, void *); +static void emitattrkobjs(FILE *); +static int emitattrkobjscb(const char *, void *, void *); +static void emitkobjs(FILE *); static void emitcfiles(FILE *); static void emitsfiles(FILE *); static void emitrules(FILE *); @@ -77,6 +86,8 @@ static void emitappmkoptions(FILE *); static void emitsubs(FILE *, const char *, const char *, int); static int selectopt(const char *, void *); +int has_build_kernel; + int mkmakefile(void) { @@ -86,13 +97,36 @@ mkmakefile(void) char *ifname; char line[BUFSIZ], buf[200]; - /* Try a makefile for the port first. + /* + * Check if conf/Makefile.kern.inc defines "build_kernel". + * + * (This is usually done by checking "version" in sys/conf/files; + * unfortunately the "build_kernel" change done around 2014 Aug didn't + * bump that version. Thus this hack.) + */ + (void)snprintf(buf, sizeof(buf), "conf/Makefile.kern.inc"); + ifname = sourcepath(buf); + if ((ifp = fopen(ifname, "r")) == NULL) { + warn("cannot read %s", ifname); + goto bad2; + } + while (fgets(line, sizeof(line), ifp) != NULL) { + if (strncmp(line, "build_kernel:", 13) == 0) { + has_build_kernel = 1; + break; + } + } + (void)fclose(ifp); + + /* + * Try a makefile for the port first. */ (void)snprintf(buf, sizeof(buf), "arch/%s/conf/Makefile.%s", machine, machine); ifname = sourcepath(buf); if ((ifp = fopen(ifname, "r")) == NULL) { - /* Try a makefile for the architecture second. + /* + * Try a makefile for the architecture second. */ (void)snprintf(buf, sizeof(buf), "arch/%s/conf/Makefile.%s", machinearch, machinearch); @@ -120,7 +154,7 @@ mkmakefile(void) continue; } if (strcmp(line, "%OBJS\n") == 0) - fn = emitobjs; + fn = Mflag ? emitkobjs : emitobjs; else if (strcmp(line, "%CFILES\n") == 0) fn = emitcfiles; else if (strcmp(line, "%SFILES\n") == 0) @@ -224,11 +258,13 @@ emitsubs(FILE *fp, const char *line, const char *file, int lineno) if (option != NULL) fputs(option->nv_str ? option->nv_str : "1", fp); - /* Otherwise it's not a selected option and we don't - * output anything. */ + /* + * Otherwise it's not a selected option and we don't + * output anything. + */ } - line = nextpct+1; + line = nextpct + 1; } } @@ -261,52 +297,48 @@ srcpath(struct files *fi) static const char * filetype_prologue(struct filetype *fit) { - if (fit->fit_flags & FIT_NOPROLOGUE || *fit->fit_path == '/') - return (""); - else - return ("$S/"); + + return (*fit->fit_path == '/') ? "" : "$S/"; } static const char * prefix_prologue(const char *path) { - if (*path == '/') - return (""); - else - return ("$S/"); + + return (*path == '/') ? "" : "$S/"; } static void emitdefs(FILE *fp) { struct nvlist *nv; - const char *sp; fprintf(fp, "KERNEL_BUILD=%s\n", conffile); - fputs("IDENT=", fp); - sp = ""; + fputs("IDENT= \\\n", fp); for (nv = options; nv != NULL; nv = nv->nv_next) { - /* skip any options output to a header file */ + /* Skip any options output to a header file */ if (DEFINED_OPTION(nv->nv_name)) continue; - fprintf(fp, "%s-D%s", sp, nv->nv_name); - if (nv->nv_str) - fprintf(fp, "=\"%s\"", nv->nv_str); - sp = " "; + const char *s = nv->nv_str; + fprintf(fp, "\t-D%s%s%s%s \\\n", nv->nv_name, + s ? "=\"" : "", + s ? s : "", + s ? "\"" : ""); } putc('\n', fp); fprintf(fp, "PARAM=-DMAXUSERS=%d\n", maxusers); fprintf(fp, "MACHINE=%s\n", machine); - if (*srcdir == '/' || *srcdir == '.') { - fprintf(fp, "S=\t%s\n", srcdir); - } else { + + const char *subdir = ""; + if (*srcdir != '/' && *srcdir != '.') { /* * libkern and libcompat "Makefile.inc"s want relative S * specification to begin with '.'. */ - fprintf(fp, "S=\t./%s\n", srcdir); + subdir = "./"; } + fprintf(fp, "S=\t%s%s\n", subdir, srcdir); for (nv = mkoptions; nv != NULL; nv = nv->nv_next) fprintf(fp, "%s=%s\n", nv->nv_name, nv->nv_str); } @@ -316,61 +348,144 @@ emitobjs(FILE *fp) { struct files *fi; struct objects *oi; - int lpos, len, sp; - fputs("OBJS=", fp); - sp = '\t'; - lpos = 7; + fputs("OBJS= \\\n", fp); TAILQ_FOREACH(fi, &allfiles, fi_next) { if ((fi->fi_flags & FI_SEL) == 0) continue; - len = strlen(fi->fi_base) + 2; - if (lpos + len > 72) { - fputs(" \\\n", fp); - sp = '\t'; - lpos = 7; - } - fprintf(fp, "%c%s.o", sp, fi->fi_base); - lpos += len + 1; - sp = ' '; + fprintf(fp, "\t%s.o \\\n", fi->fi_base); } TAILQ_FOREACH(oi, &allobjects, oi_next) { + const char *prologue, *prefix, *sep; + if ((oi->oi_flags & OI_SEL) == 0) continue; - len = strlen(oi->oi_path); - if (*oi->oi_path != '/') - { - /* e.g. "$S/" */ - if (oi->oi_prefix != NULL) - len += strlen(prefix_prologue(oi->oi_path)) + - strlen(oi->oi_prefix) + 1; - else - len += strlen(filetype_prologue(&oi->oi_fit)); - } - if (lpos + len > 72) { - fputs(" \\\n", fp); - sp = '\t'; - lpos = 7; - } - if (*oi->oi_path == '/') { - fprintf(fp, "%c%s", sp, oi->oi_path); - } else { + prologue = prefix = sep = ""; + if (*oi->oi_path != '/') { if (oi->oi_prefix != NULL) { - fprintf(fp, "%c%s%s/%s", sp, - prefix_prologue(oi->oi_path), - oi->oi_prefix, oi->oi_path); + prologue = prefix_prologue(oi->oi_path); + prefix = oi->oi_prefix; + sep = "/"; } else { - fprintf(fp, "%c%s%s", sp, - filetype_prologue(&oi->oi_fit), - oi->oi_path); + prologue = filetype_prologue(&oi->oi_fit); } } - lpos += len + 1; - sp = ' '; + fprintf(fp, "\t%s%s%s%s \\\n", prologue, prefix, sep, + oi->oi_path); } putc('\n', fp); } +static void +emitkobjs(FILE *fp) +{ + emitallkobjs(fp); + emitattrkobjs(fp); +} + +static int emitallkobjsweighcb(const char *name, void *v, void *arg); +static void weighattr(struct attr *a); +static int attrcmp(const void *l, const void *r); + +struct attr **attrbuf; +size_t attridx; + +static void +emitallkobjs(FILE *fp) +{ + size_t i; + + attrbuf = emalloc(nattrs * sizeof(*attrbuf)); + + ht_enumerate(attrtab, emitallkobjsweighcb, NULL); + ht_enumerate(attrtab, emitallkobjscb, NULL); + qsort(attrbuf, attridx, sizeof(struct attr *), attrcmp); + + fputs("OBJS= \\\n", fp); + for (i = 0; i < attridx; i++) + fprintf(fp, "\t%s.ko \\\n", attrbuf[i]->a_name); + putc('\n', fp); + + free(attrbuf); +} + +static int +emitallkobjscb(const char *name, void *v, void *arg) +{ + struct attr *a = v; + + if (ht_lookup(selecttab, name) == NULL) + return 0; + if (TAILQ_EMPTY(&a->a_files)) + return 0; + attrbuf[attridx++] = a; + /* XXX nattrs tracking is not exact yet */ + if (attridx == nattrs) { + nattrs *= 2; + attrbuf = erealloc(attrbuf, nattrs * sizeof(*attrbuf)); + } + return 0; +} + +static int +emitallkobjsweighcb(const char *name, void *v, void *arg) +{ + struct attr *a = v; + + weighattr(a); + return 0; +} + +static void +weighattr(struct attr *a) +{ + struct attrlist *al; + + for (al = a->a_deps; al != NULL; al = al->al_next) { + weighattr(al->al_this); + } + a->a_weight++; +} + +static int +attrcmp(const void *l, const void *r) +{ + const struct attr * const *a = l, * const *b = r; + const int wa = (*a)->a_weight, wb = (*b)->a_weight; + return (wa > wb) ? -1 : (wa < wb) ? 1 : 0; +} + +static void +emitattrkobjs(FILE *fp) +{ + extern struct hashtab *attrtab; + + ht_enumerate(attrtab, emitattrkobjscb, fp); +} + +static int +emitattrkobjscb(const char *name, void *v, void *arg) +{ + struct attr *a = v; + struct files *fi; + FILE *fp = arg; + + if (ht_lookup(selecttab, name) == NULL) + return 0; + if (TAILQ_EMPTY(&a->a_files)) + return 0; + fputc('\n', fp); + fprintf(fp, "# %s (%d)\n", name, a->a_weight); + fprintf(fp, "OBJS.%s= \\\n", name); + TAILQ_FOREACH(fi, &a->a_files, fi_anext) { + fprintf(fp, "\t%s.o \\\n", fi->fi_base); + } + fputc('\n', fp); + fprintf(fp, "%s.ko: ${OBJS.%s}\n", name, name); + fprintf(fp, "\t${LINK_O}\n"); + return 0; +} + static void emitcfiles(FILE *fp) { @@ -389,49 +504,31 @@ static void emitfiles(FILE *fp, int suffix, int upper_suffix) { struct files *fi; - int lpos, len, sp; const char *fpath; struct config *cf; char swapname[100]; - fprintf(fp, "%cFILES=", toupper(suffix)); - sp = '\t'; - lpos = 7; + fprintf(fp, "%cFILES= \\\n", toupper(suffix)); TAILQ_FOREACH(fi, &allfiles, fi_next) { + const char *prologue, *prefix, *sep; + if ((fi->fi_flags & FI_SEL) == 0) continue; fpath = srcpath(fi); - len = strlen(fpath); - if (fpath[len - 1] != suffix && fpath[len - 1] != upper_suffix) + if (fi->fi_suffix != suffix && fi->fi_suffix != upper_suffix) continue; - if (*fpath != '/') { - /* "$S/" */ - if (fi->fi_prefix != NULL) - len += strlen(prefix_prologue(fi->fi_prefix)) + - strlen(fi->fi_prefix) + 1; - else - len += strlen(filetype_prologue(&fi->fi_fit)); - } - if (lpos + len > 72) { - fputs(" \\\n", fp); - sp = '\t'; - lpos = 7; - } - if (*fi->fi_path == '/') { - fprintf(fp, "%c%s", sp, fpath); - } else { + prologue = prefix = sep = ""; + if (*fi->fi_path != '/') { if (fi->fi_prefix != NULL) { - fprintf(fp, "%c%s%s/%s", sp, - prefix_prologue(fi->fi_prefix), - fi->fi_prefix, fpath); + prologue = prefix_prologue(fi->fi_prefix); + prefix = fi->fi_prefix; + sep = "/"; } else { - fprintf(fp, "%c%s%s", sp, - filetype_prologue(&fi->fi_fit), - fpath); + prologue = filetype_prologue(&fi->fi_fit); } } - lpos += len + 1; - sp = ' '; + fprintf(fp, "\t%s%s%s%s \\\n", + prologue, prefix, sep, fpath); } /* * The allfiles list does not include the configuration-specific @@ -442,15 +539,7 @@ emitfiles(FILE *fp, int suffix, int upper_suffix) TAILQ_FOREACH(cf, &allcf, cf_next) { (void)snprintf(swapname, sizeof(swapname), "swap%s.c", cf->cf_name); - len = strlen(swapname); - if (lpos + len > 72) { - fputs(" \\\n", fp); - sp = '\t'; - lpos = 7; - } - fprintf(fp, "%c%s", sp, swapname); - lpos += len + 1; - sp = ' '; + fprintf(fp, "\t%s \\\n", swapname); } } putc('\n', fp); @@ -463,37 +552,30 @@ static void emitrules(FILE *fp) { struct files *fi; - const char *cp, *fpath; - int ch; + const char *fpath; TAILQ_FOREACH(fi, &allfiles, fi_next) { + const char *prologue, *prefix, *sep; + if ((fi->fi_flags & FI_SEL) == 0) continue; fpath = srcpath(fi); - if (*fpath == '/') { - fprintf(fp, "%s.o: %s\n", fi->fi_base, fpath); - } else { + prologue = prefix = sep = ""; + if (*fpath != '/') { if (fi->fi_prefix != NULL) { - fprintf(fp, "%s.o: %s%s/%s\n", fi->fi_base, - prefix_prologue(fi->fi_prefix), - fi->fi_prefix, fpath); + prologue = prefix_prologue(fi->fi_prefix); + prefix = fi->fi_prefix; + sep = "/"; } else { - fprintf(fp, "%s.o: %s%s\n", - fi->fi_base, - filetype_prologue(&fi->fi_fit), - fpath); + prologue = filetype_prologue(&fi->fi_fit); } } + fprintf(fp, "%s.o: %s%s%s%s\n", fi->fi_base, + prologue, prefix, sep, fpath); if (fi->fi_mkrule != NULL) { fprintf(fp, "\t%s\n\n", fi->fi_mkrule); } else { - fputs("\t${NORMAL_", fp); - cp = strrchr(fpath, '.'); - cp = cp == NULL ? fpath : cp + 1; - while ((ch = *cp++) != '\0') { - fputc(toupper(ch), fp); - } - fputs("}\n\n", fp); + fprintf(fp, "\t${NORMAL_%c}\n\n", toupper(fi->fi_suffix)); } } } @@ -507,9 +589,9 @@ static void emitload(FILE *fp) { struct config *cf; - const char *nm, *swname; - fputs(".MAIN: all\nall:", fp); + fputs(".MAIN: all\n", fp); + fputs("all:", fp); TAILQ_FOREACH(cf, &allcf, cf_next) { fprintf(fp, " %s", cf->cf_name); /* @@ -521,20 +603,28 @@ emitload(FILE *fp) fprintf(fp, " .WAIT"); } fputs("\n\n", fp); - TAILQ_FOREACH(cf, &allcf, cf_next) { - nm = cf->cf_name; - swname = - cf->cf_root != NULL ? cf->cf_name : "generic"; - fprintf(fp, "KERNELS+=%s\n", nm); - fprintf(fp, "%s: ${SYSTEM_DEP} swap${.TARGET}.o vers.o", nm); - fprintf(fp, "\n" - "\t${SYSTEM_LD_HEAD}\n" - "\t${SYSTEM_LD} swap${.TARGET}.o\n" - "\t${SYSTEM_LD_TAIL}\n" - "\n" - "swap%s.o: swap%s.c\n" - "\t${NORMAL_C}\n\n", swname, swname); + /* + * Generate the backward-compatible "build_kernel" rule if + * sys/conf/Makefile.kern.inc doesn't define any (pre-2014 Aug). + */ + if (has_build_kernel == 0) { + fprintf(fp, "build_kernel: .USE\n" + "\t${SYSTEM_LD_HEAD}\n" + "\t${SYSTEM_LD} swap${.TARGET}.o\n" + "\t${SYSTEM_LD_TAIL}\n" + "\n"); } + /* + * Generate per-kernel rules. + */ + TAILQ_FOREACH(cf, &allcf, cf_next) { + fprintf(fp, "KERNELS+=%s\n", cf->cf_name); + fprintf(fp, "%s: ${SYSTEM_DEP} swap%s.o vers.o build_kernel\n", + cf->cf_name, cf->cf_name); + fprintf(fp, "swap%s.o: swap%s.c\n" + "\t${NORMAL_C}\n\n", cf->cf_name, cf->cf_name); + } + fputs("\n", fp); } /* diff --git a/usr.bin/config/mkswap.c b/usr.bin/config/mkswap.c index 2f49c18eec9c..18cc65e5c9f8 100644 --- a/usr.bin/config/mkswap.c +++ b/usr.bin/config/mkswap.c @@ -1,4 +1,4 @@ -/* $NetBSD: mkswap.c,v 1.7 2009/01/20 18:20:48 drochner Exp $ */ +/* $NetBSD: mkswap.c,v 1.7.26.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,6 +44,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: mkswap.c,v 1.7.26.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -114,7 +117,7 @@ mkoneswap(struct config *cf) cf->cf_root->nv_str); fprintf(fp, "const char *rootspec = %s;\n", specinfo); fprintf(fp, "dev_t\trootdev = %s;\t/* %s */\n\n", - mkdevstr(nv->nv_num), + mkdevstr((dev_t)nv->nv_num), nv->nv_str == s_qmark ? "wildcarded" : nv->nv_str); /* @@ -127,7 +130,7 @@ mkoneswap(struct config *cf) snprintf(specinfo, sizeof(specinfo), "\"%s\"", cf->cf_dump->nv_str); fprintf(fp, "const char *dumpspec = %s;\n", specinfo); fprintf(fp, "dev_t\tdumpdev = %s;\t/* %s */\n\n", - nv ? mkdevstr(nv->nv_num) : "NODEV", + nv ? mkdevstr((dev_t)nv->nv_num) : "NODEV", nv ? nv->nv_str : "unspecified"); /* diff --git a/usr.bin/config/pack.c b/usr.bin/config/pack.c index 5d3fc2cbdc1c..22e651ce2748 100644 --- a/usr.bin/config/pack.c +++ b/usr.bin/config/pack.c @@ -1,4 +1,4 @@ -/* $NetBSD: pack.c,v 1.8 2010/03/08 10:19:14 pooka Exp $ */ +/* $NetBSD: pack.c,v 1.8.24.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,6 +44,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: pack.c,v 1.8.24.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -137,7 +140,7 @@ packdevi(void) { struct devi *firststar, *i, **ip, *l, *p; struct devbase *d; - int j, m, n; + u_short j, m, n; /* * Sort all the cloning units to after the non-cloning units, diff --git a/usr.bin/config/scan.l b/usr.bin/config/scan.l index 7cc131fb35f9..b747512ae95d 100644 --- a/usr.bin/config/scan.l +++ b/usr.bin/config/scan.l @@ -1,5 +1,5 @@ %{ -/* $NetBSD: scan.l,v 1.17 2012/03/20 20:34:57 matt Exp $ */ +/* $NetBSD: scan.l,v 1.17.10.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -41,6 +41,9 @@ * from: @(#)scan.l 8.1 (Berkeley) 6/6/93 */ +#include +__RCSID("$NetBSD: scan.l,v 1.17.10.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -108,12 +111,12 @@ static int getcurifdef(void); %} -%option noyywrap +%option noyywrap nounput noinput PATH [A-Za-z_0-9]*[./][-A-Za-z_0-9./]* -QCHARS ([^"\n]|\\\")+ +QCHARS \"(\\.|[^\\"])*\" WORD [A-Za-z_][-A-Za-z_0-9]* -FILENAME ({PATH}|\"{QCHARS}\") +FILENAME ({PATH}|{QCHARS}) RESTOFLINE [ \t]*(#[^\n]*)?\n %x IGNORED @@ -164,6 +167,7 @@ prefix return PREFIX; pseudo-device return PSEUDO_DEVICE; pseudo-root return PSEUDO_ROOT; root return ROOT; +select return SELECT; single return SINGLE; source return SOURCE; type return TYPE; @@ -319,12 +323,11 @@ package[ \t]+{FILENAME}{RESTOFLINE} { return EMPTYSTRING; } -\"{QCHARS} { - tok = input(); /* eat closing quote */ - if (tok != '"') { - cfgerror("closing quote missing\n"); - unput(tok); - } +{QCHARS} { + size_t l = strlen(yytext); + if (l > 1 && yytext[l - 1] == '"') + yytext[l - 1] = '\0'; + yylval.str = intern(yytext + 1); return QSTRING; } @@ -335,7 +338,7 @@ package[ \t]+{FILENAME}{RESTOFLINE} { } 0[xX][0-9a-fA-F]+ { yylval.num.fmt = 16; - yylval.num.val = strtoull(yytext + 2, NULL, 16); + yylval.num.val = (long long)strtoull(yytext + 2, NULL, 16); return NUMBER; } [1-9][0-9]* { @@ -397,8 +400,7 @@ curdir_push(const char *fname) free(f); return (-1); } - p = emalloc(strlen(cwd) + strlen(d) + 2); - sprintf(p, "%s/%s", cwd, d); + easprintf(&p, "%s/%s", cwd, d); } free(f); pf = ecalloc(1, sizeof(*pf)); @@ -498,8 +500,7 @@ include(const char *fname, int ateof, int conditional, int direct) s = estrdup(fname); else if (fname[0] == '.' && fname[1] == '/') { struct prefix *pf = SLIST_FIRST(&curdirs); - s = emalloc(strlen(pf->pf_prefix) + strlen(fname)); - sprintf(s, "%s/%s", pf->pf_prefix, fname + 2); + easprintf(&s, "%s/%s", pf->pf_prefix, fname + 2); } else s = sourcepath(fname); if ((fp = fopen(s, "r")) == NULL) { @@ -530,6 +531,7 @@ include(const char *fname, int ateof, int conditional, int direct) if (interesting) logconfig_include(fp, fname); incl = in; + CFGDBG(1, "include `%s' from `%s' line %d", fname, yyfile, yyline); yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); yyfile = intern(s); yyline = 1; @@ -604,12 +606,12 @@ endinclude(void) * us to consume a newline, we have to subtract one. yychar is yacc's * token lookahead, so we can tell. */ -int +u_short currentline(void) { extern int yychar; - return (yyline - (yychar == '\n')); + return (u_short)(yyline - (yychar == '\n')); } static int diff --git a/usr.bin/config/sem.c b/usr.bin/config/sem.c index a04801f93c28..11d764b090ea 100644 --- a/usr.bin/config/sem.c +++ b/usr.bin/config/sem.c @@ -1,4 +1,4 @@ -/* $NetBSD: sem.c,v 1.43 2014/05/29 07:47:45 mrg Exp $ */ +/* $NetBSD: sem.c,v 1.43.2.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,6 +44,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: sem.c,v 1.43.2.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -65,6 +68,8 @@ const char *s_none; static struct hashtab *cfhashtab; /* for config lookup */ struct hashtab *devitab; /* etc */ +struct attr allattr; +size_t nattrs; static struct attr errattr; static struct devbase errdev; @@ -95,6 +100,13 @@ initsem(void) { attrtab = ht_new(); + attrdeptab = ht_new(); + + allattr.a_name = "netbsd"; + TAILQ_INIT(&allattr.a_files); + (void)ht_insert(attrtab, allattr.a_name, &allattr); + selectattr(&allattr); + errattr.a_name = ""; TAILQ_INIT(&allbases); @@ -121,11 +133,79 @@ initsem(void) /* Name of include file just ended (set in scan.l) */ extern const char *lastfile; +static struct attr * +finddep(struct attr *a, const char *name) +{ + struct attrlist *al; + + for (al = a->a_deps; al != NULL; al = al->al_next) { + struct attr *this = al->al_this; + if (strcmp(this->a_name, name) == 0) + return this; + } + return NULL; +} + +static void +mergedeps(const char *dname, const char *name) +{ + struct attr *a, *newa; + + CFGDBG(4, "merging attr `%s' to devbase `%s'", name, dname); + a = refattr(dname); + if (finddep(a, name) == NULL) { + newa = refattr(name); + a->a_deps = attrlist_cons(a->a_deps, newa); + CFGDBG(3, "attr `%s' merged to attr `%s'", newa->a_name, + a->a_name); + } +} + +static void +fixdev(struct devbase *dev) +{ + struct attrlist *al; + struct attr *devattr, *a; + + devattr = refattr(dev->d_name); + if (devattr->a_devclass) + panic("%s: dev %s is devclass!", __func__, devattr->a_name); + + CFGDBG(4, "fixing devbase `%s'", dev->d_name); + for (al = dev->d_attrs; al != NULL; al = al->al_next) { + a = al->al_this; + CFGDBG(4, "fixing devbase `%s' attr `%s'", dev->d_name, a->a_name); + if (a->a_iattr) { + a->a_refs = addtoattr(a->a_refs, dev); + CFGDBG(3, "device `%s' has iattr `%s'", dev->d_name, + a->a_name); + } else if (a->a_devclass != NULL) { + if (dev->d_classattr != NULL && dev->d_classattr != a) { + cfgwarn("device `%s' has multiple classes " + "(`%s' and `%s')", + dev->d_name, dev->d_classattr->a_name, + a->a_name); + } + if (dev->d_classattr == NULL) { + dev->d_classattr = a; + CFGDBG(3, "device `%s' is devclass `%s'", dev->d_name, + a->a_name); + } + } else { + if (strcmp(dev->d_name, a->a_name) != 0) { + mergedeps(dev->d_name, a->a_name); + } + } + } +} + void enddefs(void) { struct devbase *dev; + yyfile = "enddefs"; + TAILQ_FOREACH(dev, &allbases, d_next) { if (!dev->d_isdef) { (void)fprintf(stderr, @@ -134,6 +214,7 @@ enddefs(void) errors++; continue; } + fixdev(dev); } if (errors) { (void)fprintf(stderr, "*** Stop.\n"); @@ -196,20 +277,25 @@ setident(const char *i) * Since an empty locator list is logically different from "no interface", * all locator lists include a dummy head node, which we discard here. */ +int +defattr0(const char *name, struct loclist *locs, struct attrlist *deps, + int devclass) +{ + + if (locs != NULL) + return defiattr(name, locs, deps, devclass); + else if (devclass) + return defdevclass(name, locs, deps, devclass); + else + return defattr(name, locs, deps, devclass); +} + int defattr(const char *name, struct loclist *locs, struct attrlist *deps, int devclass) { struct attr *a, *dep; struct attrlist *al; - struct loclist *ll; - int len; - - if (locs != NULL && devclass) - panic("defattr(%s): locators and devclass", name); - - if (deps != NULL && devclass) - panic("defattr(%s): dependencies and devclass", name); /* * If this attribute depends on any others, make sure none of @@ -222,56 +308,100 @@ defattr(const char *name, struct loclist *locs, struct attrlist *deps, "attribute", name, dep->a_name); return (1); } + (void)ht_insert2(attrdeptab, name, dep->a_name, NULL); + CFGDBG(2, "attr `%s' depends on attr `%s'", name, dep->a_name); } - a = ecalloc(1, sizeof *a); - if (ht_insert(attrtab, name, a)) { - free(a); + if (getrefattr(name, &a)) { cfgerror("attribute `%s' already defined", name); loclist_destroy(locs); return (1); } + if (a == NULL) + a = mkattr(name); - a->a_name = name; - if (locs != NULL) { - a->a_iattr = 1; - /* unwrap */ - a->a_locs = locs->ll_next; - locs->ll_next = NULL; - loclist_destroy(locs); - } else { - a->a_iattr = 0; - a->a_locs = NULL; + a->a_deps = deps; + expandattr(a, NULL); + CFGDBG(3, "attr `%s' defined", a->a_name); + + return (0); +} + +struct attr * +mkattr(const char *name) +{ + struct attr *a; + + a = ecalloc(1, sizeof *a); + if (ht_insert(attrtab, name, a)) { + free(a); + return NULL; } - if (devclass) { - char classenum[256], *cp; - int errored = 0; + a->a_name = name; + TAILQ_INIT(&a->a_files); + CFGDBG(3, "attr `%s' allocated", name); - (void)snprintf(classenum, sizeof(classenum), "DV_%s", name); - for (cp = classenum + 3; *cp; cp++) { - if (!errored && - (!isalnum((unsigned char)*cp) || - (isalpha((unsigned char)*cp) && !islower((unsigned char)*cp)))) { - cfgerror("device class names must be " - "lower-case alphanumeric characters"); - errored = 1; - } - *cp = toupper((unsigned char)*cp); - } - a->a_devclass = intern(classenum); - } else - a->a_devclass = NULL; + return a; +} + +/* "interface attribute" initialization */ +int +defiattr(const char *name, struct loclist *locs, struct attrlist *deps, + int devclass) +{ + struct attr *a; + int len; + struct loclist *ll; + + if (devclass) + panic("defattr(%s): locators and devclass", name); + + if (defattr(name, locs, deps, devclass) != 0) + return (1); + + a = getattr(name); + a->a_iattr = 1; + /* unwrap */ + a->a_locs = locs->ll_next; + locs->ll_next = NULL; + loclist_destroy(locs); len = 0; for (ll = a->a_locs; ll != NULL; ll = ll->ll_next) len++; a->a_loclen = len; - a->a_devs = NULL; - a->a_refs = NULL; - a->a_deps = deps; - a->a_expanding = 0; + if (deps) + CFGDBG(2, "attr `%s' iface with deps", a->a_name); + return (0); +} - /* Expand the attribute to check for cycles in the graph. */ - expandattr(a, NULL); +/* "device class" initialization */ +int +defdevclass(const char *name, struct loclist *locs, struct attrlist *deps, + int devclass) +{ + struct attr *a; + char classenum[256], *cp; + int errored = 0; + + if (deps) + panic("defattr(%s): dependencies and devclass", name); + + if (defattr(name, locs, deps, devclass) != 0) + return (1); + + a = getattr(name); + (void)snprintf(classenum, sizeof(classenum), "DV_%s", name); + for (cp = classenum + 3; *cp; cp++) { + if (!errored && + (!isalnum((unsigned char)*cp) || + (isalpha((unsigned char)*cp) && !islower((unsigned char)*cp)))) { + cfgerror("device class names must be " + "lower-case alphanumeric characters"); + errored = 1; + } + *cp = (char)toupper((unsigned char)*cp); + } + a->a_devclass = intern(classenum); return (0); } @@ -332,7 +462,6 @@ defdev(struct devbase *dev, struct loclist *loclist, struct attrlist *attrs, { struct loclist *ll; struct attrlist *al; - struct attr *a; if (dev == &errdev) goto bad; @@ -354,7 +483,7 @@ defdev(struct devbase *dev, struct loclist *loclist, struct attrlist *attrs, if (loclist != NULL) { ll = loclist; loclist = NULL; /* defattr disposes of them for us */ - if (defattr(dev->d_name, ll, NULL, 0)) + if (defiattr(dev->d_name, ll, NULL, 0)) goto bad; attrs = attrlist_cons(attrs, getattr(dev->d_name)); /* This used to be stored but was never used */ @@ -386,6 +515,12 @@ defdev(struct devbase *dev, struct loclist *loclist, struct attrlist *attrs, dev->d_ispseudo = ispseudo; dev->d_attrs = attrs; dev->d_classattr = NULL; /* for now */ + CFGDBG(3, "dev `%s' defined", dev->d_name); + + /* + * Implicit attribute definition for device. + */ + refattr(dev->d_name); /* * For each interface attribute this device refers to, add this @@ -397,18 +532,13 @@ defdev(struct devbase *dev, struct loclist *loclist, struct attrlist *attrs, * device has two classes). */ for (al = attrs; al != NULL; al = al->al_next) { - a = al->al_this; - if (a->a_iattr) - a->a_refs = addtoattr(a->a_refs, dev); - if (a->a_devclass != NULL) { - if (dev->d_classattr != NULL) { - cfgerror("device `%s' has multiple classes " - "(`%s' and `%s')", - dev->d_name, dev->d_classattr->a_name, - a->a_name); - } - dev->d_classattr = a; - } + /* + * Implicit attribute definition for device dependencies. + */ + refattr(al->al_this->a_name); + (void)ht_insert2(attrdeptab, dev->d_name, al->al_this->a_name, NULL); + CFGDBG(2, "device `%s' depends on attr `%s'", dev->d_name, + al->al_this->a_name); } return; bad: @@ -453,6 +583,7 @@ getdevbase(const char *name) TAILQ_INSERT_TAIL(&allbases, dev, d_next); if (ht_insert(devbasetab, name, dev)) panic("getdevbase(%s)", name); + CFGDBG(3, "devbase defined `%s'", dev->d_name); } return (dev); } @@ -504,6 +635,12 @@ defdevattach(struct deva *deva, struct devbase *dev, struct nvlist *atlist, deva->d_attrs = attrs; deva->d_atlist = atlist; deva->d_devbase = dev; + CFGDBG(3, "deva `%s' defined", deva->d_name); + + /* + * Implicit attribute definition for device attachment. + */ + refattr(deva->d_name); /* * Turn the `at' list into interface attributes (map each @@ -604,6 +741,41 @@ getattr(const char *name) return (a); } +/* + * Implicit attribute definition. + */ +struct attr * +refattr(const char *name) +{ + struct attr *a; + + if ((a = ht_lookup(attrtab, name)) == NULL) + a = mkattr(name); + return a; +} + +int +getrefattr(const char *name, struct attr **ra) +{ + struct attr *a; + + a = ht_lookup(attrtab, name); + if (a == NULL) { + *ra = NULL; + return (0); + } + /* + * Check if the existing attr is only referenced, not really defined. + */ + if (a->a_deps == NULL && + a->a_iattr == 0 && + a->a_devclass == 0) { + *ra = a; + return (0); + } + return (1); +} + /* * Recursively expand an attribute and its dependencies, checking for * cycles, and invoking a callback for each attribute found. @@ -717,7 +889,7 @@ resolve(struct nvlist **nvp, const char *name, const char *what, const char *cp; devmajor_t maj; devminor_t min; - int i, l; + size_t i, l; int unit; char buf[NAMESIZE]; @@ -737,7 +909,7 @@ resolve(struct nvlist **nvp, const char *name, const char *what, cp = makedevstr(maj, min); } else cp = NULL; - *nvp = nv = newnv(NULL, cp, NULL, d, NULL); + *nvp = nv = newnv(NULL, cp, NULL, (long long)d, NULL); } if ((dev_t)nv->nv_num != NODEV) { /* @@ -784,7 +956,7 @@ resolve(struct nvlist **nvp, const char *name, const char *what, * don't bother making a device number. */ if (has_attr(dev->d_attrs, s_ifnet)) { - nv->nv_num = NODEV; + nv->nv_num = (long long)NODEV; nv->nv_ifunit = unit; /* XXX XXX XXX */ } else { maj = dev2major(dev); @@ -793,7 +965,7 @@ resolve(struct nvlist **nvp, const char *name, const char *what, name, what, nv->nv_str); return (1); } - nv->nv_num = makedev(maj, unit * maxpartitions + part); + nv->nv_num = (long long)makedev(maj, unit * maxpartitions + part); } nv->nv_name = dev->d_name; @@ -877,6 +1049,7 @@ delconf(const char *name) { struct config *cf; + CFGDBG(5, "deselecting config `%s'", name); if (ht_lookup(cfhashtab, name) == NULL) { cfgerror("configuration `%s' undefined", name); return; @@ -1075,6 +1248,7 @@ adddev(const char *name, const char *at, struct loclist *loclist, int flags) i->i_pspec = p; i->i_atdeva = iba; i->i_cfflags = flags; + CFGDBG(3, "devi `%s' added", i->i_name); *iba->d_ipp = i; iba->d_ipp = &i->i_asame; @@ -1093,6 +1267,7 @@ deldevi(const char *name, const char *at) int unit; char base[NAMESIZE]; + CFGDBG(5, "deselecting devi `%s'", name); if (split(name, strlen(name), base, sizeof base, &unit)) { cfgerror("invalid device name `%s'", name); return; @@ -1131,6 +1306,7 @@ remove_devi(struct devi *i) struct devi *f, *j, **ppi; struct deva *iba; + CFGDBG(5, "removing devi `%s'", i->i_name); f = ht_lookup(devitab, i->i_name); if (f == NULL) panic("remove_devi(): instance %s disappeared from devitab", @@ -1154,7 +1330,8 @@ remove_devi(struct devi *i) * list. */ if (i != f) { - for (j = f; j->i_alias != i; j = j->i_alias); + for (j = f; j->i_alias != i; j = j->i_alias) + continue; j->i_alias = i->i_alias; } else { if (i->i_alias == NULL) { @@ -1177,7 +1354,8 @@ remove_devi(struct devi *i) */ for (ppi = &d->d_ihead; *ppi != NULL && *ppi != i && (*ppi)->i_bsame != i; - ppi = &(*ppi)->i_bsame); + ppi = &(*ppi)->i_bsame) + continue; if (*ppi == NULL) panic("deldev: dev (%s) doesn't list the devi" " (%s at %s)", d->d_name, i->i_name, i->i_at); @@ -1203,7 +1381,8 @@ remove_devi(struct devi *i) iba = i->i_atdeva; for (ppi = &iba->d_ihead; *ppi != NULL && *ppi != i && (*ppi)->i_asame != i; - ppi = &(*ppi)->i_asame); + ppi = &(*ppi)->i_asame) + continue; if (*ppi == NULL) panic("deldev: deva (%s) doesn't list the devi (%s)", iba->d_name, i->i_name); @@ -1267,7 +1446,8 @@ remove_devi(struct devi *i) panic("remove_devi(%s) - can't add to deaddevitab", i->i_name); } else { - for (j = f; j->i_alias != NULL; j = j->i_alias); + for (j = f; j->i_alias != NULL; j = j->i_alias) + continue; j->i_alias = i; } /* @@ -1295,13 +1475,18 @@ deldeva(const char *at) if (i->i_at == NULL) stack = newnv(NULL, NULL, i, 0, stack); } else { - int l; + size_t l; + CFGDBG(5, "deselecting deva `%s'", at); + if (at[0] == '\0') + goto out; + l = strlen(at) - 1; if (at[l] == '?' || isdigit((unsigned char)at[l])) { char base[NAMESIZE]; if (split(at, l+1, base, sizeof base, &unit)) { +out: cfgerror("invalid attachment name `%s'", at); return; } @@ -1376,15 +1561,20 @@ deldeva(const char *at) void deldev(const char *name) { - int l; + size_t l; struct devi *firsti, *i; struct nvlist *nv, *stack = NULL; + CFGDBG(5, "deselecting dev `%s'", name); + if (name[0] == '\0') + goto out; + l = strlen(name) - 1; if (name[l] == '*' || isdigit((unsigned char)name[l])) { /* `no mydev0' or `no mydev*' */ firsti = ht_lookup(devitab, name); if (firsti == NULL) { +out: cfgerror("unknown instance %s", name); return; } @@ -1530,6 +1720,7 @@ delpseudo(const char *name) struct devbase *d; struct devi *i; + CFGDBG(5, "deselecting pseudo `%s'", name); d = ht_lookup(devbasetab, name); if (d == NULL) { cfgerror("undefined pseudo-device %s", name); @@ -1599,7 +1790,8 @@ fixdevis(void) struct devi *i; int error = 0; - TAILQ_FOREACH(i, &alldevi, i_next) + TAILQ_FOREACH(i, &alldevi, i_next) { + CFGDBG(3, "fixing devis `%s'", i->i_name); if (i->i_active == DEVI_ACTIVE) selectbase(i->i_base, i->i_atdeva); else if (i->i_active == DEVI_ORPHAN) { @@ -1616,6 +1808,7 @@ fixdevis(void) cfgxwarn(i->i_srcfile, i->i_lineno, "ignoring " "explicitly orphaned instance `%s at %s'", i->i_name, i->i_at); + } if (error) return error; @@ -1707,8 +1900,8 @@ concat(const char *name, int c) len = sizeof(buf) - 2; } memmove(buf, name, len); - buf[len] = c; - buf[len + 1] = 0; + buf[len] = (char)c; + buf[len + 1] = '\0'; return (intern(buf)); } @@ -1760,11 +1953,74 @@ split(const char *name, size_t nlen, char *base, size_t bsize, int *aunit) return (0); } +void +addattr(const char *name) +{ + struct attr *a; + + a = refattr(name); + selectattr(a); +} + +void +delattr(const char *name) +{ + struct attr *a; + + a = refattr(name); + deselectattr(a); +} + void selectattr(struct attr *a) { + struct attrlist *al; + struct attr *dep; - (void)ht_insert(selecttab, a->a_name, __UNCONST(a->a_name)); + CFGDBG(5, "selecting attr `%s'", a->a_name); + for (al = a->a_deps; al != NULL; al = al->al_next) { + dep = al->al_this; + selectattr(dep); + } + if (ht_insert(selecttab, a->a_name, __UNCONST(a->a_name)) == 0) + nattrs++; + CFGDBG(3, "attr selected `%s'", a->a_name); +} + +static int +deselectattrcb2(const char *name1, const char *name2, void *v, void *arg) +{ + const char *name = arg; + + if (strcmp(name, name2) == 0) + delattr(name1); + return 0; +} + +void +deselectattr(struct attr *a) +{ + + CFGDBG(5, "deselecting attr `%s'", a->a_name); + ht_enumerate2(attrdeptab, deselectattrcb2, __UNCONST(a->a_name)); + if (ht_remove(selecttab, a->a_name) == 0) + nattrs--; + CFGDBG(3, "attr deselected `%s'", a->a_name); +} + +static int +dumpattrdepcb2(const char *name1, const char *name2, void *v, void *arg) +{ + + CFGDBG(3, "attr `%s' depends on attr `%s'", name1, name2); + return 0; +} + +void +dependattrs(void) +{ + + ht_enumerate2(attrdeptab, dumpattrdepcb2, NULL); } /* @@ -1778,17 +2034,27 @@ selectbase(struct devbase *d, struct deva *da) struct attrlist *al; (void)ht_insert(selecttab, d->d_name, __UNCONST(d->d_name)); + CFGDBG(3, "devbase selected `%s'", d->d_name); + CFGDBG(5, "selecting dependencies of devbase `%s'", d->d_name); for (al = d->d_attrs; al != NULL; al = al->al_next) { a = al->al_this; expandattr(a, selectattr); } + + struct attr *devattr; + devattr = refattr(d->d_name); + expandattr(devattr, selectattr); + if (da != NULL) { (void)ht_insert(selecttab, da->d_name, __UNCONST(da->d_name)); + CFGDBG(3, "devattr selected `%s'", da->d_name); for (al = da->d_attrs; al != NULL; al = al->al_next) { a = al->al_this; expandattr(a, selectattr); } } + + fixdev(d); } /* @@ -1839,7 +2105,7 @@ fixloc(const char *name, struct attr *attr, struct loclist *got) if (attr->a_loclen == 0) /* e.g., "at root" */ lp = nullvec; else - lp = emalloc((attr->a_loclen + 1) * sizeof(const char *)); + lp = emalloc((size_t)(attr->a_loclen + 1) * sizeof(const char *)); for (n = got; n != NULL; n = n->ll_next) n->ll_num = -1; nmissing = 0; diff --git a/usr.bin/config/sem.h b/usr.bin/config/sem.h index 66a393ad48cc..a478c07adbb6 100644 --- a/usr.bin/config/sem.h +++ b/usr.bin/config/sem.h @@ -1,4 +1,4 @@ -/* $NetBSD: sem.h,v 1.10 2012/03/11 21:16:08 dholland Exp $ */ +/* $NetBSD: sem.h,v 1.10.10.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -46,15 +46,25 @@ void setversion(int); void setdefmaxusers(int, int, int); void setmaxusers(int); void setident(const char *); +int defattr0(const char *, struct loclist *, struct attrlist *, int); int defattr(const char *, struct loclist *, struct attrlist *, int); +int defiattr(const char *, struct loclist *, struct attrlist *, int); +int defdevclass(const char *, struct loclist *, struct attrlist *, int); void defdev(struct devbase *, struct loclist *, struct attrlist *, int); void defdevattach(struct deva *, struct devbase *, struct nvlist *, struct attrlist *); struct devbase *getdevbase(const char *); struct deva *getdevattach(const char *); +struct attr *mkattr(const char *); struct attr *getattr(const char *); +struct attr *refattr(const char *); +int getrefattr(const char *, struct attr **); void expandattr(struct attr *, void (*)(struct attr *)); +void addattr(const char *); +void delattr(const char *); void selectattr(struct attr *); +void deselectattr(struct attr *); +void dependattrs(void); void setmajor(struct devbase *, int); void addconf(struct config *); void setconf(struct nvlist **, const char *, struct nvlist *); @@ -67,7 +77,7 @@ void deldev(const char *); void addpseudo(const char *, int); void delpseudo(const char *); void addpseudoroot(const char *); -void adddevm(const char *, int, int, +void adddevm(const char *, devmajor_t, devmajor_t, struct condexpr *, struct nvlist *); int fixdevis(void); const char *ref(const char *); @@ -78,3 +88,4 @@ int has_attr(struct attrlist *, const char *); extern const char *s_qmark; extern const char *s_none; extern const char *s_ifnet; +extern size_t nattrs; diff --git a/usr.bin/config/util.c b/usr.bin/config/util.c index 0c8fab81e031..0544a1bcdf0a 100644 --- a/usr.bin/config/util.c +++ b/usr.bin/config/util.c @@ -1,4 +1,4 @@ -/* $NetBSD: util.c,v 1.16 2013/11/01 21:39:13 christos Exp $ */ +/* $NetBSD: util.c,v 1.16.4.1 2015/03/06 21:00:23 snj Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,6 +44,9 @@ #include "nbtool_config.h" #endif +#include +__RCSID("$NetBSD: util.c,v 1.16.4.1 2015/03/06 21:00:23 snj Exp $"); + #include #include #include @@ -57,6 +60,8 @@ static void cfgvxerror(const char *, int, const char *, va_list) __printflike(3, 0); +static void cfgvxdbg(const char *, int, const char *, va_list) + __printflike(3, 0); static void cfgvxwarn(const char *, int, const char *, va_list) __printflike(3, 0); static void cfgvxmsg(const char *, int, const char *, const char *, va_list) @@ -413,6 +418,17 @@ condexpr_destroy(struct condexpr *expr) * Diagnostic messages */ +void +cfgdbg(const char *fmt, ...) +{ + va_list ap; + extern const char *yyfile; + + va_start(ap, fmt); + cfgvxdbg(yyfile, currentline(), fmt, ap); + va_end(ap); +} + void cfgwarn(const char *fmt, ...) { @@ -434,6 +450,12 @@ cfgxwarn(const char *file, int line, const char *fmt, ...) va_end(ap); } +static void +cfgvxdbg(const char *file, int line, const char *fmt, va_list ap) +{ + cfgvxmsg(file, line, "debug: ", fmt, ap); +} + static void cfgvxwarn(const char *file, int line, const char *fmt, va_list ap) {