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