/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratories.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)gram.y 8.1 (Berkeley) 6/6/93
*/
/*
* A complete configuration consists of both the selection part (a
* kernel config such as GENERIC or SKYNET, plus also the various
* std.* files), which selects the material to be in the kernel, and
* also the definition part (files, files.*, etc.) that declares what
* material is available to be placed in kernels.
*
* The two parts have almost entirely separate syntaxes. This grammar
* covers both of them. When config is run on a kernel configuration
* file, the std.* file for the port is included explicitly. The
* files.* files are included implicitly when the std.* file declares
* the machine type.
*
* The machine spec, which brings in the definition part, must appear
* before all configuration material except for the "topthings"; these
* are the "source" and "build" declarations that tell config where
* things are. These are not used by default.
*
* A previous version of this comment contained the following text:
*
* Note that we do not have sufficient keywords to enforce any
* order between elements of "topthings" without introducing
* shift/reduce conflicts. Instead, check order requirements in
* the C code.
*
* As of March 2012 this comment makes no sense, as there are only two
* topthings and no reason for them to be forcibly ordered.
* Furthermore, the statement about conflicts is false.
*/
/* list of filesystems */
fs_list:
fsoption
| fs_list ',' fsoption
;
/* one filesystem */
fsoption:
WORD { addfsoption($1); }
;
/* list of filesystems that had NO in front */
no_fs_list:
no_fsoption
| no_fs_list ',' no_fsoption
;
/* one filesystem that had NO in front */
no_fsoption:
WORD { delfsoption($1, nowarn); }
;
/* list of make options */
/* XXX why is this right-recursive? */
mkopt_list:
mkoption
| mkopt_list ',' mkoption
;
/* one make option */
mkoption:
mkvarname '=' value { addmkoption($1, $3); }
| mkvarname PLUSEQ value { appendmkoption($1, $3); }
;
/* list of make options that had NO in front */
no_mkopt_list:
no_mkoption
| no_mkopt_list ',' no_mkoption
;
/* one make option that had NO in front */
/* XXX shouldn't this be mkvarname rather than WORD? */
no_mkoption:
WORD { delmkoption($1, nowarn); }
;
/* list of options */
opt_list:
option
| opt_list ',' option
;
/* one option */
option:
WORD { addoption($1, NULL); }
| WORD '=' value { addoption($1, $3); }
;
/* list of options that had NO in front */
no_opt_list:
no_option
| no_opt_list ',' no_option
;
/* one option that had NO in front */
no_option:
WORD { deloption($1, nowarn); }
;
/* the name in "config name root on ..." */
conf:
WORD {
conf.cf_name = $1;
conf.cf_where.w_srcline = currentline();
conf.cf_fstype = NULL;
conf.cf_root = NULL;
conf.cf_dump = NULL;
}
;
/* major and minor device number */
major_minor:
MAJOR NUMBER MINOR NUMBER { $$ = (int64_t)makedev($2.val, $4.val); }
;
/* filesystem type for root fs specification */
fs_spec:
TYPE '?' { setfstype(&conf.cf_fstype, intern("?")); }
| TYPE WORD { setfstype(&conf.cf_fstype, $2); }
;
/* zero or more additional system parameters */
sysparam_list:
/* empty */
| sysparam_list sysparam
;
/* one additional system parameter (there's only one: dumps) */
sysparam:
DUMPS on_opt dev_spec { setconf(&conf.cf_dump, "dumps", $3); }
;
/* number of pseudo devices to configure (which is optional) */
npseudo:
/* empty */ { $$ = 1; }
| int32 { $$ = $1; }
;
/* name of a device to configure */
device_instance:
WORD { $$ = $1; }
| WORD '*' { $$ = starref($1); }
;
/* name of a device to configure an attachment to */
attachment:
ROOT { $$ = NULL; }
| WORD { $$ = $1; }
| WORD '?' { $$ = wildref($1); }
;
/* zero or more locators */
locators:
/* empty */ { $$ = NULL; }
| locators locator { $$ = $2; app($2, $1); }
;
/* one locator */
locator:
WORD '?' { $$ = MK3(loc, $1, NULL, 0); }
| WORD values { $$ = namelocvals($1, $2); }
;
/*
* We succeeded; commit to keeping everything that's been allocated so
* far and clear the stack.
*/
static void
wrap_continue(void)
{
wrap_depth = 0;
}
/*
* We failed; destroy all the objects allocated.
*/
static void
wrap_cleanup(void)
{
unsigned i;
/*
* Destroy each item. Note that because everything allocated
* is entered on the list separately, lists and trees need to
* have their links blanked before being destroyed. Also note
* that strings are interned elsewhere and not handled by this
* mechanism.
*/
for (i=0; i<wrap_depth; i++) {
switch (wrapstack[i].typecode) {
case WRAP_CODE_nvlist:
nvfree(wrapstack[i].ptr);
break;
case WRAP_CODE_defoptlist:
{
struct defoptlist *dl = wrapstack[i].ptr;
/*
* Instantiate the wrapper functions.
*
* Each one calls wrap_alloc to save the pointer and then returns the
* pointer again; these need to be generated with the preprocessor in
* order to be typesafe.
*/
#define DEF_ALLOCWRAP(t) \
static struct t * \
wrap_mk_##t(struct t *arg) \
{ \
wrap_alloc(arg, WRAP_CODE_##t); \
return arg; \
}
/*
* Define attributes for all the given names
*/
if (defattr(machine, NULL, NULL, 0) != 0 ||
(machinearch != NULL &&
defattr(machinearch, NULL, NULL, 0) != 0))
exit(1);
for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) {
if (defattr(nv->nv_name, NULL, NULL, 0) != 0)
exit(1);
}
/*
* Set up the file inclusion stack. This empty include tells
* the parser there are no more device definitions coming.
*/
if (include(_PATH_DEVNULL, ENDDEFS, 0, 0) != 0)
exit(1);
/* Include arch/${MACHINE}/conf/files.${MACHINE} */
(void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s",
machine, machine);
if (include(buf, ENDFILE, 0, 0) != 0)
exit(1);
/* Include any arch/${MACHINE_SUBARCH}/conf/files.${MACHINE_SUBARCH} */
for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) {
(void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s",
nv->nv_name, nv->nv_name);
if (include(buf, ENDFILE, 0, 0) != 0)
exit(1);
}
/* Include any arch/${MACHINE_ARCH}/conf/files.${MACHINE_ARCH} */
if (machinearch != NULL)
(void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s",
machinearch, machinearch);
else
strlcpy(buf, _PATH_DEVNULL, sizeof(buf));
if (include(buf, ENDFILE, 0, 0) != 0)
exit(1);
/*
* Include the global conf/files. As the last thing
* pushed on the stack, it will be processed first.
*/
if (include("conf/files", ENDFILE, 0, 0) != 0)
exit(1);
oktopackage = 1;
}
static void
check_maxpart(void)
{
if (maxpartitions <= 0 && ioconfname == NULL) {
stop("cannot proceed without maxpartitions specifier");
}
}
static void
check_version(void)
{
/*
* In essence, version is 0 and is not supported anymore
*/
if (version < CONFIG_MINVERSION)
stop("your sources are out of date -- please update.");
}
/*
* Prepend a blank entry to the locator definitions so the code in
* sem.c can distinguish "empty locator list" from "no locator list".
* XXX gross.
*/
static struct loclist *
present_loclist(struct loclist *ll)
{
struct loclist *ret;