blob: 0d24ac52fc2164fb7fb301afd8b6731a55db1d29 [file] [log] [blame]
Eric Andersenc9f20d92002-12-05 08:41:41 +00001/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 *
5 * Allow 'n' as a symbol value.
6 * 2002-11-05 Petr Baudis <pasky@ucw.cz>
7 */
8
9#include <ctype.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14
15#define LKC_DIRECT_LINK
16#include "lkc.h"
17
18const char conf_def_filename[] = ".config";
19
Eric Andersenfa7532b2003-06-12 22:09:08 +000020const char conf_defname[] = "sysdeps/linux/defconfig";
Eric Andersenc9f20d92002-12-05 08:41:41 +000021
22const char *conf_confnames[] = {
23 ".config",
24 conf_defname,
25 NULL,
26};
27
28static char *conf_expand_value(const char *in)
29{
30 struct symbol *sym;
31 const char *src;
32 static char res_value[SYMBOL_MAXLENGTH];
33 char *dst, name[SYMBOL_MAXLENGTH];
34
35 res_value[0] = 0;
36 dst = name;
37 while ((src = strchr(in, '$'))) {
38 strncat(res_value, in, src - in);
39 src++;
40 dst = name;
41 while (isalnum((int)*src) || *src == '_')
42 *dst++ = *src++;
43 *dst = 0;
44 sym = sym_lookup(name, 0);
45 sym_calc_value(sym);
46 strcat(res_value, sym_get_string_value(sym));
47 in = src;
48 }
49 strcat(res_value, in);
50
51 return res_value;
52}
53
54char *conf_get_default_confname(void)
55{
56 return conf_expand_value(conf_defname);
57}
58
59int conf_read(const char *name)
60{
61 FILE *in = NULL;
62 char line[1024];
63 char *p, *p2;
64 int lineno = 0;
65 struct symbol *sym;
66 struct property *prop;
67 struct expr *e;
68 int i;
69
70 if (name) {
71 in = fopen(name, "r");
72 } else {
73 const char **names = conf_confnames;
74 while ((name = *names++)) {
75 name = conf_expand_value(name);
76 in = fopen(name, "r");
77 if (in) {
78 printf("#\n"
79 "# using defaults found in %s\n"
80 "#\n", name);
81 break;
82 }
83 }
84 }
85
86 if (!in)
87 return 1;
88
89 for_all_symbols(i, sym) {
90 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
91 sym->flags &= ~SYMBOL_VALID;
92 switch (sym->type) {
93 case S_INT:
94 case S_HEX:
95 case S_STRING:
96 if (S_VAL(sym->def))
97 free(S_VAL(sym->def));
98 default:
99 S_VAL(sym->def) = NULL;
100 S_TRI(sym->def) = no;
101 ;
102 }
103 }
104
105 while (fgets(line, sizeof(line), in)) {
106 lineno++;
107 switch (line[0]) {
108 case '\n':
109 break;
110 case ' ':
111 break;
112 case '#':
113 p = strchr(line, ' ');
114 if (!p)
115 continue;
116 *p++ = 0;
117 p = strchr(p, ' ');
118 if (!p)
119 continue;
120 *p++ = 0;
121 if (strncmp(p, "is not set", 10))
122 continue;
123 sym = sym_lookup(line+2, 0);
124 switch (sym->type) {
125 case S_BOOLEAN:
126 case S_TRISTATE:
127 sym->def = symbol_no.curr;
128 sym->flags &= ~SYMBOL_NEW;
129 break;
130 default:
131 ;
132 }
133 break;
134 case 'A' ... 'Z':
135 p = strchr(line, '=');
136 if (!p)
137 continue;
138 *p++ = 0;
139 p2 = strchr(p, '\n');
140 if (p2)
141 *p2 = 0;
142 sym = sym_find(line);
143 if (!sym) {
144 fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line);
145 break;
146 }
147 switch (sym->type) {
148 case S_TRISTATE:
149 if (p[0] == 'm') {
150 S_TRI(sym->def) = mod;
151 sym->flags &= ~SYMBOL_NEW;
152 break;
153 }
154 case S_BOOLEAN:
155 if (p[0] == 'y') {
156 S_TRI(sym->def) = yes;
157 sym->flags &= ~SYMBOL_NEW;
158 break;
159 }
160 if (p[0] == 'n') {
161 S_TRI(sym->def) = no;
162 sym->flags &= ~SYMBOL_NEW;
163 break;
164 }
165 break;
166 case S_STRING:
167 if (*p++ != '"')
168 break;
169 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
170 if (*p2 == '"') {
171 *p2 = 0;
172 break;
173 }
174 memmove(p2, p2 + 1, strlen(p2));
175 }
176 case S_INT:
177 case S_HEX:
178 if (sym_string_valid(sym, p)) {
179 S_VAL(sym->def) = strdup(p);
180 sym->flags &= ~SYMBOL_NEW;
181 } else
182 fprintf(stderr, "%s:%d:symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
183 break;
184 default:
185 ;
186 }
187 if (sym_is_choice_value(sym)) {
188 prop = sym_get_choice_prop(sym);
189 switch (S_TRI(sym->def)) {
190 case mod:
191 if (S_TRI(prop->def->def) == yes)
192 /* warn? */;
193 break;
194 case yes:
195 if (S_TRI(prop->def->def) != no)
196 /* warn? */;
197 S_VAL(prop->def->def) = sym;
198 break;
199 case no:
200 break;
201 }
202 S_TRI(prop->def->def) = S_TRI(sym->def);
203 }
204 break;
205 default:
206 continue;
207 }
208 }
209 fclose(in);
210
211 for_all_symbols(i, sym) {
212 if (!sym_is_choice(sym))
213 continue;
214 prop = sym_get_choice_prop(sym);
215 for (e = prop->dep; e; e = e->left.expr)
216 sym->flags |= e->right.sym->flags & SYMBOL_NEW;
217 sym->flags &= ~SYMBOL_NEW;
218 }
219
220 sym_change_count = 1;
221
222 return 0;
223}
224
225int conf_write(const char *name)
226{
227 FILE *out, *out_h;
228 struct symbol *sym;
229 struct menu *menu;
230 char oldname[128];
231 int type, l;
232 const char *str;
233
234 out = fopen(".tmpconfig", "w");
235 if (!out)
236 return 1;
237 out_h = fopen(".tmpconfig.h", "w");
238 if (!out_h)
239 return 1;
240 fprintf(out, "#\n"
241 "# Automatically generated make config: don't edit\n"
242 "#\n");
243 fprintf(out_h, "/*\n"
244 " * Automatically generated header file: don't edit\n"
245 " */\n\n"
246 "#define AUTOCONF_INCLUDED\n\n"
247 "/* Version Number */\n"
248 "#define BB_VER \"%s\"\n"
249 "#define BB_BT \"%s\"\n\n",
250 getenv("VERSION"),
251 getenv("BUILDTIME")
252 );
253
254 if (!sym_change_count)
255 sym_clear_all_valid();
256
257 menu = rootmenu.list;
258 while (menu) {
259 sym = menu->sym;
260 if (!sym) {
261 if (!menu_is_visible(menu))
262 goto next;
263 str = menu_get_prompt(menu);
264 fprintf(out, "\n"
265 "#\n"
266 "# %s\n"
267 "#\n", str);
268 fprintf(out_h, "\n"
269 "/*\n"
270 " * %s\n"
271 " */\n", str);
272 } else if (!(sym->flags & SYMBOL_CHOICE)) {
273 sym_calc_value(sym);
274 if (!(sym->flags & SYMBOL_WRITE))
275 goto next;
276 sym->flags &= ~SYMBOL_WRITE;
277 type = sym->type;
278 if (type == S_TRISTATE) {
279 sym_calc_value(modules_sym);
280 if (S_TRI(modules_sym->curr) == no)
281 type = S_BOOLEAN;
282 }
283 switch (type) {
284 case S_BOOLEAN:
285 case S_TRISTATE:
286 switch (sym_get_tristate_value(sym)) {
287 case no:
288 fprintf(out, "# %s is not set\n", sym->name);
289 fprintf(out_h, "#undef %s\n", sym->name);
290 break;
291 case mod:
292#if 0
293 fprintf(out, "%s=m\n", sym->name);
294 fprintf(out_h, "#define __%s__MODULE 1\n", sym->name);
295#endif
296 break;
297 case yes:
298 fprintf(out, "%s=y\n", sym->name);
299 fprintf(out_h, "#define %s 1\n", sym->name);
300 break;
301 }
302 break;
303 case S_STRING:
304 // fix me
305 str = sym_get_string_value(sym);
306 fprintf(out, "%s=\"", sym->name);
307 fprintf(out_h, "#define %s \"", sym->name);
308 do {
309 l = strcspn(str, "\"\\");
310 if (l) {
311 fwrite(str, l, 1, out);
312 fwrite(str, l, 1, out_h);
313 }
314 str += l;
315 while (*str == '\\' || *str == '"') {
316 fprintf(out, "\\%c", *str);
317 fprintf(out_h, "\\%c", *str);
318 str++;
319 }
320 } while (*str);
321 fputs("\"\n", out);
322 fputs("\"\n", out_h);
323 break;
324 case S_HEX:
325 str = sym_get_string_value(sym);
326 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
327 fprintf(out, "%s=%s\n", sym->name, str);
328 fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
329 break;
330 }
331 case S_INT:
332 str = sym_get_string_value(sym);
333 fprintf(out, "%s=%s\n", sym->name, str);
334 fprintf(out_h, "#define %s %s\n", sym->name, str);
335 break;
336 }
337 }
338
339 next:
340 if (menu->list) {
341 menu = menu->list;
342 continue;
343 }
344 if (menu->next)
345 menu = menu->next;
346 else while ((menu = menu->parent)) {
347 if (menu->next) {
348 menu = menu->next;
349 break;
350 }
351 }
352 }
353 fclose(out);
354 fclose(out_h);
355
356 if (!name) {
357 rename(".tmpconfig.h", "include/config.h");
358 name = conf_def_filename;
359 file_write_dep(NULL);
360 } else
361 unlink(".tmpconfig.h");
362
363 sprintf(oldname, "%s.old", name);
364 rename(name, oldname);
365 if (rename(".tmpconfig", name))
366 return 1;
367
368 sym_change_count = 0;
369
370 return 0;
371}