%union { char *str; int val; } %token ARCH %token COMMA %token CONFIG %token CPU %token NOCPU %token DEVICE %token NODEVICE %token ENV %token ENVVAR %token EQUALS %token PLUSEQUALS %token HINTS %token IDENT %token MAXUSERS %token PROFILE %token OPTIONS %token NOOPTION %token MAKEOPTIONS %token NOMAKEOPTION %token SEMICOLON %token INCLUDE %token FILES %token ENVLINE %token ID %token NUMBER %type Save_id %type Opt_value %type Dev %token PATH %{ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1988, 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. * * @(#)config.y 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ #include #include #include #include #include #include "config.h" stailq_device dtab; char *ident; char *env; int yyline; const char *yyfile; stailq_file_list ftab; stailq_files_name fntab; char errbuf[80]; int maxusers; #define ns(s) strdup(s) int include(const char *, int); static void newfile(char *name); static void newenvvar(char *name, bool is_file); static char * devopt(char *dev) { char *ret = (char *) malloc(strlen(dev) + 5); sprintf(ret, "DEV_%s", dev); raisestr(ret); return ret; } %} %% Configuration: Many_specs ; Many_specs: Many_specs Spec | /* lambda */ ; Spec: Device_spec SEMICOLON | Config_spec SEMICOLON | INCLUDE PATH SEMICOLON { if (incignore == 0) include($2, 0); }; | INCLUDE ID SEMICOLON { if (incignore == 0) include($2, 0); }; | FILES ID SEMICOLON { newfile($2); }; | SEMICOLON | error SEMICOLON ; Config_spec: ARCH Save_id { if (machinename != NULL && !eq($2, machinename)) errx(1, "%s:%d: only one machine directive is allowed", yyfile, yyline); machinename = $2; machinearch = $2; } | ARCH Save_id Save_id { if (machinename != NULL && !(eq($2, machinename) && eq($3, machinearch))) errx(1, "%s:%d: only one machine directive is allowed", yyfile, yyline); machinename = $2; machinearch = $3; } | CPU Save_id { cputype.push_front (cputype_t ($2)); } | NOCPU Save_id { for (slist_cputype::iterator cp = cputype.begin(); cp != cputype.end();) { slist_cputype::iterator candidate_for_removal = cp; cp++; if (candidate_for_removal->cpu_name.compare ($2) == 0) { cputype.erase (candidate_for_removal); } } } | OPTIONS Opt_list | NOOPTION NoOpt_list | MAKEOPTIONS Mkopt_list | NOMAKEOPTION Save_id { mkopt.rmopt($2); } | IDENT ID { ident = $2; } | System_spec | MAXUSERS NUMBER { maxusers = $2; } | PROFILE NUMBER { profiling = $2; } | ENV ID { newenvvar($2, true); } | ENVVAR ENVLINE { newenvvar($2, false); } | HINTS ID { hints.push_front (hint ($2)); } System_spec: CONFIG System_id System_parameter_list { errx(1, "%s:%d: root/dump/swap specifications obsolete", yyfile, yyline); } | CONFIG System_id ; System_id: Save_id { mkopt.newopt("KERNEL", $1, false); }; System_parameter_list: System_parameter_list ID | ID ; Opt_list: Opt_list COMMA Option | Option ; NoOpt_list: NoOpt_list COMMA NoOption | NoOption ; Option: Save_id { opt.newopt($1, NULL, false); if (strchr($1, '=') != NULL) errx(1, "%s:%d: The `=' in options should not be " "quoted", yyfile, yyline); } | Save_id EQUALS Opt_value { opt.newopt($1, $3, false); } ; NoOption: Save_id { opt.rmopt ($1); }; Opt_value: ID { $$ = $1; } | NUMBER { char buf[80]; (void) snprintf(buf, sizeof(buf), "%d", $1); $$ = ns(buf); } ; Save_id: ID { $$ = $1; } ; Mkopt_list: Mkopt_list COMMA Mkoption | Mkoption ; Mkoption: Save_id { mkopt.newopt($1, "", false); } | Save_id EQUALS { mkopt.newopt($1, "", false); } | Save_id EQUALS Opt_value { mkopt.newopt($1, $3, 0); } | Save_id PLUSEQUALS Opt_value { mkopt.newopt($1, $3, 1); } ; Dev: ID { $$ = $1; } ; Device_spec: DEVICE Dev_list | NODEVICE NoDev_list ; Dev_list: Dev_list COMMA Device | Device ; NoDev_list: NoDev_list COMMA NoDevice | NoDevice ; Device: Dev { opt.newopt(devopt($1), "1", false); /* and the device part */ dtab.newdev($1); } NoDevice: Dev { char *s = devopt($1); opt.rmopt (s); free(s); /* and the device part */ dtab.rmdev($1); } ; %% void yyerror(const char *s) { errx(1, "%s:%d: %s", yyfile, yyline + 1, s); } int yywrap(void) { if (found_defaults) { if (freopen(PREFIX, "r", stdin) == NULL) err(2, "%s", PREFIX); yyfile = PREFIX; yyline = 0; found_defaults = 0; return 0; } return 1; } /* * Add a new file to the list of files. */ static void newfile(char *name) { fntab.push_back (files_name(name)); } static void newenvvar(char *name, bool is_file) { envvars.push_front (envvar (name,is_file)); } stailq_device::iterator stailq_device::find(const char *name) { iterator dp; for (dp = begin(); dp != end(); dp++) { if (dp->d_name.compare (name) == 0) break; } return (dp); } /* * Add a device to the list of devices. */ void stailq_device::newdev(const char *name) { const iterator dp = find(name); if (dp != end()) { fprintf(stderr, "WARNING: duplicate device `%s' encountered.\n", name); } else { push_back (device (name)); } } /* * Schedule a device to removal. */ void stailq_device::rmdev (const char *device_name) { stailq_device::iterator dp = find(device_name); if (dp != end()) { erase (dp); } } /* * Find an option in the list of options. */ slist_opt::iterator slist_opt::find(const char *name) { iterator op; for (op = begin(); op != end(); op++) { if (op->op_name.compare (name) == 0) break; } return (op); } /* * Add an option to the list of options. */ void slist_opt::newopt ( const char *name, /* Never NULL */ const char *value, /* May be NULL */ bool append ) { /* * Ignore inclusions listed explicitly for configuration files. */ if (eq(name, OPT_AUTOGEN)) { incignore = 1; return; } iterator existing_option = find(name); if (existing_option != end()) { if (append) { existing_option->append (value); } else { fprintf(stderr,"WARNING: duplicate option `%s' encountered.\n", name); } } else { push_front (opt_t (name,value)); } } /* * Remove an option from the list of options. */ void slist_opt::rmopt (const char *name) { iterator existing_option = find(name); if (existing_option != end()) { erase (existing_option); } }