home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6-686 / scripts / kconfig / menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  9.9 KB  |  398 lines

  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 <stdlib.h>
  7. #include <string.h>
  8.  
  9. #define LKC_DIRECT_LINK
  10. #include "lkc.h"
  11.  
  12. struct menu rootmenu;
  13. static struct menu **last_entry_ptr;
  14.  
  15. struct file *file_list;
  16. struct file *current_file;
  17.  
  18. static void menu_warn(struct menu *menu, const char *fmt, ...)
  19. {
  20.     va_list ap;
  21.     va_start(ap, fmt);
  22.     fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
  23.     vfprintf(stderr, fmt, ap);
  24.     fprintf(stderr, "\n");
  25.     va_end(ap);
  26. }
  27.  
  28. static void prop_warn(struct property *prop, const char *fmt, ...)
  29. {
  30.     va_list ap;
  31.     va_start(ap, fmt);
  32.     fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
  33.     vfprintf(stderr, fmt, ap);
  34.     fprintf(stderr, "\n");
  35.     va_end(ap);
  36. }
  37.  
  38. void menu_init(void)
  39. {
  40.     current_entry = current_menu = &rootmenu;
  41.     last_entry_ptr = &rootmenu.list;
  42. }
  43.  
  44. void menu_add_entry(struct symbol *sym)
  45. {
  46.     struct menu *menu;
  47.  
  48.     menu = malloc(sizeof(*menu));
  49.     memset(menu, 0, sizeof(*menu));
  50.     menu->sym = sym;
  51.     menu->parent = current_menu;
  52.     menu->file = current_file;
  53.     menu->lineno = zconf_lineno();
  54.  
  55.     *last_entry_ptr = menu;
  56.     last_entry_ptr = &menu->next;
  57.     current_entry = menu;
  58. }
  59.  
  60. void menu_end_entry(void)
  61. {
  62. }
  63.  
  64. struct menu *menu_add_menu(void)
  65. {
  66.     menu_end_entry();
  67.     last_entry_ptr = ¤t_entry->list;
  68.     return current_menu = current_entry;
  69. }
  70.  
  71. void menu_end_menu(void)
  72. {
  73.     last_entry_ptr = ¤t_menu->next;
  74.     current_menu = current_menu->parent;
  75. }
  76.  
  77. struct expr *menu_check_dep(struct expr *e)
  78. {
  79.     if (!e)
  80.         return e;
  81.  
  82.     switch (e->type) {
  83.     case E_NOT:
  84.         e->left.expr = menu_check_dep(e->left.expr);
  85.         break;
  86.     case E_OR:
  87.     case E_AND:
  88.         e->left.expr = menu_check_dep(e->left.expr);
  89.         e->right.expr = menu_check_dep(e->right.expr);
  90.         break;
  91.     case E_SYMBOL:
  92.         /* change 'm' into 'm' && MODULES */
  93.         if (e->left.sym == &symbol_mod)
  94.             return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
  95.         break;
  96.     default:
  97.         break;
  98.     }
  99.     return e;
  100. }
  101.  
  102. void menu_add_dep(struct expr *dep)
  103. {
  104.     current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
  105. }
  106.  
  107. void menu_set_type(int type)
  108. {
  109.     struct symbol *sym = current_entry->sym;
  110.  
  111.     if (sym->type == type)
  112.         return;
  113.     if (sym->type == S_UNKNOWN) {
  114.         sym->type = type;
  115.         return;
  116.     }
  117.     menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n",
  118.         sym->name ? sym->name : "<choice>",
  119.         sym_type_name(sym->type), sym_type_name(type));
  120. }
  121.  
  122. struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
  123. {
  124.     struct property *prop = prop_alloc(type, current_entry->sym);
  125.  
  126.     prop->menu = current_entry;
  127.     prop->text = prompt;
  128.     prop->expr = expr;
  129.     prop->visible.expr = menu_check_dep(dep);
  130.  
  131.     if (prompt) {
  132.         if (current_entry->prompt)
  133.             menu_warn(current_entry, "prompt redefined\n");
  134.         current_entry->prompt = prop;
  135.     }
  136.  
  137.     return prop;
  138. }
  139.  
  140. struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
  141. {
  142.     return menu_add_prop(type, prompt, NULL, dep);
  143. }
  144.  
  145. void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
  146. {
  147.     menu_add_prop(type, NULL, expr, dep);
  148. }
  149.  
  150. void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
  151. {
  152.     menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
  153. }
  154.  
  155. static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
  156. {
  157.     return sym2->type == S_INT || sym2->type == S_HEX ||
  158.            (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
  159. }
  160.  
  161. void sym_check_prop(struct symbol *sym)
  162. {
  163.     struct property *prop;
  164.     struct symbol *sym2;
  165.     for (prop = sym->prop; prop; prop = prop->next) {
  166.         switch (prop->type) {
  167.         case P_DEFAULT:
  168.             if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
  169.                 prop->expr->type != E_SYMBOL)
  170.                 prop_warn(prop,
  171.                     "default for config symbol '%'"
  172.                     " must be a single symbol", sym->name);
  173.             break;
  174.         case P_SELECT:
  175.             sym2 = prop_get_symbol(prop);
  176.             if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
  177.                 prop_warn(prop,
  178.                     "config symbol '%s' uses select, but is "
  179.                     "not boolean or tristate", sym->name);
  180.             else if (sym2->type == S_UNKNOWN)
  181.                 prop_warn(prop,
  182.                     "'select' used by config symbol '%s' "
  183.                     "refer to undefined symbol '%s'",
  184.                     sym->name, sym2->name);
  185.             else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
  186.                 prop_warn(prop,
  187.                     "'%s' has wrong type. 'select' only "
  188.                     "accept arguments of boolean and "
  189.                     "tristate type", sym2->name);
  190.             break;
  191.         case P_RANGE:
  192.             if (sym->type != S_INT && sym->type != S_HEX)
  193.                 prop_warn(prop, "range is only allowed "
  194.                                 "for int or hex symbols");
  195.             if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
  196.                 !menu_range_valid_sym(sym, prop->expr->right.sym))
  197.                 prop_warn(prop, "range is invalid");
  198.             break;
  199.         default:
  200.             ;
  201.         }
  202.     }
  203. }
  204.  
  205. void menu_finalize(struct menu *parent)
  206. {
  207.     struct menu *menu, *last_menu;
  208.     struct symbol *sym;
  209.     struct property *prop;
  210.     struct expr *parentdep, *basedep, *dep, *dep2, **ep;
  211.  
  212.     sym = parent->sym;
  213.     if (parent->list) {
  214.         if (sym && sym_is_choice(sym)) {
  215.             /* find the first choice value and find out choice type */
  216.             for (menu = parent->list; menu; menu = menu->next) {
  217.                 if (menu->sym) {
  218.                     current_entry = parent;
  219.                     menu_set_type(menu->sym->type);
  220.                     current_entry = menu;
  221.                     menu_set_type(sym->type);
  222.                     break;
  223.                 }
  224.             }
  225.             parentdep = expr_alloc_symbol(sym);
  226.         } else if (parent->prompt)
  227.             parentdep = parent->prompt->visible.expr;
  228.         else
  229.             parentdep = parent->dep;
  230.  
  231.         for (menu = parent->list; menu; menu = menu->next) {
  232.             basedep = expr_transform(menu->dep);
  233.             basedep = expr_alloc_and(expr_copy(parentdep), basedep);
  234.             basedep = expr_eliminate_dups(basedep);
  235.             menu->dep = basedep;
  236.             if (menu->sym)
  237.                 prop = menu->sym->prop;
  238.             else
  239.                 prop = menu->prompt;
  240.             for (; prop; prop = prop->next) {
  241.                 if (prop->menu != menu)
  242.                     continue;
  243.                 dep = expr_transform(prop->visible.expr);
  244.                 dep = expr_alloc_and(expr_copy(basedep), dep);
  245.                 dep = expr_eliminate_dups(dep);
  246.                 if (menu->sym && menu->sym->type != S_TRISTATE)
  247.                     dep = expr_trans_bool(dep);
  248.                 prop->visible.expr = dep;
  249.                 if (prop->type == P_SELECT) {
  250.                     struct symbol *es = prop_get_symbol(prop);
  251.                     es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
  252.                             expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
  253.                 }
  254.             }
  255.         }
  256.         for (menu = parent->list; menu; menu = menu->next)
  257.             menu_finalize(menu);
  258.     } else if (sym) {
  259.         basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
  260.         basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
  261.         basedep = expr_eliminate_dups(expr_transform(basedep));
  262.         last_menu = NULL;
  263.         for (menu = parent->next; menu; menu = menu->next) {
  264.             dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
  265.             if (!expr_contains_symbol(dep, sym))
  266.                 break;
  267.             if (expr_depends_symbol(dep, sym))
  268.                 goto next;
  269.             dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
  270.             dep = expr_eliminate_dups(expr_transform(dep));
  271.             dep2 = expr_copy(basedep);
  272.             expr_eliminate_eq(&dep, &dep2);
  273.             expr_free(dep);
  274.             if (!expr_is_yes(dep2)) {
  275.                 expr_free(dep2);
  276.                 break;
  277.             }
  278.             expr_free(dep2);
  279.         next:
  280.             menu_finalize(menu);
  281.             menu->parent = parent;
  282.             last_menu = menu;
  283.         }
  284.         if (last_menu) {
  285.             parent->list = parent->next;
  286.             parent->next = last_menu->next;
  287.             last_menu->next = NULL;
  288.         }
  289.     }
  290.     for (menu = parent->list; menu; menu = menu->next) {
  291.         if (sym && sym_is_choice(sym) && menu->sym) {
  292.             menu->sym->flags |= SYMBOL_CHOICEVAL;
  293.             if (!menu->prompt)
  294.                 menu_warn(menu, "choice value must have a prompt");
  295.             for (prop = menu->sym->prop; prop; prop = prop->next) {
  296.                 if (prop->type == P_PROMPT && prop->menu != menu) {
  297.                     prop_warn(prop, "choice values "
  298.                         "currently only support a "
  299.                         "single prompt");
  300.                 }
  301.                 if (prop->type == P_DEFAULT)
  302.                     prop_warn(prop, "defaults for choice "
  303.                         "values not supported");
  304.             }
  305.             current_entry = menu;
  306.             menu_set_type(sym->type);
  307.             menu_add_symbol(P_CHOICE, sym, NULL);
  308.             prop = sym_get_choice_prop(sym);
  309.             for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
  310.                 ;
  311.             *ep = expr_alloc_one(E_CHOICE, NULL);
  312.             (*ep)->right.sym = menu->sym;
  313.         }
  314.         if (menu->list && (!menu->prompt || !menu->prompt->text)) {
  315.             for (last_menu = menu->list; ; last_menu = last_menu->next) {
  316.                 last_menu->parent = parent;
  317.                 if (!last_menu->next)
  318.                     break;
  319.             }
  320.             last_menu->next = menu->next;
  321.             menu->next = menu->list;
  322.             menu->list = NULL;
  323.         }
  324.     }
  325.  
  326.     if (sym && !(sym->flags & SYMBOL_WARNED)) {
  327.         if (sym->type == S_UNKNOWN)
  328.             menu_warn(parent, "config symbol defined "
  329.                 "without type\n");
  330.  
  331.         if (sym_is_choice(sym) && !parent->prompt)
  332.             menu_warn(parent, "choice must have a prompt\n");
  333.  
  334.         /* Check properties connected to this symbol */
  335.         sym_check_prop(sym);
  336.         sym->flags |= SYMBOL_WARNED;
  337.     }
  338.  
  339.     if (sym && !sym_is_optional(sym) && parent->prompt) {
  340.         sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
  341.                 expr_alloc_and(parent->prompt->visible.expr,
  342.                     expr_alloc_symbol(&symbol_mod)));
  343.     }
  344. }
  345.  
  346. bool menu_is_visible(struct menu *menu)
  347. {
  348.     struct menu *child;
  349.     struct symbol *sym;
  350.     tristate visible;
  351.  
  352.     if (!menu->prompt)
  353.         return false;
  354.     sym = menu->sym;
  355.     if (sym) {
  356.         sym_calc_value(sym);
  357.         visible = menu->prompt->visible.tri;
  358.     } else
  359.         visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
  360.  
  361.     if (visible != no)
  362.         return true;
  363.     if (!sym || sym_get_tristate_value(menu->sym) == no)
  364.         return false;
  365.  
  366.     for (child = menu->list; child; child = child->next)
  367.         if (menu_is_visible(child))
  368.             return true;
  369.     return false;
  370. }
  371.  
  372. const char *menu_get_prompt(struct menu *menu)
  373. {
  374.     if (menu->prompt)
  375.         return _(menu->prompt->text);
  376.     else if (menu->sym)
  377.         return _(menu->sym->name);
  378.     return NULL;
  379. }
  380.  
  381. struct menu *menu_get_root_menu(struct menu *menu)
  382. {
  383.     return &rootmenu;
  384. }
  385.  
  386. struct menu *menu_get_parent_menu(struct menu *menu)
  387. {
  388.     enum prop_type type;
  389.  
  390.     for (; menu != &rootmenu; menu = menu->parent) {
  391.         type = menu->prompt ? menu->prompt->type : 0;
  392.         if (type == P_MENU)
  393.             break;
  394.     }
  395.     return menu;
  396. }
  397.  
  398.