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