From fee8e88355b32d2b0f431f4a42a0ff79ad5eba52 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Boric Date: Mon, 14 Nov 2016 22:26:31 +0100 Subject: [PATCH] import config command --- distrib/sets/lists/minix-base/mi | 1 + distrib/sets/lists/minix-man/mi | 5 +- usr.bin/Makefile | 2 +- usr.bin/config/Makefile | 27 + usr.bin/config/TODO | 461 +++++ usr.bin/config/config | Bin 0 -> 422059 bytes usr.bin/config/config.1 | 358 ++++ usr.bin/config/config.5 | 764 ++++++++ usr.bin/config/config.samples.5 | 252 +++ usr.bin/config/defs.h | 666 +++++++ usr.bin/config/files.c | 622 ++++++ usr.bin/config/gram.c | 2431 +++++++++++++++++++++++ usr.bin/config/gram.h | 89 + usr.bin/config/gram.y | 1450 ++++++++++++++ usr.bin/config/hash.c | 456 +++++ usr.bin/config/lint.c | 208 ++ usr.bin/config/main.c | 2037 ++++++++++++++++++++ usr.bin/config/mkdevsw.c | 241 +++ usr.bin/config/mkheaders.c | 547 ++++++ usr.bin/config/mkioconf.c | 510 +++++ usr.bin/config/mkmakefile.c | 598 ++++++ usr.bin/config/mkswap.c | 164 ++ usr.bin/config/pack.c | 352 ++++ usr.bin/config/scan.c | 3094 ++++++++++++++++++++++++++++++ usr.bin/config/scan.l | 638 ++++++ usr.bin/config/sem.c | 2177 +++++++++++++++++++++ usr.bin/config/sem.h | 91 + usr.bin/config/util.c | 575 ++++++ 28 files changed, 18814 insertions(+), 2 deletions(-) create mode 100644 usr.bin/config/Makefile create mode 100644 usr.bin/config/TODO create mode 100755 usr.bin/config/config create mode 100644 usr.bin/config/config.1 create mode 100644 usr.bin/config/config.5 create mode 100644 usr.bin/config/config.samples.5 create mode 100644 usr.bin/config/defs.h create mode 100644 usr.bin/config/files.c create mode 100644 usr.bin/config/gram.c create mode 100644 usr.bin/config/gram.h create mode 100644 usr.bin/config/gram.y create mode 100644 usr.bin/config/hash.c create mode 100644 usr.bin/config/lint.c create mode 100644 usr.bin/config/main.c create mode 100644 usr.bin/config/mkdevsw.c create mode 100644 usr.bin/config/mkheaders.c create mode 100644 usr.bin/config/mkioconf.c create mode 100644 usr.bin/config/mkmakefile.c create mode 100644 usr.bin/config/mkswap.c create mode 100644 usr.bin/config/pack.c create mode 100644 usr.bin/config/scan.c create mode 100644 usr.bin/config/scan.l create mode 100644 usr.bin/config/sem.c create mode 100644 usr.bin/config/sem.h create mode 100644 usr.bin/config/util.c diff --git a/distrib/sets/lists/minix-base/mi b/distrib/sets/lists/minix-base/mi index bb4cbec8b..d45151deb 100644 --- a/distrib/sets/lists/minix-base/mi +++ b/distrib/sets/lists/minix-base/mi @@ -284,6 +284,7 @@ ./usr/bin/column minix-base ./usr/bin/comm minix-base ./usr/bin/compress minix-base +./usr/bin/config minix-base ./usr/bin/cpio minix-base ./usr/bin/cprofalyze minix-base obsolete ./usr/bin/crc minix-base diff --git a/distrib/sets/lists/minix-man/mi b/distrib/sets/lists/minix-man/mi index a188227b3..f87267a7f 100644 --- a/distrib/sets/lists/minix-man/mi +++ b/distrib/sets/lists/minix-man/mi @@ -66,6 +66,7 @@ ./usr/man/man1/comm.1 minix-man ./usr/man/man1/command.1 minix-man obsolete ./usr/man/man1/compress.1 minix-man +./usr/man/man1/config.1 minix-man ./usr/man/man1/continue.1 minix-man obsolete ./usr/man/man1/cp.1 minix-man ./usr/man/man1/cpio.1 minix-man @@ -3268,6 +3269,8 @@ ./usr/man/man5/blacklistd.conf.5 minix-man ./usr/man/man5/boot.cfg.5 minix-man ./usr/man/man5/cdb.5 minix-man +./usr/man/man5/config.5 minix-man +./usr/man/man5/config.samples.5 minix-man ./usr/man/man5/configfile.5 minix-man ./usr/man/man5/cpio.5 minix-man ./usr/man/man5/crontab.5 minix-man @@ -3424,7 +3427,7 @@ ./usr/man/man8/pr_routes.8 minix-man ./usr/man/man8/printroot.8 minix-man ./usr/man/man8/pwd_mkdb.8 minix-man -./usr/man/man8/pwdauth.8 minix-man obsolete +./usr/man/man8/pwdauth.8 minix-man obsolete ./usr/man/man8/rarpd.8 minix-man ./usr/man/man8/rawspeed.8 minix-man ./usr/man/man8/rdate.8 minix-man diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 0c8cf553b..01e633bd2 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -7,7 +7,7 @@ SUBDIR= asa \ banner basename \ bzip2 bzip2recover cal calendar \ checknr chpass cksum cmp col colcrt colrm \ - column comm csplit ctags cut \ + column comm config csplit ctags cut \ deroff dirname du \ env expand \ false find finger flock fold fpr from \ diff --git a/usr.bin/config/Makefile b/usr.bin/config/Makefile new file mode 100644 index 000000000..429921eeb --- /dev/null +++ b/usr.bin/config/Makefile @@ -0,0 +1,27 @@ +# $NetBSD: Makefile,v 1.10 2014/10/29 19:10:49 christos 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 \ + mkmakefile.c mkswap.c pack.c scan.l sem.c util.c + +.PATH: ${NETBSDSRCDIR}/usr.bin/cksum +SRCS+= crc.c + +MAN= config.1 +MAN+= config.5 config.samples.5 +YHEADER=1 +CPPFLAGS+=-I${.CURDIR} -I. +CPPFLAGS+= -I${NETBSDSRCDIR}/usr.bin/cksum + +.ifndef HOSTPROG +LDADD+=-lutil +DPADD+=${LIBUTIL} +.endif + +CWARNFLAGS+=-Wno-format-y2k + +.include diff --git a/usr.bin/config/TODO b/usr.bin/config/TODO new file mode 100644 index 000000000..d92d3c5c8 --- /dev/null +++ b/usr.bin/config/TODO @@ -0,0 +1,461 @@ +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 + + Always provide xxxbusprint() (and xxxbussubmatch if multiple children). + Extend struct cfiattrdata like: + + struct cfiattrdata { + const char *ci_name; + cfprint_t ci_print; + cfsubmatch_t ci_submatch; + int ci_loclen; + const struct cflocdesc ci_locdesc[]; + }; + +o Simplify child configuration API + + With said struct cfiattrdata extension, config_found*() can omit + print/submatch args. If the found child is known (e.g., "pcibus" creating + "pci"): + + config_found(self, "pcibus"); + + If finding unknown children (e.g. "pci" finding pci devices): + + config_find(self, "pci", locs, aux); + +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 Always use explicit kernel linker script. + + ld(1) has an option -T to use a given linker script. If not + specified, a default, built-in linker script, mainly meant for userland + programs, is used. + + Currently m68k, sh3, and vax don't have kernel linker scripts. These work + because these have no constraints about page boundary; they map and access + kernel .text/.data in the same way. + +o Pass input files to ${LD} via linker script. + + Instead of passing input files on command-line, output "INPUT(xxx.o)" + commands, and include it from generated linker scripts. + +o Generate `*.d' files. + + Output source/object files in raw texts instead of `Makefile'. Generate + `*.d' (make(1) depend) files. make(1) knows which object files are to be + compiled. With "INPUT(xxx.o)" linker scripts, either generated `Makefile' + or `Makefile.kern.inc' don't need to keep source/object files in variables. + +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 Fix db_symtab copying (COPY_SYMTAB) + + o Collect all objects and create a relocatable (netbsd.ro). At this point, + the number of symbols is known. + + o Relink and allocate .rodata.symtab with the calculated size of .symtab. + Linker recalculates symbol addresses. + + o Embed the .symtab into .rodata.symtab. + + o Link the final netbsd ELF. + + The make(1) rule (dependency graph) should be identical with/without + COPY_SYMTAB. Kill .ifdef COPY_SYMTAB from $S/conf/Makefile.kern.inc. + +o Preprocess and generate linker scripts dynamically. + + Include opt_xxx.h and replace some constant values (e.g. COHERENCY_UNIT, + PAGE_SIZE, KERNEL_BASE_PHYS, KERNEL_BASE_VIRT, ...) with cpp(1). + + Don't unnecessarily define symbols. Don't use sed(1). + +o Clean up linker scripts. + + o Don't specify OUTPUT_FORMAT()/OUTPUT_ARCH() + + These are basically set in compilers/linkers. If non-default ABI is used, + command-line arguments should be specified. + + o Remove .rel/.rela handlings. + + These are set in relocatable objects, and handled by dynamic linkers. + Totally irrelefant for kernels. + + o Clean up debug section handlings. + + o Document (section boundary) symbols set in linker scripts. + + There must be a reason why symbols are defined and exported. + + PROVIDE() is to define internal symbols. + + o Clean up load addresses. + + o Program headers. + + o According to matt@, .ARM.extab/.ARM.exidx sections are no longer needed. + +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.) + +o Convert pseudo(dev) attach functions to take (void) (== kernel ctors). + + The pseudo attach function was originally designed to take `int n' as + the number of instances of the pseudo device. Now most of pseudo + devices have been converted to be `cloneable', meaning that their + instances are dynamically allocated at run-time, because guessing how + much instances are needed for users at compile time is almost impossible. + Restricting such a pure software resource at compile time is senseless, + considering that the rest of the world is dynamic. + + If pseudo attach functions once become (void), config(1) no longer + has to generate iteration to call those functions, by making them part + of kernel constructors, that are a list of (void) functions. + + Some pseudo devices may have dependency/ordering problems, because + pseudo attach functions have no choice when to be called. This could + be solved by converting to kctors, where functions are called in order + by dependency. + +o Enhance ioconf behavior for pseudo-devices + + See "bin/48571: config(1) ioconf is insufficient for pseudo-devices" for + more details. In a nutshell, it would be "useful" for config to emit + the necessary stuff in the generated ioconf.[ch] to enable use of + config_{init,fini}_component() for attaching and detaching pseudodev's. + + Currently, you need to manually construct your own data structures, and + manually "attach" them, one at a time. This leads to duplication of + code (where multiple drivers contain the same basic logic), and doesn't + necessarily handle all of the "frobbing" of the kernel lists. + +o Don't use -Ttext ${TEXTADDR}. + + Although ld(1)'s `-Ttext ${TEXTADDR}' is an easy way to specify the virtual + base address of .text at link time, it needs to change command-line; in + kernel build, Makefile needs to change to reflect kernel's configuration. + It is simpler to reflect kenel configuration using linker script via assym.h. + +o Convert ${DIAGNOSTIC} and ${DEBUG} as flags (defflag). + + Probably generate opt_diagnostic.h/opt_debug.h and include them in + sys/param.h. + +o Strictly define DIAGNOSTIC. + + It is possible to make DIAGNOSTIC kernel and modules binary-compatible with + non-DIAGNOSTIC ones. In that case, debug type informations should match + theoretically (not confirmed). + +o Use suffix rules. + + Build objects following suffix rules. Source files are defined as relative to + $S (e.g. sys/kern/init_main.c) and objects are generated in the corresponding + subdirectories under kernel build directories (e.g. + .../compile/GENERIC/sys/kern/init_main.o). Dig subdirectories from within + config(1). + + Debugging (-g) and profiling (-pg) objects could be generated with *.go/*.po + suffixes as userland libraries do. Maybe something similar for + DIAGNOSTIC/DEBUG. + + genassym(1) definitions will be split into per-source instead of the single + assym.h. Dependencies are corrected and some of misterious dependencies on + `Makefile' in sys/conf/Makefile.kern.inc can go away. + +o Define genassym(1) symbols per file. + + Have each file define symbols that have to be generated by genassym(1) so + that more accurate dependency is reflected. + + For example, if foo.S needs some symbols, it defines them in foo.assym, + declaring that foo.S depends on foo.assym.h, and includes foo.assym.h. + foo.assym.h is generated by following the suffix rule of .assym -> .assym.h. + When one header is updated, only related *.assym.h files are regenerated, + instead of rebuilding all MD/*.S files that depend on the global, single + assym.h. + +o Support library. + + Provide a consistent way to build library either as .o or .a. + + Build libraries in sub-make. Don't include library makefiles. Don't + pollute search path (.PATH). libkern does too much. + +o Accept `.a' suffix. + + Make "file" command accept `.a' suffix. Handle it the same way as `.o'. + +o Clean up ${MD_OBJS} and friends in Makefile.${MACHINE}. + + Don't use ${MD_OBJS}, ${MD_LIBS}, ${MD_SFILES}, and ${MD_CFILES}. + + List files in config(5)'s "file". Override build rules only when neccesary. + + Rely on the fact that config(1) parses files.${MACHINE} first, outputs + files in the order it parses files.* (actually include depth), and + `Makefile.kern.inc' preserve file order to pass to ${LD}. + +o Clean up CTF-related rules. + + Don't overwrite compile/link rules conditionally by existence of + ${CTFCONVERT}/${CTFMERGE}. Give a separate suffix (*.ctfo) and define its + rules (.c -> .ctfo). diff --git a/usr.bin/config/config b/usr.bin/config/config new file mode 100755 index 0000000000000000000000000000000000000000..2e3baf7cea97c9a52dbc24deb7f77d47ea89b460 GIT binary patch literal 422059 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

KcoFPm!UnQTXGx&ULOCmuPE%ZM_(k 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

Uz7jM2aq%P!Zg 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 +#include +#include + +#if !defined(MAKE_BOOTSTRAP) && defined(BSD) +#include +#include +#endif + +#include +#include +#include + +/* These are really for MAKE_BOOTSTRAP but harmless. */ +#ifndef __dead +#define __dead +#endif +#ifndef __printflike +#define __printflike(a, b) +#endif +#ifndef _PATH_DEVNULL +#define _PATH_DEVNULL "/dev/null" +#endif + +#ifdef MAKE_BOOTSTRAP +#undef dev_t +#undef devmajor_t +#undef devminor_t +#undef NODEV +#undef NODEVMAJOR +#undef major +#undef minor +#undef makedev +#define dev_t unsigned int /* XXX: assumes int is 32 bits */ +#define NODEV ((dev_t)-1) +#define devmajor_t int +#define devminor_t int +#define NODEVMAJOR (-1) +#define major(x) ((devmajor_t)((((x) & 0x000fff00) >> 8))) +#define minor(x) ((devminor_t)((((x) & 0xfff00000) >> 12) | \ + (((x) & 0x000000ff) >> 0))) +#define makedev(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \ + (((y) << 12) & 0xfff00000) | \ + (((y) << 0) & 0x000000ff))) +#define __attribute__(x) +#endif /* MAKE_BOOTSTRAP */ + +#undef setprogname +#undef getprogname +extern const char *progname; +#define setprogname(s) ((void)(progname = (s))) +#define getprogname() (progname) + +#define ARRCHR '#' + +/* + * 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 20150846 +#define CONFIG_MINVERSION 0 + +/* + * Name/value lists. Values can be strings or pointers and/or can carry + * integers. The names can be NULL, resulting in simple value lists. + */ +struct nvlist { + struct nvlist *nv_next; + const char *nv_name; + const char *nv_str; + void *nv_ptr; + long long nv_num; + int nv_ifunit; /* XXX XXX XXX */ + int nv_flags; +#define NV_DEPENDED 1 +}; + +/* + * Kernel configurations. + */ +struct config { + TAILQ_ENTRY(config) cf_next; + const char *cf_name; /* "netbsd" */ + int cf_lineno; /* source line */ + const char *cf_fstype; /* file system type */ + struct nvlist *cf_root; /* "root on ra0a" */ + struct nvlist *cf_dump; /* "dumps on ra0b" */ +}; + +/* + * Option definition list + */ +struct defoptlist { + struct defoptlist *dl_next; + const char *dl_name; + const char *dl_value; + const char *dl_lintvalue; + int dl_obsolete; + struct nvlist *dl_depends; +}; + +struct files; +TAILQ_HEAD(filelist, files); + +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; + struct filelist m_files; + int m_weight; +}; + +/* + * Attributes. These come in three flavors: "plain", "device class," + * and "interface". Plain attributes (e.g., "ether") simply serve + * to pull in files. Device class attributes are like plain + * attributes, but additionally specify a device class (e.g., the + * "disk" device class attribute specifies that devices with the + * attribute belong to the "DV_DISK" class) and are mutually exclusive. + * Interface attributes (e.g., "scsi") carry three lists: locators, + * child devices, and references. The locators are those things + * that must be specified in order to configure a device instance + * using this attribute (e.g., "tg0 at scsi0"). The a_devs field + * lists child devices that can connect here (e.g., "tg"s), while + * the a_refs are parents that carry the attribute (e.g., actual + * SCSI host adapter drivers such as the SPARC "esp"). + */ +struct attr { + /* 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 */ + struct loclist *a_locs; /* locators required */ + int a_loclen; /* length of above list */ + struct nvlist *a_devs; /* children */ + struct nvlist *a_refs; /* parents */ + + /* "device class" */ + const char *a_devclass; /* device class described */ +}; + +/* + * List of attributes. + */ +struct attrlist { + struct attrlist *al_next; + struct attr *al_this; +}; + +/* + * List of locators. (Either definitions or uses...) + * + * XXX it would be nice if someone could clarify wtf ll_string and ll_num + * are actually holding. (This stuff was previously stored in a very ad + * hoc fashion, and the code is far from clear.) + */ +struct loclist { + const char *ll_name; + const char *ll_string; + long long ll_num; + struct loclist *ll_next; +}; + +/* + * Parent specification. Multiple device instances may share a + * given parent spec. Parent specs are emitted only if there are + * device instances which actually reference it. + */ +struct pspec { + TAILQ_ENTRY(pspec) p_list; /* link on parent spec list */ + struct attr *p_iattr; /* interface attribute of parent */ + struct devbase *p_atdev; /* optional parent device base */ + int p_atunit; /* optional parent device unit */ + struct nvlist *p_devs; /* children using it */ + int p_inst; /* parent spec instance */ + int p_active; /* parent spec is actively used */ +}; + +/* + * The "base" part (struct devbase) of a device ("uba", "sd"; but not + * "uba2" or "sd0"). It may be found "at" one or more attributes, + * including "at root" (this is represented by a NULL attribute), as + * specified by the device attachments (struct deva). + * + * Each device may also export attributes. If any provide an output + * interface (e.g., "esp" provides "scsi"), other devices (e.g., + * "tg"s) can be found at instances of this one (e.g., "esp"s). + * Such a connection must provide locators as specified by that + * interface attribute (e.g., "target"). The base device can + * export both output (aka `interface') attributes, as well as + * import input (`plain') attributes. Device attachments may + * only import input attributes; it makes no sense to have a + * specific attachment export a new interface to other devices. + * + * Each base carries a list of instances (via d_ihead). Note that this + * list "skips over" aliases; those must be found through the instances + * themselves. Each base also carries a list of possible attachments, + * each of which specify a set of devices that the device can attach + * to, as well as the device instances that are actually using that + * attachment. + */ +struct devbase { + const char *d_name; /* e.g., "sd" */ + TAILQ_ENTRY(devbase) d_next; + int d_isdef; /* set once properly defined */ + int d_ispseudo; /* is a pseudo-device */ + devmajor_t d_major; /* used for "root on sd0", e.g. */ + struct attrlist *d_attrs; /* attributes, if any */ + int d_umax; /* highest unit number + 1 */ + struct devi *d_ihead; /* first instance, if any */ + struct devi **d_ipp; /* used for tacking on more instances */ + struct deva *d_ahead; /* first attachment, if any */ + struct deva **d_app; /* used for tacking on attachments */ + struct attr *d_classattr; /* device class attribute (if any) */ +}; + +struct deva { + const char *d_name; /* name of attachment, e.g. "com_isa" */ + TAILQ_ENTRY(deva) d_next; /* list of all instances */ + struct deva *d_bsame; /* list on same base */ + int d_isdef; /* set once properly defined */ + struct devbase *d_devbase; /* the base device */ + struct nvlist *d_atlist; /* e.g., "at tg" (attr list) */ + struct attrlist *d_attrs; /* attributes, if any */ + struct devi *d_ihead; /* first instance, if any */ + struct devi **d_ipp; /* used for tacking on more instances */ +}; + +/* + * An "instance" of a device. The same instance may be listed more + * than once, e.g., "xx0 at isa? port FOO" + "xx0 at isa? port BAR". + * + * After everything has been read in and verified, the devi's are + * "packed" to collect all the information needed to generate ioconf.c. + * In particular, we try to collapse multiple aliases into a single entry. + * We then assign each "primary" (non-collapsed) instance a cfdata index. + * Note that there may still be aliases among these. + */ +struct devi { + /* created while parsing config file */ + const char *i_name; /* e.g., "sd0" */ + int i_unit; /* unit from name, e.g., 0 */ + struct devbase *i_base;/* e.g., pointer to "sd" base */ + TAILQ_ENTRY(devi) i_next; /* list of all instances */ + struct devi *i_bsame; /* list on same base */ + struct devi *i_asame; /* list on same base attachment */ + struct devi *i_alias; /* other aliases of this instance */ + const char *i_at; /* where this is "at" (NULL if at root) */ + struct pspec *i_pspec; /* parent spec (NULL if at root) */ + struct deva *i_atdeva; + const char **i_locs; /* locators (as given by pspec's iattr) */ + int i_cfflags; /* flags from config line */ + int i_lineno; /* line # in config, for later errors */ + const char *i_srcfile; /* file it appears in */ + int i_level; /* position between negated instances */ + int i_active; +#define DEVI_ORPHAN 0 /* instance has no active parent */ +#define DEVI_ACTIVE 1 /* instance has an active parent */ +#define DEVI_IGNORED 2 /* instance's parent has been removed */ +#define DEVI_BROKEN 3 /* instance is broken (syntax error) */ + int i_pseudoroot; /* instance is pseudoroot */ + + /* created during packing or ioconf.c generation */ + short i_collapsed; /* set => this alias no longer needed */ + u_short i_cfindex; /* our index in cfdata */ + int i_locoff; /* offset in locators.vec */ + +}; +/* special units */ +#define STAR (-1) /* unit number for, e.g., "sd*" */ +#define WILD (-2) /* unit number for, e.g., "sd?" */ + +/* + * Files (*.c, *.S, or *.o). This structure defines the common fields + * between the two. + */ +struct files { + TAILQ_ENTRY(files) fi_next; + TAILQ_ENTRY(files) fi_snext; /* per-suffix list */ + const char *fi_srcfile; /* the name of the "files" file that got us */ + u_short fi_srcline; /* and the line number */ + u_char fi_flags; /* as below */ + const char *fi_tail; /* name, i.e., strrchr(fi_path, '/') + 1 */ + const char *fi_base; /* tail minus ".c" (or whatever) */ + const char *fi_dir; /* path to file */ + const char *fi_path; /* full file path */ + const char *fi_prefix; /* any file prefix */ + const char *fi_buildprefix; /* prefix in builddir */ + int fi_suffix; /* single char suffix */ + size_t fi_len; /* path string length */ + struct condexpr *fi_optx; /* options expression */ + struct nvlist *fi_optf; /* flattened version of above, if needed */ + const char *fi_mkrule; /* special make rule, if any */ + struct attr *fi_attr; /* owner attr */ + int fi_order; /* score of order in ${ALLFILES} */ + TAILQ_ENTRY(files) fi_anext; /* next file in attr */ +}; + +/* flags */ +#define FI_SEL 0x01 /* selected */ +#define FI_NEEDSCOUNT 0x02 /* needs-count */ +#define FI_NEEDSFLAG 0x04 /* needs-flag */ +#define FI_HIDDEN 0x08 /* obscured by other(s), base names overlap */ + +extern size_t nselfiles; +extern struct files **selfiles; + +/* + * Condition expressions. + */ + +enum condexpr_types { + CX_ATOM, + CX_NOT, + CX_AND, + CX_OR, +}; +struct condexpr { + enum condexpr_types cx_type; + union { + const char *atom; + struct condexpr *not; + struct { + struct condexpr *left; + struct condexpr *right; + } and, or; + } cx_u; +}; +#define cx_atom cx_u.atom +#define cx_not cx_u.not +#define cx_and cx_u.and +#define cx_or cx_u.or + +/* + * File/object prefixes. These are arranged in a stack, and affect + * the behavior of the source path. + */ + +struct prefix; +SLIST_HEAD(prefixlist, prefix); + +struct prefix { + SLIST_ENTRY(prefix) pf_next; /* next prefix in stack */ + const char *pf_prefix; /* the actual prefix */ +}; + +/* + * Device major informations. + */ +struct devm { + TAILQ_ENTRY(devm) dm_next; + const char *dm_srcfile; /* the name of the "majors" file */ + u_short dm_srcline; /* the line number */ + const char *dm_name; /* [bc]devsw name */ + devmajor_t dm_cmajor; /* character major */ + devmajor_t dm_bmajor; /* block major */ + struct condexpr *dm_opts; /* options */ + struct nvlist *dm_devnodes; /* information on /dev nodes */ +}; + +/* + * Hash tables look up name=value pairs. The pointer value of the name + * is assumed to be constant forever; this can be arranged by interning + * the name. (This is fairly convenient since our lexer does this for + * all identifier-like strings---it has to save them anyway, lest yacc's + * look-ahead wipe out the current one.) + */ +struct hashtab; + +int lkmmode; +const char *conffile; /* source file, e.g., "GENERIC.sparc" */ +const char *machine; /* machine type, e.g., "sparc" or "sun3" */ +const char *machinearch; /* machine arch, e.g., "sparc" or "m68k" */ +struct nvlist *machinesubarches; + /* machine subarches, e.g., "sun68k" or "hpc" */ +const char *ioconfname; /* ioconf name, mutually exclusive to machine */ +const char *srcdir; /* path to source directory (rel. to build) */ +const char *builddir; /* path to build directory */ +const char *defbuilddir; /* default build directory */ +const char *ident; /* kernel "ident"ification string */ +int errors; /* counts calls to error() */ +int minmaxusers; /* minimum "maxusers" parameter */ +int defmaxusers; /* default "maxusers" parameter */ +int maxmaxusers; /* default "maxusers" parameter */ +int maxusers; /* configuration's "maxusers" parameter */ +int maxpartitions; /* configuration's "maxpartitions" parameter */ +int version; /* version of the configuration file */ +struct nvlist *options; /* options */ +struct nvlist *fsoptions; /* filesystems */ +struct nvlist *mkoptions; /* makeoptions */ +struct nvlist *appmkoptions; /* appending mkoptions */ +struct nvlist *condmkoptions; /* conditional makeoption table */ +struct hashtab *devbasetab; /* devbase lookup */ +struct hashtab *devroottab; /* attach at root lookup */ +struct hashtab *devatab; /* devbase attachment lookup */ +struct hashtab *devitab; /* device instance lookup */ +struct hashtab *deaddevitab; /* removed instances lookup */ +struct hashtab *selecttab; /* selects things that are "optional foo" */ +struct hashtab *needcnttab; /* retains names marked "needs-count" */ +struct hashtab *opttab; /* table of configured options */ +struct hashtab *fsopttab; /* table of configured file systems */ +struct dlhash *defopttab; /* options that have been "defopt"'d */ +struct dlhash *defflagtab; /* options that have been "defflag"'d */ +struct dlhash *defparamtab; /* options that have been "defparam"'d */ +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 */ + +TAILQ_HEAD(, devbase) allbases; /* list of all devbase structures */ +TAILQ_HEAD(, deva) alldevas; /* list of all devbase attachments */ +TAILQ_HEAD(conftq, config) allcf; /* list of configured kernels */ +TAILQ_HEAD(, devi) alldevi, /* list of all instances */ + allpseudo; /* list of all pseudo-devices */ +TAILQ_HEAD(, devm) alldevms; /* list of all device-majors */ +TAILQ_HEAD(, pspec) allpspecs; /* list of all parent specs */ +int ndevi; /* number of devi's (before packing) */ +int npspecs; /* number of parent specs */ +devmajor_t maxbdevm; /* max number of block major */ +devmajor_t maxcdevm; /* max number of character major */ +int do_devsw; /* 0 if pre-devsw config */ +int oktopackage; /* 0 before setmachine() */ +int devilevel; /* used for devi->i_level */ + +struct filelist allfiles; /* list of all kernel source files */ +struct filelist allcfiles; /* list of all .c files */ +struct filelist allsfiles; /* list of all .S files */ +struct filelist allofiles; /* list of all .o files */ + +struct prefixlist prefixes, /* prefix stack */ + allprefixes; /* all prefixes used (after popped) */ +struct prefixlist buildprefixes, /* build prefix stack */ + allbuildprefixes;/* all build 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 */ + +struct { /* loc[] table for config */ + const char **vec; + int used; +} locators; + +struct numconst { + int64_t val; + int fmt; +}; + +/* files.c */ +void initfiles(void); +void checkfiles(void); +int fixfiles(void); /* finalize */ +int fixdevsw(void); +void addfile(const char *, struct condexpr *, u_char, const 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 */ +#define DECLHASH(HT, VT) \ + struct HT; \ + struct HT *HT##_create(void); \ + int HT##_insert(struct HT *, const char *, struct VT *); \ + int HT##_replace(struct HT *, const char *, struct VT *); \ + int HT##_remove(struct HT *, const char *); \ + struct VT *HT##_lookup(struct HT *, const char *); \ + int HT##_enumerate(struct HT *, \ + int (*)(const char *, struct VT *, void *), \ + void *) +DECLHASH(nvhash, nvlist); +DECLHASH(dlhash, defoptlist); + +/* lint.c */ +void emit_instances(void); +void emit_options(void); +void emit_params(void); + +/* main.c */ +extern int Mflag; +extern int Sflag; +void addoption(const char *, const char *); +void addfsoption(const char *); +void addmkoption(const char *, const char *); +void appendmkoption(const char *, const char *); +void appendcondmkoption(struct condexpr *, const char *, const char *); +void deffilesystem(struct nvlist *, struct nvlist *); +void defoption(const char *, struct defoptlist *, struct nvlist *); +void defflag(const char *, struct defoptlist *, struct nvlist *, int); +void defparam(const char *, struct defoptlist *, struct nvlist *, int); +void deloption(const char *); +void delfsoption(const char *); +void delmkoption(const char *); +int devbase_has_instances(struct devbase *, int); +int is_declared_option(const char *); +int deva_has_instances(struct deva *, int); +void setupdirs(void); +void fixmaxusers(void); +void fixmkoption(void); +const char *strtolower(const char *); + +/* tests on option types */ +#define OPT_FSOPT(n) (nvhash_lookup(deffstab, (n)) != NULL) +#define OPT_DEFOPT(n) (dlhash_lookup(defopttab, (n)) != NULL) +#define OPT_DEFFLAG(n) (dlhash_lookup(defflagtab, (n)) != NULL) +#define OPT_DEFPARAM(n) (dlhash_lookup(defparamtab, (n)) != NULL) +#define OPT_OBSOLETE(n) (dlhash_lookup(obsopttab, (n)) != NULL) +#define DEFINED_OPTION(n) (is_declared_option((n))) + +/* main.c */ +void logconfig_include(FILE *, const char *); + +/* mkdevsw.c */ +int mkdevsw(void); + +/* mkheaders.c */ +int mkheaders(void); +int moveifchanged(const char *, const char *); +int emitlocs(void); +int emitioconfh(void); + +/* mkioconf.c */ +int mkioconf(void); + +/* mkmakefile.c */ +int mkmakefile(void); + +/* mkswap.c */ +int mkswap(void); + +/* pack.c */ +void pack(void); + +/* scan.l */ +u_short currentline(void); +int firstfile(const char *); +void package(const char *); +int include(const char *, int, int, int); +extern int includedepth; + +/* sem.c, other than for yacc actions */ +void initsem(void); +int onlist(struct nvlist *, void *); + +/* util.c */ +void prefix_push(const char *); +void prefix_pop(void); +void buildprefix_push(const char *); +void buildprefix_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 */ + __printflike(3, 4); +void cfgerror(const char *, ...) /* immediate errs */ + __printflike(1, 2); +void cfgxerror(const char *, int, const char *, ...) /* delayed errs */ + __printflike(3, 4); +__dead void panic(const char *, ...) + __printflike(1, 2); +struct nvlist *newnv(const char *, const char *, void *, long long, struct nvlist *); +void nvfree(struct nvlist *); +void nvfreel(struct nvlist *); +struct nvlist *nvcat(struct nvlist *, struct nvlist *); +void autogen_comment(FILE *, const char *); +struct defoptlist *defoptlist_create(const char *, const char *, const char *); +void defoptlist_destroy(struct defoptlist *); +struct defoptlist *defoptlist_append(struct defoptlist *, struct defoptlist *); +struct attrlist *attrlist_create(void); +struct attrlist *attrlist_cons(struct attrlist *, struct attr *); +void attrlist_destroy(struct attrlist *); +void attrlist_destroyall(struct attrlist *); +struct loclist *loclist_create(const char *, const char *, long long); +void loclist_destroy(struct loclist *); +struct condexpr *condexpr_create(enum condexpr_types); +void condexpr_destroy(struct condexpr *); + +/* liby */ +void yyerror(const char *); +int yylex(void); diff --git a/usr.bin/config/files.c b/usr.bin/config/files.c new file mode 100644 index 000000000..3b43f69bf --- /dev/null +++ b/usr.bin/config/files.c @@ -0,0 +1,622 @@ +/* $NetBSD: files.c,v 1.35 2015/09/04 21:32:54 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)files.c 8.1 (Berkeley) 6/6/93 + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: files.c,v 1.35 2015/09/04 21:32:54 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" + +extern const char *yyfile; + +int nallfiles; +size_t nselfiles; +struct files **selfiles; + +/* + * We check that each full path name is unique. File base names + * should generally also be unique, e.g., having both a net/xx.c and + * a kern/xx.c (or, worse, a net/xx.c and a new/xx.c++) is probably + * wrong, but is permitted under some conditions. + */ +static struct hashtab *basetab; /* file base names */ +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 *); +static int fixsel(const char *, void *); + +void +initfiles(void) +{ + + basetab = ht_new(); + pathtab = ht_new(); + TAILQ_INIT(&allfiles); + TAILQ_INIT(&allcfiles); + TAILQ_INIT(&allsfiles); + TAILQ_INIT(&allofiles); + unchecked = &TAILQ_FIRST(&allfiles); +} + +void +addfile(const char *path, struct condexpr *optx, u_char flags, const char *rule) +{ + struct files *fi; + const char *dotp, *tail; + size_t baselen; + size_t dirlen; + int needc, needf; + char base[200]; + char dir[MAXPATHLEN]; + + /* check various errors */ + needc = flags & FI_NEEDSCOUNT; + needf = flags & FI_NEEDSFLAG; + if (needc && needf) { + cfgerror("cannot mix needs-count and needs-flag"); + goto bad; + } + if (optx == NULL && (needc || needf)) { + cfgerror("nothing to %s for %s", needc ? "count" : "flag", + path); + goto bad; + } + if (*path == '/') { + cfgerror("path must be relative"); + goto bad; + } + + /* find last part of pathname, and same without trailing suffix */ + tail = strrchr(path, '/'); + if (tail == NULL) { + dirlen = 0; + tail = path; + } else { + dirlen = (size_t)(tail - path); + tail++; + } + memcpy(dir, path, dirlen); + dir[dirlen] = '\0'; + + dotp = strrchr(tail, '.'); + if (dotp == NULL || dotp[1] == 0 || + (baselen = (size_t)(dotp - tail)) >= sizeof(base)) { + cfgerror("invalid pathname `%s'", path); + goto bad; + } + + /* + * Commit this file to memory. We will decide later whether it + * will be used after all. + */ + fi = ecalloc(1, sizeof *fi); + if (ht_insert(pathtab, path, fi)) { + free(fi); + if ((fi = ht_lookup(pathtab, path)) == NULL) + panic("addfile: ht_lookup(%s)", path); + + /* + * If it's a duplicate entry, it is must specify a make + * rule, and only a make rule, and must come from + * a different source file than the original entry. + * If it does otherwise, it is disallowed. This allows + * machine-dependent files to override the compilation + * options for specific files. + */ + if (rule != NULL && optx == NULL && flags == 0 && + yyfile != fi->fi_srcfile) { + fi->fi_mkrule = rule; + return; + } + cfgerror("duplicate file %s", path); + cfgxerror(fi->fi_srcfile, fi->fi_srcline, + "here is the original definition"); + goto bad; + } + memcpy(base, tail, baselen); + base[baselen] = '\0'; + fi->fi_srcfile = yyfile; + fi->fi_srcline = currentline(); + fi->fi_flags = flags; + fi->fi_path = path; + fi->fi_tail = tail; + fi->fi_base = intern(base); + fi->fi_dir = intern(dir); + fi->fi_prefix = SLIST_EMPTY(&prefixes) ? NULL : + SLIST_FIRST(&prefixes)->pf_prefix; + fi->fi_buildprefix = SLIST_EMPTY(&buildprefixes) ? NULL : + SLIST_FIRST(&buildprefixes)->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; + fi->fi_order = (int)nallfiles + (includedepth << 16); + switch (fi->fi_suffix) { + case 'c': + TAILQ_INSERT_TAIL(&allcfiles, fi, fi_snext); + TAILQ_INSERT_TAIL(&allfiles, fi, fi_next); + break; + case 'S': + fi->fi_suffix = 's'; + /* FALLTHRU */ + case 's': + TAILQ_INSERT_TAIL(&allsfiles, fi, fi_snext); + TAILQ_INSERT_TAIL(&allfiles, fi, fi_next); + break; + case 'o': + TAILQ_INSERT_TAIL(&allofiles, fi, fi_snext); + TAILQ_INSERT_TAIL(&allfiles, fi, fi_next); + break; + default: + cfgxerror(fi->fi_srcfile, fi->fi_srcline, + "unknown suffix"); + break; + } + CFGDBG(3, "file added `%s' at order score %d", fi->fi_path, fi->fi_order); + nallfiles++; + return; + bad: + if (optx != NULL) { + condexpr_destroy(optx); + } +} + +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 + * needing a count is reasonable. (This prevents ../../conf/files from + * depending on some machine-specific device.) + */ +void +checkfiles(void) +{ + struct files *fi, *last; + + last = NULL; + for (fi = *unchecked; fi != NULL; + last = fi, fi = TAILQ_NEXT(fi, fi_next)) { + if ((fi->fi_flags & FI_NEEDSCOUNT) != 0) + (void)expr_eval(fi->fi_optx, checkaux, fi); + } + if (last != NULL) + unchecked = &TAILQ_NEXT(last, fi_next); +} + +/* + * Auxiliary function for checkfiles, called from expr_eval. + * We are not actually interested in the expression's value. + */ +static int +checkaux(const char *name, void *context) +{ + struct files *fi = context; + + if (ht_lookup(devbasetab, name) == NULL) { + cfgxerror(fi->fi_srcfile, fi->fi_srcline, + "`%s' is not a countable device", + name); + /* keep fixfiles() from complaining again */ + fi->fi_flags |= FI_HIDDEN; + } + return (0); +} + +static int +cmpfiles(const void *a, const void *b) +{ + const struct files * const *fia = a, * const *fib = b; + int sa = (*fia)->fi_order; + int sb = (*fib)->fi_order; + + if (sa < sb) + return -1; + else if (sa > sb) + return 1; + else + return 0; +} + +/* + * We have finished reading everything. Tack the files down: calculate + * selection and counts as needed. Check that the object files built + * from the selected sources do not collide. + */ +int +fixfiles(void) +{ + struct files *fi, *ofi; + struct nvlist *flathead, **flatp; + int err, sel; + struct config *cf; + char swapname[100]; + + /* Place these files at last. */ + int onallfiles = nallfiles; + nallfiles = 1 << 30; + addfile("devsw.c", NULL, 0, NULL); + addfile("ioconf.c", NULL, 0, NULL); + + TAILQ_FOREACH(cf, &allcf, cf_next) { + (void)snprintf(swapname, sizeof(swapname), "swap%s.c", + cf->cf_name); + addfile(intern(swapname), NULL, 0, NULL); + } + nallfiles = onallfiles; + + err = 0; + TAILQ_FOREACH(fi, &allfiles, fi_next) { + + /* Skip files that generated counted-device complaints. */ + if (fi->fi_flags & FI_HIDDEN) + continue; + + 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, + fi->fi_flags & FI_NEEDSCOUNT ? fixcount : + fi->fi_flags & FI_NEEDSFLAG ? fixfsel : + fixsel, + &flatp); + fi->fi_optf = flathead; + if (!sel) + continue; + } + + /* We like this file. Make sure it generates a unique .o. */ + if (ht_insert(basetab, fi->fi_base, fi)) { + if ((ofi = ht_lookup(basetab, fi->fi_base)) == NULL) + panic("fixfiles ht_lookup(%s)", fi->fi_base); + /* + * If the new file comes from a different source, + * allow the new one to override the old one. + */ + if (fi->fi_path != ofi->fi_path) { + if (ht_replace(basetab, fi->fi_base, fi) != 1) + panic("fixfiles ht_replace(%s)", + fi->fi_base); + ofi->fi_flags &= (u_char)~FI_SEL; + ofi->fi_flags |= FI_HIDDEN; + } else { + cfgxerror(fi->fi_srcfile, fi->fi_srcline, + "object file collision on %s.o, from %s", + fi->fi_base, fi->fi_path); + cfgxerror(ofi->fi_srcfile, ofi->fi_srcline, + "here is the previous file: %s", + ofi->fi_path); + err = 1; + } + } + fi->fi_flags |= FI_SEL; + nselfiles++; + 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); + } + + /* Order files. */ + selfiles = malloc(nselfiles * sizeof(fi)); + unsigned i = 0; + TAILQ_FOREACH(fi, &allfiles, fi_next) { + if ((fi->fi_flags & FI_SEL) == 0) + continue; + selfiles[i++] = fi; + } + assert(i <= nselfiles); + nselfiles = i; + qsort(selfiles, nselfiles, (unsigned)sizeof(fi), cmpfiles); + return (err); +} + + +/* + * We have finished reading everything. Tack the devsws down: calculate + * selection. + */ +int +fixdevsw(void) +{ + int error; + struct devm *dm, *res; + struct hashtab *fixdevmtab; + char mstr[16]; + + error = 0; + fixdevmtab = ht_new(); + + TAILQ_FOREACH(dm, &alldevms, dm_next) { + res = ht_lookup(fixdevmtab, intern(dm->dm_name)); + if (res != NULL) { + if (res->dm_cmajor != dm->dm_cmajor || + res->dm_bmajor != dm->dm_bmajor) { + cfgxerror(res->dm_srcfile, res->dm_srcline, + "device-major '%s' " + "block %d, char %d redefined" + " at %s:%d as block %d, char %d", + res->dm_name, + res->dm_bmajor, res->dm_cmajor, + dm->dm_srcfile, dm->dm_srcline, + dm->dm_bmajor, dm->dm_cmajor); + } else { + cfgxerror(res->dm_srcfile, res->dm_srcline, + "device-major '%s' " + "(block %d, char %d) duplicated" + " at %s:%d", + dm->dm_name, dm->dm_bmajor, + dm->dm_cmajor, + dm->dm_srcfile, dm->dm_srcline); + } + error = 1; + goto out; + } + if (ht_insert(fixdevmtab, intern(dm->dm_name), dm)) { + panic("fixdevsw: %s char %d block %d", + dm->dm_name, dm->dm_cmajor, dm->dm_bmajor); + } + + if (dm->dm_opts != NULL && + !expr_eval(dm->dm_opts, fixsel, NULL)) + continue; + + if (dm->dm_cmajor != NODEVMAJOR) { + if (ht_lookup(cdevmtab, intern(dm->dm_name)) != NULL) { + cfgxerror(dm->dm_srcfile, dm->dm_srcline, + "device-major of character device '%s' " + "is already defined", dm->dm_name); + error = 1; + goto out; + } + (void)snprintf(mstr, sizeof(mstr), "%d", dm->dm_cmajor); + if (ht_lookup(cdevmtab, intern(mstr)) != NULL) { + cfgxerror(dm->dm_srcfile, dm->dm_srcline, + "device-major of character major '%d' " + "is already defined", dm->dm_cmajor); + error = 1; + goto out; + } + if (ht_insert(cdevmtab, intern(dm->dm_name), dm) || + ht_insert(cdevmtab, intern(mstr), dm)) { + panic("fixdevsw: %s character major %d", + dm->dm_name, dm->dm_cmajor); + } + } + if (dm->dm_bmajor != NODEVMAJOR) { + if (ht_lookup(bdevmtab, intern(dm->dm_name)) != NULL) { + cfgxerror(dm->dm_srcfile, dm->dm_srcline, + "device-major of block device '%s' " + "is already defined", dm->dm_name); + error = 1; + goto out; + } + (void)snprintf(mstr, sizeof(mstr), "%d", dm->dm_bmajor); + if (ht_lookup(bdevmtab, intern(mstr)) != NULL) { + cfgxerror(dm->dm_srcfile, dm->dm_srcline, + "device-major of block major '%d' " + "is already defined", dm->dm_bmajor); + error = 1; + goto out; + } + if (ht_insert(bdevmtab, intern(dm->dm_name), dm) || + ht_insert(bdevmtab, intern(mstr), dm)) { + panic("fixdevsw: %s block major %d", + dm->dm_name, dm->dm_bmajor); + } + } + } + +out: + ht_free(fixdevmtab); + return (error); +} + +/* + * Called when evaluating a needs-count expression. Make sure the + * atom is a countable device. The expression succeeds iff there + * is at least one of them (note that while `xx*' will not always + * set xx's d_umax > 0, you cannot mix '*' and needs-count). The + * mkheaders() routine wants a flattened, in-order list of the + * atoms for `#define name value' lines, so we build that as we + * are called to eval each atom. + */ +static int +fixcount(const char *name, void *context) +{ + struct nvlist ***p = context; + struct devbase *dev; + struct nvlist *nv; + + dev = ht_lookup(devbasetab, name); + if (dev == NULL) /* cannot occur here; we checked earlier */ + panic("fixcount(%s)", name); + nv = newnv(name, NULL, NULL, dev->d_umax, NULL); + **p = nv; + *p = &nv->nv_next; + (void)ht_insert(needcnttab, name, nv); + return (dev->d_umax != 0); +} + +/* + * Called from fixfiles when eval'ing a selection expression for a + * file that will generate a .h with flags. We will need the flat list. + */ +static int +fixfsel(const char *name, void *context) +{ + struct nvlist ***p = context; + struct nvlist *nv; + int sel; + + sel = ht_lookup(selecttab, name) != NULL; + nv = newnv(name, NULL, NULL, sel, NULL); + **p = nv; + *p = &nv->nv_next; + return (sel); +} + +/* + * As for fixfsel above, but we do not need the flat list. + */ +static int +/*ARGSUSED*/ +fixsel(const char *name, void *context) +{ + + return (ht_lookup(selecttab, name) != NULL); +} + +/* + * Eval an expression tree. Calls the given function on each node, + * passing it the given context & the name; return value is &/|/! of + * results of evaluating atoms. + * + * No short circuiting ever occurs. fn must return 0 or 1 (otherwise + * our mixing of C's bitwise & boolean here may give surprises). + */ +int +expr_eval(struct condexpr *expr, int (*fn)(const char *, void *), void *ctx) +{ + int lhs, rhs; + + switch (expr->cx_type) { + + case CX_ATOM: + return ((*fn)(expr->cx_atom, ctx)); + + case CX_NOT: + return (!expr_eval(expr->cx_not, fn, ctx)); + + case CX_AND: + lhs = expr_eval(expr->cx_and.left, fn, ctx); + rhs = expr_eval(expr->cx_and.right, fn, ctx); + return (lhs & rhs); + + case CX_OR: + lhs = expr_eval(expr->cx_or.left, fn, ctx); + rhs = expr_eval(expr->cx_or.right, fn, ctx); + return (lhs | rhs); + } + panic("invalid condexpr type %d", (int)expr->cx_type); + /* NOTREACHED */ + return (0); +} + +#ifdef DEBUG +/* + * Print expression tree. + */ +void +prexpr(struct nvlist *expr) +{ + static void pr0(); + + printf("expr ="); + pr0(expr); + printf("\n"); + (void)fflush(stdout); +} + +static void +pr0(struct nvlist *e) +{ + + switch (e->nv_num) { + case FX_ATOM: + printf(" %s", e->nv_name); + return; + case FX_NOT: + printf(" (!"); + break; + case FX_AND: + printf(" (&"); + break; + case FX_OR: + printf(" (|"); + break; + default: + printf(" (?%lld?", e->nv_num); + break; + } + if (e->nv_ptr) + pr0(e->nv_ptr); + pr0(e->nv_next); + printf(")"); +} +#endif diff --git a/usr.bin/config/gram.c b/usr.bin/config/gram.c new file mode 100644 index 000000000..84dd4a614 --- /dev/null +++ b/usr.bin/config/gram.c @@ -0,0 +1,2431 @@ +/* original parser id follows */ +/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */ +/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */ + +#define YYBYACC 1 +#define YYMAJOR 1 +#define YYMINOR 9 + +#define YYEMPTY (-1) +#define yyclearin (yychar = YYEMPTY) +#define yyerrok (yyerrflag = 0) +#define YYRECOVERING() (yyerrflag != 0) +#define YYENOMEM (-2) +#define YYEOF 0 +#undef YYBTYACC +#define YYBTYACC 0 +#define YYDEBUGSTR YYPREFIX "debug" +#define YYPREFIX "yy" + +#define YYPURE 0 + +#line 2 "gram.y" +/* $NetBSD: gram.y,v 1.52 2015/09/01 13:42:48 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)gram.y 8.1 (Berkeley) 6/6/93 + */ + +#include +__RCSID("$NetBSD: gram.y,v 1.52 2015/09/01 13:42:48 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" +#include "sem.h" + +#define FORMAT(n) (((n).fmt == 8 && (n).val != 0) ? "0%llo" : \ + ((n).fmt == 16) ? "0x%llx" : "%lld") + +#define stop(s) cfgerror(s), exit(1) + +static struct config conf; /* at most one active at a time */ + + +/* + * Allocation wrapper functions + */ +static void wrap_alloc(void *ptr, unsigned code); +static void wrap_continue(void); +static void wrap_cleanup(void); + +/* + * Allocation wrapper type codes + */ +#define WRAP_CODE_nvlist 1 +#define WRAP_CODE_defoptlist 2 +#define WRAP_CODE_loclist 3 +#define WRAP_CODE_attrlist 4 +#define WRAP_CODE_condexpr 5 + +/* + * The allocation wrappers themselves + */ +#define DECL_ALLOCWRAP(t) static struct t *wrap_mk_##t(struct t *arg) + +DECL_ALLOCWRAP(nvlist); +DECL_ALLOCWRAP(defoptlist); +DECL_ALLOCWRAP(loclist); +DECL_ALLOCWRAP(attrlist); +DECL_ALLOCWRAP(condexpr); + +/* allow shorter names */ +#define wrap_mk_loc(p) wrap_mk_loclist(p) +#define wrap_mk_cx(p) wrap_mk_condexpr(p) + +/* + * Macros for allocating new objects + */ + +/* old-style for struct nvlist */ +#define new0(n,s,p,i,x) wrap_mk_nvlist(newnv(n, s, p, i, x)) +#define new_n(n) new0(n, NULL, NULL, 0, NULL) +#define new_nx(n, x) new0(n, NULL, NULL, 0, x) +#define new_ns(n, s) new0(n, s, NULL, 0, NULL) +#define new_si(s, i) new0(NULL, s, NULL, i, NULL) +#define new_nsi(n,s,i) new0(n, s, NULL, i, NULL) +#define new_np(n, p) new0(n, NULL, p, 0, NULL) +#define new_s(s) new0(NULL, s, NULL, 0, NULL) +#define new_p(p) new0(NULL, NULL, p, 0, NULL) +#define new_px(p, x) new0(NULL, NULL, p, 0, x) +#define new_sx(s, x) new0(NULL, s, NULL, 0, x) +#define new_nsx(n,s,x) new0(n, s, NULL, 0, x) +#define new_i(i) new0(NULL, NULL, NULL, i, NULL) + +/* new style, type-polymorphic; ordinary and for types with multiple flavors */ +#define MK0(t) wrap_mk_##t(mk_##t()) +#define MK1(t, a0) wrap_mk_##t(mk_##t(a0)) +#define MK2(t, a0, a1) wrap_mk_##t(mk_##t(a0, a1)) +#define MK3(t, a0, a1, a2) wrap_mk_##t(mk_##t(a0, a1, a2)) + +#define MKF0(t, f) wrap_mk_##t(mk_##t##_##f()) +#define MKF1(t, f, a0) wrap_mk_##t(mk_##t##_##f(a0)) +#define MKF2(t, f, a0, a1) wrap_mk_##t(mk_##t##_##f(a0, a1)) + +/* + * Data constructors + */ + +static struct defoptlist *mk_defoptlist(const char *, const char *, + const char *); +static struct loclist *mk_loc(const char *, const char *, long long); +static struct loclist *mk_loc_val(const char *, struct loclist *); +static struct attrlist *mk_attrlist(struct attrlist *, struct attr *); +static struct condexpr *mk_cx_atom(const char *); +static struct condexpr *mk_cx_not(struct condexpr *); +static struct condexpr *mk_cx_and(struct condexpr *, struct condexpr *); +static struct condexpr *mk_cx_or(struct condexpr *, struct condexpr *); + +/* + * Other private functions + */ + +static void setmachine(const char *, const char *, struct nvlist *, int); +static void check_maxpart(void); + +static struct loclist *present_loclist(struct loclist *ll); +static void app(struct loclist *, struct loclist *); +static struct loclist *locarray(const char *, int, struct loclist *, int); +static struct loclist *namelocvals(const char *, struct loclist *); + +#line 153 "gram.y" +#ifdef YYSTYPE +#undef YYSTYPE_IS_DECLARED +#define YYSTYPE_IS_DECLARED 1 +#endif +#ifndef YYSTYPE_IS_DECLARED +#define YYSTYPE_IS_DECLARED 1 +typedef union { + struct attr *attr; + struct devbase *devb; + struct deva *deva; + struct nvlist *list; + struct defoptlist *defoptlist; + struct loclist *loclist; + struct attrlist *attrlist; + struct condexpr *condexpr; + const char *str; + struct numconst num; + int64_t val; + u_char flag; + devmajor_t devmajor; + int32_t i32; +} YYSTYPE; +#endif /* !YYSTYPE_IS_DECLARED */ +#line 197 "gram.c" + +/* compatibility with bison */ +#ifdef YYPARSE_PARAM +/* compatibility with FreeBSD */ +# ifdef YYPARSE_PARAM_TYPE +# define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM) +# else +# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM) +# endif +#else +# define YYPARSE_DECL() yyparse(void) +#endif + +/* Parameters sent to lex. */ +#ifdef YYLEX_PARAM +# define YYLEX_DECL() yylex(void *YYLEX_PARAM) +# define YYLEX yylex(YYLEX_PARAM) +#else +# define YYLEX_DECL() yylex(void) +# define YYLEX yylex() +#endif + +/* Parameters sent to yyerror. */ +#ifndef YYERROR_DECL +#define YYERROR_DECL() yyerror(const char *s) +#endif +#ifndef YYERROR_CALL +#define YYERROR_CALL(msg) yyerror(msg) +#endif + +extern int YYPARSE_DECL(); + +#define AND 257 +#define AT 258 +#define ATTACH 259 +#define BLOCK 260 +#define BUILD 261 +#define CHAR 262 +#define COLONEQ 263 +#define COMPILE_WITH 264 +#define CONFIG 265 +#define DEFFS 266 +#define DEFINE 267 +#define DEFOPT 268 +#define DEFPARAM 269 +#define DEFFLAG 270 +#define DEFPSEUDO 271 +#define DEFPSEUDODEV 272 +#define DEVICE 273 +#define DEVCLASS 274 +#define DUMPS 275 +#define DEVICE_MAJOR 276 +#define ENDFILE 277 +#define XFILE 278 +#define FILE_SYSTEM 279 +#define FLAGS 280 +#define IDENT 281 +#define IOCONF 282 +#define LINKZERO 283 +#define XMACHINE 284 +#define MAJOR 285 +#define MAKEOPTIONS 286 +#define MAXUSERS 287 +#define MAXPARTITIONS 288 +#define MINOR 289 +#define NEEDS_COUNT 290 +#define NEEDS_FLAG 291 +#define NO 292 +#define XOBJECT 293 +#define OBSOLETE 294 +#define ON 295 +#define OPTIONS 296 +#define PACKAGE 297 +#define PLUSEQ 298 +#define PREFIX 299 +#define BUILDPREFIX 300 +#define PSEUDO_DEVICE 301 +#define PSEUDO_ROOT 302 +#define ROOT 303 +#define SELECT 304 +#define SINGLE 305 +#define SOURCE 306 +#define TYPE 307 +#define VECTOR 308 +#define VERSION 309 +#define WITH 310 +#define NUMBER 311 +#define PATHNAME 312 +#define QSTRING 313 +#define WORD 314 +#define EMPTYSTRING 315 +#define ENDDEFS 316 +#define YYERRCODE 256 +typedef int YYINT; +static const YYINT yylhs[] = { -1, + 0, 57, 57, 61, 61, 61, 58, 58, 58, 58, + 58, 46, 46, 59, 62, 62, 62, 62, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 64, 65, 66, 67, 67, 68, 68, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 1, 1, 9, 9, + 10, 10, 13, 13, 11, 11, 12, 52, 52, 51, + 51, 53, 53, 53, 54, 54, 56, 56, 55, 39, + 39, 38, 18, 18, 18, 20, 20, 21, 21, 21, + 21, 21, 21, 49, 49, 22, 24, 25, 25, 26, + 26, 14, 44, 44, 43, 43, 42, 17, 17, 19, + 19, 41, 41, 40, 40, 40, 40, 86, 86, 88, + 15, 16, 16, 87, 87, 89, 35, 60, 90, 90, + 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 113, 113, 121, 112, 112, 122, 115, + 115, 123, 123, 114, 114, 124, 117, 117, 125, 125, + 116, 116, 126, 118, 119, 119, 29, 29, 29, 33, + 8, 8, 120, 120, 128, 36, 36, 30, 30, 31, + 31, 31, 27, 27, 28, 28, 37, 37, 2, 4, + 4, 5, 5, 6, 7, 7, 7, 3, 50, 50, + 45, 45, 47, 47, 32, 32, 32, 32, 48, 48, + 23, 23, 34, 34, 127, 127, +}; +static const YYINT yylen[] = { 2, + 4, 0, 2, 1, 3, 3, 3, 4, 5, 3, + 1, 1, 2, 2, 0, 2, 3, 3, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 5, 4, 6, 2, 1, 2, 2, 1, 2, + 3, 4, 4, 4, 4, 4, 4, 4, 6, 2, + 4, 2, 4, 4, 4, 2, 0, 1, 0, 2, + 1, 1, 0, 2, 0, 2, 1, 0, 2, 0, + 2, 0, 3, 1, 1, 3, 1, 3, 1, 1, + 2, 1, 0, 2, 3, 1, 3, 2, 1, 4, + 4, 5, 7, 1, 1, 2, 4, 0, 2, 1, + 3, 1, 0, 2, 1, 3, 1, 1, 3, 1, + 1, 1, 2, 1, 3, 3, 5, 1, 3, 4, + 1, 0, 2, 1, 3, 3, 1, 1, 0, 2, + 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 3, 3, 2, 3, 2, 3, + 2, 2, 2, 2, 4, 3, 3, 3, 2, 4, + 4, 2, 5, 1, 3, 1, 1, 3, 1, 1, + 3, 3, 3, 1, 3, 1, 1, 3, 1, 3, + 1, 3, 1, 1, 3, 4, 1, 1, 1, 4, + 2, 2, 0, 2, 3, 0, 1, 1, 2, 1, + 1, 2, 0, 2, 2, 2, 0, 2, 1, 1, + 3, 1, 3, 1, 1, 2, 3, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 2, 0, 1, +}; +static const YYINT yydefred[] = { 2, + 0, 0, 11, 0, 0, 0, 0, 4, 15, 3, + 244, 243, 0, 0, 0, 0, 139, 0, 6, 10, + 0, 7, 5, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 14, 16, + 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 12, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 140, 0, + 143, 0, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, 18, 131, 0, 92, 90, 0, 0, 0, + 242, 0, 0, 0, 0, 0, 50, 0, 0, 0, + 238, 0, 0, 0, 235, 0, 0, 232, 234, 0, + 128, 137, 0, 60, 0, 0, 0, 45, 48, 47, + 66, 17, 13, 9, 142, 204, 0, 186, 0, 184, + 249, 250, 173, 239, 0, 0, 0, 190, 0, 0, + 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, + 197, 0, 179, 164, 219, 0, 141, 0, 0, 91, + 51, 0, 0, 0, 122, 0, 0, 0, 0, 0, + 0, 0, 0, 69, 68, 0, 0, 134, 236, 0, + 240, 0, 0, 0, 0, 0, 75, 0, 0, 0, + 213, 0, 0, 0, 0, 176, 0, 189, 0, 187, + 196, 0, 194, 203, 0, 201, 177, 165, 0, 0, + 0, 217, 178, 220, 0, 223, 121, 120, 0, 118, + 117, 115, 0, 105, 104, 94, 0, 0, 0, 0, + 0, 52, 0, 0, 123, 53, 56, 54, 63, 64, + 58, 79, 0, 0, 0, 0, 65, 0, 237, 0, + 0, 233, 129, 61, 0, 0, 0, 256, 0, 0, + 185, 253, 245, 246, 247, 0, 193, 248, 192, 191, + 181, 0, 0, 0, 180, 200, 198, 222, 0, 0, + 0, 0, 0, 0, 95, 0, 0, 0, 98, 112, + 110, 0, 126, 0, 81, 0, 0, 71, 72, 70, + 42, 136, 135, 130, 77, 76, 0, 208, 207, 0, + 209, 0, 214, 254, 188, 195, 202, 0, 0, 224, + 183, 133, 119, 59, 116, 0, 0, 97, 106, 0, + 0, 0, 85, 0, 44, 0, 74, 0, 0, 206, + 0, 228, 225, 226, 0, 0, 100, 0, 111, 127, + 0, 0, 0, 212, 211, 215, 0, 0, 0, 102, + 0, 86, 89, 83, 210, 252, 0, 0, 0, 103, + 0, 88, 107, +}; +#if defined(YYDESTRUCT_CALL) || defined(YYSTYPE_TOSTRING) +static const YYINT yystos[] = { 0, + 318, 375, 256, 261, 282, 284, 306, 10, 376, 379, + 312, 313, 365, 314, 314, 365, 377, 380, 10, 10, + 314, 10, 10, 378, 408, 256, 259, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 276, 277, 278, 285, + 286, 287, 288, 293, 294, 299, 300, 309, 316, 10, + 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 314, 10, 364, 256, 265, 279, 281, + 286, 287, 292, 296, 301, 302, 304, 314, 10, 348, + 381, 409, 410, 411, 412, 413, 414, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, + 428, 429, 10, 314, 333, 314, 356, 357, 314, 363, + 365, 363, 363, 333, 333, 333, 314, 314, 365, 123, + 314, 33, 40, 320, 321, 322, 323, 324, 325, 404, + 406, 311, 353, 353, 365, 269, 270, 365, 314, 365, + 353, 10, 314, 10, 10, 314, 436, 314, 431, 439, + 313, 314, 366, 313, 314, 368, 433, 441, 353, 265, + 273, 279, 281, 286, 296, 301, 304, 348, 314, 435, + 443, 314, 348, 314, 42, 258, 10, 258, 58, 356, + 362, 123, 336, 314, 358, 359, 359, 359, 336, 336, + 336, 262, 370, 319, 320, 333, 405, 407, 321, 320, + 314, 368, 124, 38, 44, 353, 319, 363, 363, 303, + 437, 44, 298, 61, 44, 314, 258, 314, 430, 440, + 314, 432, 442, 314, 434, 444, 314, 314, 258, 61, + 44, 353, 354, 303, 314, 349, 303, 314, 335, 337, + 314, 360, 361, 313, 314, 125, 91, 338, 339, 367, + 58, 343, 263, 61, 358, 362, 362, 362, 343, 343, + 343, 353, 260, 369, 327, 61, 125, 44, 41, 298, + 323, 324, 406, 353, 329, 359, 359, 295, 445, 438, + 439, 311, 313, 314, 315, 45, 350, 352, 350, 441, + 349, 44, 44, 44, 349, 350, 443, 63, 345, 310, + 44, 334, 44, 367, 125, 44, 61, 91, 340, 314, + 332, 344, 350, 350, 353, 319, 264, 290, 291, 328, + 331, 353, 407, 350, 291, 330, 285, 314, 63, 347, + 351, 275, 446, 311, 440, 442, 444, 280, 314, 346, + 355, 314, 337, 343, 360, 91, 340, 338, 350, 353, + 44, 263, 305, 308, 371, 372, 366, 311, 307, 326, + 445, 353, 63, 341, 350, 353, 93, 93, 332, 350, + 61, 44, 289, 314, 63, 347, 44, 93, 61, 342, + 311, 374, 283, 373, 311, 341, 342, 123, 58, 93, + 341, 311, 125, +}; +#endif /* YYDESTRUCT_CALL || YYSTYPE_TOSTRING */ +static const YYINT yydgoto[] = { 1, + 204, 134, 135, 136, 137, 138, 139, 370, 275, 330, + 285, 336, 331, 321, 206, 312, 249, 193, 250, 258, + 259, 319, 374, 390, 262, 322, 309, 350, 340, 90, + 246, 375, 341, 298, 216, 243, 351, 117, 118, 195, + 196, 252, 253, 191, 120, 76, 121, 163, 260, 166, + 274, 203, 365, 366, 394, 392, 2, 9, 17, 24, + 10, 18, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 140, 207, 141, 208, 25, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 229, 159, 232, 167, 235, 180, 157, 221, 290, + 160, 230, 168, 233, 181, 236, 289, 343, +}; +static const YYINT yysindex[] = { 0, + 0, 117, 0, -188, -247, -238, -188, 0, 0, 0, + 0, 0, 85, 95, 12, 99, 0, -8, 0, 0, + 19, 0, 0, 0, 51, 101, -198, -193, -182, -188, + -188, -188, -198, -198, -198, -179, -172, 0, -188, 22, + -21, -164, -164, -188, -196, -188, -156, -164, 0, 0, + 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 26, 162, -141, -139, -184, + -30, -164, -194, -138, -137, -136, -135, 138, 0, -77, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -75, 0, 0, -40, 62, -128, + 0, -128, -128, 62, 62, 62, 0, -74, -21, -198, + 0, -127, -21, -175, 0, 65, 152, 0, 0, 148, + 0, 0, -164, 0, -21, -188, -188, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -110, 0, 150, 0, + 0, 0, 0, 0, 0, -48, 154, 0, -164, -118, + -59, -113, 0, -112, -111, -109, -108, -54, 146, 164, + 0, -164, 0, 0, 0, -231, 0, -221, -105, 0, + 0, -76, 153, -36, 0, -27, -27, -27, 153, 153, + 153, -164, -50, 0, 0, 151, -12, 0, 0, 173, + 0, -85, -21, -21, -21, -164, 0, -128, -128, -80, + 0, -139, 89, 89, -175, 0, -231, 0, 174, 0, + 0, 175, 0, 0, 176, 0, 0, 0, -231, 89, + -138, 0, 0, 0, 158, 0, 0, 0, -28, 0, + 0, 0, 178, 0, 0, 0, -143, 91, 179, -7, + -97, 0, 89, 89, 0, 0, 0, 0, 0, 0, + 0, 0, -164, -21, -173, -164, 0, -198, 0, 89, + 152, 0, 0, 0, -67, -128, -128, 0, -18, -49, + 0, 0, 0, 0, 0, -86, 0, 0, 0, 0, + 0, -113, -112, -111, 0, 0, 0, 0, -236, -84, + -221, 153, -105, 9, 0, -71, 89, -164, 0, 0, + 0, 184, 0, -34, 0, -239, -184, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -79, 0, 0, -72, + 0, -80, 0, 0, 0, 0, 0, -164, 83, 0, + 0, 0, 0, 0, 0, -164, 140, 0, 0, 143, + -97, 89, 0, 180, 0, 195, 0, -45, -25, 0, + -18, 0, 0, 0, 196, 156, 0, 185, 0, 0, + -66, -26, -64, 0, 0, 0, 89, 185, 130, 0, + 198, 0, 0, 0, 0, 0, 161, 89, -39, 0, + 165, 0, 0, +}; +static const YYINT yyrindex[] = { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 273, 0, 0, 0, 0, -15, + -15, -15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 324, 331, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 101, 31, 0, + 0, 0, 0, 31, 31, 31, 0, -5, 7, 0, + 0, 0, 0, 0, 0, 78, 67, 0, 0, 338, + 0, 0, 0, 0, 4, -15, -15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 344, 0, + 0, 0, 0, 0, 76, 0, 346, 0, 349, 0, + 0, 0, 0, 0, 0, 0, 0, 353, 50, 354, + 0, 356, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 357, -2, 0, 101, 101, 101, 357, 357, + 357, 0, -3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -10, + 0, 0, 0, 0, 0, 0, 0, 0, 360, 0, + 0, 361, 0, 0, 367, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 0, 0, 0, 32, 0, + 0, 0, 372, 0, 0, 0, 0, 0, 262, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 41, 378, 0, 0, 0, 0, 0, + 71, 0, 0, 0, 383, 385, 395, 0, 0, 396, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 397, 0, + 0, 357, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 398, 0, -1, 0, 399, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, + 0, -10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 400, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; +#if YYBTYACC +static const YYINT yycindex[] = { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; +#endif +static const YYINT yygindex[] = { 0, + -124, -90, 279, 0, 199, 200, 0, 0, 0, 0, + 0, 0, 0, 54, 128, 0, 0, 40, 102, 100, + 0, 103, -301, 30, -153, 0, 0, 0, 48, 20, + -159, -165, 0, 0, -42, 0, 0, 302, 0, -133, + -96, 108, 0, -29, 2, 0, 97, 98, 167, 288, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 212, 155, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 206, 127, 205, 129, 190, 131, 92, 0, +}; +#define YYTABLESIZE 435 +static const YYINT yytable[] = { 143, + 144, 50, 132, 218, 78, 151, 80, 124, 125, 133, + 251, 132, 224, 67, 257, 311, 67, 189, 133, 257, + 217, 22, 205, 221, 264, 197, 198, 78, 75, 80, + 189, 278, 122, 123, 78, 154, 80, 385, 205, 169, + 93, 132, 210, 348, 339, 269, 270, 271, 256, 99, + 67, 101, 255, 317, 205, 124, 125, 297, 299, 199, + 89, 87, 265, 265, 265, 363, 14, 301, 364, 317, + 170, 244, 146, 147, 306, 15, 230, 349, 171, 305, + 231, 247, 245, 318, 172, 396, 173, 229, 93, 132, + 327, 174, 248, 199, 19, 87, 401, 323, 324, 356, + 13, 175, 178, 16, 20, 183, 176, 230, 23, 177, + 113, 231, 277, 238, 334, 114, 328, 329, 229, 88, + 116, 286, 287, 11, 12, 251, 8, 296, 161, 162, + 99, 119, 101, 296, 127, 129, 240, 164, 211, 242, + 145, 128, 148, 150, 130, 373, 142, 218, 219, 326, + 152, 359, 265, 265, 115, 11, 12, 149, 354, 272, + 124, 125, 126, 199, 200, 201, 266, 267, 268, 254, + 255, 155, 156, 284, 158, 179, 182, 88, 184, 185, + 186, 187, 188, 205, 192, 194, 131, 202, 213, 214, + 230, 215, 220, 222, 231, 226, 380, 225, 227, 238, + 228, 231, 234, 239, 237, 238, 240, 241, 251, 273, + 261, 276, 280, 279, 288, 315, 320, 302, 303, 304, + 308, 313, 316, 335, 344, 342, 263, 361, 362, 352, + 325, 368, 377, 332, 369, 378, 254, 255, 382, 387, + 381, 254, 255, 383, 391, 389, 395, 26, 388, 223, + 27, 218, 398, 400, 78, 399, 393, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 337, 37, 38, 39, + 67, 402, 138, 116, 255, 360, 40, 41, 42, 43, + 251, 310, 164, 165, 44, 45, 194, 205, 384, 403, + 46, 47, 131, 221, 67, 338, 67, 67, 241, 78, + 48, 80, 78, 255, 80, 372, 77, 49, 78, 27, + 80, 124, 125, 376, 251, 78, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 21, 37, 221, 39, 79, + 230, 80, 74, 46, 231, 40, 81, 82, 43, 153, + 49, 229, 83, 44, 45, 67, 84, 62, 67, 46, + 47, 85, 86, 167, 87, 169, 230, 230, 172, 48, + 231, 231, 182, 171, 88, 216, 108, 229, 229, 166, + 168, 230, 3, 240, 230, 231, 170, 4, 231, 230, + 230, 114, 229, 231, 231, 229, 96, 73, 238, 238, + 229, 229, 43, 292, 57, 293, 294, 295, 5, 292, + 6, 293, 294, 295, 55, 175, 227, 109, 82, 84, + 209, 281, 353, 282, 379, 358, 357, 397, 386, 190, + 355, 212, 7, 314, 367, 91, 283, 291, 345, 300, + 307, 346, 333, 371, 347, +}; +static const YYINT yycheck[] = { 42, + 43, 10, 33, 10, 10, 48, 10, 10, 10, 40, + 10, 33, 61, 10, 91, 44, 10, 58, 40, 91, + 145, 10, 10, 10, 61, 122, 123, 33, 10, 33, + 58, 44, 31, 32, 40, 10, 40, 63, 129, 82, + 10, 10, 133, 280, 63, 199, 200, 201, 125, 44, + 10, 44, 63, 61, 145, 58, 58, 223, 224, 10, + 10, 10, 196, 197, 198, 305, 314, 227, 308, 61, + 265, 303, 269, 270, 240, 314, 10, 314, 273, 239, + 10, 303, 314, 91, 279, 387, 281, 10, 58, 58, + 264, 286, 314, 44, 10, 44, 398, 263, 264, 91, + 4, 296, 83, 7, 10, 86, 301, 41, 10, 304, + 10, 41, 125, 38, 280, 314, 290, 291, 41, 314, + 314, 218, 219, 312, 313, 125, 10, 45, 313, 314, + 125, 314, 125, 45, 314, 39, 61, 313, 314, 182, + 44, 314, 46, 47, 123, 63, 311, 146, 147, 274, + 10, 317, 286, 287, 27, 312, 313, 314, 312, 202, + 33, 34, 35, 124, 125, 126, 196, 197, 198, 313, + 314, 10, 314, 216, 314, 314, 314, 314, 314, 42, + 258, 10, 258, 274, 123, 314, 314, 262, 124, 38, + 124, 44, 303, 44, 124, 314, 362, 44, 258, 124, + 314, 314, 314, 258, 314, 314, 61, 44, 314, 260, + 58, 61, 298, 41, 295, 125, 314, 44, 44, 44, + 63, 44, 44, 291, 311, 275, 263, 44, 263, 314, + 273, 311, 93, 276, 307, 93, 313, 314, 44, 44, + 61, 313, 314, 289, 311, 61, 311, 256, 93, 298, + 259, 258, 123, 93, 260, 58, 283, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 285, 276, 277, 278, + 264, 311, 0, 314, 285, 318, 285, 286, 287, 288, + 280, 310, 313, 314, 293, 294, 314, 275, 314, 125, + 299, 300, 314, 280, 291, 314, 290, 291, 314, 305, + 309, 305, 308, 314, 308, 348, 256, 316, 314, 259, + 314, 314, 314, 356, 314, 265, 266, 267, 268, 269, + 270, 271, 272, 273, 274, 314, 276, 314, 278, 279, + 264, 281, 314, 10, 264, 285, 286, 287, 288, 314, + 10, 264, 292, 293, 294, 305, 296, 10, 308, 299, + 300, 301, 302, 10, 304, 10, 290, 291, 10, 309, + 290, 291, 10, 10, 314, 10, 10, 290, 291, 10, + 10, 305, 256, 298, 308, 305, 10, 261, 308, 313, + 314, 10, 305, 313, 314, 308, 125, 10, 313, 314, + 313, 314, 10, 311, 10, 313, 314, 315, 282, 311, + 284, 313, 314, 315, 10, 10, 10, 10, 10, 10, + 132, 213, 311, 214, 361, 316, 314, 388, 371, 118, + 313, 134, 306, 257, 327, 25, 215, 222, 302, 225, + 241, 303, 278, 342, 304, +}; +#if YYBTYACC +static const YYINT yyctable[] = { -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, +}; +#endif +#define YYFINAL 1 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYMAXTOKEN 316 +#define YYUNDFTOKEN 447 +#define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? YYUNDFTOKEN : (a)) +#if YYDEBUG +static const char *const yyname[] = { + +"$end",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +"'!'",0,0,0,0,"'&'",0,"'('","')'","'*'",0,"','","'-'",0,0,0,0,0,0,0,0,0,0,0,0, +"':'",0,0,"'='",0,"'?'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +"'['",0,"']'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'", +"'|'","'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"error","AND","AT","ATTACH","BLOCK","BUILD", +"CHAR","COLONEQ","COMPILE_WITH","CONFIG","DEFFS","DEFINE","DEFOPT","DEFPARAM", +"DEFFLAG","DEFPSEUDO","DEFPSEUDODEV","DEVICE","DEVCLASS","DUMPS","DEVICE_MAJOR", +"ENDFILE","XFILE","FILE_SYSTEM","FLAGS","IDENT","IOCONF","LINKZERO","XMACHINE", +"MAJOR","MAKEOPTIONS","MAXUSERS","MAXPARTITIONS","MINOR","NEEDS_COUNT", +"NEEDS_FLAG","NO","XOBJECT","OBSOLETE","ON","OPTIONS","PACKAGE","PLUSEQ", +"PREFIX","BUILDPREFIX","PSEUDO_DEVICE","PSEUDO_ROOT","ROOT","SELECT","SINGLE", +"SOURCE","TYPE","VECTOR","VERSION","WITH","NUMBER","PATHNAME","QSTRING","WORD", +"EMPTYSTRING","ENDDEFS","$accept","configuration","fopts","condexpr","condatom", +"cond_or_expr","cond_and_expr","cond_prefix_expr","cond_base_expr","fs_spec", +"fflags","fflag","oflags","oflag","rule","depend","devbase","devattach_opt", +"atlist","interface_opt","atname","loclist","locdef","locdefault","values", +"locdefaults","depend_list","depends","locators","locator","dev_spec", +"device_instance","attachment","value","major_minor","signed_number","int32", +"npseudo","device_flags","deffs","deffses","defopt","defopts","optdepend", +"optdepends","optdepend_list","optfile_opt","subarches","filename", +"stringvalue","locname","mkvarname","device_major_block","device_major_char", +"devnodes","devnodetype","devnodeflags","devnode_dims","topthings", +"machine_spec","definition_part","selection_part","topthing","definitions", +"definition","define_file","define_object","define_device_major", +"define_prefix","define_buildprefix","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","condmkopt_list","majorlist","condmkoption","majordef", +"selections","selection","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","no_fs_list","fs_list","no_mkopt_list","mkopt_list", +"no_opt_list","opt_list","conf","root_spec","sysparam_list","fsoption", +"no_fsoption","mkoption","no_mkoption","option","no_option","on_opt","sysparam", +"illegal-symbol", +}; +static const char *const yyrule[] = { +"$accept : configuration", +"configuration : topthings machine_spec definition_part selection_part", +"topthings :", +"topthings : topthings topthing", +"topthing : '\\n'", +"topthing : SOURCE filename '\\n'", +"topthing : BUILD filename '\\n'", +"machine_spec : XMACHINE WORD '\\n'", +"machine_spec : XMACHINE WORD WORD '\\n'", +"machine_spec : XMACHINE WORD WORD subarches '\\n'", +"machine_spec : IOCONF WORD '\\n'", +"machine_spec : error", +"subarches : WORD", +"subarches : subarches WORD", +"definition_part : definitions ENDDEFS", +"definitions :", +"definitions : definitions '\\n'", +"definitions : definitions definition '\\n'", +"definitions : definitions error '\\n'", +"definitions : definitions ENDFILE", +"definition : define_file", +"definition : define_object", +"definition : define_device_major", +"definition : define_prefix", +"definition : define_buildprefix", +"definition : define_devclass", +"definition : define_filesystems", +"definition : define_attribute", +"definition : define_option", +"definition : define_flag", +"definition : define_obsolete_flag", +"definition : define_param", +"definition : define_obsolete_param", +"definition : define_device", +"definition : define_device_attachment", +"definition : define_maxpartitions", +"definition : define_maxusers", +"definition : define_makeoptions", +"definition : define_pseudo", +"definition : define_pseudodev", +"definition : define_major", +"definition : define_version", +"define_file : XFILE filename fopts fflags rule", +"define_object : XOBJECT filename fopts oflags", +"define_device_major : DEVICE_MAJOR WORD device_major_char device_major_block fopts devnodes", +"define_prefix : PREFIX filename", +"define_prefix : PREFIX", +"define_buildprefix : BUILDPREFIX filename", +"define_buildprefix : BUILDPREFIX WORD", +"define_buildprefix : BUILDPREFIX", +"define_devclass : DEVCLASS WORD", +"define_filesystems : DEFFS deffses optdepend_list", +"define_attribute : DEFINE WORD interface_opt depend_list", +"define_option : DEFOPT optfile_opt defopts optdepend_list", +"define_flag : DEFFLAG optfile_opt defopts optdepend_list", +"define_obsolete_flag : OBSOLETE DEFFLAG optfile_opt defopts", +"define_param : DEFPARAM optfile_opt defopts optdepend_list", +"define_obsolete_param : OBSOLETE DEFPARAM optfile_opt defopts", +"define_device : DEVICE devbase interface_opt depend_list", +"define_device_attachment : ATTACH devbase AT atlist devattach_opt depend_list", +"define_maxpartitions : MAXPARTITIONS int32", +"define_maxusers : MAXUSERS int32 int32 int32", +"define_makeoptions : MAKEOPTIONS condmkopt_list", +"define_pseudo : DEFPSEUDO devbase interface_opt depend_list", +"define_pseudodev : DEFPSEUDODEV devbase interface_opt depend_list", +"define_major : MAJOR '{' majorlist '}'", +"define_version : VERSION int32", +"fopts :", +"fopts : condexpr", +"fflags :", +"fflags : fflags fflag", +"fflag : NEEDS_COUNT", +"fflag : NEEDS_FLAG", +"rule :", +"rule : COMPILE_WITH stringvalue", +"oflags :", +"oflags : oflags oflag", +"oflag : NEEDS_FLAG", +"device_major_char :", +"device_major_char : CHAR int32", +"device_major_block :", +"device_major_block : BLOCK int32", +"devnodes :", +"devnodes : devnodetype ',' devnodeflags", +"devnodes : devnodetype", +"devnodetype : SINGLE", +"devnodetype : VECTOR '=' devnode_dims", +"devnode_dims : NUMBER", +"devnode_dims : NUMBER ':' NUMBER", +"devnodeflags : LINKZERO", +"deffses : deffs", +"deffses : deffses deffs", +"deffs : WORD", +"interface_opt :", +"interface_opt : '{' '}'", +"interface_opt : '{' loclist '}'", +"loclist : locdef", +"loclist : locdef ',' loclist", +"locdef : locname locdefault", +"locdef : locname", +"locdef : '[' locname locdefault ']'", +"locdef : locname '[' int32 ']'", +"locdef : locname '[' int32 ']' locdefaults", +"locdef : '[' locname '[' int32 ']' locdefaults ']'", +"locname : WORD", +"locname : QSTRING", +"locdefault : '=' value", +"locdefaults : '=' '{' values '}'", +"depend_list :", +"depend_list : ':' depends", +"depends : depend", +"depends : depends ',' depend", +"depend : WORD", +"optdepend_list :", +"optdepend_list : ':' optdepends", +"optdepends : optdepend", +"optdepends : optdepends ',' optdepend", +"optdepend : WORD", +"atlist : atname", +"atlist : atlist ',' atname", +"atname : WORD", +"atname : ROOT", +"defopts : defopt", +"defopts : defopts defopt", +"defopt : WORD", +"defopt : WORD '=' value", +"defopt : WORD COLONEQ value", +"defopt : WORD '=' value COLONEQ value", +"condmkopt_list : condmkoption", +"condmkopt_list : condmkopt_list ',' condmkoption", +"condmkoption : condexpr mkvarname PLUSEQ value", +"devbase : WORD", +"devattach_opt :", +"devattach_opt : WITH WORD", +"majorlist : majordef", +"majorlist : majorlist ',' majordef", +"majordef : devbase '=' int32", +"int32 : NUMBER", +"selection_part : selections", +"selections :", +"selections : selections '\\n'", +"selections : selections selection '\\n'", +"selections : selections error '\\n'", +"selection : definition", +"selection : select_attr", +"selection : select_no_attr", +"selection : select_no_filesystems", +"selection : select_filesystems", +"selection : select_no_makeoptions", +"selection : select_makeoptions", +"selection : select_no_options", +"selection : select_options", +"selection : select_maxusers", +"selection : select_ident", +"selection : select_no_ident", +"selection : select_config", +"selection : select_no_config", +"selection : select_no_pseudodev", +"selection : select_pseudodev", +"selection : select_pseudoroot", +"selection : select_no_device_instance_attachment", +"selection : select_no_device_attachment", +"selection : select_no_device_instance", +"selection : select_device_instance", +"select_attr : SELECT WORD", +"select_no_attr : NO SELECT WORD", +"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", +"select_ident : IDENT stringvalue", +"select_no_ident : NO IDENT", +"select_config : CONFIG conf root_spec sysparam_list", +"select_no_config : NO CONFIG WORD", +"select_no_pseudodev : NO PSEUDO_DEVICE WORD", +"select_pseudodev : PSEUDO_DEVICE WORD npseudo", +"select_pseudoroot : PSEUDO_ROOT device_instance", +"select_no_device_instance_attachment : NO device_instance AT attachment", +"select_no_device_attachment : NO DEVICE AT attachment", +"select_no_device_instance : NO device_instance", +"select_device_instance : device_instance AT attachment locators device_flags", +"fs_list : fsoption", +"fs_list : fs_list ',' fsoption", +"fsoption : WORD", +"no_fs_list : no_fsoption", +"no_fs_list : no_fs_list ',' no_fsoption", +"no_fsoption : WORD", +"mkopt_list : mkoption", +"mkopt_list : mkopt_list ',' mkoption", +"mkoption : mkvarname '=' value", +"mkoption : mkvarname PLUSEQ value", +"no_mkopt_list : no_mkoption", +"no_mkopt_list : no_mkopt_list ',' no_mkoption", +"no_mkoption : WORD", +"opt_list : option", +"opt_list : opt_list ',' option", +"option : WORD", +"option : WORD '=' value", +"no_opt_list : no_option", +"no_opt_list : no_opt_list ',' no_option", +"no_option : WORD", +"conf : WORD", +"root_spec : ROOT on_opt dev_spec", +"root_spec : ROOT on_opt dev_spec fs_spec", +"dev_spec : '?'", +"dev_spec : WORD", +"dev_spec : major_minor", +"major_minor : MAJOR NUMBER MINOR NUMBER", +"fs_spec : TYPE '?'", +"fs_spec : TYPE WORD", +"sysparam_list :", +"sysparam_list : sysparam_list sysparam", +"sysparam : DUMPS on_opt dev_spec", +"npseudo :", +"npseudo : int32", +"device_instance : WORD", +"device_instance : WORD '*'", +"attachment : ROOT", +"attachment : WORD", +"attachment : WORD '?'", +"locators :", +"locators : locators locator", +"locator : WORD '?'", +"locator : WORD values", +"device_flags :", +"device_flags : FLAGS int32", +"condexpr : cond_or_expr", +"cond_or_expr : cond_and_expr", +"cond_or_expr : cond_or_expr '|' cond_and_expr", +"cond_and_expr : cond_prefix_expr", +"cond_and_expr : cond_and_expr '&' cond_prefix_expr", +"cond_prefix_expr : cond_base_expr", +"cond_base_expr : condatom", +"cond_base_expr : '!' condatom", +"cond_base_expr : '(' condexpr ')'", +"condatom : WORD", +"mkvarname : QSTRING", +"mkvarname : WORD", +"optfile_opt :", +"optfile_opt : filename", +"filename : QSTRING", +"filename : PATHNAME", +"value : QSTRING", +"value : WORD", +"value : EMPTYSTRING", +"value : signed_number", +"stringvalue : QSTRING", +"stringvalue : WORD", +"values : value", +"values : value ',' values", +"signed_number : NUMBER", +"signed_number : '-' NUMBER", +"on_opt :", +"on_opt : ON", + +}; +#endif + +int yydebug; +int yynerrs; + +int yyerrflag; +int yychar; +YYSTYPE yyval; +YYSTYPE yylval; + +/* define the initial stack-sizes */ +#ifdef YYSTACKSIZE +#undef YYMAXDEPTH +#define YYMAXDEPTH YYSTACKSIZE +#else +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 10000 +#define YYMAXDEPTH 10000 +#endif +#endif + +#define YYINITSTACKSIZE 200 + +typedef struct { + unsigned stacksize; + YYINT *s_base; + YYINT *s_mark; + YYINT *s_last; + YYSTYPE *l_base; + YYSTYPE *l_mark; +} YYSTACKDATA; +/* variables for the parser stack */ +static YYSTACKDATA yystack; +#line 1083 "gram.y" + +void +yyerror(const char *s) +{ + + cfgerror("%s", s); +} + +/************************************************************/ + +/* + * Wrap allocations that live on the parser stack so that we can free + * them again on error instead of leaking. + */ + +#define MAX_WRAP 1000 + +struct wrap_entry { + void *ptr; + unsigned typecode; +}; + +static struct wrap_entry wrapstack[MAX_WRAP]; +static unsigned wrap_depth; + +/* + * Remember pointer PTR with type-code CODE. + */ +static void +wrap_alloc(void *ptr, unsigned code) +{ + unsigned pos; + + if (wrap_depth >= MAX_WRAP) { + panic("allocation wrapper stack overflow"); + } + pos = wrap_depth++; + wrapstack[pos].ptr = ptr; + wrapstack[pos].typecode = code; +} + +/* + * We succeeded; commit to keeping everything that's been allocated so + * far and clear the stack. + */ +static void +wrap_continue(void) +{ + wrap_depth = 0; +} + +/* + * We failed; destroy all the objects allocated. + */ +static void +wrap_cleanup(void) +{ + unsigned i; + + /* + * Destroy each item. Note that because everything allocated + * is entered on the list separately, lists and trees need to + * have their links blanked before being destroyed. Also note + * that strings are interned elsewhere and not handled by this + * mechanism. + */ + + for (i=0; idl_next = NULL; + defoptlist_destroy(dl); + } + break; + case WRAP_CODE_loclist: + { + struct loclist *ll = wrapstack[i].ptr; + + ll->ll_next = NULL; + loclist_destroy(ll); + } + break; + case WRAP_CODE_attrlist: + { + struct attrlist *al = wrapstack[i].ptr; + + al->al_next = NULL; + al->al_this = NULL; + attrlist_destroy(al); + } + break; + case WRAP_CODE_condexpr: + { + struct condexpr *cx = wrapstack[i].ptr; + + cx->cx_type = CX_ATOM; + cx->cx_atom = NULL; + condexpr_destroy(cx); + } + break; + default: + panic("invalid code %u on allocation wrapper stack", + wrapstack[i].typecode); + } + } + + wrap_depth = 0; +} + +/* + * Instantiate the wrapper functions. + * + * Each one calls wrap_alloc to save the pointer and then returns the + * pointer again; these need to be generated with the preprocessor in + * order to be typesafe. + */ +#define DEF_ALLOCWRAP(t) \ + static struct t * \ + wrap_mk_##t(struct t *arg) \ + { \ + wrap_alloc(arg, WRAP_CODE_##t); \ + return arg; \ + } + +DEF_ALLOCWRAP(nvlist); +DEF_ALLOCWRAP(defoptlist); +DEF_ALLOCWRAP(loclist); +DEF_ALLOCWRAP(attrlist); +DEF_ALLOCWRAP(condexpr); + +/************************************************************/ + +/* + * Data constructors + * + * (These are *beneath* the allocation wrappers.) + */ + +static struct defoptlist * +mk_defoptlist(const char *name, const char *val, const char *lintval) +{ + return defoptlist_create(name, val, lintval); +} + +static struct loclist * +mk_loc(const char *name, const char *str, long long num) +{ + return loclist_create(name, str, num); +} + +static struct loclist * +mk_loc_val(const char *str, struct loclist *next) +{ + struct loclist *ll; + + ll = mk_loc(NULL, str, 0); + ll->ll_next = next; + return ll; +} + +static struct attrlist * +mk_attrlist(struct attrlist *next, struct attr *a) +{ + return attrlist_cons(next, a); +} + +static struct condexpr * +mk_cx_atom(const char *s) +{ + struct condexpr *cx; + + cx = condexpr_create(CX_ATOM); + cx->cx_atom = s; + return cx; +} + +static struct condexpr * +mk_cx_not(struct condexpr *sub) +{ + struct condexpr *cx; + + cx = condexpr_create(CX_NOT); + cx->cx_not = sub; + return cx; +} + +static struct condexpr * +mk_cx_and(struct condexpr *left, struct condexpr *right) +{ + struct condexpr *cx; + + cx = condexpr_create(CX_AND); + cx->cx_and.left = left; + cx->cx_and.right = right; + return cx; +} + +static struct condexpr * +mk_cx_or(struct condexpr *left, struct condexpr *right) +{ + struct condexpr *cx; + + cx = condexpr_create(CX_OR); + cx->cx_or.left = left; + cx->cx_or.right = right; + return cx; +} + +/************************************************************/ + +static void +setmachine(const char *mch, const char *mcharch, struct nvlist *mchsubarches, + int isioconf) +{ + char buf[MAXPATHLEN]; + struct nvlist *nv; + + if (isioconf) { + if (include(_PATH_DEVNULL, ENDDEFS, 0, 0) != 0) + exit(1); + ioconfname = mch; + return; + } + + machine = mch; + machinearch = mcharch; + machinesubarches = mchsubarches; + + /* + * Define attributes for all the given names + */ + if (defattr(machine, NULL, NULL, 0) != 0 || + (machinearch != NULL && + defattr(machinearch, NULL, NULL, 0) != 0)) + exit(1); + for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) { + if (defattr(nv->nv_name, NULL, NULL, 0) != 0) + exit(1); + } + + /* + * Set up the file inclusion stack. This empty include tells + * the parser there are no more device definitions coming. + */ + if (include(_PATH_DEVNULL, ENDDEFS, 0, 0) != 0) + exit(1); + + /* Include arch/${MACHINE}/conf/files.${MACHINE} */ + (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s", + machine, machine); + if (include(buf, ENDFILE, 0, 0) != 0) + exit(1); + + /* Include any arch/${MACHINE_SUBARCH}/conf/files.${MACHINE_SUBARCH} */ + for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) { + (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s", + nv->nv_name, nv->nv_name); + if (include(buf, ENDFILE, 0, 0) != 0) + exit(1); + } + + /* Include any arch/${MACHINE_ARCH}/conf/files.${MACHINE_ARCH} */ + if (machinearch != NULL) + (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s", + machinearch, machinearch); + else + strlcpy(buf, _PATH_DEVNULL, sizeof(buf)); + if (include(buf, ENDFILE, 0, 0) != 0) + exit(1); + + /* + * Include the global conf/files. As the last thing + * pushed on the stack, it will be processed first. + */ + if (include("conf/files", ENDFILE, 0, 0) != 0) + exit(1); + + oktopackage = 1; +} + +static void +check_maxpart(void) +{ + + if (maxpartitions <= 0 && ioconfname == NULL) { + stop("cannot proceed without maxpartitions specifier"); + } +} + +static void +check_version(void) +{ + /* + * In essence, version is 0 and is not supported anymore + */ + if (version < CONFIG_MINVERSION) + stop("your sources are out of date -- please update."); +} + +/* + * Prepend a blank entry to the locator definitions so the code in + * sem.c can distinguish "empty locator list" from "no locator list". + * XXX gross. + */ +static struct loclist * +present_loclist(struct loclist *ll) +{ + struct loclist *ret; + + ret = MK3(loc, "", NULL, 0); + ret->ll_next = ll; + return ret; +} + +static void +app(struct loclist *p, struct loclist *q) +{ + while (p->ll_next) + p = p->ll_next; + p->ll_next = q; +} + +static struct loclist * +locarray(const char *name, int count, struct loclist *adefs, int opt) +{ + struct loclist *defs = adefs; + struct loclist **p; + char buf[200]; + int i; + + if (count <= 0) { + fprintf(stderr, "config: array with <= 0 size: %s\n", name); + exit(1); + } + p = &defs; + for(i = 0; i < count; i++) { + if (*p == NULL) + *p = MK3(loc, NULL, "0", 0); + snprintf(buf, sizeof(buf), "%s%c%d", name, ARRCHR, i); + (*p)->ll_name = i == 0 ? name : intern(buf); + (*p)->ll_num = i > 0 || opt; + p = &(*p)->ll_next; + } + *p = 0; + return defs; +} + + +static struct loclist * +namelocvals(const char *name, struct loclist *vals) +{ + struct loclist *p; + char buf[200]; + int i; + + for (i = 0, p = vals; p; i++, p = p->ll_next) { + snprintf(buf, sizeof(buf), "%s%c%d", name, ARRCHR, i); + p->ll_name = i == 0 ? name : intern(buf); + } + return vals; +} + +#line 1456 "gram.c" + +#if YYDEBUG +#include /* needed for printf */ +#endif + +#include /* needed for malloc, etc */ +#include /* needed for memset */ + +/* allocate initial stack or double stack size, up to YYMAXDEPTH */ +static int yygrowstack(YYSTACKDATA *data) +{ + int i; + unsigned newsize; + YYINT *newss; + YYSTYPE *newvs; + + if ((newsize = data->stacksize) == 0) + newsize = YYINITSTACKSIZE; + else if (newsize >= YYMAXDEPTH) + return YYENOMEM; + else if ((newsize *= 2) > YYMAXDEPTH) + newsize = YYMAXDEPTH; + + i = (int) (data->s_mark - data->s_base); + newss = (YYINT *)realloc(data->s_base, newsize * sizeof(*newss)); + if (newss == 0) + return YYENOMEM; + + data->s_base = newss; + data->s_mark = newss + i; + + newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs)); + if (newvs == 0) + return YYENOMEM; + + data->l_base = newvs; + data->l_mark = newvs + i; + + data->stacksize = newsize; + data->s_last = data->s_base + newsize - 1; + return 0; +} + +#if YYPURE || defined(YY_NO_LEAKS) +static void yyfreestack(YYSTACKDATA *data) +{ + free(data->s_base); + free(data->l_base); + memset(data, 0, sizeof(*data)); +} +#else +#define yyfreestack(data) /* nothing */ +#endif + +#define YYABORT goto yyabort +#define YYREJECT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab + +int +YYPARSE_DECL() +{ + int yym, yyn, yystate; +#if YYDEBUG + const char *yys; + + if ((yys = getenv("YYDEBUG")) != 0) + { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif + + yynerrs = 0; + yyerrflag = 0; + yychar = YYEMPTY; + yystate = 0; + +#if YYPURE + memset(&yystack, 0, sizeof(yystack)); +#endif + + if (yystack.s_base == NULL && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow; + yystack.s_mark = yystack.s_base; + yystack.l_mark = yystack.l_base; + yystate = 0; + *yystack.s_mark = 0; + +yyloop: + if ((yyn = yydefred[yystate]) != 0) goto yyreduce; + if (yychar < 0) + { + if ((yychar = YYLEX) < 0) yychar = YYEOF; +#if YYDEBUG + if (yydebug) + { + yys = yyname[YYTRANSLATE(yychar)]; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, yystate, yychar, yys); + } +#endif + } + if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, shifting to state %d\n", + YYPREFIX, yystate, yytable[yyn]); +#endif + if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) + { + goto yyoverflow; + } + yystate = yytable[yyn]; + *++yystack.s_mark = yytable[yyn]; + *++yystack.l_mark = yylval; + yychar = YYEMPTY; + if (yyerrflag > 0) --yyerrflag; + goto yyloop; + } + if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { + yyn = yytable[yyn]; + goto yyreduce; + } + if (yyerrflag) goto yyinrecovery; + + YYERROR_CALL("syntax error"); + + goto yyerrlab; + +yyerrlab: + ++yynerrs; + +yyinrecovery: + if (yyerrflag < 3) + { + yyerrflag = 3; + for (;;) + { + if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, error recovery shifting\ + to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]); +#endif + if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) + { + goto yyoverflow; + } + yystate = yytable[yyn]; + *++yystack.s_mark = yytable[yyn]; + *++yystack.l_mark = yylval; + goto yyloop; + } + else + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: error recovery discarding state %d\n", + YYPREFIX, *yystack.s_mark); +#endif + if (yystack.s_mark <= yystack.s_base) goto yyabort; + --yystack.s_mark; + --yystack.l_mark; + } + } + } + else + { + if (yychar == YYEOF) goto yyabort; +#if YYDEBUG + if (yydebug) + { + yys = yyname[YYTRANSLATE(yychar)]; + printf("%sdebug: state %d, error recovery discards token %d (%s)\n", + YYPREFIX, yystate, yychar, yys); + } +#endif + yychar = YYEMPTY; + goto yyloop; + } + +yyreduce: +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, reducing by rule %d (%s)\n", + YYPREFIX, yystate, yyn, yyrule[yyn]); +#endif + yym = yylen[yyn]; + if (yym) + yyval = yystack.l_mark[1-yym]; + else + memset(&yyval, 0, sizeof yyval); + switch (yyn) + { +case 5: +#line 275 "gram.y" + { if (!srcdir) srcdir = yystack.l_mark[-1].str; } +break; +case 6: +#line 276 "gram.y" + { if (!builddir) builddir = yystack.l_mark[-1].str; } +break; +case 7: +#line 281 "gram.y" + { setmachine(yystack.l_mark[-1].str,NULL,NULL,0); } +break; +case 8: +#line 282 "gram.y" + { setmachine(yystack.l_mark[-2].str,yystack.l_mark[-1].str,NULL,0); } +break; +case 9: +#line 283 "gram.y" + { setmachine(yystack.l_mark[-3].str,yystack.l_mark[-2].str,yystack.l_mark[-1].list,0); } +break; +case 10: +#line 284 "gram.y" + { setmachine(yystack.l_mark[-1].str,NULL,NULL,1); } +break; +case 11: +#line 285 "gram.y" + { stop("cannot proceed without machine or ioconf specifier"); } +break; +case 12: +#line 290 "gram.y" + { yyval.list = new_n(yystack.l_mark[0].str); } +break; +case 13: +#line 291 "gram.y" + { yyval.list = new_nx(yystack.l_mark[0].str, yystack.l_mark[-1].list); } +break; +case 14: +#line 302 "gram.y" + { check_maxpart(); check_version(); } +break; +case 17: +#line 309 "gram.y" + { wrap_continue(); } +break; +case 18: +#line 310 "gram.y" + { wrap_cleanup(); } +break; +case 19: +#line 311 "gram.y" + { enddefs(); checkfiles(); } +break; +case 42: +#line 342 "gram.y" + { addfile(yystack.l_mark[-3].str, yystack.l_mark[-2].condexpr, yystack.l_mark[-1].flag, yystack.l_mark[0].str); } +break; +case 43: +#line 347 "gram.y" + { addfile(yystack.l_mark[-2].str, yystack.l_mark[-1].condexpr, yystack.l_mark[0].flag, NULL); } +break; +case 44: +#line 353 "gram.y" + { + adddevm(yystack.l_mark[-4].str, yystack.l_mark[-3].devmajor, yystack.l_mark[-2].devmajor, yystack.l_mark[-1].condexpr, yystack.l_mark[0].list); + do_devsw = 1; + } +break; +case 45: +#line 361 "gram.y" + { prefix_push(yystack.l_mark[0].str); } +break; +case 46: +#line 362 "gram.y" + { prefix_pop(); } +break; +case 47: +#line 366 "gram.y" + { buildprefix_push(yystack.l_mark[0].str); } +break; +case 48: +#line 367 "gram.y" + { buildprefix_push(yystack.l_mark[0].str); } +break; +case 49: +#line 368 "gram.y" + { buildprefix_pop(); } +break; +case 50: +#line 372 "gram.y" + { (void)defdevclass(yystack.l_mark[0].str, NULL, NULL, 1); } +break; +case 51: +#line 376 "gram.y" + { deffilesystem(yystack.l_mark[-1].list, yystack.l_mark[0].list); } +break; +case 52: +#line 381 "gram.y" + { (void)defattr0(yystack.l_mark[-2].str, yystack.l_mark[-1].loclist, yystack.l_mark[0].attrlist, 0); } +break; +case 53: +#line 386 "gram.y" + { defoption(yystack.l_mark[-2].str, yystack.l_mark[-1].defoptlist, yystack.l_mark[0].list); } +break; +case 54: +#line 391 "gram.y" + { defflag(yystack.l_mark[-2].str, yystack.l_mark[-1].defoptlist, yystack.l_mark[0].list, 0); } +break; +case 55: +#line 396 "gram.y" + { defflag(yystack.l_mark[-1].str, yystack.l_mark[0].defoptlist, NULL, 1); } +break; +case 56: +#line 401 "gram.y" + { defparam(yystack.l_mark[-2].str, yystack.l_mark[-1].defoptlist, yystack.l_mark[0].list, 0); } +break; +case 57: +#line 406 "gram.y" + { defparam(yystack.l_mark[-1].str, yystack.l_mark[0].defoptlist, NULL, 1); } +break; +case 58: +#line 411 "gram.y" + { defdev(yystack.l_mark[-2].devb, yystack.l_mark[-1].loclist, yystack.l_mark[0].attrlist, 0); } +break; +case 59: +#line 416 "gram.y" + { defdevattach(yystack.l_mark[-1].deva, yystack.l_mark[-4].devb, yystack.l_mark[-2].list, yystack.l_mark[0].attrlist); } +break; +case 60: +#line 420 "gram.y" + { maxpartitions = yystack.l_mark[0].i32; } +break; +case 61: +#line 425 "gram.y" + { setdefmaxusers(yystack.l_mark[-2].i32, yystack.l_mark[-1].i32, yystack.l_mark[0].i32); } +break; +case 63: +#line 435 "gram.y" + { defdev(yystack.l_mark[-2].devb, yystack.l_mark[-1].loclist, yystack.l_mark[0].attrlist, 1); } +break; +case 64: +#line 440 "gram.y" + { defdev(yystack.l_mark[-2].devb, yystack.l_mark[-1].loclist, yystack.l_mark[0].attrlist, 2); } +break; +case 66: +#line 448 "gram.y" + { setversion(yystack.l_mark[0].i32); } +break; +case 67: +#line 453 "gram.y" + { yyval.condexpr = NULL; } +break; +case 68: +#line 454 "gram.y" + { yyval.condexpr = yystack.l_mark[0].condexpr; } +break; +case 69: +#line 459 "gram.y" + { yyval.flag = 0; } +break; +case 70: +#line 460 "gram.y" + { yyval.flag = yystack.l_mark[-1].flag | yystack.l_mark[0].flag; } +break; +case 71: +#line 465 "gram.y" + { yyval.flag = FI_NEEDSCOUNT; } +break; +case 72: +#line 466 "gram.y" + { yyval.flag = FI_NEEDSFLAG; } +break; +case 73: +#line 471 "gram.y" + { yyval.str = NULL; } +break; +case 74: +#line 472 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 75: +#line 477 "gram.y" + { yyval.flag = 0; } +break; +case 76: +#line 478 "gram.y" + { yyval.flag = yystack.l_mark[-1].flag | yystack.l_mark[0].flag; } +break; +case 77: +#line 483 "gram.y" + { yyval.flag = FI_NEEDSFLAG; } +break; +case 78: +#line 488 "gram.y" + { yyval.devmajor = -1; } +break; +case 79: +#line 489 "gram.y" + { yyval.devmajor = yystack.l_mark[0].i32; } +break; +case 80: +#line 494 "gram.y" + { yyval.devmajor = -1; } +break; +case 81: +#line 495 "gram.y" + { yyval.devmajor = yystack.l_mark[0].i32; } +break; +case 82: +#line 500 "gram.y" + { yyval.list = new_s("DEVNODE_DONTBOTHER"); } +break; +case 83: +#line 501 "gram.y" + { yyval.list = nvcat(yystack.l_mark[-2].list, yystack.l_mark[0].list); } +break; +case 84: +#line 502 "gram.y" + { yyval.list = yystack.l_mark[0].list; } +break; +case 85: +#line 507 "gram.y" + { yyval.list = new_s("DEVNODE_SINGLE"); } +break; +case 86: +#line 508 "gram.y" + { yyval.list = nvcat(new_s("DEVNODE_VECTOR"), yystack.l_mark[0].list); } +break; +case 87: +#line 513 "gram.y" + { yyval.list = new_i(yystack.l_mark[0].num.val); } +break; +case 88: +#line 514 "gram.y" + { + struct nvlist *__nv1, *__nv2; + + __nv1 = new_i(yystack.l_mark[-2].num.val); + __nv2 = new_i(yystack.l_mark[0].num.val); + yyval.list = nvcat(__nv1, __nv2); + } +break; +case 89: +#line 525 "gram.y" + { yyval.list = new_s("DEVNODE_FLAG_LINKZERO");} +break; +case 90: +#line 530 "gram.y" + { yyval.list = new_n(yystack.l_mark[0].str); } +break; +case 91: +#line 531 "gram.y" + { yyval.list = new_nx(yystack.l_mark[0].str, yystack.l_mark[-1].list); } +break; +case 92: +#line 536 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 93: +#line 541 "gram.y" + { yyval.loclist = NULL; } +break; +case 94: +#line 542 "gram.y" + { yyval.loclist = present_loclist(NULL); } +break; +case 95: +#line 543 "gram.y" + { yyval.loclist = present_loclist(yystack.l_mark[-1].loclist); } +break; +case 96: +#line 553 "gram.y" + { yyval.loclist = yystack.l_mark[0].loclist; } +break; +case 97: +#line 554 "gram.y" + { yyval.loclist = yystack.l_mark[-2].loclist; app(yystack.l_mark[-2].loclist, yystack.l_mark[0].loclist); } +break; +case 98: +#line 563 "gram.y" + { yyval.loclist = MK3(loc, yystack.l_mark[-1].str, yystack.l_mark[0].str, 0); } +break; +case 99: +#line 564 "gram.y" + { yyval.loclist = MK3(loc, yystack.l_mark[0].str, NULL, 0); } +break; +case 100: +#line 565 "gram.y" + { yyval.loclist = MK3(loc, yystack.l_mark[-2].str, yystack.l_mark[-1].str, 1); } +break; +case 101: +#line 566 "gram.y" + { yyval.loclist = locarray(yystack.l_mark[-3].str, yystack.l_mark[-1].i32, NULL, 0); } +break; +case 102: +#line 568 "gram.y" + { yyval.loclist = locarray(yystack.l_mark[-4].str, yystack.l_mark[-2].i32, yystack.l_mark[0].loclist, 0); } +break; +case 103: +#line 570 "gram.y" + { yyval.loclist = locarray(yystack.l_mark[-5].str, yystack.l_mark[-3].i32, yystack.l_mark[-1].loclist, 1); } +break; +case 104: +#line 575 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 105: +#line 576 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 106: +#line 581 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 107: +#line 586 "gram.y" + { yyval.loclist = yystack.l_mark[-1].loclist; } +break; +case 108: +#line 591 "gram.y" + { yyval.attrlist = NULL; } +break; +case 109: +#line 592 "gram.y" + { yyval.attrlist = yystack.l_mark[0].attrlist; } +break; +case 110: +#line 597 "gram.y" + { yyval.attrlist = MK2(attrlist, NULL, yystack.l_mark[0].attr); } +break; +case 111: +#line 598 "gram.y" + { yyval.attrlist = MK2(attrlist, yystack.l_mark[-2].attrlist, yystack.l_mark[0].attr); } +break; +case 112: +#line 603 "gram.y" + { yyval.attr = refattr(yystack.l_mark[0].str); } +break; +case 113: +#line 608 "gram.y" + { yyval.list = NULL; } +break; +case 114: +#line 609 "gram.y" + { yyval.list = yystack.l_mark[0].list; } +break; +case 115: +#line 614 "gram.y" + { yyval.list = new_n(yystack.l_mark[0].str); } +break; +case 116: +#line 615 "gram.y" + { yyval.list = new_nx(yystack.l_mark[0].str, yystack.l_mark[-2].list); } +break; +case 117: +#line 620 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 118: +#line 626 "gram.y" + { yyval.list = new_n(yystack.l_mark[0].str); } +break; +case 119: +#line 627 "gram.y" + { yyval.list = new_nx(yystack.l_mark[0].str, yystack.l_mark[-2].list); } +break; +case 120: +#line 632 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 121: +#line 633 "gram.y" + { yyval.str = NULL; } +break; +case 122: +#line 638 "gram.y" + { yyval.defoptlist = yystack.l_mark[0].defoptlist; } +break; +case 123: +#line 639 "gram.y" + { yyval.defoptlist = defoptlist_append(yystack.l_mark[0].defoptlist, yystack.l_mark[-1].defoptlist); } +break; +case 124: +#line 644 "gram.y" + { yyval.defoptlist = MK3(defoptlist, yystack.l_mark[0].str, NULL, NULL); } +break; +case 125: +#line 645 "gram.y" + { yyval.defoptlist = MK3(defoptlist, yystack.l_mark[-2].str, yystack.l_mark[0].str, NULL); } +break; +case 126: +#line 646 "gram.y" + { yyval.defoptlist = MK3(defoptlist, yystack.l_mark[-2].str, NULL, yystack.l_mark[0].str); } +break; +case 127: +#line 647 "gram.y" + { yyval.defoptlist = MK3(defoptlist, yystack.l_mark[-4].str, yystack.l_mark[-2].str, yystack.l_mark[0].str); } +break; +case 130: +#line 658 "gram.y" + { appendcondmkoption(yystack.l_mark[-3].condexpr, yystack.l_mark[-2].str, yystack.l_mark[0].str); } +break; +case 131: +#line 663 "gram.y" + { yyval.devb = getdevbase(yystack.l_mark[0].str); } +break; +case 132: +#line 668 "gram.y" + { yyval.deva = NULL; } +break; +case 133: +#line 669 "gram.y" + { yyval.deva = getdevattach(yystack.l_mark[0].str); } +break; +case 136: +#line 681 "gram.y" + { setmajor(yystack.l_mark[-2].devb, yystack.l_mark[0].i32); } +break; +case 137: +#line 685 "gram.y" + { + if (yystack.l_mark[0].num.val > INT_MAX || yystack.l_mark[0].num.val < INT_MIN) + cfgerror("overflow %" PRId64, yystack.l_mark[0].num.val); + else + yyval.i32 = (int32_t)yystack.l_mark[0].num.val; + } +break; +case 141: +#line 708 "gram.y" + { wrap_continue(); } +break; +case 142: +#line 709 "gram.y" + { wrap_cleanup(); } +break; +case 164: +#line 738 "gram.y" + { addattr(yystack.l_mark[0].str); } +break; +case 165: +#line 742 "gram.y" + { delattr(yystack.l_mark[0].str); } +break; +case 172: +#line 770 "gram.y" + { setmaxusers(yystack.l_mark[0].i32); } +break; +case 173: +#line 774 "gram.y" + { setident(yystack.l_mark[0].str); } +break; +case 174: +#line 778 "gram.y" + { setident(NULL); } +break; +case 175: +#line 783 "gram.y" + { addconf(&conf); } +break; +case 176: +#line 787 "gram.y" + { delconf(yystack.l_mark[0].str); } +break; +case 177: +#line 791 "gram.y" + { delpseudo(yystack.l_mark[0].str); } +break; +case 178: +#line 795 "gram.y" + { addpseudo(yystack.l_mark[-1].str, yystack.l_mark[0].i32); } +break; +case 179: +#line 799 "gram.y" + { addpseudoroot(yystack.l_mark[0].str); } +break; +case 180: +#line 804 "gram.y" + { deldevi(yystack.l_mark[-2].str, yystack.l_mark[0].str); } +break; +case 181: +#line 808 "gram.y" + { deldeva(yystack.l_mark[0].str); } +break; +case 182: +#line 812 "gram.y" + { deldev(yystack.l_mark[0].str); } +break; +case 183: +#line 817 "gram.y" + { adddev(yystack.l_mark[-4].str, yystack.l_mark[-2].str, yystack.l_mark[-1].loclist, yystack.l_mark[0].i32); } +break; +case 186: +#line 828 "gram.y" + { addfsoption(yystack.l_mark[0].str); } +break; +case 189: +#line 839 "gram.y" + { delfsoption(yystack.l_mark[0].str); } +break; +case 192: +#line 851 "gram.y" + { addmkoption(yystack.l_mark[-2].str, yystack.l_mark[0].str); } +break; +case 193: +#line 852 "gram.y" + { appendmkoption(yystack.l_mark[-2].str, yystack.l_mark[0].str); } +break; +case 196: +#line 864 "gram.y" + { delmkoption(yystack.l_mark[0].str); } +break; +case 199: +#line 875 "gram.y" + { addoption(yystack.l_mark[0].str, NULL); } +break; +case 200: +#line 876 "gram.y" + { addoption(yystack.l_mark[-2].str, yystack.l_mark[0].str); } +break; +case 203: +#line 887 "gram.y" + { deloption(yystack.l_mark[0].str); } +break; +case 204: +#line 892 "gram.y" + { + conf.cf_name = yystack.l_mark[0].str; + conf.cf_lineno = currentline(); + conf.cf_fstype = NULL; + conf.cf_root = NULL; + conf.cf_dump = NULL; + } +break; +case 205: +#line 903 "gram.y" + { setconf(&conf.cf_root, "root", yystack.l_mark[0].list); } +break; +case 206: +#line 904 "gram.y" + { setconf(&conf.cf_root, "root", yystack.l_mark[-1].list); } +break; +case 207: +#line 909 "gram.y" + { yyval.list = new_si(intern("?"), + (long long)NODEV); } +break; +case 208: +#line 911 "gram.y" + { yyval.list = new_si(yystack.l_mark[0].str, + (long long)NODEV); } +break; +case 209: +#line 913 "gram.y" + { yyval.list = new_si(NULL, yystack.l_mark[0].val); } +break; +case 210: +#line 918 "gram.y" + { yyval.val = (int64_t)makedev(yystack.l_mark[-2].num.val, yystack.l_mark[0].num.val); } +break; +case 211: +#line 923 "gram.y" + { setfstype(&conf.cf_fstype, intern("?")); } +break; +case 212: +#line 924 "gram.y" + { setfstype(&conf.cf_fstype, yystack.l_mark[0].str); } +break; +case 215: +#line 935 "gram.y" + { setconf(&conf.cf_dump, "dumps", yystack.l_mark[0].list); } +break; +case 216: +#line 940 "gram.y" + { yyval.i32 = 1; } +break; +case 217: +#line 941 "gram.y" + { yyval.i32 = yystack.l_mark[0].i32; } +break; +case 218: +#line 946 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 219: +#line 947 "gram.y" + { yyval.str = starref(yystack.l_mark[-1].str); } +break; +case 220: +#line 952 "gram.y" + { yyval.str = NULL; } +break; +case 221: +#line 953 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 222: +#line 954 "gram.y" + { yyval.str = wildref(yystack.l_mark[-1].str); } +break; +case 223: +#line 959 "gram.y" + { yyval.loclist = NULL; } +break; +case 224: +#line 960 "gram.y" + { yyval.loclist = yystack.l_mark[0].loclist; app(yystack.l_mark[0].loclist, yystack.l_mark[-1].loclist); } +break; +case 225: +#line 965 "gram.y" + { yyval.loclist = MK3(loc, yystack.l_mark[-1].str, NULL, 0); } +break; +case 226: +#line 966 "gram.y" + { yyval.loclist = namelocvals(yystack.l_mark[-1].str, yystack.l_mark[0].loclist); } +break; +case 227: +#line 971 "gram.y" + { yyval.i32 = 0; } +break; +case 228: +#line 972 "gram.y" + { yyval.i32 = yystack.l_mark[0].i32; } +break; +case 231: +#line 995 "gram.y" + { yyval.condexpr = MKF2(cx, or, yystack.l_mark[-2].condexpr, yystack.l_mark[0].condexpr); } +break; +case 233: +#line 1000 "gram.y" + { yyval.condexpr = MKF2(cx, and, yystack.l_mark[-2].condexpr, yystack.l_mark[0].condexpr); } +break; +case 235: +#line 1010 "gram.y" + { yyval.condexpr = yystack.l_mark[0].condexpr; } +break; +case 236: +#line 1011 "gram.y" + { yyval.condexpr = MKF1(cx, not, yystack.l_mark[0].condexpr); } +break; +case 237: +#line 1012 "gram.y" + { yyval.condexpr = yystack.l_mark[-1].condexpr; } +break; +case 238: +#line 1017 "gram.y" + { yyval.condexpr = MKF1(cx, atom, yystack.l_mark[0].str); } +break; +case 239: +#line 1028 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 240: +#line 1029 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 241: +#line 1034 "gram.y" + { yyval.str = NULL; } +break; +case 242: +#line 1035 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 243: +#line 1040 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 244: +#line 1041 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 245: +#line 1046 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 246: +#line 1047 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 247: +#line 1048 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 248: +#line 1049 "gram.y" + { + char bf[40]; + + (void)snprintf(bf, sizeof(bf), FORMAT(yystack.l_mark[0].num), (long long)yystack.l_mark[0].num.val); + yyval.str = intern(bf); + } +break; +case 249: +#line 1059 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 250: +#line 1060 "gram.y" + { yyval.str = yystack.l_mark[0].str; } +break; +case 251: +#line 1066 "gram.y" + { yyval.loclist = MKF2(loc, val, yystack.l_mark[0].str, NULL); } +break; +case 252: +#line 1067 "gram.y" + { yyval.loclist = MKF2(loc, val, yystack.l_mark[-2].str, yystack.l_mark[0].loclist); } +break; +case 253: +#line 1072 "gram.y" + { yyval.num = yystack.l_mark[0].num; } +break; +case 254: +#line 1073 "gram.y" + { yyval.num.fmt = yystack.l_mark[0].num.fmt; yyval.num.val = -yystack.l_mark[0].num.val; } +break; +#line 2373 "gram.c" + } + yystack.s_mark -= yym; + yystate = *yystack.s_mark; + yystack.l_mark -= yym; + yym = yylhs[yyn]; + if (yystate == 0 && yym == 0) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state 0 to\ + state %d\n", YYPREFIX, YYFINAL); +#endif + yystate = YYFINAL; + *++yystack.s_mark = YYFINAL; + *++yystack.l_mark = yyval; + if (yychar < 0) + { + if ((yychar = YYLEX) < 0) yychar = YYEOF; +#if YYDEBUG + if (yydebug) + { + yys = yyname[YYTRANSLATE(yychar)]; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, YYFINAL, yychar, yys); + } +#endif + } + if (yychar == YYEOF) goto yyaccept; + goto yyloop; + } + if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yystate) + yystate = yytable[yyn]; + else + yystate = yydgoto[yym]; +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state %d \ +to state %d\n", YYPREFIX, *yystack.s_mark, yystate); +#endif + if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) + { + goto yyoverflow; + } + *++yystack.s_mark = (YYINT) yystate; + *++yystack.l_mark = yyval; + goto yyloop; + +yyoverflow: + YYERROR_CALL("yacc stack overflow"); + +yyabort: + yyfreestack(&yystack); + return (1); + +yyaccept: + yyfreestack(&yystack); + return (0); +} diff --git a/usr.bin/config/gram.h b/usr.bin/config/gram.h new file mode 100644 index 000000000..16ef96578 --- /dev/null +++ b/usr.bin/config/gram.h @@ -0,0 +1,89 @@ +#ifndef _yy_defines_h_ +#define _yy_defines_h_ + +#define AND 257 +#define AT 258 +#define ATTACH 259 +#define BLOCK 260 +#define BUILD 261 +#define CHAR 262 +#define COLONEQ 263 +#define COMPILE_WITH 264 +#define CONFIG 265 +#define DEFFS 266 +#define DEFINE 267 +#define DEFOPT 268 +#define DEFPARAM 269 +#define DEFFLAG 270 +#define DEFPSEUDO 271 +#define DEFPSEUDODEV 272 +#define DEVICE 273 +#define DEVCLASS 274 +#define DUMPS 275 +#define DEVICE_MAJOR 276 +#define ENDFILE 277 +#define XFILE 278 +#define FILE_SYSTEM 279 +#define FLAGS 280 +#define IDENT 281 +#define IOCONF 282 +#define LINKZERO 283 +#define XMACHINE 284 +#define MAJOR 285 +#define MAKEOPTIONS 286 +#define MAXUSERS 287 +#define MAXPARTITIONS 288 +#define MINOR 289 +#define NEEDS_COUNT 290 +#define NEEDS_FLAG 291 +#define NO 292 +#define XOBJECT 293 +#define OBSOLETE 294 +#define ON 295 +#define OPTIONS 296 +#define PACKAGE 297 +#define PLUSEQ 298 +#define PREFIX 299 +#define BUILDPREFIX 300 +#define PSEUDO_DEVICE 301 +#define PSEUDO_ROOT 302 +#define ROOT 303 +#define SELECT 304 +#define SINGLE 305 +#define SOURCE 306 +#define TYPE 307 +#define VECTOR 308 +#define VERSION 309 +#define WITH 310 +#define NUMBER 311 +#define PATHNAME 312 +#define QSTRING 313 +#define WORD 314 +#define EMPTYSTRING 315 +#define ENDDEFS 316 +#ifdef YYSTYPE +#undef YYSTYPE_IS_DECLARED +#define YYSTYPE_IS_DECLARED 1 +#endif +#ifndef YYSTYPE_IS_DECLARED +#define YYSTYPE_IS_DECLARED 1 +typedef union { + struct attr *attr; + struct devbase *devb; + struct deva *deva; + struct nvlist *list; + struct defoptlist *defoptlist; + struct loclist *loclist; + struct attrlist *attrlist; + struct condexpr *condexpr; + const char *str; + struct numconst num; + int64_t val; + u_char flag; + devmajor_t devmajor; + int32_t i32; +} YYSTYPE; +#endif /* !YYSTYPE_IS_DECLARED */ +extern YYSTYPE yylval; + +#endif /* _yy_defines_h_ */ diff --git a/usr.bin/config/gram.y b/usr.bin/config/gram.y new file mode 100644 index 000000000..3c234d607 --- /dev/null +++ b/usr.bin/config/gram.y @@ -0,0 +1,1450 @@ +%{ +/* $NetBSD: gram.y,v 1.52 2015/09/01 13:42:48 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)gram.y 8.1 (Berkeley) 6/6/93 + */ + +#include +__RCSID("$NetBSD: gram.y,v 1.52 2015/09/01 13:42:48 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" +#include "sem.h" + +#define FORMAT(n) (((n).fmt == 8 && (n).val != 0) ? "0%llo" : \ + ((n).fmt == 16) ? "0x%llx" : "%lld") + +#define stop(s) cfgerror(s), exit(1) + +static struct config conf; /* at most one active at a time */ + + +/* + * Allocation wrapper functions + */ +static void wrap_alloc(void *ptr, unsigned code); +static void wrap_continue(void); +static void wrap_cleanup(void); + +/* + * Allocation wrapper type codes + */ +#define WRAP_CODE_nvlist 1 +#define WRAP_CODE_defoptlist 2 +#define WRAP_CODE_loclist 3 +#define WRAP_CODE_attrlist 4 +#define WRAP_CODE_condexpr 5 + +/* + * The allocation wrappers themselves + */ +#define DECL_ALLOCWRAP(t) static struct t *wrap_mk_##t(struct t *arg) + +DECL_ALLOCWRAP(nvlist); +DECL_ALLOCWRAP(defoptlist); +DECL_ALLOCWRAP(loclist); +DECL_ALLOCWRAP(attrlist); +DECL_ALLOCWRAP(condexpr); + +/* allow shorter names */ +#define wrap_mk_loc(p) wrap_mk_loclist(p) +#define wrap_mk_cx(p) wrap_mk_condexpr(p) + +/* + * Macros for allocating new objects + */ + +/* old-style for struct nvlist */ +#define new0(n,s,p,i,x) wrap_mk_nvlist(newnv(n, s, p, i, x)) +#define new_n(n) new0(n, NULL, NULL, 0, NULL) +#define new_nx(n, x) new0(n, NULL, NULL, 0, x) +#define new_ns(n, s) new0(n, s, NULL, 0, NULL) +#define new_si(s, i) new0(NULL, s, NULL, i, NULL) +#define new_nsi(n,s,i) new0(n, s, NULL, i, NULL) +#define new_np(n, p) new0(n, NULL, p, 0, NULL) +#define new_s(s) new0(NULL, s, NULL, 0, NULL) +#define new_p(p) new0(NULL, NULL, p, 0, NULL) +#define new_px(p, x) new0(NULL, NULL, p, 0, x) +#define new_sx(s, x) new0(NULL, s, NULL, 0, x) +#define new_nsx(n,s,x) new0(n, s, NULL, 0, x) +#define new_i(i) new0(NULL, NULL, NULL, i, NULL) + +/* new style, type-polymorphic; ordinary and for types with multiple flavors */ +#define MK0(t) wrap_mk_##t(mk_##t()) +#define MK1(t, a0) wrap_mk_##t(mk_##t(a0)) +#define MK2(t, a0, a1) wrap_mk_##t(mk_##t(a0, a1)) +#define MK3(t, a0, a1, a2) wrap_mk_##t(mk_##t(a0, a1, a2)) + +#define MKF0(t, f) wrap_mk_##t(mk_##t##_##f()) +#define MKF1(t, f, a0) wrap_mk_##t(mk_##t##_##f(a0)) +#define MKF2(t, f, a0, a1) wrap_mk_##t(mk_##t##_##f(a0, a1)) + +/* + * Data constructors + */ + +static struct defoptlist *mk_defoptlist(const char *, const char *, + const char *); +static struct loclist *mk_loc(const char *, const char *, long long); +static struct loclist *mk_loc_val(const char *, struct loclist *); +static struct attrlist *mk_attrlist(struct attrlist *, struct attr *); +static struct condexpr *mk_cx_atom(const char *); +static struct condexpr *mk_cx_not(struct condexpr *); +static struct condexpr *mk_cx_and(struct condexpr *, struct condexpr *); +static struct condexpr *mk_cx_or(struct condexpr *, struct condexpr *); + +/* + * Other private functions + */ + +static void setmachine(const char *, const char *, struct nvlist *, int); +static void check_maxpart(void); + +static struct loclist *present_loclist(struct loclist *ll); +static void app(struct loclist *, struct loclist *); +static struct loclist *locarray(const char *, int, struct loclist *, int); +static struct loclist *namelocvals(const char *, struct loclist *); + +%} + +%union { + struct attr *attr; + struct devbase *devb; + struct deva *deva; + struct nvlist *list; + struct defoptlist *defoptlist; + struct loclist *loclist; + struct attrlist *attrlist; + struct condexpr *condexpr; + const char *str; + struct numconst num; + int64_t val; + u_char flag; + devmajor_t devmajor; + int32_t i32; +} + +%token AND AT ATTACH +%token BLOCK BUILD +%token CHAR COLONEQ COMPILE_WITH CONFIG +%token DEFFS DEFINE DEFOPT DEFPARAM DEFFLAG DEFPSEUDO DEFPSEUDODEV +%token DEVICE DEVCLASS DUMPS DEVICE_MAJOR +%token ENDFILE +%token XFILE FILE_SYSTEM FLAGS +%token IDENT IOCONF +%token LINKZERO +%token XMACHINE MAJOR MAKEOPTIONS MAXUSERS MAXPARTITIONS MINOR +%token NEEDS_COUNT NEEDS_FLAG NO +%token XOBJECT OBSOLETE ON OPTIONS +%token PACKAGE PLUSEQ PREFIX BUILDPREFIX PSEUDO_DEVICE PSEUDO_ROOT +%token ROOT +%token SELECT SINGLE SOURCE +%token TYPE +%token VECTOR VERSION +%token WITH +%token NUMBER +%token PATHNAME QSTRING WORD EMPTYSTRING +%token ENDDEFS + +%type fopts condexpr condatom +%type cond_or_expr cond_and_expr cond_prefix_expr +%type cond_base_expr +%type fs_spec +%type fflags fflag oflags oflag +%type rule +%type depend +%type devbase +%type devattach_opt +%type atlist +%type interface_opt +%type atname +%type loclist locdef +%type locdefault +%type values locdefaults +%type depend_list depends +%type locators locator +%type dev_spec +%type device_instance +%type attachment +%type value +%type major_minor +%type signed_number +%type int32 npseudo device_flags +%type deffs +%type deffses +%type defopt +%type defopts +%type optdepend +%type optdepends +%type optdepend_list +%type optfile_opt +%type subarches +%type filename stringvalue locname mkvarname +%type device_major_block device_major_char +%type devnodes devnodetype devnodeflags devnode_dims + +%% + +/* + * 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 + * material is available to be placed in kernels. + * + * The two parts have almost entirely separate syntaxes. This grammar + * covers both of them. When config is run on a kernel configuration + * file, the std.* file for the port is included explicitly. The + * files.* files are included implicitly when the std.* file declares + * the machine type. + * + * The machine spec, which brings in the definition part, must appear + * before all configuration material except for the "topthings"; these + * are the "source" and "build" declarations that tell config where + * things are. These are not used by default. + * + * A previous version of this comment contained the following text: + * + * Note that we do not have sufficient keywords to enforce any + * order between elements of "topthings" without introducing + * shift/reduce conflicts. Instead, check order requirements in + * the C code. + * + * As of March 2012 this comment makes no sense, as there are only two + * topthings and no reason for them to be forcibly ordered. + * Furthermore, the statement about conflicts is false. + */ + +/* Complete configuration. */ +configuration: + topthings machine_spec definition_part selection_part +; + +/* Sequence of zero or more topthings. */ +topthings: + /* empty */ + | topthings topthing +; + +/* Directory specification. */ +topthing: + '\n' + | SOURCE filename '\n' { if (!srcdir) srcdir = $2; } + | BUILD filename '\n' { if (!builddir) builddir = $2; } +; + +/* "machine foo" from std.whatever */ +machine_spec: + XMACHINE WORD '\n' { setmachine($2,NULL,NULL,0); } + | XMACHINE WORD WORD '\n' { setmachine($2,$3,NULL,0); } + | XMACHINE WORD WORD subarches '\n' { setmachine($2,$3,$4,0); } + | IOCONF WORD '\n' { setmachine($2,NULL,NULL,1); } + | error { stop("cannot proceed without machine or ioconf specifier"); } +; + +/* One or more sub-arches. */ +subarches: + WORD { $$ = new_n($1); } + | subarches WORD { $$ = new_nx($2, $1); } +; + +/************************************************************/ + +/* + * The machine definitions grammar. + */ + +/* Complete definition part: the contents of all files.* files. */ +definition_part: + definitions ENDDEFS { check_maxpart(); check_version(); } +; + +/* Zero or more definitions. Trap errors. */ +definitions: + /* empty */ + | definitions '\n' + | definitions definition '\n' { wrap_continue(); } + | definitions error '\n' { wrap_cleanup(); } + | definitions ENDFILE { enddefs(); checkfiles(); } +; + +/* A single definition. */ +definition: + define_file + | define_object + | define_device_major + | define_prefix + | define_buildprefix + | 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 */ +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 { addfile($2, $3, $4, NULL); } +; + +/* 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_buildprefix: + BUILDPREFIX filename { buildprefix_push($2); } + | BUILDPREFIX WORD { buildprefix_push($2); } + | BUILDPREFIX { buildprefix_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; } + | condexpr { $$ = $1; } +; + +/* zero or more flags for a file */ +fflags: + /* empty */ { $$ = 0; } + | fflags fflag { $$ = $1 | $2; } +; + +/* one flag for a file */ +fflag: + NEEDS_COUNT { $$ = FI_NEEDSCOUNT; } + | NEEDS_FLAG { $$ = FI_NEEDSFLAG; } +; + +/* extra compile directive for a source file */ +rule: + /* empty */ { $$ = NULL; } + | COMPILE_WITH stringvalue { $$ = $2; } +; + +/* zero or more flags for an object file */ +oflags: + /* empty */ { $$ = 0; } + | oflags oflag { $$ = $1 | $2; } +; + +/* a single flag for an object file */ +oflag: + NEEDS_FLAG { $$ = FI_NEEDSFLAG; } +; + +/* char 55 */ +device_major_char: + /* empty */ { $$ = -1; } + | CHAR int32 { $$ = $2; } +; + +/* block 33 */ +device_major_block: + /* empty */ { $$ = -1; } + | BLOCK int32 { $$ = $2; } +; + +/* device node specification */ +devnodes: + /* empty */ { $$ = new_s("DEVNODE_DONTBOTHER"); } + | devnodetype ',' devnodeflags { $$ = nvcat($1, $3); } + | devnodetype { $$ = $1; } +; + +/* device nodes without flags */ +devnodetype: + SINGLE { $$ = new_s("DEVNODE_SINGLE"); } + | VECTOR '=' devnode_dims { $$ = nvcat(new_s("DEVNODE_VECTOR"), $3); } +; + +/* dimensions (?) */ +devnode_dims: + NUMBER { $$ = new_i($1.val); } + | NUMBER ':' NUMBER { + struct nvlist *__nv1, *__nv2; + + __nv1 = new_i($1.val); + __nv2 = new_i($3.val); + $$ = nvcat(__nv1, __nv2); + } +; + +/* flags for device nodes */ +devnodeflags: + LINKZERO { $$ = new_s("DEVNODE_FLAG_LINKZERO");} +; + +/* one or more file system names */ +deffses: + deffs { $$ = new_n($1); } + | deffses deffs { $$ = new_nx($2, $1); } +; + +/* a single file system name */ +deffs: + WORD { $$ = $1; } +; + +/* optional locator specification */ +interface_opt: + /* empty */ { $$ = NULL; } + | '{' '}' { $$ = present_loclist(NULL); } + | '{' loclist '}' { $$ = present_loclist($2); } +; + +/* + * loclist order matters, must use right recursion + * XXX wot? + */ + +/* list of locator definitions */ +loclist: + locdef { $$ = $1; } + | locdef ',' loclist { $$ = $1; app($1, $3); } +; + +/* + * "[ WORD locdefault ]" syntax may be unnecessary... + */ + +/* one locator definition */ +locdef: + locname locdefault { $$ = MK3(loc, $1, $2, 0); } + | locname { $$ = MK3(loc, $1, NULL, 0); } + | '[' locname locdefault ']' { $$ = MK3(loc, $2, $3, 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 */ +locname: + WORD { $$ = $1; } + | QSTRING { $$ = $1; } +; + +/* locator default value */ +locdefault: + '=' value { $$ = $2; } +; + +/* multiple locator default values */ +locdefaults: + '=' '{' values '}' { $$ = $3; } +; + +/* list of depends, may be empty */ +depend_list: + /* empty */ { $$ = NULL; } + | ':' depends { $$ = $2; } +; + +/* one or more depend items */ +depends: + depend { $$ = MK2(attrlist, NULL, $1); } + | depends ',' depend { $$ = MK2(attrlist, $1, $3); } +; + +/* one depend item (which is an attribute) */ +depend: + WORD { $$ = refattr($1); } +; + +/* list of option depends, may be empty */ +optdepend_list: + /* empty */ { $$ = NULL; } + | ':' optdepends { $$ = $2; } +; + +/* a list of option dependencies */ +optdepends: + optdepend { $$ = new_n($1); } + | optdepends ',' optdepend { $$ = new_nx($3, $1); } +; + +/* one option depend, which is an option name */ +optdepend: + WORD { $$ = $1; } +; + + +/* list of places to attach: attach blah at ... */ +atlist: + atname { $$ = new_n($1); } + | atlist ',' atname { $$ = new_nx($3, $1); } +; + +/* a place to attach a device */ +atname: + WORD { $$ = $1; } + | ROOT { $$ = NULL; } +; + +/* one or more defined options */ +defopts: + defopt { $$ = $1; } + | defopts defopt { $$ = defoptlist_append($2, $1); } +; + +/* one defined option */ +defopt: + WORD { $$ = MK3(defoptlist, $1, NULL, NULL); } + | WORD '=' value { $$ = MK3(defoptlist, $1, $3, NULL); } + | WORD COLONEQ value { $$ = MK3(defoptlist, $1, NULL, $3); } + | WORD '=' value COLONEQ value { $$ = MK3(defoptlist, $1, $3, $5); } +; + +/* list of conditional makeoptions */ +condmkopt_list: + condmkoption + | condmkopt_list ',' condmkoption +; + +/* one conditional make option */ +condmkoption: + condexpr mkvarname PLUSEQ value { appendcondmkoption($1, $2, $4); } +; + +/* device name */ +devbase: + WORD { $$ = getdevbase($1); } +; + +/* optional attachment: with foo */ +devattach_opt: + /* empty */ { $$ = NULL; } + | WITH WORD { $$ = getdevattach($2); } +; + +/* list of major numbers */ +/* XXX why is this right-recursive? */ +majorlist: + majordef + | majorlist ',' majordef +; + +/* one major number */ +majordef: + 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 selection grammar. + */ + +/* Complete selection part: all std.* files plus selected config. */ +selection_part: + selections +; + +/* Zero or more config items. Trap errors. */ +selections: + /* empty */ + | selections '\n' + | selections selection '\n' { wrap_continue(); } + | selections error '\n' { wrap_cleanup(); } +; + +/* One config item. */ +selection: + definition + | 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); } +; + +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); } +; + +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); } +; + +/* list of filesystems */ +fs_list: + fsoption + | fs_list ',' fsoption +; + +/* one filesystem */ +fsoption: + WORD { addfsoption($1); } +; + +/* list of filesystems that had NO in front */ +no_fs_list: + no_fsoption + | no_fs_list ',' no_fsoption +; + +/* one filesystem that had NO in front */ +no_fsoption: + WORD { delfsoption($1); } +; + +/* list of make options */ +/* XXX why is this right-recursive? */ +mkopt_list: + mkoption + | mkopt_list ',' mkoption +; + +/* one make option */ +mkoption: + mkvarname '=' value { addmkoption($1, $3); } + | mkvarname PLUSEQ value { appendmkoption($1, $3); } +; + +/* list of make options that had NO in front */ +no_mkopt_list: + no_mkoption + | no_mkopt_list ',' no_mkoption +; + +/* one make option that had NO in front */ +/* XXX shouldn't this be mkvarname rather than WORD? */ +no_mkoption: + WORD { delmkoption($1); } +; + +/* list of options */ +opt_list: + option + | opt_list ',' option +; + +/* one option */ +option: + WORD { addoption($1, NULL); } + | WORD '=' value { addoption($1, $3); } +; + +/* list of options that had NO in front */ +no_opt_list: + no_option + | no_opt_list ',' no_option +; + +/* one option that had NO in front */ +no_option: + WORD { deloption($1); } +; + +/* the name in "config name root on ..." */ +conf: + WORD { + conf.cf_name = $1; + conf.cf_lineno = currentline(); + conf.cf_fstype = NULL; + conf.cf_root = NULL; + conf.cf_dump = NULL; + } +; + +/* root fs specification */ +root_spec: + ROOT on_opt dev_spec { setconf(&conf.cf_root, "root", $3); } + | ROOT on_opt dev_spec fs_spec { setconf(&conf.cf_root, "root", $3); } +; + +/* device for root fs or dump */ +dev_spec: + '?' { $$ = 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 { $$ = (int64_t)makedev($2.val, $4.val); } +; + +/* filesystem type for root fs specification */ +fs_spec: + TYPE '?' { setfstype(&conf.cf_fstype, intern("?")); } + | TYPE WORD { setfstype(&conf.cf_fstype, $2); } +; + +/* zero or more additional system parameters */ +sysparam_list: + /* empty */ + | sysparam_list sysparam +; + +/* one additional system parameter (there's only one: dumps) */ +sysparam: + DUMPS on_opt dev_spec { setconf(&conf.cf_dump, "dumps", $3); } +; + +/* number of pseudo devices to configure (which is optional) */ +npseudo: + /* empty */ { $$ = 1; } + | int32 { $$ = $1; } +; + +/* name of a device to configure */ +device_instance: + WORD { $$ = $1; } + | WORD '*' { $$ = starref($1); } +; + +/* name of a device to configure an attachment to */ +attachment: + ROOT { $$ = NULL; } + | WORD { $$ = $1; } + | WORD '?' { $$ = wildref($1); } +; + +/* zero or more locators */ +locators: + /* empty */ { $$ = NULL; } + | locators locator { $$ = $2; app($2, $1); } +; + +/* one locator */ +locator: + WORD '?' { $$ = MK3(loc, $1, NULL, 0); } + | WORD values { $$ = namelocvals($1, $2); } +; + +/* optional device flags */ +device_flags: + /* empty */ { $$ = 0; } + | FLAGS int32 { $$ = $2; } +; + +/************************************************************/ + +/* + * conditions + */ + + +/* + * order of options is important, must use right recursion + * + * dholland 20120310: wut? + */ + +/* expression of conditions */ +condexpr: + cond_or_expr +; + +cond_or_expr: + cond_and_expr + | cond_or_expr '|' cond_and_expr { $$ = MKF2(cx, or, $1, $3); } +; + +cond_and_expr: + cond_prefix_expr + | cond_and_expr '&' cond_prefix_expr { $$ = MKF2(cx, and, $1, $3); } +; + +cond_prefix_expr: + cond_base_expr +/* XXX notyet - need to strengthen downstream first */ +/* | '!' cond_prefix_expr { $$ = MKF1(cx, not, $2); } */ +; + +cond_base_expr: + condatom { $$ = $1; } + | '!' condatom { $$ = MKF1(cx, not, $2); } + | '(' condexpr ')' { $$ = $2; } +; + +/* basic element of config element expression: a config element */ +condatom: + WORD { $$ = MKF1(cx, atom, $1); } +; + +/************************************************************/ + +/* + * Various nonterminals shared between the grammars. + */ + +/* variable name for make option */ +mkvarname: + QSTRING { $$ = $1; } + | WORD { $$ = $1; } +; + +/* optional file for an option */ +optfile_opt: + /* empty */ { $$ = NULL; } + | filename { $$ = $1; } +; + +/* filename. */ +filename: + QSTRING { $$ = $1; } + | PATHNAME { $$ = $1; } +; + +/* constant value */ +value: + QSTRING { $$ = $1; } + | WORD { $$ = $1; } + | EMPTYSTRING { $$ = $1; } + | signed_number { + char bf[40]; + + (void)snprintf(bf, sizeof(bf), FORMAT($1), (long long)$1.val); + $$ = intern(bf); + } +; + +/* constant value that is a string */ +stringvalue: + QSTRING { $$ = $1; } + | WORD { $$ = $1; } +; + +/* comma-separated list of values */ +/* XXX why right-recursive? */ +values: + value { $$ = MKF2(loc, val, $1, NULL); } + | value ',' values { $$ = MKF2(loc, val, $1, $3); } +; + +/* possibly negative number */ +signed_number: + NUMBER { $$ = $1; } + | '-' NUMBER { $$.fmt = $2.fmt; $$.val = -$2.val; } +; + +/* optional ON keyword */ +on_opt: + /* empty */ + | ON +; + +%% + +void +yyerror(const char *s) +{ + + cfgerror("%s", s); +} + +/************************************************************/ + +/* + * Wrap allocations that live on the parser stack so that we can free + * them again on error instead of leaking. + */ + +#define MAX_WRAP 1000 + +struct wrap_entry { + void *ptr; + unsigned typecode; +}; + +static struct wrap_entry wrapstack[MAX_WRAP]; +static unsigned wrap_depth; + +/* + * Remember pointer PTR with type-code CODE. + */ +static void +wrap_alloc(void *ptr, unsigned code) +{ + unsigned pos; + + if (wrap_depth >= MAX_WRAP) { + panic("allocation wrapper stack overflow"); + } + pos = wrap_depth++; + wrapstack[pos].ptr = ptr; + wrapstack[pos].typecode = code; +} + +/* + * We succeeded; commit to keeping everything that's been allocated so + * far and clear the stack. + */ +static void +wrap_continue(void) +{ + wrap_depth = 0; +} + +/* + * We failed; destroy all the objects allocated. + */ +static void +wrap_cleanup(void) +{ + unsigned i; + + /* + * Destroy each item. Note that because everything allocated + * is entered on the list separately, lists and trees need to + * have their links blanked before being destroyed. Also note + * that strings are interned elsewhere and not handled by this + * mechanism. + */ + + for (i=0; idl_next = NULL; + defoptlist_destroy(dl); + } + break; + case WRAP_CODE_loclist: + { + struct loclist *ll = wrapstack[i].ptr; + + ll->ll_next = NULL; + loclist_destroy(ll); + } + break; + case WRAP_CODE_attrlist: + { + struct attrlist *al = wrapstack[i].ptr; + + al->al_next = NULL; + al->al_this = NULL; + attrlist_destroy(al); + } + break; + case WRAP_CODE_condexpr: + { + struct condexpr *cx = wrapstack[i].ptr; + + cx->cx_type = CX_ATOM; + cx->cx_atom = NULL; + condexpr_destroy(cx); + } + break; + default: + panic("invalid code %u on allocation wrapper stack", + wrapstack[i].typecode); + } + } + + wrap_depth = 0; +} + +/* + * Instantiate the wrapper functions. + * + * Each one calls wrap_alloc to save the pointer and then returns the + * pointer again; these need to be generated with the preprocessor in + * order to be typesafe. + */ +#define DEF_ALLOCWRAP(t) \ + static struct t * \ + wrap_mk_##t(struct t *arg) \ + { \ + wrap_alloc(arg, WRAP_CODE_##t); \ + return arg; \ + } + +DEF_ALLOCWRAP(nvlist); +DEF_ALLOCWRAP(defoptlist); +DEF_ALLOCWRAP(loclist); +DEF_ALLOCWRAP(attrlist); +DEF_ALLOCWRAP(condexpr); + +/************************************************************/ + +/* + * Data constructors + * + * (These are *beneath* the allocation wrappers.) + */ + +static struct defoptlist * +mk_defoptlist(const char *name, const char *val, const char *lintval) +{ + return defoptlist_create(name, val, lintval); +} + +static struct loclist * +mk_loc(const char *name, const char *str, long long num) +{ + return loclist_create(name, str, num); +} + +static struct loclist * +mk_loc_val(const char *str, struct loclist *next) +{ + struct loclist *ll; + + ll = mk_loc(NULL, str, 0); + ll->ll_next = next; + return ll; +} + +static struct attrlist * +mk_attrlist(struct attrlist *next, struct attr *a) +{ + return attrlist_cons(next, a); +} + +static struct condexpr * +mk_cx_atom(const char *s) +{ + struct condexpr *cx; + + cx = condexpr_create(CX_ATOM); + cx->cx_atom = s; + return cx; +} + +static struct condexpr * +mk_cx_not(struct condexpr *sub) +{ + struct condexpr *cx; + + cx = condexpr_create(CX_NOT); + cx->cx_not = sub; + return cx; +} + +static struct condexpr * +mk_cx_and(struct condexpr *left, struct condexpr *right) +{ + struct condexpr *cx; + + cx = condexpr_create(CX_AND); + cx->cx_and.left = left; + cx->cx_and.right = right; + return cx; +} + +static struct condexpr * +mk_cx_or(struct condexpr *left, struct condexpr *right) +{ + struct condexpr *cx; + + cx = condexpr_create(CX_OR); + cx->cx_or.left = left; + cx->cx_or.right = right; + return cx; +} + +/************************************************************/ + +static void +setmachine(const char *mch, const char *mcharch, struct nvlist *mchsubarches, + int isioconf) +{ + char buf[MAXPATHLEN]; + struct nvlist *nv; + + if (isioconf) { + if (include(_PATH_DEVNULL, ENDDEFS, 0, 0) != 0) + exit(1); + ioconfname = mch; + return; + } + + machine = mch; + machinearch = mcharch; + machinesubarches = mchsubarches; + + /* + * Define attributes for all the given names + */ + if (defattr(machine, NULL, NULL, 0) != 0 || + (machinearch != NULL && + defattr(machinearch, NULL, NULL, 0) != 0)) + exit(1); + for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) { + if (defattr(nv->nv_name, NULL, NULL, 0) != 0) + exit(1); + } + + /* + * Set up the file inclusion stack. This empty include tells + * the parser there are no more device definitions coming. + */ + if (include(_PATH_DEVNULL, ENDDEFS, 0, 0) != 0) + exit(1); + + /* Include arch/${MACHINE}/conf/files.${MACHINE} */ + (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s", + machine, machine); + if (include(buf, ENDFILE, 0, 0) != 0) + exit(1); + + /* Include any arch/${MACHINE_SUBARCH}/conf/files.${MACHINE_SUBARCH} */ + for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) { + (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s", + nv->nv_name, nv->nv_name); + if (include(buf, ENDFILE, 0, 0) != 0) + exit(1); + } + + /* Include any arch/${MACHINE_ARCH}/conf/files.${MACHINE_ARCH} */ + if (machinearch != NULL) + (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s", + machinearch, machinearch); + else + strlcpy(buf, _PATH_DEVNULL, sizeof(buf)); + if (include(buf, ENDFILE, 0, 0) != 0) + exit(1); + + /* + * Include the global conf/files. As the last thing + * pushed on the stack, it will be processed first. + */ + if (include("conf/files", ENDFILE, 0, 0) != 0) + exit(1); + + oktopackage = 1; +} + +static void +check_maxpart(void) +{ + + if (maxpartitions <= 0 && ioconfname == NULL) { + stop("cannot proceed without maxpartitions specifier"); + } +} + +static void +check_version(void) +{ + /* + * In essence, version is 0 and is not supported anymore + */ + if (version < CONFIG_MINVERSION) + stop("your sources are out of date -- please update."); +} + +/* + * Prepend a blank entry to the locator definitions so the code in + * sem.c can distinguish "empty locator list" from "no locator list". + * XXX gross. + */ +static struct loclist * +present_loclist(struct loclist *ll) +{ + struct loclist *ret; + + ret = MK3(loc, "", NULL, 0); + ret->ll_next = ll; + return ret; +} + +static void +app(struct loclist *p, struct loclist *q) +{ + while (p->ll_next) + p = p->ll_next; + p->ll_next = q; +} + +static struct loclist * +locarray(const char *name, int count, struct loclist *adefs, int opt) +{ + struct loclist *defs = adefs; + struct loclist **p; + char buf[200]; + int i; + + if (count <= 0) { + fprintf(stderr, "config: array with <= 0 size: %s\n", name); + exit(1); + } + p = &defs; + for(i = 0; i < count; i++) { + if (*p == NULL) + *p = MK3(loc, NULL, "0", 0); + snprintf(buf, sizeof(buf), "%s%c%d", name, ARRCHR, i); + (*p)->ll_name = i == 0 ? name : intern(buf); + (*p)->ll_num = i > 0 || opt; + p = &(*p)->ll_next; + } + *p = 0; + return defs; +} + + +static struct loclist * +namelocvals(const char *name, struct loclist *vals) +{ + struct loclist *p; + char buf[200]; + int i; + + for (i = 0, p = vals; p; i++, p = p->ll_next) { + snprintf(buf, sizeof(buf), "%s%c%d", name, ARRCHR, i); + p->ll_name = i == 0 ? name : intern(buf); + } + return vals; +} + diff --git a/usr.bin/config/hash.c b/usr.bin/config/hash.c new file mode 100644 index 000000000..77382a2fa --- /dev/null +++ b/usr.bin/config/hash.c @@ -0,0 +1,456 @@ +/* $NetBSD: hash.c,v 1.11 2014/10/29 17:14:50 christos Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)hash.c 8.1 (Berkeley) 6/6/93 + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: hash.c,v 1.11 2014/10/29 17:14:50 christos Exp $"); + +#include +#include +#include +#include +#include +#include "defs.h" + +/* + * Interned strings are kept in a hash table. By making each string + * unique, the program can compare strings by comparing pointers. + */ +struct hashent { + // XXXLUKEM: a SIMPLEQ might be more appropriate + TAILQ_ENTRY(hashent) h_next; + 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) */ + 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; +}; + +static struct hashtab strings; + +/* + * HASHFRACTION controls ht_lim, which in turn controls the average chain + * length. We allow a few entries, on average, as comparing them is usually + * cheap (the h_hash values prevent a strcmp). + */ +#define HASHFRACTION(sz) ((sz) * 3 / 2) + +static void ht_expand(struct hashtab *); +static void ht_init(struct hashtab *, size_t); +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); + +/* + * Initialize a new hash table. The size must be a power of 2. + */ +static void +ht_init(struct hashtab *ht, size_t sz) +{ + u_int n; + + ht->ht_tab = emalloc(sz * sizeof (ht->ht_tab[0])); + ht->ht_size = sz; + ht->ht_mask = sz - 1; + for (n = 0; n < sz; n++) + TAILQ_INIT(&ht->ht_tab[n]); + ht->ht_used = 0; + ht->ht_lim = HASHFRACTION(sz); +} + +/* + * Expand an existing hash table. + */ +static void +ht_expand(struct hashtab *ht) +{ + struct hashenthead *h, *oldh; + struct hashent *p; + size_t n, i; + + n = ht->ht_size * 2; + h = emalloc(n * sizeof *h); + for (i = 0; i < n; i++) + TAILQ_INIT(&h[i]); + oldh = ht->ht_tab; + n--; + for (i = 0; i < ht->ht_size; i++) { + while ((p = TAILQ_FIRST(&oldh[i])) != NULL) { + TAILQ_REMOVE(&oldh[i], p, h_next); + // XXXLUKEM: really should be TAILQ_INSERT_TAIL + TAILQ_INSERT_HEAD(&h[p->h_hash & n], p, h_next); + } + } + free(ht->ht_tab); + ht->ht_tab = h; + ht->ht_mask = n; + ht->ht_size = ++n; + ht->ht_lim = HASHFRACTION(n); +} + +/* + * Make a new hash entry, setting its h_next to NULL. + * If the free list is not empty, use the first entry from there, + * otherwise allocate a new entry. + */ +static inline struct hashent * +newhashent2(const char *name1, const char *name2, u_int h) +{ + struct hashent *hp; + + hp = ecalloc(1, sizeof(*hp)); + + 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(u_int h, const char *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); +} + +void +initintern(void) +{ + + ht_init(&strings, 128); +} + +/* + * Generate a single unique copy of the given string. We expect this + * function to be used frequently, so it should be fast. + */ +const char * +intern(const char *s) +{ + struct hashtab *ht; + struct hashent *hp; + struct hashenthead *hpp; + u_int h; + char *p; + + ht = &strings; + 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) + return (hp->h_name); + } + p = estrdup(s); + hp = newhashent(p, h); + TAILQ_INSERT_TAIL(hpp, hp, h_next); + if (++ht->ht_used > ht->ht_lim) + ht_expand(ht); + return (p); +} + +struct hashtab * +ht_new(void) +{ + struct hashtab *ht; + + ht = ecalloc(1, sizeof *ht); + ht_init(ht, 8); + return (ht); +} + +void +ht_free(struct hashtab *ht) +{ + size_t i; + struct hashent *hp; + struct hashenthead *hpp; + + for (i = 0; i < ht->ht_size; i++) { + hpp = &ht->ht_tab[i]; + while ((hp = TAILQ_FIRST(hpp)) != NULL) { + TAILQ_REMOVE(hpp, hp, h_next); + free(hp); + ht->ht_used--; + } + } + + assert(ht->ht_used == 0); + free(ht->ht_tab); + free(ht); +} + +/* + * Insert and/or replace. + */ +int +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 = hash2(0, nam1, nam2); + hpp = &ht->ht_tab[h & ht->ht_mask]; + TAILQ_FOREACH(hp, hpp, h_next) { + if (hp->h_name1 == nam1 && + hp->h_name2 == nam2) { + if (replace) + hp->h_value = val; + return (1); + } + } + hp = newhashent2(nam1, nam2, h); + TAILQ_INSERT_TAIL(hpp, hp, h_next); + hp->h_value = val; + if (++ht->ht_used > ht->ht_lim) + ht_expand(ht); + 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_remove2(struct hashtab *ht, const char *name1, const char *name2) +{ + struct hashent *hp; + struct hashenthead *hpp; + u_int h; + + h = hash2(0, name1, name2); + hpp = &ht->ht_tab[h & ht->ht_mask]; + + TAILQ_FOREACH(hp, hpp, h_next) { + if (hp->h_name1 != name1 || hp->h_name2 != name2) + continue; + TAILQ_REMOVE(hpp, hp, h_next); + + free(hp); + ht->ht_used--; + return (0); + } + return (1); +} + +int +ht_remove(struct hashtab *ht, const char *name) +{ + return ht_remove2(ht, name, NULL); +} + +void * +ht_lookup2(struct hashtab *ht, const char *nam1, const char *nam2) +{ + struct hashent *hp; + struct hashenthead *hpp; + u_int h; + + h = hash2(0, nam1, nam2); + hpp = &ht->ht_tab[h & ht->ht_mask]; + TAILQ_FOREACH(hp, hpp, h_next) + 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) +{ + 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 += (*cbfunc)(hp->h_name, hp->h_value, arg); + } + return rval; +} + +/************************************************************/ + +/* + * Type-safe wrappers. + */ + +#define DEFHASH(HT, VT) \ + struct HT { \ + struct hashtab imp; \ + }; \ + \ + struct HT * \ + HT##_create(void) \ + { \ + struct HT *tbl; \ + \ + tbl = ecalloc(1, sizeof(*tbl)); \ + ht_init(&tbl->imp, 8); \ + return tbl; \ + } \ + \ + int \ + HT##_insert(struct HT *tbl, const char *name, struct VT *val) \ + { \ + return ht_insert(&tbl->imp, name, val); \ + } \ + \ + int \ + HT##_replace(struct HT *tbl, const char *name, struct VT *val) \ + { \ + return ht_replace(&tbl->imp, name, val); \ + } \ + \ + int \ + HT##_remove(struct HT *tbl, const char *name) \ + { \ + return ht_remove(&tbl->imp, name); \ + } \ + \ + struct VT * \ + HT##_lookup(struct HT *tbl, const char *name) \ + { \ + return ht_lookup(&tbl->imp, name); \ + } \ + \ + struct HT##_enumcontext { \ + int (*func)(const char *, struct VT *, void *); \ + void *userctx; \ + }; \ + \ + static int \ + HT##_enumerate_thunk(const char *name, void *value, void *voidctx) \ + { \ + struct HT##_enumcontext *ctx = voidctx; \ + \ + return ctx->func(name, value, ctx->userctx); \ + } \ + \ + int \ + HT##_enumerate(struct HT *tbl, \ + int (*func)(const char *, struct VT *, void *), \ + void *userctx) \ + { \ + struct HT##_enumcontext ctx; \ + \ + ctx.func = func; \ + ctx.userctx = userctx; \ + return ht_enumerate(&tbl->imp, HT##_enumerate_thunk, &ctx); \ + } + +DEFHASH(nvhash, nvlist); +DEFHASH(dlhash, defoptlist); diff --git a/usr.bin/config/lint.c b/usr.bin/config/lint.c new file mode 100644 index 000000000..0066acd8b --- /dev/null +++ b/usr.bin/config/lint.c @@ -0,0 +1,208 @@ +/* $NetBSD: lint.c,v 1.15 2014/10/29 17:14:50 christos Exp $ */ + +/* + * Copyright (c) 2007 The NetBSD Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: lint.c,v 1.15 2014/10/29 17:14:50 christos Exp $"); + +#include +#include + +#include "defs.h" + +void +emit_params(void) +{ + + printf("version\t%d\n", CONFIG_VERSION); + printf("ident\t\"LINT_%s\"\n", conffile); + printf("maxusers\t%d\n", defmaxusers); + printf("config netbsdlint root on ?\n"); + printf("\n"); +} + +enum opt_types { + OT_FLAG, + OT_PARAM, + OT_FS +}; + +static struct opt_type { + enum opt_types ot_type; + const char *ot_name; + struct hashtab **ot_ht; +} opt_types[] = { + { OT_FLAG, "options", &opttab }, + { OT_PARAM, "options", &opttab }, + { OT_FS, "file-system", &fsopttab }, +}; + +static int +do_emit_option(const char *name, struct defoptlist *dl, void *v) +{ + const struct opt_type *ot = v; + const char *value; + + if (dl->dl_obsolete) + return 0; + + if (ht_lookup(*(ot->ot_ht), name)) + return 0; + + printf("%s\t%s", ot->ot_name, dl->dl_name); + if (ot->ot_type == OT_PARAM) { + struct defoptlist *dl2 = dlhash_lookup(defoptlint, dl->dl_name); + if (dl2 != NULL) + value = dl2->dl_lintvalue; + else + value = dl->dl_value; + assert(dl2 == dl); + printf("=\"%s\"", value ? value : "1"); + } + printf("\n"); + + return 1; +} + +/* + * Same as do_emit_option but for filesystem definitions, which now + * have a different data type. XXX these should probably be unified + * again. + */ +static int +do_emit_fs(const char *name, struct nvlist *nv, void *v) +{ + const struct opt_type *ot = v; + + if (ht_lookup(*(ot->ot_ht), name)) + return 0; + + assert(ot->ot_type != OT_PARAM); + printf("%s\t%s\n", ot->ot_name, nv->nv_name); + + return 1; +} + + +void +emit_options(void) +{ + + (void)dlhash_enumerate(defflagtab, do_emit_option, &opt_types[0]); + printf("\n"); + (void)dlhash_enumerate(defparamtab, do_emit_option, &opt_types[1]); + printf("\n"); + (void)nvhash_enumerate(deffstab, do_emit_fs, &opt_types[2]); + printf("\n"); +} + +static void +do_emit_instances(struct devbase *d, struct attr *at) +{ + struct nvlist *nv1; + struct loclist *ll; + struct attrlist *al; + struct attr *a; + struct deva *da; + + /* + * d_isdef is used to check whether a deva has been seen or not, + * for there are devices that can be their own ancestor (e.g. + * uhub, pci). + */ + + if (at != NULL) { + for (da = d->d_ahead; da != NULL; da = da->d_bsame) + if (onlist(da->d_atlist, at)) + break; + if (da == NULL) + panic("do_emit_instances: no deva found for %s at %s", + d->d_name, at->a_name); + + if (da->d_isdef > 1) + return; + da->d_isdef = 2; + } + + if (at == NULL && !d->d_ispseudo && d->d_ihead == NULL) + printf("%s0\tat\troot\n", d->d_name); + else if (at != NULL && !d->d_ispseudo && da->d_ihead == NULL) { + printf("%s0\tat\t%s?", d->d_name, at->a_name); + + for (ll = at->a_locs; ll != NULL; ll = ll->ll_next) { + if (ll->ll_num == 0) + printf(" %s %c", ll->ll_name, + ll->ll_string ? '?' : '0'); + } + + printf("\n"); + } + + /* + * Children attachments are found the same way as in the orphan + * detection code in main.c. + */ + for (al = d->d_attrs; al != NULL; al = al->al_next) { + a = al->al_this; + for (nv1 = a->a_devs; nv1 != NULL; nv1 = nv1->nv_next) + do_emit_instances(nv1->nv_ptr, a); + } +} + +/* ARGSUSED */ +static int +emit_root_instance(const char *name, void *value, void *v) +{ + + do_emit_instances((struct devbase *)value, NULL); + + return 1; +} + +/* ARGSUSED */ +static int +emit_pseudo_instance(const char *name, void *value, void *v) +{ + struct devbase *d = value; + + if (d->d_ispseudo && d->d_ihead == NULL) + printf("pseudo-device\t%s\n", d->d_name); + return 0; +} + +void +emit_instances(void) +{ + + (void)ht_enumerate(devroottab, emit_root_instance, NULL); + printf("\n"); + (void)ht_enumerate(devbasetab, emit_pseudo_instance, NULL); +} diff --git a/usr.bin/config/main.c b/usr.bin/config/main.c new file mode 100644 index 000000000..20f29e0bd --- /dev/null +++ b/usr.bin/config/main.c @@ -0,0 +1,2037 @@ +/* $NetBSD: main.c,v 1.89 2015/09/04 06:01:40 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)main.c 8.1 (Berkeley) 6/6/93 + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: main.c,v 1.89 2015/09/04 06:01:40 uebayasi Exp $"); + +#ifndef MAKE_BOOTSTRAP +#include +#define COPYRIGHT(x) __COPYRIGHT(x) +#else +#define COPYRIGHT(x) static const char copyright[] = x +#endif + +#ifndef lint +COPYRIGHT("@(#) Copyright (c) 1992, 1993\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#include +#include +#include +#include +#if !HAVE_NBTOOL_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "sem.h" + +#ifndef LINE_MAX +#define LINE_MAX 1024 +#endif + +int vflag; /* verbose output */ +int Pflag; /* pack locators */ +int Lflag; /* lint config generation */ +int Mflag; /* modular build */ +int Sflag; /* suffix rules & subdirectory */ +int handling_cmdlineopts; /* currently processing -D/-U options */ + +int yyparse(void); + +#ifndef MAKE_BOOTSTRAP +extern int yydebug; +#endif +int dflag; + +static struct dlhash *obsopttab; +static struct hashtab *mkopttab; +static struct nvlist **nextopt; +static struct nvlist **nextmkopt; +static struct nvlist **nextappmkopt; +static struct nvlist **nextcndmkopt; +static struct nvlist **nextfsopt; +static struct nvlist *cmdlinedefs, *cmdlineundefs; + +static void usage(void) __dead; +static void dependopts(void); +static void dependopts_one(const char *); +static void do_depends(struct nvlist *); +static void do_depend(struct nvlist *); +static void stop(void); +static int do_option(struct hashtab *, struct nvlist **, + struct nvlist ***, const char *, const char *, + const char *, struct hashtab *); +static int undo_option(struct hashtab *, struct nvlist **, + struct nvlist ***, const char *, const char *); +static int crosscheck(void); +static int badstar(void); + int main(int, char **); +static int mkallsubdirs(void); +static int mksymlinks(void); +static int mkident(void); +static int devbase_has_dead_instances(const char *, void *, void *); +static int devbase_has_any_instance(struct devbase *, int, int, int); +static int check_dead_devi(const char *, void *, void *); +static void add_makeopt(const char *); +static void remove_makeopt(const char *); +static void handle_cmdline_makeoptions(void); +static void kill_orphans(void); +static void do_kill_orphans(struct devbase *, struct attr *, + struct devbase *, int); +static int kill_orphans_cb(const char *, void *, void *); +static int cfcrosscheck(struct config *, const char *, struct nvlist *); +static void defopt(struct dlhash *ht, const char *fname, + struct defoptlist *opts, struct nvlist *deps, int obs); +static struct defoptlist *find_declared_option_option(const char *name); +static struct nvlist *find_declared_fs_option(const char *name); + +#define LOGCONFIG_LARGE "INCLUDE_CONFIG_FILE" +#define LOGCONFIG_SMALL "INCLUDE_JUST_CONFIG" + +static void logconfig_start(void); +static void logconfig_end(void); +static FILE *cfg; +static time_t cfgtime; + +static int is_elf(const char *); +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) +{ + char *p, cname[PATH_MAX]; + const char *last_component; + int pflag, xflag, ch, removeit; + + setprogname(argv[0]); + + pflag = 0; + xflag = 0; + while ((ch = getopt(argc, argv, "D:LMPSU:dgpvb:s:x")) != -1) { + switch (ch) { + + case 'd': +#ifndef MAKE_BOOTSTRAP + yydebug = 1; +#endif + dflag++; + break; + + case 'M': + Mflag = 1; + break; + + case 'L': + Lflag = 1; + break; + + case 'P': + Pflag = 1; + break; + + case 'g': + /* + * In addition to DEBUG, you probably wanted to + * set "options KGDB" and maybe others. We could + * do that for you, but you really should just + * put them in the config file. + */ + warnx("-g is obsolete (use -D DEBUG=\"-g\")"); + usage(); + /*NOTREACHED*/ + + case 'p': + /* + * Essentially the same as makeoptions PROF="-pg", + * but also changes the path from ../../compile/FOO + * to ../../compile/FOO.PROF; i.e., compile a + * profiling kernel based on a typical "regular" + * kernel. + * + * Note that if you always want profiling, you + * can (and should) use a "makeoptions" line. + */ + pflag = 1; + break; + + case 'v': + vflag = 1; + break; + + case 'b': + builddir = optarg; + break; + + case 's': + srcdir = optarg; + break; + + case 'S': + Sflag = 1; + break; + + case 'x': + xflag = 1; + break; + + case 'D': + add_makeopt(optarg); + break; + + case 'U': + remove_makeopt(optarg); + break; + + case '?': + default: + usage(); + } + } + + if (xflag && optind != 2) { + errx(EXIT_FAILURE, "-x must be used alone"); + } + + argc -= optind; + argv += optind; + if (argc > 1) { + usage(); + } + + if (Lflag && (builddir != NULL || Pflag || pflag)) + errx(EXIT_FAILURE, "-L can only be used with -s and -v"); + + if (xflag) { + if (argc == 0) { +#if !HAVE_NBTOOL_CONFIG_H + char path_unix[MAXPATHLEN]; + size_t len = sizeof(path_unix) - 1; + path_unix[0] = '/'; + + conffile = sysctlbyname("machdep.booted_kernel", + &path_unix[1], &len, NULL, 0) == -1 ? _PATH_UNIX : + path_unix; +#else + errx(EXIT_FAILURE, "no kernel supplied"); +#endif + } else + conffile = argv[0]; + if (!is_elf(conffile)) + errx(EXIT_FAILURE, "%s: not a binary kernel", + conffile); + if (!extract_config(conffile, "stdout", STDOUT_FILENO)) + errx(EXIT_FAILURE, "%s does not contain embedded " + "configuration data", conffile); + exit(0); + } + + conffile = (argc == 1) ? argv[0] : "CONFIG"; + if (firstfile(conffile)) { + err(EXIT_FAILURE, "Cannot read `%s'", conffile); + exit(2); + } + + /* + * Init variables. + */ + minmaxusers = 1; + maxmaxusers = 10000; + initintern(); + ident = NULL; + devbasetab = ht_new(); + devroottab = ht_new(); + devatab = ht_new(); + devitab = ht_new(); + deaddevitab = ht_new(); + selecttab = ht_new(); + needcnttab = ht_new(); + opttab = ht_new(); + mkopttab = ht_new(); + fsopttab = ht_new(); + deffstab = nvhash_create(); + defopttab = dlhash_create(); + defparamtab = dlhash_create(); + defoptlint = dlhash_create(); + defflagtab = dlhash_create(); + optfiletab = dlhash_create(); + obsopttab = dlhash_create(); + bdevmtab = ht_new(); + maxbdevm = 0; + cdevmtab = ht_new(); + maxcdevm = 0; + nextopt = &options; + nextmkopt = &mkoptions; + nextappmkopt = &appmkoptions; + nextcndmkopt = &condmkoptions; + nextfsopt = &fsoptions; + initfiles(); + initsem(); + + /* + * Handle profiling (must do this before we try to create any + * files). + */ + last_component = strrchr(conffile, '/'); + last_component = (last_component) ? last_component + 1 : conffile; + if (pflag) { + p = emalloc(strlen(last_component) + 17); + (void)sprintf(p, "../compile/%s.PROF", last_component); + (void)addmkoption(intern("PROF"), "-pg"); + (void)addoption(intern("GPROF"), NULL); + } else { + p = emalloc(strlen(last_component) + 13); + (void)sprintf(p, "../compile/%s", last_component); + } + defbuilddir = (argc == 0) ? "." : p; + + if (Lflag) { + char resolvedname[MAXPATHLEN]; + + if (realpath(conffile, resolvedname) == NULL) + err(EXIT_FAILURE, "realpath(%s)", conffile); + + if (yyparse()) + stop(); + + printf("include \"%s\"\n", resolvedname); + + emit_params(); + emit_options(); + emit_instances(); + + exit(EXIT_SUCCESS); + } + + removeit = 0; + if (is_elf(conffile)) { + const char *tmpdir; + int cfd; + + if (builddir == NULL) + errx(EXIT_FAILURE, "Build directory must be specified " + "with binary kernels"); + + /* Open temporary configuration file */ + tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + tmpdir = _PATH_TMP; + snprintf(cname, sizeof(cname), "%s/config.tmp.XXXXXX", tmpdir); + cfd = mkstemp(cname); + if (cfd == -1) + err(EXIT_FAILURE, "Cannot create `%s'", cname); + + printf("Using configuration data embedded in kernel...\n"); + if (!extract_config(conffile, cname, cfd)) { + unlink(cname); + errx(EXIT_FAILURE, "%s does not contain embedded " + "configuration data", conffile); + } + + removeit = 1; + close(cfd); + firstfile(cname); + } + + /* + * Log config file. We don't know until yyparse() if we're + * going to need config_file.h (i.e. if we're doing ioconf-only + * or not). Just start creating the file, and when we know + * later, we'll just keep or discard our work here. + */ + logconfig_start(); + + /* + * Parse config file (including machine definitions). + */ + if (yyparse()) + stop(); + + if (ioconfname && cfg) + fclose(cfg); + else + logconfig_end(); + + if (removeit) + unlink(cname); + + /* + * 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(); + + /* + * Copy maxusers to param. + */ + yyfile = "fixmaxusers"; + fixmaxusers(); + + /* + * Copy makeoptions to params + */ + yyfile = "fixmkoption"; + fixmkoption(); + + /* + * 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 device-majors. + */ + yyfile = "fixdevsw"; + if (fixdevsw()) + stop(); + + /* + * Perform cross-checking. + */ + if (maxusers == 0) { + if (defmaxusers) { + (void)printf("maxusers not specified; %d assumed\n", + defmaxusers); + maxusers = defmaxusers; + } else { + warnx("need \"maxusers\" line"); + errors++; + } + } + if (crosscheck() || errors) + stop(); + + /* + * 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. + */ + if ((Sflag && mkallsubdirs()) || mksymlinks() || mkmakefile() || mkheaders() || mkswap() || + mkioconf() || (do_devsw ? mkdevsw() : 0) || mkident() || errors) + stop(); + (void)printf("Build directory is %s\n", builddir); + (void)printf("Don't forget to run \"make depend\"\n"); + + return 0; +} + +static void +usage(void) +{ + (void)fprintf(stderr, "Usage: %s [-Ppv] [-b builddir] [-D var=value] " + "[-s srcdir] [-U var] " + "[config-file]\n\t%s -x [kernel-file]\n" + "\t%s -L [-v] [-s srcdir] [config-file]\n", + getprogname(), getprogname(), getprogname()); + exit(1); +} + +/* + * Set any options that are implied by other options. + */ +static void +dependopts(void) +{ + struct nvlist *nv; + + for (nv = options; nv != NULL; nv = nv->nv_next) { + dependopts_one(nv->nv_name); + } + + for (nv = fsoptions; nv != NULL; nv = nv->nv_next) { + dependopts_one(nv->nv_name); + } +} + +static void +dependopts_one(const char *name) +{ + struct defoptlist *dl; + struct nvlist *fs; + + dl = find_declared_option_option(name); + if (dl != NULL) { + do_depends(dl->dl_depends); + } + fs = find_declared_fs_option(name); + if (fs != NULL) { + do_depends(fs->nv_ptr); + } + + CFGDBG(3, "depend `%s' searched", name); +} + +static void +do_depends(struct nvlist *nv) +{ + struct nvlist *opt; + + for (opt = nv; opt != NULL; opt = opt->nv_next) { + do_depend(opt); + } +} + +static void +do_depend(struct nvlist *nv) +{ + struct attr *a; + + if (nv != NULL && (nv->nv_flags & NV_DEPENDED) == 0) { + nv->nv_flags |= NV_DEPENDED; + /* + * 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", + nv->nv_name, a->a_name); + expandattr(a, selectattr); + } else { + if (ht_lookup(opttab, nv->nv_name) == NULL) + addoption(nv->nv_name, NULL); + dependopts_one(nv->nv_name); + } + } +} + +static int +recreate(const char *p, const char *q) +{ + int ret; + + if ((ret = unlink(q)) == -1 && errno != ENOENT) + warn("unlink(%s)", q); + if ((ret = symlink(p, q)) == -1) + warn("symlink(%s -> %s)", q, p); + return ret; +} + +static void +mksubdir(char *buf) +{ + char *p; + struct stat st; + + p = strrchr(buf, '/'); + if (p != NULL && *p == '/') { + *p = '\0'; + mksubdir(buf); + *p = '/'; + } + if (stat(buf, &st) == 0) { + if (!S_ISDIR(st.st_mode)) + errx(EXIT_FAILURE, "not directory %s", buf); + } else + if (mkdir(buf, 0777) == -1) + errx(EXIT_FAILURE, "cannot create %s", buf); +} + +static int +mksubdirs(struct filelist *fl) +{ + struct files *fi; + const char *prologue, *prefix, *sep; + char buf[MAXPATHLEN]; + + TAILQ_FOREACH(fi, fl, fi_next) { + if ((fi->fi_flags & FI_SEL) == 0) + continue; + prefix = sep = ""; + if (fi->fi_buildprefix != NULL) { + prefix = fi->fi_buildprefix; + sep = "/"; + } else { + if (fi->fi_prefix != NULL) { + prefix = fi->fi_prefix; + sep = "/"; + } + } + snprintf(buf, sizeof(buf), "%s%s%s", prefix, sep, fi->fi_dir); + if (buf[0] == '\0') + continue; + mksubdir(buf); + if (fi->fi_prefix != NULL && fi->fi_buildprefix != NULL) { + char org[MAXPATHLEN]; + + if (fi->fi_prefix[0] == '/') { + prologue = ""; + sep = ""; + } else { + prologue = srcdir; + sep = "/"; + } + snprintf(buf, sizeof(buf), "%s%s%s", + fi->fi_buildprefix, "/", fi->fi_path); + snprintf(org, sizeof(org), "%s%s%s%s%s", + prologue, sep, fi->fi_prefix, "/", fi->fi_path); + recreate(org, buf); + fi->fi_prefix = fi->fi_buildprefix; + fi->fi_buildprefix = NULL; + } + } + + return 0; +} + +static int +mkallsubdirs(void) +{ + + mksubdirs(&allfiles); + mksubdirs(&allofiles); + return 0; +} + +/* + * Make a symlink for "machine" so that "#include " works, + * and for the machine's CPU architecture, so that works as well. + */ +static int +mksymlinks(void) +{ + int ret; + char *p, buf[MAXPATHLEN]; + const char *q; + struct nvlist *nv; + + p = buf; + + snprintf(buf, sizeof(buf), "%s/arch/%s/include", srcdir, machine); + ret = recreate(p, "machine"); + ret = recreate(p, machine); + + if (machinearch != NULL) { + snprintf(buf, sizeof(buf), "%s/arch/%s/include", srcdir, machinearch); + q = machinearch; + } else { + snprintf(buf, sizeof(buf), "machine"); + q = machine; + } + + ret = recreate(p, q); + + for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) { + q = nv->nv_name; + snprintf(buf, sizeof(buf), "%s/arch/%s/include", srcdir, q); + ret = recreate(p, q); + } + + return (ret); +} + +static __dead void +stop(void) +{ + (void)fprintf(stderr, "*** Stop.\n"); + exit(1); +} + +static void +check_dependencies(const char *thing, struct nvlist *deps) +{ + struct nvlist *dep; + struct attr *a; + + for (dep = deps; dep != NULL; dep = dep->nv_next) { + /* + * If the dependency is an attribute, it must not + * be an interface attribute. Otherwise, it must + * be a previously declared option. + */ + if ((a = ht_lookup(attrtab, dep->nv_name)) != NULL) { + if (a->a_iattr) + cfgerror("option `%s' dependency `%s' " + "is an interface attribute", + thing, a->a_name); + } else if (OPT_OBSOLETE(dep->nv_name)) { + cfgerror("option `%s' dependency `%s' " + "is obsolete", thing, dep->nv_name); + } else if (!is_declared_option(dep->nv_name)) { + cfgerror("option `%s' dependency `%s' " + "is an unknown option", + thing, dep->nv_name); + } + } +} + +static void +add_fs_dependencies(struct nvlist *nv, struct nvlist *deps) +{ + /* Use nv_ptr to link any other options that are implied. */ + nv->nv_ptr = deps; + check_dependencies(nv->nv_name, deps); +} + +static void +add_opt_dependencies(struct defoptlist *dl, struct nvlist *deps) +{ + dl->dl_depends = deps; + check_dependencies(dl->dl_name, deps); +} + +/* + * Define one or more file systems. + */ +void +deffilesystem(struct nvlist *fses, struct nvlist *deps) +{ + struct nvlist *nv; + + /* + * Mark these options as ones to skip when creating the Makefile. + */ + for (nv = fses; nv != NULL; nv = nv->nv_next) { + if (DEFINED_OPTION(nv->nv_name)) { + cfgerror("file system or option `%s' already defined", + nv->nv_name); + return; + } + + /* + * Also mark it as a valid file system, which may be + * used in "file-system" directives in the config + * file. + */ + if (nvhash_insert(deffstab, nv->nv_name, nv)) + panic("file system `%s' already in table?!", + nv->nv_name); + + add_fs_dependencies(nv, deps); + + /* + * Implicit attribute definition for filesystem. + */ + const char *n; + n = strtolower(nv->nv_name); + refattr(n); + } +} + +/* + * Sanity check a file name. + */ +int +badfilename(const char *fname) +{ + const char *n; + + /* + * We're putting multiple options into one file. Sanity + * check the file name. + */ + if (strchr(fname, '/') != NULL) { + cfgerror("option file name contains a `/'"); + return 1; + } + if ((n = strrchr(fname, '.')) == NULL || strcmp(n, ".h") != 0) { + cfgerror("option file name does not end in `.h'"); + return 1; + } + return 0; +} + + +/* + * Search for a defined option (defopt, filesystem, etc), and if found, + * return the option's struct nvlist. + * + * This used to be one function (find_declared_option) before options + * and filesystems became different types. + */ +static struct defoptlist * +find_declared_option_option(const char *name) +{ + struct defoptlist *option; + + if ((option = dlhash_lookup(defopttab, name)) != NULL || + (option = dlhash_lookup(defparamtab, name)) != NULL || + (option = dlhash_lookup(defflagtab, name)) != NULL) { + return (option); + } + + return (NULL); +} + +static struct nvlist * +find_declared_fs_option(const char *name) +{ + struct nvlist *fs; + + if ((fs = nvhash_lookup(deffstab, name)) != NULL) { + return fs; + } + + return (NULL); +} + +/* + * Like find_declared_option but doesn't return what it finds, so it + * can search both the various kinds of options and also filesystems. + */ +int +is_declared_option(const char *name) +{ + struct defoptlist *option = NULL; + struct nvlist *fs; + + if ((option = dlhash_lookup(defopttab, name)) != NULL || + (option = dlhash_lookup(defparamtab, name)) != NULL || + (option = dlhash_lookup(defflagtab, name)) != NULL) { + return 1; + } + if ((fs = nvhash_lookup(deffstab, name)) != NULL) { + return 1; + } + + return 0; +} + +/* + * Define one or more standard options. If an option file name is specified, + * place all options in one file with the specified name. Otherwise, create + * an option file for each option. + * record the option information in the specified table. + */ +void +defopt(struct dlhash *ht, const char *fname, struct defoptlist *opts, + struct nvlist *deps, int obs) +{ + struct defoptlist *dl, *nextdl, *olddl; + const char *name; + char buf[500]; + + if (fname != NULL && badfilename(fname)) { + return; + } + + /* + * Mark these options as ones to skip when creating the Makefile. + */ + for (dl = opts; dl != NULL; dl = nextdl) { + nextdl = dl->dl_next; + + if (dl->dl_lintvalue != NULL) { + /* + * If an entry already exists, then we are about to + * complain, so no worry. + */ + (void) dlhash_insert(defoptlint, dl->dl_name, + dl); + } + + /* An option name can be declared at most once. */ + if (DEFINED_OPTION(dl->dl_name)) { + cfgerror("file system or option `%s' already defined", + dl->dl_name); + return; + } + + if (dlhash_insert(ht, dl->dl_name, dl)) { + cfgerror("file system or option `%s' already defined", + dl->dl_name); + return; + } + + if (fname == NULL) { + /* + * Each option will be going into its own file. + * Convert the option name to lower case. This + * lower case name will be used as the option + * file name. + */ + (void) snprintf(buf, sizeof(buf), "opt_%s.h", + strtolower(dl->dl_name)); + name = intern(buf); + } else { + name = fname; + } + + add_opt_dependencies(dl, deps); + + /* + * Remove this option from the parameter list before adding + * it to the list associated with this option file. + */ + dl->dl_next = NULL; + + /* + * Flag as obsolete, if requested. + */ + if (obs) { + dl->dl_obsolete = 1; + (void)dlhash_insert(obsopttab, dl->dl_name, dl); + } + + /* + * Add this option file if we haven't seen it yet. + * Otherwise, append to the list of options already + * associated with this file. + */ + if ((olddl = dlhash_lookup(optfiletab, name)) == NULL) { + (void)dlhash_insert(optfiletab, name, dl); + } else { + while (olddl->dl_next != NULL) + olddl = olddl->dl_next; + olddl->dl_next = dl; + } + } +} + +/* + * Define one or more standard options. If an option file name is specified, + * place all options in one file with the specified name. Otherwise, create + * an option file for each option. + */ +void +defoption(const char *fname, struct defoptlist *opts, struct nvlist *deps) +{ + + cfgwarn("The use of `defopt' is deprecated"); + defopt(defopttab, fname, opts, deps, 0); +} + + +/* + * Define an option for which a value is required. + */ +void +defparam(const char *fname, struct defoptlist *opts, struct nvlist *deps, int obs) +{ + + defopt(defparamtab, fname, opts, deps, obs); +} + +/* + * Define an option which must not have a value, and which + * emits a "needs-flag" style output. + */ +void +defflag(const char *fname, struct defoptlist *opts, struct nvlist *deps, int obs) +{ + + defopt(defflagtab, fname, opts, deps, obs); +} + + +/* + * Add an option from "options FOO". Note that this selects things that + * are "optional foo". + */ +void +addoption(const char *name, const char *value) +{ + const char *n; + int is_fs, is_param, is_flag, is_undecl, is_obs; + + /* + * Figure out how this option was declared (if at all.) + * XXX should use "params" and "flags" in config. + * XXX crying out for a type field in a unified hashtab. + */ + is_fs = OPT_FSOPT(name); + is_param = OPT_DEFPARAM(name); + is_flag = OPT_DEFFLAG(name); + is_obs = OPT_OBSOLETE(name); + is_undecl = !DEFINED_OPTION(name); + + /* Warn and pretend the user had not selected the option */ + if (is_obs) { + cfgwarn("obsolete option `%s' will be ignored", name); + return; + } + + /* Make sure this is not a defined file system. */ + if (is_fs) { + cfgerror("`%s' is a defined file system", name); + return; + } + /* A defparam must have a value */ + if (is_param && value == NULL) { + cfgerror("option `%s' must have a value", name); + return; + } + /* A defflag must not have a value */ + if (is_flag && value != NULL) { + cfgerror("option `%s' must not have a value", name); + return; + } + + if (is_undecl && vflag) { + cfgwarn("undeclared option `%s' added to IDENT", name); + } + + if (do_option(opttab, &options, &nextopt, name, value, "options", + selecttab)) + return; + + /* 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")) + return; +} + +/* + * Add a file system option. This routine simply inserts the name into + * a list of valid file systems, which is used to validate the root + * file system type. The name is then treated like a standard option. + */ +void +addfsoption(const char *name) +{ + const char *n; + + /* Make sure this is a defined file system. */ + if (!OPT_FSOPT(name)) { + cfgerror("`%s' is not a defined file system", name); + return; + } + + /* + * Convert to lower case. This will be used in the select + * table, to verify root file systems. + */ + n = strtolower(name); + + if (do_option(fsopttab, &fsoptions, &nextfsopt, name, n, "file-system", + selecttab)) + return; + + /* 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 +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; + if (undo_option(selecttab, NULL, NULL, n, "file-system")) + return; +} + +/* + * Add a "make" option. + */ +void +addmkoption(const char *name, const char *value) +{ + + (void)do_option(mkopttab, &mkoptions, &nextmkopt, name, value, + "makeoptions", NULL); +} + +void +delmkoption(const char *name) +{ + + CFGDBG(4, "deselecting mkopt `%s'", name); + (void)undo_option(mkopttab, &mkoptions, &nextmkopt, name, + "makeoptions"); +} + +/* + * Add an appending "make" option. + */ +void +appendmkoption(const char *name, const char *value) +{ + struct nvlist *nv; + + nv = newnv(name, value, NULL, 0, NULL); + *nextappmkopt = nv; + nextappmkopt = &nv->nv_next; +} + +/* + * Add a conditional appending "make" option. + */ +void +appendcondmkoption(struct condexpr *cond, const char *name, const char *value) +{ + struct nvlist *nv; + + nv = newnv(name, value, cond, 0, NULL); + *nextcndmkopt = nv; + nextcndmkopt = &nv->nv_next; +} + +/* + * Copy maxusers to param "MAXUSERS". + */ +void +fixmaxusers(void) +{ + char str[32]; + + snprintf(str, sizeof(str), "%d", maxusers); + addoption(intern("MAXUSERS"), intern(str)); +} + +/* + * Copy makeoptions to params with "makeoptions_" prefix. + */ +void +fixmkoption(void) +{ + struct nvlist *nv; + char buf[100]; + const char *name; + + for (nv = mkoptions; nv != NULL; nv = nv->nv_next) { + snprintf(buf, sizeof(buf), "makeoptions_%s", nv->nv_name); + name = intern(buf); + if (!DEFINED_OPTION(name) || !OPT_DEFPARAM(name)) + continue; + addoption(name, intern(nv->nv_str)); + } +} + +/* + * Add a name=value pair to an option list. The value may be NULL. + */ +static int +do_option(struct hashtab *ht, struct nvlist **npp, struct nvlist ***next, + const char *name, const char *value, const char *type, + struct hashtab *stab) +{ + struct nvlist *nv, *onv; + + /* assume it will work */ + nv = newnv(name, value, NULL, 0, NULL); + if (ht_insert(ht, name, nv) != 0) { + + /* oops, already got that option - remove it first */ + if ((onv = ht_lookup(ht, name)) == NULL) + panic("do_option 1"); + if (onv->nv_str != NULL && !OPT_FSOPT(name)) + cfgwarn("already have %s `%s=%s'", type, name, + onv->nv_str); + else + cfgwarn("already have %s `%s'", type, name); + + if (undo_option(ht, npp, next, name, type)) + panic("do_option 2"); + if (stab != NULL && + undo_option(stab, NULL, NULL, strtolower(name), type)) + panic("do_option 3"); + + /* now try adding it again */ + if (ht_insert(ht, name, nv) != 0) + panic("do_option 4"); + + CFGDBG(2, "opt `%s' replaced", name); + } + **next = nv; + *next = &nv->nv_next; + + return (0); +} + +/* + * Remove a name from a hash table, + * and optionally, a name=value pair from an option list. + */ +static int +undo_option(struct hashtab *ht, struct nvlist **npp, + struct nvlist ***next, const char *name, const char *type) +{ + struct nvlist *nv; + + if (ht_remove(ht, name)) { + /* + * -U command line option removals are always silent + */ + if (!handling_cmdlineopts) + cfgwarn("%s `%s' is not defined", type, name); + return (1); + } + if (npp == NULL) { + CFGDBG(2, "opt `%s' deselected", name); + return (0); + } + + for ( ; *npp != NULL; npp = &(*npp)->nv_next) { + if ((*npp)->nv_name != name) + continue; + 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); + } + panic("%s `%s' is not defined in nvlist", type, name); + return (1); +} + +/* + * Return true if there is at least one instance of the given unit + * on the given device attachment (or any units, if unit == WILD). + */ +int +deva_has_instances(struct deva *deva, int unit) +{ + struct devi *i; + + /* + * EHAMMERTOOBIG: we shouldn't check i_pseudoroot here. + * What we want by this check is them to appear non-present + * except for purposes of other devices being able to attach + * to them. + */ + for (i = deva->d_ihead; i != NULL; i = i->i_asame) + if (i->i_active == DEVI_ACTIVE && i->i_pseudoroot == 0 && + (unit == WILD || unit == i->i_unit || i->i_unit == STAR)) + return (1); + return (0); +} + +/* + * Return true if there is at least one instance of the given unit + * on the given base (or any units, if unit == WILD). + */ +int +devbase_has_instances(struct devbase *dev, int unit) +{ + struct deva *da; + + /* + * Pseudo-devices are a little special. We consider them + * to have instances only if they are both: + * + * 1. Included in this kernel configuration. + * + * 2. Be declared "defpseudodev". + */ + if (dev->d_ispseudo) { + return ((ht_lookup(devitab, dev->d_name) != NULL) + && (dev->d_ispseudo > 1)); + } + + for (da = dev->d_ahead; da != NULL; da = da->d_bsame) + if (deva_has_instances(da, unit)) + return (1); + return (0); +} + +static int +cfcrosscheck(struct config *cf, const char *what, struct nvlist *nv) +{ + struct devbase *dev; + struct devi *pd; + int errs, devunit; + + if (maxpartitions <= 0) + panic("cfcrosscheck"); + + for (errs = 0; nv != NULL; nv = nv->nv_next) { + if (nv->nv_name == NULL) + continue; + dev = ht_lookup(devbasetab, nv->nv_name); + if (dev == NULL) + panic("cfcrosscheck(%s)", nv->nv_name); + if (has_attr(dev->d_attrs, s_ifnet)) + devunit = nv->nv_ifunit; /* XXX XXX XXX */ + else + devunit = (int)(minor(nv->nv_num) / maxpartitions); + if (devbase_has_instances(dev, devunit)) + continue; + if (devbase_has_instances(dev, STAR) && + devunit >= dev->d_umax) + continue; + TAILQ_FOREACH(pd, &allpseudo, i_next) { + if (pd->i_base == dev && devunit < dev->d_umax && + devunit >= 0) + goto loop; + } + (void)fprintf(stderr, + "%s:%d: %s says %s on %s, but there's no %s\n", + conffile, cf->cf_lineno, + cf->cf_name, what, nv->nv_str, nv->nv_str); + errs++; + loop: + ; + } + return (errs); +} + +/* + * Cross-check the configuration: make sure that each target device + * or attribute (`at foo[0*?]') names at least one real device. Also + * see that the root and dump devices for all configurations are there. + */ +int +crosscheck(void) +{ + struct config *cf; + int errs; + + errs = 0; + if (TAILQ_EMPTY(&allcf)) { + warnx("%s has no configurations!", conffile); + errs++; + } + TAILQ_FOREACH(cf, &allcf, cf_next) { + if (cf->cf_root != NULL) { /* i.e., not root on ? */ + errs += cfcrosscheck(cf, "root", cf->cf_root); + errs += cfcrosscheck(cf, "dumps", cf->cf_dump); + } + } + return (errs); +} + +/* + * Check to see if there is a *'d unit with a needs-count file. + */ +int +badstar(void) +{ + struct devbase *d; + struct deva *da; + struct devi *i; + int errs, n; + + errs = 0; + TAILQ_FOREACH(d, &allbases, d_next) { + for (da = d->d_ahead; da != NULL; da = da->d_bsame) + for (i = da->d_ihead; i != NULL; i = i->i_asame) { + if (i->i_unit == STAR) + goto aybabtu; + } + continue; + aybabtu: + if (ht_lookup(needcnttab, d->d_name)) { + warnx("%s's cannot be *'d until its driver is fixed", + d->d_name); + errs++; + continue; + } + for (n = 0; i != NULL; i = i->i_alias) + if (!i->i_collapsed) + n++; + if (n < 1) + panic("badstar() n<1"); + } + return (errs); +} + +/* + * Verify/create builddir if necessary, change to it, and verify srcdir. + * This will be called when we see the first include. + */ +void +setupdirs(void) +{ + struct stat st; + + /* srcdir must be specified if builddir is not specified or if + * no configuration filename was specified. */ + if ((builddir || strcmp(defbuilddir, ".") == 0) && !srcdir) { + cfgerror("source directory must be specified"); + exit(1); + } + + if (Lflag) { + if (srcdir == NULL) + srcdir = "../../.."; + return; + } + + if (srcdir == NULL) + srcdir = "../../../.."; + if (builddir == NULL) + builddir = defbuilddir; + + if (stat(builddir, &st) == -1) { + if (mkdir(builddir, 0777) == -1) + errx(EXIT_FAILURE, "cannot create %s", builddir); + } else if (!S_ISDIR(st.st_mode)) + errx(EXIT_FAILURE, "%s is not a directory", builddir); + if (chdir(builddir) == -1) + err(EXIT_FAILURE, "cannot change to %s", builddir); + if (stat(srcdir, &st) == -1) + err(EXIT_FAILURE, "cannot stat %s", srcdir); + if (!S_ISDIR(st.st_mode)) + errx(EXIT_FAILURE, "%s is not a directory", srcdir); +} + +/* + * Write identifier from "ident" directive into file, for + * newvers.sh to pick it up. + */ +int +mkident(void) +{ + FILE *fp; + int error = 0; + + (void)unlink("ident"); + + if (ident == NULL) + return (0); + + if ((fp = fopen("ident", "w")) == NULL) { + warn("cannot write ident"); + return (1); + } + if (vflag) + (void)printf("using ident '%s'\n", ident); + fprintf(fp, "%s\n", ident); + fflush(fp); + if (ferror(fp)) + error = 1; + (void)fclose(fp); + + return error; +} + +void +logconfig_start(void) +{ + extern FILE *yyin; + char line[1024]; + const char *tmpdir; + struct stat st; + int fd; + + if (yyin == NULL || fstat(fileno(yyin), &st) == -1) + return; + cfgtime = st.st_mtime; + + tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + tmpdir = _PATH_TMP; + (void)snprintf(line, sizeof(line), "%s/config.tmp.XXXXXX", tmpdir); + if ((fd = mkstemp(line)) == -1 || + (cfg = fdopen(fd, "r+")) == NULL) { + if (fd != -1) { + (void)unlink(line); + (void)close(fd); + } + cfg = NULL; + return; + } + (void)unlink(line); + + (void)fprintf(cfg, "#include \n\n"); + (void)fprintf(cfg, "#include \"opt_config.h\"\n"); + (void)fprintf(cfg, "\n"); + (void)fprintf(cfg, "/*\n"); + (void)fprintf(cfg, " * Add either (or both) of\n"); + (void)fprintf(cfg, " *\n"); + (void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_LARGE); + (void)fprintf(cfg, " *\toptions %s\n", LOGCONFIG_SMALL); + (void)fprintf(cfg, " *\n"); + (void)fprintf(cfg, + " * to your kernel config file to embed it in the resulting\n"); + (void)fprintf(cfg, + " * kernel. The latter option does not include files that are\n"); + (void)fprintf(cfg, + " * included (recursively) by your config file. The embedded\n"); + (void)fprintf(cfg, + " * data be extracted by using the command:\n"); + (void)fprintf(cfg, " *\n"); + (void)fprintf(cfg, + " *\tstrings netbsd | sed -n 's/^_CFG_//p' | unvis\n"); + (void)fprintf(cfg, " */\n"); + (void)fprintf(cfg, "\n"); + (void)fprintf(cfg, "#ifdef CONFIG_FILE\n"); + (void)fprintf(cfg, "#if defined(%s) || defined(%s)\n\n", + LOGCONFIG_LARGE, LOGCONFIG_SMALL); + (void)fprintf(cfg, "static const char config[] __used =\n\n"); + + (void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE); + (void)fprintf(cfg, "\"_CFG_### START CONFIG FILE \\\"%s\\\"\\n\"\n\n", + conffile); + (void)fprintf(cfg, "#endif /* %s */\n\n", LOGCONFIG_LARGE); + + logconfig_include(yyin, NULL); + + (void)fprintf(cfg, "#ifdef %s\n\n", LOGCONFIG_LARGE); + (void)fprintf(cfg, "\"_CFG_### END CONFIG FILE \\\"%s\\\"\\n\"\n", + conffile); + + rewind(yyin); +} + +void +logconfig_include(FILE *cf, const char *filename) +{ + char line[1024], in[2048], *out; + struct stat st; + int missingeol; + + if (!cfg) + return; + + missingeol = 0; + if (fstat(fileno(cf), &st) == -1) + return; + if (cfgtime < st.st_mtime) + cfgtime = st.st_mtime; + + if (filename) + (void)fprintf(cfg, + "\"_CFG_### (included from \\\"%s\\\")\\n\"\n", + filename); + while (fgets(line, sizeof(line), cf) != NULL) { + missingeol = 1; + (void)fprintf(cfg, "\"_CFG_"); + if (filename) + (void)fprintf(cfg, "###> "); + strvis(in, line, VIS_TAB); + for (out = in; *out; out++) + switch (*out) { + case '\n': + (void)fprintf(cfg, "\\n\"\n"); + missingeol = 0; + break; + case '"': case '\\': + (void)fputc('\\', cfg); + /* FALLTHROUGH */ + default: + (void)fputc(*out, cfg); + break; + } + } + if (missingeol) { + (void)fprintf(cfg, "\\n\"\n"); + warnx("%s: newline missing at EOF", + filename != NULL ? filename : conffile); + } + if (filename) + (void)fprintf(cfg, "\"_CFG_### (end include \\\"%s\\\")\\n\"\n", + filename); + + rewind(cf); +} + +void +logconfig_end(void) +{ + char line[1024]; + FILE *fp; + struct stat st; + + if (!cfg) + return; + + (void)fprintf(cfg, "#endif /* %s */\n", LOGCONFIG_LARGE); + (void)fprintf(cfg, ";\n"); + (void)fprintf(cfg, "#endif /* %s || %s */\n", + LOGCONFIG_LARGE, LOGCONFIG_SMALL); + (void)fprintf(cfg, "#endif /* CONFIG_FILE */\n"); + fflush(cfg); + if (ferror(cfg)) + err(EXIT_FAILURE, "write to temporary file for config.h failed"); + rewind(cfg); + + if (stat("config_file.h", &st) != -1) { + if (cfgtime < st.st_mtime) { + fclose(cfg); + return; + } + } + + fp = fopen("config_file.h", "w"); + if (!fp) + err(EXIT_FAILURE, "cannot open \"config.h\""); + + while (fgets(line, sizeof(line), cfg) != NULL) + fputs(line, fp); + fflush(fp); + if (ferror(fp)) + err(EXIT_FAILURE, "write to \"config.h\" failed"); + fclose(fp); + fclose(cfg); +} + +const char * +strtolower(const char *name) +{ + const char *n; + char *p, low[500]; + char c; + + for (n = name, p = low; (c = *n) != '\0'; n++) + *p++ = (char)(isupper((u_char)c) ? tolower((u_char)c) : c); + *p = '\0'; + return (intern(low)); +} + +static int +is_elf(const char *file) +{ + int kernel; + char hdr[4]; + + kernel = open(file, O_RDONLY); + if (kernel == -1) + err(EXIT_FAILURE, "cannot open %s", file); + if (read(kernel, hdr, 4) != 4) + err(EXIT_FAILURE, "Cannot read from %s", file); + (void)close(kernel); + + return memcmp("\177ELF", hdr, 4) == 0 ? 1 : 0; +} + +static int +extract_config(const char *kname, const char *cname, int cfd) +{ + char *ptr; + void *base; + int found, kfd; + struct stat st; + off_t i; + + found = 0; + + /* mmap(2) binary kernel */ + kfd = open(conffile, O_RDONLY); + if (kfd == -1) + err(EXIT_FAILURE, "cannot open %s", kname); + if (fstat(kfd, &st) == -1) + err(EXIT_FAILURE, "cannot stat %s", kname); + base = mmap(0, (size_t)st.st_size, PROT_READ, MAP_FILE | MAP_SHARED, + kfd, 0); + if (base == MAP_FAILED) + err(EXIT_FAILURE, "cannot mmap %s", kname); + ptr = base; + + /* Scan mmap(2)'ed region, extracting kernel configuration */ + for (i = 0; i < st.st_size; i++) { + if ((*ptr == '_') && (st.st_size - i > 5) && memcmp(ptr, + "_CFG_", 5) == 0) { + /* Line found */ + char *oldptr, line[LINE_MAX + 1], uline[LINE_MAX + 1]; + int j; + + found = 1; + + oldptr = (ptr += 5); + while (*ptr != '\n' && *ptr != '\0') + ptr++; + if (ptr - oldptr > LINE_MAX) + errx(EXIT_FAILURE, "line too long"); + i += ptr - oldptr + 5; + (void)memcpy(line, oldptr, (size_t)(ptr - oldptr)); + line[ptr - oldptr] = '\0'; + j = strunvis(uline, line); + if (j == -1) + errx(EXIT_FAILURE, "unvis: invalid " + "encoded sequence"); + uline[j] = '\n'; + if (write(cfd, uline, (size_t)j + 1) == -1) + err(EXIT_FAILURE, "cannot write to %s", cname); + } else + ptr++; + } + + (void)close(kfd); + (void)munmap(base, (size_t)st.st_size); + + return found; +} + +struct dhdi_params { + struct devbase *d; + int unit; + int level; +}; + +static int +devbase_has_dead_instances(const char *key, void *value, void *aux) +{ + struct devi *i; + struct dhdi_params *dhdi = aux; + + for (i = value; i != NULL; i = i->i_alias) + if (i->i_base == dhdi->d && + (dhdi->unit == WILD || dhdi->unit == i->i_unit || + i->i_unit == STAR) && + i->i_level >= dhdi->level) + return 1; + return 0; +} + +/* + * This is almost the same as devbase_has_instances, except it + * may have special considerations regarding ignored instances. + */ + +static int +devbase_has_any_instance(struct devbase *dev, int unit, int state, int level) +{ + struct deva *da; + struct devi *i; + + if (dev->d_ispseudo) { + if (dev->d_ihead != NULL) + return 1; + else if (state != DEVI_IGNORED) + return 0; + if ((i = ht_lookup(deaddevitab, dev->d_name)) == NULL) + return 0; + return (i->i_level >= level); + } + + for (da = dev->d_ahead; da != NULL; da = da->d_bsame) + for (i = da->d_ihead; i != NULL; i = i->i_asame) + if ((i->i_active == DEVI_ACTIVE || + i->i_active == state) && + (unit == WILD || unit == i->i_unit || + i->i_unit == STAR)) + return 1; + + if (state == DEVI_IGNORED) { + struct dhdi_params dhdi = { dev, unit, level }; + /* also check dead devices */ + return ht_enumerate(deaddevitab, devbase_has_dead_instances, + &dhdi); + } + + return 0; +} + +/* + * check_dead_devi(), used with ht_enumerate, checks if any of the removed + * device instances would have been a valid instance considering the devbase, + * the parent device and the interface attribute. + * + * In other words, for a non-active device, it checks if children would be + * actual orphans or the result of a negative statement in the config file. + */ + +struct cdd_params { + struct devbase *d; + struct attr *at; + struct devbase *parent; +}; + +static int +check_dead_devi(const char *key, void *value, void *aux) +{ + struct cdd_params *cdd = aux; + struct devi *i = value; + struct pspec *p; + + if (i->i_base != cdd->d) + return 0; + + for (; i != NULL; i = i->i_alias) { + p = i->i_pspec; + if ((p == NULL && cdd->at == NULL) || + (p != NULL && p->p_iattr == cdd->at && + (p->p_atdev == NULL || p->p_atdev == cdd->parent))) { + if (p != NULL && + !devbase_has_any_instance(cdd->parent, p->p_atunit, + DEVI_IGNORED, i->i_level)) + return 0; + else + return 1; + } + } + return 0; +} + +static void +do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent, + int state) +{ + struct nvlist *nv1; + struct attrlist *al; + struct attr *a; + struct devi *i, *j = NULL; + struct pspec *p; + int active = 0; + + /* + * A pseudo-device will always attach at root, and if it has an + * instance (it cannot have more than one), it is enough to consider + * it active, as there is no real attachment. + * + * A pseudo device can never be marked DEVI_IGNORED. + */ + if (d->d_ispseudo) { + if (d->d_ihead != NULL) + d->d_ihead->i_active = active = DEVI_ACTIVE; + else { + if (ht_lookup(deaddevitab, d->d_name) != NULL) + active = DEVI_IGNORED; + else + return; + } + } else { + int seen = 0; + + for (i = d->d_ihead; i != NULL; i = i->i_bsame) { + for (j = i; j != NULL; j = j->i_alias) { + p = j->i_pspec; + if ((p == NULL && at == NULL) || + (p != NULL && p->p_iattr == at && + (p->p_atdev == NULL || + p->p_atdev == parent))) { + if (p != NULL && + !devbase_has_any_instance(parent, + p->p_atunit, state, j->i_level)) + continue; + /* + * There are Fry-like devices which can + * be their own grand-parent (or even + * parent, like uhub). We don't want + * to loop, so if we've already reached + * an instance for one reason or + * another, stop there. + */ + if (j->i_active == DEVI_ACTIVE || + j->i_active == state) { + /* + * Device has already been + * seen. However it might + * have siblings who still + * have to be activated or + * orphaned. + */ + seen = 1; + continue; + } + j->i_active = active = state; + if (p != NULL) + p->p_active = state; + } + } + } + /* + * If we've been there but have made no change, stop. + */ + if (seen && !active) + return; + if (!active) { + struct cdd_params cdd = { d, at, parent }; + /* Look for a matching dead devi */ + if (ht_enumerate(deaddevitab, check_dead_devi, &cdd) && + d != parent) + /* + * That device had its instances removed. + * Continue the loop marking descendants + * with DEVI_IGNORED instead of DEVI_ACTIVE. + * + * There is one special case for devices that + * are their own parent: if that instance is + * removed (e.g., no uhub* at uhub?), we don't + * have to continue looping. + */ + active = DEVI_IGNORED; + else + return; + } + } + + for (al = d->d_attrs; al != NULL; al = al->al_next) { + a = al->al_this; + for (nv1 = a->a_devs; nv1 != NULL; nv1 = nv1->nv_next) + do_kill_orphans(nv1->nv_ptr, a, d, active); + } +} + +static int +/*ARGSUSED*/ +kill_orphans_cb(const char *key, void *value, void *aux) +{ + do_kill_orphans((struct devbase *)value, NULL, NULL, DEVI_ACTIVE); + return 0; +} + +static void +kill_orphans(void) +{ + ht_enumerate(devroottab, kill_orphans_cb, NULL); +} + +static void +add_makeopt(const char *opt) +{ + struct nvlist *p; + char *buf = estrdup(opt); + char *eq = strchr(buf, '='); + + if (!eq) + errx(EXIT_FAILURE, "-D %s is not in var=value format", opt); + + *eq = 0; + p = newnv(estrdup(buf), estrdup(eq+1), NULL, 0, NULL); + free(buf); + p->nv_next = cmdlinedefs; + cmdlinedefs = p; +} + +static void +remove_makeopt(const char *opt) +{ + struct nvlist *p; + + p = newnv(estrdup(opt), NULL, NULL, 0, NULL); + p->nv_next = cmdlineundefs; + cmdlineundefs = p; +} + +static void +handle_cmdline_makeoptions(void) +{ + struct nvlist *p, *n; + + handling_cmdlineopts = 1; + for (p = cmdlineundefs; p; p = n) { + n = p->nv_next; + delmkoption(intern(p->nv_name)); + free(__UNCONST(p->nv_name)); + nvfree(p); + } + for (p = cmdlinedefs; p; p = n) { + const char *name = intern(p->nv_name); + + n = p->nv_next; + delmkoption(name); + addmkoption(name, intern(p->nv_str)); + free(__UNCONST(p->nv_name)); + free(__UNCONST(p->nv_str)); + + nvfree(p); + } + handling_cmdlineopts = 0; +} diff --git a/usr.bin/config/mkdevsw.c b/usr.bin/config/mkdevsw.c new file mode 100644 index 000000000..66c8ac7d8 --- /dev/null +++ b/usr.bin/config/mkdevsw.c @@ -0,0 +1,241 @@ +/* $NetBSD: mkdevsw.c,v 1.14 2015/09/03 13:53:36 uebayasi Exp $ */ + +/* + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by MAEKAWA Masahide (gehenna@NetBSD.org). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: mkdevsw.c,v 1.14 2015/09/03 13:53:36 uebayasi Exp $"); + +#include +#include +#include +#include + +#include "defs.h" + +static void emitconv(FILE *); +static void emitdev(FILE *); +static void emitdevm(FILE *); +static void emitheader(FILE *); + +int +mkdevsw(void) +{ + FILE *fp; + + if ((fp = fopen("devsw.c.tmp", "w")) == NULL) { + warn("cannot create devsw.c"); + return (1); + } + + emitheader(fp); + emitdevm(fp); + emitconv(fp); + emitdev(fp); + + fflush(fp); + if (ferror(fp)) { + warn("error writing devsw.c"); + fclose(fp); + return 1; + } + + (void)fclose(fp); + + if (moveifchanged("devsw.c.tmp", "devsw.c") != 0) { + warn("error renaming devsw.c"); + return (1); + } + + return (0); +} + +static void +emitheader(FILE *fp) +{ + autogen_comment(fp, "devsw.c"); + + fputs("#include \n" + "#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) +{ + devmajor_t i; + + fputs("\n/* device switch table for block device */\n", fp); + + for (i = 0; i <= maxbdevm ; i++) + dentry(fp, cdevmtab, i, 'b'); + + fputs("\nconst struct bdevsw *bdevsw0[] = {\n", fp); + + for (i = 0; i <= maxbdevm; i++) + pentry(fp, bdevmtab, i, 'b'); + + fputs("};\n\nconst struct bdevsw **bdevsw = bdevsw0;\n", fp); + + fputs("const int sys_bdevsws = __arraycount(bdevsw0);\n" + "int max_bdevsws = __arraycount(bdevsw0);\n", fp); + + fputs("\n/* device switch table for character device */\n", fp); + + for (i = 0; i <= maxcdevm; i++) + dentry(fp, cdevmtab, i, 'c'); + + fputs("\nconst struct cdevsw *cdevsw0[] = {\n", fp); + + for (i = 0; i <= maxcdevm; i++) + pentry(fp, cdevmtab, i, 'c'); + + fputs("};\n\nconst struct cdevsw **cdevsw = cdevsw0;\n", fp); + + fputs("const int sys_cdevsws = __arraycount(cdevsw0);\n" + "int max_cdevsws = __arraycount(cdevsw0);\n", fp); +} + +/* + * Emit device major conversion table. + */ +static void +emitconv(FILE *fp) +{ + struct devm *dm; + + fputs("\n/* device conversion table */\n" + "struct devsw_conv devsw_conv0[] = {\n", fp); + TAILQ_FOREACH(dm, &alldevms, dm_next) { + if (version < 20100430) { + /* Emit compatible structure */ + fprintf(fp, "\t{ \"%s\", %d, %d },\n", dm->dm_name, + dm->dm_bmajor, dm->dm_cmajor); + continue; + } + struct nvlist *nv; + const char *d_class, *d_flags = "0"; + int d_vec[2] = { 0, 0 }; + int i = 0; + + /* + * "parse" info. currently the rules are simple: + * 1) first entry defines class + * 2) next ones without n_str are d_vectdim + * 3) next one with n_str is d_flags + * 4) EOL + */ + nv = dm->dm_devnodes; + d_class = nv->nv_str; + while ((nv = nv->nv_next) != NULL) { + if (i > 2) + panic("invalid devnode definition"); + if (nv->nv_str) { + d_flags = nv->nv_str; + break; + } + 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", + dm->dm_name, dm->dm_bmajor, dm->dm_cmajor, + d_class, d_flags, d_vec[0], d_vec[1]); + + } + fputs("};\n\n" + "struct devsw_conv *devsw_conv = devsw_conv0;\n" + "int max_devsw_convs = __arraycount(devsw_conv0);\n", + fp); +} + +/* + * Emit specific device major informations. + */ +static void +emitdev(FILE *fp) +{ + struct devm *dm; + char mstr[16]; + + fputs("\n", fp); + + (void)strlcpy(mstr, "swap", sizeof(mstr)); + if ((dm = ht_lookup(bdevmtab, intern(mstr))) != NULL) { + fprintf(fp, "const dev_t swapdev = makedev(%d, 0);\n", + dm->dm_bmajor); + } + + (void)strlcpy(mstr, "mem", sizeof(mstr)); + if ((dm = ht_lookup(cdevmtab, intern(mstr))) == NULL) + panic("memory device is not configured"); + fprintf(fp, "const dev_t zerodev = makedev(%d, DEV_ZERO);\n", + dm->dm_cmajor); + + fputs("\n/* mem_no is only used in iskmemdev() */\n", fp); + fprintf(fp, "const int mem_no = %d;\n", dm->dm_cmajor); +} diff --git a/usr.bin/config/mkheaders.c b/usr.bin/config/mkheaders.c new file mode 100644 index 000000000..bf250188f --- /dev/null +++ b/usr.bin/config/mkheaders.c @@ -0,0 +1,547 @@ +/* $NetBSD: mkheaders.c,v 1.29 2015/09/03 13:53:36 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)mkheaders.c 8.1 (Berkeley) 6/6/93 + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: mkheaders.c,v 1.29 2015/09/03 13:53:36 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" + +#include + +static int emitcnt(struct nvlist *); +static int emitopts(void); +static int emittime(void); +static int herr(const char *, const char *, FILE *); +static int defopts_print(const char *, struct defoptlist *, void *); +static char *cntname(const char *); + +/* + * We define a global symbol with the name of each option and its value. + * This should stop code compiled with different options being linked together. + */ + +/* Unlikely constant for undefined options */ +#define UNDEFINED ('n' << 24 | 0 << 20 | 't' << 12 | 0xdefU) +/* Value for defined options with value UNDEFINED */ +#define DEFINED (0xdef1U << 16 | 'n' << 8 | 0xed) + +/* + * Make the various config-generated header files. + */ +int +mkheaders(void) +{ + struct files *fi; + + /* + * Make headers containing counts, as needed. + */ + TAILQ_FOREACH(fi, &allfiles, fi_next) { + if (fi->fi_flags & FI_HIDDEN) + continue; + if (fi->fi_flags & (FI_NEEDSCOUNT | FI_NEEDSFLAG) && + emitcnt(fi->fi_optf)) + return (1); + } + + if (emitopts() || emitlocs() || emitioconfh()) + return (1); + + /* + * If the minimum required version is ever bumped beyond 20090513, + * emittime() can be removed. + */ + if (version <= 20090513 && emittime()) + return (1); + + return (0); +} + +static void +fprint_global(FILE *fp, const char *name, long long value) +{ + /* + * We have to doubt the founding fathers here. + * The gas syntax for hppa is 'var .equ value', for all? other + * instruction sets it is ' .equ var,value'. both have been used in + * various assemblers, but supporting a common syntax would be good. + * Fortunately we can use .equiv since it has a consistent syntax, + * but requires us to detect multiple assignments - event with the + * same value. + */ + fprintf(fp, "#ifdef _LOCORE\n" + " .ifndef _KERNEL_OPT_%s\n" + " .global _KERNEL_OPT_%s\n" + " .equiv _KERNEL_OPT_%s,0x%llx\n" + " .endif\n" + "#else\n" + "__asm(\" .ifndef _KERNEL_OPT_%s\\n" + " .global _KERNEL_OPT_%s\\n" + " .equiv _KERNEL_OPT_%s,0x%llx\\n" + " .endif\");\n" + "#endif\n", + name, name, name, value, + name, name, name, value); +} + +/* Convert the option argument to a 32bit numder */ +static unsigned int +global_hash(const char *str) +{ + unsigned long h; + char *ep; + + /* + * 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 */ + h = crc_buf(0, str, strlen(str)); + + /* Avoid colliding with the value used for undefined options. */ + /* At least until I stop any options being set to zero */ + return (unsigned int)(h != UNDEFINED ? h : DEFINED); +} + +static void +fprintcnt(FILE *fp, struct nvlist *nv) +{ + const char *name = cntname(nv->nv_name); + + fprintf(fp, "#define\t%s\t%lld\n", name, nv->nv_num); + fprint_global(fp, name, nv->nv_num); +} + +static int +emitcnt(struct nvlist *head) +{ + char nfname[BUFSIZ], tfname[BUFSIZ]; + struct nvlist *nv; + FILE *fp; + + (void)snprintf(nfname, sizeof(nfname), "%s.h", head->nv_name); + (void)snprintf(tfname, sizeof(tfname), "tmp_%s", nfname); + + if ((fp = fopen(tfname, "w")) == NULL) + return (herr("open", tfname, NULL)); + + for (nv = head; nv != NULL; nv = nv->nv_next) + fprintcnt(fp, nv); + + fflush(fp); + if (ferror(fp)) + return herr("writ", tfname, fp); + + if (fclose(fp) == EOF) + return (herr("clos", tfname, NULL)); + + return (moveifchanged(tfname, nfname)); +} + +/* + * Output a string, preceded by a tab and possibly unescaping any quotes. + * The argument will be output as is if it doesn't start with \". + * Otherwise the first backslash in a \? sequence will be dropped. + */ +static void +fprintstr(FILE *fp, const char *str) +{ + + if (strncmp(str, "\\\"", 2) != 0) { + (void)fprintf(fp, "\t%s", str); + return; + } + + (void)fputc('\t', fp); + + for (; *str; str++) { + switch (*str) { + case '\\': + if (!*++str) /* XXX */ + str--; + /*FALLTHROUGH*/ + default: + (void)fputc(*str, fp); + break; + } + } +} + +/* + * Callback function for walking the option file hash table. We write out + * the options defined for this file. + */ +static int +/*ARGSUSED*/ +defopts_print(const char *name, struct defoptlist *value, void *arg) +{ + char tfname[BUFSIZ]; + struct nvlist *option; + struct defoptlist *dl; + const char *opt_value; + int isfsoption; + FILE *fp; + + (void)snprintf(tfname, sizeof(tfname), "tmp_%s", name); + if ((fp = fopen(tfname, "w")) == NULL) + return (herr("open", tfname, NULL)); + + for (dl = value; dl != NULL; dl = dl->dl_next) { + isfsoption = OPT_FSOPT(dl->dl_name); + + if (dl->dl_obsolete) { + fprintf(fp, "/* %s `%s' is obsolete */\n", + isfsoption ? "file system" : "option", + dl->dl_name); + fprint_global(fp, dl->dl_name, 0xdeadbeef); + continue; + } + + if (((option = ht_lookup(opttab, dl->dl_name)) == NULL && + (option = ht_lookup(fsopttab, dl->dl_name)) == NULL) && + (dl->dl_value == NULL)) { + fprintf(fp, "/* %s `%s' not defined */\n", + isfsoption ? "file system" : "option", + dl->dl_name); + fprint_global(fp, dl->dl_name, UNDEFINED); + continue; + } + + opt_value = option != NULL ? option->nv_str : dl->dl_value; + if (isfsoption == 1) + /* For filesysteme we'd output the lower case name */ + opt_value = NULL; + + fprintf(fp, "#define\t%s", dl->dl_name); + if (opt_value != NULL) + fprintstr(fp, opt_value); + else if (!isfsoption) + fprintstr(fp, "1"); + fputc('\n', fp); + fprint_global(fp, dl->dl_name, + opt_value == NULL ? 1 : global_hash(opt_value)); + } + + fflush(fp); + if (ferror(fp)) + return herr("writ", tfname, fp); + + if (fclose(fp) == EOF) + return (herr("clos", tfname, NULL)); + + return (moveifchanged(tfname, name)); +} + +/* + * Emit the option header files. + */ +static int +emitopts(void) +{ + + return (dlhash_enumerate(optfiletab, defopts_print, NULL)); +} + +/* + * A callback function for walking the attribute hash table. + * Emit CPP definitions of manifest constants for the locators on the + * "name" attribute node (passed as the "value" parameter). + */ +static int +locators_print(const char *name, void *value, void *arg) +{ + struct attr *a; + struct loclist *ll; + int i; + char *locdup, *namedup; + char *cp; + FILE *fp = arg; + + a = value; + if (a->a_locs) { + if (strchr(name, ' ') != NULL || strchr(name, '\t') != NULL) + /* + * name contains a space; we can't generate + * usable defines, so ignore it. + */ + return 0; + locdup = estrdup(name); + for (cp = locdup; *cp; cp++) + if (islower((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) + /* + * name contains a space; we can't generate + * usable defines, so ignore it. + */ + continue; + namedup = estrdup(ll->ll_name); + for (cp = namedup; *cp; cp++) + if (islower((unsigned char)*cp)) + *cp = (char)toupper((unsigned char)*cp); + else if (*cp == ARRCHR) + *cp = '_'; + fprintf(fp, "#define %sCF_%s %d\n", locdup, namedup, i); + if (ll->ll_string != NULL) + fprintf(fp, "#define %sCF_%s_DEFAULT %s\n", + locdup, namedup, ll->ll_string); + free(namedup); + } + /* assert(i == a->a_loclen) */ + fprintf(fp, "#define %sCF_NLOCS %d\n", locdup, a->a_loclen); + free(locdup); + } + return 0; +} + +/* + * Build the "locators.h" file with manifest constants for all potential + * locators in the configuration. Do this by enumerating the attribute + * hash table and emitting all the locators for each attribute. + */ +int +emitlocs(void) +{ + const char *tfname; + int rval; + FILE *tfp; + + tfname = "tmp_locators.h"; + if ((tfp = fopen(tfname, "w")) == NULL) + return (herr("open", tfname, NULL)); + + rval = ht_enumerate(attrtab, locators_print, tfp); + + fflush(tfp); + if (ferror(tfp)) + return (herr("writ", tfname, NULL)); + if (fclose(tfp) == EOF) + return (herr("clos", tfname, NULL)); + if (rval) + return (rval); + return (moveifchanged(tfname, "locators.h")); +} + +/* + * Build the "ioconf.h" file with extern declarations for all configured + * cfdrivers. + */ +int +emitioconfh(void) +{ + const char *tfname; + FILE *tfp; + struct devbase *d; + struct devi *i; + + tfname = "tmp_ioconf.h"; + if ((tfp = fopen(tfname, "w")) == NULL) + return (herr("open", tfname, NULL)); + + fputs("\n/* pseudo-devices */\n", tfp); + TAILQ_FOREACH(i, &allpseudo, i_next) { + fprintf(tfp, "void %sattach(int);\n", + i->i_base->d_name); + } + + fputs("\n/* driver structs */\n", tfp); + TAILQ_FOREACH(d, &allbases, d_next) { + if (!devbase_has_instances(d, WILD)) + continue; + fprintf(tfp, "extern struct cfdriver %s_cd;\n", d->d_name); + } + + fflush(tfp); + if (ferror(tfp)) + return herr("writ", tfname, tfp); + + if (fclose(tfp) == EOF) + return (herr("clos", tfname, NULL)); + + return (moveifchanged(tfname, "ioconf.h")); +} + +/* + * Make a file that config_time.h can use as a source, if required. + */ +static int +emittime(void) +{ + FILE *fp; + time_t t; + struct tm *tm; + char buf[128]; + + t = time(NULL); + tm = gmtime(&t); + + if ((fp = fopen("config_time.src", "w")) == NULL) + return (herr("open", "config_time.src", NULL)); + + if (strftime(buf, sizeof(buf), "%c %Z", tm) == 0) + return (herr("strftime", "config_time.src", fp)); + + fprintf(fp, "/* %s */\n" + "#define CONFIG_TIME\t%2lld\n" + "#define CONFIG_YEAR\t%2d\n" + "#define CONFIG_MONTH\t%2d\n" + "#define CONFIG_DATE\t%2d\n" + "#define CONFIG_HOUR\t%2d\n" + "#define CONFIG_MINS\t%2d\n" + "#define CONFIG_SECS\t%2d\n", + buf, (long long)t, + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + fflush(fp); + if (ferror(fp)) + return (herr("fprintf", "config_time.src", fp)); + + if (fclose(fp) != 0) + return (herr("clos", "config_time.src", NULL)); + + /* + * *Don't* moveifchanged this file. Makefile.kern.inc will + * handle that if it determines such a move is necessary. + */ + return (0); +} + +/* + * Compare two files. If nfname doesn't exist, or is different from + * tfname, move tfname to nfname. Otherwise, delete tfname. + */ +int +moveifchanged(const char *tfname, const char *nfname) +{ + char tbuf[BUFSIZ], nbuf[BUFSIZ]; + FILE *tfp, *nfp; + + if ((tfp = fopen(tfname, "r")) == NULL) + return (herr("open", tfname, NULL)); + + if ((nfp = fopen(nfname, "r")) == NULL) + goto moveit; + + while (fgets(tbuf, sizeof(tbuf), tfp) != NULL) { + if (fgets(nbuf, sizeof(nbuf), nfp) == NULL) { + /* + * Old file has fewer lines. + */ + goto moveit; + } + if (strcmp(tbuf, nbuf) != 0) + goto moveit; + } + + /* + * We've reached the end of the new file. Check to see if new file + * has fewer lines than old. + */ + if (fgets(nbuf, sizeof(nbuf), nfp) != NULL) { + /* + * New file has fewer lines. + */ + goto moveit; + } + + (void) fclose(nfp); + (void) fclose(tfp); + if (remove(tfname) == -1) + return(herr("remov", tfname, NULL)); + return (0); + + moveit: + /* + * They're different, or the file doesn't exist. + */ + if (nfp) + (void) fclose(nfp); + if (tfp) + (void) fclose(tfp); + if (rename(tfname, nfname) == -1) + return (herr("renam", tfname, NULL)); + return (0); +} + +static int +herr(const char *what, const char *fname, FILE *fp) +{ + + warn("error %sing %s", what, fname); + if (fp) + (void)fclose(fp); + return (1); +} + +static char * +cntname(const char *src) +{ + char *dst; + char c; + static char buf[100]; + + dst = buf; + *dst++ = 'N'; + while ((c = *src++) != 0) + *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 new file mode 100644 index 000000000..88333a34f --- /dev/null +++ b/usr.bin/config/mkioconf.c @@ -0,0 +1,510 @@ +/* $NetBSD: mkioconf.c,v 1.32 2015/09/03 13:53:36 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)mkioconf.c 8.1 (Berkeley) 6/6/93 + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: mkioconf.c,v 1.32 2015/09/03 13:53:36 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include "defs.h" + +/* + * Make ioconf.c. + */ +static int cf_locators_print(const char *, void *, void *); +static int cforder(const void *, const void *); +static void emitcfdata(FILE *); +static void emitcfdrivers(FILE *); +static void emitexterns(FILE *); +static void emitcfattachinit(FILE *); +static void emithdr(FILE *); +static void emitloc(FILE *); +static void emitpseudo(FILE *); +static void emitparents(FILE *); +static void emitroots(FILE *); +static void emitname2blk(FILE *); + +#define SEP(pos, max) (((u_int)(pos) % (max)) == 0 ? "\n\t" : " ") + +#define ARRNAME(n, l) (strchr((n), ARRCHR) && strncmp((n), (l), strlen((l))) == 0) + +/* + * NEWLINE can only be used in the emitXXX functions. + * In most cases it can be subsumed into an fprintf. + */ +#define NEWLINE putc('\n', fp) + +int +mkioconf(void) +{ + FILE *fp; + + qsort(packed, npacked, sizeof *packed, cforder); + if ((fp = fopen("ioconf.c.tmp", "w")) == NULL) { + warn("cannot write ioconf.c"); + return (1); + } + + fprintf(fp, "#include \"ioconf.h\"\n"); + + emithdr(fp); + emitcfdrivers(fp); + emitexterns(fp); + emitloc(fp); + emitparents(fp); + emitcfdata(fp); + emitcfattachinit(fp); + + if (ioconfname == NULL) { + emitroots(fp); + emitpseudo(fp); + if (!do_devsw) + emitname2blk(fp); + } + + fflush(fp); + if (ferror(fp)) { + warn("error writing ioconf.c"); + (void)fclose(fp); +#if 0 + (void)unlink("ioconf.c.tmp"); +#endif + return (1); + } + + (void)fclose(fp); + if (moveifchanged("ioconf.c.tmp", "ioconf.c") != 0) { + warn("error renaming ioconf.c"); + return (1); + } + return (0); +} + +static int +cforder(const void *a, const void *b) +{ + int n1, n2; + + n1 = (*(const struct devi * const *)a)->i_cfindex; + n2 = (*(const struct devi * const *)b)->i_cfindex; + return (n1 - n2); +} + +static void +emithdr(FILE *ofp) +{ + FILE *ifp; + size_t n; + char ifnbuf[200], buf[BUFSIZ]; + char *ifn; + + autogen_comment(ofp, "ioconf.c"); + + (void)snprintf(ifnbuf, sizeof(ifnbuf), "%s/arch/%s/conf/ioconf.incl.%s", + srcdir, + machine ? machine : "(null)", machine ? machine : "(null)"); + ifn = ifnbuf; + if ((ifp = fopen(ifn, "r")) != NULL) { + while ((n = fread(buf, 1, sizeof(buf), ifp)) > 0) + (void)fwrite(buf, 1, n, ofp); + if (ferror(ifp)) + err(EXIT_FAILURE, "error reading %s", ifn); + (void)fclose(ifp); + } else { + fputs("#include \n" + "#include \n" + "#include \n" + "#include \n", ofp); + } +} + +/* + * Emit an initialized array of character strings describing this + * attribute's locators. + */ +static int +cf_locators_print(const char *name, void *value, void *arg) +{ + struct attr *a; + struct loclist *ll; + FILE *fp = 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", 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, + (ll->ll_string ? ll->ll_string : "NULL"), + (ll->ll_string ? ll->ll_string : "0")); + fprintf(fp, "\t}\n};\n"); + } else { + fprintf(fp, + "static const struct cfiattrdata %scf_iattrdata = {\n" + "\t\"%s\", 0, {\n\t\t{ NULL, NULL, 0 },\n\t}\n};\n", + name, name); + } + + return 0; +} + +static void +emitcfdrivers(FILE *fp) +{ + struct devbase *d; + struct attrlist *al; + struct attr *a; + int has_iattrs; + + NEWLINE; + ht_enumerate(attrtab, cf_locators_print, fp); + + NEWLINE; + TAILQ_FOREACH(d, &allbases, d_next) { + if (!devbase_has_instances(d, WILD)) + continue; + has_iattrs = 0; + for (al = d->d_attrs; al != NULL; al = al->al_next) { + a = al->al_this; + if (a->a_iattr == 0) + continue; + if (has_iattrs == 0) + fprintf(fp, + "static const struct cfiattrdata * const %s_attrs[] = { ", + d->d_name); + has_iattrs = 1; + fprintf(fp, "&%scf_iattrdata, ", a->a_name); + } + if (has_iattrs) + fprintf(fp, "NULL };\n"); + fprintf(fp, "CFDRIVER_DECL(%s, %s, ", d->d_name, /* ) */ + d->d_classattr != NULL ? d->d_classattr->a_devclass + : "DV_DULL"); + if (has_iattrs) + fprintf(fp, "%s_attrs", d->d_name); + else + fprintf(fp, "NULL"); + fprintf(fp, /* ( */ ");\n\n"); + } + + NEWLINE; + + fprintf(fp, + "%sstruct cfdriver * const cfdriver_%s_%s[] = {\n", + ioconfname ? "static " : "", + ioconfname ? "ioconf" : "list", + ioconfname ? ioconfname : "initial"); + + TAILQ_FOREACH(d, &allbases, d_next) { + if (!devbase_has_instances(d, WILD)) + continue; + fprintf(fp, "\t&%s_cd,\n", d->d_name); + } + fprintf(fp, "\tNULL\n};\n"); +} + +static void +emitexterns(FILE *fp) +{ + struct deva *da; + + NEWLINE; + TAILQ_FOREACH(da, &alldevas, d_next) { + if (!deva_has_instances(da, WILD)) + continue; + fprintf(fp, "extern struct cfattach %s_ca;\n", + da->d_name); + } +} + +static void +emitcfattachinit(FILE *fp) +{ + struct devbase *d; + struct deva *da; + + NEWLINE; + TAILQ_FOREACH(d, &allbases, d_next) { + if (!devbase_has_instances(d, WILD)) + continue; + if (d->d_ahead == NULL) + continue; + + fprintf(fp, + "static struct cfattach * const %s_cfattachinit[] = {\n\t", + d->d_name); + for (da = d->d_ahead; da != NULL; da = da->d_bsame) { + if (!deva_has_instances(da, WILD)) + continue; + fprintf(fp, "&%s_ca, ", da->d_name); + } + fprintf(fp, "NULL\n};\n"); + } + + NEWLINE; + fprintf(fp, "%sconst struct cfattachinit cfattach%s%s[] = {\n", + ioconfname ? "static " : "", + ioconfname ? "_ioconf_" : "init", + ioconfname ? ioconfname : ""); + + TAILQ_FOREACH(d, &allbases, d_next) { + if (!devbase_has_instances(d, WILD)) + continue; + if (d->d_ahead == NULL) + continue; + + fprintf(fp, "\t{ \"%s\", %s_cfattachinit },\n", + d->d_name, d->d_name); + } + + fprintf(fp, "\t{ NULL, NULL }\n};\n"); +} + +static void +emitloc(FILE *fp) +{ + int i; + + if (locators.used != 0) { + fprintf(fp, "\n/* locators */\n" + "static int loc[%d] = {", locators.used); + for (i = 0; i < locators.used; i++) + fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]); + fprintf(fp, "\n};\n"); + } +} + +/* + * Emit static parent data. + */ +static void +emitparents(FILE *fp) +{ + struct pspec *p; + + NEWLINE; + TAILQ_FOREACH(p, &allpspecs, p_list) { + if (p->p_devs == NULL || p->p_active != DEVI_ACTIVE) + continue; + fprintf(fp, + "static const struct cfparent pspec%d = {\n", p->p_inst); + fprintf(fp, "\t\"%s\", ", p->p_iattr->a_name); + if (p->p_atdev != NULL) { + fprintf(fp, "\"%s\", ", p->p_atdev->d_name); + if (p->p_atunit == WILD) + fprintf(fp, "DVUNIT_ANY"); + else + fprintf(fp, "%d", p->p_atunit); + } else + fprintf(fp, "NULL, 0"); + fprintf(fp, "\n};\n"); + } +} + +/* + * Emit the cfdata array. + */ +static void +emitcfdata(FILE *fp) +{ + struct devi **p, *i; + struct pspec *ps; + int unit, v; + const char *state, *basename, *attachment; + struct loclist *ll; + struct attr *a; + const char *loc; + char locbuf[20]; + const char *lastname = ""; + + fprintf(fp, "\n" + "#define NORM FSTATE_NOTFOUND\n" + "#define STAR FSTATE_STAR\n" + "\n" + "%sstruct cfdata cfdata%s%s[] = {\n" + " /* driver attachment unit state " + " loc flags pspec */\n", + ioconfname ? "static " : "", + ioconfname ? "_ioconf_" : "", + ioconfname ? ioconfname : ""); + for (p = packed; (i = *p) != NULL; p++) { + /* the description */ + fprintf(fp, "/*%3d: %s at ", i->i_cfindex, i->i_name); + if ((ps = i->i_pspec) != NULL) { + if (ps->p_atdev != NULL && + ps->p_atunit != WILD) { + fprintf(fp, "%s%d", ps->p_atdev->d_name, + ps->p_atunit); + } else if (ps->p_atdev != NULL) { + fprintf(fp, "%s?", ps->p_atdev->d_name); + } else { + fprintf(fp, "%s?", ps->p_iattr->a_name); + } + + a = ps->p_iattr; + for (ll = a->a_locs, v = 0; ll != NULL; + ll = ll->ll_next, v++) { + if (ARRNAME(ll->ll_name, lastname)) { + fprintf(fp, " %s %s", + ll->ll_name, i->i_locs[v]); + } else { + fprintf(fp, " %s %s", + ll->ll_name, + i->i_locs[v]); + lastname = ll->ll_name; + } + } + } else { + a = NULL; + fputs("root", fp); + } + + fputs(" */\n", fp); + + /* then the actual defining line */ + basename = i->i_base->d_name; + attachment = i->i_atdeva->d_name; + if (i->i_unit == STAR) { + unit = i->i_base->d_umax; + state = "STAR"; + } else { + unit = i->i_unit; + state = "NORM"; + } + if (i->i_locoff >= 0) { + (void)snprintf(locbuf, sizeof(locbuf), "loc+%3d", + i->i_locoff); + loc = locbuf; + } else + loc = "NULL"; + fprintf(fp, " { \"%s\",%s\"%s\",%s%2d, %s, %7s, %#6x, ", + basename, strlen(basename) < 7 ? "\t\t" + : "\t", + attachment, strlen(attachment) < 5 ? "\t\t" + : "\t", + unit, state, loc, i->i_cfflags); + if (ps != NULL) + fprintf(fp, "&pspec%d },\n", ps->p_inst); + else + 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"); +} + +/* + * Emit the table of potential roots. + */ +static void +emitroots(FILE *fp) +{ + struct devi **p, *i; + + fputs("\nconst short cfroots[] = {\n", fp); + for (p = packed; (i = *p) != NULL; p++) { + if (i->i_at != NULL) + continue; + if (i->i_unit != 0 && + (i->i_unit != STAR || i->i_base->d_umax != 0)) + warnx("warning: `%s at root' is not unit 0", i->i_name); + fprintf(fp, "\t%2d /* %s */,\n", + i->i_cfindex, i->i_name); + } + fputs("\t-1\n};\n", fp); +} + +/* + * Emit pseudo-device initialization. + */ +static void +emitpseudo(FILE *fp) +{ + struct devi *i; + struct devbase *d; + + fputs("\n/* pseudo-devices */\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", + d->d_name, d->d_umax); + } + fputs("\t{ 0, 0 }\n};\n", fp); +} + +/* + * Emit name to major block number table. + */ +void +emitname2blk(FILE *fp) +{ + struct devbase *dev; + + fputs("\n/* device name to major block number */\n", fp); + + fprintf(fp, "struct devnametobdevmaj dev_name2blk[] = {\n"); + + TAILQ_FOREACH(dev, &allbases, d_next) { + if (dev->d_major == NODEVMAJOR) + continue; + + fprintf(fp, "\t{ \"%s\", %d },\n", + dev->d_name, dev->d_major); + } + fprintf(fp, "\t{ NULL, 0 }\n};\n"); +} diff --git a/usr.bin/config/mkmakefile.c b/usr.bin/config/mkmakefile.c new file mode 100644 index 000000000..d848ef15a --- /dev/null +++ b/usr.bin/config/mkmakefile.c @@ -0,0 +1,598 @@ +/* $NetBSD: mkmakefile.c,v 1.68 2015/09/04 10:16:35 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)mkmakefile.c 8.1 (Berkeley) 6/6/93 + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: mkmakefile.c,v 1.68 2015/09/04 10:16:35 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" +#include "sem.h" + +/* + * Make the Makefile. + */ + +static void emitdefs(FILE *); +static void emitallfiles(FILE *); + +static void emitofiles(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 *); +static void emitload(FILE *); +static void emitincludes(FILE *); +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) +{ + FILE *ifp, *ofp; + int lineno; + void (*fn)(FILE *); + char line[BUFSIZ], ifname[200]; + + /* + * 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(ifname, sizeof(ifname), "%s/conf/Makefile.kern.inc", + srcdir); + 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(ifname, sizeof(ifname), "%s/arch/%s/conf/Makefile.%s", + srcdir, machine, machine); + if ((ifp = fopen(ifname, "r")) == NULL) { + /* + * Try a makefile for the architecture second. + */ + (void)snprintf(ifname, sizeof(ifname), + "%s/arch/%s/conf/Makefile.%s", + srcdir, machinearch, machinearch); + ifp = fopen(ifname, "r"); + } + if (ifp == NULL) { + warn("cannot read %s", ifname); + goto bad2; + } + + if ((ofp = fopen("Makefile.tmp", "w")) == NULL) { + warn("cannot write Makefile"); + goto bad1; + } + + emitdefs(ofp); + + lineno = 0; + while (fgets(line, sizeof(line), ifp) != NULL) { + lineno++; + if ((version < 20090214 && line[0] != '%') || line[0] == '#') { + fputs(line, ofp); + continue; + } + if (strcmp(line, "%OBJS\n") == 0) + fn = Mflag ? emitkobjs : emitofiles; + else if (strcmp(line, "%CFILES\n") == 0) + fn = emitcfiles; + else if (strcmp(line, "%SFILES\n") == 0) + fn = emitsfiles; + else if (strcmp(line, "%RULES\n") == 0) + fn = emitrules; + else if (strcmp(line, "%LOAD\n") == 0) + fn = emitload; + else if (strcmp(line, "%INCLUDES\n") == 0) + fn = emitincludes; + else if (strcmp(line, "%MAKEOPTIONSAPPEND\n") == 0) + fn = emitappmkoptions; + else if (strncmp(line, "%VERSION ", sizeof("%VERSION ")-1) == 0) { + int newvers; + if (sscanf(line, "%%VERSION %d\n", &newvers) != 1) { + cfgxerror(ifname, lineno, "syntax error for " + "%%VERSION"); + } else + setversion(newvers); + continue; + } else { + if (version < 20090214) + cfgxerror(ifname, lineno, + "unknown %% construct ignored: %s", line); + else + emitsubs(ofp, line, ifname, lineno); + continue; + } + (*fn)(ofp); + } + + fflush(ofp); + if (ferror(ofp)) + goto wrerror; + + if (ferror(ifp)) { + warn("error reading %s (at line %d)", ifname, lineno); + goto bad; + } + + if (fclose(ofp)) { + ofp = NULL; + goto wrerror; + } + (void)fclose(ifp); + + if (moveifchanged("Makefile.tmp", "Makefile") != 0) { + warn("error renaming Makefile"); + goto bad2; + } + return (0); + + wrerror: + warn("error writing Makefile"); + bad: + if (ofp != NULL) + (void)fclose(ofp); + bad1: + (void)fclose(ifp); + /* (void)unlink("Makefile.tmp"); */ + bad2: + return (1); +} + +static void +emitsubs(FILE *fp, const char *line, const char *file, int lineno) +{ + char *nextpct; + const char *optname; + struct nvlist *option; + + while (*line != '\0') { + if (*line != '%') { + fputc(*line++, fp); + continue; + } + + line++; + nextpct = strchr(line, '%'); + if (nextpct == NULL) { + cfgxerror(file, lineno, "unbalanced %% or " + "unknown construct"); + return; + } + *nextpct = '\0'; + + if (*line == '\0') + fputc('%', fp); + else { + optname = intern(line); + if (!DEFINED_OPTION(optname)) { + cfgxerror(file, lineno, "unknown option %s", + optname); + return; + } + + if ((option = ht_lookup(opttab, optname)) == NULL) + option = ht_lookup(fsopttab, optname); + 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. + */ + } + + line = nextpct + 1; + } +} + +static void +emitdefs(FILE *fp) +{ + struct nvlist *nv; + + fprintf(fp, "KERNEL_BUILD=%s\n", conffile); + fputs("IDENT= \\\n", fp); + for (nv = options; nv != NULL; nv = nv->nv_next) { + + /* Skip any options output to a header file */ + if (DEFINED_OPTION(nv->nv_name)) + continue; + 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, "MACHINE=%s\n", machine); + + const char *subdir = ""; + if (*srcdir != '/' && *srcdir != '.') { + /* + * libkern and libcompat "Makefile.inc"s want relative S + * specification to begin with '.'. + */ + subdir = "./"; + } + fprintf(fp, "S=\t%s%s\n", subdir, srcdir); + if (Sflag) { + fprintf(fp, ".PATH: $S\n"); + fprintf(fp, "___USE_SUFFIX_RULES___=1\n"); + } + for (nv = mkoptions; nv != NULL; nv = nv->nv_next) + fprintf(fp, "%s=%s\n", nv->nv_name, nv->nv_str); +} + +static void +emitfile(FILE *fp, struct files *fi) +{ + const char *defprologue = "$S/"; + const char *prologue, *prefix, *sep; + + if (Sflag) + defprologue = ""; + prologue = prefix = sep = ""; + if (*fi->fi_path != '/') { + prologue = defprologue; + if (fi->fi_prefix != NULL) { + if (*fi->fi_prefix == '/') + prologue = ""; + prefix = fi->fi_prefix; + sep = "/"; + } + } + fprintf(fp, "%s%s%s%s", prologue, prefix, sep, fi->fi_path); +} + +static void +emitfilerel(FILE *fp, struct files *fi) +{ + const char *prefix, *sep; + + prefix = sep = ""; + if (*fi->fi_path != '/') { + if (fi->fi_prefix != NULL) { + prefix = fi->fi_prefix; + sep = "/"; + } + } + fprintf(fp, "%s%s%s", prefix, sep, fi->fi_path); +} + +static void +emitofiles(FILE *fp) +{ + + emitallfiles(fp); + fprintf(fp, "#%%OFILES\n"); +} + +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) +{ + + emitallfiles(fp); + fprintf(fp, "#%%CFILES\n"); +} + +static void +emitsfiles(FILE *fp) +{ + + emitallfiles(fp); + fprintf(fp, "#%%SFILES\n"); +} + +static void +emitallfiles(FILE *fp) +{ + struct files *fi; + static int called; + int i; + int found = 0; + + if (called++ != 0) + return; + for (i = 0; i < (int)nselfiles; i++) { + fi = selfiles[i]; + if (found++ == 0) + fprintf(fp, "ALLFILES= \\\n"); + putc('\t', fp); + emitfilerel(fp, fi); + fputs(" \\\n", fp); + } + fputc('\n', fp); +} + +/* + * Emit the make-rules. + */ +static void +emitrules(FILE *fp) +{ + struct files *fi; + int i; + int found = 0; + + for (i = 0; i < (int)nselfiles; i++) { + fi = selfiles[i]; + if (fi->fi_mkrule == NULL) + continue; + fprintf(fp, "%s.o: ", fi->fi_base); + emitfile(fp, fi); + putc('\n', fp); + fprintf(fp, "\t%s\n\n", fi->fi_mkrule); + found++; + } + if (found == 0) + fprintf(fp, "#%%RULES\n"); +} + +/* + * Emit the load commands. + * + * This function is not to be called `spurt'. + */ +static void +emitload(FILE *fp) +{ + struct config *cf; + int found = 0; + + /* + * 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}%s\n" + "\t${SYSTEM_LD_TAIL}\n" + "\n", + Sflag ? "" : " swap${.TARGET}.o"); + } + /* + * Generate per-kernel rules. + */ + TAILQ_FOREACH(cf, &allcf, cf_next) { + char swapobj[100]; + + if (Sflag) { + swapobj[0] = '\0'; + } else { + (void)snprintf(swapobj, sizeof(swapobj), " swap%s.o", + cf->cf_name); + } + fprintf(fp, "KERNELS+=%s\n", cf->cf_name); + found = 1; + } + if (found == 0) + fprintf(fp, "#%%LOAD\n"); +} + +/* + * Emit include headers (for any prefixes encountered) + */ +static void +emitincludes(FILE *fp) +{ + struct prefix *pf; + + SLIST_FOREACH(pf, &allprefixes, pf_next) { + const char *prologue = (*pf->pf_prefix == '/') ? "" : "$S/"; + + fprintf(fp, "EXTRA_INCLUDES+=\t-I%s%s\n", + prologue, pf->pf_prefix); + } +} + +/* + * Emit appending makeoptions. + */ +static void +emitappmkoptions(FILE *fp) +{ + struct nvlist *nv; + struct condexpr *cond; + + for (nv = appmkoptions; nv != NULL; nv = nv->nv_next) + fprintf(fp, "%s+=%s\n", nv->nv_name, nv->nv_str); + + for (nv = condmkoptions; nv != NULL; nv = nv->nv_next) { + cond = nv->nv_ptr; + if (expr_eval(cond, selectopt, NULL)) + fprintf(fp, "%s+=%s\n", nv->nv_name, nv->nv_str); + condexpr_destroy(cond); + nv->nv_ptr = NULL; + } +} + +static int +/*ARGSUSED*/ +selectopt(const char *name, void *context) +{ + + return (ht_lookup(selecttab, strtolower(name)) != NULL); +} diff --git a/usr.bin/config/mkswap.c b/usr.bin/config/mkswap.c new file mode 100644 index 000000000..37c8a8957 --- /dev/null +++ b/usr.bin/config/mkswap.c @@ -0,0 +1,164 @@ +/* $NetBSD: mkswap.c,v 1.10 2015/09/03 13:53:36 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)mkswap.c 8.1 (Berkeley) 6/6/93 + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: mkswap.c,v 1.10 2015/09/03 13:53:36 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include "defs.h" +#include "sem.h" + +static char *mkdevstr(dev_t); +static int mkoneswap(struct config *); + +/* + * Make the various swap*.c files. Nothing to do for generic swap. + */ +int +mkswap(void) +{ + struct config *cf; + + TAILQ_FOREACH(cf, &allcf, cf_next) { + if (mkoneswap(cf)) + return (1); + } + return (0); +} + +static char * +mkdevstr(dev_t d) +{ + static char buf[32]; + + if (d == NODEV) + (void)snprintf(buf, sizeof(buf), "NODEV"); + else + (void)snprintf(buf, sizeof(buf), "makedev(%d, %d)", + major(d), minor(d)); + return buf; +} + +static int +mkoneswap(struct config *cf) +{ + struct nvlist *nv; + FILE *fp; + char fname[200], tname[200]; + char specinfo[200]; + + (void)snprintf(fname, sizeof(fname), "swap%s.c", cf->cf_name); + (void)snprintf(tname, sizeof(tname), "swap%s.c.tmp", cf->cf_name); + if ((fp = fopen(tname, "w")) == NULL) { + warn("cannot open %s", fname); + return (1); + } + + autogen_comment(fp, fname); + + fputs("#include \n" + "#include \n\n", fp); + /* + * Emit the root device. + */ + nv = cf->cf_root; + if (cf->cf_root->nv_str == s_qmark) + strlcpy(specinfo, "NULL", sizeof(specinfo)); + else + snprintf(specinfo, sizeof(specinfo), "\"%s\"", + cf->cf_root->nv_str); + fprintf(fp, "const char *rootspec = %s;\n", specinfo); + fprintf(fp, "dev_t\trootdev = %s;\t/* %s */\n\n", + mkdevstr((dev_t)nv->nv_num), + nv->nv_str == s_qmark ? "wildcarded" : nv->nv_str); + + /* + * Emit the dump device. + */ + nv = cf->cf_dump; + if (cf->cf_dump == NULL) + strlcpy(specinfo, "NULL", sizeof(specinfo)); + else + 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((dev_t)nv->nv_num) : "NODEV", + nv ? nv->nv_str : "unspecified"); + + /* + * Emit the root file system. + */ + fprintf(fp, "const char *rootfstype = \"%s\";\n", + cf->cf_fstype ? cf->cf_fstype : "?"); + + fflush(fp); + if (ferror(fp)) + goto wrerror; + + if (fclose(fp)) { + fp = NULL; + goto wrerror; + } + if (moveifchanged(tname, fname) != 0) { + warn("error renaming %s", fname); + return (1); + } + return (0); + + wrerror: + warn("error writing %s", fname); + if (fp != NULL) + (void)fclose(fp); +#if 0 + (void)unlink(fname); +#endif + return (1); +} diff --git a/usr.bin/config/pack.c b/usr.bin/config/pack.c new file mode 100644 index 000000000..f227aa3b3 --- /dev/null +++ b/usr.bin/config/pack.c @@ -0,0 +1,352 @@ +/* $NetBSD: pack.c,v 1.10 2015/09/12 19:11:13 joerg Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)pack.c 8.1 (Berkeley) 6/6/93 + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: pack.c,v 1.10 2015/09/12 19:11:13 joerg Exp $"); + +#include +#include +#include +#include +#include "defs.h" + +/* + * Packing. We have three separate kinds of packing here. + * + * First, we pack device instances which have identical parent specs. + * + * Second, we pack locators. Given something like + * + * hp0 at mba0 drive 0 + * hp* at mba* drive ? + * ht0 at mba0 drive 0 + * tu0 at ht0 slave 0 + * ht* at mba* drive ? + * tu* at ht* slave ? + * + * (where the default drive and slave numbers are -1), we have three + * locators whose value is 0 and three whose value is -1. Rather than + * emitting six integers, we emit just two. + * + * When packing locators, we would like to find sequences such as + * {1 2 3} {2 3 4} {3} {4 5} + * and turn this into the flat sequence {1 2 3 4 5}, with each subsequence + * given by the appropriate offset (here 0, 1, 2, and 3 respectively). + * Non-overlapping packing is much easier, and so we use that here + * and miss out on the chance to squeeze the locator sequence optimally. + * (So it goes.) + */ + +typedef int (*vec_cmp_func)(const void *, int, int); + +#define TAILHSIZE 128 +#define PVHASH(i) ((i) & (TAILHSIZE - 1)) +#define LOCHASH(l) (((long)(l) >> 2) & (TAILHSIZE - 1)) +struct tails { + struct tails *t_next; + int t_ends_at; +}; + +static struct tails *tails[TAILHSIZE]; +static int locspace; + +static void packdevi(void); +static void packlocs(void); + +static int sameas(struct devi *, struct devi *); +static int findvec(const void *, int, int, vec_cmp_func, int); +static int samelocs(const void *, int, int); +static int addlocs(const char **, int); +static int loclencmp(const void *, const void *); +static void resettails(void); + +void +pack(void) +{ + struct pspec *p; + struct devi *i; + + /* Pack instances and make parent vectors. */ + packdevi(); + + /* + * Now that we know what we have, find upper limits on space + * needed for the loc[] table. The loc table size is bounded by + * what we would get if no packing occurred. + */ + locspace = 0; + TAILQ_FOREACH(i, &alldevi, i_next) { + if (i->i_active != DEVI_ACTIVE || i->i_collapsed) + continue; + if ((p = i->i_pspec) == NULL) + continue; + locspace += p->p_iattr->a_loclen; + } + + /* Allocate and pack loc[]. */ + locators.vec = ecalloc((size_t)locspace, sizeof(*locators.vec)); + locators.used = 0; + packlocs(); +} + +/* + * Pack device instances together wherever possible. + */ +static void +packdevi(void) +{ + struct devi *firststar, *i, **ip, *l, *p; + struct devbase *d; + u_short j, m, n; + + /* + * Sort all the cloning units to after the non-cloning units, + * preserving order of cloning and non-cloning units with + * respect to other units of the same type. + * + * Algorithm: Walk down the list until the first cloning unit is + * seen for the second time (or until the end of the list, if there + * are no cloning units on the list), moving starred units to the + * end of the list. + */ + TAILQ_FOREACH(d, &allbases, d_next) { + ip = &d->d_ihead; + firststar = NULL; + + for (i = *ip; i != firststar; i = *ip) { + if (i->i_unit != STAR) { + /* try i->i_bsame next */ + ip = &i->i_bsame; + } else { + if (firststar == NULL) + firststar = i; + + *d->d_ipp = i; + d->d_ipp = &i->i_bsame; + + *ip = i->i_bsame; + i->i_bsame = NULL; + + /* leave ip alone; try (old) i->i_bsame next */ + } + } + } + + packed = ecalloc((size_t)ndevi + 1, sizeof *packed); + n = 0; + TAILQ_FOREACH(d, &allbases, d_next) { + /* + * For each instance of each device, add or collapse + * all its aliases. + * + * Pseudo-devices have a non-empty d_ihead for convenience. + * Ignore them. + */ + if (d->d_ispseudo) + continue; + for (i = d->d_ihead; i != NULL; i = i->i_bsame) { + m = n; + for (l = i; l != NULL; l = l->i_alias) { + if (l->i_active != DEVI_ACTIVE + || i->i_pseudoroot) + continue; + l->i_locoff = -1; + /* try to find an equivalent for l */ + for (j = m; j < n; j++) { + p = packed[j]; + if (sameas(l, p)) { + l->i_collapsed = 1; + l->i_cfindex = p->i_cfindex; + goto nextalias; + } + } + /* could not find a suitable alias */ + l->i_collapsed = 0; + l->i_cfindex = n; + packed[n++] = l; + nextalias:; + } + } + } + npacked = n; + packed[n] = NULL; +} + +/* + * Return true if two aliases are "the same". In this case, they need + * to have the same parent spec, have the same config flags, and have + * the same locators. + */ +static int +sameas(struct devi *i1, struct devi *i2) +{ + const char **p1, **p2; + + if (i1->i_pspec != i2->i_pspec) + return (0); + if (i1->i_cfflags != i2->i_cfflags) + return (0); + for (p1 = i1->i_locs, p2 = i2->i_locs; *p1 == *p2; p2++) + if (*p1++ == 0) + return (1); + return (0); +} + +static void +packlocs(void) +{ + struct pspec *ps; + struct devi **p, *i; + int l,o; + extern int Pflag; + + qsort(packed, npacked, sizeof *packed, loclencmp); + for (p = packed; (i = *p) != NULL; p++) { + if ((ps = i->i_pspec) != NULL && + (l = ps->p_iattr->a_loclen) > 0) { + if (Pflag) { + o = findvec(i->i_locs, + LOCHASH(i->i_locs[l - 1]), l, + samelocs, locators.used); + i->i_locoff = o < 0 ? + addlocs(i->i_locs, l) : o; + } else + i->i_locoff = addlocs(i->i_locs, l); + } else + i->i_locoff = -1; + } + resettails(); +} + +/* + * Return the index at which the given vector already exists, or -1 + * if it is not anywhere in the current set. If we return -1, we assume + * our caller will add it at the end of the current set, and we make + * sure that next time, we will find it there. + */ +static int +findvec(const void *ptr, int hash, int len, vec_cmp_func cmp, int nextplace) +{ + struct tails *t, **hp; + int off; + + hp = &tails[hash]; + for (t = *hp; t != NULL; t = t->t_next) { + off = t->t_ends_at - len; + if (off >= 0 && (*cmp)(ptr, off, len)) + return (off); + } + t = ecalloc(1, sizeof(*t)); + t->t_next = *hp; + *hp = t; + t->t_ends_at = nextplace + len; + return (-1); +} + +/* + * Comparison function for locators. + */ +static int +samelocs(const void *ptr, int off, int len) +{ + const char * const *p, * const *q; + + for (p = &locators.vec[off], q = (const char * const *)ptr; --len >= 0;) + if (*p++ != *q++) + return (0); /* different */ + return (1); /* same */ +} + +/* + * Add the given locators at the end of the global loc[] table. + */ +static int +addlocs(const char **locs, int len) +{ + const char **p; + int ret; + + ret = locators.used; + if ((locators.used = ret + len) > locspace) + panic("addlocs: overrun"); + for (p = &locators.vec[ret]; --len >= 0;) + *p++ = *locs++; + return (ret); +} + +/* + * Comparison function for qsort-by-locator-length, longest first. + * We rashly assume that subtraction of these lengths does not overflow. + */ +static int +loclencmp(const void *a, const void *b) +{ + const struct pspec *p1, *p2; + int l1, l2; + + p1 = (*(const struct devi * const *)a)->i_pspec; + l1 = p1 != NULL ? p1->p_iattr->a_loclen : 0; + + p2 = (*(const struct devi * const *)b)->i_pspec; + l2 = p2 != NULL ? p2->p_iattr->a_loclen : 0; + + return (l2 - l1); +} + +static void +resettails(void) +{ + struct tails **p, *t, *next; + int i; + + for (p = tails, i = TAILHSIZE; --i >= 0; p++) { + for (t = *p; t != NULL; t = next) { + next = t->t_next; + free(t); + } + *p = NULL; + } +} diff --git a/usr.bin/config/scan.c b/usr.bin/config/scan.c new file mode 100644 index 000000000..db205dee8 --- /dev/null +++ b/usr.bin/config/scan.c @@ -0,0 +1,3094 @@ +#line 2 "scan.c" + +#line 4 "scan.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#ifdef _LIBC +#include "namespace.h" +#endif +#include +#include +#include +#include + +/* end standard C headers. */ + +/* $NetBSD: flexint.h,v 1.2 2014/10/29 18:28:36 christos Exp $ */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define yywrap() (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +#if defined(__GNUC__) && __GNUC__ >= 3 +__attribute__((__noreturn__)) +#endif +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 77 +#define YY_END_OF_BUFFER 78 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[437] = + { 0, + 0, 0, 0, 0, 78, 76, 75, 72, 76, 74, + 76, 64, 68, 70, 76, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 73, 60, 59, 60, 60, 75, 71, + 0, 66, 0, 74, 51, 64, 64, 68, 0, 0, + 70, 52, 65, 65, 65, 2, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 34, 65, 37, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, + 0, 0, 67, 69, 1, 65, 65, 65, 65, 65, + + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 0, 0, 0, 0, + 0, 65, 65, 65, 6, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 20, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 43, + 65, 65, 65, 47, 65, 65, 50, 0, 0, 0, + 0, 0, 65, 4, 5, 65, 65, 65, 65, 9, + + 65, 65, 65, 65, 65, 65, 19, 65, 65, 0, + 57, 0, 65, 65, 22, 23, 65, 65, 65, 65, + 65, 65, 27, 65, 65, 65, 31, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, + 0, 0, 0, 0, 3, 65, 65, 65, 8, 65, + 10, 12, 65, 65, 65, 17, 65, 65, 0, 0, + 58, 0, 65, 0, 65, 65, 24, 65, 65, 65, + 65, 65, 65, 35, 65, 65, 65, 39, 65, 44, + 45, 46, 48, 65, 0, 0, 0, 65, 65, 65, + 11, 65, 65, 65, 65, 65, 65, 0, 65, 0, + + 0, 65, 65, 26, 65, 65, 65, 65, 65, 65, + 38, 65, 65, 49, 0, 0, 65, 65, 65, 13, + 65, 16, 65, 0, 65, 65, 0, 53, 0, 0, + 0, 0, 25, 65, 65, 30, 65, 65, 36, 0, + 65, 65, 0, 65, 0, 65, 14, 65, 0, 0, + 65, 0, 0, 54, 0, 0, 0, 0, 0, 65, + 65, 65, 65, 0, 0, 0, 65, 65, 65, 0, + 0, 0, 65, 65, 65, 0, 55, 0, 0, 0, + 65, 0, 0, 0, 0, 0, 61, 0, 0, 65, + 65, 65, 33, 0, 0, 0, 0, 63, 0, 0, + + 65, 65, 40, 0, 0, 0, 0, 62, 0, 0, + 65, 65, 65, 0, 0, 56, 0, 0, 21, 0, + 28, 65, 32, 0, 65, 42, 0, 7, 15, 18, + 0, 65, 65, 29, 41, 0 + } ; + +static yyconst YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 4, 5, 1, 1, 1, 1, 1, + 1, 1, 6, 1, 7, 8, 8, 9, 10, 10, + 10, 10, 10, 10, 10, 11, 11, 12, 1, 1, + 13, 1, 1, 1, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 16, 15, 15, + 1, 17, 1, 1, 15, 1, 18, 19, 20, 21, + + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 15, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst YY_CHAR yy_meta[44] = + { 0, + 1, 2, 3, 4, 5, 1, 6, 7, 8, 8, + 8, 1, 1, 9, 9, 9, 1, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 1 + } ; + +static yyconst flex_uint16_t yy_base[470] = + { 0, + 0, 0, 41, 42, 924, 1387, 920, 885, 42, 0, + 871, 0, 39, 42, 869, 49, 53, 58, 65, 63, + 67, 73, 85, 75, 96, 102, 104, 111, 118, 125, + 113, 120, 123, 1387, 1387, 1387, 47, 855, 859, 1387, + 90, 1387, 849, 0, 1387, 0, 0, 130, 830, 150, + 166, 1387, 0, 136, 145, 148, 155, 171, 173, 175, + 178, 181, 185, 187, 191, 194, 203, 209, 217, 219, + 221, 225, 227, 229, 235, 237, 242, 244, 251, 254, + 256, 258, 263, 265, 268, 274, 276, 278, 281, 51, + 807, 84, 1387, 0, 283, 285, 293, 289, 297, 299, + + 307, 313, 315, 317, 319, 321, 327, 325, 338, 346, + 348, 350, 354, 356, 358, 360, 366, 369, 373, 375, + 379, 385, 391, 389, 396, 402, 408, 410, 412, 416, + 418, 420, 427, 425, 429, 432, 795, 791, 782, 769, + 766, 436, 438, 444, 451, 455, 460, 462, 464, 466, + 468, 471, 473, 475, 483, 496, 505, 507, 512, 514, + 516, 518, 521, 524, 526, 528, 530, 532, 537, 540, + 543, 546, 552, 555, 557, 560, 564, 569, 576, 566, + 581, 583, 586, 591, 595, 597, 600, 169, 608, 750, + 734, 729, 607, 609, 611, 613, 617, 621, 623, 626, + + 629, 631, 635, 640, 645, 648, 650, 652, 657, 670, + 1387, 742, 674, 691, 676, 678, 685, 681, 687, 683, + 689, 691, 693, 695, 702, 705, 707, 709, 711, 713, + 717, 722, 724, 726, 730, 732, 734, 736, 742, 701, + 686, 750, 703, 657, 752, 754, 760, 764, 768, 770, + 772, 775, 777, 782, 785, 789, 791, 793, 668, 800, + 1387, 665, 625, 659, 802, 799, 804, 809, 815, 817, + 819, 822, 319, 824, 826, 828, 832, 834, 837, 839, + 841, 843, 850, 852, 631, 627, 638, 857, 859, 861, + 863, 865, 867, 869, 605, 878, 882, 623, 587, 889, + + 607, 891, 889, 893, 899, 901, 895, 568, 567, 904, + 906, 908, 184, 910, 553, 523, 912, 921, 503, 924, + 926, 929, 498, 509, 936, 473, 937, 1387, 502, 943, + 947, 490, 946, 948, 952, 954, 459, 467, 956, 577, + 455, 428, 453, 958, 761, 427, 960, 423, 967, 439, + 407, 411, 971, 1387, 402, 980, 203, 984, 988, 970, + 986, 369, 354, 236, 995, 1000, 331, 327, 998, 367, + 1008, 1012, 314, 1010, 298, 1019, 1387, 313, 1023, 1028, + 280, 305, 385, 1032, 299, 1037, 1387, 276, 1041, 1040, + 1042, 232, 0, 390, 1049, 243, 1053, 1387, 227, 1057, + + 188, 167, 1056, 483, 1063, 193, 1067, 1387, 164, 1074, + 140, 1073, 114, 138, 1080, 1387, 133, 1084, 0, 110, + 1083, 1085, 0, 85, 49, 0, 59, 0, 1087, 0, + 55, 1089, 32, 1091, 0, 1387, 1124, 1133, 1142, 1146, + 1149, 1153, 1157, 1166, 1175, 1183, 1191, 1199, 1207, 1216, + 1224, 1232, 1240, 1248, 1256, 1264, 1273, 1282, 1290, 1299, + 1307, 1316, 1324, 1333, 1341, 1350, 1359, 1368, 1377 + } ; + +static yyconst flex_int16_t yy_def[470] = + { 0, + 436, 1, 437, 437, 436, 436, 436, 436, 438, 439, + 436, 440, 441, 441, 436, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 436, 436, 436, 436, 436, 436, 436, + 438, 436, 438, 439, 436, 440, 440, 441, 441, 441, + 441, 436, 443, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 436, + 436, 436, 436, 50, 442, 442, 442, 442, 442, 442, + + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 436, 436, 436, 436, + 436, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 436, 436, 436, + 436, 436, 442, 442, 442, 442, 442, 442, 442, 442, + + 442, 442, 442, 442, 442, 442, 442, 442, 442, 436, + 436, 444, 442, 443, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 436, + 436, 436, 436, 436, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 444, 436, + 436, 445, 443, 446, 442, 442, 442, 442, 442, 442, + 442, 442, 443, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 442, 442, 436, 436, 436, 442, 442, 442, + 442, 442, 442, 442, 443, 442, 442, 445, 443, 447, + + 448, 442, 442, 442, 442, 442, 442, 443, 443, 442, + 442, 442, 443, 442, 436, 436, 442, 442, 443, 442, + 442, 442, 443, 449, 442, 443, 436, 436, 450, 447, + 451, 452, 442, 442, 442, 442, 443, 443, 442, 453, + 443, 443, 436, 442, 454, 443, 442, 443, 455, 456, + 443, 450, 436, 436, 457, 451, 458, 459, 452, 442, + 442, 443, 443, 460, 461, 453, 443, 443, 442, 462, + 463, 454, 443, 442, 443, 436, 436, 464, 455, 465, + 443, 457, 458, 436, 458, 436, 436, 466, 459, 442, + 442, 443, 443, 460, 436, 460, 436, 436, 467, 461, + + 443, 443, 442, 462, 436, 462, 436, 436, 468, 463, + 443, 442, 443, 464, 436, 436, 469, 465, 443, 466, + 442, 442, 443, 467, 443, 443, 468, 443, 442, 443, + 469, 442, 443, 442, 443, 0, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436 + } ; + +static yyconst flex_uint16_t yy_nxt[1431] = + { 0, + 6, 7, 8, 9, 10, 11, 6, 12, 13, 14, + 14, 15, 6, 16, 16, 16, 6, 17, 18, 19, + 20, 21, 22, 16, 16, 23, 16, 16, 24, 25, + 26, 27, 28, 29, 30, 31, 16, 32, 33, 16, + 16, 16, 34, 36, 36, 42, 47, 48, 48, 47, + 51, 51, 51, 435, 50, 53, 47, 416, 43, 53, + 47, 408, 37, 37, 53, 47, 38, 38, 433, 53, + 47, 53, 47, 53, 47, 90, 137, 91, 50, 53, + 47, 53, 47, 55, 62, 138, 57, 398, 56, 59, + 60, 53, 47, 93, 58, 64, 61, 65, 66, 63, + + 72, 67, 53, 47, 140, 68, 43, 69, 53, 47, + 53, 47, 387, 73, 141, 70, 71, 53, 47, 53, + 47, 74, 77, 75, 53, 47, 53, 47, 80, 53, + 47, 53, 47, 76, 78, 416, 79, 47, 48, 48, + 377, 88, 53, 47, 81, 82, 84, 430, 89, 83, + 85, 53, 47, 87, 53, 47, 86, 47, 94, 94, + 94, 53, 47, 94, 428, 95, 408, 94, 94, 94, + 94, 94, 94, 47, 51, 51, 51, 53, 47, 53, + 47, 53, 47, 96, 53, 47, 97, 53, 47, 240, + 99, 53, 47, 53, 47, 436, 98, 53, 47, 241, + + 53, 47, 426, 103, 341, 100, 384, 101, 102, 53, + 47, 108, 106, 425, 105, 53, 47, 342, 104, 385, + 110, 107, 109, 53, 47, 53, 47, 53, 47, 398, + 111, 53, 47, 53, 47, 53, 47, 112, 114, 395, + 115, 53, 47, 53, 47, 436, 117, 113, 53, 47, + 53, 47, 396, 118, 119, 116, 122, 53, 47, 121, + 53, 47, 53, 47, 53, 47, 120, 423, 123, 53, + 47, 53, 47, 126, 53, 47, 124, 127, 387, 128, + 53, 47, 53, 47, 53, 47, 125, 53, 47, 53, + 47, 53, 47, 130, 129, 53, 47, 134, 131, 53, + + 47, 436, 142, 53, 47, 53, 47, 354, 133, 419, + 132, 135, 143, 53, 47, 377, 136, 144, 146, 53, + 47, 53, 47, 53, 47, 53, 47, 53, 47, 413, + 145, 53, 47, 53, 47, 148, 153, 149, 308, 147, + 150, 309, 154, 156, 53, 47, 151, 152, 157, 411, + 158, 155, 53, 47, 53, 47, 53, 47, 402, 159, + 53, 47, 53, 47, 53, 47, 53, 47, 401, 160, + 405, 162, 53, 47, 163, 53, 47, 393, 161, 53, + 47, 53, 47, 406, 164, 53, 47, 166, 384, 165, + 167, 53, 47, 395, 169, 53, 47, 53, 47, 392, + + 168, 385, 53, 47, 354, 173, 396, 170, 53, 47, + 172, 171, 174, 328, 53, 47, 53, 47, 53, 47, + 175, 176, 53, 47, 53, 47, 53, 47, 381, 177, + 178, 53, 47, 53, 47, 53, 47, 181, 53, 47, + 350, 182, 53, 47, 53, 47, 179, 180, 184, 375, + 53, 47, 373, 183, 350, 193, 187, 53, 47, 368, + 185, 53, 47, 186, 195, 194, 53, 47, 53, 47, + 53, 47, 53, 47, 53, 47, 367, 53, 47, 53, + 47, 53, 47, 196, 363, 197, 405, 198, 203, 53, + 47, 332, 199, 357, 206, 362, 201, 358, 200, 406, + + 202, 205, 53, 47, 328, 204, 210, 211, 351, 212, + 324, 53, 47, 53, 47, 348, 208, 207, 214, 47, + 53, 47, 53, 47, 53, 47, 209, 53, 47, 213, + 53, 47, 53, 47, 53, 47, 53, 47, 53, 47, + 217, 346, 218, 53, 47, 343, 53, 47, 215, 53, + 47, 216, 53, 47, 324, 222, 220, 225, 53, 47, + 219, 53, 47, 53, 47, 223, 53, 47, 224, 221, + 53, 47, 53, 47, 229, 53, 47, 226, 340, 227, + 364, 232, 53, 47, 365, 230, 228, 53, 47, 53, + 47, 231, 53, 47, 233, 338, 234, 53, 47, 337, + + 235, 53, 47, 53, 47, 237, 53, 47, 301, 210, + 211, 236, 212, 53, 47, 53, 47, 53, 47, 53, + 47, 326, 239, 53, 47, 261, 238, 53, 47, 53, + 47, 245, 53, 47, 323, 53, 47, 53, 47, 301, + 250, 53, 47, 246, 249, 248, 53, 47, 316, 247, + 251, 53, 47, 315, 53, 47, 53, 47, 53, 47, + 264, 254, 255, 53, 47, 299, 252, 261, 253, 256, + 211, 210, 211, 257, 212, 260, 261, 258, 262, 287, + 53, 47, 53, 47, 53, 47, 264, 53, 47, 53, + 47, 53, 47, 53, 47, 53, 47, 53, 47, 53, + + 47, 53, 47, 265, 264, 267, 286, 266, 53, 47, + 268, 53, 47, 53, 47, 273, 47, 53, 47, 53, + 47, 269, 285, 53, 47, 263, 272, 270, 53, 47, + 53, 47, 53, 47, 275, 271, 53, 47, 53, 47, + 53, 47, 53, 47, 211, 277, 274, 276, 53, 47, + 244, 260, 261, 281, 262, 282, 243, 279, 53, 47, + 53, 47, 345, 278, 370, 280, 53, 47, 371, 283, + 53, 47, 242, 284, 53, 47, 53, 47, 53, 47, + 289, 53, 47, 53, 47, 290, 192, 288, 53, 47, + 191, 53, 47, 291, 292, 295, 47, 53, 47, 53, + + 47, 260, 261, 301, 262, 53, 47, 190, 53, 47, + 53, 47, 189, 296, 297, 53, 47, 188, 293, 294, + 302, 53, 47, 53, 47, 53, 47, 139, 53, 47, + 53, 47, 53, 47, 53, 47, 304, 47, 53, 47, + 53, 47, 303, 313, 47, 53, 47, 53, 47, 53, + 47, 436, 305, 312, 306, 307, 53, 47, 53, 47, + 39, 310, 311, 53, 47, 53, 47, 319, 47, 53, + 47, 53, 47, 53, 47, 53, 47, 92, 317, 324, + 318, 52, 314, 45, 53, 47, 40, 321, 53, 47, + 327, 328, 332, 329, 320, 53, 47, 53, 47, 53, + + 47, 53, 47, 322, 325, 53, 47, 53, 47, 340, + 53, 47, 53, 47, 53, 47, 53, 47, 53, 47, + 333, 39, 345, 436, 334, 339, 335, 53, 47, 336, + 53, 47, 53, 47, 344, 53, 47, 350, 327, 328, + 436, 329, 53, 47, 327, 328, 436, 329, 353, 354, + 436, 355, 53, 47, 53, 47, 436, 347, 53, 47, + 53, 47, 53, 47, 53, 47, 53, 47, 376, 377, + 436, 378, 353, 354, 436, 355, 53, 47, 436, 360, + 374, 353, 354, 369, 355, 386, 387, 361, 388, 436, + 436, 436, 53, 47, 436, 358, 397, 398, 436, 399, + + 390, 436, 436, 436, 53, 47, 436, 365, 436, 407, + 408, 391, 409, 436, 436, 436, 53, 47, 436, 371, + 376, 377, 436, 378, 376, 377, 436, 378, 436, 415, + 416, 412, 417, 386, 387, 436, 388, 403, 386, 387, + 436, 388, 386, 387, 436, 388, 53, 47, 53, 47, + 397, 398, 436, 399, 397, 398, 436, 399, 397, 398, + 436, 399, 53, 47, 407, 408, 436, 409, 407, 408, + 436, 409, 436, 422, 421, 407, 408, 436, 409, 53, + 47, 415, 416, 436, 417, 415, 416, 436, 417, 53, + 47, 53, 47, 53, 47, 53, 47, 53, 47, 436, + + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 429, 436, 436, 436, 436, 432, 436, 436, 436, 436, + 436, 436, 436, 434, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 44, 44, 436, 44, 44, 44, 44, 44, + 44, 46, 46, 46, 46, 49, 49, 49, 54, 54, + 54, 54, 53, 436, 53, 53, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 298, 298, 298, 298, 298, + 298, 298, 298, 298, 300, 436, 436, 436, 436, 436, + 436, 300, 330, 330, 436, 330, 330, 436, 330, 330, + + 331, 436, 436, 436, 436, 436, 436, 331, 349, 436, + 436, 436, 436, 436, 436, 349, 352, 352, 352, 352, + 352, 352, 352, 352, 352, 356, 356, 436, 356, 356, + 436, 356, 356, 359, 436, 359, 436, 436, 359, 359, + 359, 366, 436, 366, 436, 436, 366, 366, 366, 372, + 436, 372, 436, 436, 372, 372, 372, 379, 379, 436, + 379, 379, 436, 379, 379, 380, 436, 436, 436, 436, + 436, 436, 380, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 383, 383, 383, 383, 383, 383, 383, 383, + 383, 389, 389, 436, 389, 389, 389, 389, 389, 394, + + 394, 394, 394, 394, 394, 394, 394, 394, 400, 400, + 436, 400, 400, 400, 400, 400, 404, 404, 404, 404, + 404, 404, 404, 404, 404, 410, 410, 436, 410, 410, + 410, 410, 410, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 418, 418, 436, 418, 418, 436, 418, 418, + 420, 420, 420, 420, 420, 420, 420, 420, 420, 424, + 424, 424, 424, 424, 424, 424, 424, 424, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 431, 431, 431, + 431, 431, 431, 431, 431, 431, 5, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 + } ; + +static yyconst flex_int16_t yy_chk[1431] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 4, 9, 13, 13, 13, 14, + 14, 14, 14, 433, 13, 16, 16, 431, 9, 17, + 17, 427, 3, 4, 18, 18, 3, 4, 425, 20, + 20, 19, 19, 21, 21, 37, 90, 37, 13, 22, + 22, 24, 24, 17, 20, 90, 18, 424, 17, 19, + 19, 23, 23, 41, 18, 21, 19, 21, 22, 20, + + 24, 22, 25, 25, 92, 23, 41, 23, 26, 26, + 27, 27, 420, 25, 92, 23, 23, 28, 28, 31, + 31, 25, 27, 26, 29, 29, 32, 32, 28, 33, + 33, 30, 30, 26, 27, 417, 27, 48, 48, 48, + 414, 32, 54, 54, 28, 28, 30, 413, 33, 29, + 30, 55, 55, 31, 56, 56, 30, 50, 50, 50, + 50, 57, 57, 50, 411, 55, 409, 50, 50, 50, + 50, 50, 50, 51, 51, 51, 51, 58, 58, 59, + 59, 60, 60, 56, 61, 61, 57, 62, 62, 188, + 59, 63, 63, 64, 64, 406, 58, 65, 65, 188, + + 66, 66, 402, 62, 313, 60, 357, 61, 61, 67, + 67, 65, 64, 401, 63, 68, 68, 313, 62, 357, + 67, 64, 66, 69, 69, 70, 70, 71, 71, 399, + 68, 72, 72, 73, 73, 74, 74, 69, 70, 364, + 71, 75, 75, 76, 76, 396, 73, 69, 77, 77, + 78, 78, 364, 73, 73, 72, 75, 79, 79, 74, + 80, 80, 81, 81, 82, 82, 73, 392, 77, 83, + 83, 84, 84, 80, 85, 85, 77, 81, 388, 82, + 86, 86, 87, 87, 88, 88, 79, 89, 89, 95, + 95, 96, 96, 84, 83, 98, 98, 88, 85, 97, + + 97, 385, 96, 99, 99, 100, 100, 382, 87, 381, + 86, 88, 97, 101, 101, 378, 89, 98, 100, 102, + 102, 103, 103, 104, 104, 105, 105, 106, 106, 375, + 99, 108, 108, 107, 107, 102, 104, 103, 273, 101, + 103, 273, 104, 106, 109, 109, 103, 103, 107, 373, + 108, 105, 110, 110, 111, 111, 112, 112, 368, 109, + 113, 113, 114, 114, 115, 115, 116, 116, 367, 110, + 370, 112, 117, 117, 113, 118, 118, 363, 111, 119, + 119, 120, 120, 370, 114, 121, 121, 116, 383, 115, + 117, 122, 122, 394, 119, 124, 124, 123, 123, 362, + + 118, 383, 125, 125, 355, 122, 394, 120, 126, 126, + 121, 120, 123, 352, 127, 127, 128, 128, 129, 129, + 124, 125, 130, 130, 131, 131, 132, 132, 351, 126, + 127, 134, 134, 133, 133, 135, 135, 130, 136, 136, + 350, 131, 142, 142, 143, 143, 128, 129, 133, 348, + 144, 144, 346, 132, 343, 142, 136, 145, 145, 342, + 134, 146, 146, 135, 144, 143, 147, 147, 148, 148, + 149, 149, 150, 150, 151, 151, 341, 152, 152, 153, + 153, 154, 154, 146, 338, 147, 404, 148, 152, 155, + 155, 332, 149, 332, 154, 337, 150, 332, 149, 404, + + 151, 153, 156, 156, 329, 152, 157, 157, 326, 157, + 324, 157, 157, 158, 158, 323, 156, 155, 159, 159, + 160, 160, 161, 161, 162, 162, 156, 163, 163, 158, + 164, 164, 165, 165, 166, 166, 167, 167, 168, 168, + 162, 319, 163, 169, 169, 316, 170, 170, 160, 171, + 171, 161, 172, 172, 315, 167, 165, 170, 173, 173, + 164, 174, 174, 175, 175, 168, 176, 176, 169, 166, + 177, 177, 180, 180, 174, 178, 178, 171, 340, 172, + 340, 177, 179, 179, 340, 175, 173, 181, 181, 182, + 182, 176, 183, 183, 178, 309, 179, 184, 184, 308, + + 181, 185, 185, 186, 186, 183, 187, 187, 301, 189, + 189, 182, 189, 193, 193, 194, 194, 195, 195, 196, + 196, 299, 186, 197, 197, 298, 185, 198, 198, 199, + 199, 193, 200, 200, 295, 201, 201, 202, 202, 287, + 199, 203, 203, 195, 198, 197, 204, 204, 286, 196, + 201, 205, 205, 285, 206, 206, 207, 207, 208, 208, + 264, 204, 205, 209, 209, 263, 202, 262, 203, 206, + 259, 210, 210, 208, 210, 213, 213, 209, 213, 244, + 213, 213, 215, 215, 216, 216, 217, 218, 218, 220, + 220, 217, 217, 219, 219, 221, 221, 222, 222, 223, + + 223, 224, 224, 218, 243, 220, 241, 219, 225, 225, + 221, 226, 226, 227, 227, 228, 228, 229, 229, 230, + 230, 222, 240, 231, 231, 214, 226, 224, 232, 232, + 233, 233, 234, 234, 230, 225, 235, 235, 236, 236, + 237, 237, 238, 238, 212, 232, 229, 231, 239, 239, + 192, 242, 242, 236, 242, 237, 191, 234, 245, 245, + 246, 246, 345, 233, 345, 235, 247, 247, 345, 238, + 248, 248, 190, 239, 249, 249, 250, 250, 251, 251, + 247, 252, 252, 253, 253, 248, 141, 246, 254, 254, + 140, 255, 255, 250, 253, 256, 256, 257, 257, 258, + + 258, 260, 260, 265, 260, 266, 266, 139, 265, 265, + 267, 267, 138, 257, 258, 268, 268, 137, 254, 255, + 266, 269, 269, 270, 270, 271, 271, 91, 272, 272, + 274, 274, 275, 275, 276, 276, 269, 49, 277, 277, + 278, 278, 268, 279, 279, 280, 280, 281, 281, 282, + 282, 43, 270, 277, 271, 272, 283, 283, 284, 284, + 39, 275, 276, 288, 288, 289, 289, 290, 290, 291, + 291, 292, 292, 293, 293, 294, 294, 38, 288, 296, + 289, 15, 284, 11, 296, 296, 8, 293, 297, 297, + 300, 300, 302, 300, 292, 303, 303, 302, 302, 304, + + 304, 307, 307, 294, 297, 305, 305, 306, 306, 312, + 310, 310, 311, 311, 312, 312, 314, 314, 317, 317, + 303, 7, 318, 5, 305, 310, 306, 318, 318, 307, + 320, 320, 321, 321, 317, 322, 322, 325, 327, 327, + 0, 327, 325, 325, 330, 330, 0, 330, 331, 331, + 0, 331, 333, 333, 334, 334, 0, 321, 335, 335, + 336, 336, 339, 339, 344, 344, 347, 347, 349, 349, + 0, 349, 353, 353, 0, 353, 360, 360, 0, 334, + 347, 356, 356, 344, 356, 358, 358, 335, 358, 359, + 0, 359, 361, 361, 0, 359, 365, 365, 0, 365, + + 360, 366, 0, 366, 369, 369, 0, 366, 0, 371, + 371, 361, 371, 372, 0, 372, 374, 374, 0, 372, + 376, 376, 0, 376, 379, 379, 0, 379, 0, 380, + 380, 374, 380, 384, 384, 0, 384, 369, 386, 386, + 0, 386, 389, 389, 0, 389, 390, 390, 391, 391, + 395, 395, 0, 395, 397, 397, 0, 397, 400, 400, + 0, 400, 403, 403, 405, 405, 0, 405, 407, 407, + 0, 407, 0, 391, 390, 410, 410, 0, 410, 412, + 412, 415, 415, 0, 415, 418, 418, 0, 418, 421, + 421, 422, 422, 429, 429, 432, 432, 434, 434, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 412, 0, 0, 0, 0, 422, 0, 0, 0, 0, + 0, 0, 0, 432, 437, 437, 437, 437, 437, 437, + 437, 437, 437, 438, 438, 438, 438, 438, 438, 438, + 438, 438, 439, 439, 0, 439, 439, 439, 439, 439, + 439, 440, 440, 440, 440, 441, 441, 441, 442, 442, + 442, 442, 443, 0, 443, 443, 444, 444, 444, 444, + 444, 444, 444, 444, 444, 445, 445, 445, 445, 445, + 445, 445, 445, 445, 446, 0, 0, 0, 0, 0, + 0, 446, 447, 447, 0, 447, 447, 0, 447, 447, + + 448, 0, 0, 0, 0, 0, 0, 448, 449, 0, + 0, 0, 0, 0, 0, 449, 450, 450, 450, 450, + 450, 450, 450, 450, 450, 451, 451, 0, 451, 451, + 0, 451, 451, 452, 0, 452, 0, 0, 452, 452, + 452, 453, 0, 453, 0, 0, 453, 453, 453, 454, + 0, 454, 0, 0, 454, 454, 454, 455, 455, 0, + 455, 455, 0, 455, 455, 456, 0, 0, 0, 0, + 0, 0, 456, 457, 457, 457, 457, 457, 457, 457, + 457, 457, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 459, 459, 0, 459, 459, 459, 459, 459, 460, + + 460, 460, 460, 460, 460, 460, 460, 460, 461, 461, + 0, 461, 461, 461, 461, 461, 462, 462, 462, 462, + 462, 462, 462, 462, 462, 463, 463, 0, 463, 463, + 463, 463, 463, 464, 464, 464, 464, 464, 464, 464, + 464, 464, 465, 465, 0, 465, 465, 0, 465, 465, + 466, 466, 466, 466, 466, 466, 466, 466, 466, 467, + 467, 467, 467, 467, 467, 467, 467, 467, 468, 468, + 468, 468, 468, 468, 468, 468, 468, 469, 469, 469, + 469, 469, 469, 469, 469, 469, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "scan.l" +#line 2 "scan.l" +/* $NetBSD: scan.l,v 1.25 2015/09/04 10:16:35 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)scan.l 8.1 (Berkeley) 6/6/93 + */ + +#include +__RCSID("$NetBSD: scan.l,v 1.25 2015/09/04 10:16:35 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef ECHO +#include "defs.h" +#include "gram.h" + +int yyline; +const char *yyfile; +const char *lastfile; +char curinclpath[PATH_MAX]; +int ifdefstate = -1; +int st; +#define IDS_PARENT_DISABLED \ + ((ifdefstate > 6) && ((((ifdefstate/6)-1) & 1) == 1)) +#define IDS_MAX_DEPTH 362797056 /* 6^11 */ +/* States for ifdefstate: + + 0 -> matched ifdef + 1 -> unmatched ifdef + 2 -> matched elifdef + 3 -> unmatched elifdef + 4 -> matched else + 5 -> unmatched else + + Upon "ifdef", add one and multiply by 6. + Upon "endif", divide by 6, remove 1. + + ifdef -> MATCH => continue + MISMATCH => set to 1 + elifdef -> if (!1) -> MISMATCH + MATCH => set to 2 + MISMATCH => if (2 || 3) set to 3, else set to 1 + else -> if (1) -> MATCH + MATCH => set to 4 + MISMATCH => set to 5 + + in each case, if parent & 1 == 1, MISMATCH +*/ + +/* + * Data for returning to previous files from include files. + */ +struct incl { + struct incl *in_prev; /* previous includes in effect, if any */ + YY_BUFFER_STATE in_buf; /* previous lex state */ + const char *in_fname; /* previous file name */ + int in_lineno; /* previous line number */ + int in_ateof; /* token to insert at EOF */ + int in_interesting; /* previous value for "interesting" */ + int in_ifdefstate; /* conditional level */ +}; +static struct incl *incl; +static int endinclude(void); +static int getincludepath(void); +static int getcurifdef(void); + + +#define YY_NO_INPUT 1 + +#line 1039 "scan.c" + +#define INITIAL 0 +#define IGNORED 1 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * _in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * _out_str ); + +yy_size_t yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int _line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + { +#line 124 "scan.l" + + /* Local variables for yylex() */ + int tok; + +#line 1256 "scan.c" + + while (/*CONSTCOND*/ 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 437 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 1387 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 128 "scan.l" +return AND; + YY_BREAK +case 2: +YY_RULE_SETUP +#line 129 "scan.l" +return AT; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 130 "scan.l" +return ATTACH; + YY_BREAK +case 4: +YY_RULE_SETUP +#line 131 "scan.l" +return BLOCK; + YY_BREAK +case 5: +YY_RULE_SETUP +#line 132 "scan.l" +return BUILD; + YY_BREAK +case 6: +YY_RULE_SETUP +#line 133 "scan.l" +return CHAR; + YY_BREAK +case 7: +YY_RULE_SETUP +#line 134 "scan.l" +return COMPILE_WITH; + YY_BREAK +case 8: +YY_RULE_SETUP +#line 135 "scan.l" +return CONFIG; + YY_BREAK +case 9: +YY_RULE_SETUP +#line 136 "scan.l" +return DEFFS; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 137 "scan.l" +return DEFINE; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 138 "scan.l" +return DEFFLAG; + YY_BREAK +case 12: +YY_RULE_SETUP +#line 139 "scan.l" +return DEFOPT; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 140 "scan.l" +return DEFPARAM; + YY_BREAK +case 14: +YY_RULE_SETUP +#line 141 "scan.l" +return DEFPSEUDO; + YY_BREAK +case 15: +YY_RULE_SETUP +#line 142 "scan.l" +return DEFPSEUDODEV; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 143 "scan.l" +return DEVCLASS; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 144 "scan.l" +return DEVICE; + YY_BREAK +case 18: +YY_RULE_SETUP +#line 145 "scan.l" +return DEVICE_MAJOR; + YY_BREAK +case 19: +YY_RULE_SETUP +#line 146 "scan.l" +return DUMPS; + YY_BREAK +case 20: +YY_RULE_SETUP +#line 147 "scan.l" +return XFILE; + YY_BREAK +case 21: +YY_RULE_SETUP +#line 148 "scan.l" +return FILE_SYSTEM; + YY_BREAK +case 22: +YY_RULE_SETUP +#line 149 "scan.l" +return FLAGS; + YY_BREAK +case 23: +YY_RULE_SETUP +#line 150 "scan.l" +return IDENT; + YY_BREAK +case 24: +YY_RULE_SETUP +#line 151 "scan.l" +return IOCONF; + YY_BREAK +case 25: +YY_RULE_SETUP +#line 152 "scan.l" +return LINKZERO; + YY_BREAK +case 26: +YY_RULE_SETUP +#line 153 "scan.l" +return XMACHINE; + YY_BREAK +case 27: +YY_RULE_SETUP +#line 154 "scan.l" +return MAJOR; + YY_BREAK +case 28: +YY_RULE_SETUP +#line 155 "scan.l" +return MAKEOPTIONS; + YY_BREAK +case 29: +YY_RULE_SETUP +#line 156 "scan.l" +return MAXPARTITIONS; + YY_BREAK +case 30: +YY_RULE_SETUP +#line 157 "scan.l" +return MAXUSERS; + YY_BREAK +case 31: +YY_RULE_SETUP +#line 158 "scan.l" +return MINOR; + YY_BREAK +case 32: +YY_RULE_SETUP +#line 159 "scan.l" +return NEEDS_COUNT; + YY_BREAK +case 33: +YY_RULE_SETUP +#line 160 "scan.l" +return NEEDS_FLAG; + YY_BREAK +case 34: +YY_RULE_SETUP +#line 161 "scan.l" +return NO; + YY_BREAK +case 35: +YY_RULE_SETUP +#line 162 "scan.l" +return XOBJECT; + YY_BREAK +case 36: +YY_RULE_SETUP +#line 163 "scan.l" +return OBSOLETE; + YY_BREAK +case 37: +YY_RULE_SETUP +#line 164 "scan.l" +return ON; + YY_BREAK +case 38: +YY_RULE_SETUP +#line 165 "scan.l" +return OPTIONS; + YY_BREAK +case 39: +YY_RULE_SETUP +#line 166 "scan.l" +return PREFIX; + YY_BREAK +case 40: +YY_RULE_SETUP +#line 167 "scan.l" +return BUILDPREFIX; + YY_BREAK +case 41: +YY_RULE_SETUP +#line 168 "scan.l" +return PSEUDO_DEVICE; + YY_BREAK +case 42: +YY_RULE_SETUP +#line 169 "scan.l" +return PSEUDO_ROOT; + YY_BREAK +case 43: +YY_RULE_SETUP +#line 170 "scan.l" +return ROOT; + YY_BREAK +case 44: +YY_RULE_SETUP +#line 171 "scan.l" +return SELECT; + YY_BREAK +case 45: +YY_RULE_SETUP +#line 172 "scan.l" +return SINGLE; + YY_BREAK +case 46: +YY_RULE_SETUP +#line 173 "scan.l" +return SOURCE; + YY_BREAK +case 47: +YY_RULE_SETUP +#line 174 "scan.l" +return TYPE; + YY_BREAK +case 48: +YY_RULE_SETUP +#line 175 "scan.l" +return VECTOR; + YY_BREAK +case 49: +YY_RULE_SETUP +#line 176 "scan.l" +return VERSION; + YY_BREAK +case 50: +YY_RULE_SETUP +#line 177 "scan.l" +return WITH; + YY_BREAK +case 51: +YY_RULE_SETUP +#line 179 "scan.l" +return PLUSEQ; + YY_BREAK +case 52: +YY_RULE_SETUP +#line 180 "scan.l" +return COLONEQ; + YY_BREAK +case 53: +/* rule 53 can match eol */ +YY_RULE_SETUP +#line 182 "scan.l" +{ + ifdefstate = (ifdefstate + 1) * 6; + if (ifdefstate >= IDS_MAX_DEPTH) { + yyerror("too many levels of conditional"); + } + if (!IDS_PARENT_DISABLED && getcurifdef()) { + BEGIN(INITIAL); + } else { + ifdefstate++; + BEGIN(IGNORED); + } + yyline++; + } + YY_BREAK +case 54: +/* rule 54 can match eol */ +YY_RULE_SETUP +#line 196 "scan.l" +{ + ifdefstate = (ifdefstate + 1) * 6; + if (ifdefstate >= IDS_MAX_DEPTH) { + yyerror("too many levels of conditional"); + } + if (!IDS_PARENT_DISABLED && !getcurifdef()) { + BEGIN(INITIAL); + } else { + ifdefstate++; + BEGIN(IGNORED); + } + yyline++; + } + YY_BREAK +case 55: +/* rule 55 can match eol */ +YY_RULE_SETUP +#line 211 "scan.l" +{ + st = ifdefstate % 6; + if (ifdefstate < 0 || st > 3) { + yyerror("mismatched elifdef"); + } + if (IDS_PARENT_DISABLED || + st != 1 || !getcurifdef()) { + if (st == 2 || st == 3) { + ifdefstate += 3 - st; + } else { + ifdefstate += 1 - st; + } + BEGIN(IGNORED); + } else { + ifdefstate++; + BEGIN(INITIAL); + } + yyline++; + } + YY_BREAK +case 56: +/* rule 56 can match eol */ +YY_RULE_SETUP +#line 231 "scan.l" +{ + st = ifdefstate % 6; + if (ifdefstate < 0 || st > 3) { + yyerror("mismatched elifndef"); + } + if (IDS_PARENT_DISABLED || + st != 1 || getcurifdef()) { + if (st == 2 || st == 3) { + ifdefstate += 3 - st; + } else { + ifdefstate += 1 - st; + } + BEGIN(IGNORED); + } else { + ifdefstate++; + BEGIN(INITIAL); + } + yyline++; + } + YY_BREAK +case 57: +/* rule 57 can match eol */ +YY_RULE_SETUP +#line 251 "scan.l" +{ + st = ifdefstate % 6; + if (ifdefstate < 0 || st > 3) { + yyerror("mismatched else"); + } + if (!IDS_PARENT_DISABLED && (st == 1)) { + ifdefstate += 3; + BEGIN(INITIAL); + } else { + ifdefstate += 5 - st; + BEGIN(IGNORED); + } + yyline++; + } + YY_BREAK +case 58: +/* rule 58 can match eol */ +YY_RULE_SETUP +#line 266 "scan.l" +{ + if (ifdefstate < 0) { + yyerror("mismatched endif"); + } + if (!IDS_PARENT_DISABLED) { + BEGIN(INITIAL); + } + ifdefstate = (ifdefstate/6) - 1; + yyline++; + } + YY_BREAK +case 59: +/* rule 59 can match eol */ +YY_RULE_SETUP +#line 277 "scan.l" +{ + yyline++; + } + YY_BREAK +case 60: +YY_RULE_SETUP +#line 281 "scan.l" +/* ignore */ + YY_BREAK +case 61: +/* rule 61 can match eol */ +YY_RULE_SETUP +#line 283 "scan.l" +{ + yyline++; + if (getincludepath()) { + include(curinclpath, 0, 0, 1); + } else { + yyerror("bad include path-name"); + } + } + YY_BREAK +case 62: +/* rule 62 can match eol */ +YY_RULE_SETUP +#line 292 "scan.l" +{ + yyline++; + if (getincludepath()) { + include(curinclpath, 0, 1, 1); + } else { + yyerror("bad cinclude path-name"); + } + } + YY_BREAK +case 63: +/* rule 63 can match eol */ +YY_RULE_SETUP +#line 301 "scan.l" +{ + yyline++; + if (!oktopackage) { + yyerror("package not allowed here"); + } else if (getincludepath()) { + package(curinclpath); + } else { + yyerror("bad package path-name"); + } + } + YY_BREAK +case 64: +YY_RULE_SETUP +#line 312 "scan.l" +{ + yylval.str = intern(yytext); + return PATHNAME; + } + YY_BREAK +case 65: +YY_RULE_SETUP +#line 317 "scan.l" +{ + yylval.str = intern(yytext); + return WORD; + } + YY_BREAK +case 66: +YY_RULE_SETUP +#line 322 "scan.l" +{ + yylval.str = intern(""); + return EMPTYSTRING; + } + YY_BREAK +case 67: +/* rule 67 can match eol */ +YY_RULE_SETUP +#line 327 "scan.l" +{ + size_t l = strlen(yytext); + if (l > 1 && yytext[l - 1] == '"') + yytext[l - 1] = '\0'; + + yylval.str = intern(yytext + 1); + return QSTRING; + } + YY_BREAK +case 68: +YY_RULE_SETUP +#line 335 "scan.l" +{ + yylval.num.fmt = 8; + yylval.num.val = strtoll(yytext, NULL, 8); + return NUMBER; + } + YY_BREAK +case 69: +YY_RULE_SETUP +#line 340 "scan.l" +{ + yylval.num.fmt = 16; + yylval.num.val = (long long)strtoull(yytext + 2, NULL, 16); + return NUMBER; + } + YY_BREAK +case 70: +YY_RULE_SETUP +#line 345 "scan.l" +{ + yylval.num.fmt = 10; + yylval.num.val = strtoll(yytext, NULL, 10); + return NUMBER; + } + YY_BREAK +case 71: +/* rule 71 can match eol */ +YY_RULE_SETUP +#line 350 "scan.l" +{ + /* + * Note: newline followed by whitespace is always a + * continuation of the previous line, so do NOT + * return a token in this case. + */ + yyline++; + } + YY_BREAK +case 72: +/* rule 72 can match eol */ +YY_RULE_SETUP +#line 358 "scan.l" +{ + yyline++; + return '\n'; + } + YY_BREAK +case 73: +YY_RULE_SETUP +#line 362 "scan.l" +{ + /* Detect NUL characters in the config file and + * error out. + */ + cfgerror("NUL character detected at line %i", yyline); + } + YY_BREAK +case 74: +YY_RULE_SETUP +#line 368 "scan.l" +{ /* ignored (comment) */; } + YY_BREAK +case 75: +YY_RULE_SETUP +#line 369 "scan.l" +{ /* ignored (white space) */; } + YY_BREAK +case 76: +YY_RULE_SETUP +#line 370 "scan.l" +{ return yytext[0]; } + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(IGNORED): +#line 371 "scan.l" +{ + if (ifdefstate > (incl == NULL ? -1 : incl->in_ifdefstate)) { + yyerror("reached EOF while looking for endif"); + } + if (incl == NULL) + return YY_NULL; + tok = endinclude(); + if (tok) + return tok; + /* otherwise continue scanning */ + } + YY_BREAK +case 77: +YY_RULE_SETUP +#line 383 "scan.l" +ECHO; + YY_BREAK +#line 1876 "scan.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register yy_size_t number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (yy_size_t)(((yy_c_buf_p) - (yytext_ptr)) - 1); + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 43); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 437 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 43; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 437 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 436); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + yy_size_t offset = (yy_size_t) + ((yy_c_buf_p) - (yytext_ptr)); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = (yy_size_t)size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + yy_size_t i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +yy_size_t yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param _line_number + * + */ +void yyset_lineno (int _line_number ) +{ + + yylineno = _line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str ) +{ + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str ) +{ + yyout = _out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int _bdebug ) +{ + yy_flex_debug = _bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 383 "scan.l" + + + +int interesting = 1; + +static int +curdir_push(const char *fname) +{ + struct prefix *pf; + char *p, *d, *f; + + /* Set up the initial "current directory" for include directives. */ + d = dirname(f = estrdup(fname)); + if (*d == '/') + p = estrdup(d); + else { + char *cwd, buf[PATH_MAX]; + + if ((cwd = getcwd(buf, sizeof(buf))) == NULL) { + free(f); + return (-1); + } + easprintf(&p, "%s/%s", cwd, d); + } + free(f); + pf = ecalloc(1, sizeof(*pf)); + pf->pf_prefix = p; + SLIST_INSERT_HEAD(&curdirs, pf, pf_next); + + return (0); +} + +static void +curdir_pop(void) +{ + struct prefix *pf; + + pf = SLIST_FIRST(&curdirs); + SLIST_REMOVE_HEAD(&curdirs, pf_next); + if (SLIST_EMPTY(&curdirs)) + panic("curdirs is empty"); + /* LINTED cast away const (pf_prefix is malloc'd for curdirs) */ + free((void *)__UNCONST(pf->pf_prefix)); + free(pf); +} + +/* + * Open the "main" file (conffile). + */ +int +firstfile(const char *fname) +{ + +#if defined(__NetBSD__) + if ((yyin = fopen(fname, "rf")) == NULL) +#else + if ((yyin = fopen(fname, "r")) == NULL) +#endif + return (-1); + + if (curdir_push(fname) == -1) + return (-1); + + yyfile = conffile = fname; + yyline = 1; + return (0); +} + +/* + * Add a "package" to the configuration. This is essentially + * syntactic sugar around the sequence: + * + * prefix ../some/directory + * include "files.package" + * prefix + */ +void +package(const char *fname) +{ + char *fname1 = estrdup(fname); + char *fname2 = estrdup(fname); + char *dir = dirname(fname1); + char *file = basename(fname2); + + /* + * Push the prefix on to the prefix stack and process the include + * file. When we reach the end of the include file, inserting + * the PREFIX token into the input stream will pop the prefix off + * of the prefix stack. + */ + prefix_push(dir); + (void) include(file, PREFIX, 0, 1); + + free(fname1); + free(fname2); +} + +int includedepth; + +/* + * Open the named file for inclusion at the current point. Returns 0 on + * success (file opened and previous state pushed), nonzero on failure + * (fopen failed, complaint made). The `ateof' parameter controls the + * token to be inserted at the end of the include file (i.e. ENDFILE). + * If ateof == 0 then nothing is inserted. + */ +int +include(const char *fname, int ateof, int conditional, int direct) +{ + FILE *fp; + struct incl *in; + char *s; + static int havedirs; + extern int vflag; + + if (havedirs == 0) { + havedirs = 1; + setupdirs(); + } + + if (fname[0] == '/') + s = estrdup(fname); + else if (fname[0] == '.' && fname[1] == '/') { + struct prefix *pf = SLIST_FIRST(&curdirs); + easprintf(&s, "%s/%s", pf->pf_prefix, fname + 2); + } else + s = sourcepath(fname); + if ((fp = fopen(s, "r")) == NULL) { + if (conditional == 0) + cfgerror("cannot open %s for reading: %s", s, + strerror(errno)); + else if (vflag) + cfgwarn("cannot open conditional include file %s: %s", + s, strerror(errno)); + free(s); + return (-1); + } + if (curdir_push(s) == -1) { + cfgerror("cannot record current working directory for %s", s); + fclose(fp); + free(s); + return (-1); + } + in = ecalloc(1, sizeof *in); + in->in_prev = incl; + in->in_buf = YY_CURRENT_BUFFER; + in->in_fname = yyfile; + in->in_lineno = yyline; + in->in_ateof = ateof; + in->in_interesting = interesting; + in->in_ifdefstate = ifdefstate; + interesting = direct & interesting; + 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; + free(s); + includedepth++; + return (0); +} + +/* + * Extract the pathname from a include/cinclude/package into curinclpath + */ +static int +getincludepath(void) +{ + const char *p = yytext; + ptrdiff_t len; + const char *e; + + while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p)) + p++; + while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p)) + p++; + if (!*p) + return 0; + if (*p == '"') { + p++; + e = strchr(p, '"'); + if (!e) return 0; + } else { + e = p; + while (*e && isascii((unsigned int)*e) + && !isspace((unsigned int)*e)) + e++; + } + + len = e-p; + if (len > (ptrdiff_t)sizeof(curinclpath)-1) + len = sizeof(curinclpath)-1; + strncpy(curinclpath, p, sizeof(curinclpath)); + curinclpath[len] = '\0'; + + return 1; +} + +/* + * Terminate the most recent inclusion. + */ +static int +endinclude(void) +{ + struct incl *in; + int ateof; + + curdir_pop(); + if ((in = incl) == NULL) + panic("endinclude"); + incl = in->in_prev; + lastfile = yyfile; + yy_delete_buffer(YY_CURRENT_BUFFER); + (void)fclose(yyin); + yy_switch_to_buffer(in->in_buf); + yyfile = in->in_fname; + yyline = in->in_lineno; + ateof = in->in_ateof; + interesting = in->in_interesting; + free(in); + + includedepth--; + + return (ateof); +} + +/* + * Return the current line number. If yacc has looked ahead and caused + * us to consume a newline, we have to subtract one. yychar is yacc's + * token lookahead, so we can tell. + */ +u_short +currentline(void) +{ + extern int yychar; + + return (u_short)(yyline - (yychar == '\n')); +} + +static int +getcurifdef(void) +{ + char *p = yytext, *q; + + while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p)) + p++; + while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p)) + p++; + q = p; + while (*q && isascii((unsigned int)*q) && !isspace((unsigned int)*q)) + q++; + *q = '\0'; + + return ht_lookup(attrtab, intern(p)) != NULL; +} + diff --git a/usr.bin/config/scan.l b/usr.bin/config/scan.l new file mode 100644 index 000000000..1c4209fe8 --- /dev/null +++ b/usr.bin/config/scan.l @@ -0,0 +1,638 @@ +%{ +/* $NetBSD: scan.l,v 1.25 2015/09/04 10:16:35 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)scan.l 8.1 (Berkeley) 6/6/93 + */ + +#include +__RCSID("$NetBSD: scan.l,v 1.25 2015/09/04 10:16:35 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef ECHO +#include "defs.h" +#include "gram.h" + +int yyline; +const char *yyfile; +const char *lastfile; +char curinclpath[PATH_MAX]; +int ifdefstate = -1; +int st; +#define IDS_PARENT_DISABLED \ + ((ifdefstate > 6) && ((((ifdefstate/6)-1) & 1) == 1)) +#define IDS_MAX_DEPTH 362797056 /* 6^11 */ +/* States for ifdefstate: + + 0 -> matched ifdef + 1 -> unmatched ifdef + 2 -> matched elifdef + 3 -> unmatched elifdef + 4 -> matched else + 5 -> unmatched else + + Upon "ifdef", add one and multiply by 6. + Upon "endif", divide by 6, remove 1. + + ifdef -> MATCH => continue + MISMATCH => set to 1 + elifdef -> if (!1) -> MISMATCH + MATCH => set to 2 + MISMATCH => if (2 || 3) set to 3, else set to 1 + else -> if (1) -> MATCH + MATCH => set to 4 + MISMATCH => set to 5 + + in each case, if parent & 1 == 1, MISMATCH +*/ + +/* + * Data for returning to previous files from include files. + */ +struct incl { + struct incl *in_prev; /* previous includes in effect, if any */ + YY_BUFFER_STATE in_buf; /* previous lex state */ + const char *in_fname; /* previous file name */ + int in_lineno; /* previous line number */ + int in_ateof; /* token to insert at EOF */ + int in_interesting; /* previous value for "interesting" */ + int in_ifdefstate; /* conditional level */ +}; +static struct incl *incl; +static int endinclude(void); +static int getincludepath(void); +static int getcurifdef(void); + + +%} + +%option noyywrap nounput noinput + +PATH [A-Za-z_0-9]*[./][-A-Za-z_0-9./]* +QCHARS \"(\\.|[^\\"])*\" +WORD [A-Za-z_][-A-Za-z_0-9]* +FILENAME ({PATH}|{QCHARS}) +RESTOFLINE [ \t]*(#[^\n]*)?\n + +%x IGNORED + +%% + /* Local variables for yylex() */ + int tok; + +and return AND; +at return AT; +attach return ATTACH; +block return BLOCK; +build return BUILD; +char return CHAR; +compile-with return COMPILE_WITH; +config return CONFIG; +deffs return DEFFS; +define return DEFINE; +defflag return DEFFLAG; +defopt return DEFOPT; +defparam return DEFPARAM; +defpseudo return DEFPSEUDO; +defpseudodev return DEFPSEUDODEV; +devclass return DEVCLASS; +device return DEVICE; +device-major return DEVICE_MAJOR; +dumps return DUMPS; +file return XFILE; +file-system return FILE_SYSTEM; +flags return FLAGS; +ident return IDENT; +ioconf return IOCONF; +linkzero return LINKZERO; +machine return XMACHINE; +major return MAJOR; +makeoptions return MAKEOPTIONS; +maxpartitions return MAXPARTITIONS; +maxusers return MAXUSERS; +minor return MINOR; +needs-count return NEEDS_COUNT; +needs-flag return NEEDS_FLAG; +no return NO; +object return XOBJECT; +obsolete return OBSOLETE; +on return ON; +options return OPTIONS; +prefix return PREFIX; +buildprefix return BUILDPREFIX; +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; +vector return VECTOR; +version return VERSION; +with return WITH; + +\+= return PLUSEQ; +:= return COLONEQ; + +<*>ifdef[ \t]+{WORD}{RESTOFLINE} { + ifdefstate = (ifdefstate + 1) * 6; + if (ifdefstate >= IDS_MAX_DEPTH) { + yyerror("too many levels of conditional"); + } + if (!IDS_PARENT_DISABLED && getcurifdef()) { + BEGIN(INITIAL); + } else { + ifdefstate++; + BEGIN(IGNORED); + } + yyline++; + } + +<*>ifndef[ \t]+{WORD}{RESTOFLINE} { + ifdefstate = (ifdefstate + 1) * 6; + if (ifdefstate >= IDS_MAX_DEPTH) { + yyerror("too many levels of conditional"); + } + if (!IDS_PARENT_DISABLED && !getcurifdef()) { + BEGIN(INITIAL); + } else { + ifdefstate++; + BEGIN(IGNORED); + } + yyline++; + } + + +<*>elifdef[ \t]+{WORD}{RESTOFLINE} { + st = ifdefstate % 6; + if (ifdefstate < 0 || st > 3) { + yyerror("mismatched elifdef"); + } + if (IDS_PARENT_DISABLED || + st != 1 || !getcurifdef()) { + if (st == 2 || st == 3) { + ifdefstate += 3 - st; + } else { + ifdefstate += 1 - st; + } + BEGIN(IGNORED); + } else { + ifdefstate++; + BEGIN(INITIAL); + } + yyline++; + } + +<*>elifndef[ \t]+{WORD}{RESTOFLINE} { + st = ifdefstate % 6; + if (ifdefstate < 0 || st > 3) { + yyerror("mismatched elifndef"); + } + if (IDS_PARENT_DISABLED || + st != 1 || getcurifdef()) { + if (st == 2 || st == 3) { + ifdefstate += 3 - st; + } else { + ifdefstate += 1 - st; + } + BEGIN(IGNORED); + } else { + ifdefstate++; + BEGIN(INITIAL); + } + yyline++; + } + +<*>else{RESTOFLINE} { + st = ifdefstate % 6; + if (ifdefstate < 0 || st > 3) { + yyerror("mismatched else"); + } + if (!IDS_PARENT_DISABLED && (st == 1)) { + ifdefstate += 3; + BEGIN(INITIAL); + } else { + ifdefstate += 5 - st; + BEGIN(IGNORED); + } + yyline++; + } + +<*>endif{RESTOFLINE} { + if (ifdefstate < 0) { + yyerror("mismatched endif"); + } + if (!IDS_PARENT_DISABLED) { + BEGIN(INITIAL); + } + ifdefstate = (ifdefstate/6) - 1; + yyline++; + } + +\n { + yyline++; + } + +. /* ignore */ + +include[ \t]+{FILENAME}{RESTOFLINE} { + yyline++; + if (getincludepath()) { + include(curinclpath, 0, 0, 1); + } else { + yyerror("bad include path-name"); + } + } + +cinclude[ \t]+{FILENAME}{RESTOFLINE} { + yyline++; + if (getincludepath()) { + include(curinclpath, 0, 1, 1); + } else { + yyerror("bad cinclude path-name"); + } + } + +package[ \t]+{FILENAME}{RESTOFLINE} { + yyline++; + if (!oktopackage) { + yyerror("package not allowed here"); + } else if (getincludepath()) { + package(curinclpath); + } else { + yyerror("bad package path-name"); + } + } + +{PATH} { + yylval.str = intern(yytext); + return PATHNAME; + } + +{WORD} { + yylval.str = intern(yytext); + return WORD; + } + +\"\" { + yylval.str = intern(""); + return EMPTYSTRING; + } + +{QCHARS} { + size_t l = strlen(yytext); + if (l > 1 && yytext[l - 1] == '"') + yytext[l - 1] = '\0'; + + yylval.str = intern(yytext + 1); + return QSTRING; + } +0[0-7]* { + yylval.num.fmt = 8; + yylval.num.val = strtoll(yytext, NULL, 8); + return NUMBER; + } +0[xX][0-9a-fA-F]+ { + yylval.num.fmt = 16; + yylval.num.val = (long long)strtoull(yytext + 2, NULL, 16); + return NUMBER; + } +[1-9][0-9]* { + yylval.num.fmt = 10; + yylval.num.val = strtoll(yytext, NULL, 10); + return NUMBER; + } +\n[ \t] { + /* + * Note: newline followed by whitespace is always a + * continuation of the previous line, so do NOT + * return a token in this case. + */ + yyline++; + } +\n { + yyline++; + return '\n'; + } +\00 { + /* Detect NUL characters in the config file and + * error out. + */ + cfgerror("NUL character detected at line %i", yyline); + } +#.* { /* ignored (comment) */; } +[ \t]+ { /* ignored (white space) */; } +. { return yytext[0]; } +<*><> { + if (ifdefstate > (incl == NULL ? -1 : incl->in_ifdefstate)) { + yyerror("reached EOF while looking for endif"); + } + if (incl == NULL) + return YY_NULL; + tok = endinclude(); + if (tok) + return tok; + /* otherwise continue scanning */ + } + +%% + +int interesting = 1; + +static int +curdir_push(const char *fname) +{ + struct prefix *pf; + char *p, *d, *f; + + /* Set up the initial "current directory" for include directives. */ + d = dirname(f = estrdup(fname)); + if (*d == '/') + p = estrdup(d); + else { + char *cwd, buf[PATH_MAX]; + + if ((cwd = getcwd(buf, sizeof(buf))) == NULL) { + free(f); + return (-1); + } + easprintf(&p, "%s/%s", cwd, d); + } + free(f); + pf = ecalloc(1, sizeof(*pf)); + pf->pf_prefix = p; + SLIST_INSERT_HEAD(&curdirs, pf, pf_next); + + return (0); +} + +static void +curdir_pop(void) +{ + struct prefix *pf; + + pf = SLIST_FIRST(&curdirs); + SLIST_REMOVE_HEAD(&curdirs, pf_next); + if (SLIST_EMPTY(&curdirs)) + panic("curdirs is empty"); + /* LINTED cast away const (pf_prefix is malloc'd for curdirs) */ + free((void *)__UNCONST(pf->pf_prefix)); + free(pf); +} + +/* + * Open the "main" file (conffile). + */ +int +firstfile(const char *fname) +{ + +#if defined(__NetBSD__) + if ((yyin = fopen(fname, "rf")) == NULL) +#else + if ((yyin = fopen(fname, "r")) == NULL) +#endif + return (-1); + + if (curdir_push(fname) == -1) + return (-1); + + yyfile = conffile = fname; + yyline = 1; + return (0); +} + +/* + * Add a "package" to the configuration. This is essentially + * syntactic sugar around the sequence: + * + * prefix ../some/directory + * include "files.package" + * prefix + */ +void +package(const char *fname) +{ + char *fname1 = estrdup(fname); + char *fname2 = estrdup(fname); + char *dir = dirname(fname1); + char *file = basename(fname2); + + /* + * Push the prefix on to the prefix stack and process the include + * file. When we reach the end of the include file, inserting + * the PREFIX token into the input stream will pop the prefix off + * of the prefix stack. + */ + prefix_push(dir); + (void) include(file, PREFIX, 0, 1); + + free(fname1); + free(fname2); +} + +int includedepth; + +/* + * Open the named file for inclusion at the current point. Returns 0 on + * success (file opened and previous state pushed), nonzero on failure + * (fopen failed, complaint made). The `ateof' parameter controls the + * token to be inserted at the end of the include file (i.e. ENDFILE). + * If ateof == 0 then nothing is inserted. + */ +int +include(const char *fname, int ateof, int conditional, int direct) +{ + FILE *fp; + struct incl *in; + char *s; + static int havedirs; + extern int vflag; + + if (havedirs == 0) { + havedirs = 1; + setupdirs(); + } + + if (fname[0] == '/') + s = estrdup(fname); + else if (fname[0] == '.' && fname[1] == '/') { + struct prefix *pf = SLIST_FIRST(&curdirs); + easprintf(&s, "%s/%s", pf->pf_prefix, fname + 2); + } else + s = sourcepath(fname); + if ((fp = fopen(s, "r")) == NULL) { + if (conditional == 0) + cfgerror("cannot open %s for reading: %s", s, + strerror(errno)); + else if (vflag) + cfgwarn("cannot open conditional include file %s: %s", + s, strerror(errno)); + free(s); + return (-1); + } + if (curdir_push(s) == -1) { + cfgerror("cannot record current working directory for %s", s); + fclose(fp); + free(s); + return (-1); + } + in = ecalloc(1, sizeof *in); + in->in_prev = incl; + in->in_buf = YY_CURRENT_BUFFER; + in->in_fname = yyfile; + in->in_lineno = yyline; + in->in_ateof = ateof; + in->in_interesting = interesting; + in->in_ifdefstate = ifdefstate; + interesting = direct & interesting; + 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; + free(s); + includedepth++; + return (0); +} + +/* + * Extract the pathname from a include/cinclude/package into curinclpath + */ +static int +getincludepath(void) +{ + const char *p = yytext; + ptrdiff_t len; + const char *e; + + while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p)) + p++; + while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p)) + p++; + if (!*p) + return 0; + if (*p == '"') { + p++; + e = strchr(p, '"'); + if (!e) return 0; + } else { + e = p; + while (*e && isascii((unsigned int)*e) + && !isspace((unsigned int)*e)) + e++; + } + + len = e-p; + if (len > (ptrdiff_t)sizeof(curinclpath)-1) + len = sizeof(curinclpath)-1; + strncpy(curinclpath, p, sizeof(curinclpath)); + curinclpath[len] = '\0'; + + return 1; +} + +/* + * Terminate the most recent inclusion. + */ +static int +endinclude(void) +{ + struct incl *in; + int ateof; + + curdir_pop(); + if ((in = incl) == NULL) + panic("endinclude"); + incl = in->in_prev; + lastfile = yyfile; + yy_delete_buffer(YY_CURRENT_BUFFER); + (void)fclose(yyin); + yy_switch_to_buffer(in->in_buf); + yyfile = in->in_fname; + yyline = in->in_lineno; + ateof = in->in_ateof; + interesting = in->in_interesting; + free(in); + + includedepth--; + + return (ateof); +} + +/* + * Return the current line number. If yacc has looked ahead and caused + * us to consume a newline, we have to subtract one. yychar is yacc's + * token lookahead, so we can tell. + */ +u_short +currentline(void) +{ + extern int yychar; + + return (u_short)(yyline - (yychar == '\n')); +} + +static int +getcurifdef(void) +{ + char *p = yytext, *q; + + while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p)) + p++; + while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p)) + p++; + q = p; + while (*q && isascii((unsigned int)*q) && !isspace((unsigned int)*q)) + q++; + *q = '\0'; + + return ht_lookup(attrtab, intern(p)) != NULL; +} diff --git a/usr.bin/config/sem.c b/usr.bin/config/sem.c new file mode 100644 index 000000000..d3697748b --- /dev/null +++ b/usr.bin/config/sem.c @@ -0,0 +1,2177 @@ +/* $NetBSD: sem.c,v 1.73 2015/08/29 07:24:49 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)sem.c 8.1 (Berkeley) 6/6/93 + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: sem.c,v 1.73 2015/08/29 07:24:49 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include "defs.h" +#include "sem.h" + +/* + * config semantics. + */ + +#define NAMESIZE 100 /* local name buffers */ + +const char *s_ifnet; /* magic attribute */ +const char *s_qmark; +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; +static struct deva errdeva; + +static int has_errobj(struct attrlist *, struct attr *); +static struct nvlist *addtoattr(struct nvlist *, struct devbase *); +static int resolve(struct nvlist **, const char *, const char *, + struct nvlist *, int); +static struct pspec *getpspec(struct attr *, struct devbase *, int); +static struct devi *newdevi(const char *, int, struct devbase *d); +static struct devi *getdevi(const char *); +static void remove_devi(struct devi *); +static const char *concat(const char *, int); +static char *extend(char *, const char *); +static int split(const char *, size_t, char *, size_t, int *); +static void selectbase(struct devbase *, struct deva *); +static const char **fixloc(const char *, struct attr *, struct loclist *); +static const char *makedevstr(devmajor_t, devminor_t); +static const char *major2name(devmajor_t); +static devmajor_t dev2major(struct devbase *); + +extern const char *yyfile; +extern int vflag; + +void +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); + + TAILQ_INIT(&alldevas); + + TAILQ_INIT(&allpspecs); + + cfhashtab = ht_new(); + TAILQ_INIT(&allcf); + + TAILQ_INIT(&alldevi); + errdev.d_name = ""; + + TAILQ_INIT(&allpseudo); + + TAILQ_INIT(&alldevms); + + s_ifnet = intern("ifnet"); + s_qmark = intern("?"); + s_none = intern("none"); +} + +/* 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, + "%s: device `%s' used but not defined\n", + lastfile, dev->d_name); + errors++; + continue; + } + fixdev(dev); + } + if (errors) { + (void)fprintf(stderr, "*** Stop.\n"); + exit(1); + } +} + +void +setdefmaxusers(int min, int def, int max) +{ + + if (min < 1 || min > def || def > max) + cfgerror("maxusers must have 1 <= min (%d) <= default (%d) " + "<= max (%d)", min, def, max); + else { + minmaxusers = min; + defmaxusers = def; + maxmaxusers = max; + } +} + +void +setmaxusers(int n) +{ + + if (maxusers == n) { + cfgerror("duplicate maxusers parameter"); + return; + } + if (vflag && maxusers != 0) + cfgwarn("warning: maxusers already defined"); + maxusers = n; + if (n < minmaxusers) { + cfgerror("warning: minimum of %d maxusers assumed", + minmaxusers); + errors--; /* take it away */ + maxusers = minmaxusers; + } else if (n > maxmaxusers) { + cfgerror("warning: maxusers (%d) > %d", n, maxmaxusers); + errors--; + } +} + +void +setident(const char *i) +{ + + if (i) + ident = intern(i); + else + ident = NULL; +} + +/* + * Define an attribute, optionally with an interface (a locator list) + * and a set of attribute-dependencies. + * + * Attribute dependencies MAY NOT be interface attributes. + * + * 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; + + /* + * If this attribute depends on any others, make sure none of + * the dependencies are interface attributes. + */ + for (al = deps; al != NULL; al = al->al_next) { + dep = al->al_this; + if (dep->a_iattr) { + cfgerror("`%s' dependency `%s' is an interface " + "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); + } + + if (getrefattr(name, &a)) { + cfgerror("attribute `%s' already defined", name); + loclist_destroy(locs); + return (1); + } + if (a == NULL) + a = mkattr(name); + + 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; + } + a->a_name = name; + TAILQ_INIT(&a->a_files); + CFGDBG(3, "attr `%s' allocated", name); + + 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; + if (deps) + CFGDBG(2, "attr `%s' iface with deps", a->a_name); + return (0); +} + +/* "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); +} + +/* + * Return true if the given `error object' is embedded in the given + * pointer list. + */ +static int +has_errobj(struct attrlist *al, struct attr *obj) +{ + + for (; al != NULL; al = al->al_next) + if (al->al_this == obj) + return (1); + return (0); +} + +/* + * Return true if the given attribute is embedded in the given + * pointer list. + */ +int +has_attr(struct attrlist *al, const char *attr) +{ + struct attr *a; + + if ((a = getattr(attr)) == NULL) + return (0); + + for (; al != NULL; al = al->al_next) + if (al->al_this == a) + return (1); + return (0); +} + +/* + * Add a device base to a list in an attribute (actually, to any list). + * Note that this does not check for duplicates, and does reverse the + * list order, but no one cares anyway. + */ +static struct nvlist * +addtoattr(struct nvlist *l, struct devbase *dev) +{ + struct nvlist *n; + + n = newnv(NULL, NULL, dev, 0, l); + return (n); +} + +/* + * Define a device. This may (or may not) also define an interface + * attribute and/or refer to existing attributes. + */ +void +defdev(struct devbase *dev, struct loclist *loclist, struct attrlist *attrs, + int ispseudo) +{ + struct loclist *ll; + struct attrlist *al; + + if (dev == &errdev) + goto bad; + if (dev->d_isdef) { + cfgerror("redefinition of `%s'", dev->d_name); + goto bad; + } + + dev->d_isdef = 1; + if (has_errobj(attrs, &errattr)) + goto bad; + + /* + * Handle implicit attribute definition from locator list. Do + * this before scanning the `at' list so that we can have, e.g.: + * device foo at other, foo { slot = -1 } + * (where you can plug in a foo-bus extender to a foo-bus). + */ + if (loclist != NULL) { + ll = loclist; + loclist = NULL; /* defattr disposes of them for us */ + 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 */ + /* attrs->al_name = dev->d_name; */ + } + + /* + * Pseudo-devices can have children. Consider them as + * attaching at root. + */ + if (ispseudo) { + for (al = attrs; al != NULL; al = al->al_next) + if (al->al_this->a_iattr) + break; + if (al != NULL) { + if (ispseudo < 2) { + if (version >= 20080610) + cfgerror("interface attribute on " + "non-device pseudo `%s'", dev->d_name); + else { + ispseudo = 2; + } + } + ht_insert(devroottab, dev->d_name, dev); + } + } + + /* Committed! Set up fields. */ + 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 + * device to its reference list. This makes, e.g., finding all + * "scsi"s easier. + * + * While looking through the attributes, set up the device + * class if any are devclass attributes (and error out if the + * device has two classes). + */ + for (al = attrs; al != NULL; al = al->al_next) { + /* + * 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: + loclist_destroy(loclist); + attrlist_destroyall(attrs); +} + +/* + * Look up a devbase. Also makes sure it is a reasonable name, + * i.e., does not end in a digit or contain special characters. + */ +struct devbase * +getdevbase(const char *name) +{ + const u_char *p; + struct devbase *dev; + + p = (const u_char *)name; + if (!isalpha(*p)) + goto badname; + while (*++p) { + if (!isalnum(*p) && *p != '_') + goto badname; + } + if (isdigit(*--p)) { + badname: + cfgerror("bad device base name `%s'", name); + return (&errdev); + } + dev = ht_lookup(devbasetab, name); + if (dev == NULL) { + dev = ecalloc(1, sizeof *dev); + dev->d_name = name; + dev->d_isdef = 0; + dev->d_major = NODEVMAJOR; + dev->d_attrs = NULL; + dev->d_ihead = NULL; + dev->d_ipp = &dev->d_ihead; + dev->d_ahead = NULL; + dev->d_app = &dev->d_ahead; + dev->d_umax = 0; + 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); +} + +/* + * Define some of a device's allowable parent attachments. + * There may be a list of (plain) attributes. + */ +void +defdevattach(struct deva *deva, struct devbase *dev, struct nvlist *atlist, + struct attrlist *attrs) +{ + struct nvlist *nv; + struct attrlist *al; + struct attr *a; + struct deva *da; + + if (dev == &errdev) + goto bad; + if (deva == NULL) + deva = getdevattach(dev->d_name); + if (deva == &errdeva) + goto bad; + if (!dev->d_isdef) { + cfgerror("attaching undefined device `%s'", dev->d_name); + goto bad; + } + if (deva->d_isdef) { + cfgerror("redefinition of `%s'", deva->d_name); + goto bad; + } + if (dev->d_ispseudo) { + cfgerror("pseudo-devices can't attach"); + goto bad; + } + + deva->d_isdef = 1; + if (has_errobj(attrs, &errattr)) + goto bad; + for (al = attrs; al != NULL; al = al->al_next) { + a = al->al_this; + if (a == &errattr) + continue; /* already complained */ + if (a->a_iattr || a->a_devclass != NULL) + cfgerror("`%s' is not a plain attribute", a->a_name); + } + + /* Committed! Set up fields. */ + 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 + * nv_name to an attribute, or to NULL for root), and add + * this device to those attributes, so that children can + * be listed at this particular device if they are supported + * by that attribute. + */ + for (nv = atlist; nv != NULL; nv = nv->nv_next) { + if (nv->nv_name == NULL) + nv->nv_ptr = a = NULL; /* at root */ + else + nv->nv_ptr = a = getattr(nv->nv_name); + if (a == &errattr) + continue; /* already complained */ + + /* + * Make sure that an attachment spec doesn't + * already say how to attach to this attribute. + */ + for (da = dev->d_ahead; da != NULL; da = da->d_bsame) + if (onlist(da->d_atlist, a)) + cfgerror("attach at `%s' already done by `%s'", + a ? a->a_name : "root", da->d_name); + + if (a == NULL) { + ht_insert(devroottab, dev->d_name, dev); + continue; /* at root; don't add */ + } + if (!a->a_iattr) + cfgerror("%s cannot be at plain attribute `%s'", + dev->d_name, a->a_name); + else + a->a_devs = addtoattr(a->a_devs, dev); + } + + /* attach to parent */ + *dev->d_app = deva; + dev->d_app = &deva->d_bsame; + return; + bad: + nvfreel(atlist); + attrlist_destroyall(attrs); +} + +/* + * Look up a device attachment. Also makes sure it is a reasonable + * name, i.e., does not contain digits or special characters. + */ +struct deva * +getdevattach(const char *name) +{ + const u_char *p; + struct deva *deva; + + p = (const u_char *)name; + if (!isalpha(*p)) + goto badname; + while (*++p) { + if (!isalnum(*p) && *p != '_') + goto badname; + } + if (isdigit(*--p)) { + badname: + cfgerror("bad device attachment name `%s'", name); + return (&errdeva); + } + deva = ht_lookup(devatab, name); + if (deva == NULL) { + deva = ecalloc(1, sizeof *deva); + deva->d_name = name; + deva->d_bsame = NULL; + deva->d_isdef = 0; + deva->d_devbase = NULL; + deva->d_atlist = NULL; + deva->d_attrs = NULL; + deva->d_ihead = NULL; + deva->d_ipp = &deva->d_ihead; + TAILQ_INSERT_TAIL(&alldevas, deva, d_next); + if (ht_insert(devatab, name, deva)) + panic("getdeva(%s)", name); + } + return (deva); +} + +/* + * Look up an attribute. + */ +struct attr * +getattr(const char *name) +{ + struct attr *a; + + if ((a = ht_lookup(attrtab, name)) == NULL) { + cfgerror("undefined attribute `%s'", name); + a = &errattr; + } + 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. + */ +void +expandattr(struct attr *a, void (*callback)(struct attr *)) +{ + struct attrlist *al; + struct attr *dep; + + if (a->a_expanding) { + cfgerror("circular dependency on attribute `%s'", a->a_name); + return; + } + + a->a_expanding = 1; + + /* First expand all of this attribute's dependencies. */ + for (al = a->a_deps; al != NULL; al = al->al_next) { + dep = al->al_this; + expandattr(dep, callback); + } + + /* ...and now invoke the callback for ourself. */ + if (callback != NULL) + (*callback)(a); + + a->a_expanding = 0; +} + +/* + * Set the major device number for a device, so that it can be used + * as a root/dumps "on" device in a configuration. + */ +void +setmajor(struct devbase *d, devmajor_t n) +{ + + if (d != &errdev && d->d_major != NODEVMAJOR) + cfgerror("device `%s' is already major %d", + d->d_name, d->d_major); + else + d->d_major = n; +} + +const char * +major2name(devmajor_t maj) +{ + struct devbase *dev; + struct devm *dm; + + if (!do_devsw) { + TAILQ_FOREACH(dev, &allbases, d_next) { + if (dev->d_major == maj) + return (dev->d_name); + } + } else { + TAILQ_FOREACH(dm, &alldevms, dm_next) { + if (dm->dm_bmajor == maj) + return (dm->dm_name); + } + } + return (NULL); +} + +devmajor_t +dev2major(struct devbase *dev) +{ + struct devm *dm; + + if (!do_devsw) + return (dev->d_major); + + TAILQ_FOREACH(dm, &alldevms, dm_next) { + if (strcmp(dm->dm_name, dev->d_name) == 0) + return (dm->dm_bmajor); + } + return (NODEVMAJOR); +} + +/* + * Make a string description of the device at maj/min. + */ +static const char * +makedevstr(devmajor_t maj, devminor_t min) +{ + const char *devicename; + char buf[32]; + + devicename = major2name(maj); + if (devicename == NULL) + (void)snprintf(buf, sizeof(buf), "<%d/%d>", maj, min); + else + (void)snprintf(buf, sizeof(buf), "%s%d%c", devicename, + min / maxpartitions, (min % maxpartitions) + 'a'); + + return (intern(buf)); +} + +/* + * Map things like "ra0b" => makedev(major("ra"), 0*maxpartitions + 'b'-'a'). + * Handle the case where the device number is given but there is no + * corresponding name, and map NULL to the default. + */ +static int +resolve(struct nvlist **nvp, const char *name, const char *what, + struct nvlist *dflt, int part) +{ + struct nvlist *nv; + struct devbase *dev; + const char *cp; + devmajor_t maj; + devminor_t min; + size_t i, l; + int unit; + char buf[NAMESIZE]; + + if ((part -= 'a') >= maxpartitions || part < 0) + panic("resolve"); + if ((nv = *nvp) == NULL) { + dev_t d = NODEV; + /* + * Apply default. Easiest to do this by number. + * Make sure to retain NODEVness, if this is dflt's disposition. + */ + if ((dev_t)dflt->nv_num != NODEV) { + maj = major(dflt->nv_num); + min = ((minor(dflt->nv_num) / maxpartitions) * + maxpartitions) + part; + d = makedev(maj, min); + cp = makedevstr(maj, min); + } else + cp = NULL; + *nvp = nv = newnv(NULL, cp, NULL, (long long)d, NULL); + } + if ((dev_t)nv->nv_num != NODEV) { + /* + * By the numbers. Find the appropriate major number + * to make a name. + */ + maj = major(nv->nv_num); + min = minor(nv->nv_num); + nv->nv_str = makedevstr(maj, min); + return (0); + } + + if (nv->nv_str == NULL || nv->nv_str == s_qmark) + /* + * Wildcarded or unspecified; leave it as NODEV. + */ + return (0); + + /* + * The normal case: things like "ra2b". Check for partition + * suffix, remove it if there, and split into name ("ra") and + * unit (2). + */ + l = i = strlen(nv->nv_str); + cp = &nv->nv_str[l]; + if (l > 1 && *--cp >= 'a' && *cp < 'a' + maxpartitions && + isdigit((unsigned char)cp[-1])) { + l--; + part = *cp - 'a'; + } + cp = nv->nv_str; + if (split(cp, l, buf, sizeof buf, &unit)) { + cfgerror("%s: invalid %s device name `%s'", name, what, cp); + return (1); + } + dev = ht_lookup(devbasetab, intern(buf)); + if (dev == NULL) { + cfgerror("%s: device `%s' does not exist", name, buf); + return (1); + } + + /* + * Check for the magic network interface attribute, and + * don't bother making a device number. + */ + if (has_attr(dev->d_attrs, s_ifnet)) { + nv->nv_num = (long long)NODEV; + nv->nv_ifunit = unit; /* XXX XXX XXX */ + } else { + maj = dev2major(dev); + if (maj == NODEVMAJOR) { + cfgerror("%s: can't make %s device from `%s'", + name, what, nv->nv_str); + return (1); + } + nv->nv_num = (long long)makedev(maj, unit * maxpartitions + part); + } + + nv->nv_name = dev->d_name; + return (0); +} + +/* + * Add a completed configuration to the list. + */ +void +addconf(struct config *cf0) +{ + struct config *cf; + const char *name; + + name = cf0->cf_name; + cf = ecalloc(1, sizeof *cf); + if (ht_insert(cfhashtab, name, cf)) { + cfgerror("configuration `%s' already defined", name); + free(cf); + goto bad; + } + *cf = *cf0; + + /* + * Resolve the root device. + */ + if (cf->cf_root == NULL) { + cfgerror("%s: no root device specified", name); + goto bad; + } + if (cf->cf_root && cf->cf_root->nv_str != s_qmark) { + struct nvlist *nv; + nv = cf->cf_root; + if (resolve(&cf->cf_root, name, "root", nv, 'a')) + goto bad; + } + + /* + * Resolve the dump device. + */ + if (cf->cf_dump == NULL || cf->cf_dump->nv_str == s_qmark) { + /* + * Wildcarded dump device is equivalent to unspecified. + */ + cf->cf_dump = NULL; + } else if (cf->cf_dump->nv_str == s_none) { + /* + * Operator has requested that no dump device should be + * configured; do nothing. + */ + } else { + if (resolve(&cf->cf_dump, name, "dumps", cf->cf_dump, 'b')) + goto bad; + } + + /* Wildcarded fstype is `unspecified'. */ + if (cf->cf_fstype == s_qmark) + cf->cf_fstype = NULL; + + TAILQ_INSERT_TAIL(&allcf, cf, cf_next); + return; + bad: + nvfreel(cf0->cf_root); + nvfreel(cf0->cf_dump); +} + +void +setconf(struct nvlist **npp, const char *what, struct nvlist *v) +{ + + if (*npp != NULL) { + cfgerror("duplicate %s specification", what); + nvfreel(v); + } else + *npp = v; +} + +void +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; + } + (void)ht_remove(cfhashtab, name); + + TAILQ_FOREACH(cf, &allcf, cf_next) + if (!strcmp(cf->cf_name, name)) + break; + if (cf == NULL) + panic("lost configuration `%s'", name); + + TAILQ_REMOVE(&allcf, cf, cf_next); +} + +void +setfstype(const char **fstp, const char *v) +{ + + if (*fstp != NULL) { + cfgerror("multiple fstype specifications"); + return; + } + + if (v != s_qmark && OPT_FSOPT(v)) { + cfgerror("\"%s\" is not a configured file system", v); + return; + } + + *fstp = v; +} + +static struct devi * +newdevi(const char *name, int unit, struct devbase *d) +{ + struct devi *i; + + i = ecalloc(1, sizeof *i); + i->i_name = name; + i->i_unit = unit; + i->i_base = d; + i->i_bsame = NULL; + i->i_asame = NULL; + i->i_alias = NULL; + i->i_at = NULL; + i->i_pspec = NULL; + i->i_atdeva = NULL; + i->i_locs = NULL; + i->i_cfflags = 0; + i->i_lineno = currentline(); + i->i_srcfile = yyfile; + i->i_active = DEVI_ORPHAN; /* Proper analysis comes later */ + i->i_level = devilevel; + i->i_pseudoroot = 0; + if (unit >= d->d_umax) + d->d_umax = unit + 1; + return (i); +} + +/* + * Add the named device as attaching to the named attribute (or perhaps + * another device instead) plus unit number. + */ +void +adddev(const char *name, const char *at, struct loclist *loclist, int flags) +{ + struct devi *i; /* the new instance */ + struct pspec *p; /* and its pspec */ + struct attr *attr; /* attribute that allows attach */ + struct devbase *ib; /* i->i_base */ + struct devbase *ab; /* not NULL => at another dev */ + struct attrlist *al; + struct deva *iba; /* devbase attachment used */ + const char *cp; + int atunit; + char atbuf[NAMESIZE]; + int hit; + + ab = NULL; + iba = NULL; + if (at == NULL) { + /* "at root" */ + p = NULL; + if ((i = getdevi(name)) == NULL) + goto bad; + /* + * Must warn about i_unit > 0 later, after taking care of + * the STAR cases (we could do non-star's here but why + * bother?). Make sure this device can be at root. + */ + ib = i->i_base; + hit = 0; + for (iba = ib->d_ahead; iba != NULL; iba = iba->d_bsame) + if (onlist(iba->d_atlist, NULL)) { + hit = 1; + break; + } + if (!hit) { + cfgerror("`%s' cannot attach to the root", ib->d_name); + i->i_active = DEVI_BROKEN; + goto bad; + } + attr = &errattr; /* a convenient "empty" attr */ + } else { + if (split(at, strlen(at), atbuf, sizeof atbuf, &atunit)) { + cfgerror("invalid attachment name `%s'", at); + /* (void)getdevi(name); -- ??? */ + goto bad; + } + if ((i = getdevi(name)) == NULL) + goto bad; + ib = i->i_base; + + /* + * Devices can attach to two types of things: Attributes, + * and other devices (which have the appropriate attributes + * to allow attachment). + * + * (1) If we're attached to an attribute, then we don't need + * look at the parent base device to see what attributes + * it has, and make sure that we can attach to them. + * + * (2) If we're attached to a real device (i.e. named in + * the config file), we want to remember that so that + * at cross-check time, if the device we're attached to + * is missing but other devices which also provide the + * attribute are present, we don't get a false "OK." + * + * (3) If the thing we're attached to is an attribute + * but is actually named in the config file, we still + * have to remember its devbase. + */ + cp = intern(atbuf); + + /* Figure out parent's devbase, to satisfy case (3). */ + ab = ht_lookup(devbasetab, cp); + + /* Find out if it's an attribute. */ + attr = ht_lookup(attrtab, cp); + + /* Make sure we're _really_ attached to the attr. Case (1). */ + if (attr != NULL && onlist(attr->a_devs, ib)) + goto findattachment; + + /* + * Else a real device, and not just an attribute. Case (2). + * + * Have to work a bit harder to see whether we have + * something like "tg0 at esp0" (where esp is merely + * not an attribute) or "tg0 at nonesuch0" (where + * nonesuch is not even a device). + */ + if (ab == NULL) { + cfgerror("%s at %s: `%s' unknown", + name, at, atbuf); + i->i_active = DEVI_BROKEN; + goto bad; + } + + /* + * See if the named parent carries an attribute + * that allows it to supervise device ib. + */ + for (al = ab->d_attrs; al != NULL; al = al->al_next) { + attr = al->al_this; + if (onlist(attr->a_devs, ib)) + goto findattachment; + } + cfgerror("`%s' cannot attach to `%s'", ib->d_name, atbuf); + i->i_active = DEVI_BROKEN; + goto bad; + + findattachment: + /* + * Find the parent spec. If a matching one has not yet been + * created, create one. + */ + p = getpspec(attr, ab, atunit); + p->p_devs = newnv(NULL, NULL, i, 0, p->p_devs); + + /* find out which attachment it uses */ + hit = 0; + for (iba = ib->d_ahead; iba != NULL; iba = iba->d_bsame) + if (onlist(iba->d_atlist, attr)) { + hit = 1; + break; + } + if (!hit) + panic("adddev: can't figure out attachment"); + } + if ((i->i_locs = fixloc(name, attr, loclist)) == NULL) { + i->i_active = DEVI_BROKEN; + goto bad; + } + i->i_at = at; + 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; + + /* all done, fall into ... */ + bad: + loclist_destroy(loclist); + return; +} + +void +deldevi(const char *name, const char *at) +{ + struct devi *firsti, *i; + struct devbase *d; + 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; + } + d = ht_lookup(devbasetab, intern(base)); + if (d == NULL) { + cfgerror("%s: unknown device `%s'", name, base); + return; + } + if (d->d_ispseudo) { + cfgerror("%s: %s is a pseudo-device", name, base); + return; + } + if ((firsti = ht_lookup(devitab, name)) == NULL) { + cfgerror("`%s' not defined", name); + return; + } + if (at == NULL && firsti->i_at == NULL) { + /* 'at root' */ + remove_devi(firsti); + return; + } else if (at != NULL) + for (i = firsti; i != NULL; i = i->i_alias) + if (i->i_active != DEVI_BROKEN && + strcmp(at, i->i_at) == 0) { + remove_devi(i); + return; + } + cfgerror("`%s' at `%s' not found", name, at ? at : "root"); +} + +static void +remove_devi(struct devi *i) +{ + struct devbase *d = i->i_base; + 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", + i->i_name); + + if (i->i_active == DEVI_BROKEN) { + cfgerror("not removing broken instance `%s'", i->i_name); + return; + } + + /* + * We have the device instance, i. + * We have to: + * - delete the alias + * + * If the devi was an alias of an already listed devi, all is + * good we don't have to do more. + * If it was the first alias, we have to replace i's entry in + * d's list by its first alias. + * If it was the only entry, we must remove i's entry from d's + * list. + */ + if (i != f) { + for (j = f; j->i_alias != i; j = j->i_alias) + continue; + j->i_alias = i->i_alias; + } else { + if (i->i_alias == NULL) { + /* No alias, must unlink the entry from devitab */ + ht_remove(devitab, i->i_name); + j = i->i_bsame; + } else { + /* Or have the first alias replace i in d's list */ + i->i_alias->i_bsame = i->i_bsame; + j = i->i_alias; + if (i == f) + ht_replace(devitab, i->i_name, i->i_alias); + } + + /* + * - remove/replace the instance from the devbase's list + * + * A double-linked list would make this much easier. Oh, well, + * what is done is done. + */ + for (ppi = &d->d_ihead; + *ppi != NULL && *ppi != i && (*ppi)->i_bsame != i; + 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); + f = *ppi; + if (f == i) + /* That implies d->d_ihead == i */ + *ppi = j; + else + (*ppi)->i_bsame = j; + if (d->d_ipp == &i->i_bsame) { + if (i->i_alias == NULL) { + if (f == i) + d->d_ipp = &d->d_ihead; + else + d->d_ipp = &f->i_bsame; + } else + d->d_ipp = &i->i_alias->i_bsame; + } + } + /* + * - delete the attachment instance + */ + iba = i->i_atdeva; + for (ppi = &iba->d_ihead; + *ppi != NULL && *ppi != i && (*ppi)->i_asame != i; + ppi = &(*ppi)->i_asame) + continue; + if (*ppi == NULL) + panic("deldev: deva (%s) doesn't list the devi (%s)", + iba->d_name, i->i_name); + f = *ppi; + if (f == i) + /* That implies iba->d_ihead == i */ + *ppi = i->i_asame; + else + (*ppi)->i_asame = i->i_asame; + if (iba->d_ipp == &i->i_asame) { + if (f == i) + iba->d_ipp = &iba->d_ihead; + else + iba->d_ipp = &f->i_asame; + } + /* + * - delete the pspec + */ + if (i->i_pspec) { + struct pspec *p = i->i_pspec; + struct nvlist *nv, *onv; + + /* Double-linked nvlist anyone? */ + for (nv = p->p_devs; nv->nv_next != NULL; nv = nv->nv_next) { + if (nv->nv_next && nv->nv_next->nv_ptr == i) { + onv = nv->nv_next; + nv->nv_next = onv->nv_next; + nvfree(onv); + break; + } + if (nv->nv_ptr == i) { + /* nv is p->p_devs in that case */ + p->p_devs = nv->nv_next; + nvfree(nv); + break; + } + } + if (p->p_devs == NULL) + TAILQ_REMOVE(&allpspecs, p, p_list); + } + /* + * - delete the alldevi entry + */ + TAILQ_REMOVE(&alldevi, i, i_next); + ndevi--; + /* + * Put it in deaddevitab + * + * Each time a devi is removed, devilevel is increased so that later on + * it is possible to tell if an instance was added before or after the + * removal of its parent. + * + * For active instances, i_level contains the number of devi removed so + * far, and for dead devis, it contains its index. + */ + i->i_level = devilevel++; + i->i_alias = NULL; + f = ht_lookup(deaddevitab, i->i_name); + if (f == NULL) { + if (ht_insert(deaddevitab, i->i_name, 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) + continue; + j->i_alias = i; + } + /* + * - reconstruct d->d_umax + */ + d->d_umax = 0; + for (i = d->d_ihead; i != NULL; i = i->i_bsame) + if (i->i_unit >= d->d_umax) + d->d_umax = i->i_unit + 1; +} + +void +deldeva(const char *at) +{ + int unit; + const char *cp; + struct devbase *d, *ad; + struct devi *i, *j; + struct attr *a; + struct pspec *p; + struct nvlist *nv, *stack = NULL; + + if (at == NULL) { + TAILQ_FOREACH(i, &alldevi, i_next) + if (i->i_at == NULL) + stack = newnv(NULL, NULL, i, 0, stack); + } else { + 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; + } + cp = intern(base); + } else { + cp = intern(at); + unit = STAR; + } + + ad = ht_lookup(devbasetab, cp); + a = ht_lookup(attrtab, cp); + if (a == NULL) { + cfgerror("unknown attachment attribute or device `%s'", + cp); + return; + } + if (!a->a_iattr) { + cfgerror("plain attribute `%s' cannot have children", + a->a_name); + return; + } + + /* + * remove_devi() makes changes to the devbase's list and the + * alias list, * so the actual deletion of the instances must + * be delayed. + */ + for (nv = a->a_devs; nv != NULL; nv = nv->nv_next) { + d = nv->nv_ptr; + for (i = d->d_ihead; i != NULL; i = i->i_bsame) + for (j = i; j != NULL; j = j->i_alias) { + /* Ignore devices at root */ + if (j->i_at == NULL) + continue; + p = j->i_pspec; + /* + * There are three cases: + * + * 1. unit is not STAR. Consider 'at' + * to be explicit, even if it + * references an interface + * attribute. + * + * 2. unit is STAR and 'at' references + * a real device. Look for pspec + * that have a matching p_atdev + * field. + * + * 3. unit is STAR and 'at' references + * an interface attribute. Look + * for pspec that have a matching + * p_iattr field. + */ + if ((unit != STAR && /* Case */ + !strcmp(j->i_at, at)) || /* 1 */ + (unit == STAR && + ((ad != NULL && /* Case */ + p->p_atdev == ad) || /* 2 */ + (ad == NULL && /* Case */ + p->p_iattr == a)))) /* 3 */ + stack = newnv(NULL, NULL, j, 0, + stack); + } + } + } + + for (nv = stack; nv != NULL; nv = nv->nv_next) + remove_devi(nv->nv_ptr); + nvfreel(stack); +} + +void +deldev(const char *name) +{ + 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; + } + for (i = firsti; i != NULL; i = i->i_alias) + stack = newnv(NULL, NULL, i, 0, stack); + } else { + struct devbase *d = ht_lookup(devbasetab, name); + + if (d == NULL) { + cfgerror("unknown device %s", name); + return; + } + if (d->d_ispseudo) { + cfgerror("%s is a pseudo-device; " + "use \"no pseudo-device %s\" instead", name, + name); + return; + } + + for (firsti = d->d_ihead; firsti != NULL; + firsti = firsti->i_bsame) + for (i = firsti; i != NULL; i = i->i_alias) + stack = newnv(NULL, NULL, i, 0, stack); + } + + for (nv = stack; nv != NULL; nv = nv->nv_next) + remove_devi(nv->nv_ptr); + nvfreel(stack); +} + +/* + * Insert given device "name" into devroottab. In case "name" + * designates a pure interface attribute, create a fake device + * instance for the attribute and insert that into the roottab + * (this scheme avoids mucking around with the orphanage analysis). + */ +void +addpseudoroot(const char *name) +{ + char buf[NAMESIZE]; + int unit; + struct attr *attr; + struct devi *i; + struct deva *iba; + struct devbase *ib; + + if (split(name, strlen(name), buf, sizeof(buf), &unit)) { + cfgerror("invalid pseudo-root name `%s'", name); + return; + } + + /* + * Prefer device because devices with locators define an + * implicit interface attribute. However, if a device is + * not available, try to attach to the interface attribute. + * This makes sure adddev() doesn't get confused when we + * are really attaching to a device (alternatively we maybe + * could specify a non-NULL atlist to defdevattach() below). + */ + ib = ht_lookup(devbasetab, intern(buf)); + if (ib == NULL) { + struct devbase *fakedev; + char fakename[NAMESIZE]; + + attr = ht_lookup(attrtab, intern(buf)); + if (!(attr && attr->a_iattr)) { + cfgerror("pseudo-root `%s' not available", name); + return; + } + + /* + * here we cheat a bit: create a fake devbase with the + * interface attribute and instantiate it. quick, cheap, + * dirty & bad for you, much like the stuff in the fridge. + * and, it works, since the pseudoroot device is not included + * in ioconf, just used by config to make sure we start from + * the right place. + */ + snprintf(fakename, sizeof(fakename), "%s_devattrs", buf); + fakedev = getdevbase(intern(fakename)); + fakedev->d_isdef = 1; + fakedev->d_ispseudo = 0; + fakedev->d_attrs = attrlist_cons(NULL, attr); + defdevattach(NULL, fakedev, NULL, NULL); + + if (unit == STAR) + snprintf(buf, sizeof(buf), "%s*", fakename); + else + snprintf(buf, sizeof(buf), "%s%d", fakename, unit); + name = buf; + } + + /* ok, everything should be set up, so instantiate a fake device */ + i = getdevi(name); + if (i == NULL) + panic("device `%s' expected to be present", name); + ib = i->i_base; + iba = ib->d_ahead; + + i->i_atdeva = iba; + i->i_cfflags = 0; + i->i_locs = fixloc(name, &errattr, NULL); + i->i_pseudoroot = 1; + i->i_active = DEVI_ORPHAN; /* set active by kill_orphans() */ + + *iba->d_ipp = i; + iba->d_ipp = &i->i_asame; + + ht_insert(devroottab, ib->d_name, ib); +} + +void +addpseudo(const char *name, int number) +{ + struct devbase *d; + struct devi *i; + + d = ht_lookup(devbasetab, name); + if (d == NULL) { + cfgerror("undefined pseudo-device %s", name); + return; + } + if (!d->d_ispseudo) { + cfgerror("%s is a real device, not a pseudo-device", name); + return; + } + if (ht_lookup(devitab, name) != NULL) { + cfgerror("`%s' already defined", name); + return; + } + i = newdevi(name, number - 1, d); /* foo 16 => "foo0..foo15" */ + if (ht_insert(devitab, name, i)) + panic("addpseudo(%s)", name); + /* Useful to retrieve the instance from the devbase */ + d->d_ihead = i; + i->i_active = DEVI_ACTIVE; + TAILQ_INSERT_TAIL(&allpseudo, i, i_next); +} + +void +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); + return; + } + if (!d->d_ispseudo) { + cfgerror("%s is a real device, not a pseudo-device", name); + return; + } + if ((i = ht_lookup(devitab, name)) == NULL) { + cfgerror("`%s' not defined", name); + return; + } + d->d_umax = 0; /* clear neads-count entries */ + d->d_ihead = NULL; /* make sure it won't be considered active */ + TAILQ_REMOVE(&allpseudo, i, i_next); + if (ht_remove(devitab, name)) + panic("delpseudo(%s) - can't remove from devitab", name); + if (ht_insert(deaddevitab, name, i)) + panic("delpseudo(%s) - can't add to deaddevitab", name); +} + +void +adddevm(const char *name, devmajor_t cmajor, devmajor_t bmajor, + struct condexpr *cond, struct nvlist *nv_nodes) +{ + struct devm *dm; + + if (cmajor != NODEVMAJOR && (cmajor < 0 || cmajor >= 4096)) { + cfgerror("character major %d is invalid", cmajor); + condexpr_destroy(cond); + nvfreel(nv_nodes); + return; + } + + if (bmajor != NODEVMAJOR && (bmajor < 0 || bmajor >= 4096)) { + cfgerror("block major %d is invalid", bmajor); + condexpr_destroy(cond); + nvfreel(nv_nodes); + return; + } + if (cmajor == NODEVMAJOR && bmajor == NODEVMAJOR) { + cfgerror("both character/block majors are not specified"); + condexpr_destroy(cond); + nvfreel(nv_nodes); + return; + } + + dm = ecalloc(1, sizeof(*dm)); + dm->dm_srcfile = yyfile; + dm->dm_srcline = currentline(); + dm->dm_name = name; + dm->dm_cmajor = cmajor; + dm->dm_bmajor = bmajor; + dm->dm_opts = cond; + dm->dm_devnodes = nv_nodes; + + TAILQ_INSERT_TAIL(&alldevms, dm, dm_next); + + maxcdevm = MAX(maxcdevm, dm->dm_cmajor); + maxbdevm = MAX(maxbdevm, dm->dm_bmajor); +} + +int +fixdevis(void) +{ + struct devi *i; + int error = 0; + + 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) { + /* + * At this point, we can't have instances for which + * i_at or i_pspec are NULL. + */ + ++error; + cfgxerror(i->i_srcfile, i->i_lineno, + "`%s at %s' is orphaned (%s `%s' found)", + i->i_name, i->i_at, i->i_pspec->p_atunit == WILD ? + "nothing matching" : "no", i->i_at); + } else if (vflag && i->i_active == DEVI_IGNORED) + cfgxwarn(i->i_srcfile, i->i_lineno, "ignoring " + "explicitly orphaned instance `%s at %s'", + i->i_name, i->i_at); + } + + if (error) + return error; + + TAILQ_FOREACH(i, &allpseudo, i_next) + if (i->i_active == DEVI_ACTIVE) + selectbase(i->i_base, NULL); + return 0; +} + +/* + * Look up a parent spec, creating a new one if it does not exist. + */ +static struct pspec * +getpspec(struct attr *attr, struct devbase *ab, int atunit) +{ + struct pspec *p; + + TAILQ_FOREACH(p, &allpspecs, p_list) { + if (p->p_iattr == attr && + p->p_atdev == ab && + p->p_atunit == atunit) + return (p); + } + + p = ecalloc(1, sizeof(*p)); + + p->p_iattr = attr; + p->p_atdev = ab; + p->p_atunit = atunit; + p->p_inst = npspecs++; + p->p_active = 0; + + TAILQ_INSERT_TAIL(&allpspecs, p, p_list); + + return (p); +} + +/* + * Define a new instance of a specific device. + */ +static struct devi * +getdevi(const char *name) +{ + struct devi *i, *firsti; + struct devbase *d; + int unit; + char base[NAMESIZE]; + + if (split(name, strlen(name), base, sizeof base, &unit)) { + cfgerror("invalid device name `%s'", name); + return (NULL); + } + d = ht_lookup(devbasetab, intern(base)); + if (d == NULL) { + cfgerror("%s: unknown device `%s'", name, base); + return (NULL); + } + if (d->d_ispseudo) { + cfgerror("%s: %s is a pseudo-device", name, base); + return (NULL); + } + firsti = ht_lookup(devitab, name); + i = newdevi(name, unit, d); + if (firsti == NULL) { + if (ht_insert(devitab, name, i)) + panic("getdevi(%s)", name); + *d->d_ipp = i; + d->d_ipp = &i->i_bsame; + } else { + while (firsti->i_alias) + firsti = firsti->i_alias; + firsti->i_alias = i; + } + TAILQ_INSERT_TAIL(&alldevi, i, i_next); + ndevi++; + return (i); +} + +static const char * +concat(const char *name, int c) +{ + size_t len; + char buf[NAMESIZE]; + + len = strlen(name); + if (len + 2 > sizeof(buf)) { + cfgerror("device name `%s%c' too long", name, c); + len = sizeof(buf) - 2; + } + memmove(buf, name, len); + buf[len] = (char)c; + buf[len + 1] = '\0'; + return (intern(buf)); +} + +const char * +starref(const char *name) +{ + + return (concat(name, '*')); +} + +const char * +wildref(const char *name) +{ + + return (concat(name, '?')); +} + +/* + * Split a name like "foo0" into base name (foo) and unit number (0). + * Return 0 on success. To make this useful for names like "foo0a", + * the length of the "foo0" part is one of the arguments. + */ +static int +split(const char *name, size_t nlen, char *base, size_t bsize, int *aunit) +{ + const char *cp; + int c; + size_t l; + + l = nlen; + if (l < 2 || l >= bsize || isdigit((unsigned char)*name)) + return (1); + c = (u_char)name[--l]; + if (!isdigit(c)) { + if (c == '*') + *aunit = STAR; + else if (c == '?') + *aunit = WILD; + else + return (1); + } else { + cp = &name[l]; + while (isdigit((unsigned char)cp[-1])) + l--, cp--; + *aunit = atoi(cp); + } + memmove(base, name, l); + base[l] = 0; + 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; + + 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); +} + +/* + * We have an instance of the base foo, so select it and all its + * attributes for "optional foo". + */ +static void +selectbase(struct devbase *d, struct deva *da) +{ + struct attr *a; + 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); +} + +/* + * Is the given pointer on the given list of pointers? + */ +int +onlist(struct nvlist *nv, void *ptr) +{ + for (; nv != NULL; nv = nv->nv_next) + if (nv->nv_ptr == ptr) + return (1); + return (0); +} + +static char * +extend(char *p, const char *name) +{ + size_t l; + + l = strlen(name); + memmove(p, name, l); + p += l; + *p++ = ','; + *p++ = ' '; + return (p); +} + +/* + * Check that we got all required locators, and default any that are + * given as "?" and have defaults. Return 0 on success. + */ +static const char ** +fixloc(const char *name, struct attr *attr, struct loclist *got) +{ + struct loclist *m, *n; + int ord; + const char **lp; + int nmissing, nextra, nnodefault; + char *mp, *ep, *ndp; + char missing[1000], extra[1000], nodefault[1000]; + static const char *nullvec[1]; + + /* + * Look for all required locators, and number the given ones + * according to the required order. While we are numbering, + * set default values for defaulted locators. + */ + if (attr->a_loclen == 0) /* e.g., "at root" */ + lp = nullvec; + else + 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; + mp = missing; + /* yes, this is O(mn), but m and n should be small */ + for (ord = 0, m = attr->a_locs; m != NULL; m = m->ll_next, ord++) { + for (n = got; n != NULL; n = n->ll_next) { + if (n->ll_name == m->ll_name) { + n->ll_num = ord; + break; + } + } + if (n == NULL && m->ll_num == 0) { + nmissing++; + mp = extend(mp, m->ll_name); + } + lp[ord] = m->ll_string; + } + if (ord != attr->a_loclen) + panic("fixloc"); + lp[ord] = NULL; + nextra = 0; + ep = extra; + nnodefault = 0; + ndp = nodefault; + for (n = got; n != NULL; n = n->ll_next) { + if (n->ll_num >= 0) { + if (n->ll_string != NULL) + lp[n->ll_num] = n->ll_string; + else if (lp[n->ll_num] == NULL) { + nnodefault++; + ndp = extend(ndp, n->ll_name); + } + } else { + nextra++; + ep = extend(ep, n->ll_name); + } + } + if (nextra) { + ep[-2] = 0; /* kill ", " */ + cfgerror("%s: extraneous locator%s: %s", + name, nextra > 1 ? "s" : "", extra); + } + if (nmissing) { + mp[-2] = 0; + cfgerror("%s: must specify %s", name, missing); + } + if (nnodefault) { + ndp[-2] = 0; + cfgerror("%s: cannot wildcard %s", name, nodefault); + } + if (nmissing || nnodefault) { + free(lp); + lp = NULL; + } + return (lp); +} + +void +setversion(int newver) +{ + if (newver > CONFIG_VERSION) + cfgerror("your sources require a newer version of config(1) " + "-- please rebuild it."); + else if (newver < CONFIG_MINVERSION) + cfgerror("your sources are out of date -- please update."); + else + version = newver; +} diff --git a/usr.bin/config/sem.h b/usr.bin/config/sem.h new file mode 100644 index 000000000..43e3bc4e6 --- /dev/null +++ b/usr.bin/config/sem.h @@ -0,0 +1,91 @@ +/* $NetBSD: sem.h,v 1.19 2014/11/21 20:46:56 christos Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)sem.h 8.1 (Berkeley) 6/6/93 + */ + +void enddefs(void); + +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 *); +void delconf(const char *); +void setfstype(const char **, const char *); +void adddev(const char *, const char *, struct loclist *, int); +void deldevi(const char *, const char *); +void deldeva(const char *); +void deldev(const char *); +void addpseudo(const char *, int); +void delpseudo(const char *); +void addpseudoroot(const char *); +void adddevm(const char *, devmajor_t, devmajor_t, + struct condexpr *, struct nvlist *); +int fixdevis(void); +const char *ref(const char *); +const char *starref(const char *); +const char *wildref(const char *); +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 new file mode 100644 index 000000000..e1837ae45 --- /dev/null +++ b/usr.bin/config/util.c @@ -0,0 +1,575 @@ +/* $NetBSD: util.c,v 1.20 2015/09/01 13:42:48 uebayasi Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)util.c 8.1 (Berkeley) 6/6/93 + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: util.c,v 1.20 2015/09/01 13:42:48 uebayasi Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" + +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) + __printflike(4, 0); + +/************************************************************/ + +/* + * Prefix stack + */ + +static void +prefixlist_push(struct prefixlist *pl, const char *path) +{ + struct prefix *prevpf = SLIST_FIRST(pl); + struct prefix *pf; + char *cp; + + pf = ecalloc(1, sizeof(struct prefix)); + + if (prevpf != NULL) { + cp = emalloc(strlen(prevpf->pf_prefix) + 1 + + strlen(path) + 1); + (void) sprintf(cp, "%s/%s", prevpf->pf_prefix, path); + pf->pf_prefix = intern(cp); + free(cp); + } else + pf->pf_prefix = intern(path); + + SLIST_INSERT_HEAD(pl, pf, pf_next); +} + +static void +prefixlist_pop(struct prefixlist *allpl, struct prefixlist *pl) +{ + struct prefix *pf; + + if ((pf = SLIST_FIRST(pl)) == NULL) { + cfgerror("no prefixes on the stack to pop"); + return; + } + + SLIST_REMOVE_HEAD(pl, pf_next); + /* Remember this prefix for emitting -I... directives later. */ + SLIST_INSERT_HEAD(allpl, pf, pf_next); +} + +/* + * Push a prefix onto the prefix stack. + */ +void +prefix_push(const char *path) +{ + prefixlist_push(&prefixes, path); +} + +/* + * Pop a prefix off the prefix stack. + */ +void +prefix_pop(void) +{ + prefixlist_pop(&allprefixes, &prefixes); +} + +/* + * Push a buildprefix onto the buildprefix stack. + */ +void +buildprefix_push(const char *path) +{ + prefixlist_push(&buildprefixes, path); +} + +/* + * Pop a buildprefix off the buildprefix stack. + */ +void +buildprefix_pop(void) +{ + prefixlist_pop(&allbuildprefixes, &buildprefixes); +} + +/* + * Prepend the source path to a file name. + */ +char * +sourcepath(const char *file) +{ + size_t len; + char *cp; + struct prefix *pf; + + pf = SLIST_EMPTY(&prefixes) ? NULL : SLIST_FIRST(&prefixes); + if (pf != NULL && *pf->pf_prefix == '/') + len = strlen(pf->pf_prefix) + 1 + strlen(file) + 1; + else { + len = strlen(srcdir) + 1 + strlen(file) + 1; + if (pf != NULL) + len += strlen(pf->pf_prefix) + 1; + } + + cp = emalloc(len); + + if (pf != NULL) { + if (*pf->pf_prefix == '/') + (void) sprintf(cp, "%s/%s", pf->pf_prefix, file); + else + (void) sprintf(cp, "%s/%s/%s", srcdir, + pf->pf_prefix, file); + } else + (void) sprintf(cp, "%s/%s", srcdir, file); + return (cp); +} + +/************************************************************/ + +/* + * Data structures + */ + +/* + * nvlist + */ + +struct nvlist * +newnv(const char *name, const char *str, void *ptr, long long i, struct nvlist *next) +{ + struct nvlist *nv; + + nv = ecalloc(1, sizeof(*nv)); + nv->nv_next = next; + nv->nv_name = name; + nv->nv_str = str; + nv->nv_ptr = ptr; + nv->nv_num = i; + return nv; +} + +/* + * Free an nvlist structure (just one). + */ +void +nvfree(struct nvlist *nv) +{ + + free(nv); +} + +/* + * Free an nvlist (the whole list). + */ +void +nvfreel(struct nvlist *nv) +{ + struct nvlist *next; + + for (; nv != NULL; nv = next) { + next = nv->nv_next; + free(nv); + } +} + +struct nvlist * +nvcat(struct nvlist *nv1, struct nvlist *nv2) +{ + struct nvlist *nv; + + if (nv1 == NULL) + return nv2; + + for (nv = nv1; nv->nv_next != NULL; nv = nv->nv_next); + + nv->nv_next = nv2; + return nv1; +} + +/* + * Option definition lists + */ + +struct defoptlist * +defoptlist_create(const char *name, const char *val, const char *lintval) +{ + struct defoptlist *dl; + + dl = emalloc(sizeof(*dl)); + dl->dl_next = NULL; + dl->dl_name = name; + dl->dl_value = val; + dl->dl_lintvalue = lintval; + dl->dl_obsolete = 0; + dl->dl_depends = NULL; + return dl; +} + +void +defoptlist_destroy(struct defoptlist *dl) +{ + struct defoptlist *next; + + while (dl != NULL) { + next = dl->dl_next; + dl->dl_next = NULL; + + // XXX should we assert that dl->dl_deps is null to + // be sure the deps have already been destroyed? + free(dl); + + dl = next; + } +} + +struct defoptlist * +defoptlist_append(struct defoptlist *dla, struct defoptlist *dlb) +{ + struct defoptlist *dl; + + if (dla == NULL) + return dlb; + + for (dl = dla; dl->dl_next != NULL; dl = dl->dl_next) + ; + + dl->dl_next = dlb; + return dla; +} + +/* + * Locator lists + */ + +struct loclist * +loclist_create(const char *name, const char *string, long long num) +{ + struct loclist *ll; + + ll = emalloc(sizeof(*ll)); + ll->ll_name = name; + ll->ll_string = string; + ll->ll_num = num; + ll->ll_next = NULL; + return ll; +} + +void +loclist_destroy(struct loclist *ll) +{ + struct loclist *next; + + while (ll != NULL) { + next = ll->ll_next; + ll->ll_next = NULL; + free(ll); + ll = next; + } +} + +/* + * Attribute lists + */ + +struct attrlist * +attrlist_create(void) +{ + struct attrlist *al; + + al = emalloc(sizeof(*al)); + al->al_next = NULL; + al->al_this = NULL; + return al; +} + +struct attrlist * +attrlist_cons(struct attrlist *next, struct attr *a) +{ + struct attrlist *al; + + al = attrlist_create(); + al->al_next = next; + al->al_this = a; + return al; +} + +void +attrlist_destroy(struct attrlist *al) +{ + assert(al->al_next == NULL); + assert(al->al_this == NULL); + free(al); +} + +void +attrlist_destroyall(struct attrlist *al) +{ + struct attrlist *next; + + while (al != NULL) { + next = al->al_next; + al->al_next = NULL; + /* XXX should we make the caller guarantee this? */ + al->al_this = NULL; + attrlist_destroy(al); + al = next; + } +} + +/* + * Condition expressions + */ + +/* + * Create an expression node. + */ +struct condexpr * +condexpr_create(enum condexpr_types type) +{ + struct condexpr *cx; + + cx = emalloc(sizeof(*cx)); + cx->cx_type = type; + switch (type) { + + case CX_ATOM: + cx->cx_atom = NULL; + break; + + case CX_NOT: + cx->cx_not = NULL; + break; + + case CX_AND: + cx->cx_and.left = NULL; + cx->cx_and.right = NULL; + break; + + case CX_OR: + cx->cx_or.left = NULL; + cx->cx_or.right = NULL; + break; + + default: + panic("condexpr_create: invalid expr type %d", (int)type); + } + return cx; +} + +/* + * Free an expression tree. + */ +void +condexpr_destroy(struct condexpr *expr) +{ + switch (expr->cx_type) { + + case CX_ATOM: + /* nothing */ + break; + + case CX_NOT: + condexpr_destroy(expr->cx_not); + break; + + case CX_AND: + condexpr_destroy(expr->cx_and.left); + condexpr_destroy(expr->cx_and.right); + break; + + case CX_OR: + condexpr_destroy(expr->cx_or.left); + condexpr_destroy(expr->cx_or.right); + break; + + default: + panic("condexpr_destroy: invalid expr type %d", + (int)expr->cx_type); + } + free(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, ...) +{ + va_list ap; + extern const char *yyfile; + + va_start(ap, fmt); + cfgvxwarn(yyfile, currentline(), fmt, ap); + va_end(ap); +} + +void +cfgxwarn(const char *file, int line, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + cfgvxwarn(file, line, fmt, ap); + 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) +{ + cfgvxmsg(file, line, "warning: ", fmt, ap); +} + +/* + * External (config file) error. Complain, using current file + * and line number. + */ +void +cfgerror(const char *fmt, ...) +{ + va_list ap; + extern const char *yyfile; + + va_start(ap, fmt); + cfgvxerror(yyfile, currentline(), fmt, ap); + va_end(ap); +} + +/* + * Delayed config file error (i.e., something was wrong but we could not + * find out about it until later). + */ +void +cfgxerror(const char *file, int line, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + cfgvxerror(file, line, fmt, ap); + va_end(ap); +} + +/* + * Internal form of error() and xerror(). + */ +static void +cfgvxerror(const char *file, int line, const char *fmt, va_list ap) +{ + cfgvxmsg(file, line, "", fmt, ap); + errors++; +} + + +/* + * Internal error, abort. + */ +__dead void +panic(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + (void)fprintf(stderr, "%s: panic: ", getprogname()); + (void)vfprintf(stderr, fmt, ap); + (void)putc('\n', stderr); + va_end(ap); + exit(2); +} + +/* + * Internal form of error() and xerror(). + */ +static void +cfgvxmsg(const char *file, int line, const char *msgclass, const char *fmt, + va_list ap) +{ + + (void)fprintf(stderr, "%s:%d: %s", file, line, msgclass); + (void)vfprintf(stderr, fmt, ap); + (void)putc('\n', stderr); +} + +void +autogen_comment(FILE *fp, const char *targetfile) +{ + + (void)fprintf(fp, + "/*\n" + " * MACHINE GENERATED: DO NOT EDIT\n" + " *\n" + " * %s, from \"%s\"\n" + " */\n\n", + targetfile, conffile); +}