source: menu/confdata.c@ 44994cb

experimental
Last change on this file since 44994cb was 613d46b, checked in by George Boudreau <georgeb@…>, 18 years ago

Added new configuration tool.. <make> menuconfig. Needs work, especially inline help text

  • Property mode set to 100644
File size: 7.8 KB
Line 
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 <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <unistd.h>
12
13#define LKC_DIRECT_LINK
14#include "lkc.h"
15
16const char conf_def_filename[] = "configuration";
17
18const char conf_defname[] = "defconfig";
19
20const char *conf_confnames[] = {
21 "configuration",
22 conf_defname,
23 NULL,
24};
25
26static char *conf_expand_value(const char *in)
27{
28 struct symbol *sym;
29 const char *src;
30 static char res_value[SYMBOL_MAXLENGTH];
31 char *dst, name[SYMBOL_MAXLENGTH];
32
33 res_value[0] = 0;
34 dst = name;
35 while ((src = strchr(in, '$'))) {
36 strncat(res_value, in, src - in);
37 src++;
38 dst = name;
39 while (isalnum(*src) || *src == '_')
40 *dst++ = *src++;
41 *dst = 0;
42 sym = sym_lookup(name, 0);
43 sym_calc_value(sym);
44 strcat(res_value, sym_get_string_value(sym));
45 in = src;
46 }
47 strcat(res_value, in);
48
49 return res_value;
50}
51
52int conf_read(const char *name)
53{
54 FILE *in = NULL;
55 char line[1024];
56 char *p, *p2;
57 int lineno = 0;
58 struct symbol *sym;
59 struct property *prop;
60 struct expr *e;
61 int i;
62
63 if (name) {
64 in = zconf_fopen(name);
65 } else {
66 const char **names = conf_confnames;
67 while ((name = *names++)) {
68 name = conf_expand_value(name);
69 in = zconf_fopen(name);
70 if (in) {
71 printf("#\n"
72 "# using defaults found in %s\n"
73 "#\n", name);
74 break;
75 }
76 }
77 }
78
79 if (!in)
80 return 1;
81
82 for_all_symbols(i, sym) {
83 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
84 sym->flags &= ~SYMBOL_VALID;
85 switch (sym->type) {
86 case S_INT:
87 case S_HEX:
88 case S_STRING:
89 free(sym->user.val);
90 default:
91 sym->user.val = NULL;
92 sym->user.tri = no;
93 }
94 }
95
96 while (fgets(line, sizeof(line), in)) {
97 lineno++;
98 sym = NULL;
99 switch (line[0]) {
100 case '#':
101 if (line[1]!=' ')
102 continue;
103 p = strchr(line + 2, ' ');
104 if (!p)
105 continue;
106 *p++ = 0;
107 if (strncmp(p, "is not set", 10))
108 continue;
109 sym = sym_find(line + 2);
110 if (!sym) {
111 fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 2);
112 break;
113 }
114 switch (sym->type) {
115 case S_BOOLEAN:
116 case S_TRISTATE:
117 sym->user.tri = no;
118 sym->flags &= ~SYMBOL_NEW;
119 break;
120 default:
121 ;
122 }
123 break;
124
125 case 'A' ... 'Z':
126 p = strchr(line, '=');
127 if (!p)
128 continue;
129 *p++ = 0;
130 p2 = strchr(p, '\n');
131 if (p2)
132 *p2 = 0;
133 sym = sym_find(line);
134 if (!sym) {
135 fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line);
136 break;
137 }
138 switch (sym->type) {
139 case S_TRISTATE:
140 if (p[0] == 'm') {
141 sym->user.tri = mod;
142 sym->flags &= ~SYMBOL_NEW;
143 break;
144 }
145 case S_BOOLEAN:
146 if (p[0] == 'y') {
147 sym->user.tri = yes;
148 sym->flags &= ~SYMBOL_NEW;
149 break;
150 }
151 if (p[0] == 'n') {
152 sym->user.tri = no;
153 sym->flags &= ~SYMBOL_NEW;
154 break;
155 }
156 break;
157 case S_STRING:
158 if (*p++ != '"')
159 break;
160 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
161 if (*p2 == '"') {
162 *p2 = 0;
163 break;
164 }
165 memmove(p2, p2 + 1, strlen(p2));
166 }
167 if (!p2) {
168 fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
169 exit(1);
170 }
171 case S_INT:
172 case S_HEX:
173 if (sym_string_valid(sym, p)) {
174 sym->user.val = strdup(p);
175 sym->flags &= ~SYMBOL_NEW;
176 } else {
177 fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
178 exit(1);
179 }
180 break;
181 default:
182 ;
183 }
184 break;
185 case '\n':
186 break;
187 default:
188 continue;
189 }
190 if (sym && sym_is_choice_value(sym)) {
191 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
192 switch (sym->user.tri) {
193 case no:
194 break;
195 case mod:
196 if (cs->user.tri == yes)
197 /* warn? */;
198 break;
199 case yes:
200 if (cs->user.tri != no)
201 /* warn? */;
202 cs->user.val = sym;
203 break;
204 }
205 cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
206 cs->flags &= ~SYMBOL_NEW;
207 }
208 }
209 fclose(in);
210
211 if (modules_sym)
212 sym_calc_value(modules_sym);
213 for_all_symbols(i, sym) {
214 sym_calc_value(sym);
215 if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
216 if (sym->visible == no)
217 sym->flags |= SYMBOL_NEW;
218 switch (sym->type) {
219 case S_STRING:
220 case S_INT:
221 case S_HEX:
222 if (!sym_string_within_range(sym, sym->user.val))
223 sym->flags |= SYMBOL_NEW;
224 default:
225 break;
226 }
227 }
228 if (!sym_is_choice(sym))
229 continue;
230 prop = sym_get_choice_prop(sym);
231 for (e = prop->expr; e; e = e->left.expr)
232 if (e->right.sym->visible != no)
233 sym->flags |= e->right.sym->flags & SYMBOL_NEW;
234 }
235
236 sym_change_count = 1;
237
238 return 0;
239}
240
241struct menu *next_menu(struct menu *menu)
242{
243 if (menu->list) return menu->list;
244 do {
245 if (menu->next) {
246 menu = menu->next;
247 break;
248 }
249 } while ((menu = menu->parent));
250
251 return menu;
252}
253
254#define SYMBOL_FORCEWRITE (1<<31)
255
256int conf_write(const char *name)
257{
258 FILE *out;
259 struct symbol *sym;
260 struct menu *menu;
261 const char *basename;
262 char dirname[128], tmpname[128], newname[128];
263 int type, l;
264 const char *str;
265
266 dirname[0] = 0;
267 if (name && name[0]) {
268 struct stat st;
269 char *slash;
270
271 if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
272 strcpy(dirname, name);
273 strcat(dirname, "/");
274 basename = conf_def_filename;
275 } else if ((slash = strrchr(name, '/'))) {
276 int size = slash - name + 1;
277 memcpy(dirname, name, size);
278 dirname[size] = 0;
279 if (slash[1])
280 basename = slash + 1;
281 else
282 basename = conf_def_filename;
283 } else
284 basename = name;
285 } else
286 basename = conf_def_filename;
287
288 sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
289 out = fopen(newname, "w");
290 if (!out)
291 return 1;
292 fprintf(out, "#\n"
293 "# Automatically generated configuration: don't edit\n"
294 "# use make menuconfig or make config to make changes\n"
295 "#\n");
296
297 if (!sym_change_count)
298 sym_clear_all_valid();
299
300 /* Force write of all non-duplicate symbols. */
301
302 /* Write out everything by default. */
303 for(menu = rootmenu.list; menu; menu = next_menu(menu))
304 if (menu->sym) menu->sym->flags |= SYMBOL_FORCEWRITE;
305
306 menu = rootmenu.list;
307 while (menu) {
308 sym = menu->sym;
309 if (!sym) {
310 if (!menu_is_visible(menu))
311 goto next;
312 str = menu_get_prompt(menu);
313 fprintf(out, "\n"
314 "#\n"
315 "# %s\n"
316 "#\n", str);
317 } else if (!(sym->flags & SYMBOL_CHOICE)) {
318 sym_calc_value(sym);
319 if (!(sym->flags & SYMBOL_FORCEWRITE))
320 goto next;
321
322 sym->flags &= ~SYMBOL_FORCEWRITE;
323 type = sym->type;
324 if (type == S_TRISTATE) {
325 sym_calc_value(modules_sym);
326 if (modules_sym->curr.tri == no)
327 type = S_BOOLEAN;
328 }
329
330
331 switch (type) {
332 case S_BOOLEAN:
333 case S_TRISTATE:
334 switch (sym_get_tristate_value(sym)) {
335 case no:
336 fprintf(out, "# %s is not set\n", sym->name);
337 break;
338 case mod:
339 fprintf(out, "%s=m\n", sym->name);
340 break;
341 case yes:
342 fprintf(out, "%s=y\n", sym->name);
343 break;
344 }
345 break;
346 case S_STRING:
347 // fix me
348 str = sym_get_string_value(sym);
349 fprintf(out, "%s=\"", sym->name);
350 do {
351 l = strcspn(str, "\"\\");
352 if (l) {
353 fwrite(str, l, 1, out);
354 }
355 str += l;
356 while (*str == '\\' || *str == '"') {
357 fprintf(out, "\\%c", *str);
358 str++;
359 }
360 } while (*str);
361 fputs("\"\n", out);
362 break;
363 case S_HEX:
364 str = sym_get_string_value(sym);
365 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
366 fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
367 break;
368 }
369 case S_INT:
370 str = sym_get_string_value(sym);
371 fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
372 break;
373 }
374 }
375next:
376 menu = next_menu(menu);
377 }
378 fclose(out);
379 if (!name || basename != conf_def_filename) {
380 if (!name)
381 name = conf_def_filename;
382 sprintf(tmpname, "%s.old", name);
383 rename(name, tmpname);
384 }
385 sprintf(tmpname, "%s%s", dirname, basename);
386 if (rename(newname, tmpname))
387 return 1;
388
389 sym_change_count = 0;
390
391 return 0;
392}
Note: See TracBrowser for help on using the repository browser.