Fix the location for the default config so 'make defconfig'
[oweals/busybox.git] / scripts / config / confdata.c
1 /*
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
18 const char conf_def_filename[] = ".config";
19
20 const char conf_defname[] = "sysdeps/linux/defconfig";
21
22 const char *conf_confnames[] = {
23         ".config",
24         conf_defname,
25         NULL,
26 };
27
28 static 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
54 char *conf_get_default_confname(void)
55 {
56         return conf_expand_value(conf_defname);
57 }
58
59 int 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
225 int 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 }