diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-12-05 08:41:41 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-12-05 08:41:41 +0000 |
commit | c9f20d9fb93c6c316518483fd103f3afab5cf1af (patch) | |
tree | 72904548bb54dcaf78017d3b35296765437e0bd5 /scripts/config/symbol.c | |
parent | deca106b6dad70ad0a1312a82d762aa8d8ad52ba (diff) | |
download | busybox-w32-c9f20d9fb93c6c316518483fd103f3afab5cf1af.tar.gz busybox-w32-c9f20d9fb93c6c316518483fd103f3afab5cf1af.tar.bz2 busybox-w32-c9f20d9fb93c6c316518483fd103f3afab5cf1af.zip |
Yet another major rework of the BusyBox config system, using the considerably
modified Kbuild system I put into uClibc. With this, there should be no more
need to modify Rules.mak since I've moved all the interesting options into the
config system. I think I've got everything updated, but you never know, I may
have made some mistakes, so watch closely.
-Erik
Diffstat (limited to 'scripts/config/symbol.c')
-rw-r--r-- | scripts/config/symbol.c | 629 |
1 files changed, 629 insertions, 0 deletions
diff --git a/scripts/config/symbol.c b/scripts/config/symbol.c new file mode 100644 index 000000000..f2d0015de --- /dev/null +++ b/scripts/config/symbol.c | |||
@@ -0,0 +1,629 @@ | |||
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 <sys/utsname.h> | ||
10 | |||
11 | #define LKC_DIRECT_LINK | ||
12 | #include "lkc.h" | ||
13 | |||
14 | struct symbol symbol_yes = { | ||
15 | name: "y", | ||
16 | curr: { "y", yes }, | ||
17 | flags: SYMBOL_YES|SYMBOL_VALID, | ||
18 | }, symbol_mod = { | ||
19 | name: "m", | ||
20 | curr: { "m", mod }, | ||
21 | flags: SYMBOL_MOD|SYMBOL_VALID, | ||
22 | }, symbol_no = { | ||
23 | name: "n", | ||
24 | curr: { "n", no }, | ||
25 | flags: SYMBOL_NO|SYMBOL_VALID, | ||
26 | }, symbol_empty = { | ||
27 | name: "", | ||
28 | curr: { "", no }, | ||
29 | flags: SYMBOL_VALID, | ||
30 | }; | ||
31 | |||
32 | int sym_change_count; | ||
33 | struct symbol *modules_sym; | ||
34 | |||
35 | void sym_add_default(struct symbol *sym, const char *def) | ||
36 | { | ||
37 | struct property *prop = create_prop(P_DEFAULT); | ||
38 | struct property **propp; | ||
39 | |||
40 | prop->sym = sym; | ||
41 | prop->def = sym_lookup(def, 1); | ||
42 | |||
43 | /* append property to the prop list of symbol */ | ||
44 | if (prop->sym) { | ||
45 | for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next) | ||
46 | ; | ||
47 | *propp = prop; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | void sym_init(void) | ||
52 | { | ||
53 | struct symbol *sym; | ||
54 | struct utsname uts; | ||
55 | char *p; | ||
56 | static bool inited = false; | ||
57 | |||
58 | if (inited) | ||
59 | return; | ||
60 | inited = true; | ||
61 | |||
62 | uname(&uts); | ||
63 | |||
64 | #if 0 | ||
65 | sym = sym_lookup("ARCH", 0); | ||
66 | sym->type = S_STRING; | ||
67 | sym->flags |= SYMBOL_AUTO; | ||
68 | p = getenv("ARCH"); | ||
69 | if (p) | ||
70 | sym_add_default(sym, p); | ||
71 | #endif | ||
72 | |||
73 | sym = sym_lookup("VERSION", 0); | ||
74 | sym->type = S_STRING; | ||
75 | sym->flags |= SYMBOL_AUTO; | ||
76 | p = getenv("VERSION"); | ||
77 | if (p) | ||
78 | sym_add_default(sym, p); | ||
79 | |||
80 | #if 0 | ||
81 | sym = sym_lookup("UNAME_RELEASE", 0); | ||
82 | sym->type = S_STRING; | ||
83 | sym->flags |= SYMBOL_AUTO; | ||
84 | sym_add_default(sym, uts.release); | ||
85 | #endif | ||
86 | |||
87 | sym = sym_lookup("TARGET_ARCH", 0); | ||
88 | sym->type = S_STRING; | ||
89 | sym->flags |= SYMBOL_AUTO; | ||
90 | p = getenv("TARGET_ARCH"); | ||
91 | if (p) | ||
92 | sym_add_default(sym, p); | ||
93 | } | ||
94 | |||
95 | int sym_get_type(struct symbol *sym) | ||
96 | { | ||
97 | int type = sym->type; | ||
98 | if (type == S_TRISTATE) { | ||
99 | if (sym_is_choice_value(sym) && sym->visible == yes) | ||
100 | type = S_BOOLEAN; | ||
101 | else { | ||
102 | sym_calc_value(modules_sym); | ||
103 | if (S_TRI(modules_sym->curr) == no) | ||
104 | type = S_BOOLEAN; | ||
105 | } | ||
106 | } | ||
107 | return type; | ||
108 | } | ||
109 | |||
110 | const char *sym_type_name(int type) | ||
111 | { | ||
112 | switch (type) { | ||
113 | case S_BOOLEAN: | ||
114 | return "boolean"; | ||
115 | case S_TRISTATE: | ||
116 | return "tristate"; | ||
117 | case S_INT: | ||
118 | return "integer"; | ||
119 | case S_HEX: | ||
120 | return "hex"; | ||
121 | case S_STRING: | ||
122 | return "string"; | ||
123 | case S_UNKNOWN: | ||
124 | return "unknown"; | ||
125 | } | ||
126 | return "???"; | ||
127 | } | ||
128 | |||
129 | struct property *sym_get_choice_prop(struct symbol *sym) | ||
130 | { | ||
131 | struct property *prop; | ||
132 | |||
133 | for_all_choices(sym, prop) | ||
134 | return prop; | ||
135 | return NULL; | ||
136 | } | ||
137 | |||
138 | struct property *sym_get_default_prop(struct symbol *sym) | ||
139 | { | ||
140 | struct property *prop; | ||
141 | tristate visible; | ||
142 | |||
143 | for_all_defaults(sym, prop) { | ||
144 | visible = E_CALC(prop->visible); | ||
145 | if (visible != no) | ||
146 | return prop; | ||
147 | } | ||
148 | return NULL; | ||
149 | } | ||
150 | |||
151 | void sym_calc_visibility(struct symbol *sym) | ||
152 | { | ||
153 | struct property *prop; | ||
154 | tristate visible, oldvisible; | ||
155 | |||
156 | /* any prompt visible? */ | ||
157 | oldvisible = sym->visible; | ||
158 | visible = no; | ||
159 | for_all_prompts(sym, prop) | ||
160 | visible = E_OR(visible, E_CALC(prop->visible)); | ||
161 | if (oldvisible != visible) { | ||
162 | sym->visible = visible; | ||
163 | sym->flags |= SYMBOL_CHANGED; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | void sym_calc_value(struct symbol *sym) | ||
168 | { | ||
169 | struct symbol_value newval, oldval; | ||
170 | struct property *prop, *def_prop; | ||
171 | struct symbol *def_sym; | ||
172 | struct expr *e; | ||
173 | |||
174 | if (sym->flags & SYMBOL_VALID) | ||
175 | return; | ||
176 | |||
177 | oldval = sym->curr; | ||
178 | |||
179 | switch (sym->type) { | ||
180 | case S_INT: | ||
181 | case S_HEX: | ||
182 | case S_STRING: | ||
183 | newval = symbol_empty.curr; | ||
184 | break; | ||
185 | case S_BOOLEAN: | ||
186 | case S_TRISTATE: | ||
187 | newval = symbol_no.curr; | ||
188 | break; | ||
189 | default: | ||
190 | S_VAL(newval) = sym->name; | ||
191 | S_TRI(newval) = no; | ||
192 | if (sym->flags & SYMBOL_CONST) { | ||
193 | goto out; | ||
194 | } | ||
195 | //newval = symbol_empty.curr; | ||
196 | // generate warning somewhere here later | ||
197 | //S_TRI(newval) = yes; | ||
198 | goto out; | ||
199 | } | ||
200 | sym->flags |= SYMBOL_VALID; | ||
201 | if (!sym_is_choice_value(sym)) | ||
202 | sym->flags &= ~SYMBOL_WRITE; | ||
203 | |||
204 | sym_calc_visibility(sym); | ||
205 | |||
206 | /* set default if recursively called */ | ||
207 | sym->curr = newval; | ||
208 | |||
209 | if (sym->visible != no) { | ||
210 | sym->flags |= SYMBOL_WRITE; | ||
211 | if (!sym_has_value(sym)) { | ||
212 | if (!sym_is_choice(sym)) { | ||
213 | prop = sym_get_default_prop(sym); | ||
214 | if (prop) { | ||
215 | sym_calc_value(prop->def); | ||
216 | newval = prop->def->curr; | ||
217 | } | ||
218 | } | ||
219 | } else | ||
220 | newval = sym->def; | ||
221 | |||
222 | S_TRI(newval) = E_AND(S_TRI(newval), sym->visible); | ||
223 | /* if the symbol is visible and not optionial, | ||
224 | * possibly ignore old user choice. */ | ||
225 | if (!sym_is_optional(sym) && S_TRI(newval) == no) | ||
226 | S_TRI(newval) = sym->visible; | ||
227 | if (sym_is_choice_value(sym) && sym->visible == yes) { | ||
228 | prop = sym_get_choice_prop(sym); | ||
229 | S_TRI(newval) = (S_VAL(prop->def->curr) == sym) ? yes : no; | ||
230 | } | ||
231 | } else { | ||
232 | prop = sym_get_default_prop(sym); | ||
233 | if (prop) { | ||
234 | sym->flags |= SYMBOL_WRITE; | ||
235 | sym_calc_value(prop->def); | ||
236 | newval = prop->def->curr; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | switch (sym_get_type(sym)) { | ||
241 | case S_TRISTATE: | ||
242 | if (S_TRI(newval) != mod) | ||
243 | break; | ||
244 | sym_calc_value(modules_sym); | ||
245 | if (S_TRI(modules_sym->curr) == no) | ||
246 | S_TRI(newval) = yes; | ||
247 | break; | ||
248 | case S_BOOLEAN: | ||
249 | if (S_TRI(newval) == mod) | ||
250 | S_TRI(newval) = yes; | ||
251 | } | ||
252 | |||
253 | out: | ||
254 | sym->curr = newval; | ||
255 | |||
256 | if (sym_is_choice(sym) && S_TRI(newval) == yes) { | ||
257 | def_sym = S_VAL(sym->def); | ||
258 | if (def_sym) { | ||
259 | sym_calc_visibility(def_sym); | ||
260 | if (def_sym->visible == no) | ||
261 | def_sym = NULL; | ||
262 | } | ||
263 | if (!def_sym) { | ||
264 | for_all_defaults(sym, def_prop) { | ||
265 | if (E_CALC(def_prop->visible) == no) | ||
266 | continue; | ||
267 | sym_calc_visibility(def_prop->def); | ||
268 | if (def_prop->def->visible != no) { | ||
269 | def_sym = def_prop->def; | ||
270 | break; | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | if (!def_sym) { | ||
276 | prop = sym_get_choice_prop(sym); | ||
277 | for (e = prop->dep; e; e = e->left.expr) { | ||
278 | sym_calc_visibility(e->right.sym); | ||
279 | if (e->right.sym->visible != no) { | ||
280 | def_sym = e->right.sym; | ||
281 | break; | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | |||
286 | S_VAL(newval) = def_sym; | ||
287 | } | ||
288 | |||
289 | if (memcmp(&oldval, &newval, sizeof(newval))) | ||
290 | sym->flags |= SYMBOL_CHANGED; | ||
291 | sym->curr = newval; | ||
292 | |||
293 | if (sym_is_choice(sym)) { | ||
294 | int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); | ||
295 | prop = sym_get_choice_prop(sym); | ||
296 | for (e = prop->dep; e; e = e->left.expr) | ||
297 | e->right.sym->flags |= flags; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | void sym_clear_all_valid(void) | ||
302 | { | ||
303 | struct symbol *sym; | ||
304 | int i; | ||
305 | |||
306 | for_all_symbols(i, sym) | ||
307 | sym->flags &= ~SYMBOL_VALID; | ||
308 | sym_change_count++; | ||
309 | } | ||
310 | |||
311 | void sym_set_all_changed(void) | ||
312 | { | ||
313 | struct symbol *sym; | ||
314 | int i; | ||
315 | |||
316 | for_all_symbols(i, sym) | ||
317 | sym->flags |= SYMBOL_CHANGED; | ||
318 | } | ||
319 | |||
320 | bool sym_tristate_within_range(struct symbol *sym, tristate val) | ||
321 | { | ||
322 | int type = sym_get_type(sym); | ||
323 | |||
324 | if (sym->visible == no) | ||
325 | return false; | ||
326 | |||
327 | if (type != S_BOOLEAN && type != S_TRISTATE) | ||
328 | return false; | ||
329 | |||
330 | switch (val) { | ||
331 | case no: | ||
332 | if (sym_is_choice_value(sym) && sym->visible == yes) | ||
333 | return false; | ||
334 | return sym_is_optional(sym); | ||
335 | case mod: | ||
336 | if (sym_is_choice_value(sym) && sym->visible == yes) | ||
337 | return false; | ||
338 | return type == S_TRISTATE; | ||
339 | case yes: | ||
340 | return type == S_BOOLEAN || sym->visible == yes; | ||
341 | } | ||
342 | return false; | ||
343 | } | ||
344 | |||
345 | bool sym_set_tristate_value(struct symbol *sym, tristate val) | ||
346 | { | ||
347 | tristate oldval = sym_get_tristate_value(sym); | ||
348 | |||
349 | if (oldval != val && !sym_tristate_within_range(sym, val)) | ||
350 | return false; | ||
351 | |||
352 | if (sym->flags & SYMBOL_NEW) { | ||
353 | sym->flags &= ~SYMBOL_NEW; | ||
354 | sym->flags |= SYMBOL_CHANGED; | ||
355 | } | ||
356 | if (sym_is_choice_value(sym) && val == yes) { | ||
357 | struct property *prop = sym_get_choice_prop(sym); | ||
358 | |||
359 | S_VAL(prop->def->def) = sym; | ||
360 | prop->def->flags &= ~SYMBOL_NEW; | ||
361 | } | ||
362 | |||
363 | S_TRI(sym->def) = val; | ||
364 | if (oldval != val) { | ||
365 | sym_clear_all_valid(); | ||
366 | if (sym == modules_sym) | ||
367 | sym_set_all_changed(); | ||
368 | } | ||
369 | |||
370 | return true; | ||
371 | } | ||
372 | |||
373 | tristate sym_toggle_tristate_value(struct symbol *sym) | ||
374 | { | ||
375 | tristate oldval, newval; | ||
376 | |||
377 | oldval = newval = sym_get_tristate_value(sym); | ||
378 | do { | ||
379 | switch (newval) { | ||
380 | case no: | ||
381 | newval = mod; | ||
382 | break; | ||
383 | case mod: | ||
384 | newval = yes; | ||
385 | break; | ||
386 | case yes: | ||
387 | newval = no; | ||
388 | break; | ||
389 | } | ||
390 | if (sym_set_tristate_value(sym, newval)) | ||
391 | break; | ||
392 | } while (oldval != newval); | ||
393 | return newval; | ||
394 | } | ||
395 | |||
396 | bool sym_string_valid(struct symbol *sym, const char *str) | ||
397 | { | ||
398 | char ch; | ||
399 | |||
400 | switch (sym->type) { | ||
401 | case S_STRING: | ||
402 | return true; | ||
403 | case S_INT: | ||
404 | ch = *str++; | ||
405 | if (ch == '-') | ||
406 | ch = *str++; | ||
407 | if (!isdigit((int)ch)) | ||
408 | return false; | ||
409 | if (ch == '0' && *str != 0) | ||
410 | return false; | ||
411 | while ((ch = *str++)) { | ||
412 | if (!isdigit((int)ch)) | ||
413 | return false; | ||
414 | } | ||
415 | return true; | ||
416 | case S_HEX: | ||
417 | if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) | ||
418 | str += 2; | ||
419 | ch = *str++; | ||
420 | do { | ||
421 | if (!isxdigit((int)ch)) | ||
422 | return false; | ||
423 | } while ((ch = *str++)); | ||
424 | return true; | ||
425 | case S_BOOLEAN: | ||
426 | case S_TRISTATE: | ||
427 | switch (str[0]) { | ||
428 | case 'y': | ||
429 | case 'Y': | ||
430 | return sym_tristate_within_range(sym, yes); | ||
431 | case 'm': | ||
432 | case 'M': | ||
433 | return sym_tristate_within_range(sym, mod); | ||
434 | case 'n': | ||
435 | case 'N': | ||
436 | return sym_tristate_within_range(sym, no); | ||
437 | } | ||
438 | return false; | ||
439 | default: | ||
440 | return false; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | bool sym_set_string_value(struct symbol *sym, const char *newval) | ||
445 | { | ||
446 | const char *oldval; | ||
447 | char *val; | ||
448 | int size; | ||
449 | |||
450 | switch (sym->type) { | ||
451 | case S_BOOLEAN: | ||
452 | case S_TRISTATE: | ||
453 | switch (newval[0]) { | ||
454 | case 'y': | ||
455 | case 'Y': | ||
456 | return sym_set_tristate_value(sym, yes); | ||
457 | case 'm': | ||
458 | case 'M': | ||
459 | return sym_set_tristate_value(sym, mod); | ||
460 | case 'n': | ||
461 | case 'N': | ||
462 | return sym_set_tristate_value(sym, no); | ||
463 | } | ||
464 | return false; | ||
465 | default: | ||
466 | ; | ||
467 | } | ||
468 | |||
469 | if (!sym_string_valid(sym, newval)) | ||
470 | return false; | ||
471 | |||
472 | if (sym->flags & SYMBOL_NEW) { | ||
473 | sym->flags &= ~SYMBOL_NEW; | ||
474 | sym->flags |= SYMBOL_CHANGED; | ||
475 | } | ||
476 | |||
477 | oldval = S_VAL(sym->def); | ||
478 | size = strlen(newval) + 1; | ||
479 | if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { | ||
480 | size += 2; | ||
481 | S_VAL(sym->def) = val = malloc(size); | ||
482 | *val++ = '0'; | ||
483 | *val++ = 'x'; | ||
484 | } else if (!oldval || strcmp(oldval, newval)) | ||
485 | S_VAL(sym->def) = val = malloc(size); | ||
486 | else | ||
487 | return true; | ||
488 | |||
489 | strcpy(val, newval); | ||
490 | free((void *)oldval); | ||
491 | sym_clear_all_valid(); | ||
492 | |||
493 | return true; | ||
494 | } | ||
495 | |||
496 | const char *sym_get_string_value(struct symbol *sym) | ||
497 | { | ||
498 | tristate val; | ||
499 | |||
500 | switch (sym->type) { | ||
501 | case S_BOOLEAN: | ||
502 | case S_TRISTATE: | ||
503 | val = sym_get_tristate_value(sym); | ||
504 | switch (val) { | ||
505 | case no: | ||
506 | return "n"; | ||
507 | case mod: | ||
508 | return "m"; | ||
509 | case yes: | ||
510 | return "y"; | ||
511 | } | ||
512 | break; | ||
513 | default: | ||
514 | ; | ||
515 | } | ||
516 | return (const char *)S_VAL(sym->curr); | ||
517 | } | ||
518 | |||
519 | bool sym_is_changable(struct symbol *sym) | ||
520 | { | ||
521 | if (sym->visible == no) | ||
522 | return false; | ||
523 | /* at least 'n' and 'y'/'m' is selectable */ | ||
524 | if (sym_is_optional(sym)) | ||
525 | return true; | ||
526 | /* no 'n', so 'y' and 'm' must be selectable */ | ||
527 | if (sym_get_type(sym) == S_TRISTATE && sym->visible == yes) | ||
528 | return true; | ||
529 | return false; | ||
530 | } | ||
531 | |||
532 | struct symbol *sym_lookup(const char *name, int isconst) | ||
533 | { | ||
534 | struct symbol *symbol; | ||
535 | const char *ptr; | ||
536 | char *new_name; | ||
537 | int hash = 0; | ||
538 | |||
539 | //printf("lookup: %s -> ", name); | ||
540 | if (name) { | ||
541 | if (name[0] && !name[1]) { | ||
542 | switch (name[0]) { | ||
543 | case 'y': return &symbol_yes; | ||
544 | case 'm': return &symbol_mod; | ||
545 | case 'n': return &symbol_no; | ||
546 | } | ||
547 | } | ||
548 | for (ptr = name; *ptr; ptr++) | ||
549 | hash += *ptr; | ||
550 | hash &= 0xff; | ||
551 | |||
552 | for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { | ||
553 | if (!strcmp(symbol->name, name)) { | ||
554 | if ((isconst && symbol->flags & SYMBOL_CONST) || | ||
555 | (!isconst && !(symbol->flags & SYMBOL_CONST))) { | ||
556 | //printf("h:%p\n", symbol); | ||
557 | return symbol; | ||
558 | } | ||
559 | } | ||
560 | } | ||
561 | new_name = strdup(name); | ||
562 | } else { | ||
563 | new_name = NULL; | ||
564 | hash = 256; | ||
565 | } | ||
566 | |||
567 | symbol = malloc(sizeof(*symbol)); | ||
568 | memset(symbol, 0, sizeof(*symbol)); | ||
569 | symbol->name = new_name; | ||
570 | symbol->type = S_UNKNOWN; | ||
571 | symbol->flags = SYMBOL_NEW; | ||
572 | if (isconst) | ||
573 | symbol->flags |= SYMBOL_CONST; | ||
574 | |||
575 | symbol->next = symbol_hash[hash]; | ||
576 | symbol_hash[hash] = symbol; | ||
577 | |||
578 | //printf("n:%p\n", symbol); | ||
579 | return symbol; | ||
580 | } | ||
581 | |||
582 | struct symbol *sym_find(const char *name) | ||
583 | { | ||
584 | struct symbol *symbol = NULL; | ||
585 | const char *ptr; | ||
586 | int hash = 0; | ||
587 | |||
588 | if (!name) | ||
589 | return NULL; | ||
590 | |||
591 | if (name[0] && !name[1]) { | ||
592 | switch (name[0]) { | ||
593 | case 'y': return &symbol_yes; | ||
594 | case 'm': return &symbol_mod; | ||
595 | case 'n': return &symbol_no; | ||
596 | } | ||
597 | } | ||
598 | for (ptr = name; *ptr; ptr++) | ||
599 | hash += *ptr; | ||
600 | hash &= 0xff; | ||
601 | |||
602 | for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { | ||
603 | if (!strcmp(symbol->name, name) && | ||
604 | !(symbol->flags & SYMBOL_CONST)) | ||
605 | break; | ||
606 | } | ||
607 | |||
608 | return symbol; | ||
609 | } | ||
610 | |||
611 | const char *prop_get_type_name(enum prop_type type) | ||
612 | { | ||
613 | switch (type) { | ||
614 | case P_PROMPT: | ||
615 | return "prompt"; | ||
616 | case P_COMMENT: | ||
617 | return "comment"; | ||
618 | case P_MENU: | ||
619 | return "menu"; | ||
620 | case P_ROOTMENU: | ||
621 | return "rootmenu"; | ||
622 | case P_DEFAULT: | ||
623 | return "default"; | ||
624 | case P_CHOICE: | ||
625 | return "choice"; | ||
626 | default: | ||
627 | return "unknown"; | ||
628 | } | ||
629 | } | ||