import config command
This commit is contained in:
parent
ccee9c2e7b
commit
fee8e88355
|
|
@ -284,6 +284,7 @@
|
|||
./usr/bin/column minix-base
|
||||
./usr/bin/comm minix-base
|
||||
./usr/bin/compress minix-base
|
||||
./usr/bin/config minix-base
|
||||
./usr/bin/cpio minix-base
|
||||
./usr/bin/cprofalyze minix-base obsolete
|
||||
./usr/bin/crc minix-base
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
./usr/man/man1/comm.1 minix-man
|
||||
./usr/man/man1/command.1 minix-man obsolete
|
||||
./usr/man/man1/compress.1 minix-man
|
||||
./usr/man/man1/config.1 minix-man
|
||||
./usr/man/man1/continue.1 minix-man obsolete
|
||||
./usr/man/man1/cp.1 minix-man
|
||||
./usr/man/man1/cpio.1 minix-man
|
||||
|
|
@ -3268,6 +3269,8 @@
|
|||
./usr/man/man5/blacklistd.conf.5 minix-man
|
||||
./usr/man/man5/boot.cfg.5 minix-man
|
||||
./usr/man/man5/cdb.5 minix-man
|
||||
./usr/man/man5/config.5 minix-man
|
||||
./usr/man/man5/config.samples.5 minix-man
|
||||
./usr/man/man5/configfile.5 minix-man
|
||||
./usr/man/man5/cpio.5 minix-man
|
||||
./usr/man/man5/crontab.5 minix-man
|
||||
|
|
@ -3424,7 +3427,7 @@
|
|||
./usr/man/man8/pr_routes.8 minix-man
|
||||
./usr/man/man8/printroot.8 minix-man
|
||||
./usr/man/man8/pwd_mkdb.8 minix-man
|
||||
./usr/man/man8/pwdauth.8 minix-man obsolete
|
||||
./usr/man/man8/pwdauth.8 minix-man obsolete
|
||||
./usr/man/man8/rarpd.8 minix-man
|
||||
./usr/man/man8/rawspeed.8 minix-man
|
||||
./usr/man/man8/rdate.8 minix-man
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ SUBDIR= asa \
|
|||
banner basename \
|
||||
bzip2 bzip2recover cal calendar \
|
||||
checknr chpass cksum cmp col colcrt colrm \
|
||||
column comm csplit ctags cut \
|
||||
column comm config csplit ctags cut \
|
||||
deroff dirname du \
|
||||
env expand \
|
||||
false find finger flock fold fpr from \
|
||||
|
|
|
|||
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