import config command
This commit is contained in:
parent
ccee9c2e7b
commit
fee8e88355
|
|
@ -284,6 +284,7 @@
|
||||||
./usr/bin/column minix-base
|
./usr/bin/column minix-base
|
||||||
./usr/bin/comm minix-base
|
./usr/bin/comm minix-base
|
||||||
./usr/bin/compress minix-base
|
./usr/bin/compress minix-base
|
||||||
|
./usr/bin/config minix-base
|
||||||
./usr/bin/cpio minix-base
|
./usr/bin/cpio minix-base
|
||||||
./usr/bin/cprofalyze minix-base obsolete
|
./usr/bin/cprofalyze minix-base obsolete
|
||||||
./usr/bin/crc minix-base
|
./usr/bin/crc minix-base
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@
|
||||||
./usr/man/man1/comm.1 minix-man
|
./usr/man/man1/comm.1 minix-man
|
||||||
./usr/man/man1/command.1 minix-man obsolete
|
./usr/man/man1/command.1 minix-man obsolete
|
||||||
./usr/man/man1/compress.1 minix-man
|
./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/continue.1 minix-man obsolete
|
||||||
./usr/man/man1/cp.1 minix-man
|
./usr/man/man1/cp.1 minix-man
|
||||||
./usr/man/man1/cpio.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/blacklistd.conf.5 minix-man
|
||||||
./usr/man/man5/boot.cfg.5 minix-man
|
./usr/man/man5/boot.cfg.5 minix-man
|
||||||
./usr/man/man5/cdb.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/configfile.5 minix-man
|
||||||
./usr/man/man5/cpio.5 minix-man
|
./usr/man/man5/cpio.5 minix-man
|
||||||
./usr/man/man5/crontab.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/pr_routes.8 minix-man
|
||||||
./usr/man/man8/printroot.8 minix-man
|
./usr/man/man8/printroot.8 minix-man
|
||||||
./usr/man/man8/pwd_mkdb.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/rarpd.8 minix-man
|
||||||
./usr/man/man8/rawspeed.8 minix-man
|
./usr/man/man8/rawspeed.8 minix-man
|
||||||
./usr/man/man8/rdate.8 minix-man
|
./usr/man/man8/rdate.8 minix-man
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ SUBDIR= asa \
|
||||||
banner basename \
|
banner basename \
|
||||||
bzip2 bzip2recover cal calendar \
|
bzip2 bzip2recover cal calendar \
|
||||||
checknr chpass cksum cmp col colcrt colrm \
|
checknr chpass cksum cmp col colcrt colrm \
|
||||||
column comm csplit ctags cut \
|
column comm config csplit ctags cut \
|
||||||
deroff dirname du \
|
deroff dirname du \
|
||||||
env expand \
|
env expand \
|
||||||
false find finger flock fold fpr from \
|
false find finger flock fold fpr from \
|
||||||
|
|
|
||||||
27
usr.bin/config/Makefile
Normal file
27
usr.bin/config/Makefile
Normal file
|
|
@ -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 <bsd.own.mk>
|
||||||
|
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 <bsd.prog.mk>
|
||||||
461
usr.bin/config/TODO
Normal file
461
usr.bin/config/TODO
Normal file
|
|
@ -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 <ldscript> 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).
|
||||||
BIN
usr.bin/config/config
Executable file
BIN
usr.bin/config/config
Executable file
Binary file not shown.
358
usr.bin/config/config.1
Normal file
358
usr.bin/config/config.1
Normal file
|
|
@ -0,0 +1,358 @@
|
||||||
|
.\" $NetBSD: config.1,v 1.19 2015/09/01 16:01:23 uebayasi Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1980, 1991, 1993
|
||||||
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. 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: @(#)config.8 8.2 (Berkeley) 4/19/94
|
||||||
|
.\"
|
||||||
|
.Dd September 1, 2015
|
||||||
|
.Dt CONFIG 1
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm config
|
||||||
|
.Nd build kernel compilation directories
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl dMPpSv
|
||||||
|
.Op Fl b Ar builddir
|
||||||
|
.Op Fl D Ar var=value
|
||||||
|
.Op Fl s Ar srcdir
|
||||||
|
.Op Fl U Ar value
|
||||||
|
.Op Ar config-file
|
||||||
|
.Nm
|
||||||
|
.Fl x
|
||||||
|
.Op Ar kernel-file
|
||||||
|
.Nm
|
||||||
|
.Fl L
|
||||||
|
.Op Fl v
|
||||||
|
.Op Fl s Ar srcdir
|
||||||
|
.Op Ar config-file
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
In its first synopsis form,
|
||||||
|
.Nm
|
||||||
|
creates a kernel build directory from the machine description file
|
||||||
|
.Ar config-file ,
|
||||||
|
which describes the system to configure.
|
||||||
|
Refer to section
|
||||||
|
.Sx KERNEL BUILD CONFIGURATION
|
||||||
|
for the details of that use
|
||||||
|
of
|
||||||
|
.Nm .
|
||||||
|
.Pp
|
||||||
|
In its second synopsis form,
|
||||||
|
.Nm
|
||||||
|
takes the binary kernel
|
||||||
|
.Ar kernel-file
|
||||||
|
as its single argument (aside from the mandatory
|
||||||
|
.Fl x
|
||||||
|
flag), then extracts the embedded configuration file (if any) and
|
||||||
|
writes it to standard output.
|
||||||
|
If
|
||||||
|
.Ar kernel-file
|
||||||
|
is not given, and the system is not running
|
||||||
|
.Nx
|
||||||
|
an error is printed.
|
||||||
|
On systems running
|
||||||
|
.Nx
|
||||||
|
the booted kernel is looked up using the
|
||||||
|
.Xr sysctl 3
|
||||||
|
variable
|
||||||
|
.Dv machdep.booted_kernel
|
||||||
|
and if that is not found,
|
||||||
|
.Dv _PATH_UNIX
|
||||||
|
.Pq Pa /netbsd
|
||||||
|
is used.
|
||||||
|
Configuration data will be available if the given kernel was compiled
|
||||||
|
with either
|
||||||
|
.Va INCLUDE_CONFIG_FILE
|
||||||
|
or
|
||||||
|
.Va INCLUDE_JUST_CONFIG
|
||||||
|
options.
|
||||||
|
.Pp
|
||||||
|
In its third synopsis form,
|
||||||
|
.Nm
|
||||||
|
is a tool for the kernel developer and generates a
|
||||||
|
.Dq lint
|
||||||
|
configuration file to be used during regression testing.
|
||||||
|
Refer to section
|
||||||
|
.Sx LINT CONFIGURATION
|
||||||
|
for the details of that use of
|
||||||
|
.Nm .
|
||||||
|
.Pp
|
||||||
|
.Nm
|
||||||
|
accepts the following parameters:
|
||||||
|
.Bl -tag -width indent
|
||||||
|
.It Fl b Ar builddir
|
||||||
|
Use
|
||||||
|
.Ar builddir
|
||||||
|
as the kernel build directory, instead of computing and creating one
|
||||||
|
automatically.
|
||||||
|
.It Fl d
|
||||||
|
Issue diagnostic output for debugging problems with
|
||||||
|
.Nm
|
||||||
|
itself.
|
||||||
|
More
|
||||||
|
.Fl d
|
||||||
|
options (currently up to 5) produce more output.
|
||||||
|
.It Fl D Ar var=value
|
||||||
|
Define a makeoptions variable to the given value.
|
||||||
|
This is equivalent to appending a
|
||||||
|
.Li makeoptions var=value
|
||||||
|
line to the config file.
|
||||||
|
.It Fl L
|
||||||
|
Generate a lint configuration.
|
||||||
|
See section
|
||||||
|
.Sx LINT CONFIGURATION
|
||||||
|
for details.
|
||||||
|
.It Fl M
|
||||||
|
Do modular build (experimental).
|
||||||
|
Instead of linking all object files (*.o) at once, collect related object
|
||||||
|
files into an intermediate relocatable object (*.ko), then link those *.ko
|
||||||
|
files into the final kernel.
|
||||||
|
This changes the order of objects in the kernel binary.
|
||||||
|
.It Fl P
|
||||||
|
Pack locators to save space in the resulting kernel binary.
|
||||||
|
The amount of space saved that way is so small that this option should
|
||||||
|
be considered historical, and of no actual use.
|
||||||
|
.It Fl p
|
||||||
|
Generate a build directory suited for kernel profiling.
|
||||||
|
However, this options should be avoided in favor of the relevant options
|
||||||
|
inside the configuration file as described in section
|
||||||
|
.Sx KERNEL BUILD CONFIGURATION .
|
||||||
|
.It Fl s Ar srcdir
|
||||||
|
Point to the top of the kernel source tree.
|
||||||
|
It must be an absolute path when
|
||||||
|
.Nm
|
||||||
|
is used to prepare a kernel build directory, but can be relative
|
||||||
|
when it is used in combination with the
|
||||||
|
.Fl L
|
||||||
|
flag.
|
||||||
|
.It Fl S
|
||||||
|
Use suffix rules and build objects under subdirectories (experimental).
|
||||||
|
.It Fl U Ar var
|
||||||
|
Undefine the makeoption
|
||||||
|
.Ar var .
|
||||||
|
This is equivalent to appending the line
|
||||||
|
.Li no makeoptions var
|
||||||
|
to the config file.
|
||||||
|
.It Fl v
|
||||||
|
Increase verbosity by enabling some more warnings.
|
||||||
|
.It Fl x
|
||||||
|
Extract the configuration embedded in a kernel binary.
|
||||||
|
.El
|
||||||
|
.Ss KERNEL BUILD CONFIGURATION
|
||||||
|
There are several different ways to run the
|
||||||
|
.Nm
|
||||||
|
program.
|
||||||
|
The traditional way is to run
|
||||||
|
.Nm
|
||||||
|
from the
|
||||||
|
.Pa conf
|
||||||
|
subdirectory of the machine-specific directory of the system source
|
||||||
|
(usually
|
||||||
|
.Pa /sys/arch/MACHINE/conf ,
|
||||||
|
where
|
||||||
|
.Pa MACHINE
|
||||||
|
is one of
|
||||||
|
.Pa vax ,
|
||||||
|
.Pa hp300 ,
|
||||||
|
and so forth), and to specify as the
|
||||||
|
.Ar config-file
|
||||||
|
the name of a machine description file located in that directory.
|
||||||
|
.Nm
|
||||||
|
will by default create files in the directory
|
||||||
|
.Pa ../compile/SYSTEMNAME ,
|
||||||
|
where
|
||||||
|
.Pa SYSTEMNAME
|
||||||
|
is the last path component of
|
||||||
|
.Ar config-file .
|
||||||
|
.Nm
|
||||||
|
will assume that the top-level kernel source directory is located four
|
||||||
|
directories above the build directory.
|
||||||
|
.Pp
|
||||||
|
Another way is to create the build directory yourself, place the
|
||||||
|
machine description file in the build directory with the name
|
||||||
|
.Pa CONFIG ,
|
||||||
|
and run
|
||||||
|
.Nm
|
||||||
|
from within the build directory without specifying a
|
||||||
|
.Ar config-file .
|
||||||
|
.Nm
|
||||||
|
will then by default create files in the current directory.
|
||||||
|
If you run
|
||||||
|
.Nm
|
||||||
|
this way, you must specify the location of the top-level kernel source
|
||||||
|
directory using the
|
||||||
|
.Fl s
|
||||||
|
option or by using the
|
||||||
|
.Dq Li source
|
||||||
|
directive at the beginning of the machine description file.
|
||||||
|
.Pp
|
||||||
|
Finally, you can specify the build directory for
|
||||||
|
.Nm
|
||||||
|
and run it from anywhere.
|
||||||
|
You can specify a build directory with the
|
||||||
|
.Fl b
|
||||||
|
option or by using the
|
||||||
|
.Dq Li build
|
||||||
|
directive at the beginning of the machine description file.
|
||||||
|
You must specify the location of the top-level kernel source directory if you
|
||||||
|
specify a build directory.
|
||||||
|
.Pp
|
||||||
|
If
|
||||||
|
.Ar config-file
|
||||||
|
is a binary kernel,
|
||||||
|
.Nm
|
||||||
|
will try to extract the configuration file embedded into it, which will
|
||||||
|
be present if that kernel was built either with
|
||||||
|
.Va INCLUDE_CONFIG_FILE
|
||||||
|
or
|
||||||
|
.Va INCLUDE_JUST_CONFIG
|
||||||
|
options.
|
||||||
|
This work mode requires you to manually specify a build directory with
|
||||||
|
the
|
||||||
|
.Fl b
|
||||||
|
option, which implies the need to provide a source tree too.
|
||||||
|
.Pp
|
||||||
|
If the
|
||||||
|
.Fl p
|
||||||
|
option is supplied,
|
||||||
|
.Pa .PROF
|
||||||
|
is appended to the default compilation directory name, and
|
||||||
|
.Nm
|
||||||
|
acts as if the lines
|
||||||
|
.Dq Li makeoptions PROF="-pg"
|
||||||
|
and
|
||||||
|
.Dq Li options GPROF
|
||||||
|
appeared in the machine description file.
|
||||||
|
This will build a system that includes profiling code; see
|
||||||
|
.Xr kgmon 8
|
||||||
|
and
|
||||||
|
.Xr gprof 1 .
|
||||||
|
The
|
||||||
|
.Fl p
|
||||||
|
flag is expected to be used for
|
||||||
|
.Dq one-shot
|
||||||
|
profiles of existing systems; for regular profiling, it is probably
|
||||||
|
wiser to create a separate machine description file containing the
|
||||||
|
.Li makeoptions
|
||||||
|
line.
|
||||||
|
.Pp
|
||||||
|
The old undocumented
|
||||||
|
.Fl g
|
||||||
|
flag is no longer supported.
|
||||||
|
Instead, use
|
||||||
|
.Dq Li makeoptions DEBUG="-g"
|
||||||
|
and (typically)
|
||||||
|
.Dq Li options KGDB .
|
||||||
|
.Pp
|
||||||
|
The output of
|
||||||
|
.Nm
|
||||||
|
consists of a number of files, principally
|
||||||
|
.Pa ioconf.c ,
|
||||||
|
a description of I/O devices that may be attached to the system; and a
|
||||||
|
.Pa Makefile ,
|
||||||
|
used by
|
||||||
|
.Xr make 1
|
||||||
|
in building the kernel.
|
||||||
|
.Pp
|
||||||
|
After running
|
||||||
|
.Nm ,
|
||||||
|
it is wise to run
|
||||||
|
.Dq Li make depend
|
||||||
|
in the directory where the new makefile
|
||||||
|
was created.
|
||||||
|
.Nm
|
||||||
|
prints a reminder of this when it completes.
|
||||||
|
.Pp
|
||||||
|
If
|
||||||
|
.Nm
|
||||||
|
stops due to errors, the problems reported should be corrected and
|
||||||
|
.Nm
|
||||||
|
should be run again.
|
||||||
|
.Nm
|
||||||
|
attempts to avoid changing the compilation directory
|
||||||
|
if there are configuration errors,
|
||||||
|
but this code is not well-tested,
|
||||||
|
and some problems (such as running out of disk space)
|
||||||
|
are unrecoverable.
|
||||||
|
.Ss LINT CONFIGURATION
|
||||||
|
A so-called
|
||||||
|
.Dq lint
|
||||||
|
configuration should include everything from the kernel that can
|
||||||
|
possibly be selected.
|
||||||
|
The rationale is to provide a way to reach all the code a user might
|
||||||
|
select, in order to make sure all options and drivers compile without
|
||||||
|
error for a given source tree.
|
||||||
|
.Pp
|
||||||
|
When used with the
|
||||||
|
.Fl L
|
||||||
|
flag,
|
||||||
|
.Nm
|
||||||
|
takes the regular configuration file
|
||||||
|
.Ar config-file
|
||||||
|
and prints on the standard output a configuration file that includes
|
||||||
|
.Ar config-file ,
|
||||||
|
selects all options and file-systems the user can possibly select,
|
||||||
|
and defines an instance of every possible attachment as described by
|
||||||
|
the kernel option definition files used by
|
||||||
|
.Ar config-file .
|
||||||
|
.Pp
|
||||||
|
The resulting configuration file is meant as a way to select all
|
||||||
|
possible features in order to test that each of them compiles.
|
||||||
|
It is not meant to result in a kernel binary that can run on any
|
||||||
|
hardware.
|
||||||
|
.Pp
|
||||||
|
Unlike the first synopsis form, the provided
|
||||||
|
.Ar srcdir
|
||||||
|
is relative to the current working directory.
|
||||||
|
In the first synopsis form, it is relative to the build directory.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
The SYNOPSIS portion of each device in section 4.
|
||||||
|
.\".Rs
|
||||||
|
.\" .%T "Building 4.4 BSD Systems with Config"
|
||||||
|
.\" .%T "Device Support in 4.4BSD"
|
||||||
|
.\".Re
|
||||||
|
.Pp
|
||||||
|
.Xr options 4 ,
|
||||||
|
.Xr config 5 ,
|
||||||
|
.Xr config 9
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
command appeared in
|
||||||
|
.Bx 4.1 .
|
||||||
|
It was completely revised in
|
||||||
|
.Bx 4.4 .
|
||||||
|
The
|
||||||
|
.Fl x
|
||||||
|
option appeared in
|
||||||
|
.Nx 2.0 .
|
||||||
|
The
|
||||||
|
.Fl L
|
||||||
|
option appeared in
|
||||||
|
.Nx 5.0 .
|
||||||
764
usr.bin/config/config.5
Normal file
764
usr.bin/config/config.5
Normal file
|
|
@ -0,0 +1,764 @@
|
||||||
|
.\" $NetBSD: config.5,v 1.34 2015/09/01 13:42:48 uebayasi Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2006, 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.
|
||||||
|
.\"
|
||||||
|
.Dd September 1, 2015
|
||||||
|
.Dt CONFIG 5
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm config
|
||||||
|
.Nd kernel configuration file syntax
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The kernel configuration file specifies the way the kernel should be compiled
|
||||||
|
by the rest of the toolchain.
|
||||||
|
It is processed by
|
||||||
|
.Xr config 1
|
||||||
|
to produce a number of files that will allow the user to compile a possibly
|
||||||
|
customised kernel.
|
||||||
|
One compilation can issue several kernel binaries, with different root and
|
||||||
|
dump devices configurations, or with full debugging information.
|
||||||
|
.Pp
|
||||||
|
This manual page is intended to serve as a complete reference of all aspects
|
||||||
|
of the syntax used in the many files processed by
|
||||||
|
.Xr config 1 .
|
||||||
|
The novice user will prefer looking at the examples given in
|
||||||
|
.Xr config.samples 5
|
||||||
|
in order to understand better how the default configuration can be changed,
|
||||||
|
and how all of its elements interact with each other.
|
||||||
|
.Pp
|
||||||
|
The kernel configuration file actually contains the description of all the
|
||||||
|
options, drivers and source files involved in the kernel compilation, and the
|
||||||
|
logic that binds them.
|
||||||
|
The
|
||||||
|
.Ic machine
|
||||||
|
statement, usually found in the
|
||||||
|
.Pa std.${MACHINE}
|
||||||
|
file, hides this from the user by automatically including all the descriptive
|
||||||
|
files spread all around the kernel source tree, the main one being
|
||||||
|
.Pa conf/files .
|
||||||
|
.Pp
|
||||||
|
Thus, the kernel configuration file contains two parts:
|
||||||
|
the description of the compilation options, and the selection of those options.
|
||||||
|
However, it begins with a small preamble that controls a couple of options of
|
||||||
|
.Xr config 1 ,
|
||||||
|
and a few statements belong to any of the two sections.
|
||||||
|
.Pp
|
||||||
|
The user controls the options selection part, which is located in a file
|
||||||
|
commonly referenced as the
|
||||||
|
.Em main configuration file
|
||||||
|
or simply the
|
||||||
|
.Em kernel configuration file .
|
||||||
|
The developer is responsible for describing the options in the relevant files
|
||||||
|
from the kernel source tree.
|
||||||
|
.Pp
|
||||||
|
Statements are separated by new-line characters.
|
||||||
|
However, new-line characters can appear in the middle of a given statement,
|
||||||
|
with the value of a space character.
|
||||||
|
.Ss OBJECTS AND NAMES
|
||||||
|
.Xr config 1
|
||||||
|
is a rather complicated piece of software that tries to comply with any
|
||||||
|
configuration the user might think of.
|
||||||
|
Quite a few different objects are manipulated through the kernel configuration
|
||||||
|
file, therefore some definitions are needed.
|
||||||
|
.Ss Options and attributes
|
||||||
|
The basic objects driving the kernel compilation are
|
||||||
|
.Em options ,
|
||||||
|
and are called
|
||||||
|
.Ar attributes
|
||||||
|
in some contexts.
|
||||||
|
An
|
||||||
|
.Ar attribute
|
||||||
|
usually refers to a feature a given piece of hardware might have.
|
||||||
|
However, the scope of an attribute is rather wide and can just be a place
|
||||||
|
holder to group some source files together.
|
||||||
|
.Pp
|
||||||
|
There is a special class of attribute, named
|
||||||
|
.Em interface attribute ,
|
||||||
|
which represents a hook that allows a device to attach to (i.e., be a child of)
|
||||||
|
another device.
|
||||||
|
An
|
||||||
|
.Em interface attribute
|
||||||
|
has a (possibly empty) list of
|
||||||
|
.Ar locators
|
||||||
|
to match the actual location of a device.
|
||||||
|
For example, on a PCI bus, devices are located by a
|
||||||
|
.Em device number
|
||||||
|
that is fixed by the wiring of the motherboard.
|
||||||
|
Additionally, each of those devices can appear through several interfaces named
|
||||||
|
.Em functions .
|
||||||
|
A single PCI device entity is a unique function number of a given device from
|
||||||
|
the considered PCI bus.
|
||||||
|
Therefore, the locators for a
|
||||||
|
.Xr pci 4
|
||||||
|
device are
|
||||||
|
.Ar dev
|
||||||
|
(for device), and
|
||||||
|
.Ar function .
|
||||||
|
.Pp
|
||||||
|
A
|
||||||
|
.Ar locator
|
||||||
|
can either be a single integer value, or an array of integer values.
|
||||||
|
It can have a default value, in which case it can be wildcarded with a
|
||||||
|
.Dq \&?
|
||||||
|
in the options selection section of the configuration file.
|
||||||
|
A single
|
||||||
|
.Ar locator
|
||||||
|
definition can take one of the following forms:
|
||||||
|
.Bl -enum -offset indent -compact
|
||||||
|
.It
|
||||||
|
.Ar locator
|
||||||
|
.It
|
||||||
|
.Ar locator
|
||||||
|
=
|
||||||
|
.Ar value
|
||||||
|
.It
|
||||||
|
.Ar locator Ns Oo Ar length Oc
|
||||||
|
.It
|
||||||
|
.Ar locator Ns Oo Ar length Oc = Brq Ar value , ...
|
||||||
|
.El
|
||||||
|
The variants that specify a default value can be enclosed into square brackets,
|
||||||
|
in which case the locator will not have to be specified later in the options
|
||||||
|
selection section of the configuration file.
|
||||||
|
.Pp
|
||||||
|
In the options selection section, the locators are specified when declaring an
|
||||||
|
instance as a space-separated list of
|
||||||
|
.Dq Ao Ar locator Ac Ao Ar value Ac
|
||||||
|
where value can be the
|
||||||
|
.Dq \&?
|
||||||
|
wildcard if the locator allows it.
|
||||||
|
.Ss Devices, instances and attachments
|
||||||
|
The main benefit of the kernel configuration file is to allow the user to avoid
|
||||||
|
compiling some drivers, and wire down the configuration of some others.
|
||||||
|
We have already seen that devices attach to each other through
|
||||||
|
.Em interface attributes ,
|
||||||
|
but not everything can attach to anything.
|
||||||
|
Furthermore, the user has the ability to define precise instances for the
|
||||||
|
devices.
|
||||||
|
An
|
||||||
|
.Ar instance
|
||||||
|
is simply the reality of a device when it is probed and attached by the kernel.
|
||||||
|
.Pp
|
||||||
|
Each driver has a name for its devices.
|
||||||
|
It is called the base device name and is found as
|
||||||
|
.Ar base
|
||||||
|
in this documentation.
|
||||||
|
An
|
||||||
|
.Ar instance
|
||||||
|
is the concatenation of a device name and a number.
|
||||||
|
In the kernel configuration file, instances can sometimes be wildcarded
|
||||||
|
(i.e., the number is replaced by a
|
||||||
|
.Dq *
|
||||||
|
or a
|
||||||
|
.Dq \&? )
|
||||||
|
in order to match all the possible instances of a device.
|
||||||
|
.Pp
|
||||||
|
The usual
|
||||||
|
.Dq *
|
||||||
|
becomes a
|
||||||
|
.Dq \&?
|
||||||
|
when the instance name is used as an
|
||||||
|
.Em attachment name .
|
||||||
|
In the options selection part of the kernel configuration files, an
|
||||||
|
.Em attachment
|
||||||
|
is an
|
||||||
|
.Em interface attribute
|
||||||
|
concatenated with a number or the wildcard
|
||||||
|
.Dq \&? .
|
||||||
|
.Ss Pseudo-devices
|
||||||
|
Some components of the kernel behave like a device although they don't have
|
||||||
|
any actual reality in the hardware.
|
||||||
|
For example, this is the case for special network devices, such as
|
||||||
|
.Xr tun 4
|
||||||
|
and
|
||||||
|
.Xr tap 4 .
|
||||||
|
They are integrated in the kernel as pseudo-devices, and can have several
|
||||||
|
instances and even children, just like normal devices.
|
||||||
|
.Ss Dependencies
|
||||||
|
The options description part of the kernel configuration file contains all the
|
||||||
|
logic that ties the source files together, and it is done first through writing
|
||||||
|
down dependencies between
|
||||||
|
.Xr config 1
|
||||||
|
objects.
|
||||||
|
.Pp
|
||||||
|
In this documentation, the syntax for
|
||||||
|
.Ar dependencies
|
||||||
|
is a comma-separated list of
|
||||||
|
.Ar options
|
||||||
|
and
|
||||||
|
.Ar attributes .
|
||||||
|
.Pp
|
||||||
|
For example, the use of an Ethernet network card requires the source files that
|
||||||
|
handle the specificities of that protocol.
|
||||||
|
Therefore, all Ethernet network card drivers depend on the
|
||||||
|
.Ar ether
|
||||||
|
attribute.
|
||||||
|
.Ss Conditions
|
||||||
|
Finally, source file selection is possible through the help of
|
||||||
|
conditionals, referred to as
|
||||||
|
.Ar condition
|
||||||
|
later in this documentation.
|
||||||
|
The syntax for those conditions uses well-known operators (
|
||||||
|
.Dq \*[Am] ,
|
||||||
|
.Dq |
|
||||||
|
and
|
||||||
|
.Dq \&! )
|
||||||
|
to combine
|
||||||
|
.Ar options
|
||||||
|
and
|
||||||
|
.Ar attributes .
|
||||||
|
.Ss CONTEXT NEUTRAL STATEMENTS
|
||||||
|
.Bl -ohang
|
||||||
|
.It Ic version Ar yyyymmdd
|
||||||
|
Indicates the syntax version used by the rest of the file, or until the next
|
||||||
|
.Ic version
|
||||||
|
statement.
|
||||||
|
The argument is an ISO date.
|
||||||
|
A given
|
||||||
|
.Xr config 1
|
||||||
|
binary might only be compatible with a limited range of version numbers.
|
||||||
|
.It Ic include Ar path
|
||||||
|
Includes a file.
|
||||||
|
The path is relative to the top of the kernel source tree, or the inner-most
|
||||||
|
defined
|
||||||
|
.Ic prefix .
|
||||||
|
.It Ic cinclude Ar path
|
||||||
|
Conditionally includes a file.
|
||||||
|
Contrary to
|
||||||
|
.Ic include ,
|
||||||
|
it will not produce an error if the file does not exist.
|
||||||
|
The argument obeys the same rules as for
|
||||||
|
.Ic include .
|
||||||
|
.It Ic prefix Op Ar path
|
||||||
|
If
|
||||||
|
.Ar path
|
||||||
|
is given, it pushes a new prefix for
|
||||||
|
.Ic file ,
|
||||||
|
.Ic include
|
||||||
|
and
|
||||||
|
.Ic cinclude .
|
||||||
|
.Ic prefix
|
||||||
|
statements act like a stack, and an empty
|
||||||
|
.Ar path
|
||||||
|
argument has the latest prefix popped out.
|
||||||
|
The
|
||||||
|
.Ar path
|
||||||
|
argument is either absolute or relative to the current defined prefix, which
|
||||||
|
defaults to the top of the kernel source tree.
|
||||||
|
.It Ic buildprefix Op Ar path
|
||||||
|
If
|
||||||
|
.Ar path
|
||||||
|
is given, it pushes a new build prefix for
|
||||||
|
.Ic file .
|
||||||
|
.Ic buildprefix
|
||||||
|
statements act like a stack, and an empty
|
||||||
|
.Ar path
|
||||||
|
argument has the latest prefix popped out.
|
||||||
|
The
|
||||||
|
.Ar path
|
||||||
|
argument is relative to the current defined buildprefix, which
|
||||||
|
defaults to the top of the kernel build directory.
|
||||||
|
When prefix is either absolute or relative out of the kernel source tree (../),
|
||||||
|
buildprefix must be defined.
|
||||||
|
.It Ic ifdef Ar attribute
|
||||||
|
.It Ic ifndef Ar attribute
|
||||||
|
.It Ic elifdef Ar attribute
|
||||||
|
.It Ic elifndef Ar attribute
|
||||||
|
.It Ic else
|
||||||
|
.It Ic endif
|
||||||
|
Conditionally interprets portions of the current file.
|
||||||
|
Those statements depend on whether or not the given
|
||||||
|
.Ar attribute
|
||||||
|
has been previously defined, through
|
||||||
|
.Ic define
|
||||||
|
or any other statement that implicitely defines attributes such as
|
||||||
|
.Ic device .
|
||||||
|
.El
|
||||||
|
.Ss PREAMBLE
|
||||||
|
In addition to
|
||||||
|
.Ic include , cinclude ,
|
||||||
|
and
|
||||||
|
.Ic prefix ,
|
||||||
|
the preamble may contain the following optional statements:
|
||||||
|
.Bl -ohang
|
||||||
|
.It Ic build Ar path
|
||||||
|
Defines the build directory for the compilation of the kernel.
|
||||||
|
It replaces the default of
|
||||||
|
.Pa ../compile/\*[Lt]config-file\*[Gt]
|
||||||
|
and is superseded by the
|
||||||
|
.Fl b
|
||||||
|
parameter of
|
||||||
|
.Xr config 1 .
|
||||||
|
.It Ic source Ar path
|
||||||
|
Defines the directory in which the source of the kernel lives.
|
||||||
|
It replaces the default of
|
||||||
|
.Pa ../../../..
|
||||||
|
and is superseded by the
|
||||||
|
.Fl s
|
||||||
|
parameter of
|
||||||
|
.Xr config 1 .
|
||||||
|
.El
|
||||||
|
.Ss OPTIONS DESCRIPTION
|
||||||
|
The user will not usually have to use descriptive statements, as they are meant
|
||||||
|
for the developer to tie a given piece of code to the rest of the kernel.
|
||||||
|
However, third parties may provide sources to add to the kernel compilation,
|
||||||
|
and the logic that binds them to the
|
||||||
|
.Nx
|
||||||
|
kernel will have to be added to the user-edited configuration file.
|
||||||
|
.Bl -ohang
|
||||||
|
.It Ic devclass Ar class
|
||||||
|
Defines a special attribute, named
|
||||||
|
.Em device class .
|
||||||
|
A given device cannot belong to more than one device class.
|
||||||
|
.Xr config 1
|
||||||
|
translates that property by the rule that a device cannot depend on more than
|
||||||
|
one device class, and will properly fill the configuration information file it
|
||||||
|
generates according to that value.
|
||||||
|
.It Ic defflag Oo Ar file Oc Ar option Oo Ar option Oo Ar ... Oc Oc \
|
||||||
|
Op : Ar dependencies
|
||||||
|
Defines a boolean option, that can either be selected or be un-selected by the
|
||||||
|
user with the
|
||||||
|
.Ic options
|
||||||
|
statement.
|
||||||
|
The optional
|
||||||
|
.Ar file
|
||||||
|
argument names a header file that will contain the C pre-processor definition
|
||||||
|
for the option.
|
||||||
|
If no file name is given, it will default to
|
||||||
|
.Ar opt_\*[Lt]option\*[Gt].h .
|
||||||
|
.Xr config 1
|
||||||
|
will always create the header file, but if the user choose not to select the
|
||||||
|
option, it will be empty.
|
||||||
|
Several options can be combined in one header file, for convenience.
|
||||||
|
The header file is created in the compilation directory, making them directly
|
||||||
|
accessible by source files.
|
||||||
|
.It Ic defparam Oo Ar file Oc Ar option Oo = Ar value Oc \
|
||||||
|
Oo := Ar lint-value Oc Oo Ar option Oo Ar ... Oc Oc Op : Ar dependencies
|
||||||
|
Behaves like
|
||||||
|
.Ic defflag ,
|
||||||
|
except the defined option must have a value.
|
||||||
|
Such options are not typed:
|
||||||
|
they can have either a numeric or a string value.
|
||||||
|
If a
|
||||||
|
.Ar value
|
||||||
|
is specified, it is treated as a default, and the option is
|
||||||
|
always defined in the corresponding header file.
|
||||||
|
If a
|
||||||
|
.Ar lint-value
|
||||||
|
is specified,
|
||||||
|
.Xr config 1
|
||||||
|
will use it as a value when generating a lint configuration with
|
||||||
|
.Fl L ,
|
||||||
|
and ignore it in all other cases.
|
||||||
|
.It Ic deffs Ar name Op Ar name Op Ar ...
|
||||||
|
Defines a file-system name.
|
||||||
|
It is no more than a regular option, as defined by
|
||||||
|
.Ic defflag ,
|
||||||
|
but it allows the user to select the
|
||||||
|
file-systems to be compiled in the kernel with the
|
||||||
|
.Ic file-system
|
||||||
|
statement instead of the
|
||||||
|
.Ic options
|
||||||
|
statement.
|
||||||
|
.It Ic obsolete defflag Oo Ar file Oc Ar option Op Ar option Op Ar ...
|
||||||
|
.It Ic obsolete defparam Oo Ar file Oc Ar option Op Ar option Op Ar ...
|
||||||
|
Those two statements are identical and mark the listed option names as
|
||||||
|
obsolete.
|
||||||
|
If the user selects one of the listed options in the kernel configuration
|
||||||
|
file,
|
||||||
|
.Xr config 1
|
||||||
|
will emit a warning and ignore the option.
|
||||||
|
The optional
|
||||||
|
.Ar file
|
||||||
|
argument should match the original definition of the option.
|
||||||
|
.It Ic define Ar attribute Oo Bro Ar locators Brc Oc Oo : Ar dependencies Oc
|
||||||
|
Defines an
|
||||||
|
.Ar attribute .
|
||||||
|
The
|
||||||
|
.Ar locators
|
||||||
|
list is optional, and can be empty.
|
||||||
|
If the pair of brackets are present, the locator list is defined and the
|
||||||
|
declared attribute becomes an
|
||||||
|
.Em interface attribute ,
|
||||||
|
on which devices can attach.
|
||||||
|
.It Ic maxpartitions Ar number
|
||||||
|
Defines the maximum number of partitions the disklabels for the considered
|
||||||
|
architecture can hold.
|
||||||
|
This statement cannot be repeated and should only appear in the
|
||||||
|
.Pa std\&.$\&{ARCH\&}
|
||||||
|
file.
|
||||||
|
.It Ic maxusers Ar min default max
|
||||||
|
Indicates the range of values that will later be accepted by
|
||||||
|
.Xr config 1
|
||||||
|
for the
|
||||||
|
.Ic maxusers
|
||||||
|
statement in the options selection part of the configuration file.
|
||||||
|
In case the user doesn't include a
|
||||||
|
.Ic maxusers
|
||||||
|
statement in the configuration file, the value
|
||||||
|
.Ar default
|
||||||
|
is used instead.
|
||||||
|
.It Ic device Ar base Oo Bro Ar locators Brc Oc Oo : dependencies Oc
|
||||||
|
Declares a device of name
|
||||||
|
.Ar base .
|
||||||
|
The optional list of
|
||||||
|
.Ar locators ,
|
||||||
|
which can also be empty, indicates the device can have children attached
|
||||||
|
directly to it.
|
||||||
|
Internally, that means
|
||||||
|
.Ar base
|
||||||
|
becomes an
|
||||||
|
.Ar interface attribute .
|
||||||
|
For every device the user selects,
|
||||||
|
.Xr config 1
|
||||||
|
will add the matching
|
||||||
|
.Fn CFDRIVER_DECL
|
||||||
|
statement to
|
||||||
|
.Pa ioconf.c .
|
||||||
|
However, it is the responsibility of the developer to add the relevant
|
||||||
|
.Fn CFATTACH_DECL
|
||||||
|
line to the source of the device's driver.
|
||||||
|
.It Ic attach Ar base Ic at Ar attr Oo , Ar attr Oo , Ar ... Oc Oc Oo Ic with \
|
||||||
|
Ar name Oc Oo : dependencies Oc
|
||||||
|
All devices must have at least one declared attachment.
|
||||||
|
Otherwise, they will never be found in the
|
||||||
|
.Xr autoconf 9
|
||||||
|
process.
|
||||||
|
The attributes on which an instance of device
|
||||||
|
.Ar base
|
||||||
|
can attach must be
|
||||||
|
.Ar interface attributes ,
|
||||||
|
or
|
||||||
|
.Ic root
|
||||||
|
in case the device is at the top-level, which is usually the case of e.g.,
|
||||||
|
.Xr mainbus 4 .
|
||||||
|
The instances of device
|
||||||
|
.Ar base
|
||||||
|
will later attach to one interface attribute from the specified list.
|
||||||
|
.Pp
|
||||||
|
Different
|
||||||
|
.Ic attach
|
||||||
|
definitions must use different names using the
|
||||||
|
.Ic with
|
||||||
|
option.
|
||||||
|
It is then possible to use the associated
|
||||||
|
.Ar name
|
||||||
|
as a conditional element in a
|
||||||
|
.Ic file
|
||||||
|
statement.
|
||||||
|
.It Ic defpseudo Ar base Oo : dependencies Oc
|
||||||
|
Declares a pseudo-device.
|
||||||
|
Those devices don't need an attachment to be declared, they will always be
|
||||||
|
attached if they were selected by the user.
|
||||||
|
.It Ic defpseudodev Ar base Oo Bro Ar locators Brc Oc Oo : dependencies Oc
|
||||||
|
Declares a pseudo-device.
|
||||||
|
Those devices don't need an attachment to be declared, they will always be
|
||||||
|
attached if they were selected by the user.
|
||||||
|
This declaration should be used if the pseudodevice uses
|
||||||
|
.Xr autoconf 9
|
||||||
|
functions to manage its instances or attach children.
|
||||||
|
As for normal devices, an optional list of
|
||||||
|
.Ar locators
|
||||||
|
can be defined, which implies an interface attribute named
|
||||||
|
.Ar base ,
|
||||||
|
allowing the pseudo-device to have children.
|
||||||
|
Interface attributes can also be defined in the
|
||||||
|
.Ar dependencies
|
||||||
|
list.
|
||||||
|
.It Ic file Ar path Oo Ar condition Oc Oo Ic needs-count Oc \
|
||||||
|
Oo Ic needs-flag Oc Op Ic compile with Ar rule
|
||||||
|
Adds a source file to the list of files to be compiled into the kernel, if the
|
||||||
|
.Ar conditions
|
||||||
|
are met.
|
||||||
|
The
|
||||||
|
.Ic needs-count
|
||||||
|
option indicates that the source file requires the number of all the countable
|
||||||
|
objects it depends on (through the
|
||||||
|
.Ar conditions )
|
||||||
|
to be defined.
|
||||||
|
It is usually used for
|
||||||
|
.Ar pseudo-devices
|
||||||
|
whose number can be specified by the user in the
|
||||||
|
.Ic pseudo-device
|
||||||
|
statement.
|
||||||
|
Countable objects are devices and pseudo-devices.
|
||||||
|
For the former, the count is the number of declared instances.
|
||||||
|
For the latter, it is the number specified by the user, defaulting to 1.
|
||||||
|
The
|
||||||
|
.Ic needs-flag
|
||||||
|
options requires that a flag indicating the selection of an attribute to
|
||||||
|
be created, but the precise number isn't needed.
|
||||||
|
This is useful for source files that only partly depend on the attribute,
|
||||||
|
and thus need to add pre-processor statements for it.
|
||||||
|
.Pp
|
||||||
|
.Ic needs-count
|
||||||
|
and
|
||||||
|
.Ic needs-flag
|
||||||
|
both produce a header file for each of the considered attributes.
|
||||||
|
The name of that file is
|
||||||
|
.Pa \*[Lt]attribute\*[Gt].h .
|
||||||
|
It contains one pre-processor definition of
|
||||||
|
.Dv NATTRIBUTE
|
||||||
|
set to 0 if the attribute was not selected by the user, or to the number of
|
||||||
|
instances of the device in the
|
||||||
|
.Ic needs-count
|
||||||
|
case, or to 1 in all the other cases.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Ar rule
|
||||||
|
argument specifies the
|
||||||
|
.Xr make 1
|
||||||
|
rule that will be used to compile the source file.
|
||||||
|
If it is not given, the default rule for the type of the file will be used.
|
||||||
|
For a given file, there can be more than one
|
||||||
|
.Ic file
|
||||||
|
statement, but not from the same configuration source file, and all later
|
||||||
|
statements can only specify a
|
||||||
|
.Ar rule
|
||||||
|
argument, and no
|
||||||
|
.Ar conditions
|
||||||
|
or flags.
|
||||||
|
This is useful when a file needs special consideration from one particular
|
||||||
|
architecture.
|
||||||
|
.Pp
|
||||||
|
The path is relative to the top of the kernel source tree, or the inner-most
|
||||||
|
defined
|
||||||
|
.Ic prefix .
|
||||||
|
.It Ic object Ar path Op Ar condition
|
||||||
|
Adds an object file to the list of objects to be linked into the kernel, if the
|
||||||
|
.Ar conditions
|
||||||
|
are met.
|
||||||
|
This is most useful for third parties providing binary-only components.
|
||||||
|
.Pp
|
||||||
|
The path is relative to the top of the kernel source tree, or the inner-most
|
||||||
|
defined
|
||||||
|
.Ic prefix .
|
||||||
|
.It Ic device-major Ar base Oo Ic char Ar number Oc Oo Ic block Ar number Oc \
|
||||||
|
Op Ar condition
|
||||||
|
Associates a major device number with the device
|
||||||
|
.Ar base .
|
||||||
|
A device can be a character device, a block device, or both, and can have
|
||||||
|
different numbers for each.
|
||||||
|
The
|
||||||
|
.Ar condition
|
||||||
|
indicates when the relevant line should be added to
|
||||||
|
.Pa ioconf.c ,
|
||||||
|
and works just like the
|
||||||
|
.Ic file
|
||||||
|
statement.
|
||||||
|
.El
|
||||||
|
.Ss OPTIONS SELECTION
|
||||||
|
.Bl -ohang
|
||||||
|
.It Ic machine Ar machine Op Ar arch Op Ar subarch Op Ar ...
|
||||||
|
The
|
||||||
|
.Ic machine
|
||||||
|
statement should appear first in the kernel configuration file, with the
|
||||||
|
exception of context-neutral statements.
|
||||||
|
It makes
|
||||||
|
.Xr config 1
|
||||||
|
include, in that order, the following files:
|
||||||
|
.Bl -enum -offset indent -compact
|
||||||
|
.It
|
||||||
|
.Pa conf/files
|
||||||
|
.It
|
||||||
|
.Pa arch/${ARCH}/conf/files.${ARCH}
|
||||||
|
if defined
|
||||||
|
.It
|
||||||
|
.Pa arch/${SUBARCH}/conf/files.${SUBARCH}
|
||||||
|
for each defined sub-architecture
|
||||||
|
.It
|
||||||
|
.Pa arch/${MACHINE}/conf/files.${MACHINE}
|
||||||
|
.El
|
||||||
|
It also defines an attribute for the
|
||||||
|
.Ar machine ,
|
||||||
|
the
|
||||||
|
.Ar arch
|
||||||
|
and each of the
|
||||||
|
.Ar subarch .
|
||||||
|
.It Ic package Ar path
|
||||||
|
Simpler version of:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
prefix PATH
|
||||||
|
include FILE
|
||||||
|
prefix
|
||||||
|
.Ed
|
||||||
|
.It Ic ident Ar string
|
||||||
|
Defines the identification string of the kernel.
|
||||||
|
This statement is optional, and the name of the main configuration file will be
|
||||||
|
used as a default value.
|
||||||
|
.It Ic no ident
|
||||||
|
Deletes any pre-existing identification string of the kernel.
|
||||||
|
.It Ic maxusers Ar number
|
||||||
|
Despite its name, this statement does not limit the maximum number of users on
|
||||||
|
the system.
|
||||||
|
There is no such limit, actually.
|
||||||
|
However, some kernel structures need to be adjusted to accommodate with more
|
||||||
|
users, and the
|
||||||
|
.Ic maxusers
|
||||||
|
parameter is used for example to compute the maximum number of opened files,
|
||||||
|
and the maximum number of processes, which itself is used to adjust a few
|
||||||
|
other parameters.
|
||||||
|
.It Ic options Ar name Oo = Ar value Oc Op , Ar name Oo = Ar \
|
||||||
|
value Oc , Ar ...
|
||||||
|
Selects the option
|
||||||
|
.Ar name ,
|
||||||
|
affecting it a
|
||||||
|
.Ar value
|
||||||
|
if the options requires it (see the
|
||||||
|
.Ic defflag
|
||||||
|
and
|
||||||
|
.Ic defparam
|
||||||
|
statements).
|
||||||
|
.Pp
|
||||||
|
If the option has not been declared in the options description part of the
|
||||||
|
kernel configuration machinery, it will be added as a pre-processor definition
|
||||||
|
when source files are compiled.
|
||||||
|
If the option has previously been selected, the statement produces a
|
||||||
|
warning, and the new
|
||||||
|
.Ic options
|
||||||
|
statement replaces the original.
|
||||||
|
.It Ic no options Ar name Op , Ar name Op , Ar ...
|
||||||
|
Un-selects the option
|
||||||
|
.Ar name .
|
||||||
|
If option
|
||||||
|
.Ar name
|
||||||
|
has not previously been selected, the statement produces a warning.
|
||||||
|
.It Ic file-system Ar name Op , Ar name Op , Ar ...
|
||||||
|
Adds support for all the listed file-systems.
|
||||||
|
.It Ic no file-system Ar name Op , Ar name Op , Ar ...
|
||||||
|
Removes support for all the listed file-systems.
|
||||||
|
.It Ic config Ar name Ic root on Ar device Oo Ic type Ar fs Oc Op Ic dumps on \
|
||||||
|
Ar device
|
||||||
|
Adds
|
||||||
|
.Ar name
|
||||||
|
to the list of kernel binaries to compile from the configuration file, using
|
||||||
|
the specified root and dump devices information.
|
||||||
|
.Pp
|
||||||
|
Any of the
|
||||||
|
.Ar device
|
||||||
|
and
|
||||||
|
.Ar fs
|
||||||
|
parameters can be wildcarded with
|
||||||
|
.Dq \&?
|
||||||
|
to let the kernel automatically discover those values.
|
||||||
|
.Pp
|
||||||
|
At least one
|
||||||
|
.Ic config
|
||||||
|
statement must appear in the configuration file.
|
||||||
|
.It Ic no config Ar name
|
||||||
|
Removes
|
||||||
|
.Ar name
|
||||||
|
from the list of kernel binaries to compile from the configuration file.
|
||||||
|
.It Ar instance Ic at Ar attachment Op Ar locator specification
|
||||||
|
Configures an instance of a device attaching at a specific location in the
|
||||||
|
device tree.
|
||||||
|
All parameters can be wildcarded, with a
|
||||||
|
.Dq *
|
||||||
|
for
|
||||||
|
.Ar instance ,
|
||||||
|
and a
|
||||||
|
.Dq \&?
|
||||||
|
for
|
||||||
|
.Ar attachment
|
||||||
|
and the locators.
|
||||||
|
.It Ic no Ar instance Op Ic at Ar attachment
|
||||||
|
Removes the previously configured instances of a device that exactly match the
|
||||||
|
given specification.
|
||||||
|
If two instances differ only by their locators, both are removed.
|
||||||
|
If no
|
||||||
|
.Ar attachment
|
||||||
|
is specified, all matching instances are removed.
|
||||||
|
.Pp
|
||||||
|
If
|
||||||
|
.Ar instance
|
||||||
|
is a bare device name, all the previously defined instances of that device,
|
||||||
|
regardless of the numbers or wildcard, are removed.
|
||||||
|
.It Ic no device at Ar attachment
|
||||||
|
Removes all previously configured instances that attach to the specified
|
||||||
|
attachment.
|
||||||
|
If
|
||||||
|
.Ar attachment
|
||||||
|
ends with a
|
||||||
|
.Dq * ,
|
||||||
|
all instances attaching to all the variants of
|
||||||
|
.Ar attachment
|
||||||
|
are removed.
|
||||||
|
.It Ic pseudo-device Ar device Op Ar number
|
||||||
|
Adds support for the specified pseudo-device.
|
||||||
|
The parameter
|
||||||
|
.Ar number
|
||||||
|
is passed to the initialisation function of the pseudo-device, usually to
|
||||||
|
indicate how many instances should be created.
|
||||||
|
It defaults to 1, and some pseudo-devices ignore that parameter.
|
||||||
|
.It Ic no pseudo-device Ar name
|
||||||
|
Removes support for the specified pseudo-device.
|
||||||
|
.It Ic makeoptions Ar name Ns = Ns Ar value Op , Ar name Ns += Ns Ar value \
|
||||||
|
Op , Ar ...
|
||||||
|
Adds or appends to a definition in the generated
|
||||||
|
.Pa Makefile .
|
||||||
|
A definition cannot be overriden, it must be removed before it can be added
|
||||||
|
again.
|
||||||
|
Optionally, if an option
|
||||||
|
.Pa makeoptions_\*[Lt]name\*[Gt]
|
||||||
|
is defined with
|
||||||
|
.Ic defparam ,
|
||||||
|
the
|
||||||
|
.Ar value
|
||||||
|
is defined as an option too.
|
||||||
|
.It Ic makeoptions Ar condition name Ns += Ns Ar value Op , Ar condition \
|
||||||
|
name Ns += Ns Ar value
|
||||||
|
Appends to a definition in the generated
|
||||||
|
.Pa Makefile .
|
||||||
|
.It Ic no makeoptions Ar name Op , Ar name Op , Ar ...
|
||||||
|
Removes one or more definitions from the generated
|
||||||
|
.Pa Makefile .
|
||||||
|
.It Ic select Ar name
|
||||||
|
Adds the specified attribute and its dependencies.
|
||||||
|
.It Ic no select Ar name
|
||||||
|
Removes the specified attribute and all the attributes which depend on it.
|
||||||
|
.El
|
||||||
|
.Sh FILES
|
||||||
|
The files are relative to the kernel source top directory (e.g.,
|
||||||
|
.Pa /usr/src/sys ) .
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width arch/${MACHINE}/conf/std.${MACHINE}
|
||||||
|
.It Pa arch/${MACHINE}/conf/std.${MACHINE}
|
||||||
|
Standard configuration for the given architecture.
|
||||||
|
This file should always be included.
|
||||||
|
.It Pa arch/${MACHINE}/conf/GENERIC
|
||||||
|
Standard options selection file for the given architecture.
|
||||||
|
Users should always start changing their main kernel configuration file by
|
||||||
|
editing a copy of this file.
|
||||||
|
.It Pa conf/files
|
||||||
|
Main options description file.
|
||||||
|
.El
|
||||||
|
.Sh EXAMPLES
|
||||||
|
.Xr config.samples 5
|
||||||
|
uses several examples to cover all the practical aspects of writing or
|
||||||
|
modifying a kernel configuration file.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr config 1 ,
|
||||||
|
.Xr options 4 ,
|
||||||
|
.Xr config.samples 5 ,
|
||||||
|
.Xr config 9
|
||||||
252
usr.bin/config/config.samples.5
Normal file
252
usr.bin/config/config.samples.5
Normal file
|
|
@ -0,0 +1,252 @@
|
||||||
|
.\" $NetBSD: config.samples.5,v 1.6 2014/03/06 15:00:21 riastradh Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2006 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.
|
||||||
|
.\"
|
||||||
|
.Dd June 4, 2006
|
||||||
|
.Dt CONFIG.SAMPLES 5
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm config.samples
|
||||||
|
.Nd kernel configuration file syntax examples
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Ss Devices, drivers and instances
|
||||||
|
For a given device, at most one driver will attach.
|
||||||
|
In order for a driver to attach, the kernel configuration file must include a
|
||||||
|
compatible instance of the driver for the location of the device.
|
||||||
|
The following lines from the
|
||||||
|
.Pa GENERIC
|
||||||
|
kernel configuration file of
|
||||||
|
.Nx Ns / Ns i386
|
||||||
|
are examples of instances of drivers:
|
||||||
|
.Bd -literal
|
||||||
|
pchb* at pci? dev ? function ? # PCI-Host bridges
|
||||||
|
pcib* at pci? dev ? function ? # PCI-ISA bridges
|
||||||
|
ppb* at pci? dev ? function ? # PCI-PCI bridges
|
||||||
|
|
||||||
|
siop* at pci? dev ? function ? # Symbios 53c8xx SCSI
|
||||||
|
esiop* at pci? dev ? function ? # Symbios 53c875 SCSI and newer
|
||||||
|
|
||||||
|
ix0 at isa? port 0x300 irq 10 # EtherExpress/16
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The first three instances allow three different drivers to attach to all the
|
||||||
|
matching devices found on any PCI bus.
|
||||||
|
This is the most generic case.
|
||||||
|
.Pp
|
||||||
|
The next two lines allow two distinct drivers to attach to any matching device
|
||||||
|
found on any PCI bus, but those two drivers are special because they both
|
||||||
|
support some of the same devices.
|
||||||
|
Each of the driver has a matching function that returns their score for the
|
||||||
|
device that is being considered.
|
||||||
|
.Xr autoconf 9
|
||||||
|
decides at run-time which driver will attach.
|
||||||
|
Of course, it is deterministic so if the user wants to change the driver that
|
||||||
|
attaches to the device, the instance of the other driver will have to be
|
||||||
|
removed, e.g. by commenting it out.
|
||||||
|
.Pp
|
||||||
|
The last line configures an instance of an ISA device.
|
||||||
|
Unlike the PCI bus, the ISA bus cannot discover the devices that are present on
|
||||||
|
the bus.
|
||||||
|
The driver has to try accessing the device in order to discover it.
|
||||||
|
That implies locators must be specified to some extent: a driver would
|
||||||
|
usually need the base address of the device, some need the IRQ line that the
|
||||||
|
device is configured to use, though some others would just try a set of known
|
||||||
|
values, at the risk of badly interacting with other devices on the bus.
|
||||||
|
.Ss Hard-wiring kernel configuration
|
||||||
|
This technique consists in specifying exactly the location of the devices on a
|
||||||
|
given system.
|
||||||
|
In the general case it has very little use, because it does not change the size
|
||||||
|
of the kernel, and it will prevent it from finding devices in case the hardware
|
||||||
|
changes, even slightly.
|
||||||
|
.Pp
|
||||||
|
Let's consider the following excerpt of
|
||||||
|
.Xr dmesg 8
|
||||||
|
output:
|
||||||
|
.Bd -literal
|
||||||
|
auich0 at pci0 dev 31 function 5: i82801DB/DBM (ICH4/ICH4M) AC-97 Audio
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Xr auich 4
|
||||||
|
driver (which controls Intel's AC-97 audio chips) attached there because of the
|
||||||
|
following instance of
|
||||||
|
.Pa GENERIC :
|
||||||
|
.Bd -literal
|
||||||
|
auich* at pci? dev ? function ?
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Hard-wiring that instance means re-writing it to the following:
|
||||||
|
.Bd -literal
|
||||||
|
auich0 at pci0 dev 31 function 5
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
and that way,
|
||||||
|
.Ar auich0
|
||||||
|
will attach to that specific location, or will not attach.
|
||||||
|
.Ss Removing options and drivers
|
||||||
|
When two kernel configurations differ by a very small number of changes, it is
|
||||||
|
easier to manage them by having one include the other, and add or remove the
|
||||||
|
differences.
|
||||||
|
Removing options and drivers is also useful in the situation of a user who
|
||||||
|
wants to follow the development of
|
||||||
|
.Nx :
|
||||||
|
drivers and options get added to the configuration files found in the source
|
||||||
|
tree, such as
|
||||||
|
.Pa GENERIC ,
|
||||||
|
so one can include it and remove all options and drivers that are not relevant
|
||||||
|
to the considered system.
|
||||||
|
Additions to
|
||||||
|
.Pa GENERIC
|
||||||
|
will then automatically be followed and used in case they are relevant.
|
||||||
|
.Pp
|
||||||
|
While negating an options (with
|
||||||
|
.Ic no options )
|
||||||
|
is unambiguous, it is not as clear for devices instances.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Ic no Ar instance definition
|
||||||
|
statements of
|
||||||
|
.Xr config 1
|
||||||
|
syntax only apply on the current state of the configuration file, not on the
|
||||||
|
resulting kernel binary.
|
||||||
|
.Xr autoconf 9
|
||||||
|
has no knowledge of instance negation, thus it is currently impossible to
|
||||||
|
express the following in a kernel configuration file:
|
||||||
|
.Bd -ragged -offset indent
|
||||||
|
.Do I want support for
|
||||||
|
.Xr ath 4
|
||||||
|
attaching at
|
||||||
|
.Xr pci 4 ,
|
||||||
|
but I do not want any instance of
|
||||||
|
.Xr ath 4
|
||||||
|
attaching at
|
||||||
|
.Ar pci3 .
|
||||||
|
.Dc
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
For a real-world use of
|
||||||
|
.Ic no device at Ar instance
|
||||||
|
consider the following, taken from
|
||||||
|
.Nx Ns / Ns i386 :
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
include "arch/i386/conf/GENERIC"
|
||||||
|
|
||||||
|
acpi0 at mainbus?
|
||||||
|
|
||||||
|
com* at acpi?
|
||||||
|
[... more instances of legacy devices attaching at acpi? ...]
|
||||||
|
|
||||||
|
no device at isa0
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
One could actually live without the
|
||||||
|
.Ar isa0
|
||||||
|
instance, as all the legacy devices are attached at
|
||||||
|
.Ar acpi0 .
|
||||||
|
But unfortunately, dependencies on the
|
||||||
|
.Ar isa
|
||||||
|
attribute are not well registered all through the source tree, so an instance
|
||||||
|
of the
|
||||||
|
.Xr isa 4
|
||||||
|
driver is required to compile a kernel.
|
||||||
|
So while:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
no isa*
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
is what is intended, the
|
||||||
|
.Xr isa 4
|
||||||
|
instance itself must be kept, and that is precisely the difference made by:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
no device at isa0
|
||||||
|
.Ed
|
||||||
|
.Ss Interface attributes
|
||||||
|
.Em Interface attributes
|
||||||
|
are a subtlety of
|
||||||
|
.Xr config 1
|
||||||
|
and
|
||||||
|
.Xr autoconf 9 ,
|
||||||
|
which often confuses users and utilities that parse
|
||||||
|
.Xr dmesg 8
|
||||||
|
output to manipulate kernel configuration files.
|
||||||
|
What they are is best shown by the following example.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Xr dmesg 8
|
||||||
|
output look like this:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
auvia0 at pci0 dev 17 function 5: VIA Technologies VT8235 AC'97 Audio (rev 0x50)
|
||||||
|
audio0 at auvia0: full duplex, mmap, independent
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
while the kernel configuration look like this:
|
||||||
|
.Bd -literal
|
||||||
|
auvia* at pci? dev ? function ?
|
||||||
|
audio* at audiobus?
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
It is not obvious from the kernel configuration file that an
|
||||||
|
.Xr audio 4
|
||||||
|
device can attach at an
|
||||||
|
.Xr auvia 4
|
||||||
|
device.
|
||||||
|
.Ar audiobus
|
||||||
|
is an
|
||||||
|
.Em interface attribute ,
|
||||||
|
exposed by
|
||||||
|
.Ar auvia .
|
||||||
|
.Pp
|
||||||
|
Of course, it is possible to specify
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
audio* at auvia?
|
||||||
|
.Ed
|
||||||
|
in the kernel configuration file, but then one instance per audio controller
|
||||||
|
would be needed.
|
||||||
|
.Em Interface attributes
|
||||||
|
reflect the fact there is a standard way to attach a device to its parent, no
|
||||||
|
matter what the latter is precisely.
|
||||||
|
It also means lower maintainance of the kernel configuration files because
|
||||||
|
drivers for audio controllers are added more easily.
|
||||||
|
.Pp
|
||||||
|
Most attachments are done through
|
||||||
|
.Em interface attributes ,
|
||||||
|
although only a few of them are specified that way in the configuration files
|
||||||
|
found in the tree.
|
||||||
|
Another example of such an attribute is
|
||||||
|
.Ar ata :
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
viaide0 at pci0 dev 17 function 1
|
||||||
|
atabus0 at viaide0 channel 0
|
||||||
|
|
||||||
|
viaide* at pci? dev ? function ?
|
||||||
|
atabus* at ata?
|
||||||
|
.Ed
|
||||||
|
.\" Suggested section, maybe for later:
|
||||||
|
.\" .Ss Using a third-party driver
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr config 1 ,
|
||||||
|
.Xr options 4 ,
|
||||||
|
.Xr config 5 ,
|
||||||
|
.Xr dmesg 8
|
||||||
666
usr.bin/config/defs.h
Normal file
666
usr.bin/config/defs.h
Normal file
|
|
@ -0,0 +1,666 @@
|
||||||
|
/* $NetBSD: defs.h,v 1.93 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: @(#)config.h 8.1 (Berkeley) 6/6/93
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* defs.h: Global definitions for "config"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_NBTOOL_CONFIG_H
|
||||||
|
#include "nbtool_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
|
||||||
|
#if !defined(MAKE_BOOTSTRAP) && defined(BSD)
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* 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);
|
||||||
622
usr.bin/config/files.c
Normal file
622
usr.bin/config/files.c
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: files.c,v 1.35 2015/09/04 21:32:54 uebayasi Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <util.h>
|
||||||
|
#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
|
||||||
2431
usr.bin/config/gram.c
Normal file
2431
usr.bin/config/gram.c
Normal file
File diff suppressed because it is too large
Load Diff
89
usr.bin/config/gram.h
Normal file
89
usr.bin/config/gram.h
Normal file
|
|
@ -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_ */
|
||||||
1450
usr.bin/config/gram.y
Normal file
1450
usr.bin/config/gram.y
Normal file
File diff suppressed because it is too large
Load Diff
456
usr.bin/config/hash.c
Normal file
456
usr.bin/config/hash.c
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: hash.c,v 1.11 2014/10/29 17:14:50 christos Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <util.h>
|
||||||
|
#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);
|
||||||
208
usr.bin/config/lint.c
Normal file
208
usr.bin/config/lint.c
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: lint.c,v 1.15 2014/10/29 17:14:50 christos Exp $");
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
2037
usr.bin/config/main.c
Normal file
2037
usr.bin/config/main.c
Normal file
File diff suppressed because it is too large
Load Diff
241
usr.bin/config/mkdevsw.c
Normal file
241
usr.bin/config/mkdevsw.c
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: mkdevsw.c,v 1.14 2015/09/03 13:53:36 uebayasi Exp $");
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
#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 <sys/param.h>\n"
|
||||||
|
"#include <sys/conf.h>\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);
|
||||||
|
}
|
||||||
547
usr.bin/config/mkheaders.c
Normal file
547
usr.bin/config/mkheaders.c
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: mkheaders.c,v 1.29 2015/09/03 13:53:36 uebayasi Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include "defs.h"
|
||||||
|
|
||||||
|
#include <crc_extern.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
510
usr.bin/config/mkioconf.c
Normal file
510
usr.bin/config/mkioconf.c
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: mkioconf.c,v 1.32 2015/09/03 13:53:36 uebayasi Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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 <sys/param.h>\n"
|
||||||
|
"#include <sys/conf.h>\n"
|
||||||
|
"#include <sys/device.h>\n"
|
||||||
|
"#include <sys/mount.h>\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");
|
||||||
|
}
|
||||||
598
usr.bin/config/mkmakefile.c
Normal file
598
usr.bin/config/mkmakefile.c
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: mkmakefile.c,v 1.68 2015/09/04 10:16:35 uebayasi Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <util.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
164
usr.bin/config/mkswap.c
Normal file
164
usr.bin/config/mkswap.c
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: mkswap.c,v 1.10 2015/09/03 13:53:36 uebayasi Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <err.h>
|
||||||
|
#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 <sys/param.h>\n"
|
||||||
|
"#include <sys/conf.h>\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);
|
||||||
|
}
|
||||||
352
usr.bin/config/pack.c
Normal file
352
usr.bin/config/pack.c
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: pack.c,v 1.10 2015/09/12 19:11:13 joerg Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <util.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
3094
usr.bin/config/scan.c
Normal file
3094
usr.bin/config/scan.c
Normal file
File diff suppressed because it is too large
Load Diff
638
usr.bin/config/scan.l
Normal file
638
usr.bin/config/scan.l
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: scan.l,v 1.25 2015/09/04 10:16:35 uebayasi Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <util.h>
|
||||||
|
#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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
<IGNORED>\n {
|
||||||
|
yyline++;
|
||||||
|
}
|
||||||
|
|
||||||
|
<IGNORED>. /* 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]; }
|
||||||
|
<*><<EOF>> {
|
||||||
|
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;
|
||||||
|
}
|
||||||
2177
usr.bin/config/sem.c
Normal file
2177
usr.bin/config/sem.c
Normal file
File diff suppressed because it is too large
Load Diff
91
usr.bin/config/sem.h
Normal file
91
usr.bin/config/sem.h
Normal file
|
|
@ -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;
|
||||||
575
usr.bin/config/util.c
Normal file
575
usr.bin/config/util.c
Normal file
|
|
@ -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 <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: util.c,v 1.20 2015/09/01 13:42:48 uebayasi Exp $");
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <err.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user