mkoptions.c revision 55603
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 55603 2000-01-08 14:34:50Z 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 *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 oldvalue = NULL; 170 op_head = NULL; 171 seen = 0; 172 tidy = 0; 173 for (;;) { 174 char *cp; 175 char *invalue; 176 177 /* get the #define */ 178 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 179 break; 180 /* get the option name */ 181 if ((inw = get_word(inf)) == 0 || inw == (char *)EOF) 182 break; 183 inw = ns(inw); 184 /* get the option value */ 185 if ((cp = get_word(inf)) == 0 || cp == (char *)EOF) 186 break; 187 /* option value */ 188 invalue = ns(cp); /* malloced */ 189 if (eq(inw, name)) { 190 oldvalue = invalue; 191 invalue = value; 192 seen++; 193 } 194 for (ol = otab; ol != 0; ol = ol->o_next) 195 if (eq(inw, ol->o_name)) 196 break; 197 if (!eq(inw, name) && !ol) { 198 printf("WARNING: unknown option `%s' removed from %s\n", 199 inw, file); 200 tidy++; 201 } else { 202 op = (struct opt *) malloc(sizeof *op); 203 bzero(op, sizeof(*op)); 204 op->op_name = inw; 205 op->op_value = invalue; 206 op->op_next = op_head; 207 op_head = op; 208 } 209 210 /* EOL? */ 211 cp = get_word(inf); 212 if (cp == (char *)EOF) 213 break; 214 } 215 (void) fclose(inf); 216 if (!tidy && ((value == NULL && oldvalue == NULL) || 217 (value && oldvalue && eq(value, oldvalue)))) { 218 for (op = op_head; op != NULL; op = topp) { 219 topp = op->op_next; 220 free(op->op_name); 221 free(op->op_value); 222 free(op); 223 } 224 return; 225 } 226 227 if (value && !seen) { 228 /* New option appears */ 229 op = (struct opt *) malloc(sizeof *op); 230 bzero(op, sizeof(*op)); 231 op->op_name = ns(name); 232 op->op_value = value ? ns(value) : NULL; 233 op->op_next = op_head; 234 op_head = op; 235 } 236 237 outf = fopen(file, "w"); 238 if (outf == 0) 239 err(1, "%s", file); 240 for (op = op_head; op != NULL; op = topp) { 241 /* was the option in the config file? */ 242 if (op->op_value) { 243 fprintf(outf, "#define %s %s\n", 244 op->op_name, op->op_value); 245 } 246 topp = op->op_next; 247 free(op->op_name); 248 free(op->op_value); 249 free(op); 250 } 251 (void) fclose(outf); 252} 253 254/* 255 * Find the filename to store the option spec into. 256 */ 257static char * 258tooption(name) 259 char *name; 260{ 261 static char hbuf[80]; 262 char nbuf[80]; 263 struct opt_list *po; 264 265 /* "cannot happen"? the otab list should be complete.. */ 266 (void) strcpy(nbuf, "options.h"); 267 268 for (po = otab ; po != 0; po = po->o_next) { 269 if (eq(po->o_name, name)) { 270 strcpy(nbuf, po->o_file); 271 break; 272 } 273 } 274 275 (void) strcpy(hbuf, path(nbuf)); 276 return (hbuf); 277} 278 279/* 280 * read the options and options.<machine> files 281 */ 282static void 283read_options() 284{ 285 FILE *fp; 286 char fname[80]; 287 char *wd, *this, *val; 288 struct opt_list *po; 289 int first = 1; 290 char genopt[80]; 291 292 otab = 0; 293 (void) snprintf(fname, sizeof fname, "../../conf/options"); 294openit: 295 fp = fopen(fname, "r"); 296 if (fp == 0) { 297 return; 298 } 299 if (ident == NULL) { 300 printf("no ident line specified\n"); 301 exit(1); 302 } 303next: 304 wd = get_word(fp); 305 if (wd == (char *)EOF) { 306 (void) fclose(fp); 307 if (first == 1) { 308 (void) snprintf(fname, sizeof fname, "options.%s", machinename); 309 first++; 310 goto openit; 311 } 312 if (first == 2) { 313 (void) snprintf(fname, sizeof fname, "options.%s", raisestr(ident)); 314 first++; 315 fp = fopen(fname, "r"); 316 if (fp != 0) 317 goto next; 318 } 319 return; 320 } 321 if (wd == 0) 322 goto next; 323 if (wd[0] == '#') 324 { 325 while (((wd = get_word(fp)) != (char *)EOF) && wd) 326 ; 327 goto next; 328 } 329 this = ns(wd); 330 val = get_word(fp); 331 if (val == (char *)EOF) 332 return; 333 if (val == 0) { 334 char *s = ns(this); 335 (void) snprintf(genopt, sizeof genopt, "opt_%s.h", lower(s)); 336 val = genopt; 337 free(s); 338 } 339 val = ns(val); 340 341 for (po = otab ; po != 0; po = po->o_next) { 342 if (eq(po->o_name, this)) { 343 printf("%s: Duplicate option %s.\n", 344 fname, this); 345 exit(1); 346 } 347 } 348 349 po = (struct opt_list *) malloc(sizeof *po); 350 bzero(po, sizeof(*po)); 351 po->o_name = this; 352 po->o_file = val; 353 po->o_next = otab; 354 otab = po; 355 356 goto next; 357} 358 359static char * 360lower(str) 361 register char *str; 362{ 363 register char *cp = str; 364 365 while (*str) { 366 if (isupper(*str)) 367 *str = tolower(*str); 368 str++; 369 } 370 return (cp); 371} 372 373