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