mkoptions.c revision 72684
1/* 2 * Copyright (c) 1995 Peter Wemm 3 * Copyright (c) 1980, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the University of 17 * California, Berkeley and its contributors. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#ifndef lint 36#if 0 37static char sccsid[] = "@(#)mkheaders.c 8.1 (Berkeley) 6/6/93"; 38#endif 39static const char rcsid[] = 40 "$FreeBSD: head/usr.sbin/config/mkoptions.c 72684 2001-02-19 04:43:21Z peter $"; 41#endif /* not lint */ 42 43/* 44 * Make all the .h files for the optional entries 45 */ 46 47#include <ctype.h> 48#include <err.h> 49#include <stdio.h> 50#include <string.h> 51#include <sys/param.h> 52#include "config.h" 53#include "y.tab.h" 54 55static struct users { 56 int u_default; 57 int u_min; 58 int u_max; 59} users= { 8, 2, 512 }; 60 61static char *lower(char *); 62static void read_options(void); 63static void do_option(char *); 64static char *tooption(char *); 65 66void 67options(void) 68{ 69 char buf[40]; 70 struct cputype *cp; 71 struct opt_list *ol; 72 struct opt *op; 73 74 /* Fake the cpu types as options. */ 75 for (cp = cputype; cp != NULL; cp = cp->cpu_next) { 76 op = (struct opt *)malloc(sizeof(*op)); 77 memset(op, 0, sizeof(*op)); 78 op->op_name = ns(cp->cpu_name); 79 op->op_next = opt; 80 opt = op; 81 } 82 83 if (maxusers == 0) { 84 printf("maxusers not specified; %d assumed\n", users.u_default); 85 maxusers = users.u_default; 86 } else if (maxusers < users.u_min) { 87 printf("minimum of %d maxusers assumed\n", users.u_min); 88 maxusers = users.u_min; 89 } else if (maxusers > users.u_max) 90 printf("warning: maxusers > %d (%d)\n", users.u_max, maxusers); 91 92 /* Fake MAXUSERS as an option. */ 93 op = (struct opt *)malloc(sizeof(*op)); 94 memset(op, 0, sizeof(*op)); 95 op->op_name = ns("MAXUSERS"); 96 snprintf(buf, sizeof(buf), "%d", maxusers); 97 op->op_value = ns(buf); 98 op->op_next = opt; 99 opt = op; 100 101 read_options(); 102 for (ol = otab; ol != 0; ol = ol->o_next) 103 do_option(ol->o_name); 104 for (op = opt; op; op = op->op_next) { 105 if (!op->op_ownfile && strncmp(op->op_name, "DEV_", 4)) { 106 printf("%s:%d: unknown option \"%s\"\n", 107 PREFIX, op->op_line, op->op_name); 108 exit(1); 109 } 110 } 111} 112 113/* 114 * Generate an <options>.h file 115 */ 116 117static void 118do_option(char *name) 119{ 120 char *file, *inw; 121 const char *basefile; 122 struct opt_list *ol; 123 struct opt *op, *op_head, *topp; 124 FILE *inf, *outf; 125 char *value; 126 char *oldvalue; 127 int seen; 128 int tidy; 129 130 file = tooption(name); 131 132 /* 133 * Check to see if the option was specified.. 134 */ 135 value = NULL; 136 for (op = opt; op; op = op->op_next) { 137 if (eq(name, op->op_name)) { 138 oldvalue = value; 139 value = op->op_value; 140 if (value == NULL) 141 value = ns("1"); 142 if (oldvalue != NULL && !eq(value, oldvalue)) 143 printf( 144 "%s:%d: option \"%s\" redefined from %s to %s\n", 145 PREFIX, op->op_line, op->op_name, oldvalue, 146 value); 147 op->op_ownfile++; 148 } 149 } 150 151 remember(file); 152 inf = fopen(file, "r"); 153 if (inf == 0) { 154 outf = fopen(file, "w"); 155 if (outf == 0) 156 err(1, "%s", file); 157 158 /* was the option in the config file? */ 159 if (value) { 160 fprintf(outf, "#define %s %s\n", name, value); 161 } /* else empty file */ 162 163 (void) fclose(outf); 164 return; 165 } 166 basefile = ""; 167 for (ol = otab; ol != 0; ol = ol->o_next) 168 if (eq(name, ol->o_name)) { 169 basefile = ol->o_file; 170 break; 171 } 172 oldvalue = NULL; 173 op_head = NULL; 174 seen = 0; 175 tidy = 0; 176 for (;;) { 177 char *cp; 178 char *invalue; 179 180 /* get the #define */ 181 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 182 break; 183 /* get the option name */ 184 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 185 break; 186 inw = ns(inw); 187 /* get the option value */ 188 if ((cp = get_word(inf)) == 0 || cp == (char *)EOF) 189 break; 190 /* option value */ 191 invalue = ns(cp); /* malloced */ 192 if (eq(inw, name)) { 193 oldvalue = invalue; 194 invalue = value; 195 seen++; 196 } 197 for (ol = otab; ol != 0; ol = ol->o_next) 198 if (eq(inw, ol->o_name)) 199 break; 200 if (!eq(inw, name) && !ol) { 201 printf("WARNING: unknown option `%s' removed from %s\n", 202 inw, file); 203 tidy++; 204 } else if (ol != NULL && !eq(basefile, ol->o_file)) { 205 printf("WARNING: option `%s' moved from %s to %s\n", 206 inw, basefile, ol->o_file); 207 tidy++; 208 } else { 209 op = (struct opt *) malloc(sizeof *op); 210 bzero(op, sizeof(*op)); 211 op->op_name = inw; 212 op->op_value = invalue; 213 op->op_next = op_head; 214 op_head = op; 215 } 216 217 /* EOL? */ 218 cp = get_word(inf); 219 if (cp == (char *)EOF) 220 break; 221 } 222 (void) fclose(inf); 223 if (!tidy && ((value == NULL && oldvalue == NULL) || 224 (value && oldvalue && eq(value, oldvalue)))) { 225 for (op = op_head; op != NULL; op = topp) { 226 topp = op->op_next; 227 free(op->op_name); 228 free(op->op_value); 229 free(op); 230 } 231 return; 232 } 233 234 if (value && !seen) { 235 /* New option appears */ 236 op = (struct opt *) malloc(sizeof *op); 237 bzero(op, sizeof(*op)); 238 op->op_name = ns(name); 239 op->op_value = value ? ns(value) : NULL; 240 op->op_next = op_head; 241 op_head = op; 242 } 243 244 outf = fopen(file, "w"); 245 if (outf == 0) 246 err(1, "%s", file); 247 for (op = op_head; op != NULL; op = topp) { 248 /* was the option in the config file? */ 249 if (op->op_value) { 250 fprintf(outf, "#define %s %s\n", 251 op->op_name, op->op_value); 252 } 253 topp = op->op_next; 254 free(op->op_name); 255 free(op->op_value); 256 free(op); 257 } 258 (void) fclose(outf); 259} 260 261/* 262 * Find the filename to store the option spec into. 263 */ 264static char * 265tooption(char *name) 266{ 267 static char hbuf[MAXPATHLEN]; 268 char nbuf[MAXPATHLEN]; 269 struct opt_list *po; 270 271 /* "cannot happen"? the otab list should be complete.. */ 272 (void) strlcpy(nbuf, "options.h", sizeof(nbuf)); 273 274 for (po = otab ; po != 0; po = po->o_next) { 275 if (eq(po->o_name, name)) { 276 strlcpy(nbuf, po->o_file, sizeof(nbuf)); 277 break; 278 } 279 } 280 281 (void) strlcpy(hbuf, path(nbuf), sizeof(hbuf)); 282 return (hbuf); 283} 284 285/* 286 * read the options and options.<machine> files 287 */ 288static void 289read_options(void) 290{ 291 FILE *fp; 292 char fname[MAXPATHLEN]; 293 char *wd, *this, *val; 294 struct opt_list *po; 295 int first = 1; 296 char genopt[MAXPATHLEN]; 297 298 otab = 0; 299 if (ident == NULL) { 300 printf("no ident line specified\n"); 301 exit(1); 302 } 303 (void) snprintf(fname, sizeof(fname), "../../conf/options"); 304openit: 305 fp = fopen(fname, "r"); 306 if (fp == 0) { 307 return; 308 } 309next: 310 wd = get_word(fp); 311 if (wd == (char *)EOF) { 312 (void) fclose(fp); 313 if (first == 1) { 314 first++; 315 (void) snprintf(fname, sizeof fname, "../../conf/options.%s", machinename); 316 fp = fopen(fname, "r"); 317 if (fp != 0) 318 goto next; 319 (void) snprintf(fname, sizeof fname, "options.%s", machinename); 320 goto openit; 321 } 322 if (first == 2) { 323 first++; 324 (void) snprintf(fname, sizeof fname, "options.%s", raisestr(ident)); 325 fp = fopen(fname, "r"); 326 if (fp != 0) 327 goto next; 328 } 329 return; 330 } 331 if (wd == 0) 332 goto next; 333 if (wd[0] == '#') 334 { 335 while (((wd = get_word(fp)) != (char *)EOF) && wd) 336 ; 337 goto next; 338 } 339 this = ns(wd); 340 val = get_word(fp); 341 if (val == (char *)EOF) 342 return; 343 if (val == 0) { 344 char *s = ns(this); 345 (void) snprintf(genopt, sizeof(genopt), "opt_%s.h", lower(s)); 346 val = genopt; 347 free(s); 348 } 349 val = ns(val); 350 351 for (po = otab ; po != 0; po = po->o_next) { 352 if (eq(po->o_name, this)) { 353 printf("%s: Duplicate option %s.\n", 354 fname, this); 355 exit(1); 356 } 357 } 358 359 po = (struct opt_list *) malloc(sizeof *po); 360 bzero(po, sizeof(*po)); 361 po->o_name = this; 362 po->o_file = val; 363 po->o_next = otab; 364 otab = po; 365 366 goto next; 367} 368 369static char * 370lower(char *str) 371{ 372 char *cp = str; 373 374 while (*str) { 375 if (isupper(*str)) 376 *str = tolower(*str); 377 str++; 378 } 379 return (cp); 380} 381