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";
#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)
{
char *p = str;
int l;
while ((isspace((int)*p)))
while ((isspace(*p)))
p++;
l = strlen(p);
if (p != str)
@ -86,10 +48,20 @@ static void strip(char *str)
if (!l)
return;
p = str + l - 1;
while ((isspace((int)*p)))
while ((isspace(*p)))
*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)
{
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[1] = 0;
if (!sym_is_changable(sym)) {
printf("%s\n", def);
line[0] = '\n';
line[1] = 0;
return;
}
switch (input_mode) {
case ask_new:
case ask_silent:
@ -108,12 +87,7 @@ static void conf_askvalue(struct symbol *sym, const char *def)
printf("%s\n", def);
return;
}
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);
}
check_stdin();
case ask_all:
fflush(stdout);
fgets(line, 128, stdin);
@ -294,9 +268,8 @@ help:
static int conf_choice(struct menu *menu)
{
struct symbol *sym, *def_sym;
struct menu *cmenu, *def_menu;
const char *help;
int type, len;
struct menu *child;
int type;
bool is_new;
sym = menu->sym;
@ -314,72 +287,111 @@ static int conf_choice(struct menu *menu)
break;
}
} else {
sym->def = sym->curr;
if (S_TRI(sym->curr) == mod) {
switch (sym_get_tristate_value(sym)) {
case no:
return 1;
case mod:
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
return 0;
case yes:
break;
}
}
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_menu = NULL;
for (cmenu = menu->list; cmenu; cmenu = cmenu->next) {
if (!menu_is_visible(cmenu))
cnt = def = 0;
line[0] = '0';
line[1] = 0;
for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child))
continue;
printo(menu_get_prompt(cmenu));
if (cmenu->sym == def_sym)
def_menu = cmenu;
}
printo(NULL);
if (def_menu)
printf("[%s] ", menu_get_prompt(def_menu));
else {
if (!child->sym) {
printf("%*c %s\n", indent, '*', menu_get_prompt(child));
continue;
}
cnt++;
if (child->sym == def_sym) {
def = cnt;
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");
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) {
case ask_new:
case ask_silent:
if (!is_new) {
cnt = def;
printf("%d\n", cnt);
break;
}
check_stdin();
case ask_all:
conf_askvalue(sym, menu_get_prompt(def_menu));
fflush(stdout);
fgets(line, 128, stdin);
strip(line);
if (line[0] == '?') {
printf("\n%s\n", menu->sym->help ?
menu->sym->help : nohelp_text);
continue;
}
if (!line[0])
cnt = def;
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;
default:
line[0] = 0;
printf("\n");
}
if (line[0] == '?' && !line[1]) {
help = nohelp_text;
if (menu->sym->help)
help = menu->sym->help;
printf("\n%s\n", help);
conf_childs:
for (child = menu->list; child; child = child->next) {
if (!child->sym || !menu_is_visible(child))
continue;
if (!--cnt)
break;
}
if (!child)
continue;
if (line[strlen(line) - 1] == '?') {
printf("\n%s\n", child->sym->help ?
child->sym->help : nohelp_text);
continue;
}
if (line[0]) {
len = strlen(line);
line[len] = 0;
def_menu = NULL;
for (cmenu = menu->list; cmenu; cmenu = cmenu->next) {
if (!cmenu->sym || !menu_is_visible(cmenu))
continue;
if (!strncasecmp(line, menu_get_prompt(cmenu), len)) {
def_menu = cmenu;
break;
}
}
}
if (def_menu) {
sym_set_choice_value(sym, def_menu->sym);
if (def_menu->list) {
indent += 2;
conf(def_menu->list);
indent -= 2;
}
return 1;
sym_set_choice_value(sym, child->sym);
if (child->list) {
indent += 2;
conf(child->list);
indent -= 2;
}
return 1;
}
}
@ -420,7 +432,7 @@ static void conf(struct menu *menu)
if (sym_is_choice(sym)) {
conf_choice(menu);
if (S_TRI(sym->curr) != mod)
if (sym->curr.tri != mod)
return;
goto conf_childs;
}
@ -454,29 +466,17 @@ static void check_conf(struct menu *menu)
return;
sym = menu->sym;
if (!sym)
goto conf_childs;
if (sym_is_choice(sym)) {
if (!sym_has_value(sym)) {
if (sym) {
if (sym_is_changable(sym) && !sym_has_value(sym)) {
if (!conf_cnt++)
printf("*\n* Restart config...\n*\n");
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
}
if (sym_get_tristate_value(sym) != mod)
if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod)
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)
check_conf(child);
}
@ -536,8 +536,8 @@ int main(int ac, char **av)
printf("***\n"
"*** You have not yet configured BusyBox!\n"
"***\n"
"*** Please run some configurator (e.g. \"make oldconfig\"\n"
"*** or \"make menuconfig\").\n"
"*** Please run some configurator (e.g. \"make config\" or\n"
"*** \"make oldconfig\" or \"make menuconfig\").\n"
"***\n");
exit(1);
}

View File

@ -1,11 +1,9 @@
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* 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 <stdio.h>
#include <stdlib.h>
@ -38,7 +36,7 @@ static char *conf_expand_value(const char *in)
strncat(res_value, in, src - in);
src++;
dst = name;
while (isalnum((int)*src) || *src == '_')
while (isalnum(*src) || *src == '_')
*dst++ = *src++;
*dst = 0;
sym = sym_lookup(name, 0);
@ -53,7 +51,18 @@ static char *conf_expand_value(const char *in)
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)
@ -68,12 +77,12 @@ int conf_read(const char *name)
int i;
if (name) {
in = fopen(name, "r");
in = zconf_fopen(name);
} else {
const char **names = conf_confnames;
while ((name = *names++)) {
name = conf_expand_value(name);
in = fopen(name, "r");
in = zconf_fopen(name);
if (in) {
printf("#\n"
"# using defaults found in %s\n"
@ -93,44 +102,43 @@ int conf_read(const char *name)
case S_INT:
case S_HEX:
case S_STRING:
if (S_VAL(sym->def))
free(S_VAL(sym->def));
if (sym->user.val)
free(sym->user.val);
default:
S_VAL(sym->def) = NULL;
S_TRI(sym->def) = no;
;
sym->user.val = NULL;
sym->user.tri = no;
}
}
while (fgets(line, sizeof(line), in)) {
lineno++;
sym = NULL;
switch (line[0]) {
case '\n':
break;
case ' ':
break;
case '#':
p = strchr(line, ' ');
if (!p)
if (line[1]!=' ')
continue;
*p++ = 0;
p = strchr(p, ' ');
p = strchr(line + 2, ' ');
if (!p)
continue;
*p++ = 0;
if (strncmp(p, "is not set", 10))
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) {
case S_BOOLEAN:
case S_TRISTATE:
sym->def = symbol_no.curr;
sym->user.tri = no;
sym->flags &= ~SYMBOL_NEW;
break;
default:
;
}
break;
case 'A' ... 'Z':
p = strchr(line, '=');
if (!p)
@ -145,24 +153,24 @@ int conf_read(const char *name)
break;
}
switch (sym->type) {
case S_TRISTATE:
case S_TRISTATE:
if (p[0] == 'm') {
S_TRI(sym->def) = mod;
sym->user.tri = mod;
sym->flags &= ~SYMBOL_NEW;
break;
}
case S_BOOLEAN:
if (p[0] == 'y') {
S_TRI(sym->def) = yes;
sym->user.tri = yes;
sym->flags &= ~SYMBOL_NEW;
break;
}
if (p[0] == 'n') {
S_TRI(sym->def) = no;
sym->user.tri = no;
sym->flags &= ~SYMBOL_NEW;
break;
}
break;
break;
case S_STRING:
if (*p++ != '"')
break;
@ -173,48 +181,71 @@ int conf_read(const char *name)
}
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_HEX:
if (sym_string_valid(sym, p)) {
S_VAL(sym->def) = strdup(p);
sym->user.val = strdup(p);
sym->flags &= ~SYMBOL_NEW;
} else
fprintf(stderr, "%s:%d:symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
} else {
fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
exit(1);
}
break;
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;
case yes:
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;
case '\n':
break;
default:
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);
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))
continue;
prop = sym_get_choice_prop(sym);
for (e = prop->dep; e; e = e->left.expr)
sym->flags |= e->right.sym->flags & SYMBOL_NEW;
sym->flags &= ~SYMBOL_NEW;
for (e = prop->expr; e; e = e->left.expr)
if (e->right.sym->visible != no)
sym->flags |= e->right.sym->flags & SYMBOL_NEW;
}
sym_change_count = 1;
@ -227,29 +258,50 @@ int conf_write(const char *name)
FILE *out, *out_h;
struct symbol *sym;
struct menu *menu;
char oldname[128];
const char *basename;
char dirname[128], tmpname[128], newname[128];
int type, l;
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)
return 1;
out_h = fopen(".tmpconfig.h", "w");
if (!out_h)
return 1;
out_h = NULL;
if (!name) {
out_h = fopen(".tmpconfig.h", "w");
if (!out_h)
return 1;
}
fprintf(out, "#\n"
"# Automatically generated make config: don't edit\n"
"#\n");
fprintf(out_h, "/*\n"
" * Automatically generated header file: don't edit\n"
" */\n\n"
"#define AUTOCONF_INCLUDED\n\n"
"/* Version Number */\n"
"#define BB_VER \"%s\"\n"
"#define BB_BT \"%s\"\n\n",
getenv("VERSION"),
getenv("BUILDTIME")
);
if (out_h)
fprintf(out_h, "/*\n"
" * Automatically generated header file: don't edit\n"
" */\n\n"
"#define AUTOCONF_INCLUDED\n\n"
"/* Version Number */\n"
"#define BB_VER \"%s\"\n"
"#define BB_BT \"%s\"\n\n",
getenv("VERSION"),
getenv("BUILDTIME"));
if (!sym_change_count)
sym_clear_all_valid();
@ -265,10 +317,11 @@ int conf_write(const char *name)
"#\n"
"# %s\n"
"#\n", str);
fprintf(out_h, "\n"
"/*\n"
" * %s\n"
" */\n", str);
if (out_h)
fprintf(out_h, "\n"
"/*\n"
" * %s\n"
" */\n", str);
} else if (!(sym->flags & SYMBOL_CHOICE)) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_WRITE))
@ -277,7 +330,7 @@ int conf_write(const char *name)
type = sym->type;
if (type == S_TRISTATE) {
sym_calc_value(modules_sym);
if (S_TRI(modules_sym->curr) == no)
if (modules_sym->curr.tri == no)
type = S_BOOLEAN;
}
switch (type) {
@ -286,17 +339,20 @@ int conf_write(const char *name)
switch (sym_get_tristate_value(sym)) {
case no:
fprintf(out, "# %s is not set\n", sym->name);
fprintf(out_h, "#undef %s\n", sym->name);
if (out_h)
fprintf(out_h, "#undef %s\n", sym->name);
break;
case mod:
#if 0
case mod:
fprintf(out, "%s=m\n", sym->name);
fprintf(out_h, "#define __%s__MODULE 1\n", sym->name);
#endif
if (out_h)
fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
break;
#endif
case yes:
fprintf(out, "%s=y\n", sym->name);
fprintf(out_h, "#define %s 1\n", sym->name);
if (out_h)
fprintf(out_h, "#define %s 1\n", sym->name);
break;
}
break;
@ -304,34 +360,40 @@ int conf_write(const char *name)
// fix me
str = sym_get_string_value(sym);
fprintf(out, "%s=\"", sym->name);
fprintf(out_h, "#define %s \"", sym->name);
if (out_h)
fprintf(out_h, "#define %s \"", sym->name);
do {
l = strcspn(str, "\"\\");
if (l) {
fwrite(str, l, 1, out);
fwrite(str, l, 1, out_h);
if (out_h)
fwrite(str, l, 1, out_h);
}
str += l;
while (*str == '\\' || *str == '"') {
fprintf(out, "\\%c", *str);
fprintf(out_h, "\\%c", *str);
if (out_h)
fprintf(out_h, "\\%c", *str);
str++;
}
} while (*str);
fputs("\"\n", out);
fputs("\"\n", out_h);
if (out_h)
fputs("\"\n", out_h);
break;
case S_HEX:
str = sym_get_string_value(sym);
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
fprintf(out, "%s=%s\n", sym->name, str);
fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
if (out_h)
fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
break;
}
case S_INT:
str = sym_get_string_value(sym);
fprintf(out, "%s=%s\n", sym->name, str);
fprintf(out_h, "#define %s %s\n", sym->name, str);
if (out_h)
fprintf(out_h, "#define %s %s\n", sym->name, str);
break;
}
}
@ -351,18 +413,19 @@ int conf_write(const char *name)
}
}
fclose(out);
fclose(out_h);
if (!name) {
if (out_h) {
fclose(out_h);
rename(".tmpconfig.h", "include/config.h");
name = conf_def_filename;
file_write_dep(NULL);
} else
unlink(".tmpconfig.h");
sprintf(oldname, "%s.old", name);
rename(name, oldname);
if (rename(".tmpconfig", name))
}
if (!name || basename != conf_def_filename) {
if (!name)
name = conf_def_filename;
sprintf(tmpname, "%s.old", name);
rename(name, tmpname);
}
sprintf(tmpname, "%s%s", dirname, basename);
if (rename(newname, tmpname))
return 1;
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;
}
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 *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)
{
if (!e1 || !e2 || e1->type != e2->type)
if (!e1 || !e2)
return;
__expr_eliminate_eq(e1->type, ep1, ep2);
switch (e1->type) {
case E_OR:
case E_AND:
__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);
e2 = expr_eliminate_yn(e2);
}
@ -195,6 +215,7 @@ int expr_eq(struct expr *e1, struct expr *e2)
trans_count = old_count;
return res;
case E_CHOICE:
case E_RANGE:
case E_NONE:
/* panic */;
}
@ -897,6 +918,7 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
case E_SYMBOL:
return expr_alloc_comp(type, e->left.sym, sym);
case E_CHOICE:
case E_RANGE:
case E_NONE:
/* panic */;
}
@ -914,7 +936,7 @@ tristate expr_calc_value(struct expr *e)
switch (e->type) {
case E_SYMBOL:
sym_calc_value(e->left.sym);
return S_TRI(e->left.sym->curr);
return e->left.sym->curr.tri;
case E_AND:
val1 = expr_calc_value(e->left.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);
break;
case E_CHOICE:
if (e->left.expr) {
expr_print(e->left.expr, fn, data, E_CHOICE);
fn(data, " ^ ");
}
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;
default:
{

View File

@ -18,10 +18,6 @@ extern "C" {
struct file {
struct file *next;
struct file *parent;
#ifdef CML1
struct statement *stmt;
struct statement *last_stmt;
#endif
char *name;
int lineno;
int flags;
@ -36,7 +32,7 @@ typedef enum tristate {
} tristate;
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 {
@ -45,18 +41,10 @@ union expr_data {
};
struct expr {
#ifdef CML1
int token;
#else
enum expr_type type;
#endif
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_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
#define E_NOT(dep) (2-(dep))
@ -66,12 +54,8 @@ struct expr_value {
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 {
void *value;
void *val;
tristate tri;
};
@ -83,31 +67,17 @@ struct symbol {
struct symbol *next;
char *name;
char *help;
#ifdef CML1
int type;
#else
enum symbol_type type;
#endif
struct symbol_value curr, def;
struct symbol_value curr, user;
tristate visible;
int flags;
struct property *prop;
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)
#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_MOD 0x0002
#define SYMBOL_NO 0x0004
@ -122,42 +92,38 @@ struct symbol {
#define SYMBOL_CHANGED 0x0400
#define SYMBOL_NEW 0x0800
#define SYMBOL_AUTO 0x1000
#define SYMBOL_CHECKED 0x2000
#define SYMBOL_CHECK_DONE 0x4000
#define SYMBOL_WARNED 0x8000
#define SYMBOL_MAXLENGTH 256
#define SYMBOL_HASHSIZE 257
#define SYMBOL_HASHMASK 0xff
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 *next;
struct symbol *sym;
#ifdef CML1
int token;
#else
enum prop_type type;
#endif
const char *text;
struct symbol *def;
struct expr_value visible;
struct expr *dep;
struct expr *dep2;
struct expr *expr;
struct menu *menu;
struct file *file;
int lineno;
#ifdef CML1
struct property *next_pos;
#endif
};
#define for_all_properties(sym, st, tok) \
for (st = sym->prop; st; st = st->next) \
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_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 *next;
@ -166,12 +132,16 @@ struct menu {
struct symbol *sym;
struct property *prompt;
struct expr *dep;
unsigned int flags;
//char *help;
struct file *file;
int lineno;
void *data;
};
#define MENU_CHANGED 0x0001
#define MENU_ROOT 0x0002
#ifndef SWIG
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 *modules_sym;
extern int cdebug;
extern int print_type;
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_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);
#endif
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);
void expr_free(struct expr *e);
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 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)
{
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);
}
#endif
#endif
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@ -21,12 +21,14 @@ extern "C" {
#include "lkc_proto.h"
#undef P
void symbol_end(char *help);
#define SRCTREE "srctree"
int zconfparse(void);
void zconfdump(FILE *out);
extern int zconfdebug;
void zconf_starthelp(void);
FILE *zconf_fopen(const char *name);
void zconf_initscan(const char *name);
void zconf_nextfile(const char *name);
int zconf_lineno(void);
@ -47,9 +49,11 @@ void menu_add_menu(void);
void menu_end_menu(void);
void menu_add_entry(struct symbol *sym);
void menu_end_entry(void);
struct property *create_prop(enum prop_type type);
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_set_type(int type);
struct file *file_lookup(const char *name);
@ -61,16 +65,20 @@ extern struct menu *current_menu;
/* symbol.c */
void sym_init(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)
{
return S_TRI(sym->curr);
return sym->curr.tri;
}
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)
@ -95,7 +103,6 @@ static inline bool sym_is_optional(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;
}

View File

@ -5,7 +5,7 @@ P(conf_read,int,(const char *name));
P(conf_write,int,(const char *name));
/* menu.c */
extern struct menu rootmenu;
P(rootmenu,struct menu,);
P(menu_is_visible,bool,(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 */
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_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_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_set_tristate_value,bool,(struct symbol *sym,tristate tri));
P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
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_is_changable,bool,(struct symbol *sym));
P(sym_get_choice_prop,struct property *,(struct symbol *sym));

View File

@ -28,6 +28,7 @@
#define LKC_DIRECT_LINK
#include "lkc.h"
static char menu_backtitle[128];
static const char menu_instructions[] =
"Arrow keys navigate the menu. "
"<Enter> selects submenus --->. "
@ -65,7 +66,7 @@ load_config_help[] =
"configurations available on a single machine.\n"
"\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"
"\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)
{
struct winsize ws;
char *env;
if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
rows = 24;
@ -127,6 +129,20 @@ static void init_wsize(void)
} else {
rows = ws.ws_row;
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) {
@ -226,9 +242,7 @@ static void build_conf(struct menu *menu)
menu->data ? "-->" : "++>",
indent + 1, ' ', prompt);
} else {
if (menu->parent != &rootmenu)
cprint_name(" %*c", indent + 1, ' ');
cprint_name("%s --->", prompt);
cprint_name(" %*c%s --->", indent + 1, ' ', prompt);
}
if (single_menu_mode && menu->data)
@ -303,7 +317,10 @@ static void build_conf(struct menu *menu)
switch (type) {
case S_BOOLEAN:
cprint_tag("t%p", menu);
cprint_name("[%c]", val == no ? ' ' : '*');
if (sym_is_changable(sym))
cprint_name("[%c]", val == no ? ' ' : '*');
else
cprint_name("---");
break;
case S_TRISTATE:
cprint_tag("t%p", menu);
@ -312,7 +329,10 @@ static void build_conf(struct menu *menu)
case mod: ch = 'M'; break;
default: ch = ' '; break;
}
cprint_name("<%c>", ch);
if (sym_is_changable(sym))
cprint_name("<%c>", ch);
else
cprint_name("---");
break;
default:
cprint_tag("s%p", menu);
@ -321,12 +341,18 @@ static void build_conf(struct menu *menu)
if (tmp < 0)
tmp = 0;
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;
}
}
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:
@ -390,13 +416,15 @@ static void conf(struct menu *menu)
switch (type) {
case 'm':
if (single_menu_mode)
submenu->data = (submenu->data)? NULL : (void *)1;
submenu->data = (void *) (long) !submenu->data;
else
conf(submenu);
break;
case 't':
if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
conf_choice(submenu);
else if (submenu->prompt->type == P_MENU)
conf(submenu);
break;
case 's':
conf_string(submenu);
@ -602,7 +630,6 @@ static void conf_cleanup(void)
{
tcsetattr(1, TCSAFLUSH, &ios_org);
unlink(".help.tmp");
unlink("lxdialog.scrltmp");
}
static void winch_handler(int sig)
@ -638,10 +665,9 @@ int main(int ac, char **av)
conf_parse(av[1]);
conf_read(NULL);
backtitle = malloc(128);
sym = sym_lookup("VERSION", 0);
sym_calc_value(sym);
snprintf(backtitle, 128, "BusyBox v%s Configuration",
snprintf(menu_backtitle, 128, "BusyBox v%s Configuration",
sym_get_string_value(sym));
mode = getenv("MENUCONFIG_MODE");

View File

@ -54,9 +54,34 @@ void menu_end_menu(void)
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)
{
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)
@ -69,56 +94,43 @@ void menu_set_type(int type)
sym->type = type;
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,
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->text = prompt;
prop->def = def;
E_EXPR(prop->visible) = dep;
prop->expr = expr;
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;
/* append property to the prop list of symbol */
if (prop->sym) {
for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next)
;
*propp = 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)
@ -126,7 +138,7 @@ void menu_finalize(struct menu *parent)
struct menu *menu, *last_menu;
struct symbol *sym;
struct property *prop;
struct expr *parentdep, *basedep, *dep, *dep2;
struct expr *parentdep, *basedep, *dep, *dep2, **ep;
sym = parent->sym;
if (parent->list) {
@ -143,7 +155,7 @@ void menu_finalize(struct menu *parent)
}
parentdep = expr_alloc_symbol(sym);
} else if (parent->prompt)
parentdep = E_EXPR(parent->prompt->visible);
parentdep = parent->prompt->visible.expr;
else
parentdep = parent->dep;
@ -159,23 +171,28 @@ void menu_finalize(struct menu *parent)
for (; prop; prop = prop->next) {
if (prop->menu != menu)
continue;
dep = expr_transform(E_EXPR(prop->visible));
dep = expr_transform(prop->visible.expr);
dep = expr_alloc_and(expr_copy(basedep), dep);
dep = expr_eliminate_dups(dep);
if (menu->sym && menu->sym->type != S_TRISTATE)
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)
menu_finalize(menu);
} else if (sym && parent->prompt) {
basedep = E_EXPR(parent->prompt->visible);
} else if (sym) {
basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
basedep = expr_eliminate_dups(expr_transform(basedep));
last_menu = NULL;
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))
break;
if (expr_depends_symbol(dep, sym))
@ -204,14 +221,27 @@ void menu_finalize(struct menu *parent)
for (menu = parent->list; menu; menu = menu->next) {
if (sym && sym_is_choice(sym) && menu->sym) {
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;
menu_set_type(sym->type);
menu_add_prop(P_CHOICE, NULL, parent->sym, NULL);
prop = sym_get_choice_prop(parent->sym);
//dep = expr_alloc_one(E_CHOICE, dep);
//dep->right.sym = menu->sym;
prop->dep = expr_alloc_one(E_CHOICE, prop->dep);
prop->dep->right.sym = menu->sym;
menu_add_symbol(P_CHOICE, sym, NULL);
prop = sym_get_choice_prop(sym);
for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
;
*ep = expr_alloc_one(E_CHOICE, NULL);
(*ep)->right.sym = menu->sym;
}
if (menu->list && (!menu->prompt || !menu->prompt->text)) {
for (last_menu = menu->list; ; last_menu = last_menu->next) {
@ -224,20 +254,79 @@ void menu_finalize(struct menu *parent)
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)
{
struct menu *child;
struct symbol *sym;
tristate visible;
if (!menu->prompt)
return false;
if (menu->sym) {
sym_calc_value(menu->sym);
visible = E_TRI(menu->prompt->visible);
sym = menu->sym;
if (sym) {
sym_calc_value(sym);
visible = menu->prompt->visible.tri;
} else
visible = E_CALC(menu->prompt->visible);
return visible != no;
visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
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)
@ -258,10 +347,9 @@ struct menu *menu_get_parent_menu(struct menu *menu)
{
enum prop_type type;
while (menu != &rootmenu) {
menu = menu->parent;
for (; menu != &rootmenu; menu = menu->parent) {
type = menu->prompt ? menu->prompt->type : 0;
if (type == P_MENU || type == P_ROOTMENU)
if (type == P_MENU)
break;
}
return menu;

View File

@ -34,24 +34,14 @@ struct symbol *modules_sym;
void sym_add_default(struct symbol *sym, const char *def)
{
struct property *prop = create_prop(P_DEFAULT);
struct property **propp;
struct property *prop = prop_alloc(P_DEFAULT, sym);
prop->sym = sym;
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;
}
prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
}
void sym_init(void)
{
struct symbol *sym;
struct utsname uts;
char *p;
static bool inited = false;
@ -59,17 +49,6 @@ void sym_init(void)
return;
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->type = S_STRING;
sym->flags |= SYMBOL_AUTO;
@ -77,37 +56,32 @@ void sym_init(void)
if (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->type = S_STRING;
sym->flags |= SYMBOL_AUTO;
p = getenv("TARGET_ARCH");
if (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 (sym_is_choice_value(sym) && sym->visible == yes)
type = S_BOOLEAN;
else {
sym_calc_value(modules_sym);
if (S_TRI(modules_sym->curr) == no)
if (modules_sym->curr.tri == no)
type = S_BOOLEAN;
}
}
return type;
}
const char *sym_type_name(int type)
const char *sym_type_name(enum symbol_type type)
{
switch (type) {
case S_BOOLEAN:
@ -122,6 +96,8 @@ const char *sym_type_name(int type)
return "string";
case S_UNKNOWN:
return "unknown";
case S_OTHER:
break;
}
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 *prop;
tristate visible;
for_all_defaults(sym, prop) {
visible = E_CALC(prop->visible);
if (visible != no)
prop->visible.tri = expr_calc_value(prop->visible.expr);
if (prop->visible.tri != no)
return prop;
}
return NULL;
}
void sym_calc_visibility(struct symbol *sym)
struct property *sym_get_range_prop(struct symbol *sym)
{
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? */
oldvisible = sym->visible;
visible = no;
for_all_prompts(sym, prop)
visible = E_OR(visible, E_CALC(prop->visible));
if (oldvisible != visible) {
sym->visible = visible;
sym->flags |= SYMBOL_CHANGED;
tri = no;
for_all_prompts(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
tri = E_OR(tri, prop->visible.tri);
}
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)
{
struct symbol_value newval, oldval;
struct property *prop, *def_prop;
struct symbol *def_sym;
struct property *prop;
struct expr *e;
if (!sym)
return;
if (sym->flags & SYMBOL_VALID)
return;
sym->flags |= SYMBOL_VALID;
oldval = sym->curr;
@ -187,17 +226,10 @@ void sym_calc_value(struct symbol *sym)
newval = symbol_no.curr;
break;
default:
S_VAL(newval) = sym->name;
S_TRI(newval) = no;
if (sym->flags & SYMBOL_CONST) {
goto out;
}
//newval = symbol_empty.curr;
// generate warning somewhere here later
//S_TRI(newval) = yes;
goto out;
sym->curr.val = sym->name;
sym->curr.tri = no;
return;
}
sym->flags |= SYMBOL_VALID;
if (!sym_is_choice_value(sym))
sym->flags &= ~SYMBOL_WRITE;
@ -206,95 +238,77 @@ void sym_calc_value(struct symbol *sym)
/* set default if recursively called */
sym->curr = newval;
if (sym->visible != no) {
sym->flags |= SYMBOL_WRITE;
if (!sym_has_value(sym)) {
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;
switch (sym_get_type(sym)) {
case S_BOOLEAN:
case S_TRISTATE:
if (sym_is_choice_value(sym) && sym->visible == yes) {
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);
}
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);
if (prop) {
sym->flags |= SYMBOL_WRITE;
newval.tri = expr_calc_value(prop->expr);
}
}
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;
}
}
} else {
prop = sym_get_default_prop(sym);
if (prop) {
sym->flags |= SYMBOL_WRITE;
sym_calc_value(prop->def);
newval = prop->def->curr;
struct symbol *ds = prop_get_symbol(prop);
if (ds) {
sym->flags |= SYMBOL_WRITE;
sym_calc_value(ds);
newval.val = ds->curr.val;
}
}
}
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;
default:
;
}
out:
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) {
def_sym = S_VAL(sym->def);
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 (memcmp(&oldval, &sym->curr, sizeof(oldval)))
sym_set_changed(sym);
if (sym_is_choice(sym)) {
int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
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;
if (flags & SYMBOL_CHANGED)
sym_set_changed(e->right.sym);
}
}
}
@ -308,13 +322,24 @@ void sym_clear_all_valid(void)
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)
{
struct symbol *sym;
int i;
for_all_symbols(i, sym)
sym->flags |= SYMBOL_CHANGED;
sym_set_changed(sym);
}
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)
return false;
switch (val) {
case no:
if (sym_is_choice_value(sym) && sym->visible == yes)
return false;
return sym_is_optional(sym);
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;
if (type == S_BOOLEAN && val == mod)
return false;
if (sym->visible <= sym->rev_dep.tri)
return false;
if (sym_is_choice_value(sym) && sym->visible == yes)
return val == yes;
return val >= sym->rev_dep.tri && val <= sym->visible;
}
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) {
sym->flags &= ~SYMBOL_NEW;
sym->flags |= SYMBOL_CHANGED;
sym_set_changed(sym);
}
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;
prop->def->flags &= ~SYMBOL_NEW;
cs->user.val = sym;
cs->flags &= ~SYMBOL_NEW;
}
S_TRI(sym->def) = val;
sym->user.tri = val;
if (oldval != val) {
sym_clear_all_valid();
if (sym == modules_sym)
@ -404,12 +423,12 @@ bool sym_string_valid(struct symbol *sym, const char *str)
ch = *str++;
if (ch == '-')
ch = *str++;
if (!isdigit((int)ch))
if (!isdigit(ch))
return false;
if (ch == '0' && *str != 0)
return false;
while ((ch = *str++)) {
if (!isdigit((int)ch))
if (!isdigit(ch))
return false;
}
return true;
@ -418,21 +437,58 @@ bool sym_string_valid(struct symbol *sym, const char *str)
str += 2;
ch = *str++;
do {
if (!isxdigit((int)ch))
if (!isxdigit(ch))
return false;
} while ((ch = *str++));
return true;
case S_BOOLEAN:
case S_TRISTATE:
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);
case 'm':
case 'M':
case 'm': case 'M':
return sym_tristate_within_range(sym, mod);
case 'n':
case 'N':
case 'n': case 'N':
return sym_tristate_within_range(sym, no);
}
return false;
@ -451,14 +507,11 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
case S_BOOLEAN:
case S_TRISTATE:
switch (newval[0]) {
case 'y':
case 'Y':
case 'y': case 'Y':
return sym_set_tristate_value(sym, yes);
case 'm':
case 'M':
case 'm': case 'M':
return sym_set_tristate_value(sym, mod);
case 'n':
case 'N':
case 'n': case 'N':
return sym_set_tristate_value(sym, no);
}
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;
if (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;
if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
size += 2;
S_VAL(sym->def) = val = malloc(size);
sym->user.val = val = malloc(size);
*val++ = '0';
*val++ = 'x';
} else if (!oldval || strcmp(oldval, newval))
S_VAL(sym->def) = val = malloc(size);
sym->user.val = val = malloc(size);
else
return true;
@ -513,20 +566,12 @@ const char *sym_get_string_value(struct symbol *sym)
default:
;
}
return (const char *)S_VAL(sym->curr);
return (const char *)sym->curr.val;
}
bool sym_is_changable(struct symbol *sym)
{
if (sym->visible == no)
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;
return sym->visible > sym->rev_dep.tri;
}
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;
int hash = 0;
//printf("lookup: %s -> ", name);
if (name) {
if (name[0] && !name[1]) {
switch (name[0]) {
@ -552,10 +596,8 @@ struct symbol *sym_lookup(const char *name, int isconst)
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
if (!strcmp(symbol->name, name)) {
if ((isconst && symbol->flags & SYMBOL_CONST) ||
(!isconst && !(symbol->flags & SYMBOL_CONST))) {
//printf("h:%p\n", symbol);
(!isconst && !(symbol->flags & SYMBOL_CONST)))
return symbol;
}
}
}
new_name = strdup(name);
@ -575,7 +617,6 @@ struct symbol *sym_lookup(const char *name, int isconst)
symbol->next = symbol_hash[hash];
symbol_hash[hash] = symbol;
//printf("n:%p\n", symbol);
return symbol;
}
@ -608,6 +649,104 @@ struct symbol *sym_find(const char *name)
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)
{
switch (type) {
@ -617,13 +756,16 @@ const char *prop_get_type_name(enum prop_type type)
return "comment";
case P_MENU:
return "menu";
case P_ROOTMENU:
return "rootmenu";
case P_DEFAULT:
return "default";
case P_CHOICE:
return "choice";
default:
return "unknown";
case P_SELECT:
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.
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -14,7 +15,6 @@
#define LKC_DIRECT_LINK
#include "lkc.h"
#include "zconf.tab.h"
#define START_STRSIZE 16
@ -96,6 +96,7 @@ n [A-Za-z0-9_]
"endchoice" BEGIN(PARAM); return T_ENDCHOICE;
"comment" BEGIN(PARAM); return T_COMMENT;
"config" BEGIN(PARAM); return T_CONFIG;
"menuconfig" BEGIN(PARAM); return T_MENUCONFIG;
"help" BEGIN(PARAM); return T_HELP;
"if" BEGIN(PARAM); return T_IF;
"endif" BEGIN(PARAM); return T_ENDIF;
@ -105,11 +106,17 @@ n [A-Za-z0-9_]
"default" BEGIN(PARAM); return T_DEFAULT;
"prompt" BEGIN(PARAM); return T_PROMPT;
"tristate" BEGIN(PARAM); return T_TRISTATE;
"def_tristate" BEGIN(PARAM); return T_DEF_TRISTATE;
"bool" 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;
"hex" BEGIN(PARAM); return T_HEX;
"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}+ {
alloc_string(yytext, yyleng);
zconflval.string = text;
@ -141,6 +148,8 @@ n [A-Za-z0-9_]
zconflval.string = text;
return T_WORD;
}
#.* /* comment */
\\\n current_file->lineno++;
.
<<EOF>> {
BEGIN(INITIAL);
@ -151,29 +160,30 @@ n [A-Za-z0-9_]
[^'"\\\n]+/\n {
append_string(yytext, yyleng);
zconflval.string = text;
return T_STRING;
return T_WORD_QUOTE;
}
[^'"\\\n]+ {
append_string(yytext, yyleng);
}
\\.?/\n {
append_string(yytext+1, yyleng);
append_string(yytext + 1, yyleng - 1);
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]) {
BEGIN(PARAM);
zconflval.string = text;
return T_STRING;
return T_WORD_QUOTE;
} else
append_string(yytext, 1);
}
\n {
printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
current_file->lineno++;
BEGIN(INITIAL);
return T_EOL;
}
@ -204,9 +214,8 @@ n [A-Za-z0-9_]
}
append_string(" ", ts);
}
}
\n/[^ \t\n] {
[ \t]*\n/[^ \t\n] {
current_file->lineno++;
zconf_endhelp();
return T_HELPTEXT;
@ -246,12 +255,37 @@ void zconf_starthelp(void)
static void zconf_endhelp(void)
{
zconflval.string = text;
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)
{
yyin = fopen(name, "r");
yyin = zconf_fopen(name);
if (!yyin) {
printf("can't find file %s\n", name);
exit(1);
@ -272,7 +306,7 @@ void zconf_nextfile(const char *name)
memset(buf, 0, sizeof(*buf));
current_buf->state = YY_CURRENT_BUFFER;
yyin = fopen(name, "r");
yyin = zconf_fopen(name);
if (!yyin) {
printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
exit(1);
@ -318,7 +352,7 @@ static struct buffer *zconf_endfile(void)
int zconf_lineno(void)
{
if (current_buf)
return current_file->lineno;
return current_file->lineno - 1;
else
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
%}
%expect 36
%expect 40
%union
{
@ -46,6 +46,7 @@ struct symbol *symbol_hash[257];
%token T_ENDCHOICE
%token T_COMMENT
%token T_CONFIG
%token T_MENUCONFIG
%token T_HELP
%token <string> T_HELPTEXT
%token T_IF
@ -56,17 +57,22 @@ struct symbol *symbol_hash[257];
%token T_PROMPT
%token T_DEFAULT
%token T_TRISTATE
%token T_DEF_TRISTATE
%token T_BOOLEAN
%token T_DEF_BOOLEAN
%token T_STRING
%token T_INT
%token T_HEX
%token <string> T_WORD
%token <string> T_STRING
%token <string> T_WORD_QUOTE
%token T_UNEQUAL
%token T_EOF
%token T_EOL
%token T_CLOSE_PAREN
%token T_OPEN_PAREN
%token T_ON
%token T_SELECT
%token T_RANGE
%left T_OR
%left T_AND
@ -103,14 +109,15 @@ common_block:
if_stmt
| comment_stmt
| config_stmt
| menuconfig_stmt
| source_stmt
| 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);
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);
};
config_stmt: config_entry_start T_EOL config_option_list
config_stmt: config_entry_start config_option_list
{
menu_end_entry();
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:
/* empty */
| config_option_list config_option T_EOL
| config_option_list depends T_EOL
| config_option_list config_option
| config_option_list depends
| config_option_list help
| 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);
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);
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);
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);
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);
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());
};
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());
};
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: T_CHOICE
choice: T_CHOICE T_EOL
{
struct symbol *sym = sym_lookup(NULL, 0);
sym->flags |= SYMBOL_CHOICE;
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());
};
choice_entry: choice T_EOL choice_option_list
choice_entry: choice choice_option_list
{
menu_end_entry();
menu_add_menu();
@ -200,7 +251,7 @@ choice_end: end
};
choice_stmt:
choice_entry choice_block choice_end T_EOL
choice_entry choice_block choice_end
| choice_entry choice_block
{
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:
/* empty */
| choice_option_list choice_option T_EOL
| choice_option_list depends T_EOL
| choice_option_list choice_option
| choice_option_list depends
| choice_option_list help
| 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());
};
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;
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);
//current_choice->prop->def = $2;
menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
};
@ -241,11 +303,10 @@ choice_block:
/* if entry */
if: T_IF expr
if: T_IF expr T_EOL
{
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
menu_add_entry(NULL);
//current_entry->prompt = menu_add_prop(T_IF, NULL, NULL, $2);
menu_add_dep($2);
menu_end_entry();
menu_add_menu();
@ -260,8 +321,8 @@ if_end: end
};
if_stmt:
if T_EOL if_block if_end T_EOL
| if T_EOL if_block
if if_block if_end
| if if_block
{
printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
zconfnerrs++;
@ -276,14 +337,14 @@ if_block:
/* menu entry */
menu: T_MENU prompt
menu: T_MENU prompt T_EOL
{
menu_add_entry(NULL);
menu_add_prop(P_MENU, $2, NULL, NULL);
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_add_menu();
@ -298,7 +359,7 @@ menu_end: end
};
menu_stmt:
menu_entry menu_block menu_end T_EOL
menu_entry menu_block menu_end
| menu_entry menu_block
{
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; }
;
source: T_SOURCE prompt
source: T_SOURCE prompt T_EOL
{
$$ = $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);
};
/* comment entry */
comment: T_COMMENT prompt
comment: T_COMMENT prompt T_EOL
{
menu_add_entry(NULL);
menu_add_prop(P_COMMENT, $2, NULL, NULL);
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();
};
@ -354,21 +415,21 @@ help: help_start T_HELPTEXT
/* depends option */
depends_list: /* empty */
| depends_list depends T_EOL
| depends_list depends
| depends_list T_EOL
{ };
;
depends: T_DEPENDS T_ON expr
depends: T_DEPENDS T_ON expr T_EOL
{
menu_add_dep($3);
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
}
| T_DEPENDS expr
| T_DEPENDS expr T_EOL
{
menu_add_dep($2);
printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
}
| T_REQUIRES expr
| T_REQUIRES expr T_EOL
{
menu_add_dep($2);
printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
@ -378,22 +439,18 @@ depends: T_DEPENDS T_ON expr
prompt_stmt_opt:
/* empty */
| prompt
| prompt if_expr
{
menu_add_prop(P_PROMPT, $1, NULL, NULL);
}
| prompt T_IF expr
{
menu_add_prop(P_PROMPT, $1, NULL, $3);
menu_add_prop(P_PROMPT, $1, NULL, $2);
};
prompt: T_WORD
| T_STRING
| T_WORD_QUOTE
;
end: T_ENDMENU { $$ = T_ENDMENU; }
| T_ENDCHOICE { $$ = T_ENDCHOICE; }
| T_ENDIF { $$ = T_ENDIF; }
end: T_ENDMENU nl_or_eof { $$ = T_ENDMENU; }
| T_ENDCHOICE nl_or_eof { $$ = T_ENDCHOICE; }
| T_ENDIF nl_or_eof { $$ = T_ENDIF; }
;
nl_or_eof:
@ -413,26 +470,34 @@ expr: symbol { $$ = expr_alloc_symbol($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)
{
struct symbol *sym;
int i;
zconf_initscan(name);
sym_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;
zconfparse();
if (zconfnerrs)
exit(1);
menu_finalize(&rootmenu);
modules_sym = sym_lookup("MODULES", 0);
for_all_symbols(i, sym) {
if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym))
printf("\n");
else
sym->flags |= SYMBOL_CHECK_DONE;
}
sym_change_count = 1;
}
@ -448,7 +513,7 @@ const char *zconf_tokenname(int token)
case T_ENDIF: return "endif";
}
return "<token>";
}
}
static bool zconf_endtoken(int token, int starttoken, int endtoken)
{
@ -470,7 +535,7 @@ static void zconfprint(const char *err, ...)
{
va_list ap;
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1);
va_start(ap, err);
vfprintf(stderr, err, ap);
va_end(ap);
@ -479,7 +544,7 @@ static void zconfprint(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)
@ -504,8 +569,6 @@ void print_symbol(FILE *out, struct menu *menu)
struct symbol *sym = menu->sym;
struct property *prop;
//sym->flags |= SYMBOL_PRINTED;
if (sym_is_choice(sym))
fprintf(out, "choice\n");
else
@ -530,13 +593,6 @@ void print_symbol(FILE *out, struct menu *menu)
fputs(" ???\n", out);
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) {
if (prop->menu != menu)
continue;
@ -544,25 +600,18 @@ void print_symbol(FILE *out, struct menu *menu)
case P_PROMPT:
fputs(" prompt ", out);
print_quoted_string(out, prop->text);
if (prop->def) {
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))) {
if (!expr_is_yes(prop->visible.expr)) {
fputs(" if ", out);
expr_fprint(E_EXPR(prop->visible), out);
expr_fprint(prop->visible.expr, out);
}
fputc('\n', out);
break;
case P_DEFAULT:
fputs( " default ", out);
print_quoted_string(out, prop->def->name);
if (!expr_is_yes(E_EXPR(prop->visible))) {
expr_fprint(prop->expr, out);
if (!expr_is_yes(prop->visible.expr)) {
fputs(" if ", out);
expr_fprint(E_EXPR(prop->visible), out);
expr_fprint(prop->visible.expr, out);
}
fputc('\n', out);
break;
@ -585,7 +634,6 @@ void print_symbol(FILE *out, struct menu *menu)
void zconfdump(FILE *out)
{
//struct file *file;
struct property *prop;
struct symbol *sym;
struct menu *menu;
@ -596,11 +644,6 @@ void zconfdump(FILE *out)
print_symbol(out, menu);
else if ((prop = menu->prompt)) {
switch (prop->type) {
//case T_MAINMENU:
// fputs("\nmainmenu ", out);
// print_quoted_string(out, prop->text);
// fputs("\n", out);
// break;
case P_COMMENT:
fputs("\ncomment ", out);
print_quoted_string(out, prop->text);
@ -611,19 +654,12 @@ void zconfdump(FILE *out)
print_quoted_string(out, prop->text);
fputs("\n", out);
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:
;
}
if (!expr_is_yes(E_EXPR(prop->visible))) {
if (!expr_is_yes(prop->visible.expr)) {
fputs(" depends ", out);
expr_fprint(E_EXPR(prop->visible), out);
expr_fprint(prop->visible.expr, out);
fputc('\n', out);
}
fputs("\n", out);

View File

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

View File

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