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