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