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 } 378 sym = sym_lookup("KERNELRELEASE", 0); 379 sym_calc_value(sym); 380 time(&now); 381 env = getenv("KCONFIG_NOTIMESTAMP"); 382 if (env && *env) 383 use_timestamp = 0; 384 385 fprintf(out, _("#\n" 386 "# Automatically generated make config: don't edit\n" 387 "# Linux kernel version: %s\n" 388 "%s%s" 389 "#\n"), 390 sym_get_string_value(sym), 391 use_timestamp ? "# " : "", 392 use_timestamp ? ctime(&now) : ""); 393 if (out_h) 394 fprintf(out_h, "/*\n" 395 " * Automatically generated C config: don't edit\n" 396 " * Linux kernel version: %s\n" 397 "%s%s" 398 " */\n" 399 "#define AUTOCONF_INCLUDED\n", 400 sym_get_string_value(sym), 401 use_timestamp ? " * " : "", 402 use_timestamp ? ctime(&now) : ""); 403 404 if (!sym_change_count) 405 sym_clear_all_valid(); 406 407 menu = rootmenu.list; 408 while (menu) { 409 sym = menu->sym; 410 if (!sym) { 411 if (!menu_is_visible(menu)) 412 goto next; 413 str = menu_get_prompt(menu); 414 fprintf(out, "\n" 415 "#\n" 416 "# %s\n" 417 "#\n", str); 418 if (out_h) 419 fprintf(out_h, "\n" 420 "/*\n" 421 " * %s\n" 422 " */\n", str); 423 } else if (!(sym->flags & SYMBOL_CHOICE)) { 424 sym_calc_value(sym); 425 if (!(sym->flags & SYMBOL_WRITE)) 426 goto next; 427 sym->flags &= ~SYMBOL_WRITE; 428 type = sym->type; 429 if (type == S_TRISTATE) { 430 sym_calc_value(modules_sym); 431 if (modules_sym->curr.tri == no) 432 type = S_BOOLEAN; 433 } 434 switch (type) { 435 case S_BOOLEAN: 436 case S_TRISTATE: 437 switch (sym_get_tristate_value(sym)) { 438 case no: 439 fprintf(out, "# CONFIG_%s is not set\n", sym->name); 440 if (out_h) 441 fprintf(out_h, "#undef CONFIG_%s\n", sym->name); 442 break; 443 case mod: 444 fprintf(out, "CONFIG_%s=m\n", sym->name); 445 if (out_h) 446 fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); 447 break; 448 case yes: 449 fprintf(out, "CONFIG_%s=y\n", sym->name); 450 if (out_h) 451 fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); 452 break; 453 } 454 break; 455 case S_STRING: 456 // fix me 457 str = sym_get_string_value(sym); 458 fprintf(out, "CONFIG_%s=\"", sym->name); 459 if (out_h) 460 fprintf(out_h, "#define CONFIG_%s \"", sym->name); 461 do { 462 l = strcspn(str, "\"\\"); 463 if (l) { 464 fwrite(str, l, 1, out); 465 if (out_h) 466 fwrite(str, l, 1, out_h); 467 } 468 str += l; 469 while (*str == '\\' || *str == '"') { 470 fprintf(out, "\\%c", *str); 471 if (out_h) 472 fprintf(out_h, "\\%c", *str); 473 str++; 474 } 475 } while (*str); 476 fputs("\"\n", out); 477 if (out_h) 478 fputs("\"\n", out_h); 479 break; 480 case S_HEX: 481 str = sym_get_string_value(sym); 482 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { 483 fprintf(out, "CONFIG_%s=%s\n", sym->name, str); 484 if (out_h) 485 fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); 486 break; 487 } 488 case S_INT: 489 str = sym_get_string_value(sym); 490 fprintf(out, "CONFIG_%s=%s\n", sym->name, str); 491 if (out_h) 492 fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); 493 break; 494 } 495 } 496 497 next: 498 if (menu->list) { 499 menu = menu->list; 500 continue; 501 } 502 if (menu->next) 503 menu = menu->next; 504 else while ((menu = menu->parent)) { 505 if (menu->next) { 506 menu = menu->next; 507 break; 508 } 509 } 510 } 511 fclose(out); 512 if (out_h) { 513 fclose(out_h); 514 rename(".tmpconfig.h", "include/linux/autoconf.h"); 515 file_write_dep(NULL); 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