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