ia64/linux-2.6.18-xen.hg

view scripts/kconfig/symbol.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
6 #include <ctype.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <regex.h>
10 #include <sys/utsname.h>
12 #define LKC_DIRECT_LINK
13 #include "lkc.h"
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 };
33 int sym_change_count;
34 struct symbol *sym_defconfig_list;
35 struct symbol *modules_sym;
36 tristate modules_val;
38 void sym_add_default(struct symbol *sym, const char *def)
39 {
40 struct property *prop = prop_alloc(P_DEFAULT, sym);
42 prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
43 }
45 void sym_init(void)
46 {
47 struct symbol *sym;
48 struct utsname uts;
49 char *p;
50 static bool inited = false;
52 if (inited)
53 return;
54 inited = true;
56 uname(&uts);
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);
65 sym = sym_lookup("KERNELVERSION", 0);
66 sym->type = S_STRING;
67 sym->flags |= SYMBOL_AUTO;
68 p = getenv("KERNELVERSION");
69 if (p)
70 sym_add_default(sym, p);
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 }
78 enum symbol_type sym_get_type(struct symbol *sym)
79 {
80 enum symbol_type type = sym->type;
82 if (type == S_TRISTATE) {
83 if (sym_is_choice_value(sym) && sym->visible == yes)
84 type = S_BOOLEAN;
85 else if (modules_val == no)
86 type = S_BOOLEAN;
87 }
88 return type;
89 }
91 const char *sym_type_name(enum symbol_type type)
92 {
93 switch (type) {
94 case S_BOOLEAN:
95 return "boolean";
96 case S_TRISTATE:
97 return "tristate";
98 case S_INT:
99 return "integer";
100 case S_HEX:
101 return "hex";
102 case S_STRING:
103 return "string";
104 case S_UNKNOWN:
105 return "unknown";
106 case S_OTHER:
107 break;
108 }
109 return "???";
110 }
112 struct property *sym_get_choice_prop(struct symbol *sym)
113 {
114 struct property *prop;
116 for_all_choices(sym, prop)
117 return prop;
118 return NULL;
119 }
121 struct property *sym_get_default_prop(struct symbol *sym)
122 {
123 struct property *prop;
125 for_all_defaults(sym, prop) {
126 prop->visible.tri = expr_calc_value(prop->visible.expr);
127 if (prop->visible.tri != no)
128 return prop;
129 }
130 return NULL;
131 }
133 struct property *sym_get_range_prop(struct symbol *sym)
134 {
135 struct property *prop;
137 for_all_properties(sym, prop, P_RANGE) {
138 prop->visible.tri = expr_calc_value(prop->visible.expr);
139 if (prop->visible.tri != no)
140 return prop;
141 }
142 return NULL;
143 }
145 static int sym_get_range_val(struct symbol *sym, int base)
146 {
147 sym_calc_value(sym);
148 switch (sym->type) {
149 case S_INT:
150 base = 10;
151 break;
152 case S_HEX:
153 base = 16;
154 break;
155 default:
156 break;
157 }
158 return strtol(sym->curr.val, NULL, base);
159 }
161 static void sym_validate_range(struct symbol *sym)
162 {
163 struct property *prop;
164 int base, val, val2;
165 char str[64];
167 switch (sym->type) {
168 case S_INT:
169 base = 10;
170 break;
171 case S_HEX:
172 base = 16;
173 break;
174 default:
175 return;
176 }
177 prop = sym_get_range_prop(sym);
178 if (!prop)
179 return;
180 val = strtol(sym->curr.val, NULL, base);
181 val2 = sym_get_range_val(prop->expr->left.sym, base);
182 if (val >= val2) {
183 val2 = sym_get_range_val(prop->expr->right.sym, base);
184 if (val <= val2)
185 return;
186 }
187 if (sym->type == S_INT)
188 sprintf(str, "%d", val2);
189 else
190 sprintf(str, "0x%x", val2);
191 sym->curr.val = strdup(str);
192 }
194 static void sym_calc_visibility(struct symbol *sym)
195 {
196 struct property *prop;
197 tristate tri;
199 /* any prompt visible? */
200 tri = no;
201 for_all_prompts(sym, prop) {
202 prop->visible.tri = expr_calc_value(prop->visible.expr);
203 tri = E_OR(tri, prop->visible.tri);
204 }
205 if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
206 tri = yes;
207 if (sym->visible != tri) {
208 sym->visible = tri;
209 sym_set_changed(sym);
210 }
211 if (sym_is_choice_value(sym))
212 return;
213 tri = no;
214 if (sym->rev_dep.expr)
215 tri = expr_calc_value(sym->rev_dep.expr);
216 if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
217 tri = yes;
218 if (sym->rev_dep.tri != tri) {
219 sym->rev_dep.tri = tri;
220 sym_set_changed(sym);
221 }
222 }
224 static struct symbol *sym_calc_choice(struct symbol *sym)
225 {
226 struct symbol *def_sym;
227 struct property *prop;
228 struct expr *e;
230 /* is the user choice visible? */
231 def_sym = sym->def[S_DEF_USER].val;
232 if (def_sym) {
233 sym_calc_visibility(def_sym);
234 if (def_sym->visible != no)
235 return def_sym;
236 }
238 /* any of the defaults visible? */
239 for_all_defaults(sym, prop) {
240 prop->visible.tri = expr_calc_value(prop->visible.expr);
241 if (prop->visible.tri == no)
242 continue;
243 def_sym = prop_get_symbol(prop);
244 sym_calc_visibility(def_sym);
245 if (def_sym->visible != no)
246 return def_sym;
247 }
249 /* just get the first visible value */
250 prop = sym_get_choice_prop(sym);
251 for (e = prop->expr; e; e = e->left.expr) {
252 def_sym = e->right.sym;
253 sym_calc_visibility(def_sym);
254 if (def_sym->visible != no)
255 return def_sym;
256 }
258 /* no choice? reset tristate value */
259 sym->curr.tri = no;
260 return NULL;
261 }
263 void sym_calc_value(struct symbol *sym)
264 {
265 struct symbol_value newval, oldval;
266 struct property *prop;
267 struct expr *e;
269 if (!sym)
270 return;
272 if (sym->flags & SYMBOL_VALID)
273 return;
274 sym->flags |= SYMBOL_VALID;
276 oldval = sym->curr;
278 switch (sym->type) {
279 case S_INT:
280 case S_HEX:
281 case S_STRING:
282 newval = symbol_empty.curr;
283 break;
284 case S_BOOLEAN:
285 case S_TRISTATE:
286 newval = symbol_no.curr;
287 break;
288 default:
289 sym->curr.val = sym->name;
290 sym->curr.tri = no;
291 return;
292 }
293 if (!sym_is_choice_value(sym))
294 sym->flags &= ~SYMBOL_WRITE;
296 sym_calc_visibility(sym);
298 /* set default if recursively called */
299 sym->curr = newval;
301 switch (sym_get_type(sym)) {
302 case S_BOOLEAN:
303 case S_TRISTATE:
304 if (sym_is_choice_value(sym) && sym->visible == yes) {
305 prop = sym_get_choice_prop(sym);
306 newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
307 } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
308 sym->flags |= SYMBOL_WRITE;
309 if (sym_has_value(sym))
310 newval.tri = sym->def[S_DEF_USER].tri;
311 else if (!sym_is_choice(sym)) {
312 prop = sym_get_default_prop(sym);
313 if (prop)
314 newval.tri = expr_calc_value(prop->expr);
315 }
316 newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
317 } else if (!sym_is_choice(sym)) {
318 prop = sym_get_default_prop(sym);
319 if (prop) {
320 sym->flags |= SYMBOL_WRITE;
321 newval.tri = expr_calc_value(prop->expr);
322 }
323 }
324 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
325 newval.tri = yes;
326 break;
327 case S_STRING:
328 case S_HEX:
329 case S_INT:
330 if (sym->visible != no) {
331 sym->flags |= SYMBOL_WRITE;
332 if (sym_has_value(sym)) {
333 newval.val = sym->def[S_DEF_USER].val;
334 break;
335 }
336 }
337 prop = sym_get_default_prop(sym);
338 if (prop) {
339 struct symbol *ds = prop_get_symbol(prop);
340 if (ds) {
341 sym->flags |= SYMBOL_WRITE;
342 sym_calc_value(ds);
343 newval.val = ds->curr.val;
344 }
345 }
346 break;
347 default:
348 ;
349 }
351 sym->curr = newval;
352 if (sym_is_choice(sym) && newval.tri == yes)
353 sym->curr.val = sym_calc_choice(sym);
354 sym_validate_range(sym);
356 if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
357 sym_set_changed(sym);
358 if (modules_sym == sym) {
359 sym_set_all_changed();
360 modules_val = modules_sym->curr.tri;
361 }
362 }
364 if (sym_is_choice(sym)) {
365 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
366 prop = sym_get_choice_prop(sym);
367 for (e = prop->expr; e; e = e->left.expr) {
368 e->right.sym->flags |= flags;
369 if (flags & SYMBOL_CHANGED)
370 sym_set_changed(e->right.sym);
371 }
372 }
373 }
375 void sym_clear_all_valid(void)
376 {
377 struct symbol *sym;
378 int i;
380 for_all_symbols(i, sym)
381 sym->flags &= ~SYMBOL_VALID;
382 sym_change_count++;
383 if (modules_sym)
384 sym_calc_value(modules_sym);
385 }
387 void sym_set_changed(struct symbol *sym)
388 {
389 struct property *prop;
391 sym->flags |= SYMBOL_CHANGED;
392 for (prop = sym->prop; prop; prop = prop->next) {
393 if (prop->menu)
394 prop->menu->flags |= MENU_CHANGED;
395 }
396 }
398 void sym_set_all_changed(void)
399 {
400 struct symbol *sym;
401 int i;
403 for_all_symbols(i, sym)
404 sym_set_changed(sym);
405 }
407 bool sym_tristate_within_range(struct symbol *sym, tristate val)
408 {
409 int type = sym_get_type(sym);
411 if (sym->visible == no)
412 return false;
414 if (type != S_BOOLEAN && type != S_TRISTATE)
415 return false;
417 if (type == S_BOOLEAN && val == mod)
418 return false;
419 if (sym->visible <= sym->rev_dep.tri)
420 return false;
421 if (sym_is_choice_value(sym) && sym->visible == yes)
422 return val == yes;
423 return val >= sym->rev_dep.tri && val <= sym->visible;
424 }
426 bool sym_set_tristate_value(struct symbol *sym, tristate val)
427 {
428 tristate oldval = sym_get_tristate_value(sym);
430 if (oldval != val && !sym_tristate_within_range(sym, val))
431 return false;
433 if (!(sym->flags & SYMBOL_DEF_USER)) {
434 sym->flags |= SYMBOL_DEF_USER;
435 sym_set_changed(sym);
436 }
437 /*
438 * setting a choice value also resets the new flag of the choice
439 * symbol and all other choice values.
440 */
441 if (sym_is_choice_value(sym) && val == yes) {
442 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
443 struct property *prop;
444 struct expr *e;
446 cs->def[S_DEF_USER].val = sym;
447 cs->flags |= SYMBOL_DEF_USER;
448 prop = sym_get_choice_prop(cs);
449 for (e = prop->expr; e; e = e->left.expr) {
450 if (e->right.sym->visible != no)
451 e->right.sym->flags |= SYMBOL_DEF_USER;
452 }
453 }
455 sym->def[S_DEF_USER].tri = val;
456 if (oldval != val)
457 sym_clear_all_valid();
459 return true;
460 }
462 tristate sym_toggle_tristate_value(struct symbol *sym)
463 {
464 tristate oldval, newval;
466 oldval = newval = sym_get_tristate_value(sym);
467 do {
468 switch (newval) {
469 case no:
470 newval = mod;
471 break;
472 case mod:
473 newval = yes;
474 break;
475 case yes:
476 newval = no;
477 break;
478 }
479 if (sym_set_tristate_value(sym, newval))
480 break;
481 } while (oldval != newval);
482 return newval;
483 }
485 bool sym_string_valid(struct symbol *sym, const char *str)
486 {
487 signed char ch;
489 switch (sym->type) {
490 case S_STRING:
491 return true;
492 case S_INT:
493 ch = *str++;
494 if (ch == '-')
495 ch = *str++;
496 if (!isdigit(ch))
497 return false;
498 if (ch == '0' && *str != 0)
499 return false;
500 while ((ch = *str++)) {
501 if (!isdigit(ch))
502 return false;
503 }
504 return true;
505 case S_HEX:
506 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
507 str += 2;
508 ch = *str++;
509 do {
510 if (!isxdigit(ch))
511 return false;
512 } while ((ch = *str++));
513 return true;
514 case S_BOOLEAN:
515 case S_TRISTATE:
516 switch (str[0]) {
517 case 'y': case 'Y':
518 case 'm': case 'M':
519 case 'n': case 'N':
520 return true;
521 }
522 return false;
523 default:
524 return false;
525 }
526 }
528 bool sym_string_within_range(struct symbol *sym, const char *str)
529 {
530 struct property *prop;
531 int val;
533 switch (sym->type) {
534 case S_STRING:
535 return sym_string_valid(sym, str);
536 case S_INT:
537 if (!sym_string_valid(sym, str))
538 return false;
539 prop = sym_get_range_prop(sym);
540 if (!prop)
541 return true;
542 val = strtol(str, NULL, 10);
543 return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
544 val <= sym_get_range_val(prop->expr->right.sym, 10);
545 case S_HEX:
546 if (!sym_string_valid(sym, str))
547 return false;
548 prop = sym_get_range_prop(sym);
549 if (!prop)
550 return true;
551 val = strtol(str, NULL, 16);
552 return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
553 val <= sym_get_range_val(prop->expr->right.sym, 16);
554 case S_BOOLEAN:
555 case S_TRISTATE:
556 switch (str[0]) {
557 case 'y': case 'Y':
558 return sym_tristate_within_range(sym, yes);
559 case 'm': case 'M':
560 return sym_tristate_within_range(sym, mod);
561 case 'n': case 'N':
562 return sym_tristate_within_range(sym, no);
563 }
564 return false;
565 default:
566 return false;
567 }
568 }
570 bool sym_set_string_value(struct symbol *sym, const char *newval)
571 {
572 const char *oldval;
573 char *val;
574 int size;
576 switch (sym->type) {
577 case S_BOOLEAN:
578 case S_TRISTATE:
579 switch (newval[0]) {
580 case 'y': case 'Y':
581 return sym_set_tristate_value(sym, yes);
582 case 'm': case 'M':
583 return sym_set_tristate_value(sym, mod);
584 case 'n': case 'N':
585 return sym_set_tristate_value(sym, no);
586 }
587 return false;
588 default:
589 ;
590 }
592 if (!sym_string_within_range(sym, newval))
593 return false;
595 if (!(sym->flags & SYMBOL_DEF_USER)) {
596 sym->flags |= SYMBOL_DEF_USER;
597 sym_set_changed(sym);
598 }
600 oldval = sym->def[S_DEF_USER].val;
601 size = strlen(newval) + 1;
602 if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
603 size += 2;
604 sym->def[S_DEF_USER].val = val = malloc(size);
605 *val++ = '0';
606 *val++ = 'x';
607 } else if (!oldval || strcmp(oldval, newval))
608 sym->def[S_DEF_USER].val = val = malloc(size);
609 else
610 return true;
612 strcpy(val, newval);
613 free((void *)oldval);
614 sym_clear_all_valid();
616 return true;
617 }
619 const char *sym_get_string_value(struct symbol *sym)
620 {
621 tristate val;
623 switch (sym->type) {
624 case S_BOOLEAN:
625 case S_TRISTATE:
626 val = sym_get_tristate_value(sym);
627 switch (val) {
628 case no:
629 return "n";
630 case mod:
631 return "m";
632 case yes:
633 return "y";
634 }
635 break;
636 default:
637 ;
638 }
639 return (const char *)sym->curr.val;
640 }
642 bool sym_is_changable(struct symbol *sym)
643 {
644 return sym->visible > sym->rev_dep.tri;
645 }
647 struct symbol *sym_lookup(const char *name, int isconst)
648 {
649 struct symbol *symbol;
650 const char *ptr;
651 char *new_name;
652 int hash = 0;
654 if (name) {
655 if (name[0] && !name[1]) {
656 switch (name[0]) {
657 case 'y': return &symbol_yes;
658 case 'm': return &symbol_mod;
659 case 'n': return &symbol_no;
660 }
661 }
662 for (ptr = name; *ptr; ptr++)
663 hash += *ptr;
664 hash &= 0xff;
666 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
667 if (!strcmp(symbol->name, name)) {
668 if ((isconst && symbol->flags & SYMBOL_CONST) ||
669 (!isconst && !(symbol->flags & SYMBOL_CONST)))
670 return symbol;
671 }
672 }
673 new_name = strdup(name);
674 } else {
675 new_name = NULL;
676 hash = 256;
677 }
679 symbol = malloc(sizeof(*symbol));
680 memset(symbol, 0, sizeof(*symbol));
681 symbol->name = new_name;
682 symbol->type = S_UNKNOWN;
683 if (isconst)
684 symbol->flags |= SYMBOL_CONST;
686 symbol->next = symbol_hash[hash];
687 symbol_hash[hash] = symbol;
689 return symbol;
690 }
692 struct symbol *sym_find(const char *name)
693 {
694 struct symbol *symbol = NULL;
695 const char *ptr;
696 int hash = 0;
698 if (!name)
699 return NULL;
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;
712 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
713 if (!strcmp(symbol->name, name) &&
714 !(symbol->flags & SYMBOL_CONST))
715 break;
716 }
718 return symbol;
719 }
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;
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;
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);
754 return sym_arr;
755 }
758 struct symbol *sym_check_deps(struct symbol *sym);
760 static struct symbol *sym_check_expr_deps(struct expr *e)
761 {
762 struct symbol *sym;
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 }
790 struct symbol *sym_check_deps(struct symbol *sym)
791 {
792 struct symbol *sym2;
793 struct property *prop;
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;
802 sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
803 sym2 = sym_check_expr_deps(sym->rev_dep.expr);
804 if (sym2)
805 goto out;
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 }
831 struct property *prop_alloc(enum prop_type type, struct symbol *sym)
832 {
833 struct property *prop;
834 struct property **propp;
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();
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 }
850 return prop;
851 }
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 }
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 }