* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
*/
+#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
return S_ISDIR(st.st_mode);
}
+/* return true if the given two files are the same, false otherwise */
+static bool is_same(const char *file1, const char *file2)
+{
+ int fd1, fd2;
+ struct stat st1, st2;
+ void *map1, *map2;
+ bool ret = false;
+
+ fd1 = open(file1, O_RDONLY);
+ if (fd1 < 0)
+ return ret;
+
+ fd2 = open(file2, O_RDONLY);
+ if (fd2 < 0)
+ goto close1;
+
+ ret = fstat(fd1, &st1);
+ if (ret)
+ goto close2;
+ ret = fstat(fd2, &st2);
+ if (ret)
+ goto close2;
+
+ if (st1.st_size != st2.st_size)
+ goto close2;
+
+ map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
+ if (map1 == MAP_FAILED)
+ goto close2;
+
+ map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
+ if (map2 == MAP_FAILED)
+ goto close2;
+
+ if (bcmp(map1, map2, st1.st_size))
+ goto close2;
+
+ ret = true;
+close2:
+ close(fd2);
+close1:
+ close(fd1);
+
+ return ret;
+}
+
/*
* Create the parent directory of the given path.
*
static const char *conf_filename;
static int conf_lineno, conf_warnings;
-const char conf_defname[] = "include/generated/defconfig";
-
static void conf_warning(const char *fmt, ...)
{
va_list ap;
return name ? name : ".config";
}
-const char *conf_get_autoconfig_name(void)
+static const char *conf_get_autoconfig_name(void)
{
char *name = getenv("KCONFIG_AUTOCONFIG");
return name ? name : "include/generated/auto.conf";
}
-char *conf_get_default_confname(void)
-{
- static char fullname[PATH_MAX+1];
- char *env, *name;
-
- name = expand_string(conf_defname);
- env = getenv(SRCTREE);
- if (env) {
- sprintf(fullname, "%s/%s", env, name);
- if (is_present(fullname))
- return fullname;
- }
- return name;
-}
-
static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
{
char *p2;
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
- if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
- break;
- if (!sym_is_choice(sym))
+ if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym))
continue;
- /* fall through */
+ break;
default:
if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
continue;
fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value);
}
+static void
+kconfig_print_cmake_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
+{
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ if (*value == 'n') {
+ bool skip_unset = (arg != NULL);
+
+ if (!skip_unset)
+ fprintf(fp, "set(%s%s false)\n",
+ CONFIG_, sym->name, value);
+ return;
+ } else if (*value == 'm') {
+ abort();
+ } else {
+ fprintf(fp, "set(%s%s true)\n", CONFIG_, sym->name, value);
+ }
+ break;
+ case S_HEX: {
+ const char *prefix = "";
+
+ if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))
+ prefix = "0x";
+ fprintf(fp, "set(%s%s %s%s)\n",
+ CONFIG_, sym->name, prefix, value);
+ break;
+ }
+ case S_STRING:
+ case S_INT:
+ fprintf(fp, "set(%s%s %s)\n",
+ CONFIG_, sym->name, value);
+ break;
+ default:
+ break;
+ }
+
+}
+
static void
kconfig_print_comment(FILE *fp, const char *value, void *arg)
{
.print_comment = kconfig_print_comment,
};
+static struct conf_printer kconfig_printer_cmake_cb =
+{
+ .print_symbol = kconfig_print_cmake_symbol,
+ .print_comment = kconfig_print_comment,
+};
+
/*
* Header printer
*
.print_comment = header_print_comment,
};
-/*
- * Tristate printer
- *
- * This printer is used when generating the `include/generated/tristate.conf' file.
- */
-static void
-tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
-{
-
- if (sym->type == S_TRISTATE && *value != 'n')
- fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
-}
-
-static struct conf_printer tristate_printer_cb =
-{
- .print_symbol = tristate_print_symbol,
- .print_comment = kconfig_print_comment,
-};
-
static void conf_write_symbol(FILE *fp, struct symbol *sym,
struct conf_printer *printer, void *printer_arg)
{
goto next_menu;
sym->flags &= ~SYMBOL_WRITE;
/* If we cannot change the symbol - skip */
- if (!sym_is_changable(sym))
+ if (!sym_is_changeable(sym))
goto next_menu;
/* If symbol equals to default value - skip */
if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
FILE *out;
struct symbol *sym;
struct menu *menu;
- const char *basename;
const char *str;
- char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8];
+ char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
char *env;
+ int i;
+ bool need_newline = false;
+
+ if (!name)
+ name = conf_get_configname();
+
+ if (!*name) {
+ fprintf(stderr, "config name is empty\n");
+ return -1;
+ }
+
+ if (is_dir(name)) {
+ fprintf(stderr, "%s: Is a directory\n", name);
+ return -1;
+ }
+
+ if (make_parent_dir(name))
+ return -1;
- dirname[0] = 0;
- if (name && name[0]) {
- char *slash;
-
- if (is_dir(name)) {
- strcpy(dirname, name);
- strcat(dirname, "/");
- basename = conf_get_configname();
- } else if ((slash = strrchr(name, '/'))) {
- int size = slash - name + 1;
- memcpy(dirname, name, size);
- dirname[size] = 0;
- if (slash[1])
- basename = slash + 1;
- else
- basename = conf_get_configname();
- } else
- basename = name;
- } else
- basename = conf_get_configname();
-
- sprintf(newname, "%s%s", dirname, basename);
env = getenv("KCONFIG_OVERWRITECONFIG");
- if (!env || !*env) {
- sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
- out = fopen(tmpname, "w");
- } else {
+ if (env && *env) {
*tmpname = 0;
- out = fopen(newname, "w");
+ out = fopen(name, "w");
+ } else {
+ snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp",
+ name, (int)getpid());
+ out = fopen(tmpname, "w");
}
if (!out)
return 1;
"#\n"
"# %s\n"
"#\n", str);
- } else if (!(sym->flags & SYMBOL_CHOICE)) {
+ need_newline = false;
+ } else if (!(sym->flags & SYMBOL_CHOICE) &&
+ !(sym->flags & SYMBOL_WRITTEN)) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_WRITE))
goto next;
- sym->flags &= ~SYMBOL_WRITE;
-
+ if (need_newline) {
+ fprintf(out, "\n");
+ need_newline = false;
+ }
+ sym->flags |= SYMBOL_WRITTEN;
conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
}
if (menu->next)
menu = menu->next;
else while ((menu = menu->parent)) {
+ if (!menu->sym && menu_is_visible(menu) &&
+ menu != &rootmenu) {
+ str = menu_get_prompt(menu);
+ fprintf(out, "# end of %s\n", str);
+ need_newline = true;
+ }
if (menu->next) {
menu = menu->next;
break;
}
fclose(out);
+ for_all_symbols(i, sym)
+ sym->flags &= ~SYMBOL_WRITTEN;
+
if (*tmpname) {
- strcat(dirname, basename);
- strcat(dirname, ".old");
- rename(newname, dirname);
- if (rename(tmpname, newname))
+ if (is_same(name, tmpname)) {
+ conf_message("No change to %s", name);
+ unlink(tmpname);
+ sym_set_change_count(0);
+ return 0;
+ }
+
+ snprintf(oldname, sizeof(oldname), "%s.old", name);
+ rename(name, oldname);
+ if (rename(tmpname, name))
return 1;
}
- conf_message("configuration written to %s", newname);
+ conf_message("configuration written to %s", name);
sym_set_change_count(0);
struct file *file;
FILE *out;
- if (!name)
- name = ".kconfig.d";
out = fopen("..config.tmp", "w");
if (!out)
return 1;
struct symbol *sym;
const char *name;
const char *autoconf_name = conf_get_autoconfig_name();
- FILE *out, *tristate, *out_h;
+ FILE *out, *out_h, *out_c;
int i;
if (!overwrite && is_present(autoconf_name))
return 0;
- sym_clear_all_valid();
-
conf_write_dep("include/generated/auto.conf.cmd");
if (conf_touch_deps())
if (!out)
return 1;
- tristate = fopen(".tmpconfig_tristate", "w");
- if (!tristate) {
+ out_h = fopen(".tmpconfig.h", "w");
+ if (!out_h) {
fclose(out);
return 1;
}
- out_h = fopen(".tmpconfig.h", "w");
- if (!out_h) {
+ out_c = fopen(".tmpconfig.cmake", "w");
+ if (!out_c) {
fclose(out);
- fclose(tristate);
- return 1;
+ fclose(out_h);
}
conf_write_heading(out, &kconfig_printer_cb, NULL);
- conf_write_heading(tristate, &tristate_printer_cb, NULL);
-
conf_write_heading(out_h, &header_printer_cb, NULL);
+ conf_write_heading(out_c, &kconfig_printer_cmake_cb, NULL);
+
for_all_symbols(i, sym) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
continue;
- /* write symbol to auto.conf, tristate and header files */
+ /* write symbol to auto.conf and header files */
conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
- conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
-
conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
+
+ conf_write_symbol(out_c, sym, &kconfig_printer_cmake_cb, NULL);
}
fclose(out);
- fclose(tristate);
fclose(out_h);
+ fclose(out_c);
name = getenv("KCONFIG_AUTOHEADER");
if (!name)
if (rename(".tmpconfig.h", name))
return 1;
- name = getenv("KCONFIG_TRISTATE");
+ if (make_parent_dir(autoconf_name))
+ return 1;
+
+ name = getenv("KCONFIG_CMAKE");
if (!name)
- name = "include/generated/tristate.conf";
+ name = "config.cmake";
if (make_parent_dir(name))
return 1;
- if (rename(".tmpconfig_tristate", name))
+ if (rename(".tmpconfig.cmake", name))
return 1;
- if (make_parent_dir(autoconf_name))
- return 1;
/*
* This must be the last step, kbuild has a dependency on auto.conf
* and this marks the successful completion of the previous steps.
sym_calc_value(csym);
if (mode == def_random)
- has_changed = randomize_choice_values(csym);
+ has_changed |= randomize_choice_values(csym);
else {
set_all_choice_values(csym);
has_changed = true;
return has_changed;
}
+
+void conf_rewrite_mod_or_yes(enum conf_def_mode mode)
+{
+ struct symbol *sym;
+ int i;
+ tristate old_val = (mode == def_y2m) ? yes : mod;
+ tristate new_val = (mode == def_y2m) ? mod : yes;
+
+ for_all_symbols(i, sym) {
+ if (sym_get_type(sym) == S_TRISTATE &&
+ sym->def[S_DEF_USER].tri == old_val)
+ sym->def[S_DEF_USER].tri = new_val;
+ }
+ sym_clear_all_valid();
+}