Commit 59e89e3ddf8523be39a8e0a66bacbbdd6a72d069
Committed by
Michal Marek
1 parent
861b4ea4cc
Exists in
master
and in
7 other branches
kconfig: save location of config symbols
When we add a new config symbol save the file/line so we later can refer to their location. The information is saved as a property to a config symbol because we may have multiple definitions of the same symbol. This has the side-effect that a symbol always has at least one property. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Cc: Roman Zippel <zippel@linux-m68k.org> Signed-off-by: Michal Marek <mmarek@suse.cz>
Showing 3 changed files with 5 additions and 0 deletions Inline Diff
scripts/kconfig/expr.h
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | 2 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |
3 | * Released under the terms of the GNU GPL v2.0. | 3 | * Released under the terms of the GNU GPL v2.0. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef EXPR_H | 6 | #ifndef EXPR_H |
7 | #define EXPR_H | 7 | #define EXPR_H |
8 | 8 | ||
9 | #ifdef __cplusplus | 9 | #ifdef __cplusplus |
10 | extern "C" { | 10 | extern "C" { |
11 | #endif | 11 | #endif |
12 | 12 | ||
13 | #include <stdio.h> | 13 | #include <stdio.h> |
14 | #ifndef __cplusplus | 14 | #ifndef __cplusplus |
15 | #include <stdbool.h> | 15 | #include <stdbool.h> |
16 | #endif | 16 | #endif |
17 | 17 | ||
18 | struct file { | 18 | struct file { |
19 | struct file *next; | 19 | struct file *next; |
20 | struct file *parent; | 20 | struct file *parent; |
21 | char *name; | 21 | char *name; |
22 | int lineno; | 22 | int lineno; |
23 | int flags; | 23 | int flags; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | #define FILE_BUSY 0x0001 | 26 | #define FILE_BUSY 0x0001 |
27 | #define FILE_SCANNED 0x0002 | 27 | #define FILE_SCANNED 0x0002 |
28 | 28 | ||
29 | typedef enum tristate { | 29 | typedef enum tristate { |
30 | no, mod, yes | 30 | no, mod, yes |
31 | } tristate; | 31 | } tristate; |
32 | 32 | ||
33 | enum expr_type { | 33 | enum expr_type { |
34 | E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE | 34 | E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE |
35 | }; | 35 | }; |
36 | 36 | ||
37 | union expr_data { | 37 | union expr_data { |
38 | struct expr *expr; | 38 | struct expr *expr; |
39 | struct symbol *sym; | 39 | struct symbol *sym; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | struct expr { | 42 | struct expr { |
43 | enum expr_type type; | 43 | enum expr_type type; |
44 | union expr_data left, right; | 44 | union expr_data left, right; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | #define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) | 47 | #define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) |
48 | #define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) | 48 | #define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) |
49 | #define EXPR_NOT(dep) (2-(dep)) | 49 | #define EXPR_NOT(dep) (2-(dep)) |
50 | 50 | ||
51 | #define expr_list_for_each_sym(l, e, s) \ | 51 | #define expr_list_for_each_sym(l, e, s) \ |
52 | for (e = (l); e && (s = e->right.sym); e = e->left.expr) | 52 | for (e = (l); e && (s = e->right.sym); e = e->left.expr) |
53 | 53 | ||
54 | struct expr_value { | 54 | struct expr_value { |
55 | struct expr *expr; | 55 | struct expr *expr; |
56 | tristate tri; | 56 | tristate tri; |
57 | }; | 57 | }; |
58 | 58 | ||
59 | struct symbol_value { | 59 | struct symbol_value { |
60 | void *val; | 60 | void *val; |
61 | tristate tri; | 61 | tristate tri; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | enum symbol_type { | 64 | enum symbol_type { |
65 | S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER | 65 | S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER |
66 | }; | 66 | }; |
67 | 67 | ||
68 | /* enum values are used as index to symbol.def[] */ | 68 | /* enum values are used as index to symbol.def[] */ |
69 | enum { | 69 | enum { |
70 | S_DEF_USER, /* main user value */ | 70 | S_DEF_USER, /* main user value */ |
71 | S_DEF_AUTO, /* values read from auto.conf */ | 71 | S_DEF_AUTO, /* values read from auto.conf */ |
72 | S_DEF_DEF3, /* Reserved for UI usage */ | 72 | S_DEF_DEF3, /* Reserved for UI usage */ |
73 | S_DEF_DEF4, /* Reserved for UI usage */ | 73 | S_DEF_DEF4, /* Reserved for UI usage */ |
74 | S_DEF_COUNT | 74 | S_DEF_COUNT |
75 | }; | 75 | }; |
76 | 76 | ||
77 | struct symbol { | 77 | struct symbol { |
78 | struct symbol *next; | 78 | struct symbol *next; |
79 | char *name; | 79 | char *name; |
80 | enum symbol_type type; | 80 | enum symbol_type type; |
81 | struct symbol_value curr; | 81 | struct symbol_value curr; |
82 | struct symbol_value def[S_DEF_COUNT]; | 82 | struct symbol_value def[S_DEF_COUNT]; |
83 | tristate visible; | 83 | tristate visible; |
84 | int flags; | 84 | int flags; |
85 | struct property *prop; | 85 | struct property *prop; |
86 | struct expr_value dir_dep; | 86 | struct expr_value dir_dep; |
87 | struct expr_value rev_dep; | 87 | struct expr_value rev_dep; |
88 | }; | 88 | }; |
89 | 89 | ||
90 | #define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) | 90 | #define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) |
91 | 91 | ||
92 | #define SYMBOL_CONST 0x0001 /* symbol is const */ | 92 | #define SYMBOL_CONST 0x0001 /* symbol is const */ |
93 | #define SYMBOL_CHECK 0x0008 /* used during dependency checking */ | 93 | #define SYMBOL_CHECK 0x0008 /* used during dependency checking */ |
94 | #define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */ | 94 | #define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */ |
95 | #define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */ | 95 | #define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */ |
96 | #define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */ | 96 | #define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */ |
97 | #define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ | 97 | #define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ |
98 | #define SYMBOL_WRITE 0x0200 /* ? */ | 98 | #define SYMBOL_WRITE 0x0200 /* ? */ |
99 | #define SYMBOL_CHANGED 0x0400 /* ? */ | 99 | #define SYMBOL_CHANGED 0x0400 /* ? */ |
100 | #define SYMBOL_AUTO 0x1000 /* value from environment variable */ | 100 | #define SYMBOL_AUTO 0x1000 /* value from environment variable */ |
101 | #define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ | 101 | #define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ |
102 | #define SYMBOL_WARNED 0x8000 /* warning has been issued */ | 102 | #define SYMBOL_WARNED 0x8000 /* warning has been issued */ |
103 | 103 | ||
104 | /* Set when symbol.def[] is used */ | 104 | /* Set when symbol.def[] is used */ |
105 | #define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */ | 105 | #define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */ |
106 | #define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */ | 106 | #define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */ |
107 | #define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */ | 107 | #define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */ |
108 | #define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ | 108 | #define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ |
109 | #define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ | 109 | #define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ |
110 | 110 | ||
111 | #define SYMBOL_MAXLENGTH 256 | 111 | #define SYMBOL_MAXLENGTH 256 |
112 | #define SYMBOL_HASHSIZE 9973 | 112 | #define SYMBOL_HASHSIZE 9973 |
113 | 113 | ||
114 | /* A property represent the config options that can be associated | 114 | /* A property represent the config options that can be associated |
115 | * with a config "symbol". | 115 | * with a config "symbol". |
116 | * Sample: | 116 | * Sample: |
117 | * config FOO | 117 | * config FOO |
118 | * default y | 118 | * default y |
119 | * prompt "foo prompt" | 119 | * prompt "foo prompt" |
120 | * select BAR | 120 | * select BAR |
121 | * config BAZ | 121 | * config BAZ |
122 | * int "BAZ Value" | 122 | * int "BAZ Value" |
123 | * range 1..255 | 123 | * range 1..255 |
124 | */ | 124 | */ |
125 | enum prop_type { | 125 | enum prop_type { |
126 | P_UNKNOWN, | 126 | P_UNKNOWN, |
127 | P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */ | 127 | P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */ |
128 | P_COMMENT, /* text associated with a comment */ | 128 | P_COMMENT, /* text associated with a comment */ |
129 | P_MENU, /* prompt associated with a menuconfig option */ | 129 | P_MENU, /* prompt associated with a menuconfig option */ |
130 | P_DEFAULT, /* default y */ | 130 | P_DEFAULT, /* default y */ |
131 | P_CHOICE, /* choice value */ | 131 | P_CHOICE, /* choice value */ |
132 | P_SELECT, /* select BAR */ | 132 | P_SELECT, /* select BAR */ |
133 | P_RANGE, /* range 7..100 (for a symbol) */ | 133 | P_RANGE, /* range 7..100 (for a symbol) */ |
134 | P_ENV, /* value from environment variable */ | 134 | P_ENV, /* value from environment variable */ |
135 | P_SYMBOL, /* where a symbol is defined */ | ||
135 | }; | 136 | }; |
136 | 137 | ||
137 | struct property { | 138 | struct property { |
138 | struct property *next; /* next property - null if last */ | 139 | struct property *next; /* next property - null if last */ |
139 | struct symbol *sym; /* the symbol for which the property is associated */ | 140 | struct symbol *sym; /* the symbol for which the property is associated */ |
140 | enum prop_type type; /* type of property */ | 141 | enum prop_type type; /* type of property */ |
141 | const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ | 142 | const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ |
142 | struct expr_value visible; | 143 | struct expr_value visible; |
143 | struct expr *expr; /* the optional conditional part of the property */ | 144 | struct expr *expr; /* the optional conditional part of the property */ |
144 | struct menu *menu; /* the menu the property are associated with | 145 | struct menu *menu; /* the menu the property are associated with |
145 | * valid for: P_SELECT, P_RANGE, P_CHOICE, | 146 | * valid for: P_SELECT, P_RANGE, P_CHOICE, |
146 | * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */ | 147 | * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */ |
147 | struct file *file; /* what file was this property defined */ | 148 | struct file *file; /* what file was this property defined */ |
148 | int lineno; /* what lineno was this property defined */ | 149 | int lineno; /* what lineno was this property defined */ |
149 | }; | 150 | }; |
150 | 151 | ||
151 | #define for_all_properties(sym, st, tok) \ | 152 | #define for_all_properties(sym, st, tok) \ |
152 | for (st = sym->prop; st; st = st->next) \ | 153 | for (st = sym->prop; st; st = st->next) \ |
153 | if (st->type == (tok)) | 154 | if (st->type == (tok)) |
154 | #define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) | 155 | #define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) |
155 | #define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) | 156 | #define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) |
156 | #define for_all_prompts(sym, st) \ | 157 | #define for_all_prompts(sym, st) \ |
157 | for (st = sym->prop; st; st = st->next) \ | 158 | for (st = sym->prop; st; st = st->next) \ |
158 | if (st->text) | 159 | if (st->text) |
159 | 160 | ||
160 | struct menu { | 161 | struct menu { |
161 | struct menu *next; | 162 | struct menu *next; |
162 | struct menu *parent; | 163 | struct menu *parent; |
163 | struct menu *list; | 164 | struct menu *list; |
164 | struct symbol *sym; | 165 | struct symbol *sym; |
165 | struct property *prompt; | 166 | struct property *prompt; |
166 | struct expr *dep; | 167 | struct expr *dep; |
167 | struct expr *dir_dep; | 168 | struct expr *dir_dep; |
168 | unsigned int flags; | 169 | unsigned int flags; |
169 | char *help; | 170 | char *help; |
170 | struct file *file; | 171 | struct file *file; |
171 | int lineno; | 172 | int lineno; |
172 | void *data; | 173 | void *data; |
173 | }; | 174 | }; |
174 | 175 | ||
175 | #define MENU_CHANGED 0x0001 | 176 | #define MENU_CHANGED 0x0001 |
176 | #define MENU_ROOT 0x0002 | 177 | #define MENU_ROOT 0x0002 |
177 | 178 | ||
178 | #ifndef SWIG | 179 | #ifndef SWIG |
179 | 180 | ||
180 | extern struct file *file_list; | 181 | extern struct file *file_list; |
181 | extern struct file *current_file; | 182 | extern struct file *current_file; |
182 | struct file *lookup_file(const char *name); | 183 | struct file *lookup_file(const char *name); |
183 | 184 | ||
184 | extern struct symbol symbol_yes, symbol_no, symbol_mod; | 185 | extern struct symbol symbol_yes, symbol_no, symbol_mod; |
185 | extern struct symbol *modules_sym; | 186 | extern struct symbol *modules_sym; |
186 | extern struct symbol *sym_defconfig_list; | 187 | extern struct symbol *sym_defconfig_list; |
187 | extern int cdebug; | 188 | extern int cdebug; |
188 | struct expr *expr_alloc_symbol(struct symbol *sym); | 189 | struct expr *expr_alloc_symbol(struct symbol *sym); |
189 | struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); | 190 | struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); |
190 | struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); | 191 | struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); |
191 | struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); | 192 | struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); |
192 | struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); | 193 | struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); |
193 | struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); | 194 | struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); |
194 | struct expr *expr_copy(struct expr *org); | 195 | struct expr *expr_copy(struct expr *org); |
195 | void expr_free(struct expr *e); | 196 | void expr_free(struct expr *e); |
196 | int expr_eq(struct expr *e1, struct expr *e2); | 197 | int expr_eq(struct expr *e1, struct expr *e2); |
197 | void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); | 198 | void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); |
198 | tristate expr_calc_value(struct expr *e); | 199 | tristate expr_calc_value(struct expr *e); |
199 | struct expr *expr_eliminate_yn(struct expr *e); | 200 | struct expr *expr_eliminate_yn(struct expr *e); |
200 | struct expr *expr_trans_bool(struct expr *e); | 201 | struct expr *expr_trans_bool(struct expr *e); |
201 | struct expr *expr_eliminate_dups(struct expr *e); | 202 | struct expr *expr_eliminate_dups(struct expr *e); |
202 | struct expr *expr_transform(struct expr *e); | 203 | struct expr *expr_transform(struct expr *e); |
203 | int expr_contains_symbol(struct expr *dep, struct symbol *sym); | 204 | int expr_contains_symbol(struct expr *dep, struct symbol *sym); |
204 | bool expr_depends_symbol(struct expr *dep, struct symbol *sym); | 205 | bool expr_depends_symbol(struct expr *dep, struct symbol *sym); |
205 | struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); | 206 | struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); |
206 | struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); | 207 | struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); |
207 | void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); | 208 | void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); |
208 | struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); | 209 | struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); |
209 | 210 | ||
210 | void expr_fprint(struct expr *e, FILE *out); | 211 | void expr_fprint(struct expr *e, FILE *out); |
211 | struct gstr; /* forward */ | 212 | struct gstr; /* forward */ |
212 | void expr_gstr_print(struct expr *e, struct gstr *gs); | 213 | void expr_gstr_print(struct expr *e, struct gstr *gs); |
213 | 214 | ||
214 | static inline int expr_is_yes(struct expr *e) | 215 | static inline int expr_is_yes(struct expr *e) |
215 | { | 216 | { |
216 | return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); | 217 | return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); |
217 | } | 218 | } |
218 | 219 | ||
219 | static inline int expr_is_no(struct expr *e) | 220 | static inline int expr_is_no(struct expr *e) |
220 | { | 221 | { |
221 | return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); | 222 | return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); |
222 | } | 223 | } |
223 | #endif | 224 | #endif |
224 | 225 | ||
225 | #ifdef __cplusplus | 226 | #ifdef __cplusplus |
226 | } | 227 | } |
227 | #endif | 228 | #endif |
228 | 229 | ||
229 | #endif /* EXPR_H */ | 230 | #endif /* EXPR_H */ |
230 | 231 |
scripts/kconfig/menu.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | 2 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |
3 | * Released under the terms of the GNU GPL v2.0. | 3 | * Released under the terms of the GNU GPL v2.0. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
7 | #include <string.h> | 7 | #include <string.h> |
8 | 8 | ||
9 | #define LKC_DIRECT_LINK | 9 | #define LKC_DIRECT_LINK |
10 | #include "lkc.h" | 10 | #include "lkc.h" |
11 | 11 | ||
12 | static const char nohelp_text[] = N_( | 12 | static const char nohelp_text[] = N_( |
13 | "There is no help available for this kernel option.\n"); | 13 | "There is no help available for this kernel option.\n"); |
14 | 14 | ||
15 | struct menu rootmenu; | 15 | struct menu rootmenu; |
16 | static struct menu **last_entry_ptr; | 16 | static struct menu **last_entry_ptr; |
17 | 17 | ||
18 | struct file *file_list; | 18 | struct file *file_list; |
19 | struct file *current_file; | 19 | struct file *current_file; |
20 | 20 | ||
21 | void menu_warn(struct menu *menu, const char *fmt, ...) | 21 | void menu_warn(struct menu *menu, const char *fmt, ...) |
22 | { | 22 | { |
23 | va_list ap; | 23 | va_list ap; |
24 | va_start(ap, fmt); | 24 | va_start(ap, fmt); |
25 | fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); | 25 | fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); |
26 | vfprintf(stderr, fmt, ap); | 26 | vfprintf(stderr, fmt, ap); |
27 | fprintf(stderr, "\n"); | 27 | fprintf(stderr, "\n"); |
28 | va_end(ap); | 28 | va_end(ap); |
29 | } | 29 | } |
30 | 30 | ||
31 | static void prop_warn(struct property *prop, const char *fmt, ...) | 31 | static void prop_warn(struct property *prop, const char *fmt, ...) |
32 | { | 32 | { |
33 | va_list ap; | 33 | va_list ap; |
34 | va_start(ap, fmt); | 34 | va_start(ap, fmt); |
35 | fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); | 35 | fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); |
36 | vfprintf(stderr, fmt, ap); | 36 | vfprintf(stderr, fmt, ap); |
37 | fprintf(stderr, "\n"); | 37 | fprintf(stderr, "\n"); |
38 | va_end(ap); | 38 | va_end(ap); |
39 | } | 39 | } |
40 | 40 | ||
41 | void _menu_init(void) | 41 | void _menu_init(void) |
42 | { | 42 | { |
43 | current_entry = current_menu = &rootmenu; | 43 | current_entry = current_menu = &rootmenu; |
44 | last_entry_ptr = &rootmenu.list; | 44 | last_entry_ptr = &rootmenu.list; |
45 | } | 45 | } |
46 | 46 | ||
47 | void menu_add_entry(struct symbol *sym) | 47 | void menu_add_entry(struct symbol *sym) |
48 | { | 48 | { |
49 | struct menu *menu; | 49 | struct menu *menu; |
50 | 50 | ||
51 | menu = malloc(sizeof(*menu)); | 51 | menu = malloc(sizeof(*menu)); |
52 | memset(menu, 0, sizeof(*menu)); | 52 | memset(menu, 0, sizeof(*menu)); |
53 | menu->sym = sym; | 53 | menu->sym = sym; |
54 | menu->parent = current_menu; | 54 | menu->parent = current_menu; |
55 | menu->file = current_file; | 55 | menu->file = current_file; |
56 | menu->lineno = zconf_lineno(); | 56 | menu->lineno = zconf_lineno(); |
57 | 57 | ||
58 | *last_entry_ptr = menu; | 58 | *last_entry_ptr = menu; |
59 | last_entry_ptr = &menu->next; | 59 | last_entry_ptr = &menu->next; |
60 | current_entry = menu; | 60 | current_entry = menu; |
61 | if (sym) | ||
62 | menu_add_symbol(P_SYMBOL, sym, NULL); | ||
61 | } | 63 | } |
62 | 64 | ||
63 | void menu_end_entry(void) | 65 | void menu_end_entry(void) |
64 | { | 66 | { |
65 | } | 67 | } |
66 | 68 | ||
67 | struct menu *menu_add_menu(void) | 69 | struct menu *menu_add_menu(void) |
68 | { | 70 | { |
69 | menu_end_entry(); | 71 | menu_end_entry(); |
70 | last_entry_ptr = ¤t_entry->list; | 72 | last_entry_ptr = ¤t_entry->list; |
71 | return current_menu = current_entry; | 73 | return current_menu = current_entry; |
72 | } | 74 | } |
73 | 75 | ||
74 | void menu_end_menu(void) | 76 | void menu_end_menu(void) |
75 | { | 77 | { |
76 | last_entry_ptr = ¤t_menu->next; | 78 | last_entry_ptr = ¤t_menu->next; |
77 | current_menu = current_menu->parent; | 79 | current_menu = current_menu->parent; |
78 | } | 80 | } |
79 | 81 | ||
80 | static struct expr *menu_check_dep(struct expr *e) | 82 | static struct expr *menu_check_dep(struct expr *e) |
81 | { | 83 | { |
82 | if (!e) | 84 | if (!e) |
83 | return e; | 85 | return e; |
84 | 86 | ||
85 | switch (e->type) { | 87 | switch (e->type) { |
86 | case E_NOT: | 88 | case E_NOT: |
87 | e->left.expr = menu_check_dep(e->left.expr); | 89 | e->left.expr = menu_check_dep(e->left.expr); |
88 | break; | 90 | break; |
89 | case E_OR: | 91 | case E_OR: |
90 | case E_AND: | 92 | case E_AND: |
91 | e->left.expr = menu_check_dep(e->left.expr); | 93 | e->left.expr = menu_check_dep(e->left.expr); |
92 | e->right.expr = menu_check_dep(e->right.expr); | 94 | e->right.expr = menu_check_dep(e->right.expr); |
93 | break; | 95 | break; |
94 | case E_SYMBOL: | 96 | case E_SYMBOL: |
95 | /* change 'm' into 'm' && MODULES */ | 97 | /* change 'm' into 'm' && MODULES */ |
96 | if (e->left.sym == &symbol_mod) | 98 | if (e->left.sym == &symbol_mod) |
97 | return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); | 99 | return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); |
98 | break; | 100 | break; |
99 | default: | 101 | default: |
100 | break; | 102 | break; |
101 | } | 103 | } |
102 | return e; | 104 | return e; |
103 | } | 105 | } |
104 | 106 | ||
105 | void menu_add_dep(struct expr *dep) | 107 | void menu_add_dep(struct expr *dep) |
106 | { | 108 | { |
107 | current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); | 109 | current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); |
108 | current_entry->dir_dep = current_entry->dep; | 110 | current_entry->dir_dep = current_entry->dep; |
109 | } | 111 | } |
110 | 112 | ||
111 | void menu_set_type(int type) | 113 | void menu_set_type(int type) |
112 | { | 114 | { |
113 | struct symbol *sym = current_entry->sym; | 115 | struct symbol *sym = current_entry->sym; |
114 | 116 | ||
115 | if (sym->type == type) | 117 | if (sym->type == type) |
116 | return; | 118 | return; |
117 | if (sym->type == S_UNKNOWN) { | 119 | if (sym->type == S_UNKNOWN) { |
118 | sym->type = type; | 120 | sym->type = type; |
119 | return; | 121 | return; |
120 | } | 122 | } |
121 | menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", | 123 | menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", |
122 | sym->name ? sym->name : "<choice>", | 124 | sym->name ? sym->name : "<choice>", |
123 | sym_type_name(sym->type), sym_type_name(type)); | 125 | sym_type_name(sym->type), sym_type_name(type)); |
124 | } | 126 | } |
125 | 127 | ||
126 | struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) | 128 | struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) |
127 | { | 129 | { |
128 | struct property *prop = prop_alloc(type, current_entry->sym); | 130 | struct property *prop = prop_alloc(type, current_entry->sym); |
129 | 131 | ||
130 | prop->menu = current_entry; | 132 | prop->menu = current_entry; |
131 | prop->expr = expr; | 133 | prop->expr = expr; |
132 | prop->visible.expr = menu_check_dep(dep); | 134 | prop->visible.expr = menu_check_dep(dep); |
133 | 135 | ||
134 | if (prompt) { | 136 | if (prompt) { |
135 | if (isspace(*prompt)) { | 137 | if (isspace(*prompt)) { |
136 | prop_warn(prop, "leading whitespace ignored"); | 138 | prop_warn(prop, "leading whitespace ignored"); |
137 | while (isspace(*prompt)) | 139 | while (isspace(*prompt)) |
138 | prompt++; | 140 | prompt++; |
139 | } | 141 | } |
140 | if (current_entry->prompt) | 142 | if (current_entry->prompt) |
141 | prop_warn(prop, "prompt redefined"); | 143 | prop_warn(prop, "prompt redefined"); |
142 | current_entry->prompt = prop; | 144 | current_entry->prompt = prop; |
143 | } | 145 | } |
144 | prop->text = prompt; | 146 | prop->text = prompt; |
145 | 147 | ||
146 | return prop; | 148 | return prop; |
147 | } | 149 | } |
148 | 150 | ||
149 | struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) | 151 | struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) |
150 | { | 152 | { |
151 | return menu_add_prop(type, prompt, NULL, dep); | 153 | return menu_add_prop(type, prompt, NULL, dep); |
152 | } | 154 | } |
153 | 155 | ||
154 | void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) | 156 | void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) |
155 | { | 157 | { |
156 | menu_add_prop(type, NULL, expr, dep); | 158 | menu_add_prop(type, NULL, expr, dep); |
157 | } | 159 | } |
158 | 160 | ||
159 | void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) | 161 | void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) |
160 | { | 162 | { |
161 | menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); | 163 | menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); |
162 | } | 164 | } |
163 | 165 | ||
164 | void menu_add_option(int token, char *arg) | 166 | void menu_add_option(int token, char *arg) |
165 | { | 167 | { |
166 | struct property *prop; | 168 | struct property *prop; |
167 | 169 | ||
168 | switch (token) { | 170 | switch (token) { |
169 | case T_OPT_MODULES: | 171 | case T_OPT_MODULES: |
170 | prop = prop_alloc(P_DEFAULT, modules_sym); | 172 | prop = prop_alloc(P_DEFAULT, modules_sym); |
171 | prop->expr = expr_alloc_symbol(current_entry->sym); | 173 | prop->expr = expr_alloc_symbol(current_entry->sym); |
172 | break; | 174 | break; |
173 | case T_OPT_DEFCONFIG_LIST: | 175 | case T_OPT_DEFCONFIG_LIST: |
174 | if (!sym_defconfig_list) | 176 | if (!sym_defconfig_list) |
175 | sym_defconfig_list = current_entry->sym; | 177 | sym_defconfig_list = current_entry->sym; |
176 | else if (sym_defconfig_list != current_entry->sym) | 178 | else if (sym_defconfig_list != current_entry->sym) |
177 | zconf_error("trying to redefine defconfig symbol"); | 179 | zconf_error("trying to redefine defconfig symbol"); |
178 | break; | 180 | break; |
179 | case T_OPT_ENV: | 181 | case T_OPT_ENV: |
180 | prop_add_env(arg); | 182 | prop_add_env(arg); |
181 | break; | 183 | break; |
182 | } | 184 | } |
183 | } | 185 | } |
184 | 186 | ||
185 | static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) | 187 | static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) |
186 | { | 188 | { |
187 | return sym2->type == S_INT || sym2->type == S_HEX || | 189 | return sym2->type == S_INT || sym2->type == S_HEX || |
188 | (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); | 190 | (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); |
189 | } | 191 | } |
190 | 192 | ||
191 | static void sym_check_prop(struct symbol *sym) | 193 | static void sym_check_prop(struct symbol *sym) |
192 | { | 194 | { |
193 | struct property *prop; | 195 | struct property *prop; |
194 | struct symbol *sym2; | 196 | struct symbol *sym2; |
195 | for (prop = sym->prop; prop; prop = prop->next) { | 197 | for (prop = sym->prop; prop; prop = prop->next) { |
196 | switch (prop->type) { | 198 | switch (prop->type) { |
197 | case P_DEFAULT: | 199 | case P_DEFAULT: |
198 | if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && | 200 | if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && |
199 | prop->expr->type != E_SYMBOL) | 201 | prop->expr->type != E_SYMBOL) |
200 | prop_warn(prop, | 202 | prop_warn(prop, |
201 | "default for config symbol '%s'" | 203 | "default for config symbol '%s'" |
202 | " must be a single symbol", sym->name); | 204 | " must be a single symbol", sym->name); |
203 | break; | 205 | break; |
204 | case P_SELECT: | 206 | case P_SELECT: |
205 | sym2 = prop_get_symbol(prop); | 207 | sym2 = prop_get_symbol(prop); |
206 | if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) | 208 | if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) |
207 | prop_warn(prop, | 209 | prop_warn(prop, |
208 | "config symbol '%s' uses select, but is " | 210 | "config symbol '%s' uses select, but is " |
209 | "not boolean or tristate", sym->name); | 211 | "not boolean or tristate", sym->name); |
210 | else if (sym2->type != S_UNKNOWN && | 212 | else if (sym2->type != S_UNKNOWN && |
211 | sym2->type != S_BOOLEAN && | 213 | sym2->type != S_BOOLEAN && |
212 | sym2->type != S_TRISTATE) | 214 | sym2->type != S_TRISTATE) |
213 | prop_warn(prop, | 215 | prop_warn(prop, |
214 | "'%s' has wrong type. 'select' only " | 216 | "'%s' has wrong type. 'select' only " |
215 | "accept arguments of boolean and " | 217 | "accept arguments of boolean and " |
216 | "tristate type", sym2->name); | 218 | "tristate type", sym2->name); |
217 | break; | 219 | break; |
218 | case P_RANGE: | 220 | case P_RANGE: |
219 | if (sym->type != S_INT && sym->type != S_HEX) | 221 | if (sym->type != S_INT && sym->type != S_HEX) |
220 | prop_warn(prop, "range is only allowed " | 222 | prop_warn(prop, "range is only allowed " |
221 | "for int or hex symbols"); | 223 | "for int or hex symbols"); |
222 | if (!menu_range_valid_sym(sym, prop->expr->left.sym) || | 224 | if (!menu_range_valid_sym(sym, prop->expr->left.sym) || |
223 | !menu_range_valid_sym(sym, prop->expr->right.sym)) | 225 | !menu_range_valid_sym(sym, prop->expr->right.sym)) |
224 | prop_warn(prop, "range is invalid"); | 226 | prop_warn(prop, "range is invalid"); |
225 | break; | 227 | break; |
226 | default: | 228 | default: |
227 | ; | 229 | ; |
228 | } | 230 | } |
229 | } | 231 | } |
230 | } | 232 | } |
231 | 233 | ||
232 | void menu_finalize(struct menu *parent) | 234 | void menu_finalize(struct menu *parent) |
233 | { | 235 | { |
234 | struct menu *menu, *last_menu; | 236 | struct menu *menu, *last_menu; |
235 | struct symbol *sym; | 237 | struct symbol *sym; |
236 | struct property *prop; | 238 | struct property *prop; |
237 | struct expr *parentdep, *basedep, *dep, *dep2, **ep; | 239 | struct expr *parentdep, *basedep, *dep, *dep2, **ep; |
238 | 240 | ||
239 | sym = parent->sym; | 241 | sym = parent->sym; |
240 | if (parent->list) { | 242 | if (parent->list) { |
241 | if (sym && sym_is_choice(sym)) { | 243 | if (sym && sym_is_choice(sym)) { |
242 | if (sym->type == S_UNKNOWN) { | 244 | if (sym->type == S_UNKNOWN) { |
243 | /* find the first choice value to find out choice type */ | 245 | /* find the first choice value to find out choice type */ |
244 | current_entry = parent; | 246 | current_entry = parent; |
245 | for (menu = parent->list; menu; menu = menu->next) { | 247 | for (menu = parent->list; menu; menu = menu->next) { |
246 | if (menu->sym && menu->sym->type != S_UNKNOWN) { | 248 | if (menu->sym && menu->sym->type != S_UNKNOWN) { |
247 | menu_set_type(menu->sym->type); | 249 | menu_set_type(menu->sym->type); |
248 | break; | 250 | break; |
249 | } | 251 | } |
250 | } | 252 | } |
251 | } | 253 | } |
252 | /* set the type of the remaining choice values */ | 254 | /* set the type of the remaining choice values */ |
253 | for (menu = parent->list; menu; menu = menu->next) { | 255 | for (menu = parent->list; menu; menu = menu->next) { |
254 | current_entry = menu; | 256 | current_entry = menu; |
255 | if (menu->sym && menu->sym->type == S_UNKNOWN) | 257 | if (menu->sym && menu->sym->type == S_UNKNOWN) |
256 | menu_set_type(sym->type); | 258 | menu_set_type(sym->type); |
257 | } | 259 | } |
258 | parentdep = expr_alloc_symbol(sym); | 260 | parentdep = expr_alloc_symbol(sym); |
259 | } else if (parent->prompt) | 261 | } else if (parent->prompt) |
260 | parentdep = parent->prompt->visible.expr; | 262 | parentdep = parent->prompt->visible.expr; |
261 | else | 263 | else |
262 | parentdep = parent->dep; | 264 | parentdep = parent->dep; |
263 | 265 | ||
264 | for (menu = parent->list; menu; menu = menu->next) { | 266 | for (menu = parent->list; menu; menu = menu->next) { |
265 | basedep = expr_transform(menu->dep); | 267 | basedep = expr_transform(menu->dep); |
266 | basedep = expr_alloc_and(expr_copy(parentdep), basedep); | 268 | basedep = expr_alloc_and(expr_copy(parentdep), basedep); |
267 | basedep = expr_eliminate_dups(basedep); | 269 | basedep = expr_eliminate_dups(basedep); |
268 | menu->dep = basedep; | 270 | menu->dep = basedep; |
269 | if (menu->sym) | 271 | if (menu->sym) |
270 | prop = menu->sym->prop; | 272 | prop = menu->sym->prop; |
271 | else | 273 | else |
272 | prop = menu->prompt; | 274 | prop = menu->prompt; |
273 | for (; prop; prop = prop->next) { | 275 | for (; prop; prop = prop->next) { |
274 | if (prop->menu != menu) | 276 | if (prop->menu != menu) |
275 | continue; | 277 | continue; |
276 | dep = expr_transform(prop->visible.expr); | 278 | dep = expr_transform(prop->visible.expr); |
277 | dep = expr_alloc_and(expr_copy(basedep), dep); | 279 | dep = expr_alloc_and(expr_copy(basedep), dep); |
278 | dep = expr_eliminate_dups(dep); | 280 | dep = expr_eliminate_dups(dep); |
279 | if (menu->sym && menu->sym->type != S_TRISTATE) | 281 | if (menu->sym && menu->sym->type != S_TRISTATE) |
280 | dep = expr_trans_bool(dep); | 282 | dep = expr_trans_bool(dep); |
281 | prop->visible.expr = dep; | 283 | prop->visible.expr = dep; |
282 | if (prop->type == P_SELECT) { | 284 | if (prop->type == P_SELECT) { |
283 | struct symbol *es = prop_get_symbol(prop); | 285 | struct symbol *es = prop_get_symbol(prop); |
284 | es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, | 286 | es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, |
285 | expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); | 287 | expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); |
286 | } | 288 | } |
287 | } | 289 | } |
288 | } | 290 | } |
289 | for (menu = parent->list; menu; menu = menu->next) | 291 | for (menu = parent->list; menu; menu = menu->next) |
290 | menu_finalize(menu); | 292 | menu_finalize(menu); |
291 | } else if (sym) { | 293 | } else if (sym) { |
292 | /* ignore inherited dependencies for dir_dep */ | 294 | /* ignore inherited dependencies for dir_dep */ |
293 | sym->dir_dep.expr = expr_transform(expr_copy(parent->dir_dep)); | 295 | sym->dir_dep.expr = expr_transform(expr_copy(parent->dir_dep)); |
294 | sym->dir_dep.expr = expr_eliminate_dups(sym->dir_dep.expr); | 296 | sym->dir_dep.expr = expr_eliminate_dups(sym->dir_dep.expr); |
295 | 297 | ||
296 | basedep = parent->prompt ? parent->prompt->visible.expr : NULL; | 298 | basedep = parent->prompt ? parent->prompt->visible.expr : NULL; |
297 | basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); | 299 | basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); |
298 | basedep = expr_eliminate_dups(expr_transform(basedep)); | 300 | basedep = expr_eliminate_dups(expr_transform(basedep)); |
299 | last_menu = NULL; | 301 | last_menu = NULL; |
300 | for (menu = parent->next; menu; menu = menu->next) { | 302 | for (menu = parent->next; menu; menu = menu->next) { |
301 | dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; | 303 | dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; |
302 | if (!expr_contains_symbol(dep, sym)) | 304 | if (!expr_contains_symbol(dep, sym)) |
303 | break; | 305 | break; |
304 | if (expr_depends_symbol(dep, sym)) | 306 | if (expr_depends_symbol(dep, sym)) |
305 | goto next; | 307 | goto next; |
306 | dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); | 308 | dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); |
307 | dep = expr_eliminate_dups(expr_transform(dep)); | 309 | dep = expr_eliminate_dups(expr_transform(dep)); |
308 | dep2 = expr_copy(basedep); | 310 | dep2 = expr_copy(basedep); |
309 | expr_eliminate_eq(&dep, &dep2); | 311 | expr_eliminate_eq(&dep, &dep2); |
310 | expr_free(dep); | 312 | expr_free(dep); |
311 | if (!expr_is_yes(dep2)) { | 313 | if (!expr_is_yes(dep2)) { |
312 | expr_free(dep2); | 314 | expr_free(dep2); |
313 | break; | 315 | break; |
314 | } | 316 | } |
315 | expr_free(dep2); | 317 | expr_free(dep2); |
316 | next: | 318 | next: |
317 | menu_finalize(menu); | 319 | menu_finalize(menu); |
318 | menu->parent = parent; | 320 | menu->parent = parent; |
319 | last_menu = menu; | 321 | last_menu = menu; |
320 | } | 322 | } |
321 | if (last_menu) { | 323 | if (last_menu) { |
322 | parent->list = parent->next; | 324 | parent->list = parent->next; |
323 | parent->next = last_menu->next; | 325 | parent->next = last_menu->next; |
324 | last_menu->next = NULL; | 326 | last_menu->next = NULL; |
325 | } | 327 | } |
326 | } | 328 | } |
327 | for (menu = parent->list; menu; menu = menu->next) { | 329 | for (menu = parent->list; menu; menu = menu->next) { |
328 | if (sym && sym_is_choice(sym) && | 330 | if (sym && sym_is_choice(sym) && |
329 | menu->sym && !sym_is_choice_value(menu->sym)) { | 331 | menu->sym && !sym_is_choice_value(menu->sym)) { |
330 | current_entry = menu; | 332 | current_entry = menu; |
331 | menu->sym->flags |= SYMBOL_CHOICEVAL; | 333 | menu->sym->flags |= SYMBOL_CHOICEVAL; |
332 | if (!menu->prompt) | 334 | if (!menu->prompt) |
333 | menu_warn(menu, "choice value must have a prompt"); | 335 | menu_warn(menu, "choice value must have a prompt"); |
334 | for (prop = menu->sym->prop; prop; prop = prop->next) { | 336 | for (prop = menu->sym->prop; prop; prop = prop->next) { |
335 | if (prop->type == P_DEFAULT) | 337 | if (prop->type == P_DEFAULT) |
336 | prop_warn(prop, "defaults for choice " | 338 | prop_warn(prop, "defaults for choice " |
337 | "values not supported"); | 339 | "values not supported"); |
338 | if (prop->menu == menu) | 340 | if (prop->menu == menu) |
339 | continue; | 341 | continue; |
340 | if (prop->type == P_PROMPT && | 342 | if (prop->type == P_PROMPT && |
341 | prop->menu->parent->sym != sym) | 343 | prop->menu->parent->sym != sym) |
342 | prop_warn(prop, "choice value used outside its choice group"); | 344 | prop_warn(prop, "choice value used outside its choice group"); |
343 | } | 345 | } |
344 | /* Non-tristate choice values of tristate choices must | 346 | /* Non-tristate choice values of tristate choices must |
345 | * depend on the choice being set to Y. The choice | 347 | * depend on the choice being set to Y. The choice |
346 | * values' dependencies were propagated to their | 348 | * values' dependencies were propagated to their |
347 | * properties above, so the change here must be re- | 349 | * properties above, so the change here must be re- |
348 | * propagated. | 350 | * propagated. |
349 | */ | 351 | */ |
350 | if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { | 352 | if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { |
351 | basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); | 353 | basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); |
352 | menu->dep = expr_alloc_and(basedep, menu->dep); | 354 | menu->dep = expr_alloc_and(basedep, menu->dep); |
353 | for (prop = menu->sym->prop; prop; prop = prop->next) { | 355 | for (prop = menu->sym->prop; prop; prop = prop->next) { |
354 | if (prop->menu != menu) | 356 | if (prop->menu != menu) |
355 | continue; | 357 | continue; |
356 | prop->visible.expr = expr_alloc_and(expr_copy(basedep), | 358 | prop->visible.expr = expr_alloc_and(expr_copy(basedep), |
357 | prop->visible.expr); | 359 | prop->visible.expr); |
358 | } | 360 | } |
359 | } | 361 | } |
360 | menu_add_symbol(P_CHOICE, sym, NULL); | 362 | menu_add_symbol(P_CHOICE, sym, NULL); |
361 | prop = sym_get_choice_prop(sym); | 363 | prop = sym_get_choice_prop(sym); |
362 | for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) | 364 | for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) |
363 | ; | 365 | ; |
364 | *ep = expr_alloc_one(E_LIST, NULL); | 366 | *ep = expr_alloc_one(E_LIST, NULL); |
365 | (*ep)->right.sym = menu->sym; | 367 | (*ep)->right.sym = menu->sym; |
366 | } | 368 | } |
367 | if (menu->list && (!menu->prompt || !menu->prompt->text)) { | 369 | if (menu->list && (!menu->prompt || !menu->prompt->text)) { |
368 | for (last_menu = menu->list; ; last_menu = last_menu->next) { | 370 | for (last_menu = menu->list; ; last_menu = last_menu->next) { |
369 | last_menu->parent = parent; | 371 | last_menu->parent = parent; |
370 | if (!last_menu->next) | 372 | if (!last_menu->next) |
371 | break; | 373 | break; |
372 | } | 374 | } |
373 | last_menu->next = menu->next; | 375 | last_menu->next = menu->next; |
374 | menu->next = menu->list; | 376 | menu->next = menu->list; |
375 | menu->list = NULL; | 377 | menu->list = NULL; |
376 | } | 378 | } |
377 | } | 379 | } |
378 | 380 | ||
379 | if (sym && !(sym->flags & SYMBOL_WARNED)) { | 381 | if (sym && !(sym->flags & SYMBOL_WARNED)) { |
380 | if (sym->type == S_UNKNOWN) | 382 | if (sym->type == S_UNKNOWN) |
381 | menu_warn(parent, "config symbol defined without type"); | 383 | menu_warn(parent, "config symbol defined without type"); |
382 | 384 | ||
383 | if (sym_is_choice(sym) && !parent->prompt) | 385 | if (sym_is_choice(sym) && !parent->prompt) |
384 | menu_warn(parent, "choice must have a prompt"); | 386 | menu_warn(parent, "choice must have a prompt"); |
385 | 387 | ||
386 | /* Check properties connected to this symbol */ | 388 | /* Check properties connected to this symbol */ |
387 | sym_check_prop(sym); | 389 | sym_check_prop(sym); |
388 | sym->flags |= SYMBOL_WARNED; | 390 | sym->flags |= SYMBOL_WARNED; |
389 | } | 391 | } |
390 | 392 | ||
391 | if (sym && !sym_is_optional(sym) && parent->prompt) { | 393 | if (sym && !sym_is_optional(sym) && parent->prompt) { |
392 | sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, | 394 | sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, |
393 | expr_alloc_and(parent->prompt->visible.expr, | 395 | expr_alloc_and(parent->prompt->visible.expr, |
394 | expr_alloc_symbol(&symbol_mod))); | 396 | expr_alloc_symbol(&symbol_mod))); |
395 | } | 397 | } |
396 | } | 398 | } |
397 | 399 | ||
398 | bool menu_has_prompt(struct menu *menu) | 400 | bool menu_has_prompt(struct menu *menu) |
399 | { | 401 | { |
400 | if (!menu->prompt) | 402 | if (!menu->prompt) |
401 | return false; | 403 | return false; |
402 | return true; | 404 | return true; |
403 | } | 405 | } |
404 | 406 | ||
405 | bool menu_is_visible(struct menu *menu) | 407 | bool menu_is_visible(struct menu *menu) |
406 | { | 408 | { |
407 | struct menu *child; | 409 | struct menu *child; |
408 | struct symbol *sym; | 410 | struct symbol *sym; |
409 | tristate visible; | 411 | tristate visible; |
410 | 412 | ||
411 | if (!menu->prompt) | 413 | if (!menu->prompt) |
412 | return false; | 414 | return false; |
413 | 415 | ||
414 | sym = menu->sym; | 416 | sym = menu->sym; |
415 | if (sym) { | 417 | if (sym) { |
416 | sym_calc_value(sym); | 418 | sym_calc_value(sym); |
417 | visible = menu->prompt->visible.tri; | 419 | visible = menu->prompt->visible.tri; |
418 | } else | 420 | } else |
419 | visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); | 421 | visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); |
420 | 422 | ||
421 | if (visible != no) | 423 | if (visible != no) |
422 | return true; | 424 | return true; |
423 | 425 | ||
424 | if (!sym || sym_get_tristate_value(menu->sym) == no) | 426 | if (!sym || sym_get_tristate_value(menu->sym) == no) |
425 | return false; | 427 | return false; |
426 | 428 | ||
427 | for (child = menu->list; child; child = child->next) { | 429 | for (child = menu->list; child; child = child->next) { |
428 | if (menu_is_visible(child)) { | 430 | if (menu_is_visible(child)) { |
429 | if (sym) | 431 | if (sym) |
430 | sym->flags |= SYMBOL_DEF_USER; | 432 | sym->flags |= SYMBOL_DEF_USER; |
431 | return true; | 433 | return true; |
432 | } | 434 | } |
433 | } | 435 | } |
434 | 436 | ||
435 | return false; | 437 | return false; |
436 | } | 438 | } |
437 | 439 | ||
438 | const char *menu_get_prompt(struct menu *menu) | 440 | const char *menu_get_prompt(struct menu *menu) |
439 | { | 441 | { |
440 | if (menu->prompt) | 442 | if (menu->prompt) |
441 | return menu->prompt->text; | 443 | return menu->prompt->text; |
442 | else if (menu->sym) | 444 | else if (menu->sym) |
443 | return menu->sym->name; | 445 | return menu->sym->name; |
444 | return NULL; | 446 | return NULL; |
445 | } | 447 | } |
446 | 448 | ||
447 | struct menu *menu_get_root_menu(struct menu *menu) | 449 | struct menu *menu_get_root_menu(struct menu *menu) |
448 | { | 450 | { |
449 | return &rootmenu; | 451 | return &rootmenu; |
450 | } | 452 | } |
451 | 453 | ||
452 | struct menu *menu_get_parent_menu(struct menu *menu) | 454 | struct menu *menu_get_parent_menu(struct menu *menu) |
453 | { | 455 | { |
454 | enum prop_type type; | 456 | enum prop_type type; |
455 | 457 | ||
456 | for (; menu != &rootmenu; menu = menu->parent) { | 458 | for (; menu != &rootmenu; menu = menu->parent) { |
457 | type = menu->prompt ? menu->prompt->type : 0; | 459 | type = menu->prompt ? menu->prompt->type : 0; |
458 | if (type == P_MENU) | 460 | if (type == P_MENU) |
459 | break; | 461 | break; |
460 | } | 462 | } |
461 | return menu; | 463 | return menu; |
462 | } | 464 | } |
463 | 465 | ||
464 | bool menu_has_help(struct menu *menu) | 466 | bool menu_has_help(struct menu *menu) |
465 | { | 467 | { |
466 | return menu->help != NULL; | 468 | return menu->help != NULL; |
467 | } | 469 | } |
468 | 470 | ||
469 | const char *menu_get_help(struct menu *menu) | 471 | const char *menu_get_help(struct menu *menu) |
470 | { | 472 | { |
471 | if (menu->help) | 473 | if (menu->help) |
472 | return menu->help; | 474 | return menu->help; |
473 | else | 475 | else |
474 | return ""; | 476 | return ""; |
475 | } | 477 | } |
476 | 478 | ||
477 | static void get_prompt_str(struct gstr *r, struct property *prop) | 479 | static void get_prompt_str(struct gstr *r, struct property *prop) |
478 | { | 480 | { |
479 | int i, j; | 481 | int i, j; |
480 | struct menu *submenu[8], *menu; | 482 | struct menu *submenu[8], *menu; |
481 | 483 | ||
482 | str_printf(r, _("Prompt: %s\n"), _(prop->text)); | 484 | str_printf(r, _("Prompt: %s\n"), _(prop->text)); |
483 | str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, | 485 | str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, |
484 | prop->menu->lineno); | 486 | prop->menu->lineno); |
485 | if (!expr_is_yes(prop->visible.expr)) { | 487 | if (!expr_is_yes(prop->visible.expr)) { |
486 | str_append(r, _(" Depends on: ")); | 488 | str_append(r, _(" Depends on: ")); |
487 | expr_gstr_print(prop->visible.expr, r); | 489 | expr_gstr_print(prop->visible.expr, r); |
488 | str_append(r, "\n"); | 490 | str_append(r, "\n"); |
489 | } | 491 | } |
490 | menu = prop->menu->parent; | 492 | menu = prop->menu->parent; |
491 | for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) | 493 | for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) |
492 | submenu[i++] = menu; | 494 | submenu[i++] = menu; |
493 | if (i > 0) { | 495 | if (i > 0) { |
494 | str_printf(r, _(" Location:\n")); | 496 | str_printf(r, _(" Location:\n")); |
495 | for (j = 4; --i >= 0; j += 2) { | 497 | for (j = 4; --i >= 0; j += 2) { |
496 | menu = submenu[i]; | 498 | menu = submenu[i]; |
497 | str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); | 499 | str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); |
498 | if (menu->sym) { | 500 | if (menu->sym) { |
499 | str_printf(r, " (%s [=%s])", menu->sym->name ? | 501 | str_printf(r, " (%s [=%s])", menu->sym->name ? |
500 | menu->sym->name : _("<choice>"), | 502 | menu->sym->name : _("<choice>"), |
501 | sym_get_string_value(menu->sym)); | 503 | sym_get_string_value(menu->sym)); |
502 | } | 504 | } |
503 | str_append(r, "\n"); | 505 | str_append(r, "\n"); |
504 | } | 506 | } |
505 | } | 507 | } |
506 | } | 508 | } |
507 | 509 | ||
508 | void get_symbol_str(struct gstr *r, struct symbol *sym) | 510 | void get_symbol_str(struct gstr *r, struct symbol *sym) |
509 | { | 511 | { |
510 | bool hit; | 512 | bool hit; |
511 | struct property *prop; | 513 | struct property *prop; |
512 | 514 | ||
513 | if (sym && sym->name) { | 515 | if (sym && sym->name) { |
514 | str_printf(r, "Symbol: %s [=%s]\n", sym->name, | 516 | str_printf(r, "Symbol: %s [=%s]\n", sym->name, |
515 | sym_get_string_value(sym)); | 517 | sym_get_string_value(sym)); |
516 | str_printf(r, "Type : %s\n", sym_type_name(sym->type)); | 518 | str_printf(r, "Type : %s\n", sym_type_name(sym->type)); |
517 | if (sym->type == S_INT || sym->type == S_HEX) { | 519 | if (sym->type == S_INT || sym->type == S_HEX) { |
518 | prop = sym_get_range_prop(sym); | 520 | prop = sym_get_range_prop(sym); |
519 | if (prop) { | 521 | if (prop) { |
520 | str_printf(r, "Range : "); | 522 | str_printf(r, "Range : "); |
521 | expr_gstr_print(prop->expr, r); | 523 | expr_gstr_print(prop->expr, r); |
522 | str_append(r, "\n"); | 524 | str_append(r, "\n"); |
523 | } | 525 | } |
524 | } | 526 | } |
525 | } | 527 | } |
526 | for_all_prompts(sym, prop) | 528 | for_all_prompts(sym, prop) |
527 | get_prompt_str(r, prop); | 529 | get_prompt_str(r, prop); |
528 | hit = false; | 530 | hit = false; |
529 | for_all_properties(sym, prop, P_SELECT) { | 531 | for_all_properties(sym, prop, P_SELECT) { |
530 | if (!hit) { | 532 | if (!hit) { |
531 | str_append(r, " Selects: "); | 533 | str_append(r, " Selects: "); |
532 | hit = true; | 534 | hit = true; |
533 | } else | 535 | } else |
534 | str_printf(r, " && "); | 536 | str_printf(r, " && "); |
535 | expr_gstr_print(prop->expr, r); | 537 | expr_gstr_print(prop->expr, r); |
536 | } | 538 | } |
537 | if (hit) | 539 | if (hit) |
538 | str_append(r, "\n"); | 540 | str_append(r, "\n"); |
539 | if (sym->rev_dep.expr) { | 541 | if (sym->rev_dep.expr) { |
540 | str_append(r, _(" Selected by: ")); | 542 | str_append(r, _(" Selected by: ")); |
541 | expr_gstr_print(sym->rev_dep.expr, r); | 543 | expr_gstr_print(sym->rev_dep.expr, r); |
542 | str_append(r, "\n"); | 544 | str_append(r, "\n"); |
543 | } | 545 | } |
544 | str_append(r, "\n\n"); | 546 | str_append(r, "\n\n"); |
545 | } | 547 | } |
546 | 548 | ||
547 | struct gstr get_relations_str(struct symbol **sym_arr) | 549 | struct gstr get_relations_str(struct symbol **sym_arr) |
548 | { | 550 | { |
549 | struct symbol *sym; | 551 | struct symbol *sym; |
550 | struct gstr res = str_new(); | 552 | struct gstr res = str_new(); |
551 | int i; | 553 | int i; |
552 | 554 | ||
553 | for (i = 0; sym_arr && (sym = sym_arr[i]); i++) | 555 | for (i = 0; sym_arr && (sym = sym_arr[i]); i++) |
554 | get_symbol_str(&res, sym); | 556 | get_symbol_str(&res, sym); |
555 | if (!i) | 557 | if (!i) |
556 | str_append(&res, _("No matches found.\n")); | 558 | str_append(&res, _("No matches found.\n")); |
557 | return res; | 559 | return res; |
558 | } | 560 | } |
559 | 561 | ||
560 | 562 | ||
561 | void menu_get_ext_help(struct menu *menu, struct gstr *help) | 563 | void menu_get_ext_help(struct menu *menu, struct gstr *help) |
562 | { | 564 | { |
563 | struct symbol *sym = menu->sym; | 565 | struct symbol *sym = menu->sym; |
564 | 566 | ||
565 | if (menu_has_help(menu)) { | 567 | if (menu_has_help(menu)) { |
566 | if (sym->name) { | 568 | if (sym->name) { |
567 | str_printf(help, "CONFIG_%s:\n\n", sym->name); | 569 | str_printf(help, "CONFIG_%s:\n\n", sym->name); |
568 | str_append(help, _(menu_get_help(menu))); | 570 | str_append(help, _(menu_get_help(menu))); |
569 | str_append(help, "\n"); | 571 | str_append(help, "\n"); |
570 | } | 572 | } |
571 | } else { | 573 | } else { |
572 | str_append(help, nohelp_text); | 574 | str_append(help, nohelp_text); |
573 | } | 575 | } |
574 | if (sym) | 576 | if (sym) |
575 | get_symbol_str(help, sym); | 577 | get_symbol_str(help, sym); |
576 | } | 578 | } |
577 | 579 |
scripts/kconfig/symbol.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | 2 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |
3 | * Released under the terms of the GNU GPL v2.0. | 3 | * Released under the terms of the GNU GPL v2.0. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <ctype.h> | 6 | #include <ctype.h> |
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include <string.h> | 8 | #include <string.h> |
9 | #include <regex.h> | 9 | #include <regex.h> |
10 | #include <sys/utsname.h> | 10 | #include <sys/utsname.h> |
11 | 11 | ||
12 | #define LKC_DIRECT_LINK | 12 | #define LKC_DIRECT_LINK |
13 | #include "lkc.h" | 13 | #include "lkc.h" |
14 | 14 | ||
15 | struct symbol symbol_yes = { | 15 | struct symbol symbol_yes = { |
16 | .name = "y", | 16 | .name = "y", |
17 | .curr = { "y", yes }, | 17 | .curr = { "y", yes }, |
18 | .flags = SYMBOL_CONST|SYMBOL_VALID, | 18 | .flags = SYMBOL_CONST|SYMBOL_VALID, |
19 | }, symbol_mod = { | 19 | }, symbol_mod = { |
20 | .name = "m", | 20 | .name = "m", |
21 | .curr = { "m", mod }, | 21 | .curr = { "m", mod }, |
22 | .flags = SYMBOL_CONST|SYMBOL_VALID, | 22 | .flags = SYMBOL_CONST|SYMBOL_VALID, |
23 | }, symbol_no = { | 23 | }, symbol_no = { |
24 | .name = "n", | 24 | .name = "n", |
25 | .curr = { "n", no }, | 25 | .curr = { "n", no }, |
26 | .flags = SYMBOL_CONST|SYMBOL_VALID, | 26 | .flags = SYMBOL_CONST|SYMBOL_VALID, |
27 | }, symbol_empty = { | 27 | }, symbol_empty = { |
28 | .name = "", | 28 | .name = "", |
29 | .curr = { "", no }, | 29 | .curr = { "", no }, |
30 | .flags = SYMBOL_VALID, | 30 | .flags = SYMBOL_VALID, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | struct symbol *sym_defconfig_list; | 33 | struct symbol *sym_defconfig_list; |
34 | struct symbol *modules_sym; | 34 | struct symbol *modules_sym; |
35 | tristate modules_val; | 35 | tristate modules_val; |
36 | 36 | ||
37 | struct expr *sym_env_list; | 37 | struct expr *sym_env_list; |
38 | 38 | ||
39 | static void sym_add_default(struct symbol *sym, const char *def) | 39 | static void sym_add_default(struct symbol *sym, const char *def) |
40 | { | 40 | { |
41 | struct property *prop = prop_alloc(P_DEFAULT, sym); | 41 | struct property *prop = prop_alloc(P_DEFAULT, sym); |
42 | 42 | ||
43 | prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); | 43 | prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); |
44 | } | 44 | } |
45 | 45 | ||
46 | void sym_init(void) | 46 | void sym_init(void) |
47 | { | 47 | { |
48 | struct symbol *sym; | 48 | struct symbol *sym; |
49 | struct utsname uts; | 49 | struct utsname uts; |
50 | static bool inited = false; | 50 | static bool inited = false; |
51 | 51 | ||
52 | if (inited) | 52 | if (inited) |
53 | return; | 53 | return; |
54 | inited = true; | 54 | inited = true; |
55 | 55 | ||
56 | uname(&uts); | 56 | uname(&uts); |
57 | 57 | ||
58 | sym = sym_lookup("UNAME_RELEASE", 0); | 58 | sym = sym_lookup("UNAME_RELEASE", 0); |
59 | sym->type = S_STRING; | 59 | sym->type = S_STRING; |
60 | sym->flags |= SYMBOL_AUTO; | 60 | sym->flags |= SYMBOL_AUTO; |
61 | sym_add_default(sym, uts.release); | 61 | sym_add_default(sym, uts.release); |
62 | } | 62 | } |
63 | 63 | ||
64 | enum symbol_type sym_get_type(struct symbol *sym) | 64 | enum symbol_type sym_get_type(struct symbol *sym) |
65 | { | 65 | { |
66 | enum symbol_type type = sym->type; | 66 | enum symbol_type type = sym->type; |
67 | 67 | ||
68 | if (type == S_TRISTATE) { | 68 | if (type == S_TRISTATE) { |
69 | if (sym_is_choice_value(sym) && sym->visible == yes) | 69 | if (sym_is_choice_value(sym) && sym->visible == yes) |
70 | type = S_BOOLEAN; | 70 | type = S_BOOLEAN; |
71 | else if (modules_val == no) | 71 | else if (modules_val == no) |
72 | type = S_BOOLEAN; | 72 | type = S_BOOLEAN; |
73 | } | 73 | } |
74 | return type; | 74 | return type; |
75 | } | 75 | } |
76 | 76 | ||
77 | const char *sym_type_name(enum symbol_type type) | 77 | const char *sym_type_name(enum symbol_type type) |
78 | { | 78 | { |
79 | switch (type) { | 79 | switch (type) { |
80 | case S_BOOLEAN: | 80 | case S_BOOLEAN: |
81 | return "boolean"; | 81 | return "boolean"; |
82 | case S_TRISTATE: | 82 | case S_TRISTATE: |
83 | return "tristate"; | 83 | return "tristate"; |
84 | case S_INT: | 84 | case S_INT: |
85 | return "integer"; | 85 | return "integer"; |
86 | case S_HEX: | 86 | case S_HEX: |
87 | return "hex"; | 87 | return "hex"; |
88 | case S_STRING: | 88 | case S_STRING: |
89 | return "string"; | 89 | return "string"; |
90 | case S_UNKNOWN: | 90 | case S_UNKNOWN: |
91 | return "unknown"; | 91 | return "unknown"; |
92 | case S_OTHER: | 92 | case S_OTHER: |
93 | break; | 93 | break; |
94 | } | 94 | } |
95 | return "???"; | 95 | return "???"; |
96 | } | 96 | } |
97 | 97 | ||
98 | struct property *sym_get_choice_prop(struct symbol *sym) | 98 | struct property *sym_get_choice_prop(struct symbol *sym) |
99 | { | 99 | { |
100 | struct property *prop; | 100 | struct property *prop; |
101 | 101 | ||
102 | for_all_choices(sym, prop) | 102 | for_all_choices(sym, prop) |
103 | return prop; | 103 | return prop; |
104 | return NULL; | 104 | return NULL; |
105 | } | 105 | } |
106 | 106 | ||
107 | struct property *sym_get_env_prop(struct symbol *sym) | 107 | struct property *sym_get_env_prop(struct symbol *sym) |
108 | { | 108 | { |
109 | struct property *prop; | 109 | struct property *prop; |
110 | 110 | ||
111 | for_all_properties(sym, prop, P_ENV) | 111 | for_all_properties(sym, prop, P_ENV) |
112 | return prop; | 112 | return prop; |
113 | return NULL; | 113 | return NULL; |
114 | } | 114 | } |
115 | 115 | ||
116 | struct property *sym_get_default_prop(struct symbol *sym) | 116 | struct property *sym_get_default_prop(struct symbol *sym) |
117 | { | 117 | { |
118 | struct property *prop; | 118 | struct property *prop; |
119 | 119 | ||
120 | for_all_defaults(sym, prop) { | 120 | for_all_defaults(sym, prop) { |
121 | prop->visible.tri = expr_calc_value(prop->visible.expr); | 121 | prop->visible.tri = expr_calc_value(prop->visible.expr); |
122 | if (prop->visible.tri != no) | 122 | if (prop->visible.tri != no) |
123 | return prop; | 123 | return prop; |
124 | } | 124 | } |
125 | return NULL; | 125 | return NULL; |
126 | } | 126 | } |
127 | 127 | ||
128 | static struct property *sym_get_range_prop(struct symbol *sym) | 128 | static struct property *sym_get_range_prop(struct symbol *sym) |
129 | { | 129 | { |
130 | struct property *prop; | 130 | struct property *prop; |
131 | 131 | ||
132 | for_all_properties(sym, prop, P_RANGE) { | 132 | for_all_properties(sym, prop, P_RANGE) { |
133 | prop->visible.tri = expr_calc_value(prop->visible.expr); | 133 | prop->visible.tri = expr_calc_value(prop->visible.expr); |
134 | if (prop->visible.tri != no) | 134 | if (prop->visible.tri != no) |
135 | return prop; | 135 | return prop; |
136 | } | 136 | } |
137 | return NULL; | 137 | return NULL; |
138 | } | 138 | } |
139 | 139 | ||
140 | static int sym_get_range_val(struct symbol *sym, int base) | 140 | static int sym_get_range_val(struct symbol *sym, int base) |
141 | { | 141 | { |
142 | sym_calc_value(sym); | 142 | sym_calc_value(sym); |
143 | switch (sym->type) { | 143 | switch (sym->type) { |
144 | case S_INT: | 144 | case S_INT: |
145 | base = 10; | 145 | base = 10; |
146 | break; | 146 | break; |
147 | case S_HEX: | 147 | case S_HEX: |
148 | base = 16; | 148 | base = 16; |
149 | break; | 149 | break; |
150 | default: | 150 | default: |
151 | break; | 151 | break; |
152 | } | 152 | } |
153 | return strtol(sym->curr.val, NULL, base); | 153 | return strtol(sym->curr.val, NULL, base); |
154 | } | 154 | } |
155 | 155 | ||
156 | static void sym_validate_range(struct symbol *sym) | 156 | static void sym_validate_range(struct symbol *sym) |
157 | { | 157 | { |
158 | struct property *prop; | 158 | struct property *prop; |
159 | int base, val, val2; | 159 | int base, val, val2; |
160 | char str[64]; | 160 | char str[64]; |
161 | 161 | ||
162 | switch (sym->type) { | 162 | switch (sym->type) { |
163 | case S_INT: | 163 | case S_INT: |
164 | base = 10; | 164 | base = 10; |
165 | break; | 165 | break; |
166 | case S_HEX: | 166 | case S_HEX: |
167 | base = 16; | 167 | base = 16; |
168 | break; | 168 | break; |
169 | default: | 169 | default: |
170 | return; | 170 | return; |
171 | } | 171 | } |
172 | prop = sym_get_range_prop(sym); | 172 | prop = sym_get_range_prop(sym); |
173 | if (!prop) | 173 | if (!prop) |
174 | return; | 174 | return; |
175 | val = strtol(sym->curr.val, NULL, base); | 175 | val = strtol(sym->curr.val, NULL, base); |
176 | val2 = sym_get_range_val(prop->expr->left.sym, base); | 176 | val2 = sym_get_range_val(prop->expr->left.sym, base); |
177 | if (val >= val2) { | 177 | if (val >= val2) { |
178 | val2 = sym_get_range_val(prop->expr->right.sym, base); | 178 | val2 = sym_get_range_val(prop->expr->right.sym, base); |
179 | if (val <= val2) | 179 | if (val <= val2) |
180 | return; | 180 | return; |
181 | } | 181 | } |
182 | if (sym->type == S_INT) | 182 | if (sym->type == S_INT) |
183 | sprintf(str, "%d", val2); | 183 | sprintf(str, "%d", val2); |
184 | else | 184 | else |
185 | sprintf(str, "0x%x", val2); | 185 | sprintf(str, "0x%x", val2); |
186 | sym->curr.val = strdup(str); | 186 | sym->curr.val = strdup(str); |
187 | } | 187 | } |
188 | 188 | ||
189 | static void sym_calc_visibility(struct symbol *sym) | 189 | static void sym_calc_visibility(struct symbol *sym) |
190 | { | 190 | { |
191 | struct property *prop; | 191 | struct property *prop; |
192 | tristate tri; | 192 | tristate tri; |
193 | 193 | ||
194 | /* any prompt visible? */ | 194 | /* any prompt visible? */ |
195 | tri = no; | 195 | tri = no; |
196 | for_all_prompts(sym, prop) { | 196 | for_all_prompts(sym, prop) { |
197 | prop->visible.tri = expr_calc_value(prop->visible.expr); | 197 | prop->visible.tri = expr_calc_value(prop->visible.expr); |
198 | tri = EXPR_OR(tri, prop->visible.tri); | 198 | tri = EXPR_OR(tri, prop->visible.tri); |
199 | } | 199 | } |
200 | if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) | 200 | if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) |
201 | tri = yes; | 201 | tri = yes; |
202 | if (sym->visible != tri) { | 202 | if (sym->visible != tri) { |
203 | sym->visible = tri; | 203 | sym->visible = tri; |
204 | sym_set_changed(sym); | 204 | sym_set_changed(sym); |
205 | } | 205 | } |
206 | if (sym_is_choice_value(sym)) | 206 | if (sym_is_choice_value(sym)) |
207 | return; | 207 | return; |
208 | /* defaulting to "yes" if no explicit "depends on" are given */ | 208 | /* defaulting to "yes" if no explicit "depends on" are given */ |
209 | tri = yes; | 209 | tri = yes; |
210 | if (sym->dir_dep.expr) | 210 | if (sym->dir_dep.expr) |
211 | tri = expr_calc_value(sym->dir_dep.expr); | 211 | tri = expr_calc_value(sym->dir_dep.expr); |
212 | if (tri == mod) | 212 | if (tri == mod) |
213 | tri = yes; | 213 | tri = yes; |
214 | if (sym->dir_dep.tri != tri) { | 214 | if (sym->dir_dep.tri != tri) { |
215 | sym->dir_dep.tri = tri; | 215 | sym->dir_dep.tri = tri; |
216 | sym_set_changed(sym); | 216 | sym_set_changed(sym); |
217 | } | 217 | } |
218 | tri = no; | 218 | tri = no; |
219 | if (sym->rev_dep.expr) | 219 | if (sym->rev_dep.expr) |
220 | tri = expr_calc_value(sym->rev_dep.expr); | 220 | tri = expr_calc_value(sym->rev_dep.expr); |
221 | if (tri == mod && sym_get_type(sym) == S_BOOLEAN) | 221 | if (tri == mod && sym_get_type(sym) == S_BOOLEAN) |
222 | tri = yes; | 222 | tri = yes; |
223 | if (sym->rev_dep.tri != tri) { | 223 | if (sym->rev_dep.tri != tri) { |
224 | sym->rev_dep.tri = tri; | 224 | sym->rev_dep.tri = tri; |
225 | sym_set_changed(sym); | 225 | sym_set_changed(sym); |
226 | } | 226 | } |
227 | } | 227 | } |
228 | 228 | ||
229 | static struct symbol *sym_calc_choice(struct symbol *sym) | 229 | static struct symbol *sym_calc_choice(struct symbol *sym) |
230 | { | 230 | { |
231 | struct symbol *def_sym; | 231 | struct symbol *def_sym; |
232 | struct property *prop; | 232 | struct property *prop; |
233 | struct expr *e; | 233 | struct expr *e; |
234 | 234 | ||
235 | /* first calculate all choice values' visibilities */ | 235 | /* first calculate all choice values' visibilities */ |
236 | prop = sym_get_choice_prop(sym); | 236 | prop = sym_get_choice_prop(sym); |
237 | expr_list_for_each_sym(prop->expr, e, def_sym) | 237 | expr_list_for_each_sym(prop->expr, e, def_sym) |
238 | sym_calc_visibility(def_sym); | 238 | sym_calc_visibility(def_sym); |
239 | 239 | ||
240 | /* is the user choice visible? */ | 240 | /* is the user choice visible? */ |
241 | def_sym = sym->def[S_DEF_USER].val; | 241 | def_sym = sym->def[S_DEF_USER].val; |
242 | if (def_sym && def_sym->visible != no) | 242 | if (def_sym && def_sym->visible != no) |
243 | return def_sym; | 243 | return def_sym; |
244 | 244 | ||
245 | /* any of the defaults visible? */ | 245 | /* any of the defaults visible? */ |
246 | for_all_defaults(sym, prop) { | 246 | for_all_defaults(sym, prop) { |
247 | prop->visible.tri = expr_calc_value(prop->visible.expr); | 247 | prop->visible.tri = expr_calc_value(prop->visible.expr); |
248 | if (prop->visible.tri == no) | 248 | if (prop->visible.tri == no) |
249 | continue; | 249 | continue; |
250 | def_sym = prop_get_symbol(prop); | 250 | def_sym = prop_get_symbol(prop); |
251 | if (def_sym->visible != no) | 251 | if (def_sym->visible != no) |
252 | return def_sym; | 252 | return def_sym; |
253 | } | 253 | } |
254 | 254 | ||
255 | /* just get the first visible value */ | 255 | /* just get the first visible value */ |
256 | prop = sym_get_choice_prop(sym); | 256 | prop = sym_get_choice_prop(sym); |
257 | expr_list_for_each_sym(prop->expr, e, def_sym) | 257 | expr_list_for_each_sym(prop->expr, e, def_sym) |
258 | if (def_sym->visible != no) | 258 | if (def_sym->visible != no) |
259 | return def_sym; | 259 | return def_sym; |
260 | 260 | ||
261 | /* no choice? reset tristate value */ | 261 | /* no choice? reset tristate value */ |
262 | sym->curr.tri = no; | 262 | sym->curr.tri = no; |
263 | return NULL; | 263 | return NULL; |
264 | } | 264 | } |
265 | 265 | ||
266 | void sym_calc_value(struct symbol *sym) | 266 | void sym_calc_value(struct symbol *sym) |
267 | { | 267 | { |
268 | struct symbol_value newval, oldval; | 268 | struct symbol_value newval, oldval; |
269 | struct property *prop; | 269 | struct property *prop; |
270 | struct expr *e; | 270 | struct expr *e; |
271 | 271 | ||
272 | if (!sym) | 272 | if (!sym) |
273 | return; | 273 | return; |
274 | 274 | ||
275 | if (sym->flags & SYMBOL_VALID) | 275 | if (sym->flags & SYMBOL_VALID) |
276 | return; | 276 | return; |
277 | sym->flags |= SYMBOL_VALID; | 277 | sym->flags |= SYMBOL_VALID; |
278 | 278 | ||
279 | oldval = sym->curr; | 279 | oldval = sym->curr; |
280 | 280 | ||
281 | switch (sym->type) { | 281 | switch (sym->type) { |
282 | case S_INT: | 282 | case S_INT: |
283 | case S_HEX: | 283 | case S_HEX: |
284 | case S_STRING: | 284 | case S_STRING: |
285 | newval = symbol_empty.curr; | 285 | newval = symbol_empty.curr; |
286 | break; | 286 | break; |
287 | case S_BOOLEAN: | 287 | case S_BOOLEAN: |
288 | case S_TRISTATE: | 288 | case S_TRISTATE: |
289 | newval = symbol_no.curr; | 289 | newval = symbol_no.curr; |
290 | break; | 290 | break; |
291 | default: | 291 | default: |
292 | sym->curr.val = sym->name; | 292 | sym->curr.val = sym->name; |
293 | sym->curr.tri = no; | 293 | sym->curr.tri = no; |
294 | return; | 294 | return; |
295 | } | 295 | } |
296 | if (!sym_is_choice_value(sym)) | 296 | if (!sym_is_choice_value(sym)) |
297 | sym->flags &= ~SYMBOL_WRITE; | 297 | sym->flags &= ~SYMBOL_WRITE; |
298 | 298 | ||
299 | sym_calc_visibility(sym); | 299 | sym_calc_visibility(sym); |
300 | 300 | ||
301 | /* set default if recursively called */ | 301 | /* set default if recursively called */ |
302 | sym->curr = newval; | 302 | sym->curr = newval; |
303 | 303 | ||
304 | switch (sym_get_type(sym)) { | 304 | switch (sym_get_type(sym)) { |
305 | case S_BOOLEAN: | 305 | case S_BOOLEAN: |
306 | case S_TRISTATE: | 306 | case S_TRISTATE: |
307 | if (sym_is_choice_value(sym) && sym->visible == yes) { | 307 | if (sym_is_choice_value(sym) && sym->visible == yes) { |
308 | prop = sym_get_choice_prop(sym); | 308 | prop = sym_get_choice_prop(sym); |
309 | newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; | 309 | newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; |
310 | } else { | 310 | } else { |
311 | if (sym->visible != no) { | 311 | if (sym->visible != no) { |
312 | /* if the symbol is visible use the user value | 312 | /* if the symbol is visible use the user value |
313 | * if available, otherwise try the default value | 313 | * if available, otherwise try the default value |
314 | */ | 314 | */ |
315 | sym->flags |= SYMBOL_WRITE; | 315 | sym->flags |= SYMBOL_WRITE; |
316 | if (sym_has_value(sym)) { | 316 | if (sym_has_value(sym)) { |
317 | newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, | 317 | newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, |
318 | sym->visible); | 318 | sym->visible); |
319 | goto calc_newval; | 319 | goto calc_newval; |
320 | } | 320 | } |
321 | } | 321 | } |
322 | if (sym->rev_dep.tri != no) | 322 | if (sym->rev_dep.tri != no) |
323 | sym->flags |= SYMBOL_WRITE; | 323 | sym->flags |= SYMBOL_WRITE; |
324 | if (!sym_is_choice(sym)) { | 324 | if (!sym_is_choice(sym)) { |
325 | prop = sym_get_default_prop(sym); | 325 | prop = sym_get_default_prop(sym); |
326 | if (prop) { | 326 | if (prop) { |
327 | sym->flags |= SYMBOL_WRITE; | 327 | sym->flags |= SYMBOL_WRITE; |
328 | newval.tri = EXPR_AND(expr_calc_value(prop->expr), | 328 | newval.tri = EXPR_AND(expr_calc_value(prop->expr), |
329 | prop->visible.tri); | 329 | prop->visible.tri); |
330 | } | 330 | } |
331 | } | 331 | } |
332 | calc_newval: | 332 | calc_newval: |
333 | if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { | 333 | if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { |
334 | fprintf(stderr, "warning: ("); | 334 | fprintf(stderr, "warning: ("); |
335 | expr_fprint(sym->rev_dep.expr, stderr); | 335 | expr_fprint(sym->rev_dep.expr, stderr); |
336 | fprintf(stderr, ") selects %s which has unmet direct dependencies (", | 336 | fprintf(stderr, ") selects %s which has unmet direct dependencies (", |
337 | sym->name); | 337 | sym->name); |
338 | expr_fprint(sym->dir_dep.expr, stderr); | 338 | expr_fprint(sym->dir_dep.expr, stderr); |
339 | fprintf(stderr, ")\n"); | 339 | fprintf(stderr, ")\n"); |
340 | } | 340 | } |
341 | newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); | 341 | newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); |
342 | } | 342 | } |
343 | if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) | 343 | if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) |
344 | newval.tri = yes; | 344 | newval.tri = yes; |
345 | break; | 345 | break; |
346 | case S_STRING: | 346 | case S_STRING: |
347 | case S_HEX: | 347 | case S_HEX: |
348 | case S_INT: | 348 | case S_INT: |
349 | if (sym->visible != no) { | 349 | if (sym->visible != no) { |
350 | sym->flags |= SYMBOL_WRITE; | 350 | sym->flags |= SYMBOL_WRITE; |
351 | if (sym_has_value(sym)) { | 351 | if (sym_has_value(sym)) { |
352 | newval.val = sym->def[S_DEF_USER].val; | 352 | newval.val = sym->def[S_DEF_USER].val; |
353 | break; | 353 | break; |
354 | } | 354 | } |
355 | } | 355 | } |
356 | prop = sym_get_default_prop(sym); | 356 | prop = sym_get_default_prop(sym); |
357 | if (prop) { | 357 | if (prop) { |
358 | struct symbol *ds = prop_get_symbol(prop); | 358 | struct symbol *ds = prop_get_symbol(prop); |
359 | if (ds) { | 359 | if (ds) { |
360 | sym->flags |= SYMBOL_WRITE; | 360 | sym->flags |= SYMBOL_WRITE; |
361 | sym_calc_value(ds); | 361 | sym_calc_value(ds); |
362 | newval.val = ds->curr.val; | 362 | newval.val = ds->curr.val; |
363 | } | 363 | } |
364 | } | 364 | } |
365 | break; | 365 | break; |
366 | default: | 366 | default: |
367 | ; | 367 | ; |
368 | } | 368 | } |
369 | 369 | ||
370 | sym->curr = newval; | 370 | sym->curr = newval; |
371 | if (sym_is_choice(sym) && newval.tri == yes) | 371 | if (sym_is_choice(sym) && newval.tri == yes) |
372 | sym->curr.val = sym_calc_choice(sym); | 372 | sym->curr.val = sym_calc_choice(sym); |
373 | sym_validate_range(sym); | 373 | sym_validate_range(sym); |
374 | 374 | ||
375 | if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { | 375 | if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { |
376 | sym_set_changed(sym); | 376 | sym_set_changed(sym); |
377 | if (modules_sym == sym) { | 377 | if (modules_sym == sym) { |
378 | sym_set_all_changed(); | 378 | sym_set_all_changed(); |
379 | modules_val = modules_sym->curr.tri; | 379 | modules_val = modules_sym->curr.tri; |
380 | } | 380 | } |
381 | } | 381 | } |
382 | 382 | ||
383 | if (sym_is_choice(sym)) { | 383 | if (sym_is_choice(sym)) { |
384 | struct symbol *choice_sym; | 384 | struct symbol *choice_sym; |
385 | 385 | ||
386 | prop = sym_get_choice_prop(sym); | 386 | prop = sym_get_choice_prop(sym); |
387 | expr_list_for_each_sym(prop->expr, e, choice_sym) { | 387 | expr_list_for_each_sym(prop->expr, e, choice_sym) { |
388 | if ((sym->flags & SYMBOL_WRITE) && | 388 | if ((sym->flags & SYMBOL_WRITE) && |
389 | choice_sym->visible != no) | 389 | choice_sym->visible != no) |
390 | choice_sym->flags |= SYMBOL_WRITE; | 390 | choice_sym->flags |= SYMBOL_WRITE; |
391 | if (sym->flags & SYMBOL_CHANGED) | 391 | if (sym->flags & SYMBOL_CHANGED) |
392 | sym_set_changed(choice_sym); | 392 | sym_set_changed(choice_sym); |
393 | } | 393 | } |
394 | } | 394 | } |
395 | 395 | ||
396 | if (sym->flags & SYMBOL_AUTO) | 396 | if (sym->flags & SYMBOL_AUTO) |
397 | sym->flags &= ~SYMBOL_WRITE; | 397 | sym->flags &= ~SYMBOL_WRITE; |
398 | } | 398 | } |
399 | 399 | ||
400 | void sym_clear_all_valid(void) | 400 | void sym_clear_all_valid(void) |
401 | { | 401 | { |
402 | struct symbol *sym; | 402 | struct symbol *sym; |
403 | int i; | 403 | int i; |
404 | 404 | ||
405 | for_all_symbols(i, sym) | 405 | for_all_symbols(i, sym) |
406 | sym->flags &= ~SYMBOL_VALID; | 406 | sym->flags &= ~SYMBOL_VALID; |
407 | sym_add_change_count(1); | 407 | sym_add_change_count(1); |
408 | if (modules_sym) | 408 | if (modules_sym) |
409 | sym_calc_value(modules_sym); | 409 | sym_calc_value(modules_sym); |
410 | } | 410 | } |
411 | 411 | ||
412 | void sym_set_changed(struct symbol *sym) | 412 | void sym_set_changed(struct symbol *sym) |
413 | { | 413 | { |
414 | struct property *prop; | 414 | struct property *prop; |
415 | 415 | ||
416 | sym->flags |= SYMBOL_CHANGED; | 416 | sym->flags |= SYMBOL_CHANGED; |
417 | for (prop = sym->prop; prop; prop = prop->next) { | 417 | for (prop = sym->prop; prop; prop = prop->next) { |
418 | if (prop->menu) | 418 | if (prop->menu) |
419 | prop->menu->flags |= MENU_CHANGED; | 419 | prop->menu->flags |= MENU_CHANGED; |
420 | } | 420 | } |
421 | } | 421 | } |
422 | 422 | ||
423 | void sym_set_all_changed(void) | 423 | void sym_set_all_changed(void) |
424 | { | 424 | { |
425 | struct symbol *sym; | 425 | struct symbol *sym; |
426 | int i; | 426 | int i; |
427 | 427 | ||
428 | for_all_symbols(i, sym) | 428 | for_all_symbols(i, sym) |
429 | sym_set_changed(sym); | 429 | sym_set_changed(sym); |
430 | } | 430 | } |
431 | 431 | ||
432 | bool sym_tristate_within_range(struct symbol *sym, tristate val) | 432 | bool sym_tristate_within_range(struct symbol *sym, tristate val) |
433 | { | 433 | { |
434 | int type = sym_get_type(sym); | 434 | int type = sym_get_type(sym); |
435 | 435 | ||
436 | if (sym->visible == no) | 436 | if (sym->visible == no) |
437 | return false; | 437 | return false; |
438 | 438 | ||
439 | if (type != S_BOOLEAN && type != S_TRISTATE) | 439 | if (type != S_BOOLEAN && type != S_TRISTATE) |
440 | return false; | 440 | return false; |
441 | 441 | ||
442 | if (type == S_BOOLEAN && val == mod) | 442 | if (type == S_BOOLEAN && val == mod) |
443 | return false; | 443 | return false; |
444 | if (sym->visible <= sym->rev_dep.tri) | 444 | if (sym->visible <= sym->rev_dep.tri) |
445 | return false; | 445 | return false; |
446 | if (sym_is_choice_value(sym) && sym->visible == yes) | 446 | if (sym_is_choice_value(sym) && sym->visible == yes) |
447 | return val == yes; | 447 | return val == yes; |
448 | return val >= sym->rev_dep.tri && val <= sym->visible; | 448 | return val >= sym->rev_dep.tri && val <= sym->visible; |
449 | } | 449 | } |
450 | 450 | ||
451 | bool sym_set_tristate_value(struct symbol *sym, tristate val) | 451 | bool sym_set_tristate_value(struct symbol *sym, tristate val) |
452 | { | 452 | { |
453 | tristate oldval = sym_get_tristate_value(sym); | 453 | tristate oldval = sym_get_tristate_value(sym); |
454 | 454 | ||
455 | if (oldval != val && !sym_tristate_within_range(sym, val)) | 455 | if (oldval != val && !sym_tristate_within_range(sym, val)) |
456 | return false; | 456 | return false; |
457 | 457 | ||
458 | if (!(sym->flags & SYMBOL_DEF_USER)) { | 458 | if (!(sym->flags & SYMBOL_DEF_USER)) { |
459 | sym->flags |= SYMBOL_DEF_USER; | 459 | sym->flags |= SYMBOL_DEF_USER; |
460 | sym_set_changed(sym); | 460 | sym_set_changed(sym); |
461 | } | 461 | } |
462 | /* | 462 | /* |
463 | * setting a choice value also resets the new flag of the choice | 463 | * setting a choice value also resets the new flag of the choice |
464 | * symbol and all other choice values. | 464 | * symbol and all other choice values. |
465 | */ | 465 | */ |
466 | if (sym_is_choice_value(sym) && val == yes) { | 466 | if (sym_is_choice_value(sym) && val == yes) { |
467 | struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); | 467 | struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); |
468 | struct property *prop; | 468 | struct property *prop; |
469 | struct expr *e; | 469 | struct expr *e; |
470 | 470 | ||
471 | cs->def[S_DEF_USER].val = sym; | 471 | cs->def[S_DEF_USER].val = sym; |
472 | cs->flags |= SYMBOL_DEF_USER; | 472 | cs->flags |= SYMBOL_DEF_USER; |
473 | prop = sym_get_choice_prop(cs); | 473 | prop = sym_get_choice_prop(cs); |
474 | for (e = prop->expr; e; e = e->left.expr) { | 474 | for (e = prop->expr; e; e = e->left.expr) { |
475 | if (e->right.sym->visible != no) | 475 | if (e->right.sym->visible != no) |
476 | e->right.sym->flags |= SYMBOL_DEF_USER; | 476 | e->right.sym->flags |= SYMBOL_DEF_USER; |
477 | } | 477 | } |
478 | } | 478 | } |
479 | 479 | ||
480 | sym->def[S_DEF_USER].tri = val; | 480 | sym->def[S_DEF_USER].tri = val; |
481 | if (oldval != val) | 481 | if (oldval != val) |
482 | sym_clear_all_valid(); | 482 | sym_clear_all_valid(); |
483 | 483 | ||
484 | return true; | 484 | return true; |
485 | } | 485 | } |
486 | 486 | ||
487 | tristate sym_toggle_tristate_value(struct symbol *sym) | 487 | tristate sym_toggle_tristate_value(struct symbol *sym) |
488 | { | 488 | { |
489 | tristate oldval, newval; | 489 | tristate oldval, newval; |
490 | 490 | ||
491 | oldval = newval = sym_get_tristate_value(sym); | 491 | oldval = newval = sym_get_tristate_value(sym); |
492 | do { | 492 | do { |
493 | switch (newval) { | 493 | switch (newval) { |
494 | case no: | 494 | case no: |
495 | newval = mod; | 495 | newval = mod; |
496 | break; | 496 | break; |
497 | case mod: | 497 | case mod: |
498 | newval = yes; | 498 | newval = yes; |
499 | break; | 499 | break; |
500 | case yes: | 500 | case yes: |
501 | newval = no; | 501 | newval = no; |
502 | break; | 502 | break; |
503 | } | 503 | } |
504 | if (sym_set_tristate_value(sym, newval)) | 504 | if (sym_set_tristate_value(sym, newval)) |
505 | break; | 505 | break; |
506 | } while (oldval != newval); | 506 | } while (oldval != newval); |
507 | return newval; | 507 | return newval; |
508 | } | 508 | } |
509 | 509 | ||
510 | bool sym_string_valid(struct symbol *sym, const char *str) | 510 | bool sym_string_valid(struct symbol *sym, const char *str) |
511 | { | 511 | { |
512 | signed char ch; | 512 | signed char ch; |
513 | 513 | ||
514 | switch (sym->type) { | 514 | switch (sym->type) { |
515 | case S_STRING: | 515 | case S_STRING: |
516 | return true; | 516 | return true; |
517 | case S_INT: | 517 | case S_INT: |
518 | ch = *str++; | 518 | ch = *str++; |
519 | if (ch == '-') | 519 | if (ch == '-') |
520 | ch = *str++; | 520 | ch = *str++; |
521 | if (!isdigit(ch)) | 521 | if (!isdigit(ch)) |
522 | return false; | 522 | return false; |
523 | if (ch == '0' && *str != 0) | 523 | if (ch == '0' && *str != 0) |
524 | return false; | 524 | return false; |
525 | while ((ch = *str++)) { | 525 | while ((ch = *str++)) { |
526 | if (!isdigit(ch)) | 526 | if (!isdigit(ch)) |
527 | return false; | 527 | return false; |
528 | } | 528 | } |
529 | return true; | 529 | return true; |
530 | case S_HEX: | 530 | case S_HEX: |
531 | if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) | 531 | if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) |
532 | str += 2; | 532 | str += 2; |
533 | ch = *str++; | 533 | ch = *str++; |
534 | do { | 534 | do { |
535 | if (!isxdigit(ch)) | 535 | if (!isxdigit(ch)) |
536 | return false; | 536 | return false; |
537 | } while ((ch = *str++)); | 537 | } while ((ch = *str++)); |
538 | return true; | 538 | return true; |
539 | case S_BOOLEAN: | 539 | case S_BOOLEAN: |
540 | case S_TRISTATE: | 540 | case S_TRISTATE: |
541 | switch (str[0]) { | 541 | switch (str[0]) { |
542 | case 'y': case 'Y': | 542 | case 'y': case 'Y': |
543 | case 'm': case 'M': | 543 | case 'm': case 'M': |
544 | case 'n': case 'N': | 544 | case 'n': case 'N': |
545 | return true; | 545 | return true; |
546 | } | 546 | } |
547 | return false; | 547 | return false; |
548 | default: | 548 | default: |
549 | return false; | 549 | return false; |
550 | } | 550 | } |
551 | } | 551 | } |
552 | 552 | ||
553 | bool sym_string_within_range(struct symbol *sym, const char *str) | 553 | bool sym_string_within_range(struct symbol *sym, const char *str) |
554 | { | 554 | { |
555 | struct property *prop; | 555 | struct property *prop; |
556 | int val; | 556 | int val; |
557 | 557 | ||
558 | switch (sym->type) { | 558 | switch (sym->type) { |
559 | case S_STRING: | 559 | case S_STRING: |
560 | return sym_string_valid(sym, str); | 560 | return sym_string_valid(sym, str); |
561 | case S_INT: | 561 | case S_INT: |
562 | if (!sym_string_valid(sym, str)) | 562 | if (!sym_string_valid(sym, str)) |
563 | return false; | 563 | return false; |
564 | prop = sym_get_range_prop(sym); | 564 | prop = sym_get_range_prop(sym); |
565 | if (!prop) | 565 | if (!prop) |
566 | return true; | 566 | return true; |
567 | val = strtol(str, NULL, 10); | 567 | val = strtol(str, NULL, 10); |
568 | return val >= sym_get_range_val(prop->expr->left.sym, 10) && | 568 | return val >= sym_get_range_val(prop->expr->left.sym, 10) && |
569 | val <= sym_get_range_val(prop->expr->right.sym, 10); | 569 | val <= sym_get_range_val(prop->expr->right.sym, 10); |
570 | case S_HEX: | 570 | case S_HEX: |
571 | if (!sym_string_valid(sym, str)) | 571 | if (!sym_string_valid(sym, str)) |
572 | return false; | 572 | return false; |
573 | prop = sym_get_range_prop(sym); | 573 | prop = sym_get_range_prop(sym); |
574 | if (!prop) | 574 | if (!prop) |
575 | return true; | 575 | return true; |
576 | val = strtol(str, NULL, 16); | 576 | val = strtol(str, NULL, 16); |
577 | return val >= sym_get_range_val(prop->expr->left.sym, 16) && | 577 | return val >= sym_get_range_val(prop->expr->left.sym, 16) && |
578 | val <= sym_get_range_val(prop->expr->right.sym, 16); | 578 | val <= sym_get_range_val(prop->expr->right.sym, 16); |
579 | case S_BOOLEAN: | 579 | case S_BOOLEAN: |
580 | case S_TRISTATE: | 580 | case S_TRISTATE: |
581 | switch (str[0]) { | 581 | switch (str[0]) { |
582 | case 'y': case 'Y': | 582 | case 'y': case 'Y': |
583 | return sym_tristate_within_range(sym, yes); | 583 | return sym_tristate_within_range(sym, yes); |
584 | case 'm': case 'M': | 584 | case 'm': case 'M': |
585 | return sym_tristate_within_range(sym, mod); | 585 | return sym_tristate_within_range(sym, mod); |
586 | case 'n': case 'N': | 586 | case 'n': case 'N': |
587 | return sym_tristate_within_range(sym, no); | 587 | return sym_tristate_within_range(sym, no); |
588 | } | 588 | } |
589 | return false; | 589 | return false; |
590 | default: | 590 | default: |
591 | return false; | 591 | return false; |
592 | } | 592 | } |
593 | } | 593 | } |
594 | 594 | ||
595 | bool sym_set_string_value(struct symbol *sym, const char *newval) | 595 | bool sym_set_string_value(struct symbol *sym, const char *newval) |
596 | { | 596 | { |
597 | const char *oldval; | 597 | const char *oldval; |
598 | char *val; | 598 | char *val; |
599 | int size; | 599 | int size; |
600 | 600 | ||
601 | switch (sym->type) { | 601 | switch (sym->type) { |
602 | case S_BOOLEAN: | 602 | case S_BOOLEAN: |
603 | case S_TRISTATE: | 603 | case S_TRISTATE: |
604 | switch (newval[0]) { | 604 | switch (newval[0]) { |
605 | case 'y': case 'Y': | 605 | case 'y': case 'Y': |
606 | return sym_set_tristate_value(sym, yes); | 606 | return sym_set_tristate_value(sym, yes); |
607 | case 'm': case 'M': | 607 | case 'm': case 'M': |
608 | return sym_set_tristate_value(sym, mod); | 608 | return sym_set_tristate_value(sym, mod); |
609 | case 'n': case 'N': | 609 | case 'n': case 'N': |
610 | return sym_set_tristate_value(sym, no); | 610 | return sym_set_tristate_value(sym, no); |
611 | } | 611 | } |
612 | return false; | 612 | return false; |
613 | default: | 613 | default: |
614 | ; | 614 | ; |
615 | } | 615 | } |
616 | 616 | ||
617 | if (!sym_string_within_range(sym, newval)) | 617 | if (!sym_string_within_range(sym, newval)) |
618 | return false; | 618 | return false; |
619 | 619 | ||
620 | if (!(sym->flags & SYMBOL_DEF_USER)) { | 620 | if (!(sym->flags & SYMBOL_DEF_USER)) { |
621 | sym->flags |= SYMBOL_DEF_USER; | 621 | sym->flags |= SYMBOL_DEF_USER; |
622 | sym_set_changed(sym); | 622 | sym_set_changed(sym); |
623 | } | 623 | } |
624 | 624 | ||
625 | oldval = sym->def[S_DEF_USER].val; | 625 | oldval = sym->def[S_DEF_USER].val; |
626 | size = strlen(newval) + 1; | 626 | size = strlen(newval) + 1; |
627 | if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { | 627 | if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { |
628 | size += 2; | 628 | size += 2; |
629 | sym->def[S_DEF_USER].val = val = malloc(size); | 629 | sym->def[S_DEF_USER].val = val = malloc(size); |
630 | *val++ = '0'; | 630 | *val++ = '0'; |
631 | *val++ = 'x'; | 631 | *val++ = 'x'; |
632 | } else if (!oldval || strcmp(oldval, newval)) | 632 | } else if (!oldval || strcmp(oldval, newval)) |
633 | sym->def[S_DEF_USER].val = val = malloc(size); | 633 | sym->def[S_DEF_USER].val = val = malloc(size); |
634 | else | 634 | else |
635 | return true; | 635 | return true; |
636 | 636 | ||
637 | strcpy(val, newval); | 637 | strcpy(val, newval); |
638 | free((void *)oldval); | 638 | free((void *)oldval); |
639 | sym_clear_all_valid(); | 639 | sym_clear_all_valid(); |
640 | 640 | ||
641 | return true; | 641 | return true; |
642 | } | 642 | } |
643 | 643 | ||
644 | const char *sym_get_string_value(struct symbol *sym) | 644 | const char *sym_get_string_value(struct symbol *sym) |
645 | { | 645 | { |
646 | tristate val; | 646 | tristate val; |
647 | 647 | ||
648 | switch (sym->type) { | 648 | switch (sym->type) { |
649 | case S_BOOLEAN: | 649 | case S_BOOLEAN: |
650 | case S_TRISTATE: | 650 | case S_TRISTATE: |
651 | val = sym_get_tristate_value(sym); | 651 | val = sym_get_tristate_value(sym); |
652 | switch (val) { | 652 | switch (val) { |
653 | case no: | 653 | case no: |
654 | return "n"; | 654 | return "n"; |
655 | case mod: | 655 | case mod: |
656 | return "m"; | 656 | return "m"; |
657 | case yes: | 657 | case yes: |
658 | return "y"; | 658 | return "y"; |
659 | } | 659 | } |
660 | break; | 660 | break; |
661 | default: | 661 | default: |
662 | ; | 662 | ; |
663 | } | 663 | } |
664 | return (const char *)sym->curr.val; | 664 | return (const char *)sym->curr.val; |
665 | } | 665 | } |
666 | 666 | ||
667 | bool sym_is_changable(struct symbol *sym) | 667 | bool sym_is_changable(struct symbol *sym) |
668 | { | 668 | { |
669 | return sym->visible > sym->rev_dep.tri; | 669 | return sym->visible > sym->rev_dep.tri; |
670 | } | 670 | } |
671 | 671 | ||
672 | static unsigned strhash(const char *s) | 672 | static unsigned strhash(const char *s) |
673 | { | 673 | { |
674 | /* fnv32 hash */ | 674 | /* fnv32 hash */ |
675 | unsigned hash = 2166136261U; | 675 | unsigned hash = 2166136261U; |
676 | for (; *s; s++) | 676 | for (; *s; s++) |
677 | hash = (hash ^ *s) * 0x01000193; | 677 | hash = (hash ^ *s) * 0x01000193; |
678 | return hash; | 678 | return hash; |
679 | } | 679 | } |
680 | 680 | ||
681 | struct symbol *sym_lookup(const char *name, int flags) | 681 | struct symbol *sym_lookup(const char *name, int flags) |
682 | { | 682 | { |
683 | struct symbol *symbol; | 683 | struct symbol *symbol; |
684 | char *new_name; | 684 | char *new_name; |
685 | int hash; | 685 | int hash; |
686 | 686 | ||
687 | if (name) { | 687 | if (name) { |
688 | if (name[0] && !name[1]) { | 688 | if (name[0] && !name[1]) { |
689 | switch (name[0]) { | 689 | switch (name[0]) { |
690 | case 'y': return &symbol_yes; | 690 | case 'y': return &symbol_yes; |
691 | case 'm': return &symbol_mod; | 691 | case 'm': return &symbol_mod; |
692 | case 'n': return &symbol_no; | 692 | case 'n': return &symbol_no; |
693 | } | 693 | } |
694 | } | 694 | } |
695 | hash = strhash(name) % SYMBOL_HASHSIZE; | 695 | hash = strhash(name) % SYMBOL_HASHSIZE; |
696 | 696 | ||
697 | for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { | 697 | for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { |
698 | if (symbol->name && | 698 | if (symbol->name && |
699 | !strcmp(symbol->name, name) && | 699 | !strcmp(symbol->name, name) && |
700 | (flags ? symbol->flags & flags | 700 | (flags ? symbol->flags & flags |
701 | : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) | 701 | : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) |
702 | return symbol; | 702 | return symbol; |
703 | } | 703 | } |
704 | new_name = strdup(name); | 704 | new_name = strdup(name); |
705 | } else { | 705 | } else { |
706 | new_name = NULL; | 706 | new_name = NULL; |
707 | hash = 0; | 707 | hash = 0; |
708 | } | 708 | } |
709 | 709 | ||
710 | symbol = malloc(sizeof(*symbol)); | 710 | symbol = malloc(sizeof(*symbol)); |
711 | memset(symbol, 0, sizeof(*symbol)); | 711 | memset(symbol, 0, sizeof(*symbol)); |
712 | symbol->name = new_name; | 712 | symbol->name = new_name; |
713 | symbol->type = S_UNKNOWN; | 713 | symbol->type = S_UNKNOWN; |
714 | symbol->flags |= flags; | 714 | symbol->flags |= flags; |
715 | 715 | ||
716 | symbol->next = symbol_hash[hash]; | 716 | symbol->next = symbol_hash[hash]; |
717 | symbol_hash[hash] = symbol; | 717 | symbol_hash[hash] = symbol; |
718 | 718 | ||
719 | return symbol; | 719 | return symbol; |
720 | } | 720 | } |
721 | 721 | ||
722 | struct symbol *sym_find(const char *name) | 722 | struct symbol *sym_find(const char *name) |
723 | { | 723 | { |
724 | struct symbol *symbol = NULL; | 724 | struct symbol *symbol = NULL; |
725 | int hash = 0; | 725 | int hash = 0; |
726 | 726 | ||
727 | if (!name) | 727 | if (!name) |
728 | return NULL; | 728 | return NULL; |
729 | 729 | ||
730 | if (name[0] && !name[1]) { | 730 | if (name[0] && !name[1]) { |
731 | switch (name[0]) { | 731 | switch (name[0]) { |
732 | case 'y': return &symbol_yes; | 732 | case 'y': return &symbol_yes; |
733 | case 'm': return &symbol_mod; | 733 | case 'm': return &symbol_mod; |
734 | case 'n': return &symbol_no; | 734 | case 'n': return &symbol_no; |
735 | } | 735 | } |
736 | } | 736 | } |
737 | hash = strhash(name) % SYMBOL_HASHSIZE; | 737 | hash = strhash(name) % SYMBOL_HASHSIZE; |
738 | 738 | ||
739 | for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { | 739 | for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { |
740 | if (symbol->name && | 740 | if (symbol->name && |
741 | !strcmp(symbol->name, name) && | 741 | !strcmp(symbol->name, name) && |
742 | !(symbol->flags & SYMBOL_CONST)) | 742 | !(symbol->flags & SYMBOL_CONST)) |
743 | break; | 743 | break; |
744 | } | 744 | } |
745 | 745 | ||
746 | return symbol; | 746 | return symbol; |
747 | } | 747 | } |
748 | 748 | ||
749 | struct symbol **sym_re_search(const char *pattern) | 749 | struct symbol **sym_re_search(const char *pattern) |
750 | { | 750 | { |
751 | struct symbol *sym, **sym_arr = NULL; | 751 | struct symbol *sym, **sym_arr = NULL; |
752 | int i, cnt, size; | 752 | int i, cnt, size; |
753 | regex_t re; | 753 | regex_t re; |
754 | 754 | ||
755 | cnt = size = 0; | 755 | cnt = size = 0; |
756 | /* Skip if empty */ | 756 | /* Skip if empty */ |
757 | if (strlen(pattern) == 0) | 757 | if (strlen(pattern) == 0) |
758 | return NULL; | 758 | return NULL; |
759 | if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) | 759 | if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) |
760 | return NULL; | 760 | return NULL; |
761 | 761 | ||
762 | for_all_symbols(i, sym) { | 762 | for_all_symbols(i, sym) { |
763 | if (sym->flags & SYMBOL_CONST || !sym->name) | 763 | if (sym->flags & SYMBOL_CONST || !sym->name) |
764 | continue; | 764 | continue; |
765 | if (regexec(&re, sym->name, 0, NULL, 0)) | 765 | if (regexec(&re, sym->name, 0, NULL, 0)) |
766 | continue; | 766 | continue; |
767 | if (cnt + 1 >= size) { | 767 | if (cnt + 1 >= size) { |
768 | void *tmp = sym_arr; | 768 | void *tmp = sym_arr; |
769 | size += 16; | 769 | size += 16; |
770 | sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); | 770 | sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); |
771 | if (!sym_arr) { | 771 | if (!sym_arr) { |
772 | free(tmp); | 772 | free(tmp); |
773 | return NULL; | 773 | return NULL; |
774 | } | 774 | } |
775 | } | 775 | } |
776 | sym_calc_value(sym); | 776 | sym_calc_value(sym); |
777 | sym_arr[cnt++] = sym; | 777 | sym_arr[cnt++] = sym; |
778 | } | 778 | } |
779 | if (sym_arr) | 779 | if (sym_arr) |
780 | sym_arr[cnt] = NULL; | 780 | sym_arr[cnt] = NULL; |
781 | regfree(&re); | 781 | regfree(&re); |
782 | 782 | ||
783 | return sym_arr; | 783 | return sym_arr; |
784 | } | 784 | } |
785 | 785 | ||
786 | 786 | ||
787 | static struct symbol *sym_check_expr_deps(struct expr *e) | 787 | static struct symbol *sym_check_expr_deps(struct expr *e) |
788 | { | 788 | { |
789 | struct symbol *sym; | 789 | struct symbol *sym; |
790 | 790 | ||
791 | if (!e) | 791 | if (!e) |
792 | return NULL; | 792 | return NULL; |
793 | switch (e->type) { | 793 | switch (e->type) { |
794 | case E_OR: | 794 | case E_OR: |
795 | case E_AND: | 795 | case E_AND: |
796 | sym = sym_check_expr_deps(e->left.expr); | 796 | sym = sym_check_expr_deps(e->left.expr); |
797 | if (sym) | 797 | if (sym) |
798 | return sym; | 798 | return sym; |
799 | return sym_check_expr_deps(e->right.expr); | 799 | return sym_check_expr_deps(e->right.expr); |
800 | case E_NOT: | 800 | case E_NOT: |
801 | return sym_check_expr_deps(e->left.expr); | 801 | return sym_check_expr_deps(e->left.expr); |
802 | case E_EQUAL: | 802 | case E_EQUAL: |
803 | case E_UNEQUAL: | 803 | case E_UNEQUAL: |
804 | sym = sym_check_deps(e->left.sym); | 804 | sym = sym_check_deps(e->left.sym); |
805 | if (sym) | 805 | if (sym) |
806 | return sym; | 806 | return sym; |
807 | return sym_check_deps(e->right.sym); | 807 | return sym_check_deps(e->right.sym); |
808 | case E_SYMBOL: | 808 | case E_SYMBOL: |
809 | return sym_check_deps(e->left.sym); | 809 | return sym_check_deps(e->left.sym); |
810 | default: | 810 | default: |
811 | break; | 811 | break; |
812 | } | 812 | } |
813 | printf("Oops! How to check %d?\n", e->type); | 813 | printf("Oops! How to check %d?\n", e->type); |
814 | return NULL; | 814 | return NULL; |
815 | } | 815 | } |
816 | 816 | ||
817 | /* return NULL when dependencies are OK */ | 817 | /* return NULL when dependencies are OK */ |
818 | static struct symbol *sym_check_sym_deps(struct symbol *sym) | 818 | static struct symbol *sym_check_sym_deps(struct symbol *sym) |
819 | { | 819 | { |
820 | struct symbol *sym2; | 820 | struct symbol *sym2; |
821 | struct property *prop; | 821 | struct property *prop; |
822 | 822 | ||
823 | sym2 = sym_check_expr_deps(sym->rev_dep.expr); | 823 | sym2 = sym_check_expr_deps(sym->rev_dep.expr); |
824 | if (sym2) | 824 | if (sym2) |
825 | return sym2; | 825 | return sym2; |
826 | 826 | ||
827 | for (prop = sym->prop; prop; prop = prop->next) { | 827 | for (prop = sym->prop; prop; prop = prop->next) { |
828 | if (prop->type == P_CHOICE || prop->type == P_SELECT) | 828 | if (prop->type == P_CHOICE || prop->type == P_SELECT) |
829 | continue; | 829 | continue; |
830 | sym2 = sym_check_expr_deps(prop->visible.expr); | 830 | sym2 = sym_check_expr_deps(prop->visible.expr); |
831 | if (sym2) | 831 | if (sym2) |
832 | break; | 832 | break; |
833 | if (prop->type != P_DEFAULT || sym_is_choice(sym)) | 833 | if (prop->type != P_DEFAULT || sym_is_choice(sym)) |
834 | continue; | 834 | continue; |
835 | sym2 = sym_check_expr_deps(prop->expr); | 835 | sym2 = sym_check_expr_deps(prop->expr); |
836 | if (sym2) | 836 | if (sym2) |
837 | break; | 837 | break; |
838 | } | 838 | } |
839 | 839 | ||
840 | return sym2; | 840 | return sym2; |
841 | } | 841 | } |
842 | 842 | ||
843 | static struct symbol *sym_check_choice_deps(struct symbol *choice) | 843 | static struct symbol *sym_check_choice_deps(struct symbol *choice) |
844 | { | 844 | { |
845 | struct symbol *sym, *sym2; | 845 | struct symbol *sym, *sym2; |
846 | struct property *prop; | 846 | struct property *prop; |
847 | struct expr *e; | 847 | struct expr *e; |
848 | 848 | ||
849 | prop = sym_get_choice_prop(choice); | 849 | prop = sym_get_choice_prop(choice); |
850 | expr_list_for_each_sym(prop->expr, e, sym) | 850 | expr_list_for_each_sym(prop->expr, e, sym) |
851 | sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); | 851 | sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); |
852 | 852 | ||
853 | choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); | 853 | choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); |
854 | sym2 = sym_check_sym_deps(choice); | 854 | sym2 = sym_check_sym_deps(choice); |
855 | choice->flags &= ~SYMBOL_CHECK; | 855 | choice->flags &= ~SYMBOL_CHECK; |
856 | if (sym2) | 856 | if (sym2) |
857 | goto out; | 857 | goto out; |
858 | 858 | ||
859 | expr_list_for_each_sym(prop->expr, e, sym) { | 859 | expr_list_for_each_sym(prop->expr, e, sym) { |
860 | sym2 = sym_check_sym_deps(sym); | 860 | sym2 = sym_check_sym_deps(sym); |
861 | if (sym2) { | 861 | if (sym2) { |
862 | fprintf(stderr, " -> %s", sym->name); | 862 | fprintf(stderr, " -> %s", sym->name); |
863 | break; | 863 | break; |
864 | } | 864 | } |
865 | } | 865 | } |
866 | out: | 866 | out: |
867 | expr_list_for_each_sym(prop->expr, e, sym) | 867 | expr_list_for_each_sym(prop->expr, e, sym) |
868 | sym->flags &= ~SYMBOL_CHECK; | 868 | sym->flags &= ~SYMBOL_CHECK; |
869 | 869 | ||
870 | if (sym2 && sym_is_choice_value(sym2) && | 870 | if (sym2 && sym_is_choice_value(sym2) && |
871 | prop_get_symbol(sym_get_choice_prop(sym2)) == choice) | 871 | prop_get_symbol(sym_get_choice_prop(sym2)) == choice) |
872 | sym2 = choice; | 872 | sym2 = choice; |
873 | 873 | ||
874 | return sym2; | 874 | return sym2; |
875 | } | 875 | } |
876 | 876 | ||
877 | struct symbol *sym_check_deps(struct symbol *sym) | 877 | struct symbol *sym_check_deps(struct symbol *sym) |
878 | { | 878 | { |
879 | struct symbol *sym2; | 879 | struct symbol *sym2; |
880 | struct property *prop; | 880 | struct property *prop; |
881 | 881 | ||
882 | if (sym->flags & SYMBOL_CHECK) { | 882 | if (sym->flags & SYMBOL_CHECK) { |
883 | fprintf(stderr, "%s:%d:error: found recursive dependency: %s", | 883 | fprintf(stderr, "%s:%d:error: found recursive dependency: %s", |
884 | sym->prop->file->name, sym->prop->lineno, | 884 | sym->prop->file->name, sym->prop->lineno, |
885 | sym->name ? sym->name : "<choice>"); | 885 | sym->name ? sym->name : "<choice>"); |
886 | return sym; | 886 | return sym; |
887 | } | 887 | } |
888 | if (sym->flags & SYMBOL_CHECKED) | 888 | if (sym->flags & SYMBOL_CHECKED) |
889 | return NULL; | 889 | return NULL; |
890 | 890 | ||
891 | if (sym_is_choice_value(sym)) { | 891 | if (sym_is_choice_value(sym)) { |
892 | /* for choice groups start the check with main choice symbol */ | 892 | /* for choice groups start the check with main choice symbol */ |
893 | prop = sym_get_choice_prop(sym); | 893 | prop = sym_get_choice_prop(sym); |
894 | sym2 = sym_check_deps(prop_get_symbol(prop)); | 894 | sym2 = sym_check_deps(prop_get_symbol(prop)); |
895 | } else if (sym_is_choice(sym)) { | 895 | } else if (sym_is_choice(sym)) { |
896 | sym2 = sym_check_choice_deps(sym); | 896 | sym2 = sym_check_choice_deps(sym); |
897 | } else { | 897 | } else { |
898 | sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); | 898 | sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); |
899 | sym2 = sym_check_sym_deps(sym); | 899 | sym2 = sym_check_sym_deps(sym); |
900 | sym->flags &= ~SYMBOL_CHECK; | 900 | sym->flags &= ~SYMBOL_CHECK; |
901 | } | 901 | } |
902 | 902 | ||
903 | if (sym2) { | 903 | if (sym2) { |
904 | fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>"); | 904 | fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>"); |
905 | if (sym2 == sym) { | 905 | if (sym2 == sym) { |
906 | fprintf(stderr, "\n"); | 906 | fprintf(stderr, "\n"); |
907 | zconfnerrs++; | 907 | zconfnerrs++; |
908 | sym2 = NULL; | 908 | sym2 = NULL; |
909 | } | 909 | } |
910 | } | 910 | } |
911 | 911 | ||
912 | return sym2; | 912 | return sym2; |
913 | } | 913 | } |
914 | 914 | ||
915 | struct property *prop_alloc(enum prop_type type, struct symbol *sym) | 915 | struct property *prop_alloc(enum prop_type type, struct symbol *sym) |
916 | { | 916 | { |
917 | struct property *prop; | 917 | struct property *prop; |
918 | struct property **propp; | 918 | struct property **propp; |
919 | 919 | ||
920 | prop = malloc(sizeof(*prop)); | 920 | prop = malloc(sizeof(*prop)); |
921 | memset(prop, 0, sizeof(*prop)); | 921 | memset(prop, 0, sizeof(*prop)); |
922 | prop->type = type; | 922 | prop->type = type; |
923 | prop->sym = sym; | 923 | prop->sym = sym; |
924 | prop->file = current_file; | 924 | prop->file = current_file; |
925 | prop->lineno = zconf_lineno(); | 925 | prop->lineno = zconf_lineno(); |
926 | 926 | ||
927 | /* append property to the prop list of symbol */ | 927 | /* append property to the prop list of symbol */ |
928 | if (sym) { | 928 | if (sym) { |
929 | for (propp = &sym->prop; *propp; propp = &(*propp)->next) | 929 | for (propp = &sym->prop; *propp; propp = &(*propp)->next) |
930 | ; | 930 | ; |
931 | *propp = prop; | 931 | *propp = prop; |
932 | } | 932 | } |
933 | 933 | ||
934 | return prop; | 934 | return prop; |
935 | } | 935 | } |
936 | 936 | ||
937 | struct symbol *prop_get_symbol(struct property *prop) | 937 | struct symbol *prop_get_symbol(struct property *prop) |
938 | { | 938 | { |
939 | if (prop->expr && (prop->expr->type == E_SYMBOL || | 939 | if (prop->expr && (prop->expr->type == E_SYMBOL || |
940 | prop->expr->type == E_LIST)) | 940 | prop->expr->type == E_LIST)) |
941 | return prop->expr->left.sym; | 941 | return prop->expr->left.sym; |
942 | return NULL; | 942 | return NULL; |
943 | } | 943 | } |
944 | 944 | ||
945 | const char *prop_get_type_name(enum prop_type type) | 945 | const char *prop_get_type_name(enum prop_type type) |
946 | { | 946 | { |
947 | switch (type) { | 947 | switch (type) { |
948 | case P_PROMPT: | 948 | case P_PROMPT: |
949 | return "prompt"; | 949 | return "prompt"; |
950 | case P_ENV: | 950 | case P_ENV: |
951 | return "env"; | 951 | return "env"; |
952 | case P_COMMENT: | 952 | case P_COMMENT: |
953 | return "comment"; | 953 | return "comment"; |
954 | case P_MENU: | 954 | case P_MENU: |
955 | return "menu"; | 955 | return "menu"; |
956 | case P_DEFAULT: | 956 | case P_DEFAULT: |
957 | return "default"; | 957 | return "default"; |
958 | case P_CHOICE: | 958 | case P_CHOICE: |
959 | return "choice"; | 959 | return "choice"; |
960 | case P_SELECT: | 960 | case P_SELECT: |
961 | return "select"; | 961 | return "select"; |
962 | case P_RANGE: | 962 | case P_RANGE: |
963 | return "range"; | 963 | return "range"; |
964 | case P_SYMBOL: | ||
965 | return "symbol"; | ||
964 | case P_UNKNOWN: | 966 | case P_UNKNOWN: |
965 | break; | 967 | break; |
966 | } | 968 | } |
967 | return "unknown"; | 969 | return "unknown"; |
968 | } | 970 | } |
969 | 971 | ||
970 | static void prop_add_env(const char *env) | 972 | static void prop_add_env(const char *env) |
971 | { | 973 | { |
972 | struct symbol *sym, *sym2; | 974 | struct symbol *sym, *sym2; |
973 | struct property *prop; | 975 | struct property *prop; |
974 | char *p; | 976 | char *p; |
975 | 977 | ||
976 | sym = current_entry->sym; | 978 | sym = current_entry->sym; |
977 | sym->flags |= SYMBOL_AUTO; | 979 | sym->flags |= SYMBOL_AUTO; |
978 | for_all_properties(sym, prop, P_ENV) { | 980 | for_all_properties(sym, prop, P_ENV) { |
979 | sym2 = prop_get_symbol(prop); | 981 | sym2 = prop_get_symbol(prop); |
980 | if (strcmp(sym2->name, env)) | 982 | if (strcmp(sym2->name, env)) |
981 | menu_warn(current_entry, "redefining environment symbol from %s", | 983 | menu_warn(current_entry, "redefining environment symbol from %s", |
982 | sym2->name); | 984 | sym2->name); |
983 | return; | 985 | return; |
984 | } | 986 | } |
985 | 987 | ||
986 | prop = prop_alloc(P_ENV, sym); | 988 | prop = prop_alloc(P_ENV, sym); |
987 | prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); | 989 | prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); |
988 | 990 | ||
989 | sym_env_list = expr_alloc_one(E_LIST, sym_env_list); | 991 | sym_env_list = expr_alloc_one(E_LIST, sym_env_list); |
990 | sym_env_list->right.sym = sym; | 992 | sym_env_list->right.sym = sym; |
991 | 993 | ||
992 | p = getenv(env); | 994 | p = getenv(env); |
993 | if (p) | 995 | if (p) |
994 | sym_add_default(sym, p); | 996 | sym_add_default(sym, p); |
995 | else | 997 | else |
996 | menu_warn(current_entry, "environment variable %s undefined", env); | 998 | menu_warn(current_entry, "environment variable %s undefined", env); |
997 | } | 999 | } |
998 | 1000 |