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