Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Cleanup and fixes based on Coverity pass
[palacios.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 static void conf_warning(const char *fmt, ...)
18         __attribute__ ((format (printf, 1, 2)));
19
20 static const char *conf_filename;
21 static int conf_lineno, conf_warnings, conf_unsaved;
22
23 const char conf_def_filename[] = ".config";
24
25 const char conf_defname[] = "arch/$ARCH/defconfig";
26
27 const char *conf_confnames[] = {
28         ".config",
29         conf_defname,
30         NULL,
31 };
32
33 static void conf_warning(const char *fmt, ...)
34 {
35         va_list ap;
36         va_start(ap, fmt);
37         fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
38         vfprintf(stderr, fmt, ap);
39         fprintf(stderr, "\n");
40         va_end(ap);
41         conf_warnings++;
42 }
43
44 static char *conf_expand_value(const char *in)
45 {
46         struct symbol *sym;
47         const char *src;
48         static char res_value[SYMBOL_MAXLENGTH];
49         char *dst, name[SYMBOL_MAXLENGTH];
50
51         res_value[0] = 0;
52         dst = name;
53         while ((src = strchr(in, '$'))) {
54                 strncat(res_value, in, src - in);
55                 src++;
56                 dst = name;
57                 while (isalnum(*src) || *src == '_')
58                         *dst++ = *src++;
59                 *dst = 0;
60                 sym = sym_lookup(name, 0);
61                 sym_calc_value(sym);
62                 strcat(res_value, sym_get_string_value(sym));
63                 in = src;
64         }
65         strcat(res_value, in);
66
67         return res_value;
68 }
69
70 char *conf_get_default_confname(void)
71 {
72         struct stat buf;
73         static char fullname[PATH_MAX+1];
74         char *env, *name;
75
76         name = conf_expand_value(conf_defname);
77         env = getenv(SRCTREE);
78         if (env) {
79                 sprintf(fullname, "%s/%s", env, name);
80                 if (!stat(fullname, &buf))
81                         return fullname;
82         }
83         return name;
84 }
85
86 int conf_read_simple(const char *name)
87 {
88         FILE *in = NULL;
89         char line[1024];
90         char *p, *p2;
91         struct symbol *sym;
92         int i;
93
94         if (name) {
95                 in = zconf_fopen(name);
96         } else {
97                 const char **names = conf_confnames;
98                 while ((name = *names++)) {
99                         name = conf_expand_value(name);
100                         in = zconf_fopen(name);
101                         if (in) {
102                                 printf(_("#\n"
103                                          "# using defaults found in %s\n"
104                                          "#\n"), name);
105                                 break;
106                         }
107                 }
108         }
109         if (!in)
110                 return 1;
111
112         conf_filename = name;
113         conf_lineno = 0;
114         conf_warnings = 0;
115         conf_unsaved = 0;
116
117         for_all_symbols(i, sym) {
118                 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
119                 if (sym_is_choice(sym))
120                         sym->flags &= ~SYMBOL_NEW;
121                 sym->flags &= ~SYMBOL_VALID;
122                 switch (sym->type) {
123                 case S_INT:
124                 case S_HEX:
125                 case S_STRING:
126                         if (sym->user.val)
127                                 free(sym->user.val);
128                 default:
129                         sym->user.val = NULL;
130                         sym->user.tri = no;
131                 }
132         }
133
134         while (fgets(line, sizeof(line), in)) {
135                 conf_lineno++;
136                 sym = NULL;
137                 switch (line[0]) {
138                 case '#':
139                         if (memcmp(line + 2, "V3_CONFIG_", 10))
140                                 continue;
141                         p = strchr(line + 12, ' ');
142                         if (!p)
143                                 continue;
144                         *p++ = 0;
145                         if (strncmp(p, "is not set", 10))
146                                 continue;
147                         sym = sym_find(line + 12);
148                         if (!sym) {
149                                 conf_warning("trying to assign nonexistent symbol %s", line + 12);
150                                 break;
151                         } else if (!(sym->flags & SYMBOL_NEW)) {
152                                 conf_warning("trying to reassign symbol %s", sym->name);
153                                 break;
154                         }
155                         switch (sym->type) {
156                         case S_BOOLEAN:
157                         case S_TRISTATE:
158                                 sym->user.tri = no;
159                                 sym->flags &= ~SYMBOL_NEW;
160                                 break;
161                         default:
162                                 ;
163                         }
164                         break;
165                 case 'V':
166                         if (memcmp(line, "V3_CONFIG_", 10)) {
167                                 conf_warning("unexpected data (1)");
168                                 continue;
169                         }
170                         p = strchr(line + 10, '=');
171                         if (!p)
172                                 continue;
173                         *p++ = 0;
174                         p2 = strchr(p, '\n');
175                         if (p2)
176                                 *p2 = 0;
177                         sym = sym_find(line + 10);
178                         if (!sym) {
179                                 conf_warning("trying to assign nonexistent symbol %s", line + 10);
180                                 break;
181                         } else if (!(sym->flags & SYMBOL_NEW)) {
182                                 conf_warning("trying to reassign symbol %s", sym->name);
183                                 break;
184                         }
185                         switch (sym->type) {
186                         case S_TRISTATE:
187                                 if (p[0] == 'm') {
188                                         sym->user.tri = mod;
189                                         sym->flags &= ~SYMBOL_NEW;
190                                         break;
191                                 }
192                         case S_BOOLEAN:
193                                 if (p[0] == 'y') {
194                                         sym->user.tri = yes;
195                                         sym->flags &= ~SYMBOL_NEW;
196                                         break;
197                                 }
198                                 if (p[0] == 'n') {
199                                         sym->user.tri = no;
200                                         sym->flags &= ~SYMBOL_NEW;
201                                         break;
202                                 }
203                                 conf_warning("symbol value '%s' invalid for %s", p, sym->name);
204                                 break;
205                         case S_STRING:
206                                 if (*p++ != '"')
207                                         break;
208                                 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
209                                         if (*p2 == '"') {
210                                                 *p2 = 0;
211                                                 break;
212                                         }
213                                         memmove(p2, p2 + 1, strlen(p2));
214                                 }
215                                 if (!p2) {
216                                         conf_warning("invalid string found");
217                                         continue;
218                                 }
219                         case S_INT:
220                         case S_HEX:
221                                 if (sym_string_valid(sym, p)) {
222                                         sym->user.val = strdup(p);
223                                         sym->flags &= ~SYMBOL_NEW;
224                                 } else {
225                                         conf_warning("symbol value '%s' invalid for %s", p, sym->name);
226                                         continue;
227                                 }
228                                 break;
229                         default:
230                                 ;
231                         }
232                         break;
233                 case '\n':
234                         break;
235                 default:
236                         conf_warning("unexpected data (2)");
237                         continue;
238                 }
239                 if (sym && sym_is_choice_value(sym)) {
240                         struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
241                         switch (sym->user.tri) {
242                         case no:
243                                 break;
244                         case mod:
245                                 if (cs->user.tri == yes) {
246                                         conf_warning("%s creates inconsistent choice state", sym->name);
247                                         cs->flags |= SYMBOL_NEW;
248                                 }
249                                 break;
250                         case yes:
251                                 if (cs->user.tri != no) {
252                                         conf_warning("%s creates inconsistent choice state", sym->name);
253                                         cs->flags |= SYMBOL_NEW;
254                                 } else
255                                         cs->user.val = sym;
256                                 break;
257                         }
258                         cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
259                 }
260         }
261         fclose(in);
262
263         if (modules_sym)
264                 sym_calc_value(modules_sym);
265         return 0;
266 }
267
268 int conf_read(const char *name)
269 {
270         struct symbol *sym;
271         struct property *prop;
272         struct expr *e;
273         int i;
274
275         if (conf_read_simple(name))
276                 return 1;
277
278         for_all_symbols(i, sym) {
279                 sym_calc_value(sym);
280                 if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
281                         goto sym_ok;
282                 if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
283                         /* check that calculated value agrees with saved value */
284                         switch (sym->type) {
285                         case S_BOOLEAN:
286                         case S_TRISTATE:
287                                 if (sym->user.tri != sym_get_tristate_value(sym))
288                                         break;
289                                 if (!sym_is_choice(sym))
290                                         goto sym_ok;
291                         default:
292                                 if (!strcmp(sym->curr.val, sym->user.val))
293                                         goto sym_ok;
294                                 break;
295                         }
296                 } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
297                         /* no previous value and not saved */
298                         goto sym_ok;
299                 conf_unsaved++;
300                 /* maybe print value in verbose mode... */
301         sym_ok:
302                 if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
303                         if (sym->visible == no)
304                                 sym->flags |= SYMBOL_NEW;
305                         switch (sym->type) {
306                         case S_STRING:
307                         case S_INT:
308                         case S_HEX:
309                                 if (!sym_string_within_range(sym, sym->user.val)) {
310                                         sym->flags |= SYMBOL_NEW;
311                                         sym->flags &= ~SYMBOL_VALID;
312                                 }
313                         default:
314                                 break;
315                         }
316                 }
317                 if (!sym_is_choice(sym))
318                         continue;
319                 prop = sym_get_choice_prop(sym);
320                 for (e = prop->expr; e; e = e->left.expr)
321                         if (e->right.sym->visible != no)
322                                 sym->flags |= e->right.sym->flags & SYMBOL_NEW;
323         }
324
325         sym_change_count = conf_warnings || conf_unsaved;
326
327         return 0;
328 }
329
330 int conf_write(const char *name)
331 {
332         FILE *out, *out_h;
333         struct symbol *sym;
334         struct menu *menu;
335         const char *basename;
336         char dirname[128], tmpname[128], newname[128];
337         int type, l;
338         const char *str;
339         time_t now;
340         int use_timestamp = 1;
341         char *env;
342
343         dirname[0] = 0;
344         if (name && name[0]) {
345                 struct stat st;
346                 char *slash;
347
348                 if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
349                         strcpy(dirname, name);
350                         strcat(dirname, "/");
351                         basename = conf_def_filename;
352                 } else if ((slash = strrchr(name, '/'))) {
353                         int size = slash - name + 1;
354                         memcpy(dirname, name, size);
355                         dirname[size] = 0;
356                         if (slash[1])
357                                 basename = slash + 1;
358                         else
359                                 basename = conf_def_filename;
360                 } else
361                         basename = name;
362         } else
363                 basename = conf_def_filename;
364
365         sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
366         out = fopen(newname, "w");
367         if (!out)
368                 return 1;
369         out_h = NULL;
370         if (!name) {
371                 out_h = fopen(".tmpconfig.h", "w");
372                 if (!out_h)
373                         return 1;
374                 file_write_dep(NULL);
375         }
376         sym = sym_lookup("KERNELVERSION", 0);
377         sym_calc_value(sym);
378         time(&now);
379         env = getenv("KCONFIG_NOTIMESTAMP");
380         if (env && *env)
381                 use_timestamp = 0;
382
383         fprintf(out, _("#\n"
384                        "# Automatically generated make config: don't edit\n"
385                        "#Palacios: %s\n"
386                        "%s%s"
387                        "#\n"),
388                      sym_get_string_value(sym),
389                      use_timestamp ? "# " : "",
390                      use_timestamp ? ctime(&now) : "");
391         if (out_h)
392                 fprintf(out_h, "/*\n"
393                                " * Automatically generated C config: don't edit\n"
394                                " * Palacios version: %s\n"
395                                "%s%s"
396                                " */\n"
397                                "#define AUTOCONF_INCLUDED\n",
398                                sym_get_string_value(sym),
399                                use_timestamp ? " * " : "",
400                                use_timestamp ? ctime(&now) : "");
401
402         if (!sym_change_count)
403                 sym_clear_all_valid();
404
405         menu = rootmenu.list;
406         while (menu) {
407                 sym = menu->sym;
408                 if (!sym) {
409                         if (!menu_is_visible(menu))
410                                 goto next;
411                         str = menu_get_prompt(menu);
412                         fprintf(out, "\n"
413                                      "#\n"
414                                      "# %s\n"
415                                      "#\n", str);
416                         if (out_h)
417                                 fprintf(out_h, "\n"
418                                                "/*\n"
419                                                " * %s\n"
420                                                " */\n", str);
421                 } else if (!(sym->flags & SYMBOL_CHOICE)) {
422                         sym_calc_value(sym);
423                         if (!(sym->flags & SYMBOL_WRITE))
424                                 goto next;
425                         sym->flags &= ~SYMBOL_WRITE;
426                         type = sym->type;
427                         if (type == S_TRISTATE) {
428                                 sym_calc_value(modules_sym);
429                                 if (modules_sym->curr.tri == no)
430                                         type = S_BOOLEAN;
431                         }
432                         switch (type) {
433                         case S_BOOLEAN:
434                         case S_TRISTATE:
435                                 switch (sym_get_tristate_value(sym)) {
436                                 case no:
437                                         fprintf(out, "# V3_CONFIG_%s is not set\n", sym->name);
438                                         if (out_h)
439                                                 fprintf(out_h, "#undef V3_CONFIG_%s\n", sym->name);
440                                         break;
441                                 case mod:
442                                         fprintf(out, "V3_CONFIG_%s=m\n", sym->name);
443                                         if (out_h)
444                                                 fprintf(out_h, "#define V3_CONFIG_%s_MODULE 1\n", sym->name);
445                                         break;
446                                 case yes:
447                                         fprintf(out, "V3_CONFIG_%s=y\n", sym->name);
448                                         if (out_h)
449                                                 fprintf(out_h, "#define V3_CONFIG_%s 1\n", sym->name);
450                                         break;
451                                 }
452                                 break;
453                         case S_STRING:
454                                 // fix me
455                                 str = sym_get_string_value(sym);
456                                 fprintf(out, "V3_CONFIG_%s=\"", sym->name);
457                                 if (out_h)
458                                         fprintf(out_h, "#define V3_CONFIG_%s \"", sym->name);
459                                 do {
460                                         l = strcspn(str, "\"\\");
461                                         if (l) {
462                                                 fwrite(str, l, 1, out);
463                                                 if (out_h)
464                                                         fwrite(str, l, 1, out_h);
465                                         }
466                                         str += l;
467                                         while (*str == '\\' || *str == '"') {
468                                                 fprintf(out, "\\%c", *str);
469                                                 if (out_h)
470                                                         fprintf(out_h, "\\%c", *str);
471                                                 str++;
472                                         }
473                                 } while (*str);
474                                 fputs("\"\n", out);
475                                 if (out_h)
476                                         fputs("\"\n", out_h);
477                                 break;
478                         case S_HEX:
479                                 str = sym_get_string_value(sym);
480                                 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
481                                         fprintf(out, "V3_CONFIG_%s=%s\n", sym->name, str);
482                                         if (out_h)
483                                                 fprintf(out_h, "#define V3_CONFIG_%s 0x%s\n", sym->name, str);
484                                         break;
485                                 }
486                         case S_INT:
487                                 str = sym_get_string_value(sym);
488                                 fprintf(out, "V3_CONFIG_%s=%s\n", sym->name, str);
489                                 if (out_h)
490                                         fprintf(out_h, "#define V3_CONFIG_%s %s\n", sym->name, str);
491                                 break;
492                         }
493                 }
494
495         next:
496                 if (menu->list) {
497                         menu = menu->list;
498                         continue;
499                 }
500                 if (menu->next)
501                         menu = menu->next;
502                 else while ((menu = menu->parent)) {
503                         if (menu->next) {
504                                 menu = menu->next;
505                                 break;
506                         }
507                 }
508         }
509         fclose(out);
510         if (out_h) {
511                 fclose(out_h);
512                 rename(".tmpconfig.h", "palacios/include/autoconf.h");
513         }
514         if (!name || basename != conf_def_filename) {
515                 if (!name)
516                         name = conf_def_filename;
517                 sprintf(tmpname, "%s.old", name);
518                 rename(name, tmpname);
519         }
520         sprintf(tmpname, "%s%s", dirname, basename);
521         if (rename(newname, tmpname))
522                 return 1;
523
524         sym_change_count = 0;
525
526         return 0;
527 }