1331722Seadler/* 212772Speter * Copyright (c) 1995 Peter Wemm 312772Speter * Copyright (c) 1980, 1993 412772Speter * The Regents of the University of California. All rights reserved. 512772Speter * 612772Speter * Redistribution and use in source and binary forms, with or without 712772Speter * modification, are permitted provided that the following conditions 812772Speter * are met: 912772Speter * 1. Redistributions of source code must retain the above copyright 1012772Speter * notice, this list of conditions and the following disclaimer. 1112772Speter * 2. Redistributions in binary form must reproduce the above copyright 1212772Speter * notice, this list of conditions and the following disclaimer in the 1312772Speter * documentation and/or other materials provided with the distribution. 1412772Speter * 4. Neither the name of the University nor the names of its contributors 1512772Speter * may be used to endorse or promote products derived from this software 1612772Speter * without specific prior written permission. 1712772Speter * 1812772Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1912772Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2012772Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2112772Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2212772Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2312772Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2412772Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2512772Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2612772Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2712772Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2812772Speter * SUCH DAMAGE. 2912772Speter */ 3012772Speter 3112772Speter#ifndef lint 3229451Scharnier#if 0 3312772Speterstatic char sccsid[] = "@(#)mkheaders.c 8.1 (Berkeley) 6/6/93"; 3429451Scharnier#endif 3529451Scharnierstatic const char rcsid[] = 3650479Speter "$FreeBSD$"; 3712772Speter#endif /* not lint */ 3812772Speter 3912772Speter/* 4012772Speter * Make all the .h files for the optional entries 4112772Speter */ 4212772Speter 4329451Scharnier#include <ctype.h> 4429451Scharnier#include <err.h> 4512772Speter#include <stdio.h> 4620458Sjoerg#include <string.h> 4769004Simp#include <sys/param.h> 4812772Speter#include "config.h" 4916073Sphk#include "y.tab.h" 5012772Speter 5137578Sbdestatic struct users { 5237578Sbde int u_default; 5337578Sbde int u_min; 5437578Sbde int u_max; 55125935Sdes} users = { 8, 2, 512 }; 5637578Sbde 5761640Speterstatic char *lower(char *); 5861640Speterstatic void read_options(void); 5961640Speterstatic void do_option(char *); 6061640Speterstatic char *tooption(char *); 6120458Sjoerg 6229451Scharniervoid 6361640Speteroptions(void) 6412772Speter{ 6537578Sbde char buf[40]; 6637578Sbde struct cputype *cp; 6712772Speter struct opt_list *ol; 6837578Sbde struct opt *op; 6912772Speter 7037578Sbde /* Fake the cpu types as options. */ 71110895Sru SLIST_FOREACH(cp, &cputype, cpu_next) { 72159362Sdelphij op = (struct opt *)calloc(1, sizeof(*op)); 73205880Sru if (op == NULL) 74205880Sru err(EXIT_FAILURE, "calloc"); 7520458Sjoerg op->op_name = ns(cp->cpu_name); 76110895Sru SLIST_INSERT_HEAD(&opt, op, op_next); 7712772Speter } 7812772Speter 7937578Sbde if (maxusers == 0) { 80210144Simp /* fprintf(stderr, "maxusers not specified; will auto-size\n"); */ 8172000Speter } else if (maxusers < users.u_min) { 82210144Simp fprintf(stderr, "minimum of %d maxusers assumed\n", 83210144Simp users.u_min); 8472000Speter maxusers = users.u_min; 8572000Speter } else if (maxusers > users.u_max) 86210144Simp fprintf(stderr, "warning: maxusers > %d (%d)\n", 87210144Simp users.u_max, maxusers); 8837578Sbde 8937578Sbde /* Fake MAXUSERS as an option. */ 90159362Sdelphij op = (struct opt *)calloc(1, sizeof(*op)); 91205880Sru if (op == NULL) 92205880Sru err(EXIT_FAILURE, "calloc"); 9372684Speter op->op_name = ns("MAXUSERS"); 9446021Speter snprintf(buf, sizeof(buf), "%d", maxusers); 9537578Sbde op->op_value = ns(buf); 96110895Sru SLIST_INSERT_HEAD(&opt, op, op_next); 9737578Sbde 9812772Speter read_options(); 99209969Snwhitehorn 100209969Snwhitehorn /* Fake the value of MACHINE_ARCH as an option if necessary */ 101209969Snwhitehorn SLIST_FOREACH(ol, &otab, o_next) { 102209969Snwhitehorn if (strcasecmp(ol->o_name, machinearch) != 0) 103209969Snwhitehorn continue; 104209969Snwhitehorn 105209969Snwhitehorn op = (struct opt *)calloc(1, sizeof(*op)); 106209969Snwhitehorn if (op == NULL) 107209969Snwhitehorn err(EXIT_FAILURE, "calloc"); 108209969Snwhitehorn op->op_name = ns(ol->o_name); 109209969Snwhitehorn SLIST_INSERT_HEAD(&opt, op, op_next); 110209969Snwhitehorn break; 111209969Snwhitehorn } 112209969Snwhitehorn 113206664Simp SLIST_FOREACH(op, &opt, op_next) { 114206664Simp SLIST_FOREACH(ol, &otab, o_next) { 115206664Simp if (eq(op->op_name, ol->o_name) && 116206664Simp (ol->o_flags & OL_ALIAS)) { 117210144Simp fprintf(stderr, "Mapping option %s to %s.\n", 118206664Simp op->op_name, ol->o_file); 119206664Simp op->op_name = ol->o_file; 120206664Simp break; 121206664Simp } 122206664Simp } 123206664Simp } 124110895Sru SLIST_FOREACH(ol, &otab, o_next) 12512772Speter do_option(ol->o_name); 126110895Sru SLIST_FOREACH(op, &opt, op_next) { 12771251Speter if (!op->op_ownfile && strncmp(op->op_name, "DEV_", 4)) { 128210144Simp fprintf(stderr, "%s: unknown option \"%s\"\n", 12972841Speter PREFIX, op->op_name); 13061523Speter exit(1); 13161523Speter } 13261523Speter } 13312772Speter} 13412772Speter 13512772Speter/* 13612772Speter * Generate an <options>.h file 13712772Speter */ 13812772Speter 13945744Speterstatic void 14061640Speterdo_option(char *name) 14112772Speter{ 14272684Speter char *file, *inw; 14372684Speter const char *basefile; 14448401Speter struct opt_list *ol; 145110895Sru struct opt *op; 146110895Sru struct opt_head op_head; 14712772Speter FILE *inf, *outf; 14812772Speter char *value; 14912772Speter char *oldvalue; 15012772Speter int seen; 15148401Speter int tidy; 15212772Speter 15312772Speter file = tooption(name); 15412772Speter /* 15512772Speter * Check to see if the option was specified.. 15612772Speter */ 15712772Speter value = NULL; 158110895Sru SLIST_FOREACH(op, &opt, op_next) { 15912772Speter if (eq(name, op->op_name)) { 16037577Sbde oldvalue = value; 16112772Speter value = op->op_value; 16237577Sbde if (value == NULL) 16312772Speter value = ns("1"); 16437577Sbde if (oldvalue != NULL && !eq(value, oldvalue)) 165210144Simp fprintf(stderr, 16672841Speter "%s: option \"%s\" redefined from %s to %s\n", 16772841Speter PREFIX, op->op_name, oldvalue, 16837577Sbde value); 16912772Speter op->op_ownfile++; 17012772Speter } 17112772Speter } 17212772Speter 17371866Speter remember(file); 17412772Speter inf = fopen(file, "r"); 175298687Saraujo if (inf == NULL) { 17612772Speter outf = fopen(file, "w"); 177298687Saraujo if (outf == NULL) 17829451Scharnier err(1, "%s", file); 17912772Speter 18012772Speter /* was the option in the config file? */ 18112772Speter if (value) { 18212772Speter fprintf(outf, "#define %s %s\n", name, value); 18312772Speter } /* else empty file */ 18412772Speter 185207263Simp (void)fclose(outf); 18612772Speter return; 18712772Speter } 18855659Sbde basefile = ""; 189110895Sru SLIST_FOREACH(ol, &otab, o_next) 19055659Sbde if (eq(name, ol->o_name)) { 19155659Sbde basefile = ol->o_file; 19255659Sbde break; 19355659Sbde } 19412772Speter oldvalue = NULL; 195110895Sru SLIST_INIT(&op_head); 19612772Speter seen = 0; 19748401Speter tidy = 0; 19812772Speter for (;;) { 19912772Speter char *cp; 20012772Speter char *invalue; 20112772Speter 20212772Speter /* get the #define */ 203298687Saraujo if ((inw = get_word(inf)) == NULL || inw == (char *)EOF) 20412772Speter break; 20512772Speter /* get the option name */ 206298687Saraujo if ((inw = get_word(inf)) == NULL || inw == (char *)EOF) 20712772Speter break; 20812772Speter inw = ns(inw); 20948401Speter /* get the option value */ 210298687Saraujo if ((cp = get_word(inf)) == NULL || cp == (char *)EOF) 21112772Speter break; 21212772Speter /* option value */ 21312772Speter invalue = ns(cp); /* malloced */ 21412772Speter if (eq(inw, name)) { 21512772Speter oldvalue = invalue; 21612772Speter invalue = value; 21712772Speter seen++; 21812772Speter } 219110895Sru SLIST_FOREACH(ol, &otab, o_next) 22048401Speter if (eq(inw, ol->o_name)) 22148401Speter break; 22255603Sbde if (!eq(inw, name) && !ol) { 223210144Simp fprintf(stderr, 224210144Simp "WARNING: unknown option `%s' removed from %s\n", 225210144Simp inw, file); 22648401Speter tidy++; 22755659Sbde } else if (ol != NULL && !eq(basefile, ol->o_file)) { 228210144Simp fprintf(stderr, 229210144Simp "WARNING: option `%s' moved from %s to %s\n", 230210144Simp inw, basefile, ol->o_file); 23155659Sbde tidy++; 23248401Speter } else { 233159362Sdelphij op = (struct opt *) calloc(1, sizeof *op); 234205880Sru if (op == NULL) 235205880Sru err(EXIT_FAILURE, "calloc"); 23648401Speter op->op_name = inw; 23748401Speter op->op_value = invalue; 238110895Sru SLIST_INSERT_HEAD(&op_head, op, op_next); 23948401Speter } 24012772Speter 24112772Speter /* EOL? */ 24212772Speter cp = get_word(inf); 24312772Speter if (cp == (char *)EOF) 24412772Speter break; 24512772Speter } 246207263Simp (void)fclose(inf); 24748401Speter if (!tidy && ((value == NULL && oldvalue == NULL) || 24848401Speter (value && oldvalue && eq(value, oldvalue)))) { 249110895Sru while (!SLIST_EMPTY(&op_head)) { 250110895Sru op = SLIST_FIRST(&op_head); 251110895Sru SLIST_REMOVE_HEAD(&op_head, op_next); 25212772Speter free(op->op_name); 25312772Speter free(op->op_value); 25412772Speter free(op); 25512772Speter } 25612772Speter return; 25712772Speter } 25812772Speter 25912772Speter if (value && !seen) { 26012772Speter /* New option appears */ 261159362Sdelphij op = (struct opt *) calloc(1, sizeof *op); 262205880Sru if (op == NULL) 263205880Sru err(EXIT_FAILURE, "calloc"); 26412772Speter op->op_name = ns(name); 26512772Speter op->op_value = value ? ns(value) : NULL; 266110895Sru SLIST_INSERT_HEAD(&op_head, op, op_next); 26712772Speter } 26812772Speter 26912772Speter outf = fopen(file, "w"); 270298687Saraujo if (outf == NULL) 27129451Scharnier err(1, "%s", file); 272110895Sru while (!SLIST_EMPTY(&op_head)) { 273110895Sru op = SLIST_FIRST(&op_head); 27412772Speter /* was the option in the config file? */ 27512772Speter if (op->op_value) { 27612772Speter fprintf(outf, "#define %s %s\n", 27712772Speter op->op_name, op->op_value); 27812772Speter } 279110895Sru SLIST_REMOVE_HEAD(&op_head, op_next); 28012772Speter free(op->op_name); 28112772Speter free(op->op_value); 28212772Speter free(op); 28312772Speter } 284207263Simp (void)fclose(outf); 28512772Speter} 28612772Speter 28712772Speter/* 28812772Speter * Find the filename to store the option spec into. 28912772Speter */ 29045744Speterstatic char * 29161640Spetertooption(char *name) 29212772Speter{ 29369004Simp static char hbuf[MAXPATHLEN]; 29469004Simp char nbuf[MAXPATHLEN]; 29512772Speter struct opt_list *po; 29612772Speter 29712772Speter /* "cannot happen"? the otab list should be complete.. */ 298207263Simp (void)strlcpy(nbuf, "options.h", sizeof(nbuf)); 29912772Speter 300110895Sru SLIST_FOREACH(po, &otab, o_next) { 30112772Speter if (eq(po->o_name, name)) { 30269004Simp strlcpy(nbuf, po->o_file, sizeof(nbuf)); 30312772Speter break; 30412772Speter } 30512772Speter } 30612772Speter 307207263Simp (void)strlcpy(hbuf, path(nbuf), sizeof(hbuf)); 30812772Speter return (hbuf); 30912772Speter} 31012772Speter 311207263Simp 31245744Speterstatic void 313207265Simpcheck_duplicate(const char *fname, const char *this) 31412772Speter{ 315207263Simp struct opt_list *po; 316207263Simp 317207265Simp SLIST_FOREACH(po, &otab, o_next) { 318207265Simp if (eq(po->o_name, this)) { 319210144Simp fprintf(stderr, "%s: Duplicate option %s.\n", 320210144Simp fname, this); 321207265Simp exit(1); 322207265Simp } 323207265Simp } 324207265Simp} 325207265Simp 326207265Simpstatic void 327207265Simpinsert_option(const char *fname, char *this, char *val) 328207265Simp{ 329207265Simp struct opt_list *po; 330207265Simp 331207265Simp check_duplicate(fname, this); 332207263Simp po = (struct opt_list *) calloc(1, sizeof *po); 333207263Simp if (po == NULL) 334207263Simp err(EXIT_FAILURE, "calloc"); 335207263Simp po->o_name = this; 336207263Simp po->o_file = val; 337207265Simp po->o_flags = 0; 338207263Simp SLIST_INSERT_HEAD(&otab, po, o_next); 339207263Simp} 340207263Simp 341207263Simpstatic void 342207265Simpupdate_option(const char *this, char *val, int flags) 343207263Simp{ 344207263Simp struct opt_list *po; 345207263Simp 346207263Simp SLIST_FOREACH(po, &otab, o_next) { 347207263Simp if (eq(po->o_name, this)) { 348207265Simp free(po->o_file); 349207265Simp po->o_file = val; 350207265Simp po->o_flags = flags; 351207265Simp return; 352207263Simp } 353207263Simp } 354211325Simp /* 355211325Simp * Option not found, but that's OK, we just ignore it since it 356211325Simp * may be for another arch. 357211325Simp */ 358211325Simp return; 359207263Simp} 360207263Simp 361207263Simpstatic int 362207263Simpread_option_file(const char *fname, int flags) 363207263Simp{ 36412772Speter FILE *fp; 36512772Speter char *wd, *this, *val; 36669004Simp char genopt[MAXPATHLEN]; 36712772Speter 36812772Speter fp = fopen(fname, "r"); 369298687Saraujo if (fp == NULL) 370207263Simp return (0); 371207263Simp while ((wd = get_word(fp)) != (char *)EOF) { 372298687Saraujo if (wd == NULL) 373207263Simp continue; 374207263Simp if (wd[0] == '#') { 375207263Simp while (((wd = get_word(fp)) != (char *)EOF) && wd) 376207263Simp continue; 377207263Simp continue; 37812772Speter } 379207263Simp this = ns(wd); 380206664Simp val = get_word(fp); 381207263Simp if (val == (char *)EOF) 382207263Simp return (1); 383298687Saraujo if (val == NULL) { 384207263Simp if (flags) { 385210144Simp fprintf(stderr, "%s: compat file requires two" 386210144Simp " words per line at %s\n", fname, this); 387207263Simp exit(1); 388207263Simp } 389207263Simp char *s = ns(this); 390207263Simp (void)snprintf(genopt, sizeof(genopt), "opt_%s.h", 391207263Simp lower(s)); 392207263Simp val = genopt; 393207263Simp free(s); 394206664Simp } 395207263Simp val = ns(val); 396207265Simp if (flags == 0) 397207265Simp insert_option(fname, this, val); 398207265Simp else 399207265Simp update_option(this, val, flags); 40012772Speter } 401207263Simp (void)fclose(fp); 402207263Simp return (1); 403207263Simp} 40412772Speter 405207263Simp/* 406207263Simp * read the options and options.<machine> files 407207263Simp */ 408207263Simpstatic void 409207263Simpread_options(void) 410207263Simp{ 411207263Simp char fname[MAXPATHLEN]; 412207263Simp 413207263Simp SLIST_INIT(&otab); 414207263Simp read_option_file("../../conf/options", 0); 415207263Simp (void)snprintf(fname, sizeof fname, "../../conf/options.%s", 416207263Simp machinename); 417207263Simp if (!read_option_file(fname, 0)) { 418207263Simp (void)snprintf(fname, sizeof fname, "options.%s", machinename); 419207263Simp read_option_file(fname, 0); 42012772Speter } 421207263Simp read_option_file("../../conf/options-compat", OL_ALIAS); 42212772Speter} 42312772Speter 42420458Sjoergstatic char * 42561640Speterlower(char *str) 42612772Speter{ 42761640Speter char *cp = str; 42812772Speter 42912772Speter while (*str) { 43012772Speter if (isupper(*str)) 43112772Speter *str = tolower(*str); 43212772Speter str++; 43312772Speter } 43412772Speter return (cp); 43512772Speter} 436