mkoptions.c revision 55659
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 55659 2000-01-09 12:52:01Z bde $"; 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 "config.h" 52#include "y.tab.h" 53 54static struct users { 55 int u_default; 56 int u_min; 57 int u_max; 58} users[] = { 59 { 8, 2, 512 }, /* MACHINE_I386 */ 60 { 8, 2, 512 }, /* MACHINE_PC98 */ 61 { 8, 2, 512 }, /* MACHINE_ALPHA */ 62}; 63#define NUSERS (sizeof (users) / sizeof (users[0])) 64 65static char *lower __P((char *)); 66static void read_options __P((void)); 67static void do_option __P((char *)); 68static char *tooption __P((char *)); 69 70void 71options() 72{ 73 char buf[40]; 74 struct cputype *cp; 75 struct opt_list *ol; 76 struct opt *op; 77 struct users *up; 78 79 /* Fake the cpu types as options. */ 80 for (cp = cputype; cp != NULL; cp = cp->cpu_next) { 81 op = (struct opt *)malloc(sizeof(*op)); 82 memset(op, 0, sizeof(*op)); 83 op->op_name = ns(cp->cpu_name); 84 op->op_next = opt; 85 opt = op; 86 } 87 88 /* Initialize `maxusers'. */ 89 if ((unsigned)machine > NUSERS) { 90 printf("maxusers config info isn't present, using i386\n"); 91 up = &users[MACHINE_I386 - 1]; 92 } else 93 up = &users[machine - 1]; 94 if (maxusers == 0) { 95 printf("maxusers not specified; %d assumed\n", up->u_default); 96 maxusers = up->u_default; 97 } else if (maxusers < up->u_min) { 98 printf("minimum of %d maxusers assumed\n", up->u_min); 99 maxusers = up->u_min; 100 } else if (maxusers > up->u_max) 101 printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers); 102 103 /* Fake MAXUSERS as an option. */ 104 op = (struct opt *)malloc(sizeof(*op)); 105 memset(op, 0, sizeof(*op)); 106 op->op_name = "MAXUSERS"; 107 snprintf(buf, sizeof(buf), "%d", maxusers); 108 op->op_value = ns(buf); 109 op->op_next = opt; 110 opt = op; 111 112 read_options(); 113 for (ol = otab; ol != 0; ol = ol->o_next) 114 do_option(ol->o_name); 115} 116 117/* 118 * Generate an <options>.h file 119 */ 120 121static void 122do_option(name) 123 char *name; 124{ 125 char *basefile, *file, *inw; 126 struct opt_list *ol; 127 struct opt *op, *op_head, *topp; 128 FILE *inf, *outf; 129 char *value; 130 char *oldvalue; 131 int seen; 132 int tidy; 133 134 file = tooption(name); 135 136 /* 137 * Check to see if the option was specified.. 138 */ 139 value = NULL; 140 for (op = opt; op; op = op->op_next) { 141 if (eq(name, op->op_name)) { 142 oldvalue = value; 143 value = op->op_value; 144 if (value == NULL) 145 value = ns("1"); 146 if (oldvalue != NULL && !eq(value, oldvalue)) 147 printf( 148 "%s:%d: option \"%s\" redefined from %s to %s\n", 149 PREFIX, op->op_line, op->op_name, oldvalue, 150 value); 151 op->op_ownfile++; 152 } 153 } 154 155 inf = fopen(file, "r"); 156 if (inf == 0) { 157 outf = fopen(file, "w"); 158 if (outf == 0) 159 err(1, "%s", file); 160 161 /* was the option in the config file? */ 162 if (value) { 163 fprintf(outf, "#define %s %s\n", name, value); 164 } /* else empty file */ 165 166 (void) fclose(outf); 167 return; 168 } 169 basefile = ""; 170 for (ol = otab; ol != 0; ol = ol->o_next) 171 if (eq(name, ol->o_name)) { 172 basefile = ol->o_file; 173 break; 174 } 175 oldvalue = NULL; 176 op_head = NULL; 177 seen = 0; 178 tidy = 0; 179 for (;;) { 180 char *cp; 181 char *invalue; 182 183 /* get the #define */ 184 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 185 break; 186 /* get the option name */ 187 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 188 break; 189 inw = ns(inw); 190 /* get the option value */ 191 if ((cp = get_word(inf)) == 0 || cp == (char *)EOF) 192 break; 193 /* option value */ 194 invalue = ns(cp); /* malloced */ 195 if (eq(inw, name)) { 196 oldvalue = invalue; 197 invalue = value; 198 seen++; 199 } 200 for (ol = otab; ol != 0; ol = ol->o_next) 201 if (eq(inw, ol->o_name)) 202 break; 203 if (!eq(inw, name) && !ol) { 204 printf("WARNING: unknown option `%s' removed from %s\n", 205 inw, file); 206 tidy++; 207 } else if (ol != NULL && !eq(basefile, ol->o_file)) { 208 printf("WARNING: option `%s' moved from %s to %s\n", 209 inw, basefile, ol->o_file); 210 tidy++; 211 } else { 212 op = (struct opt *) malloc(sizeof *op); 213 bzero(op, sizeof(*op)); 214 op->op_name = inw; 215 op->op_value = invalue; 216 op->op_next = op_head; 217 op_head = op; 218 } 219 220 /* EOL? */ 221 cp = get_word(inf); 222 if (cp == (char *)EOF) 223 break; 224 } 225 (void) fclose(inf); 226 if (!tidy && ((value == NULL && oldvalue == NULL) || 227 (value && oldvalue && eq(value, oldvalue)))) { 228 for (op = op_head; op != NULL; op = topp) { 229 topp = op->op_next; 230 free(op->op_name); 231 free(op->op_value); 232 free(op); 233 } 234 return; 235 } 236 237 if (value && !seen) { 238 /* New option appears */ 239 op = (struct opt *) malloc(sizeof *op); 240 bzero(op, sizeof(*op)); 241 op->op_name = ns(name); 242 op->op_value = value ? ns(value) : NULL; 243 op->op_next = op_head; 244 op_head = op; 245 } 246 247 outf = fopen(file, "w"); 248 if (outf == 0) 249 err(1, "%s", file); 250 for (op = op_head; op != NULL; op = topp) { 251 /* was the option in the config file? */ 252 if (op->op_value) { 253 fprintf(outf, "#define %s %s\n", 254 op->op_name, op->op_value); 255 } 256 topp = op->op_next; 257 free(op->op_name); 258 free(op->op_value); 259 free(op); 260 } 261 (void) fclose(outf); 262} 263 264/* 265 * Find the filename to store the option spec into. 266 */ 267static char * 268tooption(name) 269 char *name; 270{ 271 static char hbuf[80]; 272 char nbuf[80]; 273 struct opt_list *po; 274 275 /* "cannot happen"? the otab list should be complete.. */ 276 (void) strcpy(nbuf, "options.h"); 277 278 for (po = otab ; po != 0; po = po->o_next) { 279 if (eq(po->o_name, name)) { 280 strcpy(nbuf, po->o_file); 281 break; 282 } 283 } 284 285 (void) strcpy(hbuf, path(nbuf)); 286 return (hbuf); 287} 288 289/* 290 * read the options and options.<machine> files 291 */ 292static void 293read_options() 294{ 295 FILE *fp; 296 char fname[80]; 297 char *wd, *this, *val; 298 struct opt_list *po; 299 int first = 1; 300 char genopt[80]; 301 302 otab = 0; 303 if (ident == NULL) { 304 printf("no ident line specified\n"); 305 exit(1); 306 } 307 (void) snprintf(fname, sizeof fname, "../../conf/options"); 308openit: 309 fp = fopen(fname, "r"); 310 if (fp == 0) { 311 return; 312 } 313next: 314 wd = get_word(fp); 315 if (wd == (char *)EOF) { 316 (void) fclose(fp); 317 if (first == 1) { 318 first++; 319 (void) snprintf(fname, sizeof fname, "../../conf/options.%s", machinename); 320 fp = fopen(fname, "r"); 321 if (fp != 0) 322 goto next; 323 (void) snprintf(fname, sizeof fname, "options.%s", machinename); 324 goto openit; 325 } 326 if (first == 2) { 327 first++; 328 (void) snprintf(fname, sizeof fname, "options.%s", raisestr(ident)); 329 fp = fopen(fname, "r"); 330 if (fp != 0) 331 goto next; 332 } 333 return; 334 } 335 if (wd == 0) 336 goto next; 337 if (wd[0] == '#') 338 { 339 while (((wd = get_word(fp)) != (char *)EOF) && wd) 340 ; 341 goto next; 342 } 343 this = ns(wd); 344 val = get_word(fp); 345 if (val == (char *)EOF) 346 return; 347 if (val == 0) { 348 char *s = ns(this); 349 (void) snprintf(genopt, sizeof genopt, "opt_%s.h", lower(s)); 350 val = genopt; 351 free(s); 352 } 353 val = ns(val); 354 355 for (po = otab ; po != 0; po = po->o_next) { 356 if (eq(po->o_name, this)) { 357 printf("%s: Duplicate option %s.\n", 358 fname, this); 359 exit(1); 360 } 361 } 362 363 po = (struct opt_list *) malloc(sizeof *po); 364 bzero(po, sizeof(*po)); 365 po->o_name = this; 366 po->o_file = val; 367 po->o_next = otab; 368 otab = po; 369 370 goto next; 371} 372 373static char * 374lower(str) 375 register char *str; 376{ 377 register char *cp = str; 378 379 while (*str) { 380 if (isupper(*str)) 381 *str = tolower(*str); 382 str++; 383 } 384 return (cp); 385} 386 387