There is something wrong around this select to ADK_BROKEN
[openadk.git] / config / confdata.c
blob3bebe2c2291b0f1a5f6f8bf0b04cd55ef81031f1
1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
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>
13 #define LKC_DIRECT_LINK
14 #include "lkc.h"
16 int output_mode = 0;
18 const char conf_def_filename[] = ".config";
20 const char conf_defname[] = "Config.default";
22 const char *conf_confnames[] = {
23 ".config",
24 conf_defname,
25 NULL,
28 static char *conf_expand_value(const char *in)
30 struct symbol *sym;
31 const char *src;
32 static char res_value[SYMBOL_MAXLENGTH];
33 char *dst, name[SYMBOL_MAXLENGTH];
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(*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;
49 strcat(res_value, in);
51 return res_value;
54 char *conf_get_default_confname(void)
56 struct stat buf;
57 static char fullname[PATH_MAX+1];
58 char *env, *name;
60 name = conf_expand_value(conf_defname);
61 env = getenv(SRCTREE);
62 if (env) {
63 sprintf(fullname, "%s/%s", env, name);
64 if (!stat(fullname, &buf))
65 return fullname;
67 return name;
70 int conf_read(const char *name)
72 FILE *in = NULL;
73 char line[2048];
74 char *p, *p2;
75 int lineno = 0;
76 struct symbol *sym;
77 struct property *prop;
78 struct expr *e;
79 int i;
81 if (name) {
82 in = zconf_fopen(name);
83 } else {
84 const char **names = conf_confnames;
85 while ((name = *names++)) {
86 name = conf_expand_value(name);
87 in = zconf_fopen(name);
88 if (in) {
89 printf("#\n"
90 "# using defaults found in %s\n"
91 "#\n", name);
92 break;
97 if (!in)
98 return 1;
100 for_all_symbols(i, sym) {
101 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
102 sym->flags &= ~SYMBOL_VALID;
103 switch (sym->type) {
104 case S_INT:
105 case S_HEX:
106 case S_STRING:
107 if (sym->user.val)
108 free(sym->user.val);
109 default:
110 sym->user.val = NULL;
111 sym->user.tri = no;
115 while (fgets(line, sizeof(line), in)) {
116 lineno++;
117 sym = NULL;
118 switch (line[0]) {
119 case '#':
120 if (line[1]!=' ')
121 continue;
122 p = strchr(line + 2, ' ');
123 if (!p)
124 continue;
125 *p++ = 0;
126 if (strncmp(p, "is not set", 10))
127 continue;
128 sym = sym_find(line + 2);
129 if (!sym) {
130 fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 2);
131 break;
133 switch (sym->type) {
134 case S_BOOLEAN:
135 case S_TRISTATE:
136 sym->user.tri = no;
137 sym->flags &= ~SYMBOL_NEW;
138 break;
139 default:
142 break;
144 case 'A' ... 'Z':
145 p = strchr(line, '=');
146 if (!p)
147 continue;
148 *p++ = 0;
149 p2 = strchr(p, '\n');
150 if (p2)
151 *p2 = 0;
152 sym = sym_find(line);
153 if (!sym) {
154 fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line);
155 break;
157 switch (sym->type) {
158 case S_TRISTATE:
159 if (p[0] == 'm') {
160 sym->user.tri = mod;
161 sym->flags &= ~SYMBOL_NEW;
162 break;
164 case S_BOOLEAN:
165 if (p[0] == 'y') {
166 sym->user.tri = yes;
167 sym->flags &= ~SYMBOL_NEW;
168 break;
170 if (p[0] == 'n') {
171 sym->user.tri = no;
172 sym->flags &= ~SYMBOL_NEW;
173 break;
175 break;
176 case S_STRING:
177 if (*p++ != '"')
178 break;
179 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
180 if (*p2 == '"') {
181 *p2 = 0;
182 break;
184 memmove(p2, p2 + 1, strlen(p2));
186 if (!p2) {
187 fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
188 exit(1);
190 case S_INT:
191 case S_HEX:
192 if (sym_string_valid(sym, p)) {
193 sym->user.val = strdup(p);
194 sym->flags &= ~SYMBOL_NEW;
195 } else {
196 fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
197 exit(1);
199 break;
200 default:
203 break;
204 case '\n':
205 break;
206 default:
207 continue;
209 if (sym && sym_is_choice_value(sym)) {
210 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
211 switch (sym->user.tri) {
212 case no:
213 break;
214 case mod:
215 if (cs->user.tri == yes)
216 /* warn? */;
217 break;
218 case yes:
219 if (cs->user.tri != no)
220 /* warn? */;
221 cs->user.val = sym;
222 break;
224 cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
225 cs->flags &= ~SYMBOL_NEW;
228 fclose(in);
230 if (modules_sym)
231 sym_calc_value(modules_sym);
232 for_all_symbols(i, sym) {
233 sym_calc_value(sym);
234 if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
235 if (sym->visible == no)
236 sym->flags |= SYMBOL_NEW;
237 switch (sym->type) {
238 case S_STRING:
239 case S_INT:
240 case S_HEX:
241 if (!sym_string_within_range(sym, sym->user.val))
242 sym->flags |= SYMBOL_NEW;
243 default:
244 break;
247 if (!sym_is_choice(sym))
248 continue;
249 prop = sym_get_choice_prop(sym);
250 for (e = prop->expr; e; e = e->left.expr)
251 if (e->right.sym->visible != no)
252 sym->flags |= e->right.sym->flags & SYMBOL_NEW;
255 sym_change_count = 1;
257 return 0;
260 int conf_write(const char *name)
262 FILE *out, *out_h;
263 struct symbol *sym;
264 struct menu *menu;
265 const char *basename;
266 char dirname[128], tmpname[128], newname[128];
267 int type, l;
268 const char *str;
270 dirname[0] = 0;
271 if (name && name[0]) {
272 struct stat st;
273 char *slash;
275 if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
276 strcpy(dirname, name);
277 strcat(dirname, "/");
278 basename = conf_def_filename;
279 } else if ((slash = strrchr(name, '/'))) {
280 int size = slash - name + 1;
281 memcpy(dirname, name, size);
282 dirname[size] = 0;
283 if (slash[1])
284 basename = slash + 1;
285 else
286 basename = conf_def_filename;
287 } else
288 basename = name;
289 } else
290 basename = conf_def_filename;
292 sprintf(newname, "%s.tmpconfig.%d", dirname, getpid());
293 out = fopen(newname, "w");
294 if (!out)
295 return 1;
296 out_h = NULL;
297 if (!name) {
298 out_h = fopen(".tmpconfig.h", "w");
299 if (!out_h)
300 return 1;
302 fprintf(out, "#\n"
303 "# Automatically generated make config: don't edit\n"
304 "#\n");
305 if (out_h) {
306 fprintf(out_h, "/*\n"
307 " * Automatically generated header file: don't edit\n"
308 " */\n\n"
309 "#define AUTOCONF_INCLUDED\n\n"
310 "/* Version Number */\n"
311 "#define BB_VER \"%s\"\n"
312 "#define BB_BT \"%s\"\n",
313 getenv("VERSION"),
314 getenv("BUILDTIME"));
315 if (getenv("EXTRA_VERSION"))
316 fprintf(out_h, "#define BB_EXTRA_VERSION \"%s\"\n",
317 getenv("EXTRA_VERSION"));
318 fprintf(out_h, "\n");
321 if (!sym_change_count)
322 sym_clear_all_valid();
324 menu = rootmenu.list;
325 while (menu) {
326 sym = menu->sym;
327 if (!sym) {
328 if (!menu_is_visible(menu))
329 goto next;
330 str = menu_get_prompt(menu);
331 fprintf(out, "\n"
332 "#\n"
333 "# %s\n"
334 "#\n", str);
335 if (out_h)
336 fprintf(out_h, "\n"
337 "/*\n"
338 " * %s\n"
339 " */\n", str);
340 } else if (!(sym->flags & SYMBOL_CHOICE)) {
341 sym_calc_value(sym);
342 if (!(sym->flags & SYMBOL_WRITE) && !output_mode)
343 goto next;
344 sym->flags &= ~SYMBOL_WRITE;
345 type = sym->type;
346 if (type == S_TRISTATE) {
347 sym_calc_value(modules_sym);
348 if (modules_sym->curr.tri == no)
349 type = S_BOOLEAN;
351 switch (type) {
352 case S_BOOLEAN:
353 case S_TRISTATE:
354 switch (sym_get_tristate_value(sym)) {
355 case no:
356 fprintf(out, "# %s is not set\n", sym->name);
357 if (out_h)
358 fprintf(out_h, "#undef %s\n", sym->name);
359 break;
360 case mod:
361 fprintf(out, "%s=m\n", sym->name);
362 #if 0
363 if (out_h)
364 fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
365 #endif
366 break;
367 case yes:
368 fprintf(out, "%s=y\n", sym->name);
369 if (out_h)
370 fprintf(out_h, "#define %s 1\n", sym->name);
371 break;
373 break;
374 case S_STRING:
375 // fix me
376 str = sym_get_string_value(sym);
377 fprintf(out, "%s=\"", sym->name);
378 if (out_h)
379 fprintf(out_h, "#define %s \"", sym->name);
380 do {
381 l = strcspn(str, "\"\\");
382 if (l) {
383 fwrite(str, l, 1, out);
384 if (out_h)
385 fwrite(str, l, 1, out_h);
387 str += l;
388 while (*str == '\\' || *str == '"') {
389 fprintf(out, "\\%c", *str);
390 if (out_h)
391 fprintf(out_h, "\\%c", *str);
392 str++;
394 } while (*str);
395 fputs("\"\n", out);
396 if (out_h)
397 fputs("\"\n", out_h);
398 break;
399 case S_HEX:
400 str = sym_get_string_value(sym);
401 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
402 fprintf(out, "%s=%s\n", sym->name, str);
403 if (out_h)
404 fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
405 break;
407 case S_INT:
408 str = sym_get_string_value(sym);
409 fprintf(out, "%s=%s\n", sym->name, str);
410 if (out_h)
411 fprintf(out_h, "#define %s %s\n", sym->name, str);
412 break;
416 next:
417 if (menu->list) {
418 menu = menu->list;
419 continue;
421 if (menu->next)
422 menu = menu->next;
423 else while ((menu = menu->parent)) {
424 if (menu->next) {
425 menu = menu->next;
426 break;
430 fclose(out);
431 if (out_h) {
432 fclose(out_h);
433 rename(".tmpconfig.h", "include/config.h");
434 file_write_dep(NULL);
436 if (!name || basename != conf_def_filename) {
437 if (!name)
438 name = conf_def_filename;
439 sprintf(tmpname, "%s.old", name);
440 rename(name, tmpname);
442 sprintf(tmpname, "%s%s", dirname, basename);
443 if (rename(newname, tmpname))
444 return 1;
446 sym_change_count = 0;
448 return 0;