1 /* 2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 3 * Released under the terms of the GNU GPL v2.0. 4 */ 5 6 #include <sys/stat.h> 7 #include <ctype.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <time.h> 12 #include <unistd.h> 13 14 #define LKC_DIRECT_LINK 15 #include "lkc.h" 16 17 static void conf_warning(const char *fmt, ...) 18 __attribute__ ((format (printf, 1, 2))); 19 20 static const char *conf_filename; 21 static int conf_lineno, conf_warnings, conf_unsaved; 22 23 const char conf_def_filename[] = ".config"; 24 25 const char conf_defname[] = "arch/$ARCH/defconfig"; 26 27 const char *conf_confnames[] = { 28 ".config", 29 "/lib/modules/$UNAME_RELEASE/.config", 30 "/etc/kernel-config", 31 "/boot/config-$UNAME_RELEASE", 32 conf_defname, 33 NULL, 34 }; 35 36 static void conf_warning(const char *fmt, ...) 37 { 38 va_list ap; 39 va_start(ap, fmt); 40 fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); 41 vfprintf(stderr, fmt, ap); 42 fprintf(stderr, "\n"); 43 va_end(ap); 44 conf_warnings++; 45 } 46 47 static char *conf_expand_value(const char *in) 48 { 49 struct symbol *sym; 50 const char *src; 51 static char res_value[SYMBOL_MAXLENGTH]; 52 char *dst, name[SYMBOL_MAXLENGTH]; 53 54 res_value[0] = 0; 55 dst = name; 56 while ((src = strchr(in, '$'))) { 57 strncat(res_value, in, src - in); 58 src++; 59 dst = name; 60 while (isalnum(*src) || *src == '_') 61 *dst++ = *src++; 62 *dst = 0; 63 sym = sym_lookup(name, 0); 64 sym_calc_value(sym); 65 strcat(res_value, sym_get_string_value(sym)); 66 in = src; 67 } 68 strcat(res_value, in); 69 70 return res_value; 71 } 72 73 char *conf_get_default_confname(void) 74 { 75 struct stat buf; 76 static char fullname[PATH_MAX+1]; 77 char *env, *name; 78 79 name = conf_expand_value(conf_defname); 80 env = getenv(SRCTREE); 81 if (env) { 82 sprintf(fullname, "%s/%s", env, name); 83 if (!stat(fullname, &buf)) 84 return fullname; 85 } 86 return name; 87 } 88 89 int conf_read_simple(const char *name) 90 { 91 FILE *in = NULL; 92 char line[1024]; 93 char *p, *p2; 94 struct symbol *sym; 95 int i; 96 97 if (name) { 98 in = zconf_fopen(name); 99 } else { 100 const char **names = conf_confnames; 101 while ((name = *names++)) { 102 name = conf_expand_value(name); 103 in = zconf_fopen(name); 104 if (in) { 105 printf(_("#\n" 106 "# using defaults found in %s\n" 107 "#\n"), name); 108 break; 109 } 110 } 111 } 112 if (!in) 113 return 1; 114 115 conf_filename = name; 116 conf_lineno = 0; 117 conf_warnings = 0; 118 conf_unsaved = 0; 119 120 for_all_symbols(i, sym) { 121 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; 122 if (sym_is_choice(sym)) 123 sym->flags &= ~SYMBOL_NEW; 124 sym->flags &= ~SYMBOL_VALID; 125 switch (sym->type) { 126 case S_INT: 127 case S_HEX: 128 case S_STRING: 129 if (sym->user.val) 130 free(sym->user.val); 131 default: 132 sym->user.val = NULL; 133 sym->user.tri = no; 134 } 135 } 136 137 while (fgets(line, sizeof(line), in)) { 138 conf_lineno++; 139 sym = NULL; 140 switch (line[0]) { 141 case '#': 142 if (memcmp(line + 2, "CONFIG_", 7)) 143 continue; 144 p = strchr(line + 9, ' '); 145 if (!p) 146 continue; 147 *p++ = 0; 148 if (strncmp(p, "is not set", 10)) 149 continue; 150 sym = sym_find(line + 9); 151 if (!sym) { 152 conf_warning("trying to assign nonexistent symbol %s", line + 9); 153 break; 154 } else if (!(sym->flags & SYMBOL_NEW)) { 155 conf_warning("trying to reassign symbol %s", sym->name); 156 break; 157 } 158 switch (sym->type) { 159 case S_BOOLEAN: 160 case S_TRISTATE: 161 sym->user.tri = no; 162 sym->flags &= ~SYMBOL_NEW; 163 break; 164 default: 165 ; 166 } 167 break; 168 case 'C': 169 if (memcmp(line, "CONFIG_", 7)) { 170 conf_warning("unexpected data"); 171 continue; 172 } 173 p = strchr(line + 7, '='); 174 if (!p) 175 continue; 176 *p++ = 0; 177 p2 = strchr(p, '\n'); 178 if (p2) 179 *p2 = 0; 180 sym = sym_find(line + 7); 181 if (!sym) { 182 conf_warning("trying to assign nonexistent symbol %s", line + 7); 183 break; 184 } else if (!(sym->flags & SYMBOL_NEW)) { 185 conf_warning("trying to reassign symbol %s", sym->name); 186 break; 187 } 188 switch (sym->type) { 189 case S_TRISTATE: 190 if (p[0] == 'm') { 191 sym->user.tri = mod; 192 sym->flags &= ~SYMBOL_NEW; 193 break; 194 } 195 case S_BOOLEAN: 196 if (p[0] == 'y') { 197 sym->user.tri = yes; 198 sym->flags &= ~SYMBOL_NEW; 199 break; 200 } 201 if (p[0] == 'n') { 202 sym->user.tri = no; 203 sym->flags &= ~SYMBOL_NEW; 204 break; 205 } 206 conf_warning("symbol value '%s' invalid for %s", p, sym->name); 207 break; 208 case S_STRING: 209 if (*p++ != '"') 210 break; 211 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { 212 if (*p2 == '"') { 213 *p2 = 0; 214 break; 215 } 216 memmove(p2, p2 + 1, strlen(p2)); 217 } 218 if (!p2) { 219 conf_warning("invalid string found"); 220 continue; 221 } 222 case S_INT: 223 case S_HEX: 224 if (sym_string_valid(sym, p)) { 225 sym->user.val = strdup(p); 226 sym->flags &= ~SYMBOL_NEW; 227 } else { 228 conf_warning("symbol value '%s' invalid for %s", p, sym->name); 229 continue; 230 } 231 break; 232 default: 233 ; 234 } 235 break; 236 case '\n': 237 break; 238 default: 239 conf_warning("unexpected data"); 240 continue; 241 } 242 if (sym && sym_is_choice_value(sym)) { 243 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); 244 switch (sym->user.tri) { 245 case no: 246 break; 247 case mod: 248 if (cs->user.tri == yes) { 249 conf_warning("%s creates inconsistent choice state", sym->name); 250 cs->flags |= SYMBOL_NEW; 251 } 252 break; 253 case yes: 254 if (cs->user.tri != no) { 255 conf_warning("%s creates inconsistent choice state", sym->name); 256 cs->flags |= SYMBOL_NEW; 257 } else 258 cs->user.val = sym; 259 break; 260 } 261 cs->user.tri = E_OR(cs->user.tri, sym->user.tri); 262 } 263 } 264 fclose(in); 265 266 if (modules_sym) 267 sym_calc_value(modules_sym); 268 return 0; 269 } 270 271 int conf_read(const char *name) 272 { 273 struct symbol *sym; 274 struct property *prop; 275 struct expr *e; 276 int i; 277 278 if (conf_read_simple(name)) 279 return 1; 280 281 for_all_symbols(i, sym) { 282 sym_calc_value(sym); 283 if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) 284 goto sym_ok; 285 if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { 286 /* check that calculated value agrees with saved value */ 287 switch (sym->type) { 288 case S_BOOLEAN: 289 case S_TRISTATE: 290 if (sym->user.tri != sym_get_tristate_value(sym)) 291 break; 292 if (!sym_is_choice(sym)) 293 goto sym_ok; 294 default: 295 if (!strcmp(sym->curr.val, sym->user.val)) 296 goto sym_ok; 297 break; 298 } 299 } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) 300 /* no previous value and not saved */ 301 goto sym_ok; 302 conf_unsaved++; 303 /* maybe print value in verbose mode... */ 304 sym_ok: 305 if (sym_has_value(sym) && !sym_is_choice_value(sym)) { 306 if (sym->visible == no) 307 sym->flags |= SYMBOL_NEW; 308 switch (sym->type) { 309 case S_STRING: 310 case S_INT: 311 case S_HEX: 312 if (!sym_string_within_range(sym, sym->user.val)) { 313 sym->flags |= SYMBOL_NEW; 314 sym->flags &= ~SYMBOL_VALID; 315 } 316 default: 317 break; 318 } 319 } 320 if (!sym_is_choice(sym)) 321 continue; 322 prop = sym_get_choice_prop(sym); 323 for (e = prop->expr; e; e = e->left.expr) 324 if (e->right.sym->visible != no) 325 sym->flags |= e->right.sym->flags & SYMBOL_NEW; 326 } 327 328 sym_change_count = conf_warnings || conf_unsaved; 329 330 return 0; 331 } 332 333 int conf_write(const char *name) 334 { 335 FILE *out, *out_h; 336 struct symbol *sym; 337 struct menu *menu; 338 const char *basename; 339 char dirname[128], tmpname[128], newname[128]; 340 int type, l; 341 const char *str; 342 time_t now; 343 int use_timestamp = 1; 344 char *env; 345 346 dirname[0] = 0; 347 if (name && name[0]) { 348 struct stat st; 349 char *slash; 350 351 if (!stat(name, &st) && S_ISDIR(st.st_mode)) { 352 strcpy(dirname, name); 353 strcat(dirname, "/"); 354 basename = conf_def_filename; 355 } else if ((slash = strrchr(name, '/'))) { 356 int size = slash - name + 1; 357 memcpy(dirname, name, size); 358 dirname[size] = 0; 359 if (slash[1]) 360 basename = slash + 1; 361 else 362 basename = conf_def_filename; 363 } else 364 basename = name; 365 } else 366 basename = conf_def_filename; 367 368 sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid()); 369 out = fopen(newname, "w"); 370 if (!out) 371 return 1; 372 out_h = NULL; 373 if (!name) { 374 out_h = fopen(".tmpconfig.h", "w"); 375 if (!out_h) 376 return 1; 377 file_write_dep(NULL); 378 } 379 sym = sym_lookup("KERNELVERSION", 0); 380 sym_calc_value(sym); 381 time(&now); 382 env = getenv("KCONFIG_NOTIMESTAMP"); 383 if (env && *env) 384 use_timestamp = 0; 385 386 fprintf(out, _("#\n" 387 "# Automatically generated make config: don't edit\n" 388 "# Linux kernel version: %s\n" 389 "%s%s" 390 "#\n"), 391 sym_get_string_value(sym), 392 use_timestamp ? "# " : "", 393 use_timestamp ? ctime(&now) : ""); 394 if (out_h) 395 fprintf(out_h, "/*\n" 396 " * Automatically generated C config: don't edit\n" 397 " * Linux kernel version: %s\n" 398 "%s%s" 399 " */\n" 400 "#define AUTOCONF_INCLUDED\n", 401 sym_get_string_value(sym), 402 use_timestamp ? " * " : "", 403 use_timestamp ? ctime(&now) : ""); 404 405 if (!sym_change_count) 406 sym_clear_all_valid(); 407 408 menu = rootmenu.list; 409 while (menu) { 410 sym = menu->sym; 411 if (!sym) { 412 if (!menu_is_visible(menu)) 413 goto next; 414 str = menu_get_prompt(menu); 415 fprintf(out, "\n" 416 "#\n" 417 "# %s\n" 418 "#\n", str); 419 if (out_h) 420 fprintf(out_h, "\n" 421 "/*\n" 422 " * %s\n" 423 " */\n", str); 424 } else if (!(sym->flags & SYMBOL_CHOICE)) { 425 sym_calc_value(sym); 426 if (!(sym->flags & SYMBOL_WRITE)) 427 goto next; 428 sym->flags &= ~SYMBOL_WRITE; 429 type = sym->type; 430 if (type == S_TRISTATE) { 431 sym_calc_value(modules_sym); 432 if (modules_sym->curr.tri == no) 433 type = S_BOOLEAN; 434 } 435 switch (type) { 436 case S_BOOLEAN: 437 case S_TRISTATE: 438 switch (sym_get_tristate_value(sym)) { 439 case no: 440 fprintf(out, "# CONFIG_%s is not set\n", sym->name); 441 if (out_h) 442 fprintf(out_h, "#undef CONFIG_%s\n", sym->name); 443 break; 444 case mod: 445 fprintf(out, "CONFIG_%s=m\n", sym->name); 446 if (out_h) 447 fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); 448 break; 449 case yes: 450 fprintf(out, "CONFIG_%s=y\n", sym->name); 451 if (out_h) 452 fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); 453 break; 454 } 455 break; 456 case S_STRING: 457 // fix me 458 str = sym_get_string_value(sym); 459 fprintf(out, "CONFIG_%s=\"", sym->name); 460 if (out_h) 461 fprintf(out_h, "#define CONFIG_%s \"", sym->name); 462 do { 463 l = strcspn(str, "\"\\"); 464 if (l) { 465 fwrite(str, l, 1, out); 466 if (out_h) 467 fwrite(str, l, 1, out_h); 468 } 469 str += l; 470 while (*str == '\\' || *str == '"') { 471 fprintf(out, "\\%c", *str); 472 if (out_h) 473 fprintf(out_h, "\\%c", *str); 474 str++; 475 } 476 } while (*str); 477 fputs("\"\n", out); 478 if (out_h) 479 fputs("\"\n", out_h); 480 break; 481 case S_HEX: 482 str = sym_get_string_value(sym); 483 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { 484 fprintf(out, "CONFIG_%s=%s\n", sym->name, str); 485 if (out_h) 486 fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); 487 break; 488 } 489 case S_INT: 490 str = sym_get_string_value(sym); 491 fprintf(out, "CONFIG_%s=%s\n", sym->name, str); 492 if (out_h) 493 fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); 494 break; 495 } 496 } 497 498 next: 499 if (menu->list) { 500 menu = menu->list; 501 continue; 502 } 503 if (menu->next) 504 menu = menu->next; 505 else while ((menu = menu->parent)) { 506 if (menu->next) { 507 menu = menu->next; 508 break; 509 } 510 } 511 } 512 fclose(out); 513 if (out_h) { 514 fclose(out_h); 515 rename(".tmpconfig.h", "include/linux/autoconf.h"); 516 } 517 if (!name || basename != conf_def_filename) { 518 if (!name) 519 name = conf_def_filename; 520 sprintf(tmpname, "%s.old", name); 521 rename(name, tmpname); 522 } 523 sprintf(tmpname, "%s%s", dirname, basename); 524 if (rename(newname, tmpname)) 525 return 1; 526 527 sym_change_count = 0; 528 529 return 0; 530 } 531