|
|
|
@ -7,15 +7,20 @@
|
|
|
|
|
#include <ctype.h> |
|
|
|
|
#include <errno.h> |
|
|
|
|
#include <fcntl.h> |
|
|
|
|
#include <stdarg.h> |
|
|
|
|
#include <stdio.h> |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
#include <time.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
|
|
|
|
|
#define LKC_DIRECT_LINK |
|
|
|
|
#include "lkc.h" |
|
|
|
|
|
|
|
|
|
struct conf_printer { |
|
|
|
|
void (*print_symbol)(FILE *, struct symbol *, const char *, void *); |
|
|
|
|
void (*print_comment)(FILE *, const char *, void *); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void conf_warning(const char *fmt, ...) |
|
|
|
|
__attribute__ ((format (printf, 1, 2))); |
|
|
|
|
|
|
|
|
@ -59,6 +64,7 @@ static void conf_message(const char *fmt, ...)
|
|
|
|
|
va_start(ap, fmt); |
|
|
|
|
if (conf_message_callback) |
|
|
|
|
conf_message_callback(fmt, ap); |
|
|
|
|
va_end(ap); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const char *conf_get_configname(void) |
|
|
|
@ -128,6 +134,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|
|
|
|
sym->flags |= def_flags; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
/* fall through */ |
|
|
|
|
case S_BOOLEAN: |
|
|
|
|
if (p[0] == 'y') { |
|
|
|
|
sym->def[def].tri = yes; |
|
|
|
@ -139,8 +146,10 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|
|
|
|
sym->flags |= def_flags; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
conf_warning("symbol value '%s' invalid for %s", p, sym->name); |
|
|
|
|
break; |
|
|
|
|
if (def != S_DEF_AUTO) |
|
|
|
|
conf_warning("symbol value '%s' invalid for %s", |
|
|
|
|
p, sym->name); |
|
|
|
|
return 1; |
|
|
|
|
case S_OTHER: |
|
|
|
|
if (*p != '"') { |
|
|
|
|
for (p2 = p; *p2 && !isspace(*p2); p2++) |
|
|
|
@ -148,6 +157,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|
|
|
|
sym->type = S_STRING; |
|
|
|
|
goto done; |
|
|
|
|
} |
|
|
|
|
/* fall through */ |
|
|
|
|
case S_STRING: |
|
|
|
|
if (*p++ != '"') |
|
|
|
|
break; |
|
|
|
@ -159,9 +169,11 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|
|
|
|
memmove(p2, p2 + 1, strlen(p2)); |
|
|
|
|
} |
|
|
|
|
if (!p2) { |
|
|
|
|
conf_warning("invalid string found"); |
|
|
|
|
if (def != S_DEF_AUTO) |
|
|
|
|
conf_warning("invalid string found"); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
/* fall through */ |
|
|
|
|
case S_INT: |
|
|
|
|
case S_HEX: |
|
|
|
|
done: |
|
|
|
@ -169,7 +181,9 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|
|
|
|
sym->def[def].val = strdup(p); |
|
|
|
|
sym->flags |= def_flags; |
|
|
|
|
} else { |
|
|
|
|
conf_warning("symbol value '%s' invalid for %s", p, sym->name); |
|
|
|
|
if (def != S_DEF_AUTO) |
|
|
|
|
conf_warning("symbol value '%s' invalid for %s", |
|
|
|
|
p, sym->name); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
@ -179,10 +193,66 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define LINE_GROWTH 16 |
|
|
|
|
static int add_byte(int c, char **lineptr, size_t slen, size_t *n) |
|
|
|
|
{ |
|
|
|
|
char *nline; |
|
|
|
|
size_t new_size = slen + 1; |
|
|
|
|
if (new_size > *n) { |
|
|
|
|
new_size += LINE_GROWTH - 1; |
|
|
|
|
new_size *= 2; |
|
|
|
|
nline = realloc(*lineptr, new_size); |
|
|
|
|
if (!nline) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
*lineptr = nline; |
|
|
|
|
*n = new_size; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
(*lineptr)[slen] = c; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) |
|
|
|
|
{ |
|
|
|
|
char *line = *lineptr; |
|
|
|
|
size_t slen = 0; |
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|
int c = getc(stream); |
|
|
|
|
|
|
|
|
|
switch (c) { |
|
|
|
|
case '\n': |
|
|
|
|
if (add_byte(c, &line, slen, n) < 0) |
|
|
|
|
goto e_out; |
|
|
|
|
slen++; |
|
|
|
|
/* fall through */ |
|
|
|
|
case EOF: |
|
|
|
|
if (add_byte('\0', &line, slen, n) < 0) |
|
|
|
|
goto e_out; |
|
|
|
|
*lineptr = line; |
|
|
|
|
if (slen == 0) |
|
|
|
|
return -1; |
|
|
|
|
return slen; |
|
|
|
|
default: |
|
|
|
|
if (add_byte(c, &line, slen, n) < 0) |
|
|
|
|
goto e_out; |
|
|
|
|
slen++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
e_out: |
|
|
|
|
line[slen-1] = '\0'; |
|
|
|
|
*lineptr = line; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int conf_read_simple(const char *name, int def) |
|
|
|
|
{ |
|
|
|
|
FILE *in = NULL; |
|
|
|
|
char line[1024]; |
|
|
|
|
char *line = NULL; |
|
|
|
|
size_t line_asize = 0; |
|
|
|
|
char *p, *p2; |
|
|
|
|
struct symbol *sym; |
|
|
|
|
int i, def_flags; |
|
|
|
@ -237,13 +307,14 @@ load:
|
|
|
|
|
case S_STRING: |
|
|
|
|
if (sym->def[def].val) |
|
|
|
|
free(sym->def[def].val); |
|
|
|
|
/* fall through */ |
|
|
|
|
default: |
|
|
|
|
sym->def[def].val = NULL; |
|
|
|
|
sym->def[def].tri = no; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (fgets(line, sizeof(line), in)) { |
|
|
|
|
while (compat_getline(&line, &line_asize, in) != -1) { |
|
|
|
|
conf_lineno++; |
|
|
|
|
sym = NULL; |
|
|
|
|
if (line[0] == '#') { |
|
|
|
@ -331,6 +402,7 @@ setsym:
|
|
|
|
|
cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
free(line); |
|
|
|
|
fclose(in); |
|
|
|
|
|
|
|
|
|
if (modules_sym) |
|
|
|
@ -340,10 +412,8 @@ setsym:
|
|
|
|
|
|
|
|
|
|
int conf_read(const char *name) |
|
|
|
|
{ |
|
|
|
|
struct symbol *sym, *choice_sym; |
|
|
|
|
struct property *prop; |
|
|
|
|
struct expr *e; |
|
|
|
|
int i, flags; |
|
|
|
|
struct symbol *sym; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
sym_set_change_count(0); |
|
|
|
|
|
|
|
|
@ -353,7 +423,7 @@ int conf_read(const char *name)
|
|
|
|
|
for_all_symbols(i, sym) { |
|
|
|
|
sym_calc_value(sym); |
|
|
|
|
if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) |
|
|
|
|
goto sym_ok; |
|
|
|
|
continue; |
|
|
|
|
if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { |
|
|
|
|
/* check that calculated value agrees with saved value */ |
|
|
|
|
switch (sym->type) { |
|
|
|
@ -362,29 +432,18 @@ int conf_read(const char *name)
|
|
|
|
|
if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) |
|
|
|
|
break; |
|
|
|
|
if (!sym_is_choice(sym)) |
|
|
|
|
goto sym_ok; |
|
|
|
|
continue; |
|
|
|
|
/* fall through */ |
|
|
|
|
default: |
|
|
|
|
if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) |
|
|
|
|
goto sym_ok; |
|
|
|
|
continue; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) |
|
|
|
|
/* no previous value and not saved */ |
|
|
|
|
goto sym_ok; |
|
|
|
|
continue; |
|
|
|
|
conf_unsaved++; |
|
|
|
|
/* maybe print value in verbose mode... */ |
|
|
|
|
sym_ok: |
|
|
|
|
if (!sym_is_choice(sym)) |
|
|
|
|
continue; |
|
|
|
|
/* The choice symbol only has a set value (and thus is not new)
|
|
|
|
|
* if all its visible childs have values. |
|
|
|
|
*/ |
|
|
|
|
prop = sym_get_choice_prop(sym); |
|
|
|
|
flags = sym->flags; |
|
|
|
|
expr_list_for_each_sym(prop->expr, e, choice_sym) |
|
|
|
|
if (choice_sym->visible != no) |
|
|
|
|
flags &= choice_sym->flags; |
|
|
|
|
sym->flags &= flags | ~SYMBOL_DEF_USER; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for_all_symbols(i, sym) { |
|
|
|
@ -417,64 +476,191 @@ int conf_read(const char *name)
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Write a S_STRING */ |
|
|
|
|
static void conf_write_string(bool headerfile, const char *name, |
|
|
|
|
const char *str, FILE *out) |
|
|
|
|
/*
|
|
|
|
|
* Kconfig configuration printer |
|
|
|
|
* |
|
|
|
|
* This printer is used when generating the resulting configuration after |
|
|
|
|
* kconfig invocation and `defconfig' files. Unset symbol might be omitted by |
|
|
|
|
* passing a non-NULL argument to the printer. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
kconfig_print_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, "# %s%s is not set\n", |
|
|
|
|
CONFIG_, sym->name); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
kconfig_print_comment(FILE *fp, const char *value, void *arg) |
|
|
|
|
{ |
|
|
|
|
int l; |
|
|
|
|
if (headerfile) |
|
|
|
|
fprintf(out, "#define %s%s \"", CONFIG_, name); |
|
|
|
|
else |
|
|
|
|
fprintf(out, "%s%s=\"", CONFIG_, name); |
|
|
|
|
|
|
|
|
|
while (1) { |
|
|
|
|
l = strcspn(str, "\"\\"); |
|
|
|
|
const char *p = value; |
|
|
|
|
size_t l; |
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|
l = strcspn(p, "\n"); |
|
|
|
|
fprintf(fp, "#"); |
|
|
|
|
if (l) { |
|
|
|
|
xfwrite(str, l, 1, out); |
|
|
|
|
str += l; |
|
|
|
|
fprintf(fp, " "); |
|
|
|
|
xfwrite(p, l, 1, fp); |
|
|
|
|
p += l; |
|
|
|
|
} |
|
|
|
|
if (!*str) |
|
|
|
|
fprintf(fp, "\n"); |
|
|
|
|
if (*p++ == '\0') |
|
|
|
|
break; |
|
|
|
|
fprintf(out, "\\%c", *str++); |
|
|
|
|
} |
|
|
|
|
fputs("\"\n", out); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) |
|
|
|
|
static struct conf_printer kconfig_printer_cb = |
|
|
|
|
{ |
|
|
|
|
.print_symbol = kconfig_print_symbol, |
|
|
|
|
.print_comment = kconfig_print_comment, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Header printer |
|
|
|
|
* |
|
|
|
|
* This printer is used when generating the `include/generated/autoconf.h' file. |
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) |
|
|
|
|
{ |
|
|
|
|
const char *str; |
|
|
|
|
|
|
|
|
|
switch (sym->type) { |
|
|
|
|
case S_BOOLEAN: |
|
|
|
|
case S_TRISTATE: |
|
|
|
|
switch (sym_get_tristate_value(sym)) { |
|
|
|
|
case no: |
|
|
|
|
if (write_no) |
|
|
|
|
fprintf(out, "# %s%s is not set\n", |
|
|
|
|
CONFIG_, sym->name); |
|
|
|
|
break; |
|
|
|
|
case mod: |
|
|
|
|
fprintf(out, "%s%s=m\n", CONFIG_, sym->name); |
|
|
|
|
break; |
|
|
|
|
case yes: |
|
|
|
|
fprintf(out, "%s%s=y\n", CONFIG_, sym->name); |
|
|
|
|
case S_TRISTATE: { |
|
|
|
|
const char *suffix = ""; |
|
|
|
|
|
|
|
|
|
switch (*value) { |
|
|
|
|
case 'n': |
|
|
|
|
break; |
|
|
|
|
case 'm': |
|
|
|
|
suffix = "_MODULE"; |
|
|
|
|
/* fall through */ |
|
|
|
|
default: |
|
|
|
|
fprintf(fp, "#define %s%s%s 1\n", |
|
|
|
|
CONFIG_, sym->name, suffix); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case S_STRING: |
|
|
|
|
conf_write_string(false, sym->name, sym_get_string_value(sym), out); |
|
|
|
|
} |
|
|
|
|
case S_HEX: { |
|
|
|
|
const char *prefix = ""; |
|
|
|
|
|
|
|
|
|
if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) |
|
|
|
|
prefix = "0x"; |
|
|
|
|
fprintf(fp, "#define %s%s %s%s\n", |
|
|
|
|
CONFIG_, sym->name, prefix, value); |
|
|
|
|
break; |
|
|
|
|
case S_HEX: |
|
|
|
|
} |
|
|
|
|
case S_STRING: |
|
|
|
|
case S_INT: |
|
|
|
|
str = sym_get_string_value(sym); |
|
|
|
|
fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); |
|
|
|
|
fprintf(fp, "#define %s%s %s\n", |
|
|
|
|
CONFIG_, sym->name, value); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
header_print_comment(FILE *fp, const char *value, void *arg) |
|
|
|
|
{ |
|
|
|
|
const char *p = value; |
|
|
|
|
size_t l; |
|
|
|
|
|
|
|
|
|
fprintf(fp, "/*\n"); |
|
|
|
|
for (;;) { |
|
|
|
|
l = strcspn(p, "\n"); |
|
|
|
|
fprintf(fp, " *"); |
|
|
|
|
if (l) { |
|
|
|
|
fprintf(fp, " "); |
|
|
|
|
xfwrite(p, l, 1, fp); |
|
|
|
|
p += l; |
|
|
|
|
} |
|
|
|
|
fprintf(fp, "\n"); |
|
|
|
|
if (*p++ == '\0') |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
fprintf(fp, " */\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static struct conf_printer header_printer_cb = |
|
|
|
|
{ |
|
|
|
|
.print_symbol = header_print_symbol, |
|
|
|
|
.print_comment = header_print_comment, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Tristate printer |
|
|
|
|
* |
|
|
|
|
* This printer is used when generating the `include/config/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) |
|
|
|
|
{ |
|
|
|
|
const char *str; |
|
|
|
|
|
|
|
|
|
switch (sym->type) { |
|
|
|
|
case S_OTHER: |
|
|
|
|
case S_UNKNOWN: |
|
|
|
|
break; |
|
|
|
|
case S_STRING: |
|
|
|
|
str = sym_get_string_value(sym); |
|
|
|
|
str = sym_escape_string_value(str); |
|
|
|
|
printer->print_symbol(fp, sym, str, printer_arg); |
|
|
|
|
free((void *)str); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
str = sym_get_string_value(sym); |
|
|
|
|
printer->print_symbol(fp, sym, str, printer_arg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) |
|
|
|
|
{ |
|
|
|
|
char buf[256]; |
|
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), |
|
|
|
|
"\n" |
|
|
|
|
"Automatically generated file; DO NOT EDIT.\n" |
|
|
|
|
"%s\n", |
|
|
|
|
rootmenu.prompt->text); |
|
|
|
|
|
|
|
|
|
printer->print_comment(fp, buf, printer_arg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Write out a minimal config. |
|
|
|
|
* All values that has default values are skipped as this is redundant. |
|
|
|
@ -531,7 +717,7 @@ int conf_write_defconfig(const char *filename)
|
|
|
|
|
goto next_menu; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
conf_write_symbol(sym, out, true); |
|
|
|
|
conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); |
|
|
|
|
} |
|
|
|
|
next_menu: |
|
|
|
|
if (menu->list != NULL) { |
|
|
|
@ -560,8 +746,6 @@ int conf_write(const char *name)
|
|
|
|
|
const char *basename; |
|
|
|
|
const char *str; |
|
|
|
|
char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; |
|
|
|
|
time_t now; |
|
|
|
|
int use_timestamp = 1; |
|
|
|
|
char *env; |
|
|
|
|
|
|
|
|
|
dirname[0] = 0; |
|
|
|
@ -598,19 +782,7 @@ int conf_write(const char *name)
|
|
|
|
|
if (!out) |
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
|
time(&now); |
|
|
|
|
env = getenv("KCONFIG_NOTIMESTAMP"); |
|
|
|
|
if (env && *env) |
|
|
|
|
use_timestamp = 0; |
|
|
|
|
|
|
|
|
|
fprintf(out, _("#\n" |
|
|
|
|
"# Automatically generated make config: don't edit\n" |
|
|
|
|
"# %s\n" |
|
|
|
|
"%s%s" |
|
|
|
|
"#\n"), |
|
|
|
|
rootmenu.prompt->text, |
|
|
|
|
use_timestamp ? "# " : "", |
|
|
|
|
use_timestamp ? ctime(&now) : ""); |
|
|
|
|
conf_write_heading(out, &kconfig_printer_cb, NULL); |
|
|
|
|
|
|
|
|
|
if (!conf_get_changed()) |
|
|
|
|
sym_clear_all_valid(); |
|
|
|
@ -631,8 +803,8 @@ int conf_write(const char *name)
|
|
|
|
|
if (!(sym->flags & SYMBOL_WRITE)) |
|
|
|
|
goto next; |
|
|
|
|
sym->flags &= ~SYMBOL_WRITE; |
|
|
|
|
/* Write config symbol to file */ |
|
|
|
|
conf_write_symbol(sym, out, true); |
|
|
|
|
|
|
|
|
|
conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
next: |
|
|
|
@ -659,7 +831,7 @@ next:
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
conf_message(_("configuration saved")); |
|
|
|
|
conf_message(_("configuration written to %s"), newname); |
|
|
|
|
|
|
|
|
|
sym_set_change_count(0); |
|
|
|
|
|
|
|
|
@ -781,7 +953,6 @@ out:
|
|
|
|
|
int conf_write_autoconf(void) |
|
|
|
|
{ |
|
|
|
|
struct symbol *sym; |
|
|
|
|
const char *str; |
|
|
|
|
const char *name; |
|
|
|
|
FILE *out, *tristate, *out_h; |
|
|
|
|
int i; |
|
|
|
@ -810,68 +981,23 @@ int conf_write_autoconf(void)
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fprintf(out, "#\n" |
|
|
|
|
"# Automatically generated make config: don't edit\n" |
|
|
|
|
"# %s\n" |
|
|
|
|
"#\n", |
|
|
|
|
rootmenu.prompt->text); |
|
|
|
|
fprintf(tristate, "#\n" |
|
|
|
|
"# Automatically generated - do not edit\n" |
|
|
|
|
"\n"); |
|
|
|
|
fprintf(out_h, "/*\n" |
|
|
|
|
" * Automatically generated C config: don't edit\n" |
|
|
|
|
" * %s\n" |
|
|
|
|
" */\n", |
|
|
|
|
rootmenu.prompt->text); |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
for_all_symbols(i, sym) { |
|
|
|
|
sym_calc_value(sym); |
|
|
|
|
if (!(sym->flags & SYMBOL_WRITE) || !sym->name) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
/* write symbol to config file */ |
|
|
|
|
conf_write_symbol(sym, out, false); |
|
|
|
|
/* write symbol to auto.conf, tristate and header files */ |
|
|
|
|
conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); |
|
|
|
|
|
|
|
|
|
/* update autoconf and tristate files */ |
|
|
|
|
switch (sym->type) { |
|
|
|
|
case S_BOOLEAN: |
|
|
|
|
case S_TRISTATE: |
|
|
|
|
switch (sym_get_tristate_value(sym)) { |
|
|
|
|
case no: |
|
|
|
|
break; |
|
|
|
|
case mod: |
|
|
|
|
fprintf(tristate, "%s%s=M\n", |
|
|
|
|
CONFIG_, sym->name); |
|
|
|
|
fprintf(out_h, "#define %s%s_MODULE 1\n", |
|
|
|
|
CONFIG_, sym->name); |
|
|
|
|
break; |
|
|
|
|
case yes: |
|
|
|
|
if (sym->type == S_TRISTATE) |
|
|
|
|
fprintf(tristate,"%s%s=Y\n", |
|
|
|
|
CONFIG_, sym->name); |
|
|
|
|
fprintf(out_h, "#define %s%s 1\n", |
|
|
|
|
CONFIG_, sym->name); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case S_STRING: |
|
|
|
|
conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); |
|
|
|
|
break; |
|
|
|
|
case S_HEX: |
|
|
|
|
str = sym_get_string_value(sym); |
|
|
|
|
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { |
|
|
|
|
fprintf(out_h, "#define %s%s 0x%s\n", |
|
|
|
|
CONFIG_, sym->name, str); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case S_INT: |
|
|
|
|
str = sym_get_string_value(sym); |
|
|
|
|
fprintf(out_h, "#define %s%s %s\n", |
|
|
|
|
CONFIG_, sym->name, str); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); |
|
|
|
|
|
|
|
|
|
conf_write_symbol(out_h, sym, &header_printer_cb, NULL); |
|
|
|
|
} |
|
|
|
|
fclose(out); |
|
|
|
|
fclose(tristate); |
|
|
|
@ -925,7 +1051,7 @@ void conf_set_changed_callback(void (*fn)(void))
|
|
|
|
|
conf_changed_callback = fn; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void randomize_choice_values(struct symbol *csym) |
|
|
|
|
static bool randomize_choice_values(struct symbol *csym) |
|
|
|
|
{ |
|
|
|
|
struct property *prop; |
|
|
|
|
struct symbol *sym; |
|
|
|
@ -938,7 +1064,7 @@ static void randomize_choice_values(struct symbol *csym)
|
|
|
|
|
* In both cases stop. |
|
|
|
|
*/ |
|
|
|
|
if (csym->curr.tri != yes) |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
prop = sym_get_choice_prop(csym); |
|
|
|
|
|
|
|
|
@ -962,13 +1088,18 @@ static void randomize_choice_values(struct symbol *csym)
|
|
|
|
|
else { |
|
|
|
|
sym->def[S_DEF_USER].tri = no; |
|
|
|
|
} |
|
|
|
|
sym->flags |= SYMBOL_DEF_USER; |
|
|
|
|
/* clear VALID to get value calculated */ |
|
|
|
|
sym->flags &= ~SYMBOL_VALID; |
|
|
|
|
} |
|
|
|
|
csym->flags |= SYMBOL_DEF_USER; |
|
|
|
|
/* clear VALID to get value calculated */ |
|
|
|
|
csym->flags &= ~(SYMBOL_VALID); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void set_all_choice_values(struct symbol *csym) |
|
|
|
|
void set_all_choice_values(struct symbol *csym) |
|
|
|
|
{ |
|
|
|
|
struct property *prop; |
|
|
|
|
struct symbol *sym; |
|
|
|
@ -985,20 +1116,66 @@ static void set_all_choice_values(struct symbol *csym)
|
|
|
|
|
} |
|
|
|
|
csym->flags |= SYMBOL_DEF_USER; |
|
|
|
|
/* clear VALID to get value calculated */ |
|
|
|
|
csym->flags &= ~(SYMBOL_VALID); |
|
|
|
|
csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void conf_set_all_new_symbols(enum conf_def_mode mode) |
|
|
|
|
bool conf_set_all_new_symbols(enum conf_def_mode mode) |
|
|
|
|
{ |
|
|
|
|
struct symbol *sym, *csym; |
|
|
|
|
int i, cnt; |
|
|
|
|
int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y
|
|
|
|
|
* pty: probability of tristate = y |
|
|
|
|
* ptm: probability of tristate = m |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
pby = 50; pty = ptm = 33; /* can't go as the default in switch-case
|
|
|
|
|
* below, otherwise gcc whines about |
|
|
|
|
* -Wmaybe-uninitialized */ |
|
|
|
|
if (mode == def_random) { |
|
|
|
|
int n, p[3]; |
|
|
|
|
char *env = getenv("KCONFIG_PROBABILITY"); |
|
|
|
|
n = 0; |
|
|
|
|
while( env && *env ) { |
|
|
|
|
char *endp; |
|
|
|
|
int tmp = strtol( env, &endp, 10 ); |
|
|
|
|
if( tmp >= 0 && tmp <= 100 ) { |
|
|
|
|
p[n++] = tmp; |
|
|
|
|
} else { |
|
|
|
|
errno = ERANGE; |
|
|
|
|
perror( "KCONFIG_PROBABILITY" ); |
|
|
|
|
exit( 1 ); |
|
|
|
|
} |
|
|
|
|
env = (*endp == ':') ? endp+1 : endp; |
|
|
|
|
if( n >=3 ) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
switch( n ) { |
|
|
|
|
case 1: |
|
|
|
|
pby = p[0]; ptm = pby/2; pty = pby-ptm; |
|
|
|
|
break; |
|
|
|
|
case 2: |
|
|
|
|
pty = p[0]; ptm = p[1]; pby = pty + ptm; |
|
|
|
|
break; |
|
|
|
|
case 3: |
|
|
|
|
pby = p[0]; pty = p[1]; ptm = p[2]; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if( pty+ptm > 100 ) { |
|
|
|
|
errno = ERANGE; |
|
|
|
|
perror( "KCONFIG_PROBABILITY" ); |
|
|
|
|
exit( 1 ); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
bool has_changed = false; |
|
|
|
|
|
|
|
|
|
for_all_symbols(i, sym) { |
|
|
|
|
if (sym_has_value(sym)) |
|
|
|
|
if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) |
|
|
|
|
continue; |
|
|
|
|
switch (sym_get_type(sym)) { |
|
|
|
|
case S_BOOLEAN: |
|
|
|
|
case S_TRISTATE: |
|
|
|
|
has_changed = true; |
|
|
|
|
switch (mode) { |
|
|
|
|
case def_yes: |
|
|
|
|
sym->def[S_DEF_USER].tri = yes; |
|
|
|
@ -1007,11 +1184,21 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
|
|
|
|
|
sym->def[S_DEF_USER].tri = mod; |
|
|
|
|
break; |
|
|
|
|
case def_no: |
|
|
|
|
sym->def[S_DEF_USER].tri = no; |
|
|
|
|
if (sym->flags & SYMBOL_ALLNOCONFIG_Y) |
|
|
|
|
sym->def[S_DEF_USER].tri = yes; |
|
|
|
|
else |
|
|
|
|
sym->def[S_DEF_USER].tri = no; |
|
|
|
|
break; |
|
|
|
|
case def_random: |
|
|
|
|
cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2; |
|
|
|
|
sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt); |
|
|
|
|
sym->def[S_DEF_USER].tri = no; |
|
|
|
|
cnt = rand() % 100; |
|
|
|
|
if (sym->type == S_TRISTATE) { |
|
|
|
|
if (cnt < pty) |
|
|
|
|
sym->def[S_DEF_USER].tri = yes; |
|
|
|
|
else if (cnt < (pty+ptm)) |
|
|
|
|
sym->def[S_DEF_USER].tri = mod; |
|
|
|
|
} else if (cnt < pby) |
|
|
|
|
sym->def[S_DEF_USER].tri = yes; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
continue; |
|
|
|
@ -1036,14 +1223,26 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
|
|
|
|
|
* selected in a choice block and we set it to yes, |
|
|
|
|
* and the rest to no. |
|
|
|
|
*/ |
|
|
|
|
if (mode != def_random) { |
|
|
|
|
for_all_symbols(i, csym) { |
|
|
|
|
if ((sym_is_choice(csym) && !sym_has_value(csym)) || |
|
|
|
|
sym_is_choice_value(csym)) |
|
|
|
|
csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for_all_symbols(i, csym) { |
|
|
|
|
if (sym_has_value(csym) || !sym_is_choice(csym)) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
sym_calc_value(csym); |
|
|
|
|
if (mode == def_random) |
|
|
|
|
randomize_choice_values(csym); |
|
|
|
|
else |
|
|
|
|
has_changed = randomize_choice_values(csym); |
|
|
|
|
else { |
|
|
|
|
set_all_choice_values(csym); |
|
|
|
|
has_changed = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return has_changed; |
|
|
|
|
} |
|
|
|
|