kconfig: environment symbol support
[linux-2.6] / scripts / kconfig / symbol.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 <ctype.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <regex.h>
10 #include <sys/utsname.h>
11
12 #define LKC_DIRECT_LINK
13 #include "lkc.h"
14
15 struct symbol symbol_yes = {
16         .name = "y",
17         .curr = { "y", yes },
18         .flags = SYMBOL_CONST|SYMBOL_VALID,
19 }, symbol_mod = {
20         .name = "m",
21         .curr = { "m", mod },
22         .flags = SYMBOL_CONST|SYMBOL_VALID,
23 }, symbol_no = {
24         .name = "n",
25         .curr = { "n", no },
26         .flags = SYMBOL_CONST|SYMBOL_VALID,
27 }, symbol_empty = {
28         .name = "",
29         .curr = { "", no },
30         .flags = SYMBOL_VALID,
31 };
32
33 struct symbol *sym_defconfig_list;
34 struct symbol *modules_sym;
35 tristate modules_val;
36
37 struct expr *sym_env_list;
38
39 void sym_add_default(struct symbol *sym, const char *def)
40 {
41         struct property *prop = prop_alloc(P_DEFAULT, sym);
42
43         prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
44 }
45
46 void sym_init(void)
47 {
48         struct symbol *sym;
49         struct utsname uts;
50         char *p;
51         static bool inited = false;
52
53         if (inited)
54                 return;
55         inited = true;
56
57         uname(&uts);
58
59         sym = sym_lookup("ARCH", 0);
60         sym->type = S_STRING;
61         sym->flags |= SYMBOL_AUTO;
62         p = getenv("ARCH");
63         if (p)
64                 sym_add_default(sym, p);
65
66         sym = sym_lookup("KERNELVERSION", 0);
67         sym->type = S_STRING;
68         sym->flags |= SYMBOL_AUTO;
69         p = getenv("KERNELVERSION");
70         if (p)
71                 sym_add_default(sym, p);
72
73         sym = sym_lookup("UNAME_RELEASE", 0);
74         sym->type = S_STRING;
75         sym->flags |= SYMBOL_AUTO;
76         sym_add_default(sym, uts.release);
77 }
78
79 enum symbol_type sym_get_type(struct symbol *sym)
80 {
81         enum symbol_type type = sym->type;
82
83         if (type == S_TRISTATE) {
84                 if (sym_is_choice_value(sym) && sym->visible == yes)
85                         type = S_BOOLEAN;
86                 else if (modules_val == no)
87                         type = S_BOOLEAN;
88         }
89         return type;
90 }
91
92 const char *sym_type_name(enum symbol_type type)
93 {
94         switch (type) {
95         case S_BOOLEAN:
96                 return "boolean";
97         case S_TRISTATE:
98                 return "tristate";
99         case S_INT:
100                 return "integer";
101         case S_HEX:
102                 return "hex";
103         case S_STRING:
104                 return "string";
105         case S_UNKNOWN:
106                 return "unknown";
107         case S_OTHER:
108                 break;
109         }
110         return "???";
111 }
112
113 struct property *sym_get_choice_prop(struct symbol *sym)
114 {
115         struct property *prop;
116
117         for_all_choices(sym, prop)
118                 return prop;
119         return NULL;
120 }
121
122 struct property *sym_get_env_prop(struct symbol *sym)
123 {
124         struct property *prop;
125
126         for_all_properties(sym, prop, P_ENV)
127                 return prop;
128         return NULL;
129 }
130
131 struct property *sym_get_default_prop(struct symbol *sym)
132 {
133         struct property *prop;
134
135         for_all_defaults(sym, prop) {
136                 prop->visible.tri = expr_calc_value(prop->visible.expr);
137                 if (prop->visible.tri != no)
138                         return prop;
139         }
140         return NULL;
141 }
142
143 struct property *sym_get_range_prop(struct symbol *sym)
144 {
145         struct property *prop;
146
147         for_all_properties(sym, prop, P_RANGE) {
148                 prop->visible.tri = expr_calc_value(prop->visible.expr);
149                 if (prop->visible.tri != no)
150                         return prop;
151         }
152         return NULL;
153 }
154
155 static int sym_get_range_val(struct symbol *sym, int base)
156 {
157         sym_calc_value(sym);
158         switch (sym->type) {
159         case S_INT:
160                 base = 10;
161                 break;
162         case S_HEX:
163                 base = 16;
164                 break;
165         default:
166                 break;
167         }
168         return strtol(sym->curr.val, NULL, base);
169 }
170
171 static void sym_validate_range(struct symbol *sym)
172 {
173         struct property *prop;
174         int base, val, val2;
175         char str[64];
176
177         switch (sym->type) {
178         case S_INT:
179                 base = 10;
180                 break;
181         case S_HEX:
182                 base = 16;
183                 break;
184         default:
185                 return;
186         }
187         prop = sym_get_range_prop(sym);
188         if (!prop)
189                 return;
190         val = strtol(sym->curr.val, NULL, base);
191         val2 = sym_get_range_val(prop->expr->left.sym, base);
192         if (val >= val2) {
193                 val2 = sym_get_range_val(prop->expr->right.sym, base);
194                 if (val <= val2)
195                         return;
196         }
197         if (sym->type == S_INT)
198                 sprintf(str, "%d", val2);
199         else
200                 sprintf(str, "0x%x", val2);
201         sym->curr.val = strdup(str);
202 }
203
204 static void sym_calc_visibility(struct symbol *sym)
205 {
206         struct property *prop;
207         tristate tri;
208
209         /* any prompt visible? */
210         tri = no;
211         for_all_prompts(sym, prop) {
212                 prop->visible.tri = expr_calc_value(prop->visible.expr);
213                 tri = EXPR_OR(tri, prop->visible.tri);
214         }
215         if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
216                 tri = yes;
217         if (sym->visible != tri) {
218                 sym->visible = tri;
219                 sym_set_changed(sym);
220         }
221         if (sym_is_choice_value(sym))
222                 return;
223         tri = no;
224         if (sym->rev_dep.expr)
225                 tri = expr_calc_value(sym->rev_dep.expr);
226         if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
227                 tri = yes;
228         if (sym->rev_dep.tri != tri) {
229                 sym->rev_dep.tri = tri;
230                 sym_set_changed(sym);
231         }
232 }
233
234 static struct symbol *sym_calc_choice(struct symbol *sym)
235 {
236         struct symbol *def_sym;
237         struct property *prop;
238         struct expr *e;
239
240         /* is the user choice visible? */
241         def_sym = sym->def[S_DEF_USER].val;
242         if (def_sym) {
243                 sym_calc_visibility(def_sym);
244                 if (def_sym->visible != no)
245                         return def_sym;
246         }
247
248         /* any of the defaults visible? */
249         for_all_defaults(sym, prop) {
250                 prop->visible.tri = expr_calc_value(prop->visible.expr);
251                 if (prop->visible.tri == no)
252                         continue;
253                 def_sym = prop_get_symbol(prop);
254                 sym_calc_visibility(def_sym);
255                 if (def_sym->visible != no)
256                         return def_sym;
257         }
258
259         /* just get the first visible value */
260         prop = sym_get_choice_prop(sym);
261         expr_list_for_each_sym(prop->expr, e, def_sym) {
262                 sym_calc_visibility(def_sym);
263                 if (def_sym->visible != no)
264                         return def_sym;
265         }
266
267         /* no choice? reset tristate value */
268         sym->curr.tri = no;
269         return NULL;
270 }
271
272 void sym_calc_value(struct symbol *sym)
273 {
274         struct symbol_value newval, oldval;
275         struct property *prop;
276         struct expr *e;
277
278         if (!sym)
279                 return;
280
281         if (sym->flags & SYMBOL_VALID)
282                 return;
283         sym->flags |= SYMBOL_VALID;
284
285         oldval = sym->curr;
286
287         switch (sym->type) {
288         case S_INT:
289         case S_HEX:
290         case S_STRING:
291                 newval = symbol_empty.curr;
292                 break;
293         case S_BOOLEAN:
294         case S_TRISTATE:
295                 newval = symbol_no.curr;
296                 break;
297         default:
298                 sym->curr.val = sym->name;
299                 sym->curr.tri = no;
300                 return;
301         }
302         if (!sym_is_choice_value(sym))
303                 sym->flags &= ~SYMBOL_WRITE;
304
305         sym_calc_visibility(sym);
306
307         /* set default if recursively called */
308         sym->curr = newval;
309
310         switch (sym_get_type(sym)) {
311         case S_BOOLEAN:
312         case S_TRISTATE:
313                 if (sym_is_choice_value(sym) && sym->visible == yes) {
314                         prop = sym_get_choice_prop(sym);
315                         newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
316                 } else if (EXPR_OR(sym->visible, sym->rev_dep.tri) != no) {
317                         sym->flags |= SYMBOL_WRITE;
318                         if (sym_has_value(sym))
319                                 newval.tri = sym->def[S_DEF_USER].tri;
320                         else if (!sym_is_choice(sym)) {
321                                 prop = sym_get_default_prop(sym);
322                                 if (prop)
323                                         newval.tri = expr_calc_value(prop->expr);
324                         }
325                         newval.tri = EXPR_OR(EXPR_AND(newval.tri, sym->visible), sym->rev_dep.tri);
326                 } else if (!sym_is_choice(sym)) {
327                         prop = sym_get_default_prop(sym);
328                         if (prop) {
329                                 sym->flags |= SYMBOL_WRITE;
330                                 newval.tri = expr_calc_value(prop->expr);
331                         }
332                 }
333                 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
334                         newval.tri = yes;
335                 break;
336         case S_STRING:
337         case S_HEX:
338         case S_INT:
339                 if (sym->visible != no) {
340                         sym->flags |= SYMBOL_WRITE;
341                         if (sym_has_value(sym)) {
342                                 newval.val = sym->def[S_DEF_USER].val;
343                                 break;
344                         }
345                 }
346                 prop = sym_get_default_prop(sym);
347                 if (prop) {
348                         struct symbol *ds = prop_get_symbol(prop);
349                         if (ds) {
350                                 sym->flags |= SYMBOL_WRITE;
351                                 sym_calc_value(ds);
352                                 newval.val = ds->curr.val;
353                         }
354                 }
355                 break;
356         default:
357                 ;
358         }
359
360         if (sym->flags & SYMBOL_AUTO)
361                 sym->flags &= ~SYMBOL_WRITE;
362
363         sym->curr = newval;
364         if (sym_is_choice(sym) && newval.tri == yes)
365                 sym->curr.val = sym_calc_choice(sym);
366         sym_validate_range(sym);
367
368         if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
369                 sym_set_changed(sym);
370                 if (modules_sym == sym) {
371                         sym_set_all_changed();
372                         modules_val = modules_sym->curr.tri;
373                 }
374         }
375
376         if (sym_is_choice(sym)) {
377                 struct symbol *choice_sym;
378                 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
379
380                 prop = sym_get_choice_prop(sym);
381                 expr_list_for_each_sym(prop->expr, e, choice_sym) {
382                         choice_sym->flags |= flags;
383                         if (flags & SYMBOL_CHANGED)
384                                 sym_set_changed(choice_sym);
385                 }
386         }
387 }
388
389 void sym_clear_all_valid(void)
390 {
391         struct symbol *sym;
392         int i;
393
394         for_all_symbols(i, sym)
395                 sym->flags &= ~SYMBOL_VALID;
396         sym_add_change_count(1);
397         if (modules_sym)
398                 sym_calc_value(modules_sym);
399 }
400
401 void sym_set_changed(struct symbol *sym)
402 {
403         struct property *prop;
404
405         sym->flags |= SYMBOL_CHANGED;
406         for (prop = sym->prop; prop; prop = prop->next) {
407                 if (prop->menu)
408                         prop->menu->flags |= MENU_CHANGED;
409         }
410 }
411
412 void sym_set_all_changed(void)
413 {
414         struct symbol *sym;
415         int i;
416
417         for_all_symbols(i, sym)
418                 sym_set_changed(sym);
419 }
420
421 bool sym_tristate_within_range(struct symbol *sym, tristate val)
422 {
423         int type = sym_get_type(sym);
424
425         if (sym->visible == no)
426                 return false;
427
428         if (type != S_BOOLEAN && type != S_TRISTATE)
429                 return false;
430
431         if (type == S_BOOLEAN && val == mod)
432                 return false;
433         if (sym->visible <= sym->rev_dep.tri)
434                 return false;
435         if (sym_is_choice_value(sym) && sym->visible == yes)
436                 return val == yes;
437         return val >= sym->rev_dep.tri && val <= sym->visible;
438 }
439
440 bool sym_set_tristate_value(struct symbol *sym, tristate val)
441 {
442         tristate oldval = sym_get_tristate_value(sym);
443
444         if (oldval != val && !sym_tristate_within_range(sym, val))
445                 return false;
446
447         if (!(sym->flags & SYMBOL_DEF_USER)) {
448                 sym->flags |= SYMBOL_DEF_USER;
449                 sym_set_changed(sym);
450         }
451         /*
452          * setting a choice value also resets the new flag of the choice
453          * symbol and all other choice values.
454          */
455         if (sym_is_choice_value(sym) && val == yes) {
456                 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
457                 struct property *prop;
458                 struct expr *e;
459
460                 cs->def[S_DEF_USER].val = sym;
461                 cs->flags |= SYMBOL_DEF_USER;
462                 prop = sym_get_choice_prop(cs);
463                 for (e = prop->expr; e; e = e->left.expr) {
464                         if (e->right.sym->visible != no)
465                                 e->right.sym->flags |= SYMBOL_DEF_USER;
466                 }
467         }
468
469         sym->def[S_DEF_USER].tri = val;
470         if (oldval != val)
471                 sym_clear_all_valid();
472
473         return true;
474 }
475
476 tristate sym_toggle_tristate_value(struct symbol *sym)
477 {
478         tristate oldval, newval;
479
480         oldval = newval = sym_get_tristate_value(sym);
481         do {
482                 switch (newval) {
483                 case no:
484                         newval = mod;
485                         break;
486                 case mod:
487                         newval = yes;
488                         break;
489                 case yes:
490                         newval = no;
491                         break;
492                 }
493                 if (sym_set_tristate_value(sym, newval))
494                         break;
495         } while (oldval != newval);
496         return newval;
497 }
498
499 bool sym_string_valid(struct symbol *sym, const char *str)
500 {
501         signed char ch;
502
503         switch (sym->type) {
504         case S_STRING:
505                 return true;
506         case S_INT:
507                 ch = *str++;
508                 if (ch == '-')
509                         ch = *str++;
510                 if (!isdigit(ch))
511                         return false;
512                 if (ch == '0' && *str != 0)
513                         return false;
514                 while ((ch = *str++)) {
515                         if (!isdigit(ch))
516                                 return false;
517                 }
518                 return true;
519         case S_HEX:
520                 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
521                         str += 2;
522                 ch = *str++;
523                 do {
524                         if (!isxdigit(ch))
525                                 return false;
526                 } while ((ch = *str++));
527                 return true;
528         case S_BOOLEAN:
529         case S_TRISTATE:
530                 switch (str[0]) {
531                 case 'y': case 'Y':
532                 case 'm': case 'M':
533                 case 'n': case 'N':
534                         return true;
535                 }
536                 return false;
537         default:
538                 return false;
539         }
540 }
541
542 bool sym_string_within_range(struct symbol *sym, const char *str)
543 {
544         struct property *prop;
545         int val;
546
547         switch (sym->type) {
548         case S_STRING:
549                 return sym_string_valid(sym, str);
550         case S_INT:
551                 if (!sym_string_valid(sym, str))
552                         return false;
553                 prop = sym_get_range_prop(sym);
554                 if (!prop)
555                         return true;
556                 val = strtol(str, NULL, 10);
557                 return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
558                        val <= sym_get_range_val(prop->expr->right.sym, 10);
559         case S_HEX:
560                 if (!sym_string_valid(sym, str))
561                         return false;
562                 prop = sym_get_range_prop(sym);
563                 if (!prop)
564                         return true;
565                 val = strtol(str, NULL, 16);
566                 return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
567                        val <= sym_get_range_val(prop->expr->right.sym, 16);
568         case S_BOOLEAN:
569         case S_TRISTATE:
570                 switch (str[0]) {
571                 case 'y': case 'Y':
572                         return sym_tristate_within_range(sym, yes);
573                 case 'm': case 'M':
574                         return sym_tristate_within_range(sym, mod);
575                 case 'n': case 'N':
576                         return sym_tristate_within_range(sym, no);
577                 }
578                 return false;
579         default:
580                 return false;
581         }
582 }
583
584 bool sym_set_string_value(struct symbol *sym, const char *newval)
585 {
586         const char *oldval;
587         char *val;
588         int size;
589
590         switch (sym->type) {
591         case S_BOOLEAN:
592         case S_TRISTATE:
593                 switch (newval[0]) {
594                 case 'y': case 'Y':
595                         return sym_set_tristate_value(sym, yes);
596                 case 'm': case 'M':
597                         return sym_set_tristate_value(sym, mod);
598                 case 'n': case 'N':
599                         return sym_set_tristate_value(sym, no);
600                 }
601                 return false;
602         default:
603                 ;
604         }
605
606         if (!sym_string_within_range(sym, newval))
607                 return false;
608
609         if (!(sym->flags & SYMBOL_DEF_USER)) {
610                 sym->flags |= SYMBOL_DEF_USER;
611                 sym_set_changed(sym);
612         }
613
614         oldval = sym->def[S_DEF_USER].val;
615         size = strlen(newval) + 1;
616         if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
617                 size += 2;
618                 sym->def[S_DEF_USER].val = val = malloc(size);
619                 *val++ = '0';
620                 *val++ = 'x';
621         } else if (!oldval || strcmp(oldval, newval))
622                 sym->def[S_DEF_USER].val = val = malloc(size);
623         else
624                 return true;
625
626         strcpy(val, newval);
627         free((void *)oldval);
628         sym_clear_all_valid();
629
630         return true;
631 }
632
633 const char *sym_get_string_value(struct symbol *sym)
634 {
635         tristate val;
636
637         switch (sym->type) {
638         case S_BOOLEAN:
639         case S_TRISTATE:
640                 val = sym_get_tristate_value(sym);
641                 switch (val) {
642                 case no:
643                         return "n";
644                 case mod:
645                         return "m";
646                 case yes:
647                         return "y";
648                 }
649                 break;
650         default:
651                 ;
652         }
653         return (const char *)sym->curr.val;
654 }
655
656 bool sym_is_changable(struct symbol *sym)
657 {
658         return sym->visible > sym->rev_dep.tri;
659 }
660
661 struct symbol *sym_lookup(const char *name, int isconst)
662 {
663         struct symbol *symbol;
664         const char *ptr;
665         char *new_name;
666         int hash = 0;
667
668         if (name) {
669                 if (name[0] && !name[1]) {
670                         switch (name[0]) {
671                         case 'y': return &symbol_yes;
672                         case 'm': return &symbol_mod;
673                         case 'n': return &symbol_no;
674                         }
675                 }
676                 for (ptr = name; *ptr; ptr++)
677                         hash += *ptr;
678                 hash &= 0xff;
679
680                 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
681                         if (!strcmp(symbol->name, name)) {
682                                 if ((isconst && symbol->flags & SYMBOL_CONST) ||
683                                     (!isconst && !(symbol->flags & SYMBOL_CONST)))
684                                         return symbol;
685                         }
686                 }
687                 new_name = strdup(name);
688         } else {
689                 new_name = NULL;
690                 hash = 256;
691         }
692
693         symbol = malloc(sizeof(*symbol));
694         memset(symbol, 0, sizeof(*symbol));
695         symbol->name = new_name;
696         symbol->type = S_UNKNOWN;
697         if (isconst)
698                 symbol->flags |= SYMBOL_CONST;
699
700         symbol->next = symbol_hash[hash];
701         symbol_hash[hash] = symbol;
702
703         return symbol;
704 }
705
706 struct symbol *sym_find(const char *name)
707 {
708         struct symbol *symbol = NULL;
709         const char *ptr;
710         int hash = 0;
711
712         if (!name)
713                 return NULL;
714
715         if (name[0] && !name[1]) {
716                 switch (name[0]) {
717                 case 'y': return &symbol_yes;
718                 case 'm': return &symbol_mod;
719                 case 'n': return &symbol_no;
720                 }
721         }
722         for (ptr = name; *ptr; ptr++)
723                 hash += *ptr;
724         hash &= 0xff;
725
726         for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
727                 if (!strcmp(symbol->name, name) &&
728                     !(symbol->flags & SYMBOL_CONST))
729                                 break;
730         }
731
732         return symbol;
733 }
734
735 struct symbol **sym_re_search(const char *pattern)
736 {
737         struct symbol *sym, **sym_arr = NULL;
738         int i, cnt, size;
739         regex_t re;
740
741         cnt = size = 0;
742         /* Skip if empty */
743         if (strlen(pattern) == 0)
744                 return NULL;
745         if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
746                 return NULL;
747
748         for_all_symbols(i, sym) {
749                 if (sym->flags & SYMBOL_CONST || !sym->name)
750                         continue;
751                 if (regexec(&re, sym->name, 0, NULL, 0))
752                         continue;
753                 if (cnt + 1 >= size) {
754                         void *tmp = sym_arr;
755                         size += 16;
756                         sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
757                         if (!sym_arr) {
758                                 free(tmp);
759                                 return NULL;
760                         }
761                 }
762                 sym_arr[cnt++] = sym;
763         }
764         if (sym_arr)
765                 sym_arr[cnt] = NULL;
766         regfree(&re);
767
768         return sym_arr;
769 }
770
771
772 struct symbol *sym_check_deps(struct symbol *sym);
773
774 static struct symbol *sym_check_expr_deps(struct expr *e)
775 {
776         struct symbol *sym;
777
778         if (!e)
779                 return NULL;
780         switch (e->type) {
781         case E_OR:
782         case E_AND:
783                 sym = sym_check_expr_deps(e->left.expr);
784                 if (sym)
785                         return sym;
786                 return sym_check_expr_deps(e->right.expr);
787         case E_NOT:
788                 return sym_check_expr_deps(e->left.expr);
789         case E_EQUAL:
790         case E_UNEQUAL:
791                 sym = sym_check_deps(e->left.sym);
792                 if (sym)
793                         return sym;
794                 return sym_check_deps(e->right.sym);
795         case E_SYMBOL:
796                 return sym_check_deps(e->left.sym);
797         default:
798                 break;
799         }
800         printf("Oops! How to check %d?\n", e->type);
801         return NULL;
802 }
803
804 /* return NULL when dependencies are OK */
805 struct symbol *sym_check_deps(struct symbol *sym)
806 {
807         struct symbol *sym2;
808         struct property *prop;
809
810         if (sym->flags & SYMBOL_CHECK) {
811                 fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
812                         sym->prop->file->name, sym->prop->lineno, sym->name);
813                 return sym;
814         }
815         if (sym->flags & SYMBOL_CHECKED)
816                 return NULL;
817
818         sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
819         sym2 = sym_check_expr_deps(sym->rev_dep.expr);
820         if (sym2)
821                 goto out;
822
823         for (prop = sym->prop; prop; prop = prop->next) {
824                 if (prop->type == P_CHOICE || prop->type == P_SELECT)
825                         continue;
826                 sym2 = sym_check_expr_deps(prop->visible.expr);
827                 if (sym2)
828                         goto out;
829                 if (prop->type != P_DEFAULT || sym_is_choice(sym))
830                         continue;
831                 sym2 = sym_check_expr_deps(prop->expr);
832                 if (sym2)
833                         goto out;
834         }
835 out:
836         if (sym2)
837                 fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": "");
838         sym->flags &= ~SYMBOL_CHECK;
839         return sym2;
840 }
841
842 struct property *prop_alloc(enum prop_type type, struct symbol *sym)
843 {
844         struct property *prop;
845         struct property **propp;
846
847         prop = malloc(sizeof(*prop));
848         memset(prop, 0, sizeof(*prop));
849         prop->type = type;
850         prop->sym = sym;
851         prop->file = current_file;
852         prop->lineno = zconf_lineno();
853
854         /* append property to the prop list of symbol */
855         if (sym) {
856                 for (propp = &sym->prop; *propp; propp = &(*propp)->next)
857                         ;
858                 *propp = prop;
859         }
860
861         return prop;
862 }
863
864 struct symbol *prop_get_symbol(struct property *prop)
865 {
866         if (prop->expr && (prop->expr->type == E_SYMBOL ||
867                            prop->expr->type == E_LIST))
868                 return prop->expr->left.sym;
869         return NULL;
870 }
871
872 const char *prop_get_type_name(enum prop_type type)
873 {
874         switch (type) {
875         case P_PROMPT:
876                 return "prompt";
877         case P_ENV:
878                 return "env";
879         case P_COMMENT:
880                 return "comment";
881         case P_MENU:
882                 return "menu";
883         case P_DEFAULT:
884                 return "default";
885         case P_CHOICE:
886                 return "choice";
887         case P_SELECT:
888                 return "select";
889         case P_RANGE:
890                 return "range";
891         case P_UNKNOWN:
892                 break;
893         }
894         return "unknown";
895 }
896
897 void prop_add_env(const char *env)
898 {
899         struct symbol *sym, *sym2;
900         struct property *prop;
901         char *p;
902
903         sym = current_entry->sym;
904         sym->flags |= SYMBOL_AUTO;
905         for_all_properties(sym, prop, P_ENV) {
906                 sym2 = prop_get_symbol(prop);
907                 if (strcmp(sym2->name, env))
908                         menu_warn(current_entry, "redefining environment symbol from %s",
909                                   sym2->name);
910                 return;
911         }
912
913         prop = prop_alloc(P_ENV, sym);
914         prop->expr = expr_alloc_symbol(sym_lookup(env, 1));
915
916         sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
917         sym_env_list->right.sym = sym;
918
919         p = getenv(env);
920         if (p)
921                 sym_add_default(sym, p);
922         else
923                 menu_warn(current_entry, "environment variable %s undefined", env);
924 }