switch4g: completely re-writen
[tomato.git] / release / src / router / config / confdata.c
blobbb520d7b62015d0427437dc31573d27d1d475d41
1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
5 * Allow 'n' as a symbol value.
6 * 2002-11-05 Petr Baudis <pasky@ucw.cz>
7 */
9 #include <ctype.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
15 #define LKC_DIRECT_LINK
16 #include "lkc.h"
18 const char conf_def_filename[] = ".config";
20 const char conf_defname[] = "extra/Configs/Config.$TARGET_ARCH.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((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;
49 strcat(res_value, in);
51 return res_value;
54 char *conf_get_default_confname(void)
56 return conf_expand_value(conf_defname);
59 int conf_read(const char *name)
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;
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;
86 if (!in)
87 return 1;
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;
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:
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;
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;
154 case S_BOOLEAN:
155 if (p[0] == 'y') {
156 S_TRI(sym->def) = yes;
157 sym->flags &= ~SYMBOL_NEW;
158 break;
160 if (p[0] == 'n') {
161 S_TRI(sym->def) = no;
162 sym->flags &= ~SYMBOL_NEW;
163 break;
165 break;
166 case S_STRING:
167 case S_INT:
168 case S_HEX:
169 if (sym_string_valid(sym, p)) {
170 S_VAL(sym->def) = strdup(p);
171 sym->flags &= ~SYMBOL_NEW;
172 } else
173 fprintf(stderr, "%s:%d:symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
174 break;
175 default:
178 if (sym_is_choice_value(sym)) {
179 prop = sym_get_choice_prop(sym);
180 switch (S_TRI(sym->def)) {
181 case mod:
182 if (S_TRI(prop->def->def) == yes)
183 /* warn? */;
184 break;
185 case yes:
186 if (S_TRI(prop->def->def) != no)
187 /* warn? */;
188 S_VAL(prop->def->def) = sym;
189 break;
190 case no:
191 break;
193 S_TRI(prop->def->def) = S_TRI(sym->def);
195 break;
196 default:
197 continue;
200 fclose(in);
202 for_all_symbols(i, sym) {
203 if (!sym_is_choice(sym))
204 continue;
205 prop = sym_get_choice_prop(sym);
206 for (e = prop->dep; e; e = e->left.expr)
207 sym->flags |= e->right.sym->flags & SYMBOL_NEW;
208 sym->flags &= ~SYMBOL_NEW;
211 sym_change_count = 1;
213 return 0;
216 int conf_write(const char *name)
218 FILE *out, *out_h;
219 struct symbol *sym;
220 struct menu *menu;
221 char oldname[128];
222 int type, l;
223 const char *str;
225 out = fopen(".tmpconfig", "w");
226 if (!out)
227 return 1;
228 out_h = fopen(".tmpconfig.h", "w");
229 if (!out_h)
230 return 1;
231 fprintf(out, "#\n"
232 "# Automatically generated make config: don't edit\n"
233 "#\n");
234 fprintf(out_h, "/*\n"
235 " * Automatically generated C config: don't edit\n"
236 " */\n"
239 if (!sym_change_count)
240 sym_clear_all_valid();
242 menu = rootmenu.list;
243 while (menu) {
244 sym = menu->sym;
245 if (!sym) {
246 if (!menu_is_visible(menu))
247 goto next;
248 str = menu_get_prompt(menu);
249 fprintf(out, "\n"
250 "#\n"
251 "# %s\n"
252 "#\n", str);
253 fprintf(out_h, "\n"
254 "/*\n"
255 " * %s\n"
256 " */\n", str);
257 } else if (!(sym->flags & SYMBOL_CHOICE)) {
258 sym_calc_value(sym);
259 if (!(sym->flags & SYMBOL_WRITE))
260 goto next;
261 sym->flags &= ~SYMBOL_WRITE;
262 type = sym->type;
263 if (type == S_TRISTATE) {
264 sym_calc_value(modules_sym);
265 if (S_TRI(modules_sym->curr) == no)
266 type = S_BOOLEAN;
268 switch (type) {
269 case S_BOOLEAN:
270 case S_TRISTATE:
271 switch (sym_get_tristate_value(sym)) {
272 case no:
273 fprintf(out, "# %s is not set\n", sym->name);
274 fprintf(out_h, "#undef %s\n", sym->name);
275 fprintf(out_h, " #define IF_%s(...)\n", sym->name);
276 fprintf(out_h, " #define IF_NOT_%s(...) __VA_ARGS__\n", sym->name);
277 break;
278 case mod:
279 fprintf(out, "%s=m\n", sym->name);
280 fprintf(out_h, "#define %s__MODULE 1\n", sym->name);
281 fprintf(out_h, " #define IF_%s__MODULE(...) __VA_ARGS__\n", sym->name);
282 fprintf(out_h, " #define IF_%s(...) __VA_ARGS__\n", sym->name);
283 fprintf(out_h, " #define IF_NOT_%s(...)\n", sym->name);
284 break;
285 case yes:
286 fprintf(out, "%s=y\n", sym->name);
287 fprintf(out_h, "#define %s 1\n", sym->name);
288 fprintf(out_h, " #define IF_%s(...) __VA_ARGS__\n", sym->name);
289 fprintf(out_h, " #define IF_NOT_%s(...)\n", sym->name);
290 break;
292 break;
293 case S_STRING:
294 // fix me
295 str = sym_get_string_value(sym);
296 fprintf(out, "%s=", sym->name);
297 fprintf(out_h, "#define %s \"", sym->name);
298 do {
299 l = strcspn(str, "\"\\");
300 if (l) {
301 fwrite(str, l, 1, out);
302 fwrite(str, l, 1, out_h);
304 str += l;
305 while (*str == '\\' || *str == '"') {
306 fprintf(out, "\\%c", *str);
307 fprintf(out_h, "\\%c", *str);
308 str++;
310 } while (*str);
311 fputs("\n", out);
312 fputs("\"\n", out_h);
313 break;
314 case S_HEX:
315 str = sym_get_string_value(sym);
316 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
317 fprintf(out, "%s=%s\n", sym->name, str);
318 fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
319 break;
321 case S_INT:
322 str = sym_get_string_value(sym);
323 fprintf(out, "%s=%s\n", sym->name, str);
324 fprintf(out_h, "#define %s %s\n", sym->name, str);
325 break;
329 next:
330 if (menu->list) {
331 menu = menu->list;
332 continue;
334 if (menu->next)
335 menu = menu->next;
336 else while ((menu = menu->parent)) {
337 if (menu->next) {
338 menu = menu->next;
339 break;
343 fclose(out);
344 fclose(out_h);
346 if (!name) {
347 rename(".tmpconfig.h", "shared/tomato_config.h");
348 name = conf_def_filename;
349 file_write_dep(NULL);
350 } else
351 unlink(".tmpconfig.h");
353 sprintf(oldname, "%s.old", name);
354 rename(name, oldname);
355 if (rename(".tmpconfig", name))
356 return 1;
358 sym_change_count = 0;
360 return 0;