0001
0002
0003
0004
0005
0006 #include <sys/mman.h>
0007 #include <sys/stat.h>
0008 #include <sys/types.h>
0009 #include <ctype.h>
0010 #include <errno.h>
0011 #include <fcntl.h>
0012 #include <limits.h>
0013 #include <stdarg.h>
0014 #include <stdbool.h>
0015 #include <stdio.h>
0016 #include <stdlib.h>
0017 #include <string.h>
0018 #include <time.h>
0019 #include <unistd.h>
0020
0021 #include "lkc.h"
0022
0023
0024 static bool is_present(const char *path)
0025 {
0026 struct stat st;
0027
0028 return !stat(path, &st);
0029 }
0030
0031
0032 static bool is_dir(const char *path)
0033 {
0034 struct stat st;
0035
0036 if (stat(path, &st))
0037 return false;
0038
0039 return S_ISDIR(st.st_mode);
0040 }
0041
0042
0043 static bool is_same(const char *file1, const char *file2)
0044 {
0045 int fd1, fd2;
0046 struct stat st1, st2;
0047 void *map1, *map2;
0048 bool ret = false;
0049
0050 fd1 = open(file1, O_RDONLY);
0051 if (fd1 < 0)
0052 return ret;
0053
0054 fd2 = open(file2, O_RDONLY);
0055 if (fd2 < 0)
0056 goto close1;
0057
0058 ret = fstat(fd1, &st1);
0059 if (ret)
0060 goto close2;
0061 ret = fstat(fd2, &st2);
0062 if (ret)
0063 goto close2;
0064
0065 if (st1.st_size != st2.st_size)
0066 goto close2;
0067
0068 map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
0069 if (map1 == MAP_FAILED)
0070 goto close2;
0071
0072 map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
0073 if (map2 == MAP_FAILED)
0074 goto close2;
0075
0076 if (bcmp(map1, map2, st1.st_size))
0077 goto close2;
0078
0079 ret = true;
0080 close2:
0081 close(fd2);
0082 close1:
0083 close(fd1);
0084
0085 return ret;
0086 }
0087
0088
0089
0090
0091
0092
0093 static int make_parent_dir(const char *path)
0094 {
0095 char tmp[PATH_MAX + 1];
0096 char *p;
0097
0098 strncpy(tmp, path, sizeof(tmp));
0099 tmp[sizeof(tmp) - 1] = 0;
0100
0101
0102 p = strrchr(tmp, '/');
0103 if (!p)
0104 return 0;
0105 *(p + 1) = 0;
0106
0107
0108 p = tmp;
0109 while (*p == '/')
0110 p++;
0111
0112 while ((p = strchr(p, '/'))) {
0113 *p = 0;
0114
0115
0116 if (!is_dir(tmp) && mkdir(tmp, 0755))
0117 return -1;
0118
0119 *p = '/';
0120 while (*p == '/')
0121 p++;
0122 }
0123
0124 return 0;
0125 }
0126
0127 static char depfile_path[PATH_MAX];
0128 static size_t depfile_prefix_len;
0129
0130
0131 static int conf_touch_dep(const char *name)
0132 {
0133 int fd;
0134
0135
0136 if (depfile_prefix_len + strlen(name) + 1 > sizeof(depfile_path))
0137 return -1;
0138
0139 strcpy(depfile_path + depfile_prefix_len, name);
0140
0141 fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
0142 if (fd == -1)
0143 return -1;
0144 close(fd);
0145
0146 return 0;
0147 }
0148
0149 static void conf_warning(const char *fmt, ...)
0150 __attribute__ ((format (printf, 1, 2)));
0151
0152 static void conf_message(const char *fmt, ...)
0153 __attribute__ ((format (printf, 1, 2)));
0154
0155 static const char *conf_filename;
0156 static int conf_lineno, conf_warnings;
0157
0158 static void conf_warning(const char *fmt, ...)
0159 {
0160 va_list ap;
0161 va_start(ap, fmt);
0162 fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
0163 vfprintf(stderr, fmt, ap);
0164 fprintf(stderr, "\n");
0165 va_end(ap);
0166 conf_warnings++;
0167 }
0168
0169 static void conf_default_message_callback(const char *s)
0170 {
0171 printf("#\n# ");
0172 printf("%s", s);
0173 printf("\n#\n");
0174 }
0175
0176 static void (*conf_message_callback)(const char *s) =
0177 conf_default_message_callback;
0178 void conf_set_message_callback(void (*fn)(const char *s))
0179 {
0180 conf_message_callback = fn;
0181 }
0182
0183 static void conf_message(const char *fmt, ...)
0184 {
0185 va_list ap;
0186 char buf[4096];
0187
0188 if (!conf_message_callback)
0189 return;
0190
0191 va_start(ap, fmt);
0192
0193 vsnprintf(buf, sizeof(buf), fmt, ap);
0194 conf_message_callback(buf);
0195 va_end(ap);
0196 }
0197
0198 const char *conf_get_configname(void)
0199 {
0200 char *name = getenv("KCONFIG_CONFIG");
0201
0202 return name ? name : ".config";
0203 }
0204
0205 static const char *conf_get_autoconfig_name(void)
0206 {
0207 char *name = getenv("KCONFIG_AUTOCONFIG");
0208
0209 return name ? name : "include/config/auto.conf";
0210 }
0211
0212 static const char *conf_get_autoheader_name(void)
0213 {
0214 char *name = getenv("KCONFIG_AUTOHEADER");
0215
0216 return name ? name : "include/generated/autoconf.h";
0217 }
0218
0219 static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
0220 {
0221 char *p2;
0222
0223 switch (sym->type) {
0224 case S_TRISTATE:
0225 if (p[0] == 'm') {
0226 sym->def[def].tri = mod;
0227 sym->flags |= def_flags;
0228 break;
0229 }
0230
0231 case S_BOOLEAN:
0232 if (p[0] == 'y') {
0233 sym->def[def].tri = yes;
0234 sym->flags |= def_flags;
0235 break;
0236 }
0237 if (p[0] == 'n') {
0238 sym->def[def].tri = no;
0239 sym->flags |= def_flags;
0240 break;
0241 }
0242 if (def != S_DEF_AUTO)
0243 conf_warning("symbol value '%s' invalid for %s",
0244 p, sym->name);
0245 return 1;
0246 case S_STRING:
0247
0248 if (def != S_DEF_AUTO) {
0249 if (*p++ != '"')
0250 break;
0251 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
0252 if (*p2 == '"') {
0253 *p2 = 0;
0254 break;
0255 }
0256 memmove(p2, p2 + 1, strlen(p2));
0257 }
0258 if (!p2) {
0259 conf_warning("invalid string found");
0260 return 1;
0261 }
0262 }
0263
0264 case S_INT:
0265 case S_HEX:
0266 if (sym_string_valid(sym, p)) {
0267 sym->def[def].val = xstrdup(p);
0268 sym->flags |= def_flags;
0269 } else {
0270 if (def != S_DEF_AUTO)
0271 conf_warning("symbol value '%s' invalid for %s",
0272 p, sym->name);
0273 return 1;
0274 }
0275 break;
0276 default:
0277 ;
0278 }
0279 return 0;
0280 }
0281
0282 #define LINE_GROWTH 16
0283 static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
0284 {
0285 char *nline;
0286 size_t new_size = slen + 1;
0287 if (new_size > *n) {
0288 new_size += LINE_GROWTH - 1;
0289 new_size *= 2;
0290 nline = xrealloc(*lineptr, new_size);
0291 if (!nline)
0292 return -1;
0293
0294 *lineptr = nline;
0295 *n = new_size;
0296 }
0297
0298 (*lineptr)[slen] = c;
0299
0300 return 0;
0301 }
0302
0303 static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
0304 {
0305 char *line = *lineptr;
0306 size_t slen = 0;
0307
0308 for (;;) {
0309 int c = getc(stream);
0310
0311 switch (c) {
0312 case '\n':
0313 if (add_byte(c, &line, slen, n) < 0)
0314 goto e_out;
0315 slen++;
0316
0317 case EOF:
0318 if (add_byte('\0', &line, slen, n) < 0)
0319 goto e_out;
0320 *lineptr = line;
0321 if (slen == 0)
0322 return -1;
0323 return slen;
0324 default:
0325 if (add_byte(c, &line, slen, n) < 0)
0326 goto e_out;
0327 slen++;
0328 }
0329 }
0330
0331 e_out:
0332 line[slen-1] = '\0';
0333 *lineptr = line;
0334 return -1;
0335 }
0336
0337 int conf_read_simple(const char *name, int def)
0338 {
0339 FILE *in = NULL;
0340 char *line = NULL;
0341 size_t line_asize = 0;
0342 char *p, *p2;
0343 struct symbol *sym;
0344 int i, def_flags;
0345
0346 if (name) {
0347 in = zconf_fopen(name);
0348 } else {
0349 char *env;
0350
0351 name = conf_get_configname();
0352 in = zconf_fopen(name);
0353 if (in)
0354 goto load;
0355 conf_set_changed(true);
0356
0357 env = getenv("KCONFIG_DEFCONFIG_LIST");
0358 if (!env)
0359 return 1;
0360
0361 while (1) {
0362 bool is_last;
0363
0364 while (isspace(*env))
0365 env++;
0366
0367 if (!*env)
0368 break;
0369
0370 p = env;
0371 while (*p && !isspace(*p))
0372 p++;
0373
0374 is_last = (*p == '\0');
0375
0376 *p = '\0';
0377
0378 in = zconf_fopen(env);
0379 if (in) {
0380 conf_message("using defaults found in %s",
0381 env);
0382 goto load;
0383 }
0384
0385 if (is_last)
0386 break;
0387
0388 env = p + 1;
0389 }
0390 }
0391 if (!in)
0392 return 1;
0393
0394 load:
0395 conf_filename = name;
0396 conf_lineno = 0;
0397 conf_warnings = 0;
0398
0399 def_flags = SYMBOL_DEF << def;
0400 for_all_symbols(i, sym) {
0401 sym->flags |= SYMBOL_CHANGED;
0402 sym->flags &= ~(def_flags|SYMBOL_VALID);
0403 if (sym_is_choice(sym))
0404 sym->flags |= def_flags;
0405 switch (sym->type) {
0406 case S_INT:
0407 case S_HEX:
0408 case S_STRING:
0409 if (sym->def[def].val)
0410 free(sym->def[def].val);
0411
0412 default:
0413 sym->def[def].val = NULL;
0414 sym->def[def].tri = no;
0415 }
0416 }
0417
0418 while (compat_getline(&line, &line_asize, in) != -1) {
0419 conf_lineno++;
0420 sym = NULL;
0421 if (line[0] == '#') {
0422 if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
0423 continue;
0424 p = strchr(line + 2 + strlen(CONFIG_), ' ');
0425 if (!p)
0426 continue;
0427 *p++ = 0;
0428 if (strncmp(p, "is not set", 10))
0429 continue;
0430 if (def == S_DEF_USER) {
0431 sym = sym_find(line + 2 + strlen(CONFIG_));
0432 if (!sym) {
0433 conf_set_changed(true);
0434 continue;
0435 }
0436 } else {
0437 sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
0438 if (sym->type == S_UNKNOWN)
0439 sym->type = S_BOOLEAN;
0440 }
0441 if (sym->flags & def_flags) {
0442 conf_warning("override: reassigning to symbol %s", sym->name);
0443 }
0444 switch (sym->type) {
0445 case S_BOOLEAN:
0446 case S_TRISTATE:
0447 sym->def[def].tri = no;
0448 sym->flags |= def_flags;
0449 break;
0450 default:
0451 ;
0452 }
0453 } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
0454 p = strchr(line + strlen(CONFIG_), '=');
0455 if (!p)
0456 continue;
0457 *p++ = 0;
0458 p2 = strchr(p, '\n');
0459 if (p2) {
0460 *p2-- = 0;
0461 if (*p2 == '\r')
0462 *p2 = 0;
0463 }
0464
0465 sym = sym_find(line + strlen(CONFIG_));
0466 if (!sym) {
0467 if (def == S_DEF_AUTO)
0468
0469
0470
0471
0472
0473
0474 conf_touch_dep(line + strlen(CONFIG_));
0475 else
0476 conf_set_changed(true);
0477 continue;
0478 }
0479
0480 if (sym->flags & def_flags) {
0481 conf_warning("override: reassigning to symbol %s", sym->name);
0482 }
0483 if (conf_set_sym_val(sym, def, def_flags, p))
0484 continue;
0485 } else {
0486 if (line[0] != '\r' && line[0] != '\n')
0487 conf_warning("unexpected data: %.*s",
0488 (int)strcspn(line, "\r\n"), line);
0489
0490 continue;
0491 }
0492
0493 if (sym && sym_is_choice_value(sym)) {
0494 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
0495 switch (sym->def[def].tri) {
0496 case no:
0497 break;
0498 case mod:
0499 if (cs->def[def].tri == yes) {
0500 conf_warning("%s creates inconsistent choice state", sym->name);
0501 cs->flags &= ~def_flags;
0502 }
0503 break;
0504 case yes:
0505 if (cs->def[def].tri != no)
0506 conf_warning("override: %s changes choice state", sym->name);
0507 cs->def[def].val = sym;
0508 break;
0509 }
0510 cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
0511 }
0512 }
0513 free(line);
0514 fclose(in);
0515 return 0;
0516 }
0517
0518 int conf_read(const char *name)
0519 {
0520 struct symbol *sym;
0521 int conf_unsaved = 0;
0522 int i;
0523
0524 conf_set_changed(false);
0525
0526 if (conf_read_simple(name, S_DEF_USER)) {
0527 sym_calc_value(modules_sym);
0528 return 1;
0529 }
0530
0531 sym_calc_value(modules_sym);
0532
0533 for_all_symbols(i, sym) {
0534 sym_calc_value(sym);
0535 if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
0536 continue;
0537 if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
0538
0539 switch (sym->type) {
0540 case S_BOOLEAN:
0541 case S_TRISTATE:
0542 if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym))
0543 continue;
0544 break;
0545 default:
0546 if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
0547 continue;
0548 break;
0549 }
0550 } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
0551
0552 continue;
0553 conf_unsaved++;
0554
0555 }
0556
0557 for_all_symbols(i, sym) {
0558 if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
0559
0560
0561
0562
0563
0564 if (sym->visible == no && !conf_unsaved)
0565 sym->flags &= ~SYMBOL_DEF_USER;
0566 switch (sym->type) {
0567 case S_STRING:
0568 case S_INT:
0569 case S_HEX:
0570
0571 if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
0572 break;
0573 sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
0574 conf_unsaved++;
0575 break;
0576 default:
0577 break;
0578 }
0579 }
0580 }
0581
0582 if (conf_warnings || conf_unsaved)
0583 conf_set_changed(true);
0584
0585 return 0;
0586 }
0587
0588 struct comment_style {
0589 const char *decoration;
0590 const char *prefix;
0591 const char *postfix;
0592 };
0593
0594 static const struct comment_style comment_style_pound = {
0595 .decoration = "#",
0596 .prefix = "#",
0597 .postfix = "#",
0598 };
0599
0600 static const struct comment_style comment_style_c = {
0601 .decoration = " *",
0602 .prefix = "/*",
0603 .postfix = " */",
0604 };
0605
0606 static void conf_write_heading(FILE *fp, const struct comment_style *cs)
0607 {
0608 fprintf(fp, "%s\n", cs->prefix);
0609
0610 fprintf(fp, "%s Automatically generated file; DO NOT EDIT.\n",
0611 cs->decoration);
0612
0613 fprintf(fp, "%s %s\n", cs->decoration, rootmenu.prompt->text);
0614
0615 fprintf(fp, "%s\n", cs->postfix);
0616 }
0617
0618
0619 static char *escape_string_value(const char *in)
0620 {
0621 const char *p;
0622 char *out;
0623 size_t len;
0624
0625 len = strlen(in) + strlen("\"\"") + 1;
0626
0627 p = in;
0628 while (1) {
0629 p += strcspn(p, "\"\\");
0630
0631 if (p[0] == '\0')
0632 break;
0633
0634 len++;
0635 p++;
0636 }
0637
0638 out = xmalloc(len);
0639 out[0] = '\0';
0640
0641 strcat(out, "\"");
0642
0643 p = in;
0644 while (1) {
0645 len = strcspn(p, "\"\\");
0646 strncat(out, p, len);
0647 p += len;
0648
0649 if (p[0] == '\0')
0650 break;
0651
0652 strcat(out, "\\");
0653 strncat(out, p++, 1);
0654 }
0655
0656 strcat(out, "\"");
0657
0658 return out;
0659 }
0660
0661 enum output_n { OUTPUT_N, OUTPUT_N_AS_UNSET, OUTPUT_N_NONE };
0662
0663 static void __print_symbol(FILE *fp, struct symbol *sym, enum output_n output_n,
0664 bool escape_string)
0665 {
0666 const char *val;
0667 char *escaped = NULL;
0668
0669 if (sym->type == S_UNKNOWN)
0670 return;
0671
0672 val = sym_get_string_value(sym);
0673
0674 if ((sym->type == S_BOOLEAN || sym->type == S_TRISTATE) &&
0675 output_n != OUTPUT_N && *val == 'n') {
0676 if (output_n == OUTPUT_N_AS_UNSET)
0677 fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name);
0678 return;
0679 }
0680
0681 if (sym->type == S_STRING && escape_string) {
0682 escaped = escape_string_value(val);
0683 val = escaped;
0684 }
0685
0686 fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, val);
0687
0688 free(escaped);
0689 }
0690
0691 static void print_symbol_for_dotconfig(FILE *fp, struct symbol *sym)
0692 {
0693 __print_symbol(fp, sym, OUTPUT_N_AS_UNSET, true);
0694 }
0695
0696 static void print_symbol_for_autoconf(FILE *fp, struct symbol *sym)
0697 {
0698 __print_symbol(fp, sym, OUTPUT_N_NONE, false);
0699 }
0700
0701 void print_symbol_for_listconfig(struct symbol *sym)
0702 {
0703 __print_symbol(stdout, sym, OUTPUT_N, true);
0704 }
0705
0706 static void print_symbol_for_c(FILE *fp, struct symbol *sym)
0707 {
0708 const char *val;
0709 const char *sym_suffix = "";
0710 const char *val_prefix = "";
0711 char *escaped = NULL;
0712
0713 if (sym->type == S_UNKNOWN)
0714 return;
0715
0716 val = sym_get_string_value(sym);
0717
0718 switch (sym->type) {
0719 case S_BOOLEAN:
0720 case S_TRISTATE:
0721 switch (*val) {
0722 case 'n':
0723 return;
0724 case 'm':
0725 sym_suffix = "_MODULE";
0726
0727 default:
0728 val = "1";
0729 }
0730 break;
0731 case S_HEX:
0732 if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
0733 val_prefix = "0x";
0734 break;
0735 case S_STRING:
0736 escaped = escape_string_value(val);
0737 val = escaped;
0738 default:
0739 break;
0740 }
0741
0742 fprintf(fp, "#define %s%s%s %s%s\n", CONFIG_, sym->name, sym_suffix,
0743 val_prefix, val);
0744
0745 free(escaped);
0746 }
0747
0748
0749
0750
0751
0752 int conf_write_defconfig(const char *filename)
0753 {
0754 struct symbol *sym;
0755 struct menu *menu;
0756 FILE *out;
0757
0758 out = fopen(filename, "w");
0759 if (!out)
0760 return 1;
0761
0762 sym_clear_all_valid();
0763
0764
0765 menu = rootmenu.list;
0766
0767 while (menu != NULL)
0768 {
0769 sym = menu->sym;
0770 if (sym == NULL) {
0771 if (!menu_is_visible(menu))
0772 goto next_menu;
0773 } else if (!sym_is_choice(sym)) {
0774 sym_calc_value(sym);
0775 if (!(sym->flags & SYMBOL_WRITE))
0776 goto next_menu;
0777 sym->flags &= ~SYMBOL_WRITE;
0778
0779 if (!sym_is_changeable(sym))
0780 goto next_menu;
0781
0782 if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
0783 goto next_menu;
0784
0785
0786
0787
0788
0789
0790
0791
0792 if (sym_is_choice_value(sym)) {
0793 struct symbol *cs;
0794 struct symbol *ds;
0795
0796 cs = prop_get_symbol(sym_get_choice_prop(sym));
0797 ds = sym_choice_default(cs);
0798 if (!sym_is_optional(cs) && sym == ds) {
0799 if ((sym->type == S_BOOLEAN) &&
0800 sym_get_tristate_value(sym) == yes)
0801 goto next_menu;
0802 }
0803 }
0804 print_symbol_for_dotconfig(out, sym);
0805 }
0806 next_menu:
0807 if (menu->list != NULL) {
0808 menu = menu->list;
0809 }
0810 else if (menu->next != NULL) {
0811 menu = menu->next;
0812 } else {
0813 while ((menu = menu->parent)) {
0814 if (menu->next != NULL) {
0815 menu = menu->next;
0816 break;
0817 }
0818 }
0819 }
0820 }
0821 fclose(out);
0822 return 0;
0823 }
0824
0825 int conf_write(const char *name)
0826 {
0827 FILE *out;
0828 struct symbol *sym;
0829 struct menu *menu;
0830 const char *str;
0831 char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
0832 char *env;
0833 int i;
0834 bool need_newline = false;
0835
0836 if (!name)
0837 name = conf_get_configname();
0838
0839 if (!*name) {
0840 fprintf(stderr, "config name is empty\n");
0841 return -1;
0842 }
0843
0844 if (is_dir(name)) {
0845 fprintf(stderr, "%s: Is a directory\n", name);
0846 return -1;
0847 }
0848
0849 if (make_parent_dir(name))
0850 return -1;
0851
0852 env = getenv("KCONFIG_OVERWRITECONFIG");
0853 if (env && *env) {
0854 *tmpname = 0;
0855 out = fopen(name, "w");
0856 } else {
0857 snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp",
0858 name, (int)getpid());
0859 out = fopen(tmpname, "w");
0860 }
0861 if (!out)
0862 return 1;
0863
0864 conf_write_heading(out, &comment_style_pound);
0865
0866 if (!conf_get_changed())
0867 sym_clear_all_valid();
0868
0869 menu = rootmenu.list;
0870 while (menu) {
0871 sym = menu->sym;
0872 if (!sym) {
0873 if (!menu_is_visible(menu))
0874 goto next;
0875 str = menu_get_prompt(menu);
0876 fprintf(out, "\n"
0877 "#\n"
0878 "# %s\n"
0879 "#\n", str);
0880 need_newline = false;
0881 } else if (!(sym->flags & SYMBOL_CHOICE) &&
0882 !(sym->flags & SYMBOL_WRITTEN)) {
0883 sym_calc_value(sym);
0884 if (!(sym->flags & SYMBOL_WRITE))
0885 goto next;
0886 if (need_newline) {
0887 fprintf(out, "\n");
0888 need_newline = false;
0889 }
0890 sym->flags |= SYMBOL_WRITTEN;
0891 print_symbol_for_dotconfig(out, sym);
0892 }
0893
0894 next:
0895 if (menu->list) {
0896 menu = menu->list;
0897 continue;
0898 }
0899
0900 end_check:
0901 if (!menu->sym && menu_is_visible(menu) && menu != &rootmenu &&
0902 menu->prompt->type == P_MENU) {
0903 fprintf(out, "# end of %s\n", menu_get_prompt(menu));
0904 need_newline = true;
0905 }
0906
0907 if (menu->next) {
0908 menu = menu->next;
0909 } else {
0910 menu = menu->parent;
0911 if (menu)
0912 goto end_check;
0913 }
0914 }
0915 fclose(out);
0916
0917 for_all_symbols(i, sym)
0918 sym->flags &= ~SYMBOL_WRITTEN;
0919
0920 if (*tmpname) {
0921 if (is_same(name, tmpname)) {
0922 conf_message("No change to %s", name);
0923 unlink(tmpname);
0924 conf_set_changed(false);
0925 return 0;
0926 }
0927
0928 snprintf(oldname, sizeof(oldname), "%s.old", name);
0929 rename(name, oldname);
0930 if (rename(tmpname, name))
0931 return 1;
0932 }
0933
0934 conf_message("configuration written to %s", name);
0935
0936 conf_set_changed(false);
0937
0938 return 0;
0939 }
0940
0941
0942 static int conf_write_autoconf_cmd(const char *autoconf_name)
0943 {
0944 char name[PATH_MAX], tmp[PATH_MAX];
0945 struct file *file;
0946 FILE *out;
0947 int ret;
0948
0949 ret = snprintf(name, sizeof(name), "%s.cmd", autoconf_name);
0950 if (ret >= sizeof(name))
0951 return -1;
0952
0953 if (make_parent_dir(name))
0954 return -1;
0955
0956 ret = snprintf(tmp, sizeof(tmp), "%s.cmd.tmp", autoconf_name);
0957 if (ret >= sizeof(tmp))
0958 return -1;
0959
0960 out = fopen(tmp, "w");
0961 if (!out) {
0962 perror("fopen");
0963 return -1;
0964 }
0965
0966 fprintf(out, "deps_config := \\\n");
0967 for (file = file_list; file; file = file->next)
0968 fprintf(out, "\t%s \\\n", file->name);
0969
0970 fprintf(out, "\n%s: $(deps_config)\n\n", autoconf_name);
0971
0972 env_write_dep(out, autoconf_name);
0973
0974 fprintf(out, "\n$(deps_config): ;\n");
0975
0976 fflush(out);
0977 ret = ferror(out);
0978 fclose(out);
0979 if (ret)
0980 return -1;
0981
0982 if (rename(tmp, name)) {
0983 perror("rename");
0984 return -1;
0985 }
0986
0987 return 0;
0988 }
0989
0990 static int conf_touch_deps(void)
0991 {
0992 const char *name, *tmp;
0993 struct symbol *sym;
0994 int res, i;
0995
0996 name = conf_get_autoconfig_name();
0997 tmp = strrchr(name, '/');
0998 depfile_prefix_len = tmp ? tmp - name + 1 : 0;
0999 if (depfile_prefix_len + 1 > sizeof(depfile_path))
1000 return -1;
1001
1002 strncpy(depfile_path, name, depfile_prefix_len);
1003 depfile_path[depfile_prefix_len] = 0;
1004
1005 conf_read_simple(name, S_DEF_AUTO);
1006 sym_calc_value(modules_sym);
1007
1008 for_all_symbols(i, sym) {
1009 sym_calc_value(sym);
1010 if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
1011 continue;
1012 if (sym->flags & SYMBOL_WRITE) {
1013 if (sym->flags & SYMBOL_DEF_AUTO) {
1014
1015
1016
1017
1018 switch (sym->type) {
1019 case S_BOOLEAN:
1020 case S_TRISTATE:
1021 if (sym_get_tristate_value(sym) ==
1022 sym->def[S_DEF_AUTO].tri)
1023 continue;
1024 break;
1025 case S_STRING:
1026 case S_HEX:
1027 case S_INT:
1028 if (!strcmp(sym_get_string_value(sym),
1029 sym->def[S_DEF_AUTO].val))
1030 continue;
1031 break;
1032 default:
1033 break;
1034 }
1035 } else {
1036
1037
1038
1039
1040 switch (sym->type) {
1041 case S_BOOLEAN:
1042 case S_TRISTATE:
1043 if (sym_get_tristate_value(sym) == no)
1044 continue;
1045 break;
1046 default:
1047 break;
1048 }
1049 }
1050 } else if (!(sym->flags & SYMBOL_DEF_AUTO))
1051
1052 continue;
1053
1054
1055
1056
1057
1058
1059 res = conf_touch_dep(sym->name);
1060 if (res)
1061 return res;
1062 }
1063
1064 return 0;
1065 }
1066
1067 static int __conf_write_autoconf(const char *filename,
1068 void (*print_symbol)(FILE *, struct symbol *),
1069 const struct comment_style *comment_style)
1070 {
1071 char tmp[PATH_MAX];
1072 FILE *file;
1073 struct symbol *sym;
1074 int ret, i;
1075
1076 if (make_parent_dir(filename))
1077 return -1;
1078
1079 ret = snprintf(tmp, sizeof(tmp), "%s.tmp", filename);
1080 if (ret >= sizeof(tmp))
1081 return -1;
1082
1083 file = fopen(tmp, "w");
1084 if (!file) {
1085 perror("fopen");
1086 return -1;
1087 }
1088
1089 conf_write_heading(file, comment_style);
1090
1091 for_all_symbols(i, sym)
1092 if ((sym->flags & SYMBOL_WRITE) && sym->name)
1093 print_symbol(file, sym);
1094
1095 fflush(file);
1096
1097 ret = ferror(file);
1098 fclose(file);
1099 if (ret)
1100 return -1;
1101
1102 if (rename(tmp, filename)) {
1103 perror("rename");
1104 return -1;
1105 }
1106
1107 return 0;
1108 }
1109
1110 int conf_write_autoconf(int overwrite)
1111 {
1112 struct symbol *sym;
1113 const char *autoconf_name = conf_get_autoconfig_name();
1114 int ret, i;
1115
1116 if (!overwrite && is_present(autoconf_name))
1117 return 0;
1118
1119 ret = conf_write_autoconf_cmd(autoconf_name);
1120 if (ret)
1121 return -1;
1122
1123 if (conf_touch_deps())
1124 return 1;
1125
1126 for_all_symbols(i, sym)
1127 sym_calc_value(sym);
1128
1129 ret = __conf_write_autoconf(conf_get_autoheader_name(),
1130 print_symbol_for_c,
1131 &comment_style_c);
1132 if (ret)
1133 return ret;
1134
1135
1136
1137
1138
1139
1140 ret = __conf_write_autoconf(conf_get_autoconfig_name(),
1141 print_symbol_for_autoconf,
1142 &comment_style_pound);
1143 if (ret)
1144 return ret;
1145
1146 return 0;
1147 }
1148
1149 static bool conf_changed;
1150 static void (*conf_changed_callback)(void);
1151
1152 void conf_set_changed(bool val)
1153 {
1154 if (conf_changed_callback && conf_changed != val)
1155 conf_changed_callback();
1156
1157 conf_changed = val;
1158 }
1159
1160 bool conf_get_changed(void)
1161 {
1162 return conf_changed;
1163 }
1164
1165 void conf_set_changed_callback(void (*fn)(void))
1166 {
1167 conf_changed_callback = fn;
1168 }
1169
1170 void set_all_choice_values(struct symbol *csym)
1171 {
1172 struct property *prop;
1173 struct symbol *sym;
1174 struct expr *e;
1175
1176 prop = sym_get_choice_prop(csym);
1177
1178
1179
1180
1181 expr_list_for_each_sym(prop->expr, e, sym) {
1182 if (!sym_has_value(sym))
1183 sym->def[S_DEF_USER].tri = no;
1184 }
1185 csym->flags |= SYMBOL_DEF_USER;
1186
1187 csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
1188 }