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:
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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:
|
||||||
{
|
{
|
||||||
|
@ -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
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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");
|
||||||
|
@ -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;
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
|
@ -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
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
Reference in New Issue
Block a user