OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / config / 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 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 #if 0
58         sym = sym_lookup("ARCH", 0);
59         sym->type = S_STRING;
60         sym->flags |= SYMBOL_AUTO;
61         p = getenv("ARCH");
62         if (p)
63                 sym_add_default(sym, p);
64
65         sym = sym_lookup("DISTVERSION", 0);
66         sym->type = S_STRING;
67         sym->flags |= SYMBOL_AUTO;
68         p = getenv("DISTVERSION");
69         if (p)
70                 sym_add_default(sym, p);
71
72         sym = sym_lookup("UNAME_RELEASE", 0);
73         sym->type = S_STRING;
74         sym->flags |= SYMBOL_AUTO;
75         sym_add_default(sym, uts.release);
76 #endif
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_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
200         /* any prompt visible? */
201         tri = no;
202         for_all_prompts(sym, prop) {
203                 prop->visible.tri = expr_calc_value(prop->visible.expr);
204                 tri = E_OR(tri, prop->visible.tri);
205         }
206         if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
207                 tri = yes;
208         if (sym->visible != tri) {
209                 sym->visible = tri;
210                 sym_set_changed(sym);
211         }
212         if (sym_is_choice_value(sym))
213                 return;
214         tri = no;
215         if (sym->rev_dep.expr)
216                 tri = expr_calc_value(sym->rev_dep.expr);
217         if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
218                 tri = yes;
219         if (sym->rev_dep.tri != tri) {
220                 sym->rev_dep.tri = tri;
221                 sym_set_changed(sym);
222         }
223 }
224
225 static struct symbol *sym_calc_choice(struct symbol *sym)
226 {
227         struct symbol *def_sym;
228         struct property *prop;
229         struct expr *e;
230
231         /* is the user choice visible? */
232         def_sym = sym->def[S_DEF_USER].val;
233         if (def_sym) {
234                 sym_calc_visibility(def_sym);
235                 if (def_sym->visible != no)
236                         return def_sym;
237         }
238
239         /* any of the defaults visible? */
240         for_all_defaults(sym, prop) {
241                 prop->visible.tri = expr_calc_value(prop->visible.expr);
242                 if (prop->visible.tri == no)
243                         continue;
244                 def_sym = prop_get_symbol(prop);
245                 sym_calc_visibility(def_sym);
246                 if (def_sym->visible != no)
247                         return def_sym;
248         }
249
250         /* just get the first visible value */
251         prop = sym_get_choice_prop(sym);
252         for (e = prop->expr; e; e = e->left.expr) {
253                 def_sym = e->right.sym;
254                 sym_calc_visibility(def_sym);
255                 if (def_sym->visible != no)
256                         return def_sym;
257         }
258
259         /* no choice? reset tristate value */
260         sym->curr.tri = no;
261         return NULL;
262 }
263
264 void sym_calc_value(struct symbol *sym)
265 {
266         struct symbol_value newval, oldval;
267         struct property *prop;
268         struct expr *e;
269
270         if (!sym)
271                 return;
272
273         if (sym->flags & SYMBOL_VALID)
274                 return;
275         sym->flags |= SYMBOL_VALID;
276
277         oldval = sym->curr;
278
279         switch (sym->type) {
280         case S_INT:
281         case S_HEX:
282         case S_STRING:
283                 newval = symbol_empty.curr;
284                 break;
285         case S_BOOLEAN:
286         case S_TRISTATE:
287                 newval = symbol_no.curr;
288                 break;
289         default:
290                 sym->curr.val = sym->name;
291                 sym->curr.tri = no;
292                 return;
293         }
294         if (!sym_is_choice_value(sym))
295                 sym->flags &= ~SYMBOL_WRITE;
296
297         sym_calc_visibility(sym);
298
299         /* set default if recursively called */
300         sym->curr = newval;
301
302         switch (sym_get_type(sym)) {
303         case S_BOOLEAN:
304         case S_TRISTATE:
305                 if (sym_is_choice_value(sym) && sym->visible == yes) {
306                         prop = sym_get_choice_prop(sym);
307                         newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
308                 } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
309                         sym->flags |= SYMBOL_WRITE;
310                         if (sym_has_value(sym))
311                                 newval.tri = sym->def[S_DEF_USER].tri;
312                         else if (!sym_is_choice(sym)) {
313                                 prop = sym_get_default_prop(sym);
314                                 if (prop)
315                                         newval.tri = expr_calc_value(prop->expr);
316                         }
317                         newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
318                 } else if (!sym_is_choice(sym)) {
319                         prop = sym_get_default_prop(sym);
320                         if (prop) {
321                                 sym->flags |= SYMBOL_WRITE;
322                                 newval.tri = expr_calc_value(prop->expr);
323                         }
324                 }
325                 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
326                         newval.tri = yes;
327                 break;
328         case S_STRING:
329         case S_HEX:
330         case S_INT:
331                 if (sym->visible != no) {
332                         sym->flags |= SYMBOL_WRITE;
333                         if (sym_has_value(sym)) {
334                                 newval.val = sym->def[S_DEF_USER].val;
335                                 break;
336                         }
337                 }
338                 prop = sym_get_default_prop(sym);
339                 if (prop) {
340                         struct symbol *ds = prop_get_symbol(prop);
341                         if (ds) {
342                                 sym->flags |= SYMBOL_WRITE;
343                                 sym_calc_value(ds);
344                                 newval.val = ds->curr.val;
345                         }
346                 }
347                 break;
348         default:
349                 ;
350         }
351
352         sym->curr = newval;
353         if (sym_is_choice(sym) && newval.tri == yes)
354                 sym->curr.val = sym_calc_choice(sym);
355         sym_validate_range(sym);
356
357         if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
358                 sym_set_changed(sym);
359                 if (modules_sym == sym) {
360                         sym_set_all_changed();
361                         modules_val = modules_sym->curr.tri;
362                 }
363         }
364
365         if (sym_is_choice(sym)) {
366                 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
367                 prop = sym_get_choice_prop(sym);
368                 for (e = prop->expr; e; e = e->left.expr) {
369                         e->right.sym->flags |= flags;
370                         if (flags & SYMBOL_CHANGED)
371                                 sym_set_changed(e->right.sym);
372                 }
373         }
374 }
375
376 void sym_clear_all_valid(void)
377 {
378         struct symbol *sym;
379         int i;
380
381         for_all_symbols(i, sym)
382                 sym->flags &= ~SYMBOL_VALID;
383         sym_add_change_count(1);
384         if (modules_sym)
385                 sym_calc_value(modules_sym);
386 }
387
388 void sym_set_changed(struct symbol *sym)
389 {
390         struct property *prop;
391
392         sym->flags |= SYMBOL_CHANGED;
393         for (prop = sym->prop; prop; prop = prop->next) {
394                 if (prop->menu)
395                         prop->menu->flags |= MENU_CHANGED;
396         }
397 }
398
399 void sym_set_all_changed(void)
400 {
401         struct symbol *sym;
402         int i;
403
404         for_all_symbols(i, sym)
405                 sym_set_changed(sym);
406 }
407
408 bool sym_tristate_within_range(struct symbol *sym, tristate val)
409 {
410         int type = sym_get_type(sym);
411
412         if (sym->visible == no)
413                 return false;
414
415         if (type != S_BOOLEAN && type != S_TRISTATE)
416                 return false;
417
418         if (type == S_BOOLEAN && val == mod)
419                 return false;
420         if (sym->visible <= sym->rev_dep.tri)
421                 return false;
422         if (sym_is_choice_value(sym) && sym->visible == yes)
423                 return val == yes;
424         return val >= sym->rev_dep.tri && val <= sym->visible;
425 }
426
427 bool sym_set_tristate_value(struct symbol *sym, tristate val)
428 {
429         tristate oldval = sym_get_tristate_value(sym);
430
431         if (oldval != val && !sym_tristate_within_range(sym, val))
432                 return false;
433
434         if (!(sym->flags & SYMBOL_DEF_USER)) {
435                 sym->flags |= SYMBOL_DEF_USER;
436                 sym_set_changed(sym);
437         }
438         /*
439          * setting a choice value also resets the new flag of the choice
440          * symbol and all other choice values.
441          */
442         if (sym_is_choice_value(sym) && val == yes) {
443                 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
444                 struct property *prop;
445                 struct expr *e;
446
447                 cs->def[S_DEF_USER].val = sym;
448                 cs->flags |= SYMBOL_DEF_USER;
449                 prop = sym_get_choice_prop(cs);
450                 for (e = prop->expr; e; e = e->left.expr) {
451                         if (e->right.sym->visible != no)
452                                 e->right.sym->flags |= SYMBOL_DEF_USER;
453                 }
454         }
455
456         sym->def[S_DEF_USER].tri = val;
457         if (oldval != val)
458                 sym_clear_all_valid();
459
460         return true;
461 }
462
463 tristate sym_toggle_tristate_value(struct symbol *sym)
464 {
465         tristate oldval, newval;
466
467         oldval = newval = sym_get_tristate_value(sym);
468         do {
469                 switch (newval) {
470                 case no:
471                         newval = mod;
472                         break;
473                 case mod:
474                         newval = yes;
475                         break;
476                 case yes:
477                         newval = no;
478                         break;
479                 }
480                 if (sym_set_tristate_value(sym, newval))
481                         break;
482         } while (oldval != newval);
483         return newval;
484 }
485
486 bool sym_string_valid(struct symbol *sym, const char *str)
487 {
488         signed char ch;
489
490         switch (sym->type) {
491         case S_STRING:
492                 return true;
493         case S_INT:
494                 ch = *str++;
495                 if (ch == '-')
496                         ch = *str++;
497                 if (!isdigit(ch))
498                         return false;
499                 if (ch == '0' && *str != 0)
500                         return false;
501                 while ((ch = *str++)) {
502                         if (!isdigit(ch))
503                                 return false;
504                 }
505                 return true;
506         case S_HEX:
507                 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
508                         str += 2;
509                 ch = *str++;
510                 do {
511                         if (!isxdigit(ch))
512                                 return false;
513                 } while ((ch = *str++));
514                 return true;
515         case S_BOOLEAN:
516         case S_TRISTATE:
517                 switch (str[0]) {
518                 case 'y': case 'Y':
519                 case 'm': case 'M':
520                 case 'n': case 'N':
521                         return true;
522                 }
523                 return false;
524         default:
525                 return false;
526         }
527 }
528
529 bool sym_string_within_range(struct symbol *sym, const char *str)
530 {
531         struct property *prop;
532         int val;
533
534         switch (sym->type) {
535         case S_STRING:
536                 return sym_string_valid(sym, str);
537         case S_INT:
538                 if (!sym_string_valid(sym, str))
539                         return false;
540                 prop = sym_get_range_prop(sym);
541                 if (!prop)
542                         return true;
543                 val = strtol(str, NULL, 10);
544                 return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
545                        val <= sym_get_range_val(prop->expr->right.sym, 10);
546         case S_HEX:
547                 if (!sym_string_valid(sym, str))
548                         return false;
549                 prop = sym_get_range_prop(sym);
550                 if (!prop)
551                         return true;
552                 val = strtol(str, NULL, 16);
553                 return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
554                        val <= sym_get_range_val(prop->expr->right.sym, 16);
555         case S_BOOLEAN:
556         case S_TRISTATE:
557                 switch (str[0]) {
558                 case 'y': case 'Y':
559                         return sym_tristate_within_range(sym, yes);
560                 case 'm': case 'M':
561                         return sym_tristate_within_range(sym, mod);
562                 case 'n': case 'N':
563                         return sym_tristate_within_range(sym, no);
564                 }
565                 return false;
566         default:
567                 return false;
568         }
569 }
570
571 bool sym_set_string_value(struct symbol *sym, const char *newval)
572 {
573         const char *oldval;
574         char *val;
575         int size;
576
577         switch (sym->type) {
578         case S_BOOLEAN:
579         case S_TRISTATE:
580                 switch (newval[0]) {
581                 case 'y': case 'Y':
582                         return sym_set_tristate_value(sym, yes);
583                 case 'm': case 'M':
584                         return sym_set_tristate_value(sym, mod);
585                 case 'n': case 'N':
586                         return sym_set_tristate_value(sym, no);
587                 }
588                 return false;
589         default:
590                 ;
591         }
592
593         if (!sym_string_within_range(sym, newval))
594                 return false;
595
596         if (!(sym->flags & SYMBOL_DEF_USER)) {
597                 sym->flags |= SYMBOL_DEF_USER;
598                 sym_set_changed(sym);
599         }
600
601         oldval = sym->def[S_DEF_USER].val;
602         size = strlen(newval) + 1;
603         if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
604                 size += 2;
605                 sym->def[S_DEF_USER].val = val = malloc(size);
606                 *val++ = '0';
607                 *val++ = 'x';
608         } else if (!oldval || strcmp(oldval, newval))
609                 sym->def[S_DEF_USER].val = val = malloc(size);
610         else
611                 return true;
612
613         strcpy(val, newval);
614         free((void *)oldval);
615         sym_clear_all_valid();
616
617         return true;
618 }
619
620 const char *sym_get_string_value(struct symbol *sym)
621 {
622         tristate val;
623
624         switch (sym->type) {
625         case S_BOOLEAN:
626         case S_TRISTATE:
627                 val = sym_get_tristate_value(sym);
628                 switch (val) {
629                 case no:
630                         return "n";
631                 case mod:
632                         return "m";
633                 case yes:
634                         return "y";
635                 }
636                 break;
637         default:
638                 ;
639         }
640         return (const char *)sym->curr.val;
641 }
642
643 bool sym_is_changable(struct symbol *sym)
644 {
645         return sym->visible > sym->rev_dep.tri;
646 }
647
648 struct symbol *sym_lookup(const char *name, int isconst)
649 {
650         struct symbol *symbol;
651         const char *ptr;
652         char *new_name;
653         int hash = 0;
654
655         if (name) {
656                 if (name[0] && !name[1]) {
657                         switch (name[0]) {
658                         case 'y': return &symbol_yes;
659                         case 'm': return &symbol_mod;
660                         case 'n': return &symbol_no;
661                         }
662                 }
663                 for (ptr = name; *ptr; ptr++)
664                         hash += *ptr;
665                 hash &= 0xff;
666
667                 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
668                         if (!strcmp(symbol->name, name)) {
669                                 if ((isconst && symbol->flags & SYMBOL_CONST) ||
670                                     (!isconst && !(symbol->flags & SYMBOL_CONST)))
671                                         return symbol;
672                         }
673                 }
674                 new_name = strdup(name);
675         } else {
676                 new_name = NULL;
677                 hash = 256;
678         }
679
680         symbol = malloc(sizeof(*symbol));
681         memset(symbol, 0, sizeof(*symbol));
682         symbol->name = new_name;
683         symbol->type = S_UNKNOWN;
684         if (isconst)
685                 symbol->flags |= SYMBOL_CONST;
686
687         symbol->next = symbol_hash[hash];
688         symbol_hash[hash] = symbol;
689
690         return symbol;
691 }
692
693 struct symbol *sym_find(const char *name)
694 {
695         struct symbol *symbol = NULL;
696         const char *ptr;
697         int hash = 0;
698
699         if (!name)
700                 return NULL;
701
702         if (name[0] && !name[1]) {
703                 switch (name[0]) {
704                 case 'y': return &symbol_yes;
705                 case 'm': return &symbol_mod;
706                 case 'n': return &symbol_no;
707                 }
708         }
709         for (ptr = name; *ptr; ptr++)
710                 hash += *ptr;
711         hash &= 0xff;
712
713         for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
714                 if (!strcmp(symbol->name, name) &&
715                     !(symbol->flags & SYMBOL_CONST))
716                                 break;
717         }
718
719         return symbol;
720 }
721
722 struct symbol **sym_re_search(const char *pattern)
723 {
724         struct symbol *sym, **sym_arr = NULL;
725         int i, cnt, size;
726         regex_t re;
727
728         cnt = size = 0;
729         /* Skip if empty */
730         if (strlen(pattern) == 0)
731                 return NULL;
732         if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
733                 return NULL;
734
735         for_all_symbols(i, sym) {
736                 if (sym->flags & SYMBOL_CONST || !sym->name)
737                         continue;
738                 if (regexec(&re, sym->name, 0, NULL, 0))
739                         continue;
740                 if (cnt + 1 >= size) {
741                         void *tmp = sym_arr;
742                         size += 16;
743                         sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
744                         if (!sym_arr) {
745                                 free(tmp);
746                                 return NULL;
747                         }
748                 }
749                 sym_arr[cnt++] = sym;
750         }
751         if (sym_arr)
752                 sym_arr[cnt] = NULL;
753         regfree(&re);
754
755         return sym_arr;
756 }
757
758
759 struct symbol *sym_check_deps(struct symbol *sym);
760
761 static struct symbol *sym_check_expr_deps(struct expr *e)
762 {
763         struct symbol *sym;
764
765         if (!e)
766                 return NULL;
767         switch (e->type) {
768         case E_OR:
769         case E_AND:
770                 sym = sym_check_expr_deps(e->left.expr);
771                 if (sym)
772                         return sym;
773                 return sym_check_expr_deps(e->right.expr);
774         case E_NOT:
775                 return sym_check_expr_deps(e->left.expr);
776         case E_EQUAL:
777         case E_UNEQUAL:
778                 sym = sym_check_deps(e->left.sym);
779                 if (sym)
780                         return sym;
781                 return sym_check_deps(e->right.sym);
782         case E_SYMBOL:
783                 return sym_check_deps(e->left.sym);
784         default:
785                 break;
786         }
787         printf("Oops! How to check %d?\n", e->type);
788         return NULL;
789 }
790
791 struct symbol *sym_check_deps(struct symbol *sym)
792 {
793         struct symbol *sym2;
794         struct property *prop;
795
796         if (sym->flags & SYMBOL_CHECK) {
797                 printf("Warning! Found recursive dependency: %s", sym->name);
798                 return sym;
799         }
800         if (sym->flags & SYMBOL_CHECKED)
801                 return NULL;
802
803         sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
804         sym2 = sym_check_expr_deps(sym->rev_dep.expr);
805         if (sym2)
806                 goto out;
807
808         for (prop = sym->prop; prop; prop = prop->next) {
809                 if (prop->type == P_CHOICE || prop->type == P_SELECT)
810                         continue;
811                 sym2 = sym_check_expr_deps(prop->visible.expr);
812                 if (sym2)
813                         goto out;
814                 if (prop->type != P_DEFAULT || sym_is_choice(sym))
815                         continue;
816                 sym2 = sym_check_expr_deps(prop->expr);
817                 if (sym2)
818                         goto out;
819         }
820 out:
821         if (sym2) {
822                 printf(" %s", sym->name);
823                 if (sym2 == sym) {
824                         printf("\n");
825                         sym2 = NULL;
826                 }
827         }
828         sym->flags &= ~SYMBOL_CHECK;
829         return sym2;
830 }
831
832 struct property *prop_alloc(enum prop_type type, struct symbol *sym)
833 {
834         struct property *prop;
835         struct property **propp;
836
837         prop = malloc(sizeof(*prop));
838         memset(prop, 0, sizeof(*prop));
839         prop->type = type;
840         prop->sym = sym;
841         prop->file = current_file;
842         prop->lineno = zconf_lineno();
843
844         /* append property to the prop list of symbol */
845         if (sym) {
846                 for (propp = &sym->prop; *propp; propp = &(*propp)->next)
847                         ;
848                 *propp = prop;
849         }
850
851         return prop;
852 }
853
854 struct symbol *prop_get_symbol(struct property *prop)
855 {
856         if (prop->expr && (prop->expr->type == E_SYMBOL ||
857                            prop->expr->type == E_CHOICE))
858                 return prop->expr->left.sym;
859         return NULL;
860 }
861
862 const char *prop_get_type_name(enum prop_type type)
863 {
864         switch (type) {
865         case P_PROMPT:
866                 return "prompt";
867         case P_COMMENT:
868                 return "comment";
869         case P_MENU:
870                 return "menu";
871         case P_DEFAULT:
872                 return "default";
873         case P_CHOICE:
874                 return "choice";
875         case P_SELECT:
876                 return "select";
877         case P_RANGE:
878                 return "range";
879         case P_UNKNOWN:
880                 break;
881         }
882         return "unknown";
883 }