Root/
Source at commit HEAD created 5 years 6 days ago. By ifabio, Few update to kernelPatcher (Credits to CrazyBirdy) | |
---|---|
1 | /*␊ |
2 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>␊ |
3 | * Released under the terms of the GNU GPL v2.0.␊ |
4 | */␊ |
5 | ␊ |
6 | #include <sys/stat.h>␊ |
7 | #include <ctype.h>␊ |
8 | #include <errno.h>␊ |
9 | #include <fcntl.h>␊ |
10 | #include <stdio.h>␊ |
11 | #include <stdlib.h>␊ |
12 | #include <string.h>␊ |
13 | #include <time.h>␊ |
14 | #include <unistd.h>␊ |
15 | ␊ |
16 | char *␊ |
17 | int_stpncpy (dst, src, len)␊ |
18 | char *dst;␊ |
19 | const char *src;␊ |
20 | size_t len;␊ |
21 | {␊ |
22 | ␉size_t n = strlen (src);␊ |
23 | ␉if (n > len)␊ |
24 | ␉␉n = len;␊ |
25 | ␉return strncpy (dst, src, len) + n;␊ |
26 | }␊ |
27 | ␊ |
28 | #define LKC_DIRECT_LINK␊ |
29 | #include "lkc.h"␊ |
30 | ␊ |
31 | #define max(a, b) ({\␊ |
32 | ␉␉typeof(a) _a = a;\␊ |
33 | ␉␉typeof(b) _b = b;\␊ |
34 | ␉␉_a > _b ? _a : _b; })␊ |
35 | ␊ |
36 | #define min(a, b) ({\␊ |
37 | ␉␉typeof(a) _a = a;\␊ |
38 | ␉␉typeof(b) _b = b;\␊ |
39 | ␉␉_a < _b ? _a : _b; })␊ |
40 | ␊ |
41 | static void conf_warning(const char *fmt, ...)␊ |
42 | ␉__attribute__ ((format (printf, 1, 2)));␊ |
43 | ␊ |
44 | static void conf_message(const char *fmt, ...)␊ |
45 | ␉__attribute__ ((format (printf, 1, 2)));␊ |
46 | ␊ |
47 | static const char *conf_filename;␊ |
48 | static int conf_lineno, conf_warnings, conf_unsaved;␊ |
49 | ␊ |
50 | const char conf_defname[] = "config/defconfig";␊ |
51 | ␊ |
52 | static void conf_warning(const char *fmt, ...)␊ |
53 | {␊ |
54 | ␉va_list ap;␊ |
55 | ␉va_start(ap, fmt);␊ |
56 | ␉fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);␊ |
57 | ␉vfprintf(stderr, fmt, ap);␊ |
58 | ␉fprintf(stderr, "\n");␊ |
59 | ␉va_end(ap);␊ |
60 | ␉conf_warnings++;␊ |
61 | }␊ |
62 | ␊ |
63 | static void conf_default_message_callback(const char *fmt, va_list ap)␊ |
64 | {␊ |
65 | ␉printf("#\n# ");␊ |
66 | ␉vprintf(fmt, ap);␊ |
67 | ␉printf("\n#\n");␊ |
68 | }␊ |
69 | ␊ |
70 | static void (*conf_message_callback) (const char *fmt, va_list ap) =␊ |
71 | ␉conf_default_message_callback;␊ |
72 | void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))␊ |
73 | {␊ |
74 | ␉conf_message_callback = fn;␊ |
75 | }␊ |
76 | ␊ |
77 | static void conf_message(const char *fmt, ...)␊ |
78 | {␊ |
79 | ␉va_list ap;␊ |
80 | ␊ |
81 | ␉va_start(ap, fmt);␊ |
82 | ␉if (conf_message_callback)␊ |
83 | ␉␉conf_message_callback(fmt, ap);␊ |
84 | ␉va_end(ap);␊ |
85 | }␊ |
86 | ␊ |
87 | const char *conf_get_configname(void)␊ |
88 | {␊ |
89 | ␉char *name = getenv("KCONFIG_CONFIG");␊ |
90 | ␊ |
91 | ␉return name ? name : ".config";␊ |
92 | }␊ |
93 | ␊ |
94 | const char *conf_get_autoconfig_name(void)␊ |
95 | {␊ |
96 | ␉char *name = getenv("KCONFIG_AUTOCONFIG");␊ |
97 | ␊ |
98 | ␉return name ? name : "auto.conf";␊ |
99 | }␊ |
100 | ␊ |
101 | /* TODO: figure out if symbols are always null-terminated */␊ |
102 | static char *conf_expand_value(const char *in)␊ |
103 | {␊ |
104 | ␉static char res_value[SYMBOL_MAXLENGTH + 1];␊ |
105 | ␉char name[SYMBOL_MAXLENGTH];␊ |
106 | ␉size_t res_rem = SYMBOL_MAXLENGTH;␊ |
107 | ␉char *res_ptr = res_value;␊ |
108 | ␉const char *src;␊ |
109 | ␉*res_ptr = 0;␊ |
110 | ␉res_ptr[SYMBOL_MAXLENGTH] = 0;␊ |
111 | ␉while ((src = strchr(in, '$')))␊ |
112 | ␉{␊ |
113 | ␉␉struct symbol *sym;␊ |
114 | ␉␉const char *symval;␊ |
115 | ␉␉char *name_ptr = name;␊ |
116 | ␉␉size_t n = min(res_rem, src - in);␊ |
117 | ␊ |
118 | ␉␉res_ptr = int_stpncpy(res_ptr, in, n);␊ |
119 | ␉␉if (!(res_rem -= n))␊ |
120 | ␉␉{␊ |
121 | ␉␉␉return res_value; /* buffer full, quit now */␊ |
122 | ␉␉}␊ |
123 | ␉␉src++;␊ |
124 | ␊ |
125 | ␉␉*name_ptr = 0;␊ |
126 | ␉␉while (isalnum(*src) || *src == '_') {␊ |
127 | ␉␉␉*name_ptr++ = *src++;␊ |
128 | ␉␉}␊ |
129 | ␉␉*name_ptr = 0;␊ |
130 | ␊ |
131 | ␉␉sym = sym_lookup(name, 0);␊ |
132 | ␉␉sym_calc_value(sym);␊ |
133 | ␉␉symval = sym_get_string_value(sym);␊ |
134 | ␉␉n = min(res_rem, strlen(symval));␊ |
135 | ␊ |
136 | ␉␉res_ptr = int_stpncpy(res_ptr, symval, n);␊ |
137 | ␉␉if (!(res_rem -= n))␊ |
138 | ␉␉{␊ |
139 | ␉␉␉return res_value; /* buffer full, quit now */␊ |
140 | ␉␉}␊ |
141 | ␉␉in = src;␊ |
142 | ␉}␊ |
143 | ␊ |
144 | ␉strncpy(res_ptr, in, res_rem + 1);␊ |
145 | ␉return res_value;␊ |
146 | }␊ |
147 | ␊ |
148 | char *conf_get_default_confname(void)␊ |
149 | {␊ |
150 | ␉struct stat buf;␊ |
151 | ␉static char fullname[PATH_MAX+1];␊ |
152 | ␉char *env, *name;␊ |
153 | ␊ |
154 | ␉name = conf_expand_value(conf_defname);␊ |
155 | ␉env = getenv(SRCTREE);␊ |
156 | ␉if (env) {␊ |
157 | ␉␉snprintf(fullname, PATH_MAX+1, "%s/%s", env, name);␊ |
158 | ␉␉if (!stat(fullname, &buf))␊ |
159 | ␉␉␉return fullname;␊ |
160 | ␉}␊ |
161 | ␉return name;␊ |
162 | }␊ |
163 | ␊ |
164 | static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)␊ |
165 | {␊ |
166 | ␉char *p2;␊ |
167 | ␊ |
168 | ␉switch (sym->type) {␊ |
169 | ␉case S_TRISTATE:␊ |
170 | ␉␉if (p[0] == 'm') {␊ |
171 | ␉␉␉sym->def[def].tri = mod;␊ |
172 | ␉␉␉sym->flags |= def_flags;␊ |
173 | ␉␉␉break;␊ |
174 | ␉␉}␊ |
175 | ␉case S_BOOLEAN:␊ |
176 | ␉␉if (p[0] == 'y') {␊ |
177 | ␉␉␉sym->def[def].tri = yes;␊ |
178 | ␉␉␉sym->flags |= def_flags;␊ |
179 | ␉␉␉break;␊ |
180 | ␉␉}␊ |
181 | ␉␉if (p[0] == 'n') {␊ |
182 | ␉␉␉sym->def[def].tri = no;␊ |
183 | ␉␉␉sym->flags |= def_flags;␊ |
184 | ␉␉␉break;␊ |
185 | ␉␉}␊ |
186 | ␉␉conf_warning("symbol value '%s' invalid for %s", p, sym->name);␊ |
187 | ␉␉break;␊ |
188 | ␉case S_OTHER:␊ |
189 | ␉␉if (*p != '"') {␊ |
190 | ␉␉␉for (p2 = p; *p2 && !isspace(*p2); p2++)␊ |
191 | ␉␉␉␉;␊ |
192 | ␉␉␉sym->type = S_STRING;␊ |
193 | ␉␉␉goto done;␊ |
194 | ␉␉}␊ |
195 | ␉case S_STRING:␊ |
196 | ␉␉if (*p++ != '"')␊ |
197 | ␉␉␉break;␊ |
198 | ␉␉for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {␊ |
199 | ␉␉␉if (*p2 == '"') {␊ |
200 | ␉␉␉␉*p2 = 0;␊ |
201 | ␉␉␉␉break;␊ |
202 | ␉␉␉}␊ |
203 | ␉␉␉memmove(p2, p2 + 1, strlen(p2));␊ |
204 | ␉␉}␊ |
205 | ␉␉if (!p2) {␊ |
206 | ␉␉␉conf_warning("invalid string found");␊ |
207 | ␉␉␉return 1;␊ |
208 | ␉␉}␊ |
209 | ␉case S_INT:␊ |
210 | ␉case S_HEX:␊ |
211 | ␉done:␊ |
212 | ␉␉if (sym_string_valid(sym, p)) {␊ |
213 | ␉␉␉sym->def[def].val = strdup(p);␊ |
214 | ␉␉␉sym->flags |= def_flags;␊ |
215 | ␉␉} else {␊ |
216 | ␉␉␉conf_warning("symbol value '%s' invalid for %s", p, sym->name);␊ |
217 | ␉␉␉return 1;␊ |
218 | ␉␉}␊ |
219 | ␉␉break;␊ |
220 | ␉default:␊ |
221 | ␉␉;␊ |
222 | ␉}␊ |
223 | ␉return 0;␊ |
224 | }␊ |
225 | ␊ |
226 | int conf_read_simple(const char *name, int def)␊ |
227 | {␊ |
228 | ␉FILE *in = NULL;␊ |
229 | ␉char line[1024];␊ |
230 | ␉char *p, *p2;␊ |
231 | ␉struct symbol *sym;␊ |
232 | ␉int i, def_flags;␊ |
233 | ␊ |
234 | ␉if (name) {␊ |
235 | ␉␉in = zconf_fopen(name);␊ |
236 | ␉} else {␊ |
237 | ␉␉struct property *prop;␊ |
238 | ␊ |
239 | ␉␉name = conf_get_configname();␊ |
240 | ␉␉in = zconf_fopen(name);␊ |
241 | ␉␉if (in)␊ |
242 | ␉␉␉goto load;␊ |
243 | ␉␉sym_add_change_count(1);␊ |
244 | ␉␉if (!sym_defconfig_list) {␊ |
245 | ␉␉␉if (modules_sym)␊ |
246 | ␉␉␉␉sym_calc_value(modules_sym);␊ |
247 | ␉␉␉return 1;␊ |
248 | ␉␉}␊ |
249 | ␊ |
250 | ␉␉for_all_defaults(sym_defconfig_list, prop) {␊ |
251 | ␉␉␉if (expr_calc_value(prop->visible.expr) == no ||␊ |
252 | ␉␉␉ prop->expr->type != E_SYMBOL)␊ |
253 | ␉␉␉␉continue;␊ |
254 | ␉␉␉name = conf_expand_value(prop->expr->left.sym->name);␊ |
255 | ␉␉␉in = zconf_fopen(name);␊ |
256 | ␉␉␉if (in) {␊ |
257 | ␉␉␉␉conf_message(_("using defaults found in %s"),␊ |
258 | ␉␉␉␉␉ name);␊ |
259 | ␉␉␉␉goto load;␊ |
260 | ␉␉␉}␊ |
261 | ␉␉}␊ |
262 | ␉}␊ |
263 | ␉if (!in)␊ |
264 | ␉␉return 1;␊ |
265 | ␊ |
266 | load:␊ |
267 | ␉conf_filename = name;␊ |
268 | ␉conf_lineno = 0;␊ |
269 | ␉conf_warnings = 0;␊ |
270 | ␉conf_unsaved = 0;␊ |
271 | ␊ |
272 | ␉def_flags = SYMBOL_DEF << def;␊ |
273 | ␉for_all_symbols(i, sym) {␊ |
274 | ␉␉sym->flags |= SYMBOL_CHANGED;␊ |
275 | ␉␉sym->flags &= ~(def_flags|SYMBOL_VALID);␊ |
276 | ␉␉if (sym_is_choice(sym))␊ |
277 | ␉␉␉sym->flags |= def_flags;␊ |
278 | ␉␉switch (sym->type) {␊ |
279 | ␉␉case S_INT:␊ |
280 | ␉␉case S_HEX:␊ |
281 | ␉␉case S_STRING:␊ |
282 | ␉␉␉if (sym->def[def].val)␊ |
283 | ␉␉␉␉free(sym->def[def].val);␊ |
284 | ␉␉default:␊ |
285 | ␉␉␉sym->def[def].val = NULL;␊ |
286 | ␉␉␉sym->def[def].tri = no;␊ |
287 | ␉␉}␊ |
288 | ␉}␊ |
289 | ␊ |
290 | ␉while (fgets(line, sizeof(line), in)) {␊ |
291 | ␉␉conf_lineno++;␊ |
292 | ␉␉sym = NULL;␊ |
293 | ␉␉if (line[0] == '#') {␊ |
294 | ␉␉␉if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))␊ |
295 | ␉␉␉␉continue;␊ |
296 | ␉␉␉p = strchr(line + 2 + strlen(CONFIG_), ' ');␊ |
297 | ␉␉␉if (!p)␊ |
298 | ␉␉␉␉continue;␊ |
299 | ␉␉␉*p++ = 0;␊ |
300 | ␉␉␉if (strncmp(p, "is not set", 10))␊ |
301 | ␉␉␉␉continue;␊ |
302 | ␉␉␉if (def == S_DEF_USER) {␊ |
303 | ␉␉␉␉sym = sym_find(line + 2 + strlen(CONFIG_));␊ |
304 | ␉␉␉␉if (!sym) {␊ |
305 | ␉␉␉␉␉sym_add_change_count(1);␊ |
306 | ␉␉␉␉␉goto setsym;␊ |
307 | ␉␉␉␉}␊ |
308 | ␉␉␉} else {␊ |
309 | ␉␉␉␉sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);␊ |
310 | ␉␉␉␉if (sym->type == S_UNKNOWN)␊ |
311 | ␉␉␉␉␉sym->type = S_BOOLEAN;␊ |
312 | ␉␉␉}␊ |
313 | ␉␉␉if (sym->flags & def_flags) {␊ |
314 | ␉␉␉␉conf_warning("override: reassigning to symbol %s", sym->name);␊ |
315 | ␉␉␉}␊ |
316 | ␉␉␉switch (sym->type) {␊ |
317 | ␉␉␉case S_BOOLEAN:␊ |
318 | ␉␉␉case S_TRISTATE:␊ |
319 | ␉␉␉␉sym->def[def].tri = no;␊ |
320 | ␉␉␉␉sym->flags |= def_flags;␊ |
321 | ␉␉␉␉break;␊ |
322 | ␉␉␉default:␊ |
323 | ␉␉␉␉;␊ |
324 | ␉␉␉}␊ |
325 | ␉␉} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {␊ |
326 | ␉␉␉p = strchr(line + strlen(CONFIG_), '=');␊ |
327 | ␉␉␉if (!p)␊ |
328 | ␉␉␉␉continue;␊ |
329 | ␉␉␉*p++ = 0;␊ |
330 | ␉␉␉p2 = strchr(p, '\n');␊ |
331 | ␉␉␉if (p2) {␊ |
332 | ␉␉␉␉*p2-- = 0;␊ |
333 | ␉␉␉␉if (*p2 == '\r')␊ |
334 | ␉␉␉␉␉*p2 = 0;␊ |
335 | ␉␉␉}␊ |
336 | ␉␉␉if (def == S_DEF_USER) {␊ |
337 | ␉␉␉␉sym = sym_find(line + strlen(CONFIG_));␊ |
338 | ␉␉␉␉if (!sym) {␊ |
339 | ␉␉␉␉␉sym_add_change_count(1);␊ |
340 | ␉␉␉␉␉goto setsym;␊ |
341 | ␉␉␉␉}␊ |
342 | ␉␉␉} else {␊ |
343 | ␉␉␉␉sym = sym_lookup(line + strlen(CONFIG_), 0);␊ |
344 | ␉␉␉␉if (sym->type == S_UNKNOWN)␊ |
345 | ␉␉␉␉␉sym->type = S_OTHER;␊ |
346 | ␉␉␉}␊ |
347 | ␉␉␉if (sym->flags & def_flags) {␊ |
348 | ␉␉␉␉conf_warning("override: reassigning to symbol %s", sym->name);␊ |
349 | ␉␉␉}␊ |
350 | ␉␉␉if (conf_set_sym_val(sym, def, def_flags, p))␊ |
351 | ␉␉␉␉continue;␊ |
352 | ␉␉} else {␊ |
353 | ␉␉␉if (line[0] != '\r' && line[0] != '\n')␊ |
354 | ␉␉␉␉conf_warning("unexpected data");␊ |
355 | ␉␉␉continue;␊ |
356 | ␉␉}␊ |
357 | setsym:␊ |
358 | ␉␉if (sym && sym_is_choice_value(sym)) {␊ |
359 | ␉␉␉struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));␊ |
360 | ␉␉␉switch (sym->def[def].tri) {␊ |
361 | ␉␉␉case no:␊ |
362 | ␉␉␉␉break;␊ |
363 | ␉␉␉case mod:␊ |
364 | ␉␉␉␉if (cs->def[def].tri == yes) {␊ |
365 | ␉␉␉␉␉conf_warning("%s creates inconsistent choice state", sym->name);␊ |
366 | ␉␉␉␉␉cs->flags &= ~def_flags;␊ |
367 | ␉␉␉␉}␊ |
368 | ␉␉␉␉break;␊ |
369 | ␉␉␉case yes:␊ |
370 | ␉␉␉␉if (cs->def[def].tri != no)␊ |
371 | ␉␉␉␉␉conf_warning("override: %s changes choice state", sym->name);␊ |
372 | ␉␉␉␉cs->def[def].val = sym;␊ |
373 | ␉␉␉␉break;␊ |
374 | ␉␉␉}␊ |
375 | ␉␉␉cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);␊ |
376 | ␉␉}␊ |
377 | ␉}␊ |
378 | ␉fclose(in);␊ |
379 | ␊ |
380 | ␉if (modules_sym)␊ |
381 | ␉␉sym_calc_value(modules_sym);␊ |
382 | ␉return 0;␊ |
383 | }␊ |
384 | ␊ |
385 | int conf_read(const char *name)␊ |
386 | {␊ |
387 | ␉struct symbol *sym, *choice_sym;␊ |
388 | ␉struct property *prop;␊ |
389 | ␉struct expr *e;␊ |
390 | ␉int i, flags;␊ |
391 | ␊ |
392 | ␉sym_set_change_count(0);␊ |
393 | ␊ |
394 | ␉if (conf_read_simple(name, S_DEF_USER))␊ |
395 | ␉␉return 1;␊ |
396 | ␊ |
397 | ␉for_all_symbols(i, sym) {␊ |
398 | ␉␉sym_calc_value(sym);␊ |
399 | ␉␉if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))␊ |
400 | ␉␉␉goto sym_ok;␊ |
401 | ␉␉if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {␊ |
402 | ␉␉␉/* check that calculated value agrees with saved value */␊ |
403 | ␉␉␉switch (sym->type) {␊ |
404 | ␉␉␉case S_BOOLEAN:␊ |
405 | ␉␉␉case S_TRISTATE:␊ |
406 | ␉␉␉␉if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))␊ |
407 | ␉␉␉␉␉break;␊ |
408 | ␉␉␉␉if (!sym_is_choice(sym))␊ |
409 | ␉␉␉␉␉goto sym_ok;␊ |
410 | ␉␉␉default:␊ |
411 | ␉␉␉␉if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))␊ |
412 | ␉␉␉␉␉goto sym_ok;␊ |
413 | ␉␉␉␉break;␊ |
414 | ␉␉␉}␊ |
415 | ␉␉} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))␊ |
416 | ␉␉␉/* no previous value and not saved */␊ |
417 | ␉␉␉goto sym_ok;␊ |
418 | ␉␉conf_unsaved++;␊ |
419 | ␉␉/* maybe print value in verbose mode... */␊ |
420 | ␉sym_ok:␊ |
421 | ␉␉if (!sym_is_choice(sym))␊ |
422 | ␉␉␉continue;␊ |
423 | ␉␉/* The choice symbol only has a set value (and thus is not new)␊ |
424 | ␉␉ * if all its visible childs have values.␊ |
425 | ␉␉ */␊ |
426 | ␉␉prop = sym_get_choice_prop(sym);␊ |
427 | ␉␉flags = sym->flags;␊ |
428 | ␉␉expr_list_for_each_sym(prop->expr, e, choice_sym)␊ |
429 | ␉␉␉if (choice_sym->visible != no)␊ |
430 | ␉␉␉␉flags &= choice_sym->flags;␊ |
431 | ␉␉sym->flags &= flags | ~SYMBOL_DEF_USER;␊ |
432 | ␉}␊ |
433 | ␊ |
434 | ␉for_all_symbols(i, sym) {␊ |
435 | ␉␉if (sym_has_value(sym) && !sym_is_choice_value(sym)) {␊ |
436 | ␉␉␉/* Reset values of generates values, so they'll appear␊ |
437 | ␉␉␉ * as new, if they should become visible, but that␊ |
438 | ␉␉␉ * doesn't quite work if the Kconfig and the saved␊ |
439 | ␉␉␉ * configuration disagree.␊ |
440 | ␉␉␉ */␊ |
441 | ␉␉␉if (sym->visible == no && !conf_unsaved)␊ |
442 | ␉␉␉␉sym->flags &= ~SYMBOL_DEF_USER;␊ |
443 | ␉␉␉switch (sym->type) {␊ |
444 | ␉␉␉case S_STRING:␊ |
445 | ␉␉␉case S_INT:␊ |
446 | ␉␉␉case S_HEX:␊ |
447 | ␉␉␉␉/* Reset a string value if it's out of range */␊ |
448 | ␉␉␉␉if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))␊ |
449 | ␉␉␉␉␉break;␊ |
450 | ␉␉␉␉sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);␊ |
451 | ␉␉␉␉conf_unsaved++;␊ |
452 | ␉␉␉␉break;␊ |
453 | ␉␉␉default:␊ |
454 | ␉␉␉␉break;␊ |
455 | ␉␉␉}␊ |
456 | ␉␉}␊ |
457 | ␉}␊ |
458 | ␊ |
459 | ␉sym_add_change_count(conf_warnings || conf_unsaved);␊ |
460 | ␊ |
461 | ␉return 0;␊ |
462 | }␊ |
463 | ␊ |
464 | /* Write a S_STRING */␊ |
465 | static void conf_write_string(bool headerfile, const char *name,␊ |
466 | const char *str, FILE *out)␊ |
467 | {␊ |
468 | ␉int l;␊ |
469 | ␉if (headerfile)␊ |
470 | ␉␉fprintf(out, "#define %s%s \"", CONFIG_, name);␊ |
471 | ␉else␊ |
472 | ␉␉fprintf(out, "%s%s=\"", CONFIG_, name);␊ |
473 | ␊ |
474 | ␉while (1) {␊ |
475 | ␉␉l = strcspn(str, "\"\\");␊ |
476 | ␉␉if (l) {␊ |
477 | ␉␉␉xfwrite(str, l, 1, out);␊ |
478 | ␉␉␉str += l;␊ |
479 | ␉␉}␊ |
480 | ␉␉if (!*str)␊ |
481 | ␉␉␉break;␊ |
482 | ␉␉fprintf(out, "\\%c", *str++);␊ |
483 | ␉}␊ |
484 | ␉fputs("\"\n", out);␊ |
485 | }␊ |
486 | ␊ |
487 | static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no)␊ |
488 | {␊ |
489 | ␉const char *str;␊ |
490 | ␊ |
491 | ␉switch (sym->type) {␊ |
492 | ␉case S_BOOLEAN:␊ |
493 | ␉case S_TRISTATE:␊ |
494 | ␉␉switch (sym_get_tristate_value(sym)) {␊ |
495 | ␉␉case no:␊ |
496 | ␉␉␉if (write_no)␊ |
497 | ␉␉␉␉fprintf(out, "# %s%s is not set\n",␊ |
498 | ␉␉␉␉ CONFIG_, sym->name);␊ |
499 | ␉␉␉break;␊ |
500 | ␉␉case mod:␊ |
501 | ␉␉␉fprintf(out, "%s%s=m\n", CONFIG_, sym->name);␊ |
502 | ␉␉␉break;␊ |
503 | ␉␉case yes:␊ |
504 | ␉␉␉fprintf(out, "%s%s=y\n", CONFIG_, sym->name);␊ |
505 | ␉␉␉break;␊ |
506 | ␉␉}␊ |
507 | ␉␉break;␊ |
508 | ␉case S_STRING:␊ |
509 | ␉␉conf_write_string(false, sym->name, sym_get_string_value(sym), out);␊ |
510 | ␉␉break;␊ |
511 | ␉case S_HEX:␊ |
512 | ␉case S_INT:␊ |
513 | ␉␉str = sym_get_string_value(sym);␊ |
514 | ␉␉fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str);␊ |
515 | ␉␉break;␊ |
516 | ␉case S_OTHER:␊ |
517 | ␉case S_UNKNOWN:␊ |
518 | ␉␉break;␊ |
519 | ␉}␊ |
520 | }␊ |
521 | ␊ |
522 | /*␊ |
523 | * Write out a minimal config.␊ |
524 | * All values that has default values are skipped as this is redundant.␊ |
525 | */␊ |
526 | int conf_write_defconfig(const char *filename)␊ |
527 | {␊ |
528 | ␉struct symbol *sym;␊ |
529 | ␉struct menu *menu;␊ |
530 | ␉FILE *out;␊ |
531 | ␊ |
532 | ␉out = fopen(filename, "w");␊ |
533 | ␉if (!out)␊ |
534 | ␉␉return 1;␊ |
535 | ␊ |
536 | ␉sym_clear_all_valid();␊ |
537 | ␊ |
538 | ␉/* Traverse all menus to find all relevant symbols */␊ |
539 | ␉menu = rootmenu.list;␊ |
540 | ␊ |
541 | ␉while (menu != NULL)␊ |
542 | ␉{␊ |
543 | ␉␉sym = menu->sym;␊ |
544 | ␉␉if (sym == NULL) {␊ |
545 | ␉␉␉if (!menu_is_visible(menu))␊ |
546 | ␉␉␉␉goto next_menu;␊ |
547 | ␉␉} else if (!sym_is_choice(sym)) {␊ |
548 | ␉␉␉sym_calc_value(sym);␊ |
549 | ␉␉␉if (!(sym->flags & SYMBOL_WRITE))␊ |
550 | ␉␉␉␉goto next_menu;␊ |
551 | ␉␉␉sym->flags &= ~SYMBOL_WRITE;␊ |
552 | ␉␉␉/* If we cannot change the symbol - skip */␊ |
553 | ␉␉␉if (!sym_is_changable(sym))␊ |
554 | ␉␉␉␉goto next_menu;␊ |
555 | ␉␉␉/* If symbol equals to default value - skip */␊ |
556 | ␉␉␉if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)␊ |
557 | ␉␉␉␉goto next_menu;␊ |
558 | ␊ |
559 | ␉␉␉/*␊ |
560 | ␉␉␉ * If symbol is a choice value and equals to the␊ |
561 | ␉␉␉ * default for a choice - skip.␊ |
562 | ␉␉␉ * But only if value is bool and equal to "y" and␊ |
563 | ␉␉␉ * choice is not "optional".␊ |
564 | ␉␉␉ * (If choice is "optional" then all values can be "n")␊ |
565 | ␉␉␉ */␊ |
566 | ␉␉␉if (sym_is_choice_value(sym)) {␊ |
567 | ␉␉␉␉struct symbol *cs;␊ |
568 | ␉␉␉␉struct symbol *ds;␊ |
569 | ␊ |
570 | ␉␉␉␉cs = prop_get_symbol(sym_get_choice_prop(sym));␊ |
571 | ␉␉␉␉ds = sym_choice_default(cs);␊ |
572 | ␉␉␉␉if (!sym_is_optional(cs) && sym == ds) {␊ |
573 | ␉␉␉␉␉if ((sym->type == S_BOOLEAN) &&␊ |
574 | ␉␉␉␉␉ sym_get_tristate_value(sym) == yes)␊ |
575 | ␉␉␉␉␉␉goto next_menu;␊ |
576 | ␉␉␉␉}␊ |
577 | ␉␉␉}␊ |
578 | ␉␉␉conf_write_symbol(sym, out, true);␊ |
579 | ␉␉}␊ |
580 | next_menu:␊ |
581 | ␉␉if (menu->list != NULL) {␊ |
582 | ␉␉␉menu = menu->list;␊ |
583 | ␉␉}␊ |
584 | ␉␉else if (menu->next != NULL) {␊ |
585 | ␉␉␉menu = menu->next;␊ |
586 | ␉␉} else {␊ |
587 | ␉␉␉while ((menu = menu->parent)) {␊ |
588 | ␉␉␉␉if (menu->next != NULL) {␊ |
589 | ␉␉␉␉␉menu = menu->next;␊ |
590 | ␉␉␉␉␉break;␊ |
591 | ␉␉␉␉}␊ |
592 | ␉␉␉}␊ |
593 | ␉␉}␊ |
594 | ␉}␊ |
595 | ␉fclose(out);␊ |
596 | ␉return 0;␊ |
597 | }␊ |
598 | ␊ |
599 | int conf_write(const char *name)␊ |
600 | {␊ |
601 | ␉FILE *out;␊ |
602 | ␉struct symbol *sym;␊ |
603 | ␉struct menu *menu;␊ |
604 | ␉const char *basename;␊ |
605 | ␉const char *str;␊ |
606 | ␉char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];␊ |
607 | ␉time_t now;␊ |
608 | ␉int use_timestamp = 1;␊ |
609 | ␉char *env;␊ |
610 | ␊ |
611 | ␉dirname[0] = 0;␊ |
612 | ␉if (name && name[0]) {␊ |
613 | ␉␉struct stat st;␊ |
614 | ␉␉char *slash;␊ |
615 | ␊ |
616 | ␉␉if (!stat(name, &st) && S_ISDIR(st.st_mode)) {␊ |
617 | ␉␉␉/* FIXME: add length check */␊ |
618 | ␉␉␉strcpy(stpcpy(dirname, name), "/");␊ |
619 | ␉␉␉basename = conf_get_configname();␊ |
620 | ␉␉} else if ((slash = strrchr(name, '/'))) {␊ |
621 | ␉␉␉size_t size = slash - name + 1;␊ |
622 | ␉␉␉memcpy(dirname, name, size);␊ |
623 | ␉␉␉dirname[size] = 0;␊ |
624 | ␉␉␉if (slash[1]) {␊ |
625 | ␉␉␉␉basename = slash + 1;␊ |
626 | ␉␉␉} else {␊ |
627 | ␉␉␉␉basename = conf_get_configname();␊ |
628 | ␉␉␉}␊ |
629 | ␉␉} else {␊ |
630 | ␉␉␉basename = name;␊ |
631 | ␉␉}␊ |
632 | ␉} else {␊ |
633 | ␉␉basename = conf_get_configname();␊ |
634 | ␉}␊ |
635 | ␉snprintf(newname, PATH_MAX+1, "%s%s", dirname, basename);␊ |
636 | ␉env = getenv("KCONFIG_OVERWRITECONFIG");␊ |
637 | ␉if (!env || !*env) {␊ |
638 | ␉␉snprintf(tmpname, PATH_MAX+1, "%s.tmpconfig.%d", dirname, (int)getpid());␊ |
639 | ␉␉out = fopen(tmpname, "w");␊ |
640 | ␉} else {␊ |
641 | ␉␉*tmpname = 0;␊ |
642 | ␉␉out = fopen(newname, "w");␊ |
643 | ␉}␊ |
644 | ␉if (!out) {␊ |
645 | ␉␉return 1;␊ |
646 | ␉}␊ |
647 | ␉time(&now);␊ |
648 | ␉env = getenv("KCONFIG_NOTIMESTAMP");␊ |
649 | ␉if (env && *env) {␊ |
650 | ␉␉use_timestamp = 0;␊ |
651 | ␉}␊ |
652 | ␊ |
653 | ␉fprintf(out, _("#\n"␊ |
654 | ␉␉ "# Automatically generated make config: don't edit\n"␊ |
655 | ␉␉ "# %s\n"␊ |
656 | ␉␉ "%s%s"␊ |
657 | ␉␉ "#\n"),␊ |
658 | ␉␉ rootmenu.prompt->text,␊ |
659 | ␉␉ use_timestamp ? "# " : "",␊ |
660 | ␉␉ use_timestamp ? ctime(&now) : "");␊ |
661 | ␊ |
662 | ␉if (!conf_get_changed())␊ |
663 | ␉␉sym_clear_all_valid();␊ |
664 | ␊ |
665 | ␉menu = rootmenu.list;␊ |
666 | ␉while (menu) {␊ |
667 | ␉␉sym = menu->sym;␊ |
668 | ␉␉if (!sym) {␊ |
669 | ␉␉␉if (!menu_is_visible(menu))␊ |
670 | ␉␉␉␉goto next;␊ |
671 | ␉␉␉str = menu_get_prompt(menu);␊ |
672 | ␉␉␉fprintf(out, "\n"␊ |
673 | ␉␉␉␉ "#\n"␊ |
674 | ␉␉␉␉ "# %s\n"␊ |
675 | ␉␉␉␉ "#\n", str);␊ |
676 | ␉␉} else if (!(sym->flags & SYMBOL_CHOICE)) {␊ |
677 | ␉␉␉sym_calc_value(sym);␊ |
678 | ␉␉␉if (!(sym->flags & SYMBOL_WRITE))␊ |
679 | ␉␉␉␉goto next;␊ |
680 | ␉␉␉sym->flags &= ~SYMBOL_WRITE;␊ |
681 | ␉␉␉/* Write config symbol to file */␊ |
682 | ␉␉␉conf_write_symbol(sym, out, true);␊ |
683 | ␉␉}␊ |
684 | ␊ |
685 | next:␊ |
686 | ␉␉if (menu->list) {␊ |
687 | ␉␉␉menu = menu->list;␊ |
688 | ␉␉␉continue;␊ |
689 | ␉␉}␊ |
690 | ␉␉if (menu->next) {␊ |
691 | ␉␉␉menu = menu->next;␊ |
692 | ␉␉} else while ((menu = menu->parent)) {␊ |
693 | ␉␉␉if (menu->next) {␊ |
694 | ␉␉␉␉menu = menu->next;␊ |
695 | ␉␉␉␉break;␊ |
696 | ␉␉␉}␊ |
697 | ␉␉}␊ |
698 | ␉}␊ |
699 | ␉fclose(out);␊ |
700 | ␊ |
701 | ␉if (*tmpname) {␊ |
702 | ␉␉strcat(dirname, basename);␊ |
703 | ␉␉strcat(dirname, ".old");␊ |
704 | ␉␉rename(newname, dirname);␊ |
705 | ␉␉if (rename(tmpname, newname)) {␊ |
706 | ␉␉␉return 1;␊ |
707 | ␉␉}␊ |
708 | ␉}␊ |
709 | ␊ |
710 | //␉conf_message(_("configuration written to %s"), newname);␊ |
711 | ␊ |
712 | ␉sym_set_change_count(0);␊ |
713 | ␊ |
714 | ␉return 0;␊ |
715 | }␊ |
716 | #if 0␊ |
717 | ␊ |
718 | static int conf_split_config(void)␊ |
719 | {␊ |
720 | ␉const char *name;␊ |
721 | ␉char path[PATH_MAX+1];␊ |
722 | ␉char *s, *d, c;␊ |
723 | ␉struct symbol *sym;␊ |
724 | ␉struct stat sb;␊ |
725 | ␉int res, i, fd;␊ |
726 | ␊ |
727 | ␉name = conf_get_autoconfig_name();␊ |
728 | ␉conf_read_simple(name, S_DEF_AUTO);␊ |
729 | ␊ |
730 | ␉//if (chdir("include/config"))␊ |
731 | ␉//␉return 1;␊ |
732 | ␊ |
733 | ␉res = 0;␊ |
734 | ␉for_all_symbols(i, sym) {␊ |
735 | ␉␉sym_calc_value(sym);␊ |
736 | ␉␉if ((sym->flags & SYMBOL_AUTO) || !sym->name)␊ |
737 | ␉␉␉continue;␊ |
738 | ␉␉if (sym->flags & SYMBOL_WRITE) {␊ |
739 | ␉␉␉if (sym->flags & SYMBOL_DEF_AUTO) {␊ |
740 | ␉␉␉␉/*␊ |
741 | ␉␉␉␉ * symbol has old and new value,␊ |
742 | ␉␉␉␉ * so compare them...␊ |
743 | ␉␉␉␉ */␊ |
744 | ␉␉␉␉switch (sym->type) {␊ |
745 | ␉␉␉␉case S_BOOLEAN:␊ |
746 | ␉␉␉␉case S_TRISTATE:␊ |
747 | ␉␉␉␉␉if (sym_get_tristate_value(sym) ==␊ |
748 | ␉␉␉␉␉ sym->def[S_DEF_AUTO].tri)␊ |
749 | ␉␉␉␉␉␉continue;␊ |
750 | ␉␉␉␉␉break;␊ |
751 | ␉␉␉␉case S_STRING:␊ |
752 | ␉␉␉␉case S_HEX:␊ |
753 | ␉␉␉␉case S_INT:␊ |
754 | ␉␉␉␉␉if (!strcmp(sym_get_string_value(sym),␊ |
755 | ␉␉␉␉␉␉ sym->def[S_DEF_AUTO].val))␊ |
756 | ␉␉␉␉␉␉continue;␊ |
757 | ␉␉␉␉␉break;␊ |
758 | ␉␉␉␉default:␊ |
759 | ␉␉␉␉␉break;␊ |
760 | ␉␉␉␉}␊ |
761 | ␉␉␉} else {␊ |
762 | ␉␉␉␉/*␊ |
763 | ␉␉␉␉ * If there is no old value, only 'no' (unset)␊ |
764 | ␉␉␉␉ * is allowed as new value.␊ |
765 | ␉␉␉␉ */␊ |
766 | ␉␉␉␉switch (sym->type) {␊ |
767 | ␉␉␉␉case S_BOOLEAN:␊ |
768 | ␉␉␉␉case S_TRISTATE:␊ |
769 | ␉␉␉␉␉if (sym_get_tristate_value(sym) == no)␊ |
770 | ␉␉␉␉␉␉continue;␊ |
771 | ␉␉␉␉␉break;␊ |
772 | ␉␉␉␉default:␊ |
773 | ␉␉␉␉␉break;␊ |
774 | ␉␉␉␉}␊ |
775 | ␉␉␉}␊ |
776 | ␉␉} else if (!(sym->flags & SYMBOL_DEF_AUTO))␊ |
777 | ␉␉␉/* There is neither an old nor a new value. */␊ |
778 | ␉␉␉continue;␊ |
779 | ␉␉/* else␊ |
780 | ␉␉ *␉There is an old value, but no new value ('no' (unset)␊ |
781 | ␉␉ *␉isn't saved in auto.conf, so the old value is always␊ |
782 | ␉␉ *␉different from 'no').␊ |
783 | ␉␉ */␊ |
784 | ␊ |
785 | ␉␉/* Replace all '_' and append ".h" */␊ |
786 | ␉␉s = sym->name;␊ |
787 | ␉␉d = path;␊ |
788 | ␉␉while ((c = *s++)) {␊ |
789 | ␉␉␉c = tolower(c);␊ |
790 | ␉␉␉*d++ = (c == '_') ? '/' : c;␊ |
791 | ␉␉}␊ |
792 | ␉␉strcpy(d, ".h");␊ |
793 | ␊ |
794 | ␉␉/* Assume directory path already exists. */␊ |
795 | ␉␉fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);␊ |
796 | ␉␉if (fd == -1) {␊ |
797 | ␉␉␉if (errno != ENOENT) {␊ |
798 | ␉␉␉␉res = 1;␊ |
799 | ␉␉␉␉break;␊ |
800 | ␉␉␉}␊ |
801 | ␉␉␉/*␊ |
802 | ␉␉␉ * Create directory components,␊ |
803 | ␉␉␉ * unless they exist already.␊ |
804 | ␉␉␉ */␊ |
805 | ␉␉␉d = path;␊ |
806 | ␉␉␉while ((d = strchr(d, '/'))) {␊ |
807 | ␉␉␉␉*d = 0;␊ |
808 | ␉␉␉␉if (stat(path, &sb) && mkdir(path, 0755)) {␊ |
809 | ␉␉␉␉␉res = 1;␊ |
810 | ␉␉␉␉␉goto out;␊ |
811 | ␉␉␉␉}␊ |
812 | ␉␉␉␉*d++ = '/';␊ |
813 | ␉␉␉}␊ |
814 | ␉␉␉/* Try it again. */␊ |
815 | ␉␉␉fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);␊ |
816 | ␉␉␉if (fd == -1) {␊ |
817 | ␉␉␉␉res = 1;␊ |
818 | ␉␉␉␉break;␊ |
819 | ␉␉␉}␊ |
820 | ␉␉}␊ |
821 | ␉␉close(fd);␊ |
822 | ␉}␊ |
823 | out:␊ |
824 | ␉if (chdir("../.."))␊ |
825 | ␉␉return 1;␊ |
826 | ␊ |
827 | ␉return res;␊ |
828 | }␊ |
829 | #endif␊ |
830 | int conf_write_autoconf(void)␊ |
831 | {␊ |
832 | ␉struct symbol *sym;␊ |
833 | ␉const char *str;␊ |
834 | ␉const char *name;␊ |
835 | ␉FILE *out, *out_h, *out_inc;␊ |
836 | ␉time_t now;␊ |
837 | ␉int i;␊ |
838 | ␊ |
839 | ␉sym_clear_all_valid();␊ |
840 | ␊ |
841 | ␉/*if (conf_split_config())␊ |
842 | ␉{␊ |
843 | printf("ERR: conf_split_config");␊ |
844 | return 1; ␊ |
845 | }*/␊ |
846 | ␊ |
847 | ␉out = fopen(".tmpconfig", "w");␊ |
848 | ␉if (!out)␊ |
849 | {␊ |
850 | printf("ERR: .tmpconfig");␊ |
851 | ␉␉return 1;␊ |
852 | }␊ |
853 | ␊ |
854 | ␉out_h = fopen(".tmpconfig.h", "w");␊ |
855 | ␉if (!out_h) {␊ |
856 | ␉␉fclose(out);␊ |
857 | ␉␉return 1;␊ |
858 | ␉}␊ |
859 | ␊ |
860 | out_inc = fopen(".tmpconfig.inc", "w");␊ |
861 | ␉if (!out_inc) {␊ |
862 | ␉␉fclose(out);␊ |
863 | fclose(out_h);␊ |
864 | ␉␉return 1;␊ |
865 | ␉}␊ |
866 | ␊ |
867 | ␊ |
868 | ␉time(&now);␊ |
869 | ␉fprintf(out, "#\n"␊ |
870 | ␉␉ "# Automatically generated make config: don't edit\n"␊ |
871 | ␉␉ "# %s\n"␊ |
872 | ␉␉ "# %s"␊ |
873 | ␉␉ "#\n",␊ |
874 | ␉␉ rootmenu.prompt->text, ctime(&now));␊ |
875 | ␊ |
876 | ␉fprintf(out_h, "//\n"␊ |
877 | "// Automatically generated make config: don't edit\n"␊ |
878 | "// %s\n"␊ |
879 | "// %s"␊ |
880 | "// \n",␊ |
881 | rootmenu.prompt->text, ctime(&now));␊ |
882 | ␊ |
883 | fprintf(out_inc, ";\n"␊ |
884 | "; Automatically generated make config: don't edit\n"␊ |
885 | "; %s\n"␊ |
886 | "; %s"␊ |
887 | ";\n",␊ |
888 | rootmenu.prompt->text, ctime(&now));␊ |
889 | ␊ |
890 | ␊ |
891 | fprintf(out_h, "#define CONFIG_IS_BUILTIN 1\n");␊ |
892 | fprintf(out_h, "#define CONFIG_IS_MODULE 2\n");␊ |
893 | ␊ |
894 | ␊ |
895 | ␉for_all_symbols(i, sym) {␊ |
896 | ␉␉sym_calc_value(sym);␊ |
897 | ␉␉if (!(sym->flags & SYMBOL_WRITE) || !sym->name)␊ |
898 | ␉␉␉continue;␊ |
899 | ␊ |
900 | ␉␉/* write symbol to config file */␊ |
901 | ␉␉conf_write_symbol(sym, out, false);␊ |
902 | ␊ |
903 | ␉␉/* update autoconf and tristate files */␊ |
904 | ␉␉switch (sym->type) {␊ |
905 | ␉␉case S_BOOLEAN:␊ |
906 | ␉␉case S_TRISTATE:␊ |
907 | ␉␉␉switch (sym_get_tristate_value(sym)) {␊ |
908 | ␉␉␉case no:␊ |
909 | fprintf(out_inc, "%s%s EQU 0\n",␊ |
910 | CONFIG_, sym->name);␊ |
911 | ␊ |
912 | ␉␉␉␉break;␊ |
913 | ␉␉␉case mod:␊ |
914 | ␉␉␉␉fprintf(out_inc, "%s%s EQU 1\n",␊ |
915 | ␉␉␉␉ CONFIG_, sym->name);␊ |
916 | fprintf(out_h, "#define %s%s CONFIG_IS_MODULE\n",␊ |
917 | CONFIG_, sym->name);␊ |
918 | ␊ |
919 | ␉␉␉␉break;␊ |
920 | ␉␉␉case yes:␊ |
921 | fprintf(out_inc, "%s%s EQU 1\n",␊ |
922 | CONFIG_, sym->name);␊ |
923 | ␉␉␉␉fprintf(out_h, "#define %s%s CONFIG_IS_BUILTIN\n",␊ |
924 | ␉␉␉␉ CONFIG_, sym->name);␊ |
925 | ␉␉␉␉break;␊ |
926 | ␉␉␉}␊ |
927 | ␉␉␉break;␊ |
928 | ␉␉case S_STRING:␊ |
929 | ␉␉␉conf_write_string(true, sym->name, sym_get_string_value(sym), out_h);␊ |
930 | ␉␉␉break;␊ |
931 | ␉␉case S_HEX:␊ |
932 | ␉␉␉str = sym_get_string_value(sym);␊ |
933 | ␉␉␉if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {␊ |
934 | fprintf(out_inc, "%s%s EQU 0x%s\n",␊ |
935 | CONFIG_, sym->name, str);␊ |
936 | ␉␉␉␉fprintf(out_h, "#define %s%s 0x%s\n",␊ |
937 | ␉␉␉␉ CONFIG_, sym->name, str);␊ |
938 | ␉␉␉␉break;␊ |
939 | ␉␉␉}␊ |
940 | ␉␉case S_INT:␊ |
941 | ␉␉␉str = sym_get_string_value(sym);␊ |
942 | fprintf(out_inc, "%s%s EQU %s\n",␊ |
943 | CONFIG_, sym->name, str);␊ |
944 | ␉␉␉fprintf(out_h, "#define %s%s %s\n",␊ |
945 | ␉␉␉ CONFIG_, sym->name, str);␊ |
946 | ␉␉␉break;␊ |
947 | ␉␉default:␊ |
948 | ␉␉␉break;␊ |
949 | ␉␉}␊ |
950 | ␉}␊ |
951 | ␉fclose(out);␊ |
952 | ␉fclose(out_h);␊ |
953 | ␉fclose(out_inc);␊ |
954 | ␊ |
955 | ␉name = getenv("CCONFIG_AUTOHEADER");␊ |
956 | ␉if (!name) name = "autoconf.h";␊ |
957 | ␉if (rename(".tmpconfig.h", name))␊ |
958 | ␉␉return 1;␊ |
959 | ␊ |
960 | name = getenv("CCONFIG_AUTOINC");␊ |
961 | ␉if (!name) name = "autoconf.inc";␊ |
962 | ␉if (rename(".tmpconfig.inc", name))␊ |
963 | ␉␉return 1;␊ |
964 | ␊ |
965 | ␊ |
966 | ␉name = conf_get_autoconfig_name();␊ |
967 | ␉/*␊ |
968 | ␉ * This must be the last step, kbuild has a dependency on auto.conf␊ |
969 | ␉ * and this marks the successful completion of the previous steps.␊ |
970 | ␉ */␊ |
971 | ␉if (rename(".tmpconfig", name))␊ |
972 | {␊ |
973 | printf("rename");␊ |
974 | ␉␉return 1;␊ |
975 | }␊ |
976 | ␉return 0;␊ |
977 | }␊ |
978 | ␊ |
979 | static int sym_change_count;␊ |
980 | static void (*conf_changed_callback)(void);␊ |
981 | ␊ |
982 | void sym_set_change_count(int count)␊ |
983 | {␊ |
984 | ␉int _sym_change_count = sym_change_count;␊ |
985 | ␉sym_change_count = count;␊ |
986 | ␉if (conf_changed_callback &&␊ |
987 | ␉ (bool)_sym_change_count != (bool)count)␊ |
988 | ␉␉conf_changed_callback();␊ |
989 | }␊ |
990 | ␊ |
991 | void sym_add_change_count(int count)␊ |
992 | {␊ |
993 | ␉sym_set_change_count(count + sym_change_count);␊ |
994 | }␊ |
995 | ␊ |
996 | bool conf_get_changed(void)␊ |
997 | {␊ |
998 | ␉return sym_change_count;␊ |
999 | }␊ |
1000 | ␊ |
1001 | void conf_set_changed_callback(void (*fn)(void))␊ |
1002 | {␊ |
1003 | ␉conf_changed_callback = fn;␊ |
1004 | }␊ |
1005 | ␊ |
1006 | static void randomize_choice_values(struct symbol *csym)␊ |
1007 | {␊ |
1008 | ␉struct property *prop;␊ |
1009 | ␉struct symbol *sym;␊ |
1010 | ␉struct expr *e;␊ |
1011 | ␉int cnt, def;␊ |
1012 | ␊ |
1013 | ␉/*␊ |
1014 | ␉ * If choice is mod then we may have more items selected␊ |
1015 | ␉ * and if no then no-one.␊ |
1016 | ␉ * In both cases stop.␊ |
1017 | ␉ */␊ |
1018 | ␉if (csym->curr.tri != yes)␊ |
1019 | ␉␉return;␊ |
1020 | ␊ |
1021 | ␉prop = sym_get_choice_prop(csym);␊ |
1022 | ␊ |
1023 | ␉/* count entries in choice block */␊ |
1024 | ␉cnt = 0;␊ |
1025 | ␉expr_list_for_each_sym(prop->expr, e, sym)␊ |
1026 | ␉␉cnt++;␊ |
1027 | ␊ |
1028 | ␉/*␊ |
1029 | ␉ * find a random value and set it to yes,␊ |
1030 | ␉ * set the rest to no so we have only one set␊ |
1031 | ␉ */␊ |
1032 | ␉def = (rand() % cnt);␊ |
1033 | ␊ |
1034 | ␉cnt = 0;␊ |
1035 | ␉expr_list_for_each_sym(prop->expr, e, sym) {␊ |
1036 | ␉␉if (def == cnt++) {␊ |
1037 | ␉␉␉sym->def[S_DEF_USER].tri = yes;␊ |
1038 | ␉␉␉csym->def[S_DEF_USER].val = sym;␊ |
1039 | ␉␉}␊ |
1040 | ␉␉else {␊ |
1041 | ␉␉␉sym->def[S_DEF_USER].tri = no;␊ |
1042 | ␉␉}␊ |
1043 | ␉}␊ |
1044 | ␉csym->flags |= SYMBOL_DEF_USER;␊ |
1045 | ␉/* clear VALID to get value calculated */␊ |
1046 | ␉csym->flags &= ~(SYMBOL_VALID);␊ |
1047 | }␊ |
1048 | ␊ |
1049 | static void set_all_choice_values(struct symbol *csym)␊ |
1050 | {␊ |
1051 | ␉struct property *prop;␊ |
1052 | ␉struct symbol *sym;␊ |
1053 | ␉struct expr *e;␊ |
1054 | ␊ |
1055 | ␉prop = sym_get_choice_prop(csym);␊ |
1056 | ␊ |
1057 | ␉/*␊ |
1058 | ␉ * Set all non-assinged choice values to no␊ |
1059 | ␉ */␊ |
1060 | ␉expr_list_for_each_sym(prop->expr, e, sym) {␊ |
1061 | ␉␉if (!sym_has_value(sym))␊ |
1062 | ␉␉␉sym->def[S_DEF_USER].tri = no;␊ |
1063 | ␉}␊ |
1064 | ␉csym->flags |= SYMBOL_DEF_USER;␊ |
1065 | ␉/* clear VALID to get value calculated */␊ |
1066 | ␉csym->flags &= ~(SYMBOL_VALID);␊ |
1067 | }␊ |
1068 | ␊ |
1069 | void conf_set_all_new_symbols(enum conf_def_mode mode)␊ |
1070 | {␊ |
1071 | ␉struct symbol *sym, *csym;␊ |
1072 | ␉int i, cnt;␊ |
1073 | ␊ |
1074 | ␉for_all_symbols(i, sym) {␊ |
1075 | ␉␉if (sym_has_value(sym))␊ |
1076 | ␉␉␉continue;␊ |
1077 | ␉␉switch (sym_get_type(sym)) {␊ |
1078 | ␉␉case S_BOOLEAN:␊ |
1079 | ␉␉case S_TRISTATE:␊ |
1080 | ␉␉␉switch (mode) {␊ |
1081 | ␉␉␉case def_yes:␊ |
1082 | ␉␉␉␉sym->def[S_DEF_USER].tri = yes;␊ |
1083 | ␉␉␉␉break;␊ |
1084 | ␉␉␉case def_mod:␊ |
1085 | ␉␉␉␉sym->def[S_DEF_USER].tri = mod;␊ |
1086 | ␉␉␉␉break;␊ |
1087 | ␉␉␉case def_no:␊ |
1088 | ␉␉␉␉sym->def[S_DEF_USER].tri = no;␊ |
1089 | ␉␉␉␉break;␊ |
1090 | ␉␉␉case def_random:␊ |
1091 | ␉␉␉␉cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;␊ |
1092 | ␉␉␉␉sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);␊ |
1093 | ␉␉␉␉break;␊ |
1094 | ␉␉␉default:␊ |
1095 | ␉␉␉␉continue;␊ |
1096 | ␉␉␉}␊ |
1097 | ␉␉␉if (!(sym_is_choice(sym) && mode == def_random))␊ |
1098 | ␉␉␉␉sym->flags |= SYMBOL_DEF_USER;␊ |
1099 | ␉␉␉break;␊ |
1100 | ␉␉default:␊ |
1101 | ␉␉␉break;␊ |
1102 | ␉␉}␊ |
1103 | ␊ |
1104 | ␉}␊ |
1105 | ␊ |
1106 | ␉sym_clear_all_valid();␊ |
1107 | ␊ |
1108 | ␉/*␊ |
1109 | ␉ * We have different type of choice blocks.␊ |
1110 | ␉ * If curr.tri equals to mod then we can select several␊ |
1111 | ␉ * choice symbols in one block.␊ |
1112 | ␉ * In this case we do nothing.␊ |
1113 | ␉ * If curr.tri equals yes then only one symbol can be␊ |
1114 | ␉ * selected in a choice block and we set it to yes,␊ |
1115 | ␉ * and the rest to no.␊ |
1116 | ␉ */␊ |
1117 | ␉for_all_symbols(i, csym) {␊ |
1118 | ␉␉if (sym_has_value(csym) || !sym_is_choice(csym))␊ |
1119 | ␉␉␉continue;␊ |
1120 | ␊ |
1121 | ␉␉sym_calc_value(csym);␊ |
1122 | ␉␉if (mode == def_random)␊ |
1123 | ␉␉␉randomize_choice_values(csym);␊ |
1124 | ␉␉else␊ |
1125 | ␉␉␉set_all_choice_values(csym);␊ |
1126 | ␉}␊ |
1127 | }␊ |
1128 |