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.


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