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