Merge/rework config system per the latest from linux-2.6.0-test2.

Fix the config bugs revealed by the updated config system.
 -Erik
This commit is contained in:
Eric Andersen
2003-08-05 02:18:25 +00:00
parent 461c279ac1
commit 72d8e444f0
15 changed files with 3529 additions and 2633 deletions

View File

@ -35,50 +35,12 @@ static struct menu *rootEntry;
static char nohelp_text[] = "Sorry, no help available for this option yet.\n"; static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
#if 0
static void printc(int ch)
{
static int sep = 0;
if (!sep) {
putchar('[');
sep = 1;
} else if (ch)
putchar('/');
if (!ch) {
putchar(']');
putchar(' ');
sep = 0;
} else
putchar(ch);
}
#endif
static void printo(const char *o)
{
static int sep = 0;
if (!sep) {
putchar('(');
sep = 1;
} else if (o) {
putchar(',');
putchar(' ');
}
if (!o) {
putchar(')');
putchar(' ');
sep = 0;
} else
printf("%s", o);
}
static void strip(char *str) static void strip(char *str)
{ {
char *p = str; char *p = str;
int l; int l;
while ((isspace((int)*p))) while ((isspace(*p)))
p++; p++;
l = strlen(p); l = strlen(p);
if (p != str) if (p != str)
@ -86,10 +48,20 @@ static void strip(char *str)
if (!l) if (!l)
return; return;
p = str + l - 1; p = str + l - 1;
while ((isspace((int)*p))) while ((isspace(*p)))
*p-- = 0; *p-- = 0;
} }
static void check_stdin(void)
{
if (!valid_stdin && input_mode == ask_silent) {
printf("aborted!\n\n");
printf("Console input/output is redirected. ");
printf("Run 'make oldconfig' to update configuration.\n\n");
exit(1);
}
}
static void conf_askvalue(struct symbol *sym, const char *def) static void conf_askvalue(struct symbol *sym, const char *def)
{ {
enum symbol_type type = sym_get_type(sym); enum symbol_type type = sym_get_type(sym);
@ -101,6 +73,13 @@ static void conf_askvalue(struct symbol *sym, const char *def)
line[0] = '\n'; line[0] = '\n';
line[1] = 0; line[1] = 0;
if (!sym_is_changable(sym)) {
printf("%s\n", def);
line[0] = '\n';
line[1] = 0;
return;
}
switch (input_mode) { switch (input_mode) {
case ask_new: case ask_new:
case ask_silent: case ask_silent:
@ -108,12 +87,7 @@ static void conf_askvalue(struct symbol *sym, const char *def)
printf("%s\n", def); printf("%s\n", def);
return; return;
} }
if (!valid_stdin && input_mode == ask_silent) { check_stdin();
printf("aborted!\n\n");
printf("Console input/output is redirected. ");
printf("Run 'make oldconfig' to update configuration.\n\n");
exit(1);
}
case ask_all: case ask_all:
fflush(stdout); fflush(stdout);
fgets(line, 128, stdin); fgets(line, 128, stdin);
@ -294,9 +268,8 @@ help:
static int conf_choice(struct menu *menu) static int conf_choice(struct menu *menu)
{ {
struct symbol *sym, *def_sym; struct symbol *sym, *def_sym;
struct menu *cmenu, *def_menu; struct menu *child;
const char *help; int type;
int type, len;
bool is_new; bool is_new;
sym = menu->sym; sym = menu->sym;
@ -314,73 +287,112 @@ static int conf_choice(struct menu *menu)
break; break;
} }
} else { } else {
sym->def = sym->curr; switch (sym_get_tristate_value(sym)) {
if (S_TRI(sym->curr) == mod) { case no:
return 1;
case mod:
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
return 0; return 0;
case yes:
break;
} }
} }
while (1) { while (1) {
printf("%*s%s ", indent - 1, "", menu_get_prompt(menu)); int cnt, def;
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
def_sym = sym_get_choice_value(sym); def_sym = sym_get_choice_value(sym);
def_menu = NULL; cnt = def = 0;
for (cmenu = menu->list; cmenu; cmenu = cmenu->next) { line[0] = '0';
if (!menu_is_visible(cmenu)) line[1] = 0;
for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child))
continue;
if (!child->sym) {
printf("%*c %s\n", indent, '*', menu_get_prompt(child));
continue; continue;
printo(menu_get_prompt(cmenu));
if (cmenu->sym == def_sym)
def_menu = cmenu;
} }
printo(NULL); cnt++;
if (def_menu) if (child->sym == def_sym) {
printf("[%s] ", menu_get_prompt(def_menu)); def = cnt;
else { printf("%*c", indent, '>');
} else
printf("%*c", indent, ' ');
printf(" %d. %s", cnt, menu_get_prompt(child));
if (child->sym->name)
printf(" (%s)", child->sym->name);
if (!sym_has_value(child->sym))
printf(" (NEW)");
printf("\n"); printf("\n");
return 1;
} }
printf("%*schoice", indent - 1, "");
if (cnt == 1) {
printf("[1]: 1\n");
goto conf_childs;
}
printf("[1-%d", cnt);
if (sym->help)
printf("?");
printf("]: ");
switch (input_mode) { switch (input_mode) {
case ask_new: case ask_new:
case ask_silent: case ask_silent:
if (!is_new) {
cnt = def;
printf("%d\n", cnt);
break;
}
check_stdin();
case ask_all: case ask_all:
conf_askvalue(sym, menu_get_prompt(def_menu)); fflush(stdout);
fgets(line, 128, stdin);
strip(line); strip(line);
break; if (line[0] == '?') {
default: printf("\n%s\n", menu->sym->help ?
line[0] = 0; menu->sym->help : nohelp_text);
printf("\n");
}
if (line[0] == '?' && !line[1]) {
help = nohelp_text;
if (menu->sym->help)
help = menu->sym->help;
printf("\n%s\n", help);
continue; continue;
} }
if (line[0]) { if (!line[0])
len = strlen(line); cnt = def;
line[len] = 0; else if (isdigit(line[0]))
cnt = atoi(line);
else
continue;
break;
case set_random:
def = (random() % cnt) + 1;
case set_default:
case set_yes:
case set_mod:
case set_no:
cnt = def;
printf("%d\n", cnt);
break;
}
def_menu = NULL; conf_childs:
for (cmenu = menu->list; cmenu; cmenu = cmenu->next) { for (child = menu->list; child; child = child->next) {
if (!cmenu->sym || !menu_is_visible(cmenu)) if (!child->sym || !menu_is_visible(child))
continue; continue;
if (!strncasecmp(line, menu_get_prompt(cmenu), len)) { if (!--cnt)
def_menu = cmenu;
break; break;
} }
if (!child)
continue;
if (line[strlen(line) - 1] == '?') {
printf("\n%s\n", child->sym->help ?
child->sym->help : nohelp_text);
continue;
} }
} sym_set_choice_value(sym, child->sym);
if (def_menu) { if (child->list) {
sym_set_choice_value(sym, def_menu->sym);
if (def_menu->list) {
indent += 2; indent += 2;
conf(def_menu->list); conf(child->list);
indent -= 2; indent -= 2;
} }
return 1; return 1;
} }
}
} }
static void conf(struct menu *menu) static void conf(struct menu *menu)
@ -420,7 +432,7 @@ static void conf(struct menu *menu)
if (sym_is_choice(sym)) { if (sym_is_choice(sym)) {
conf_choice(menu); conf_choice(menu);
if (S_TRI(sym->curr) != mod) if (sym->curr.tri != mod)
return; return;
goto conf_childs; goto conf_childs;
} }
@ -454,29 +466,17 @@ static void check_conf(struct menu *menu)
return; return;
sym = menu->sym; sym = menu->sym;
if (!sym) if (sym) {
goto conf_childs; if (sym_is_changable(sym) && !sym_has_value(sym)) {
if (sym_is_choice(sym)) {
if (!sym_has_value(sym)) {
if (!conf_cnt++) if (!conf_cnt++)
printf("*\n* Restart config...\n*\n"); printf("*\n* Restart config...\n*\n");
rootEntry = menu_get_parent_menu(menu); rootEntry = menu_get_parent_menu(menu);
conf(rootEntry); conf(rootEntry);
} }
if (sym_get_tristate_value(sym) != mod) if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod)
return; return;
goto conf_childs;
} }
if (!sym_has_value(sym)) {
if (!conf_cnt++)
printf("*\n* Restart config...\n*\n");
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
}
conf_childs:
for (child = menu->list; child; child = child->next) for (child = menu->list; child; child = child->next)
check_conf(child); check_conf(child);
} }
@ -536,8 +536,8 @@ int main(int ac, char **av)
printf("***\n" printf("***\n"
"*** You have not yet configured BusyBox!\n" "*** You have not yet configured BusyBox!\n"
"***\n" "***\n"
"*** Please run some configurator (e.g. \"make oldconfig\"\n" "*** Please run some configurator (e.g. \"make config\" or\n"
"*** or \"make menuconfig\").\n" "*** \"make oldconfig\" or \"make menuconfig\").\n"
"***\n"); "***\n");
exit(1); exit(1);
} }

View File

@ -1,11 +1,9 @@
/* /*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0. * Released under the terms of the GNU GPL v2.0.
*
* Allow 'n' as a symbol value.
* 2002-11-05 Petr Baudis <pasky@ucw.cz>
*/ */
#include <sys/stat.h>
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -38,7 +36,7 @@ static char *conf_expand_value(const char *in)
strncat(res_value, in, src - in); strncat(res_value, in, src - in);
src++; src++;
dst = name; dst = name;
while (isalnum((int)*src) || *src == '_') while (isalnum(*src) || *src == '_')
*dst++ = *src++; *dst++ = *src++;
*dst = 0; *dst = 0;
sym = sym_lookup(name, 0); sym = sym_lookup(name, 0);
@ -53,7 +51,18 @@ static char *conf_expand_value(const char *in)
char *conf_get_default_confname(void) char *conf_get_default_confname(void)
{ {
return conf_expand_value(conf_defname); struct stat buf;
static char fullname[4096+1];
char *env, *name;
name = conf_expand_value(conf_defname);
env = getenv(SRCTREE);
if (env) {
sprintf(fullname, "%s/%s", env, name);
if (!stat(fullname, &buf))
return fullname;
}
return name;
} }
int conf_read(const char *name) int conf_read(const char *name)
@ -68,12 +77,12 @@ int conf_read(const char *name)
int i; int i;
if (name) { if (name) {
in = fopen(name, "r"); in = zconf_fopen(name);
} else { } else {
const char **names = conf_confnames; const char **names = conf_confnames;
while ((name = *names++)) { while ((name = *names++)) {
name = conf_expand_value(name); name = conf_expand_value(name);
in = fopen(name, "r"); in = zconf_fopen(name);
if (in) { if (in) {
printf("#\n" printf("#\n"
"# using defaults found in %s\n" "# using defaults found in %s\n"
@ -93,44 +102,43 @@ int conf_read(const char *name)
case S_INT: case S_INT:
case S_HEX: case S_HEX:
case S_STRING: case S_STRING:
if (S_VAL(sym->def)) if (sym->user.val)
free(S_VAL(sym->def)); free(sym->user.val);
default: default:
S_VAL(sym->def) = NULL; sym->user.val = NULL;
S_TRI(sym->def) = no; sym->user.tri = no;
;
} }
} }
while (fgets(line, sizeof(line), in)) { while (fgets(line, sizeof(line), in)) {
lineno++; lineno++;
sym = NULL;
switch (line[0]) { switch (line[0]) {
case '\n':
break;
case ' ':
break;
case '#': case '#':
p = strchr(line, ' '); if (line[1]!=' ')
if (!p)
continue; continue;
*p++ = 0; p = strchr(line + 2, ' ');
p = strchr(p, ' ');
if (!p) if (!p)
continue; continue;
*p++ = 0; *p++ = 0;
if (strncmp(p, "is not set", 10)) if (strncmp(p, "is not set", 10))
continue; continue;
sym = sym_lookup(line+2, 0); sym = sym_find(line + 2);
if (!sym) {
fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 2);
break;
}
switch (sym->type) { switch (sym->type) {
case S_BOOLEAN: case S_BOOLEAN:
case S_TRISTATE: case S_TRISTATE:
sym->def = symbol_no.curr; sym->user.tri = no;
sym->flags &= ~SYMBOL_NEW; sym->flags &= ~SYMBOL_NEW;
break; break;
default: default:
; ;
} }
break; break;
case 'A' ... 'Z': case 'A' ... 'Z':
p = strchr(line, '='); p = strchr(line, '=');
if (!p) if (!p)
@ -147,18 +155,18 @@ int conf_read(const char *name)
switch (sym->type) { switch (sym->type) {
case S_TRISTATE: case S_TRISTATE:
if (p[0] == 'm') { if (p[0] == 'm') {
S_TRI(sym->def) = mod; sym->user.tri = mod;
sym->flags &= ~SYMBOL_NEW; sym->flags &= ~SYMBOL_NEW;
break; break;
} }
case S_BOOLEAN: case S_BOOLEAN:
if (p[0] == 'y') { if (p[0] == 'y') {
S_TRI(sym->def) = yes; sym->user.tri = yes;
sym->flags &= ~SYMBOL_NEW; sym->flags &= ~SYMBOL_NEW;
break; break;
} }
if (p[0] == 'n') { if (p[0] == 'n') {
S_TRI(sym->def) = no; sym->user.tri = no;
sym->flags &= ~SYMBOL_NEW; sym->flags &= ~SYMBOL_NEW;
break; break;
} }
@ -173,48 +181,71 @@ int conf_read(const char *name)
} }
memmove(p2, p2 + 1, strlen(p2)); memmove(p2, p2 + 1, strlen(p2));
} }
if (!p2) {
fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
exit(1);
}
case S_INT: case S_INT:
case S_HEX: case S_HEX:
if (sym_string_valid(sym, p)) { if (sym_string_valid(sym, p)) {
S_VAL(sym->def) = strdup(p); sym->user.val = strdup(p);
sym->flags &= ~SYMBOL_NEW; sym->flags &= ~SYMBOL_NEW;
} else } else {
fprintf(stderr, "%s:%d:symbol value '%s' invalid for %s\n", name, lineno, p, sym->name); fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
exit(1);
}
break; break;
default: default:
; ;
} }
if (sym_is_choice_value(sym)) {
prop = sym_get_choice_prop(sym);
switch (S_TRI(sym->def)) {
case mod:
if (S_TRI(prop->def->def) == yes)
/* warn? */;
break; break;
case yes: case '\n':
if (S_TRI(prop->def->def) != no)
/* warn? */;
S_VAL(prop->def->def) = sym;
break;
case no:
break;
}
S_TRI(prop->def->def) = S_TRI(sym->def);
}
break; break;
default: default:
continue; continue;
} }
if (sym && sym_is_choice_value(sym)) {
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
switch (sym->user.tri) {
case no:
break;
case mod:
if (cs->user.tri == yes)
/* warn? */;
break;
case yes:
if (cs->user.tri != no)
/* warn? */;
cs->user.val = sym;
break;
}
cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
cs->flags &= ~SYMBOL_NEW;
}
} }
fclose(in); fclose(in);
for_all_symbols(i, sym) { for_all_symbols(i, sym) {
sym_calc_value(sym);
if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
if (sym->visible == no)
sym->flags |= SYMBOL_NEW;
switch (sym->type) {
case S_STRING:
case S_INT:
case S_HEX:
if (!sym_string_within_range(sym, sym->user.val))
sym->flags |= SYMBOL_NEW;
default:
break;
}
}
if (!sym_is_choice(sym)) if (!sym_is_choice(sym))
continue; continue;
prop = sym_get_choice_prop(sym); prop = sym_get_choice_prop(sym);
for (e = prop->dep; e; e = e->left.expr) for (e = prop->expr; e; e = e->left.expr)
if (e->right.sym->visible != no)
sym->flags |= e->right.sym->flags & SYMBOL_NEW; sym->flags |= e->right.sym->flags & SYMBOL_NEW;
sym->flags &= ~SYMBOL_NEW;
} }
sym_change_count = 1; sym_change_count = 1;
@ -227,19 +258,41 @@ int conf_write(const char *name)
FILE *out, *out_h; FILE *out, *out_h;
struct symbol *sym; struct symbol *sym;
struct menu *menu; struct menu *menu;
char oldname[128]; const char *basename;
char dirname[128], tmpname[128], newname[128];
int type, l; int type, l;
const char *str; const char *str;
out = fopen(".tmpconfig", "w"); dirname[0] = 0;
if (name && name[0]) {
char *slash = strrchr(name, '/');
if (slash) {
int size = slash - name + 1;
memcpy(dirname, name, size);
dirname[size] = 0;
if (slash[1])
basename = slash + 1;
else
basename = conf_def_filename;
} else
basename = name;
} else
basename = conf_def_filename;
sprintf(newname, "%s.tmpconfig.%d", dirname, getpid());
out = fopen(newname, "w");
if (!out) if (!out)
return 1; return 1;
out_h = NULL;
if (!name) {
out_h = fopen(".tmpconfig.h", "w"); out_h = fopen(".tmpconfig.h", "w");
if (!out_h) if (!out_h)
return 1; return 1;
}
fprintf(out, "#\n" fprintf(out, "#\n"
"# Automatically generated make config: don't edit\n" "# Automatically generated make config: don't edit\n"
"#\n"); "#\n");
if (out_h)
fprintf(out_h, "/*\n" fprintf(out_h, "/*\n"
" * Automatically generated header file: don't edit\n" " * Automatically generated header file: don't edit\n"
" */\n\n" " */\n\n"
@ -248,8 +301,7 @@ int conf_write(const char *name)
"#define BB_VER \"%s\"\n" "#define BB_VER \"%s\"\n"
"#define BB_BT \"%s\"\n\n", "#define BB_BT \"%s\"\n\n",
getenv("VERSION"), getenv("VERSION"),
getenv("BUILDTIME") getenv("BUILDTIME"));
);
if (!sym_change_count) if (!sym_change_count)
sym_clear_all_valid(); sym_clear_all_valid();
@ -265,6 +317,7 @@ int conf_write(const char *name)
"#\n" "#\n"
"# %s\n" "# %s\n"
"#\n", str); "#\n", str);
if (out_h)
fprintf(out_h, "\n" fprintf(out_h, "\n"
"/*\n" "/*\n"
" * %s\n" " * %s\n"
@ -277,7 +330,7 @@ int conf_write(const char *name)
type = sym->type; type = sym->type;
if (type == S_TRISTATE) { if (type == S_TRISTATE) {
sym_calc_value(modules_sym); sym_calc_value(modules_sym);
if (S_TRI(modules_sym->curr) == no) if (modules_sym->curr.tri == no)
type = S_BOOLEAN; type = S_BOOLEAN;
} }
switch (type) { switch (type) {
@ -286,16 +339,19 @@ int conf_write(const char *name)
switch (sym_get_tristate_value(sym)) { switch (sym_get_tristate_value(sym)) {
case no: case no:
fprintf(out, "# %s is not set\n", sym->name); fprintf(out, "# %s is not set\n", sym->name);
if (out_h)
fprintf(out_h, "#undef %s\n", sym->name); fprintf(out_h, "#undef %s\n", sym->name);
break; break;
case mod:
#if 0 #if 0
case mod:
fprintf(out, "%s=m\n", sym->name); fprintf(out, "%s=m\n", sym->name);
fprintf(out_h, "#define __%s__MODULE 1\n", sym->name); if (out_h)
#endif fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
break; break;
#endif
case yes: case yes:
fprintf(out, "%s=y\n", sym->name); fprintf(out, "%s=y\n", sym->name);
if (out_h)
fprintf(out_h, "#define %s 1\n", sym->name); fprintf(out_h, "#define %s 1\n", sym->name);
break; break;
} }
@ -304,33 +360,39 @@ int conf_write(const char *name)
// fix me // fix me
str = sym_get_string_value(sym); str = sym_get_string_value(sym);
fprintf(out, "%s=\"", sym->name); fprintf(out, "%s=\"", sym->name);
if (out_h)
fprintf(out_h, "#define %s \"", sym->name); fprintf(out_h, "#define %s \"", sym->name);
do { do {
l = strcspn(str, "\"\\"); l = strcspn(str, "\"\\");
if (l) { if (l) {
fwrite(str, l, 1, out); fwrite(str, l, 1, out);
if (out_h)
fwrite(str, l, 1, out_h); fwrite(str, l, 1, out_h);
} }
str += l; str += l;
while (*str == '\\' || *str == '"') { while (*str == '\\' || *str == '"') {
fprintf(out, "\\%c", *str); fprintf(out, "\\%c", *str);
if (out_h)
fprintf(out_h, "\\%c", *str); fprintf(out_h, "\\%c", *str);
str++; str++;
} }
} while (*str); } while (*str);
fputs("\"\n", out); fputs("\"\n", out);
if (out_h)
fputs("\"\n", out_h); fputs("\"\n", out_h);
break; break;
case S_HEX: case S_HEX:
str = sym_get_string_value(sym); str = sym_get_string_value(sym);
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
fprintf(out, "%s=%s\n", sym->name, str); fprintf(out, "%s=%s\n", sym->name, str);
if (out_h)
fprintf(out_h, "#define %s 0x%s\n", sym->name, str); fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
break; break;
} }
case S_INT: case S_INT:
str = sym_get_string_value(sym); str = sym_get_string_value(sym);
fprintf(out, "%s=%s\n", sym->name, str); fprintf(out, "%s=%s\n", sym->name, str);
if (out_h)
fprintf(out_h, "#define %s %s\n", sym->name, str); fprintf(out_h, "#define %s %s\n", sym->name, str);
break; break;
} }
@ -351,18 +413,19 @@ int conf_write(const char *name)
} }
} }
fclose(out); fclose(out);
if (out_h) {
fclose(out_h); fclose(out_h);
if (!name) {
rename(".tmpconfig.h", "include/config.h"); rename(".tmpconfig.h", "include/config.h");
name = conf_def_filename;
file_write_dep(NULL); file_write_dep(NULL);
} else }
unlink(".tmpconfig.h"); if (!name || basename != conf_def_filename) {
if (!name)
sprintf(oldname, "%s.old", name); name = conf_def_filename;
rename(name, oldname); sprintf(tmpname, "%s.old", name);
if (rename(".tmpconfig", name)) rename(name, tmpname);
}
sprintf(tmpname, "%s%s", dirname, basename);
if (rename(newname, tmpname))
return 1; return 1;
sym_change_count = 0; sym_change_count = 0;

View File

@ -55,6 +55,13 @@ struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
} }
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
{
if (!e1)
return e2;
return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
}
struct expr *expr_copy(struct expr *org) struct expr *expr_copy(struct expr *org)
{ {
struct expr *e; struct expr *e;
@ -158,9 +165,22 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
{ {
if (!e1 || !e2 || e1->type != e2->type) if (!e1 || !e2)
return; return;
switch (e1->type) {
case E_OR:
case E_AND:
__expr_eliminate_eq(e1->type, ep1, ep2); __expr_eliminate_eq(e1->type, ep1, ep2);
default:
;
}
if (e1->type != e2->type) switch (e2->type) {
case E_OR:
case E_AND:
__expr_eliminate_eq(e2->type, ep1, ep2);
default:
;
}
e1 = expr_eliminate_yn(e1); e1 = expr_eliminate_yn(e1);
e2 = expr_eliminate_yn(e2); e2 = expr_eliminate_yn(e2);
} }
@ -195,6 +215,7 @@ int expr_eq(struct expr *e1, struct expr *e2)
trans_count = old_count; trans_count = old_count;
return res; return res;
case E_CHOICE: case E_CHOICE:
case E_RANGE:
case E_NONE: case E_NONE:
/* panic */; /* panic */;
} }
@ -897,6 +918,7 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
case E_SYMBOL: case E_SYMBOL:
return expr_alloc_comp(type, e->left.sym, sym); return expr_alloc_comp(type, e->left.sym, sym);
case E_CHOICE: case E_CHOICE:
case E_RANGE:
case E_NONE: case E_NONE:
/* panic */; /* panic */;
} }
@ -914,7 +936,7 @@ tristate expr_calc_value(struct expr *e)
switch (e->type) { switch (e->type) {
case E_SYMBOL: case E_SYMBOL:
sym_calc_value(e->left.sym); sym_calc_value(e->left.sym);
return S_TRI(e->left.sym->curr); return e->left.sym->curr.tri;
case E_AND: case E_AND:
val1 = expr_calc_value(e->left.expr); val1 = expr_calc_value(e->left.expr);
val2 = expr_calc_value(e->right.expr); val2 = expr_calc_value(e->right.expr);
@ -1017,11 +1039,18 @@ void expr_print(struct expr *e, void (*fn)(void *, const char *), void *data, in
expr_print(e->right.expr, fn, data, E_AND); expr_print(e->right.expr, fn, data, E_AND);
break; break;
case E_CHOICE: case E_CHOICE:
if (e->left.expr) {
expr_print(e->left.expr, fn, data, E_CHOICE);
fn(data, " ^ ");
}
fn(data, e->right.sym->name); fn(data, e->right.sym->name);
if (e->left.expr) {
fn(data, " ^ ");
expr_print(e->left.expr, fn, data, E_CHOICE);
}
break;
case E_RANGE:
fn(data, "[");
fn(data, e->left.sym->name);
fn(data, " ");
fn(data, e->right.sym->name);
fn(data, "]");
break; break;
default: default:
{ {

View File

@ -18,10 +18,6 @@ extern "C" {
struct file { struct file {
struct file *next; struct file *next;
struct file *parent; struct file *parent;
#ifdef CML1
struct statement *stmt;
struct statement *last_stmt;
#endif
char *name; char *name;
int lineno; int lineno;
int flags; int flags;
@ -36,7 +32,7 @@ typedef enum tristate {
} tristate; } tristate;
enum expr_type { enum expr_type {
E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE
}; };
union expr_data { union expr_data {
@ -45,18 +41,10 @@ union expr_data {
}; };
struct expr { struct expr {
#ifdef CML1
int token;
#else
enum expr_type type; enum expr_type type;
#endif
union expr_data left, right; union expr_data left, right;
}; };
#define E_TRI(ev) ((ev).tri)
#define E_EXPR(ev) ((ev).expr)
#define E_CALC(ev) (E_TRI(ev) = expr_calc_value(E_EXPR(ev)))
#define E_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) #define E_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
#define E_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) #define E_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
#define E_NOT(dep) (2-(dep)) #define E_NOT(dep) (2-(dep))
@ -66,12 +54,8 @@ struct expr_value {
tristate tri; tristate tri;
}; };
#define S_VAL(sv) ((sv).value)
#define S_TRI(sv) ((sv).tri)
#define S_EQ(sv1, sv2) (S_VAL(sv1) == S_VAL(sv2) || !strcmp(S_VAL(sv1), S_VAL(sv2)))
struct symbol_value { struct symbol_value {
void *value; void *val;
tristate tri; tristate tri;
}; };
@ -83,31 +67,17 @@ struct symbol {
struct symbol *next; struct symbol *next;
char *name; char *name;
char *help; char *help;
#ifdef CML1
int type;
#else
enum symbol_type type; enum symbol_type type;
#endif struct symbol_value curr, user;
struct symbol_value curr, def;
tristate visible; tristate visible;
int flags; int flags;
struct property *prop; struct property *prop;
struct expr *dep, *dep2; struct expr *dep, *dep2;
struct menu *menu; struct expr_value rev_dep;
}; };
#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) #define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
#ifdef CML1
#define SYMBOL_UNKNOWN S_UNKNOWN
#define SYMBOL_BOOLEAN S_BOOLEAN
#define SYMBOL_TRISTATE S_TRISTATE
#define SYMBOL_INT S_INT
#define SYMBOL_HEX S_HEX
#define SYMBOL_STRING S_STRING
#define SYMBOL_OTHER S_OTHER
#endif
#define SYMBOL_YES 0x0001 #define SYMBOL_YES 0x0001
#define SYMBOL_MOD 0x0002 #define SYMBOL_MOD 0x0002
#define SYMBOL_NO 0x0004 #define SYMBOL_NO 0x0004
@ -122,42 +92,38 @@ struct symbol {
#define SYMBOL_CHANGED 0x0400 #define SYMBOL_CHANGED 0x0400
#define SYMBOL_NEW 0x0800 #define SYMBOL_NEW 0x0800
#define SYMBOL_AUTO 0x1000 #define SYMBOL_AUTO 0x1000
#define SYMBOL_CHECKED 0x2000
#define SYMBOL_CHECK_DONE 0x4000
#define SYMBOL_WARNED 0x8000
#define SYMBOL_MAXLENGTH 256 #define SYMBOL_MAXLENGTH 256
#define SYMBOL_HASHSIZE 257 #define SYMBOL_HASHSIZE 257
#define SYMBOL_HASHMASK 0xff #define SYMBOL_HASHMASK 0xff
enum prop_type { enum prop_type {
P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_ROOTMENU, P_DEFAULT, P_CHOICE P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_SELECT, P_RANGE
}; };
struct property { struct property {
struct property *next; struct property *next;
struct symbol *sym; struct symbol *sym;
#ifdef CML1
int token;
#else
enum prop_type type; enum prop_type type;
#endif
const char *text; const char *text;
struct symbol *def;
struct expr_value visible; struct expr_value visible;
struct expr *dep; struct expr *expr;
struct expr *dep2;
struct menu *menu; struct menu *menu;
struct file *file; struct file *file;
int lineno; int lineno;
#ifdef CML1
struct property *next_pos;
#endif
}; };
#define for_all_properties(sym, st, tok) \ #define for_all_properties(sym, st, tok) \
for (st = sym->prop; st; st = st->next) \ for (st = sym->prop; st; st = st->next) \
if (st->type == (tok)) if (st->type == (tok))
#define for_all_prompts(sym, st) for_all_properties(sym, st, P_PROMPT)
#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) #define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) #define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
#define for_all_prompts(sym, st) \
for (st = sym->prop; st; st = st->next) \
if (st->text)
struct menu { struct menu {
struct menu *next; struct menu *next;
@ -166,12 +132,16 @@ struct menu {
struct symbol *sym; struct symbol *sym;
struct property *prompt; struct property *prompt;
struct expr *dep; struct expr *dep;
unsigned int flags;
//char *help; //char *help;
struct file *file; struct file *file;
int lineno; int lineno;
void *data; void *data;
}; };
#define MENU_CHANGED 0x0001
#define MENU_ROOT 0x0002
#ifndef SWIG #ifndef SWIG
extern struct file *file_list; extern struct file *file_list;
@ -181,18 +151,12 @@ struct file *lookup_file(const char *name);
extern struct symbol symbol_yes, symbol_no, symbol_mod; extern struct symbol symbol_yes, symbol_no, symbol_mod;
extern struct symbol *modules_sym; extern struct symbol *modules_sym;
extern int cdebug; extern int cdebug;
extern int print_type;
struct expr *expr_alloc_symbol(struct symbol *sym); struct expr *expr_alloc_symbol(struct symbol *sym);
#ifdef CML1
struct expr *expr_alloc_one(int token, struct expr *ce);
struct expr *expr_alloc_two(int token, struct expr *e1, struct expr *e2);
struct expr *expr_alloc_comp(int token, struct symbol *s1, struct symbol *s2);
#else
struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
#endif
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
struct expr *expr_copy(struct expr *org); struct expr *expr_copy(struct expr *org);
void expr_free(struct expr *e); void expr_free(struct expr *e);
int expr_eq(struct expr *e1, struct expr *e2); int expr_eq(struct expr *e1, struct expr *e2);
@ -212,17 +176,6 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
void expr_fprint(struct expr *e, FILE *out); void expr_fprint(struct expr *e, FILE *out);
void print_expr(int mask, struct expr *e, int prevtoken); void print_expr(int mask, struct expr *e, int prevtoken);
#ifdef CML1
static inline int expr_is_yes(struct expr *e)
{
return !e || (e->token == WORD && e->left.sym == &symbol_yes);
}
static inline int expr_is_no(struct expr *e)
{
return e && (e->token == WORD && e->left.sym == &symbol_no);
}
#else
static inline int expr_is_yes(struct expr *e) static inline int expr_is_yes(struct expr *e)
{ {
return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
@ -233,7 +186,6 @@ static inline int expr_is_no(struct expr *e)
return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
} }
#endif #endif
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

File diff suppressed because it is too large Load Diff

View File

@ -21,12 +21,14 @@ extern "C" {
#include "lkc_proto.h" #include "lkc_proto.h"
#undef P #undef P
void symbol_end(char *help); #define SRCTREE "srctree"
int zconfparse(void); int zconfparse(void);
void zconfdump(FILE *out); void zconfdump(FILE *out);
extern int zconfdebug; extern int zconfdebug;
void zconf_starthelp(void); void zconf_starthelp(void);
FILE *zconf_fopen(const char *name);
void zconf_initscan(const char *name); void zconf_initscan(const char *name);
void zconf_nextfile(const char *name); void zconf_nextfile(const char *name);
int zconf_lineno(void); int zconf_lineno(void);
@ -47,9 +49,11 @@ void menu_add_menu(void);
void menu_end_menu(void); void menu_end_menu(void);
void menu_add_entry(struct symbol *sym); void menu_add_entry(struct symbol *sym);
void menu_end_entry(void); void menu_end_entry(void);
struct property *create_prop(enum prop_type type);
void menu_add_dep(struct expr *dep); void menu_add_dep(struct expr *dep);
struct property *menu_add_prop(int token, char *prompt, struct symbol *def, struct expr *dep); struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
void menu_finalize(struct menu *parent); void menu_finalize(struct menu *parent);
void menu_set_type(int type); void menu_set_type(int type);
struct file *file_lookup(const char *name); struct file *file_lookup(const char *name);
@ -61,16 +65,20 @@ extern struct menu *current_menu;
/* symbol.c */ /* symbol.c */
void sym_init(void); void sym_init(void);
void sym_clear_all_valid(void); void sym_clear_all_valid(void);
void sym_set_changed(struct symbol *sym);
struct symbol *sym_check_deps(struct symbol *sym);
struct property *prop_alloc(enum prop_type type, struct symbol *sym);
struct symbol *prop_get_symbol(struct property *prop);
static inline tristate sym_get_tristate_value(struct symbol *sym) static inline tristate sym_get_tristate_value(struct symbol *sym)
{ {
return S_TRI(sym->curr); return sym->curr.tri;
} }
static inline struct symbol *sym_get_choice_value(struct symbol *sym) static inline struct symbol *sym_get_choice_value(struct symbol *sym)
{ {
return (struct symbol *)S_VAL(sym->curr); return (struct symbol *)sym->curr.val;
} }
static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval) static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
@ -95,7 +103,6 @@ static inline bool sym_is_optional(struct symbol *sym)
static inline bool sym_has_value(struct symbol *sym) static inline bool sym_has_value(struct symbol *sym)
{ {
//return S_VAL(sym->def) != NULL;
return sym->flags & SYMBOL_NEW ? false : true; return sym->flags & SYMBOL_NEW ? false : true;
} }

View File

@ -5,7 +5,7 @@ P(conf_read,int,(const char *name));
P(conf_write,int,(const char *name)); P(conf_write,int,(const char *name));
/* menu.c */ /* menu.c */
extern struct menu rootmenu; P(rootmenu,struct menu,);
P(menu_is_visible,bool,(struct menu *menu)); P(menu_is_visible,bool,(struct menu *menu));
P(menu_get_prompt,const char *,(struct menu *menu)); P(menu_get_prompt,const char *,(struct menu *menu));
@ -14,17 +14,18 @@ P(menu_get_parent_menu,struct menu *,(struct menu *menu));
/* symbol.c */ /* symbol.c */
P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
extern int sym_change_count; P(sym_change_count,int,);
P(sym_lookup,struct symbol *,(const char *name, int isconst)); P(sym_lookup,struct symbol *,(const char *name, int isconst));
P(sym_find,struct symbol *,(const char *name)); P(sym_find,struct symbol *,(const char *name));
P(sym_type_name,const char *,(int type)); P(sym_type_name,const char *,(enum symbol_type type));
P(sym_calc_value,void,(struct symbol *sym)); P(sym_calc_value,void,(struct symbol *sym));
P(sym_get_type,int,(struct symbol *sym)); P(sym_get_type,enum symbol_type,(struct symbol *sym));
P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
P(sym_string_within_range,bool,(struct symbol *sym, const char *str));
P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
P(sym_is_changable,bool,(struct symbol *sym)); P(sym_is_changable,bool,(struct symbol *sym));
P(sym_get_choice_prop,struct property *,(struct symbol *sym)); P(sym_get_choice_prop,struct property *,(struct symbol *sym));

View File

@ -28,6 +28,7 @@
#define LKC_DIRECT_LINK #define LKC_DIRECT_LINK
#include "lkc.h" #include "lkc.h"
static char menu_backtitle[128];
static const char menu_instructions[] = static const char menu_instructions[] =
"Arrow keys navigate the menu. " "Arrow keys navigate the menu. "
"<Enter> selects submenus --->. " "<Enter> selects submenus --->. "
@ -65,7 +66,7 @@ load_config_help[] =
"configurations available on a single machine.\n" "configurations available on a single machine.\n"
"\n" "\n"
"If you have saved a previous configuration in a file other than the\n" "If you have saved a previous configuration in a file other than the\n"
"BusyBox default, entering the name of the file here will allow you\n" "BusyBox's default, entering the name of the file here will allow you\n"
"to modify that configuration.\n" "to modify that configuration.\n"
"\n" "\n"
"If you are uncertain, then you have probably never used alternate\n" "If you are uncertain, then you have probably never used alternate\n"
@ -120,6 +121,7 @@ static void show_readme(void);
static void init_wsize(void) static void init_wsize(void)
{ {
struct winsize ws; struct winsize ws;
char *env;
if (ioctl(1, TIOCGWINSZ, &ws) == -1) { if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
rows = 24; rows = 24;
@ -127,6 +129,20 @@ static void init_wsize(void)
} else { } else {
rows = ws.ws_row; rows = ws.ws_row;
cols = ws.ws_col; cols = ws.ws_col;
if (!rows) {
env = getenv("LINES");
if (env)
rows = atoi(env);
if (!rows)
rows = 24;
}
if (!cols) {
env = getenv("COLUMNS");
if (env)
cols = atoi(env);
if (!cols)
cols = 80;
}
} }
if (rows < 19 || cols < 80) { if (rows < 19 || cols < 80) {
@ -226,9 +242,7 @@ static void build_conf(struct menu *menu)
menu->data ? "-->" : "++>", menu->data ? "-->" : "++>",
indent + 1, ' ', prompt); indent + 1, ' ', prompt);
} else { } else {
if (menu->parent != &rootmenu) cprint_name(" %*c%s --->", indent + 1, ' ', prompt);
cprint_name(" %*c", indent + 1, ' ');
cprint_name("%s --->", prompt);
} }
if (single_menu_mode && menu->data) if (single_menu_mode && menu->data)
@ -303,7 +317,10 @@ static void build_conf(struct menu *menu)
switch (type) { switch (type) {
case S_BOOLEAN: case S_BOOLEAN:
cprint_tag("t%p", menu); cprint_tag("t%p", menu);
if (sym_is_changable(sym))
cprint_name("[%c]", val == no ? ' ' : '*'); cprint_name("[%c]", val == no ? ' ' : '*');
else
cprint_name("---");
break; break;
case S_TRISTATE: case S_TRISTATE:
cprint_tag("t%p", menu); cprint_tag("t%p", menu);
@ -312,7 +329,10 @@ static void build_conf(struct menu *menu)
case mod: ch = 'M'; break; case mod: ch = 'M'; break;
default: ch = ' '; break; default: ch = ' '; break;
} }
if (sym_is_changable(sym))
cprint_name("<%c>", ch); cprint_name("<%c>", ch);
else
cprint_name("---");
break; break;
default: default:
cprint_tag("s%p", menu); cprint_tag("s%p", menu);
@ -321,12 +341,18 @@ static void build_conf(struct menu *menu)
if (tmp < 0) if (tmp < 0)
tmp = 0; tmp = 0;
cprint_name("%*c%s%s", tmp, ' ', menu_get_prompt(menu), cprint_name("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
sym_has_value(sym) ? "" : " (NEW)"); (sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : " (NEW)");
goto conf_childs; goto conf_childs;
} }
} }
cprint_name("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), cprint_name("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
sym_has_value(sym) ? "" : " (NEW)"); (sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : " (NEW)");
if (menu->prompt->type == P_MENU) {
cprint_name(" --->");
return;
}
} }
conf_childs: conf_childs:
@ -390,13 +416,15 @@ static void conf(struct menu *menu)
switch (type) { switch (type) {
case 'm': case 'm':
if (single_menu_mode) if (single_menu_mode)
submenu->data = (submenu->data)? NULL : (void *)1; submenu->data = (void *) (long) !submenu->data;
else else
conf(submenu); conf(submenu);
break; break;
case 't': case 't':
if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
conf_choice(submenu); conf_choice(submenu);
else if (submenu->prompt->type == P_MENU)
conf(submenu);
break; break;
case 's': case 's':
conf_string(submenu); conf_string(submenu);
@ -602,7 +630,6 @@ static void conf_cleanup(void)
{ {
tcsetattr(1, TCSAFLUSH, &ios_org); tcsetattr(1, TCSAFLUSH, &ios_org);
unlink(".help.tmp"); unlink(".help.tmp");
unlink("lxdialog.scrltmp");
} }
static void winch_handler(int sig) static void winch_handler(int sig)
@ -638,10 +665,9 @@ int main(int ac, char **av)
conf_parse(av[1]); conf_parse(av[1]);
conf_read(NULL); conf_read(NULL);
backtitle = malloc(128);
sym = sym_lookup("VERSION", 0); sym = sym_lookup("VERSION", 0);
sym_calc_value(sym); sym_calc_value(sym);
snprintf(backtitle, 128, "BusyBox v%s Configuration", snprintf(menu_backtitle, 128, "BusyBox v%s Configuration",
sym_get_string_value(sym)); sym_get_string_value(sym));
mode = getenv("MENUCONFIG_MODE"); mode = getenv("MENUCONFIG_MODE");

View File

@ -54,9 +54,34 @@ void menu_end_menu(void)
current_menu = current_menu->parent; current_menu = current_menu->parent;
} }
struct expr *menu_check_dep(struct expr *e)
{
if (!e)
return e;
switch (e->type) {
case E_NOT:
e->left.expr = menu_check_dep(e->left.expr);
break;
case E_OR:
case E_AND:
e->left.expr = menu_check_dep(e->left.expr);
e->right.expr = menu_check_dep(e->right.expr);
break;
case E_SYMBOL:
/* change 'm' into 'm' && MODULES */
if (e->left.sym == &symbol_mod)
return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
break;
default:
break;
}
return e;
}
void menu_add_dep(struct expr *dep) void menu_add_dep(struct expr *dep)
{ {
current_entry->dep = expr_alloc_and(current_entry->dep, dep); current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
} }
void menu_set_type(int type) void menu_set_type(int type)
@ -69,56 +94,43 @@ void menu_set_type(int type)
sym->type = type; sym->type = type;
return; return;
} }
fprintf(stderr, "%s:%d: type of '%s' redefined from '%s' to '%s'\n", fprintf(stderr, "%s:%d:warning: type of '%s' redefined from '%s' to '%s'\n",
current_entry->file->name, current_entry->lineno, current_entry->file->name, current_entry->lineno,
sym->name ? sym->name : "<choice>", sym_type_name(sym->type), sym_type_name(type)); sym->name ? sym->name : "<choice>", sym_type_name(sym->type), sym_type_name(type));
} }
struct property *create_prop(enum prop_type type) struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
{ {
struct property *prop; struct property *prop = prop_alloc(type, current_entry->sym);
prop = malloc(sizeof(*prop));
memset(prop, 0, sizeof(*prop));
prop->type = type;
prop->file = current_file;
prop->lineno = zconf_lineno();
return prop;
}
struct property *menu_add_prop(int token, char *prompt, struct symbol *def, struct expr *dep)
{
struct property *prop = create_prop(token);
struct property **propp;
prop->sym = current_entry->sym;
prop->menu = current_entry; prop->menu = current_entry;
prop->text = prompt; prop->text = prompt;
prop->def = def; prop->expr = expr;
E_EXPR(prop->visible) = dep; prop->visible.expr = menu_check_dep(dep);
if (prompt) if (prompt) {
if (current_entry->prompt)
fprintf(stderr, "%s:%d: prompt redefined\n",
current_entry->file->name, current_entry->lineno);
current_entry->prompt = prop; current_entry->prompt = prop;
/* append property to the prop list of symbol */
if (prop->sym) {
for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next)
;
*propp = prop;
} }
return prop; return prop;
} }
void menu_add_prompt(int token, char *prompt, struct expr *dep) void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
{ {
current_entry->prompt = menu_add_prop(token, prompt, NULL, dep); menu_add_prop(type, prompt, NULL, dep);
} }
void menu_add_default(int token, struct symbol *def, struct expr *dep) void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
{ {
current_entry->prompt = menu_add_prop(token, NULL, def, dep); menu_add_prop(type, NULL, expr, dep);
}
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
{
menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
} }
void menu_finalize(struct menu *parent) void menu_finalize(struct menu *parent)
@ -126,7 +138,7 @@ void menu_finalize(struct menu *parent)
struct menu *menu, *last_menu; struct menu *menu, *last_menu;
struct symbol *sym; struct symbol *sym;
struct property *prop; struct property *prop;
struct expr *parentdep, *basedep, *dep, *dep2; struct expr *parentdep, *basedep, *dep, *dep2, **ep;
sym = parent->sym; sym = parent->sym;
if (parent->list) { if (parent->list) {
@ -143,7 +155,7 @@ void menu_finalize(struct menu *parent)
} }
parentdep = expr_alloc_symbol(sym); parentdep = expr_alloc_symbol(sym);
} else if (parent->prompt) } else if (parent->prompt)
parentdep = E_EXPR(parent->prompt->visible); parentdep = parent->prompt->visible.expr;
else else
parentdep = parent->dep; parentdep = parent->dep;
@ -159,23 +171,28 @@ void menu_finalize(struct menu *parent)
for (; prop; prop = prop->next) { for (; prop; prop = prop->next) {
if (prop->menu != menu) if (prop->menu != menu)
continue; continue;
dep = expr_transform(E_EXPR(prop->visible)); dep = expr_transform(prop->visible.expr);
dep = expr_alloc_and(expr_copy(basedep), dep); dep = expr_alloc_and(expr_copy(basedep), dep);
dep = expr_eliminate_dups(dep); dep = expr_eliminate_dups(dep);
if (menu->sym && menu->sym->type != S_TRISTATE) if (menu->sym && menu->sym->type != S_TRISTATE)
dep = expr_trans_bool(dep); dep = expr_trans_bool(dep);
E_EXPR(prop->visible) = dep; prop->visible.expr = dep;
if (prop->type == P_SELECT) {
struct symbol *es = prop_get_symbol(prop);
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
}
} }
} }
for (menu = parent->list; menu; menu = menu->next) for (menu = parent->list; menu; menu = menu->next)
menu_finalize(menu); menu_finalize(menu);
} else if (sym && parent->prompt) { } else if (sym) {
basedep = E_EXPR(parent->prompt->visible); basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
basedep = expr_eliminate_dups(expr_transform(basedep)); basedep = expr_eliminate_dups(expr_transform(basedep));
last_menu = NULL; last_menu = NULL;
for (menu = parent->next; menu; menu = menu->next) { for (menu = parent->next; menu; menu = menu->next) {
dep = menu->prompt ? E_EXPR(menu->prompt->visible) : menu->dep; dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
if (!expr_contains_symbol(dep, sym)) if (!expr_contains_symbol(dep, sym))
break; break;
if (expr_depends_symbol(dep, sym)) if (expr_depends_symbol(dep, sym))
@ -204,14 +221,27 @@ void menu_finalize(struct menu *parent)
for (menu = parent->list; menu; menu = menu->next) { for (menu = parent->list; menu; menu = menu->next) {
if (sym && sym_is_choice(sym) && menu->sym) { if (sym && sym_is_choice(sym) && menu->sym) {
menu->sym->flags |= SYMBOL_CHOICEVAL; menu->sym->flags |= SYMBOL_CHOICEVAL;
if (!menu->prompt)
fprintf(stderr, "%s:%d:warning: choice value must have a prompt\n",
menu->file->name, menu->lineno);
for (prop = menu->sym->prop; prop; prop = prop->next) {
if (prop->type == P_PROMPT && prop->menu != menu) {
fprintf(stderr, "%s:%d:warning: choice values currently only support a single prompt\n",
prop->file->name, prop->lineno);
}
if (prop->type == P_DEFAULT)
fprintf(stderr, "%s:%d:warning: defaults for choice values not supported\n",
prop->file->name, prop->lineno);
}
current_entry = menu; current_entry = menu;
menu_set_type(sym->type); menu_set_type(sym->type);
menu_add_prop(P_CHOICE, NULL, parent->sym, NULL); menu_add_symbol(P_CHOICE, sym, NULL);
prop = sym_get_choice_prop(parent->sym); prop = sym_get_choice_prop(sym);
//dep = expr_alloc_one(E_CHOICE, dep); for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
//dep->right.sym = menu->sym; ;
prop->dep = expr_alloc_one(E_CHOICE, prop->dep); *ep = expr_alloc_one(E_CHOICE, NULL);
prop->dep->right.sym = menu->sym; (*ep)->right.sym = menu->sym;
} }
if (menu->list && (!menu->prompt || !menu->prompt->text)) { if (menu->list && (!menu->prompt || !menu->prompt->text)) {
for (last_menu = menu->list; ; last_menu = last_menu->next) { for (last_menu = menu->list; ; last_menu = last_menu->next) {
@ -224,20 +254,79 @@ void menu_finalize(struct menu *parent)
menu->list = NULL; menu->list = NULL;
} }
} }
if (sym && !(sym->flags & SYMBOL_WARNED)) {
struct symbol *sym2;
if (sym->type == S_UNKNOWN)
fprintf(stderr, "%s:%d:warning: config symbol defined without type\n",
parent->file->name, parent->lineno);
if (sym_is_choice(sym) && !parent->prompt)
fprintf(stderr, "%s:%d:warning: choice must have a prompt\n",
parent->file->name, parent->lineno);
for (prop = sym->prop; prop; prop = prop->next) {
switch (prop->type) {
case P_DEFAULT:
if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
prop->expr->type != E_SYMBOL)
fprintf(stderr, "%s:%d:warning: default must be a single symbol\n",
prop->file->name, prop->lineno);
break;
case P_SELECT:
sym2 = prop_get_symbol(prop);
if ((sym->type != S_BOOLEAN && sym->type != S_TRISTATE) ||
(sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE))
fprintf(stderr, "%s:%d:warning: enable is only allowed with boolean and tristate symbols\n",
prop->file->name, prop->lineno);
break;
case P_RANGE:
if (sym->type != S_INT && sym->type != S_HEX)
fprintf(stderr, "%s:%d:warning: range is only allowed for int or hex symbols\n",
prop->file->name, prop->lineno);
if (!sym_string_valid(sym, prop->expr->left.sym->name) ||
!sym_string_valid(sym, prop->expr->right.sym->name))
fprintf(stderr, "%s:%d:warning: range is invalid\n",
prop->file->name, prop->lineno);
break;
default:
;
}
}
sym->flags |= SYMBOL_WARNED;
}
if (sym && !sym_is_optional(sym) && parent->prompt) {
sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
expr_alloc_and(parent->prompt->visible.expr,
expr_alloc_symbol(&symbol_mod)));
}
} }
bool menu_is_visible(struct menu *menu) bool menu_is_visible(struct menu *menu)
{ {
struct menu *child;
struct symbol *sym;
tristate visible; tristate visible;
if (!menu->prompt) if (!menu->prompt)
return false; return false;
if (menu->sym) { sym = menu->sym;
sym_calc_value(menu->sym); if (sym) {
visible = E_TRI(menu->prompt->visible); sym_calc_value(sym);
visible = menu->prompt->visible.tri;
} else } else
visible = E_CALC(menu->prompt->visible); visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
return visible != no;
if (visible != no)
return true;
if (!sym || sym_get_tristate_value(menu->sym) == no)
return false;
for (child = menu->list; child; child = child->next)
if (menu_is_visible(child))
return true;
return false;
} }
const char *menu_get_prompt(struct menu *menu) const char *menu_get_prompt(struct menu *menu)
@ -258,10 +347,9 @@ struct menu *menu_get_parent_menu(struct menu *menu)
{ {
enum prop_type type; enum prop_type type;
while (menu != &rootmenu) { for (; menu != &rootmenu; menu = menu->parent) {
menu = menu->parent;
type = menu->prompt ? menu->prompt->type : 0; type = menu->prompt ? menu->prompt->type : 0;
if (type == P_MENU || type == P_ROOTMENU) if (type == P_MENU)
break; break;
} }
return menu; return menu;

View File

@ -34,24 +34,14 @@ struct symbol *modules_sym;
void sym_add_default(struct symbol *sym, const char *def) void sym_add_default(struct symbol *sym, const char *def)
{ {
struct property *prop = create_prop(P_DEFAULT); struct property *prop = prop_alloc(P_DEFAULT, sym);
struct property **propp;
prop->sym = sym; prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
prop->def = sym_lookup(def, 1);
/* append property to the prop list of symbol */
if (prop->sym) {
for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next)
;
*propp = prop;
}
} }
void sym_init(void) void sym_init(void)
{ {
struct symbol *sym; struct symbol *sym;
struct utsname uts;
char *p; char *p;
static bool inited = false; static bool inited = false;
@ -59,17 +49,6 @@ void sym_init(void)
return; return;
inited = true; inited = true;
uname(&uts);
#if 0
sym = sym_lookup("ARCH", 0);
sym->type = S_STRING;
sym->flags |= SYMBOL_AUTO;
p = getenv("ARCH");
if (p)
sym_add_default(sym, p);
#endif
sym = sym_lookup("VERSION", 0); sym = sym_lookup("VERSION", 0);
sym->type = S_STRING; sym->type = S_STRING;
sym->flags |= SYMBOL_AUTO; sym->flags |= SYMBOL_AUTO;
@ -77,37 +56,32 @@ void sym_init(void)
if (p) if (p)
sym_add_default(sym, p); sym_add_default(sym, p);
#if 0
sym = sym_lookup("UNAME_RELEASE", 0);
sym->type = S_STRING;
sym->flags |= SYMBOL_AUTO;
sym_add_default(sym, uts.release);
#endif
sym = sym_lookup("TARGET_ARCH", 0); sym = sym_lookup("TARGET_ARCH", 0);
sym->type = S_STRING; sym->type = S_STRING;
sym->flags |= SYMBOL_AUTO; sym->flags |= SYMBOL_AUTO;
p = getenv("TARGET_ARCH"); p = getenv("TARGET_ARCH");
if (p) if (p)
sym_add_default(sym, p); sym_add_default(sym, p);
} }
int sym_get_type(struct symbol *sym) enum symbol_type sym_get_type(struct symbol *sym)
{ {
int type = sym->type; enum symbol_type type = sym->type;
if (type == S_TRISTATE) { if (type == S_TRISTATE) {
if (sym_is_choice_value(sym) && sym->visible == yes) if (sym_is_choice_value(sym) && sym->visible == yes)
type = S_BOOLEAN; type = S_BOOLEAN;
else { else {
sym_calc_value(modules_sym); sym_calc_value(modules_sym);
if (S_TRI(modules_sym->curr) == no) if (modules_sym->curr.tri == no)
type = S_BOOLEAN; type = S_BOOLEAN;
} }
} }
return type; return type;
} }
const char *sym_type_name(int type) const char *sym_type_name(enum symbol_type type)
{ {
switch (type) { switch (type) {
case S_BOOLEAN: case S_BOOLEAN:
@ -122,6 +96,8 @@ const char *sym_type_name(int type)
return "string"; return "string";
case S_UNKNOWN: case S_UNKNOWN:
return "unknown"; return "unknown";
case S_OTHER:
break;
} }
return "???"; return "???";
} }
@ -138,41 +114,104 @@ struct property *sym_get_choice_prop(struct symbol *sym)
struct property *sym_get_default_prop(struct symbol *sym) struct property *sym_get_default_prop(struct symbol *sym)
{ {
struct property *prop; struct property *prop;
tristate visible;
for_all_defaults(sym, prop) { for_all_defaults(sym, prop) {
visible = E_CALC(prop->visible); prop->visible.tri = expr_calc_value(prop->visible.expr);
if (visible != no) if (prop->visible.tri != no)
return prop; return prop;
} }
return NULL; return NULL;
} }
void sym_calc_visibility(struct symbol *sym) struct property *sym_get_range_prop(struct symbol *sym)
{ {
struct property *prop; struct property *prop;
tristate visible, oldvisible;
for_all_properties(sym, prop, P_RANGE) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
if (prop->visible.tri != no)
return prop;
}
return NULL;
}
static void sym_calc_visibility(struct symbol *sym)
{
struct property *prop;
tristate tri;
/* any prompt visible? */ /* any prompt visible? */
oldvisible = sym->visible; tri = no;
visible = no; for_all_prompts(sym, prop) {
for_all_prompts(sym, prop) prop->visible.tri = expr_calc_value(prop->visible.expr);
visible = E_OR(visible, E_CALC(prop->visible)); tri = E_OR(tri, prop->visible.tri);
if (oldvisible != visible) {
sym->visible = visible;
sym->flags |= SYMBOL_CHANGED;
} }
if (sym->visible != tri) {
sym->visible = tri;
sym_set_changed(sym);
}
if (sym_is_choice_value(sym))
return;
tri = no;
if (sym->rev_dep.expr)
tri = expr_calc_value(sym->rev_dep.expr);
if (sym->rev_dep.tri != tri) {
sym->rev_dep.tri = tri;
sym_set_changed(sym);
}
}
static struct symbol *sym_calc_choice(struct symbol *sym)
{
struct symbol *def_sym;
struct property *prop;
struct expr *e;
/* is the user choice visible? */
def_sym = sym->user.val;
if (def_sym) {
sym_calc_visibility(def_sym);
if (def_sym->visible != no)
return def_sym;
}
/* any of the defaults visible? */
for_all_defaults(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
if (prop->visible.tri == no)
continue;
def_sym = prop_get_symbol(prop);
sym_calc_visibility(def_sym);
if (def_sym->visible != no)
return def_sym;
}
/* just get the first visible value */
prop = sym_get_choice_prop(sym);
for (e = prop->expr; e; e = e->left.expr) {
def_sym = e->right.sym;
sym_calc_visibility(def_sym);
if (def_sym->visible != no)
return def_sym;
}
/* no choice? reset tristate value */
sym->curr.tri = no;
return NULL;
} }
void sym_calc_value(struct symbol *sym) void sym_calc_value(struct symbol *sym)
{ {
struct symbol_value newval, oldval; struct symbol_value newval, oldval;
struct property *prop, *def_prop; struct property *prop;
struct symbol *def_sym;
struct expr *e; struct expr *e;
if (!sym)
return;
if (sym->flags & SYMBOL_VALID) if (sym->flags & SYMBOL_VALID)
return; return;
sym->flags |= SYMBOL_VALID;
oldval = sym->curr; oldval = sym->curr;
@ -187,17 +226,10 @@ void sym_calc_value(struct symbol *sym)
newval = symbol_no.curr; newval = symbol_no.curr;
break; break;
default: default:
S_VAL(newval) = sym->name; sym->curr.val = sym->name;
S_TRI(newval) = no; sym->curr.tri = no;
if (sym->flags & SYMBOL_CONST) { return;
goto out;
} }
//newval = symbol_empty.curr;
// generate warning somewhere here later
//S_TRI(newval) = yes;
goto out;
}
sym->flags |= SYMBOL_VALID;
if (!sym_is_choice_value(sym)) if (!sym_is_choice_value(sym))
sym->flags &= ~SYMBOL_WRITE; sym->flags &= ~SYMBOL_WRITE;
@ -206,95 +238,77 @@ void sym_calc_value(struct symbol *sym)
/* set default if recursively called */ /* set default if recursively called */
sym->curr = newval; sym->curr = newval;
if (sym->visible != no) { switch (sym_get_type(sym)) {
sym->flags |= SYMBOL_WRITE; case S_BOOLEAN:
if (!sym_has_value(sym)) { case S_TRISTATE:
if (!sym_is_choice(sym)) {
prop = sym_get_default_prop(sym);
if (prop) {
sym_calc_value(prop->def);
newval = prop->def->curr;
}
}
} else
newval = sym->def;
S_TRI(newval) = E_AND(S_TRI(newval), sym->visible);
/* if the symbol is visible and not optionial,
* possibly ignore old user choice. */
if (!sym_is_optional(sym) && S_TRI(newval) == no)
S_TRI(newval) = sym->visible;
if (sym_is_choice_value(sym) && sym->visible == yes) { if (sym_is_choice_value(sym) && sym->visible == yes) {
prop = sym_get_choice_prop(sym); prop = sym_get_choice_prop(sym);
S_TRI(newval) = (S_VAL(prop->def->curr) == sym) ? yes : no; newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
sym->flags |= SYMBOL_WRITE;
if (sym_has_value(sym))
newval.tri = sym->user.tri;
else if (!sym_is_choice(sym)) {
prop = sym_get_default_prop(sym);
if (prop)
newval.tri = expr_calc_value(prop->expr);
} }
} else { newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
} else if (!sym_is_choice(sym)) {
prop = sym_get_default_prop(sym); prop = sym_get_default_prop(sym);
if (prop) { if (prop) {
sym->flags |= SYMBOL_WRITE; sym->flags |= SYMBOL_WRITE;
sym_calc_value(prop->def); newval.tri = expr_calc_value(prop->expr);
newval = prop->def->curr;
} }
} }
if (sym_get_type(sym) == S_BOOLEAN) {
if (newval.tri == mod)
newval.tri = yes;
if (sym->visible == mod)
sym->visible = yes;
if (sym->rev_dep.tri == mod)
sym->rev_dep.tri = yes;
}
break;
case S_STRING:
case S_HEX:
case S_INT:
if (sym->visible != no) {
sym->flags |= SYMBOL_WRITE;
if (sym_has_value(sym)) {
newval.val = sym->user.val;
break;
}
}
prop = sym_get_default_prop(sym);
if (prop) {
struct symbol *ds = prop_get_symbol(prop);
if (ds) {
sym->flags |= SYMBOL_WRITE;
sym_calc_value(ds);
newval.val = ds->curr.val;
}
}
break;
default:
;
}
switch (sym_get_type(sym)) {
case S_TRISTATE:
if (S_TRI(newval) != mod)
break;
sym_calc_value(modules_sym);
if (S_TRI(modules_sym->curr) == no)
S_TRI(newval) = yes;
break;
case S_BOOLEAN:
if (S_TRI(newval) == mod)
S_TRI(newval) = yes;
}
out:
sym->curr = newval; sym->curr = newval;
if (sym_is_choice(sym) && newval.tri == yes)
sym->curr.val = sym_calc_choice(sym);
if (sym_is_choice(sym) && S_TRI(newval) == yes) { if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
def_sym = S_VAL(sym->def); sym_set_changed(sym);
if (def_sym) {
sym_calc_visibility(def_sym);
if (def_sym->visible == no)
def_sym = NULL;
}
if (!def_sym) {
for_all_defaults(sym, def_prop) {
if (E_CALC(def_prop->visible) == no)
continue;
sym_calc_visibility(def_prop->def);
if (def_prop->def->visible != no) {
def_sym = def_prop->def;
break;
}
}
}
if (!def_sym) {
prop = sym_get_choice_prop(sym);
for (e = prop->dep; e; e = e->left.expr) {
sym_calc_visibility(e->right.sym);
if (e->right.sym->visible != no) {
def_sym = e->right.sym;
break;
}
}
}
S_VAL(newval) = def_sym;
}
if (memcmp(&oldval, &newval, sizeof(newval)))
sym->flags |= SYMBOL_CHANGED;
sym->curr = newval;
if (sym_is_choice(sym)) { if (sym_is_choice(sym)) {
int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
prop = sym_get_choice_prop(sym); prop = sym_get_choice_prop(sym);
for (e = prop->dep; e; e = e->left.expr) for (e = prop->expr; e; e = e->left.expr) {
e->right.sym->flags |= flags; e->right.sym->flags |= flags;
if (flags & SYMBOL_CHANGED)
sym_set_changed(e->right.sym);
}
} }
} }
@ -308,13 +322,24 @@ void sym_clear_all_valid(void)
sym_change_count++; sym_change_count++;
} }
void sym_set_changed(struct symbol *sym)
{
struct property *prop;
sym->flags |= SYMBOL_CHANGED;
for (prop = sym->prop; prop; prop = prop->next) {
if (prop->menu)
prop->menu->flags |= MENU_CHANGED;
}
}
void sym_set_all_changed(void) void sym_set_all_changed(void)
{ {
struct symbol *sym; struct symbol *sym;
int i; int i;
for_all_symbols(i, sym) for_all_symbols(i, sym)
sym->flags |= SYMBOL_CHANGED; sym_set_changed(sym);
} }
bool sym_tristate_within_range(struct symbol *sym, tristate val) bool sym_tristate_within_range(struct symbol *sym, tristate val)
@ -327,19 +352,13 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val)
if (type != S_BOOLEAN && type != S_TRISTATE) if (type != S_BOOLEAN && type != S_TRISTATE)
return false; return false;
switch (val) { if (type == S_BOOLEAN && val == mod)
case no: return false;
if (sym->visible <= sym->rev_dep.tri)
return false;
if (sym_is_choice_value(sym) && sym->visible == yes) if (sym_is_choice_value(sym) && sym->visible == yes)
return false; return val == yes;
return sym_is_optional(sym); return val >= sym->rev_dep.tri && val <= sym->visible;
case mod:
if (sym_is_choice_value(sym) && sym->visible == yes)
return false;
return type == S_TRISTATE;
case yes:
return type == S_BOOLEAN || sym->visible == yes;
}
return false;
} }
bool sym_set_tristate_value(struct symbol *sym, tristate val) bool sym_set_tristate_value(struct symbol *sym, tristate val)
@ -351,16 +370,16 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val)
if (sym->flags & SYMBOL_NEW) { if (sym->flags & SYMBOL_NEW) {
sym->flags &= ~SYMBOL_NEW; sym->flags &= ~SYMBOL_NEW;
sym->flags |= SYMBOL_CHANGED; sym_set_changed(sym);
} }
if (sym_is_choice_value(sym) && val == yes) { if (sym_is_choice_value(sym) && val == yes) {
struct property *prop = sym_get_choice_prop(sym); struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
S_VAL(prop->def->def) = sym; cs->user.val = sym;
prop->def->flags &= ~SYMBOL_NEW; cs->flags &= ~SYMBOL_NEW;
} }
S_TRI(sym->def) = val; sym->user.tri = val;
if (oldval != val) { if (oldval != val) {
sym_clear_all_valid(); sym_clear_all_valid();
if (sym == modules_sym) if (sym == modules_sym)
@ -404,12 +423,12 @@ bool sym_string_valid(struct symbol *sym, const char *str)
ch = *str++; ch = *str++;
if (ch == '-') if (ch == '-')
ch = *str++; ch = *str++;
if (!isdigit((int)ch)) if (!isdigit(ch))
return false; return false;
if (ch == '0' && *str != 0) if (ch == '0' && *str != 0)
return false; return false;
while ((ch = *str++)) { while ((ch = *str++)) {
if (!isdigit((int)ch)) if (!isdigit(ch))
return false; return false;
} }
return true; return true;
@ -418,21 +437,58 @@ bool sym_string_valid(struct symbol *sym, const char *str)
str += 2; str += 2;
ch = *str++; ch = *str++;
do { do {
if (!isxdigit((int)ch)) if (!isxdigit(ch))
return false; return false;
} while ((ch = *str++)); } while ((ch = *str++));
return true; return true;
case S_BOOLEAN: case S_BOOLEAN:
case S_TRISTATE: case S_TRISTATE:
switch (str[0]) { switch (str[0]) {
case 'y': case 'y': case 'Y':
case 'Y': case 'm': case 'M':
case 'n': case 'N':
return true;
}
return false;
default:
return false;
}
}
bool sym_string_within_range(struct symbol *sym, const char *str)
{
struct property *prop;
int val;
switch (sym->type) {
case S_STRING:
return sym_string_valid(sym, str);
case S_INT:
if (!sym_string_valid(sym, str))
return false;
prop = sym_get_range_prop(sym);
if (!prop)
return true;
val = strtol(str, NULL, 10);
return val >= strtol(prop->expr->left.sym->name, NULL, 10) &&
val <= strtol(prop->expr->right.sym->name, NULL, 10);
case S_HEX:
if (!sym_string_valid(sym, str))
return false;
prop = sym_get_range_prop(sym);
if (!prop)
return true;
val = strtol(str, NULL, 16);
return val >= strtol(prop->expr->left.sym->name, NULL, 16) &&
val <= strtol(prop->expr->right.sym->name, NULL, 16);
case S_BOOLEAN:
case S_TRISTATE:
switch (str[0]) {
case 'y': case 'Y':
return sym_tristate_within_range(sym, yes); return sym_tristate_within_range(sym, yes);
case 'm': case 'm': case 'M':
case 'M':
return sym_tristate_within_range(sym, mod); return sym_tristate_within_range(sym, mod);
case 'n': case 'n': case 'N':
case 'N':
return sym_tristate_within_range(sym, no); return sym_tristate_within_range(sym, no);
} }
return false; return false;
@ -451,14 +507,11 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
case S_BOOLEAN: case S_BOOLEAN:
case S_TRISTATE: case S_TRISTATE:
switch (newval[0]) { switch (newval[0]) {
case 'y': case 'y': case 'Y':
case 'Y':
return sym_set_tristate_value(sym, yes); return sym_set_tristate_value(sym, yes);
case 'm': case 'm': case 'M':
case 'M':
return sym_set_tristate_value(sym, mod); return sym_set_tristate_value(sym, mod);
case 'n': case 'n': case 'N':
case 'N':
return sym_set_tristate_value(sym, no); return sym_set_tristate_value(sym, no);
} }
return false; return false;
@ -466,23 +519,23 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
; ;
} }
if (!sym_string_valid(sym, newval)) if (!sym_string_within_range(sym, newval))
return false; return false;
if (sym->flags & SYMBOL_NEW) { if (sym->flags & SYMBOL_NEW) {
sym->flags &= ~SYMBOL_NEW; sym->flags &= ~SYMBOL_NEW;
sym->flags |= SYMBOL_CHANGED; sym_set_changed(sym);
} }
oldval = S_VAL(sym->def); oldval = sym->user.val;
size = strlen(newval) + 1; size = strlen(newval) + 1;
if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
size += 2; size += 2;
S_VAL(sym->def) = val = malloc(size); sym->user.val = val = malloc(size);
*val++ = '0'; *val++ = '0';
*val++ = 'x'; *val++ = 'x';
} else if (!oldval || strcmp(oldval, newval)) } else if (!oldval || strcmp(oldval, newval))
S_VAL(sym->def) = val = malloc(size); sym->user.val = val = malloc(size);
else else
return true; return true;
@ -513,20 +566,12 @@ const char *sym_get_string_value(struct symbol *sym)
default: default:
; ;
} }
return (const char *)S_VAL(sym->curr); return (const char *)sym->curr.val;
} }
bool sym_is_changable(struct symbol *sym) bool sym_is_changable(struct symbol *sym)
{ {
if (sym->visible == no) return sym->visible > sym->rev_dep.tri;
return false;
/* at least 'n' and 'y'/'m' is selectable */
if (sym_is_optional(sym))
return true;
/* no 'n', so 'y' and 'm' must be selectable */
if (sym_get_type(sym) == S_TRISTATE && sym->visible == yes)
return true;
return false;
} }
struct symbol *sym_lookup(const char *name, int isconst) struct symbol *sym_lookup(const char *name, int isconst)
@ -536,7 +581,6 @@ struct symbol *sym_lookup(const char *name, int isconst)
char *new_name; char *new_name;
int hash = 0; int hash = 0;
//printf("lookup: %s -> ", name);
if (name) { if (name) {
if (name[0] && !name[1]) { if (name[0] && !name[1]) {
switch (name[0]) { switch (name[0]) {
@ -552,12 +596,10 @@ struct symbol *sym_lookup(const char *name, int isconst)
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
if (!strcmp(symbol->name, name)) { if (!strcmp(symbol->name, name)) {
if ((isconst && symbol->flags & SYMBOL_CONST) || if ((isconst && symbol->flags & SYMBOL_CONST) ||
(!isconst && !(symbol->flags & SYMBOL_CONST))) { (!isconst && !(symbol->flags & SYMBOL_CONST)))
//printf("h:%p\n", symbol);
return symbol; return symbol;
} }
} }
}
new_name = strdup(name); new_name = strdup(name);
} else { } else {
new_name = NULL; new_name = NULL;
@ -575,7 +617,6 @@ struct symbol *sym_lookup(const char *name, int isconst)
symbol->next = symbol_hash[hash]; symbol->next = symbol_hash[hash];
symbol_hash[hash] = symbol; symbol_hash[hash] = symbol;
//printf("n:%p\n", symbol);
return symbol; return symbol;
} }
@ -608,6 +649,104 @@ struct symbol *sym_find(const char *name)
return symbol; return symbol;
} }
struct symbol *sym_check_deps(struct symbol *sym);
static struct symbol *sym_check_expr_deps(struct expr *e)
{
struct symbol *sym;
if (!e)
return NULL;
switch (e->type) {
case E_OR:
case E_AND:
sym = sym_check_expr_deps(e->left.expr);
if (sym)
return sym;
return sym_check_expr_deps(e->right.expr);
case E_NOT:
return sym_check_expr_deps(e->left.expr);
case E_EQUAL:
case E_UNEQUAL:
sym = sym_check_deps(e->left.sym);
if (sym)
return sym;
return sym_check_deps(e->right.sym);
case E_SYMBOL:
return sym_check_deps(e->left.sym);
default:
break;
}
printf("Oops! How to check %d?\n", e->type);
return NULL;
}
struct symbol *sym_check_deps(struct symbol *sym)
{
struct symbol *sym2;
struct property *prop;
if (sym->flags & SYMBOL_CHECK_DONE)
return NULL;
if (sym->flags & SYMBOL_CHECK) {
printf("Warning! Found recursive dependency: %s", sym->name);
return sym;
}
sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
if (sym2)
goto out;
for (prop = sym->prop; prop; prop = prop->next) {
if (prop->type == P_CHOICE)
continue;
sym2 = sym_check_expr_deps(prop->visible.expr);
if (sym2)
goto out;
if (prop->type != P_DEFAULT || sym_is_choice(sym))
continue;
sym2 = sym_check_expr_deps(prop->expr);
if (sym2)
goto out;
}
out:
if (sym2)
printf(" %s", sym->name);
sym->flags &= ~SYMBOL_CHECK;
return sym2;
}
struct property *prop_alloc(enum prop_type type, struct symbol *sym)
{
struct property *prop;
struct property **propp;
prop = malloc(sizeof(*prop));
memset(prop, 0, sizeof(*prop));
prop->type = type;
prop->sym = sym;
prop->file = current_file;
prop->lineno = zconf_lineno();
/* append property to the prop list of symbol */
if (sym) {
for (propp = &sym->prop; *propp; propp = &(*propp)->next)
;
*propp = prop;
}
return prop;
}
struct symbol *prop_get_symbol(struct property *prop)
{
if (prop->expr && (prop->expr->type == E_SYMBOL ||
prop->expr->type == E_CHOICE))
return prop->expr->left.sym;
return NULL;
}
const char *prop_get_type_name(enum prop_type type) const char *prop_get_type_name(enum prop_type type)
{ {
switch (type) { switch (type) {
@ -617,13 +756,16 @@ const char *prop_get_type_name(enum prop_type type)
return "comment"; return "comment";
case P_MENU: case P_MENU:
return "menu"; return "menu";
case P_ROOTMENU:
return "rootmenu";
case P_DEFAULT: case P_DEFAULT:
return "default"; return "default";
case P_CHOICE: case P_CHOICE:
return "choice"; return "choice";
default: case P_SELECT:
return "unknown"; return "select";
case P_RANGE:
return "range";
case P_UNKNOWN:
break;
} }
return "unknown";
} }

View File

@ -7,6 +7,7 @@
* Released under the terms of the GNU GPL v2.0. * Released under the terms of the GNU GPL v2.0.
*/ */
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -14,7 +15,6 @@
#define LKC_DIRECT_LINK #define LKC_DIRECT_LINK
#include "lkc.h" #include "lkc.h"
#include "zconf.tab.h"
#define START_STRSIZE 16 #define START_STRSIZE 16
@ -96,6 +96,7 @@ n [A-Za-z0-9_]
"endchoice" BEGIN(PARAM); return T_ENDCHOICE; "endchoice" BEGIN(PARAM); return T_ENDCHOICE;
"comment" BEGIN(PARAM); return T_COMMENT; "comment" BEGIN(PARAM); return T_COMMENT;
"config" BEGIN(PARAM); return T_CONFIG; "config" BEGIN(PARAM); return T_CONFIG;
"menuconfig" BEGIN(PARAM); return T_MENUCONFIG;
"help" BEGIN(PARAM); return T_HELP; "help" BEGIN(PARAM); return T_HELP;
"if" BEGIN(PARAM); return T_IF; "if" BEGIN(PARAM); return T_IF;
"endif" BEGIN(PARAM); return T_ENDIF; "endif" BEGIN(PARAM); return T_ENDIF;
@ -105,11 +106,17 @@ n [A-Za-z0-9_]
"default" BEGIN(PARAM); return T_DEFAULT; "default" BEGIN(PARAM); return T_DEFAULT;
"prompt" BEGIN(PARAM); return T_PROMPT; "prompt" BEGIN(PARAM); return T_PROMPT;
"tristate" BEGIN(PARAM); return T_TRISTATE; "tristate" BEGIN(PARAM); return T_TRISTATE;
"def_tristate" BEGIN(PARAM); return T_DEF_TRISTATE;
"bool" BEGIN(PARAM); return T_BOOLEAN; "bool" BEGIN(PARAM); return T_BOOLEAN;
"boolean" BEGIN(PARAM); return T_BOOLEAN; "boolean" BEGIN(PARAM); return T_BOOLEAN;
"def_bool" BEGIN(PARAM); return T_DEF_BOOLEAN;
"def_boolean" BEGIN(PARAM); return T_DEF_BOOLEAN;
"int" BEGIN(PARAM); return T_INT; "int" BEGIN(PARAM); return T_INT;
"hex" BEGIN(PARAM); return T_HEX; "hex" BEGIN(PARAM); return T_HEX;
"string" BEGIN(PARAM); return T_STRING; "string" BEGIN(PARAM); return T_STRING;
"select" BEGIN(PARAM); return T_SELECT;
"enable" BEGIN(PARAM); return T_SELECT;
"range" BEGIN(PARAM); return T_RANGE;
{n}+ { {n}+ {
alloc_string(yytext, yyleng); alloc_string(yytext, yyleng);
zconflval.string = text; zconflval.string = text;
@ -141,6 +148,8 @@ n [A-Za-z0-9_]
zconflval.string = text; zconflval.string = text;
return T_WORD; return T_WORD;
} }
#.* /* comment */
\\\n current_file->lineno++;
. .
<<EOF>> { <<EOF>> {
BEGIN(INITIAL); BEGIN(INITIAL);
@ -151,29 +160,30 @@ n [A-Za-z0-9_]
[^'"\\\n]+/\n { [^'"\\\n]+/\n {
append_string(yytext, yyleng); append_string(yytext, yyleng);
zconflval.string = text; zconflval.string = text;
return T_STRING; return T_WORD_QUOTE;
} }
[^'"\\\n]+ { [^'"\\\n]+ {
append_string(yytext, yyleng); append_string(yytext, yyleng);
} }
\\.?/\n { \\.?/\n {
append_string(yytext+1, yyleng); append_string(yytext + 1, yyleng - 1);
zconflval.string = text; zconflval.string = text;
return T_STRING; return T_WORD_QUOTE;
} }
\\.? { \\.? {
append_string(yytext+1, yyleng); append_string(yytext + 1, yyleng - 1);
} }
\'|\" { \'|\" {
if (str == yytext[0]) { if (str == yytext[0]) {
BEGIN(PARAM); BEGIN(PARAM);
zconflval.string = text; zconflval.string = text;
return T_STRING; return T_WORD_QUOTE;
} else } else
append_string(yytext, 1); append_string(yytext, 1);
} }
\n { \n {
printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
current_file->lineno++;
BEGIN(INITIAL); BEGIN(INITIAL);
return T_EOL; return T_EOL;
} }
@ -204,9 +214,8 @@ n [A-Za-z0-9_]
} }
append_string(" ", ts); append_string(" ", ts);
} }
} }
\n/[^ \t\n] { [ \t]*\n/[^ \t\n] {
current_file->lineno++; current_file->lineno++;
zconf_endhelp(); zconf_endhelp();
return T_HELPTEXT; return T_HELPTEXT;
@ -249,9 +258,34 @@ static void zconf_endhelp(void)
BEGIN(INITIAL); BEGIN(INITIAL);
} }
/*
* Try to open specified file with following names:
* ./name
* $(srctree)/name
* The latter is used when srctree is separate from objtree
* when compiling the kernel.
* Return NULL if file is not found.
*/
FILE *zconf_fopen(const char *name)
{
char *env, fullname[PATH_MAX+1];
FILE *f;
f = fopen(name, "r");
if (!f && name[0] != '/') {
env = getenv(SRCTREE);
if (env) {
sprintf(fullname, "%s/%s", env, name);
f = fopen(fullname, "r");
}
}
return f;
}
void zconf_initscan(const char *name) void zconf_initscan(const char *name)
{ {
yyin = fopen(name, "r"); yyin = zconf_fopen(name);
if (!yyin) { if (!yyin) {
printf("can't find file %s\n", name); printf("can't find file %s\n", name);
exit(1); exit(1);
@ -272,7 +306,7 @@ void zconf_nextfile(const char *name)
memset(buf, 0, sizeof(*buf)); memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER; current_buf->state = YY_CURRENT_BUFFER;
yyin = fopen(name, "r"); yyin = zconf_fopen(name);
if (!yyin) { if (!yyin) {
printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name); printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
exit(1); exit(1);
@ -318,7 +352,7 @@ static struct buffer *zconf_endfile(void)
int zconf_lineno(void) int zconf_lineno(void)
{ {
if (current_buf) if (current_buf)
return current_file->lineno; return current_file->lineno - 1;
else else
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@ struct symbol *symbol_hash[257];
#define YYERROR_VERBOSE #define YYERROR_VERBOSE
%} %}
%expect 36 %expect 40
%union %union
{ {
@ -46,6 +46,7 @@ struct symbol *symbol_hash[257];
%token T_ENDCHOICE %token T_ENDCHOICE
%token T_COMMENT %token T_COMMENT
%token T_CONFIG %token T_CONFIG
%token T_MENUCONFIG
%token T_HELP %token T_HELP
%token <string> T_HELPTEXT %token <string> T_HELPTEXT
%token T_IF %token T_IF
@ -56,17 +57,22 @@ struct symbol *symbol_hash[257];
%token T_PROMPT %token T_PROMPT
%token T_DEFAULT %token T_DEFAULT
%token T_TRISTATE %token T_TRISTATE
%token T_DEF_TRISTATE
%token T_BOOLEAN %token T_BOOLEAN
%token T_DEF_BOOLEAN
%token T_STRING
%token T_INT %token T_INT
%token T_HEX %token T_HEX
%token <string> T_WORD %token <string> T_WORD
%token <string> T_STRING %token <string> T_WORD_QUOTE
%token T_UNEQUAL %token T_UNEQUAL
%token T_EOF %token T_EOF
%token T_EOL %token T_EOL
%token T_CLOSE_PAREN %token T_CLOSE_PAREN
%token T_OPEN_PAREN %token T_OPEN_PAREN
%token T_ON %token T_ON
%token T_SELECT
%token T_RANGE
%left T_OR %left T_OR
%left T_AND %left T_AND
@ -103,14 +109,15 @@ common_block:
if_stmt if_stmt
| comment_stmt | comment_stmt
| config_stmt | config_stmt
| menuconfig_stmt
| source_stmt | source_stmt
| nl_or_eof | nl_or_eof
; ;
/* config entry */ /* config/menuconfig entry */
config_entry_start: T_CONFIG T_WORD config_entry_start: T_CONFIG T_WORD T_EOL
{ {
struct symbol *sym = sym_lookup($2, 0); struct symbol *sym = sym_lookup($2, 0);
sym->flags |= SYMBOL_OPTIONAL; sym->flags |= SYMBOL_OPTIONAL;
@ -118,74 +125,118 @@ config_entry_start: T_CONFIG T_WORD
printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
}; };
config_stmt: config_entry_start T_EOL config_option_list config_stmt: config_entry_start config_option_list
{ {
menu_end_entry(); menu_end_entry();
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
}; };
menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
{
struct symbol *sym = sym_lookup($2, 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
};
menuconfig_stmt: menuconfig_entry_start config_option_list
{
if (current_entry->prompt)
current_entry->prompt->type = P_MENU;
else
zconfprint("warning: menuconfig statement without prompt");
menu_end_entry();
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
};
config_option_list: config_option_list:
/* empty */ /* empty */
| config_option_list config_option T_EOL | config_option_list config_option
| config_option_list depends T_EOL | config_option_list depends
| config_option_list help | config_option_list help
| config_option_list T_EOL | config_option_list T_EOL
{ }; ;
config_option: T_TRISTATE prompt_stmt_opt config_option: T_TRISTATE prompt_stmt_opt T_EOL
{ {
menu_set_type(S_TRISTATE); menu_set_type(S_TRISTATE);
printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
}; };
config_option: T_BOOLEAN prompt_stmt_opt config_option: T_DEF_TRISTATE expr if_expr T_EOL
{
menu_add_expr(P_DEFAULT, $2, $3);
menu_set_type(S_TRISTATE);
printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
};
config_option: T_BOOLEAN prompt_stmt_opt T_EOL
{ {
menu_set_type(S_BOOLEAN); menu_set_type(S_BOOLEAN);
printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
}; };
config_option: T_INT prompt_stmt_opt config_option: T_DEF_BOOLEAN expr if_expr T_EOL
{
menu_add_expr(P_DEFAULT, $2, $3);
menu_set_type(S_BOOLEAN);
printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
};
config_option: T_INT prompt_stmt_opt T_EOL
{ {
menu_set_type(S_INT); menu_set_type(S_INT);
printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno());
}; };
config_option: T_HEX prompt_stmt_opt config_option: T_HEX prompt_stmt_opt T_EOL
{ {
menu_set_type(S_HEX); menu_set_type(S_HEX);
printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno());
}; };
config_option: T_STRING prompt_stmt_opt config_option: T_STRING prompt_stmt_opt T_EOL
{ {
menu_set_type(S_STRING); menu_set_type(S_STRING);
printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno());
}; };
config_option: T_PROMPT prompt if_expr config_option: T_PROMPT prompt if_expr T_EOL
{ {
menu_add_prop(P_PROMPT, $2, NULL, $3); menu_add_prompt(P_PROMPT, $2, $3);
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
}; };
config_option: T_DEFAULT symbol if_expr config_option: T_DEFAULT expr if_expr T_EOL
{ {
menu_add_prop(P_DEFAULT, NULL, $2, $3); menu_add_expr(P_DEFAULT, $2, $3);
printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
}; };
config_option: T_SELECT T_WORD if_expr T_EOL
{
menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
};
config_option: T_RANGE symbol symbol if_expr T_EOL
{
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
};
/* choice entry */ /* choice entry */
choice: T_CHOICE choice: T_CHOICE T_EOL
{ {
struct symbol *sym = sym_lookup(NULL, 0); struct symbol *sym = sym_lookup(NULL, 0);
sym->flags |= SYMBOL_CHOICE; sym->flags |= SYMBOL_CHOICE;
menu_add_entry(sym); menu_add_entry(sym);
menu_add_prop(P_CHOICE, NULL, NULL, NULL); menu_add_expr(P_CHOICE, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
}; };
choice_entry: choice T_EOL choice_option_list choice_entry: choice choice_option_list
{ {
menu_end_entry(); menu_end_entry();
menu_add_menu(); menu_add_menu();
@ -200,7 +251,7 @@ choice_end: end
}; };
choice_stmt: choice_stmt:
choice_entry choice_block choice_end T_EOL choice_entry choice_block choice_end
| choice_entry choice_block | choice_entry choice_block
{ {
printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno); printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
@ -209,28 +260,39 @@ choice_stmt:
choice_option_list: choice_option_list:
/* empty */ /* empty */
| choice_option_list choice_option T_EOL | choice_option_list choice_option
| choice_option_list depends T_EOL | choice_option_list depends
| choice_option_list help | choice_option_list help
| choice_option_list T_EOL | choice_option_list T_EOL
; ;
choice_option: T_PROMPT prompt if_expr choice_option: T_PROMPT prompt if_expr T_EOL
{ {
menu_add_prop(P_PROMPT, $2, NULL, $3); menu_add_prompt(P_PROMPT, $2, $3);
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
}; };
choice_option: T_OPTIONAL choice_option: T_TRISTATE prompt_stmt_opt T_EOL
{
menu_set_type(S_TRISTATE);
printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
};
choice_option: T_BOOLEAN prompt_stmt_opt T_EOL
{
menu_set_type(S_BOOLEAN);
printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
};
choice_option: T_OPTIONAL T_EOL
{ {
current_entry->sym->flags |= SYMBOL_OPTIONAL; current_entry->sym->flags |= SYMBOL_OPTIONAL;
printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
}; };
choice_option: T_DEFAULT symbol choice_option: T_DEFAULT T_WORD if_expr T_EOL
{ {
menu_add_prop(P_DEFAULT, NULL, $2, NULL); menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
//current_choice->prop->def = $2;
printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
}; };
@ -241,11 +303,10 @@ choice_block:
/* if entry */ /* if entry */
if: T_IF expr if: T_IF expr T_EOL
{ {
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
menu_add_entry(NULL); menu_add_entry(NULL);
//current_entry->prompt = menu_add_prop(T_IF, NULL, NULL, $2);
menu_add_dep($2); menu_add_dep($2);
menu_end_entry(); menu_end_entry();
menu_add_menu(); menu_add_menu();
@ -260,8 +321,8 @@ if_end: end
}; };
if_stmt: if_stmt:
if T_EOL if_block if_end T_EOL if if_block if_end
| if T_EOL if_block | if if_block
{ {
printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno); printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
zconfnerrs++; zconfnerrs++;
@ -276,14 +337,14 @@ if_block:
/* menu entry */ /* menu entry */
menu: T_MENU prompt menu: T_MENU prompt T_EOL
{ {
menu_add_entry(NULL); menu_add_entry(NULL);
menu_add_prop(P_MENU, $2, NULL, NULL); menu_add_prop(P_MENU, $2, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
}; };
menu_entry: menu T_EOL depends_list menu_entry: menu depends_list
{ {
menu_end_entry(); menu_end_entry();
menu_add_menu(); menu_add_menu();
@ -298,7 +359,7 @@ menu_end: end
}; };
menu_stmt: menu_stmt:
menu_entry menu_block menu_end T_EOL menu_entry menu_block menu_end
| menu_entry menu_block | menu_entry menu_block
{ {
printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno); printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
@ -313,27 +374,27 @@ menu_block:
| menu_block error T_EOL { zconfprint("invalid menu option"); yyerrok; } | menu_block error T_EOL { zconfprint("invalid menu option"); yyerrok; }
; ;
source: T_SOURCE prompt source: T_SOURCE prompt T_EOL
{ {
$$ = $2; $$ = $2;
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
}; };
source_stmt: source T_EOL source_stmt: source
{ {
zconf_nextfile($1); zconf_nextfile($1);
}; };
/* comment entry */ /* comment entry */
comment: T_COMMENT prompt comment: T_COMMENT prompt T_EOL
{ {
menu_add_entry(NULL); menu_add_entry(NULL);
menu_add_prop(P_COMMENT, $2, NULL, NULL); menu_add_prop(P_COMMENT, $2, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
}; };
comment_stmt: comment T_EOL depends_list comment_stmt: comment depends_list
{ {
menu_end_entry(); menu_end_entry();
}; };
@ -354,21 +415,21 @@ help: help_start T_HELPTEXT
/* depends option */ /* depends option */
depends_list: /* empty */ depends_list: /* empty */
| depends_list depends T_EOL | depends_list depends
| depends_list T_EOL | depends_list T_EOL
{ }; ;
depends: T_DEPENDS T_ON expr depends: T_DEPENDS T_ON expr T_EOL
{ {
menu_add_dep($3); menu_add_dep($3);
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
} }
| T_DEPENDS expr | T_DEPENDS expr T_EOL
{ {
menu_add_dep($2); menu_add_dep($2);
printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
} }
| T_REQUIRES expr | T_REQUIRES expr T_EOL
{ {
menu_add_dep($2); menu_add_dep($2);
printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno()); printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
@ -378,22 +439,18 @@ depends: T_DEPENDS T_ON expr
prompt_stmt_opt: prompt_stmt_opt:
/* empty */ /* empty */
| prompt | prompt if_expr
{ {
menu_add_prop(P_PROMPT, $1, NULL, NULL); menu_add_prop(P_PROMPT, $1, NULL, $2);
}
| prompt T_IF expr
{
menu_add_prop(P_PROMPT, $1, NULL, $3);
}; };
prompt: T_WORD prompt: T_WORD
| T_STRING | T_WORD_QUOTE
; ;
end: T_ENDMENU { $$ = T_ENDMENU; } end: T_ENDMENU nl_or_eof { $$ = T_ENDMENU; }
| T_ENDCHOICE { $$ = T_ENDCHOICE; } | T_ENDCHOICE nl_or_eof { $$ = T_ENDCHOICE; }
| T_ENDIF { $$ = T_ENDIF; } | T_ENDIF nl_or_eof { $$ = T_ENDIF; }
; ;
nl_or_eof: nl_or_eof:
@ -413,26 +470,34 @@ expr: symbol { $$ = expr_alloc_symbol($1); }
; ;
symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
| T_STRING { $$ = sym_lookup($1, 1); free($1); } | T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); }
; ;
%% %%
void conf_parse(const char *name) void conf_parse(const char *name)
{ {
struct symbol *sym;
int i;
zconf_initscan(name); zconf_initscan(name);
sym_init(); sym_init();
menu_init(); menu_init();
rootmenu.prompt = menu_add_prop(P_MENU, "BusyBox Configuration", NULL, NULL); modules_sym = sym_lookup("MODULES", 0);
rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL);
//zconfdebug = 1; //zconfdebug = 1;
zconfparse(); zconfparse();
if (zconfnerrs) if (zconfnerrs)
exit(1); exit(1);
menu_finalize(&rootmenu); menu_finalize(&rootmenu);
for_all_symbols(i, sym) {
modules_sym = sym_lookup("MODULES", 0); if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym))
printf("\n");
else
sym->flags |= SYMBOL_CHECK_DONE;
}
sym_change_count = 1; sym_change_count = 1;
} }
@ -470,7 +535,7 @@ static void zconfprint(const char *err, ...)
{ {
va_list ap; va_list ap;
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1);
va_start(ap, err); va_start(ap, err);
vfprintf(stderr, err, ap); vfprintf(stderr, err, ap);
va_end(ap); va_end(ap);
@ -479,7 +544,7 @@ static void zconfprint(const char *err, ...)
static void zconferror(const char *err) static void zconferror(const char *err)
{ {
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno(), err); fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
} }
void print_quoted_string(FILE *out, const char *str) void print_quoted_string(FILE *out, const char *str)
@ -504,8 +569,6 @@ void print_symbol(FILE *out, struct menu *menu)
struct symbol *sym = menu->sym; struct symbol *sym = menu->sym;
struct property *prop; struct property *prop;
//sym->flags |= SYMBOL_PRINTED;
if (sym_is_choice(sym)) if (sym_is_choice(sym))
fprintf(out, "choice\n"); fprintf(out, "choice\n");
else else
@ -530,13 +593,6 @@ void print_symbol(FILE *out, struct menu *menu)
fputs(" ???\n", out); fputs(" ???\n", out);
break; break;
} }
#if 0
if (!expr_is_yes(sym->dep)) {
fputs(" depends ", out);
expr_fprint(sym->dep, out);
fputc('\n', out);
}
#endif
for (prop = sym->prop; prop; prop = prop->next) { for (prop = sym->prop; prop; prop = prop->next) {
if (prop->menu != menu) if (prop->menu != menu)
continue; continue;
@ -544,25 +600,18 @@ void print_symbol(FILE *out, struct menu *menu)
case P_PROMPT: case P_PROMPT:
fputs(" prompt ", out); fputs(" prompt ", out);
print_quoted_string(out, prop->text); print_quoted_string(out, prop->text);
if (prop->def) { if (!expr_is_yes(prop->visible.expr)) {
fputc(' ', out);
if (prop->def->flags & SYMBOL_CONST)
print_quoted_string(out, prop->def->name);
else
fputs(prop->def->name, out);
}
if (!expr_is_yes(E_EXPR(prop->visible))) {
fputs(" if ", out); fputs(" if ", out);
expr_fprint(E_EXPR(prop->visible), out); expr_fprint(prop->visible.expr, out);
} }
fputc('\n', out); fputc('\n', out);
break; break;
case P_DEFAULT: case P_DEFAULT:
fputs( " default ", out); fputs( " default ", out);
print_quoted_string(out, prop->def->name); expr_fprint(prop->expr, out);
if (!expr_is_yes(E_EXPR(prop->visible))) { if (!expr_is_yes(prop->visible.expr)) {
fputs(" if ", out); fputs(" if ", out);
expr_fprint(E_EXPR(prop->visible), out); expr_fprint(prop->visible.expr, out);
} }
fputc('\n', out); fputc('\n', out);
break; break;
@ -585,7 +634,6 @@ void print_symbol(FILE *out, struct menu *menu)
void zconfdump(FILE *out) void zconfdump(FILE *out)
{ {
//struct file *file;
struct property *prop; struct property *prop;
struct symbol *sym; struct symbol *sym;
struct menu *menu; struct menu *menu;
@ -596,11 +644,6 @@ void zconfdump(FILE *out)
print_symbol(out, menu); print_symbol(out, menu);
else if ((prop = menu->prompt)) { else if ((prop = menu->prompt)) {
switch (prop->type) { switch (prop->type) {
//case T_MAINMENU:
// fputs("\nmainmenu ", out);
// print_quoted_string(out, prop->text);
// fputs("\n", out);
// break;
case P_COMMENT: case P_COMMENT:
fputs("\ncomment ", out); fputs("\ncomment ", out);
print_quoted_string(out, prop->text); print_quoted_string(out, prop->text);
@ -611,19 +654,12 @@ void zconfdump(FILE *out)
print_quoted_string(out, prop->text); print_quoted_string(out, prop->text);
fputs("\n", out); fputs("\n", out);
break; break;
//case T_SOURCE:
// fputs("\nsource ", out);
// print_quoted_string(out, prop->text);
// fputs("\n", out);
// break;
//case T_IF:
// fputs("\nif\n", out);
default: default:
; ;
} }
if (!expr_is_yes(E_EXPR(prop->visible))) { if (!expr_is_yes(prop->visible.expr)) {
fputs(" depends ", out); fputs(" depends ", out);
expr_fprint(E_EXPR(prop->visible), out); expr_fprint(prop->visible.expr, out);
fputc('\n', out); fputc('\n', out);
} }
fputs("\n", out); fputs("\n", out);

View File

@ -7,7 +7,7 @@ menu "Another Bourne-like Shell"
choice choice
prompt "Choose your default shell" prompt "Choose your default shell"
default "none" default CONFIG_FEATURE_SH_IS_NONE
help help
Choose a shell. The ash shell is the most bash compatible Choose a shell. The ash shell is the most bash compatible
and full featured. and full featured.

View File

@ -13,7 +13,7 @@ menu "General Configuration"
choice choice
prompt "Buffer allocation policy" prompt "Buffer allocation policy"
default "Allocate with Malloc" default CONFIG_FEATURE_BUFFERS_USE_MALLOC
help help
There are 3 ways BusyBox can handle buffer allocations: There are 3 ways BusyBox can handle buffer allocations:
- Use malloc. This costs code size for the call to xmalloc. - Use malloc. This costs code size for the call to xmalloc.