Annotation of qemu/roms/seabios/tools/kconfig/menu.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (C) 2002 Roman Zippel <[email protected]>
        !             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: static const char nohelp_text[] = N_(
        !            13:        "There is no help available for this option.\n");
        !            14: 
        !            15: struct menu rootmenu;
        !            16: static struct menu **last_entry_ptr;
        !            17: 
        !            18: struct file *file_list;
        !            19: struct file *current_file;
        !            20: 
        !            21: void menu_warn(struct menu *menu, const char *fmt, ...)
        !            22: {
        !            23:        va_list ap;
        !            24:        va_start(ap, fmt);
        !            25:        fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
        !            26:        vfprintf(stderr, fmt, ap);
        !            27:        fprintf(stderr, "\n");
        !            28:        va_end(ap);
        !            29: }
        !            30: 
        !            31: static void prop_warn(struct property *prop, const char *fmt, ...)
        !            32: {
        !            33:        va_list ap;
        !            34:        va_start(ap, fmt);
        !            35:        fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
        !            36:        vfprintf(stderr, fmt, ap);
        !            37:        fprintf(stderr, "\n");
        !            38:        va_end(ap);
        !            39: }
        !            40: 
        !            41: void _menu_init(void)
        !            42: {
        !            43:        current_entry = current_menu = &rootmenu;
        !            44:        last_entry_ptr = &rootmenu.list;
        !            45: }
        !            46: 
        !            47: void menu_add_entry(struct symbol *sym)
        !            48: {
        !            49:        struct menu *menu;
        !            50: 
        !            51:        menu = malloc(sizeof(*menu));
        !            52:        memset(menu, 0, sizeof(*menu));
        !            53:        menu->sym = sym;
        !            54:        menu->parent = current_menu;
        !            55:        menu->file = current_file;
        !            56:        menu->lineno = zconf_lineno();
        !            57: 
        !            58:        *last_entry_ptr = menu;
        !            59:        last_entry_ptr = &menu->next;
        !            60:        current_entry = menu;
        !            61:        if (sym)
        !            62:                menu_add_symbol(P_SYMBOL, sym, NULL);
        !            63: }
        !            64: 
        !            65: void menu_end_entry(void)
        !            66: {
        !            67: }
        !            68: 
        !            69: struct menu *menu_add_menu(void)
        !            70: {
        !            71:        menu_end_entry();
        !            72:        last_entry_ptr = &current_entry->list;
        !            73:        return current_menu = current_entry;
        !            74: }
        !            75: 
        !            76: void menu_end_menu(void)
        !            77: {
        !            78:        last_entry_ptr = &current_menu->next;
        !            79:        current_menu = current_menu->parent;
        !            80: }
        !            81: 
        !            82: static struct expr *menu_check_dep(struct expr *e)
        !            83: {
        !            84:        if (!e)
        !            85:                return e;
        !            86: 
        !            87:        switch (e->type) {
        !            88:        case E_NOT:
        !            89:                e->left.expr = menu_check_dep(e->left.expr);
        !            90:                break;
        !            91:        case E_OR:
        !            92:        case E_AND:
        !            93:                e->left.expr = menu_check_dep(e->left.expr);
        !            94:                e->right.expr = menu_check_dep(e->right.expr);
        !            95:                break;
        !            96:        case E_SYMBOL:
        !            97:                /* change 'm' into 'm' && MODULES */
        !            98:                if (e->left.sym == &symbol_mod)
        !            99:                        return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
        !           100:                break;
        !           101:        default:
        !           102:                break;
        !           103:        }
        !           104:        return e;
        !           105: }
        !           106: 
        !           107: void menu_add_dep(struct expr *dep)
        !           108: {
        !           109:        current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
        !           110: }
        !           111: 
        !           112: void menu_set_type(int type)
        !           113: {
        !           114:        struct symbol *sym = current_entry->sym;
        !           115: 
        !           116:        if (sym->type == type)
        !           117:                return;
        !           118:        if (sym->type == S_UNKNOWN) {
        !           119:                sym->type = type;
        !           120:                return;
        !           121:        }
        !           122:        menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
        !           123:            sym->name ? sym->name : "<choice>",
        !           124:            sym_type_name(sym->type), sym_type_name(type));
        !           125: }
        !           126: 
        !           127: struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
        !           128: {
        !           129:        struct property *prop = prop_alloc(type, current_entry->sym);
        !           130: 
        !           131:        prop->menu = current_entry;
        !           132:        prop->expr = expr;
        !           133:        prop->visible.expr = menu_check_dep(dep);
        !           134: 
        !           135:        if (prompt) {
        !           136:                if (isspace(*prompt)) {
        !           137:                        prop_warn(prop, "leading whitespace ignored");
        !           138:                        while (isspace(*prompt))
        !           139:                                prompt++;
        !           140:                }
        !           141:                if (current_entry->prompt && current_entry != &rootmenu)
        !           142:                        prop_warn(prop, "prompt redefined");
        !           143: 
        !           144:                /* Apply all upper menus' visibilities to actual prompts. */
        !           145:                if(type == P_PROMPT) {
        !           146:                        struct menu *menu = current_entry;
        !           147: 
        !           148:                        while ((menu = menu->parent) != NULL) {
        !           149:                                if (!menu->visibility)
        !           150:                                        continue;
        !           151:                                prop->visible.expr
        !           152:                                        = expr_alloc_and(prop->visible.expr,
        !           153:                                                         menu->visibility);
        !           154:                        }
        !           155:                }
        !           156: 
        !           157:                current_entry->prompt = prop;
        !           158:        }
        !           159:        prop->text = prompt;
        !           160: 
        !           161:        return prop;
        !           162: }
        !           163: 
        !           164: struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
        !           165: {
        !           166:        return menu_add_prop(type, prompt, NULL, dep);
        !           167: }
        !           168: 
        !           169: void menu_add_visibility(struct expr *expr)
        !           170: {
        !           171:        current_entry->visibility = expr_alloc_and(current_entry->visibility,
        !           172:            expr);
        !           173: }
        !           174: 
        !           175: void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
        !           176: {
        !           177:        menu_add_prop(type, NULL, expr, dep);
        !           178: }
        !           179: 
        !           180: void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
        !           181: {
        !           182:        menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
        !           183: }
        !           184: 
        !           185: void menu_add_option(int token, char *arg)
        !           186: {
        !           187:        struct property *prop;
        !           188: 
        !           189:        switch (token) {
        !           190:        case T_OPT_MODULES:
        !           191:                prop = prop_alloc(P_DEFAULT, modules_sym);
        !           192:                prop->expr = expr_alloc_symbol(current_entry->sym);
        !           193:                break;
        !           194:        case T_OPT_DEFCONFIG_LIST:
        !           195:                if (!sym_defconfig_list)
        !           196:                        sym_defconfig_list = current_entry->sym;
        !           197:                else if (sym_defconfig_list != current_entry->sym)
        !           198:                        zconf_error("trying to redefine defconfig symbol");
        !           199:                break;
        !           200:        case T_OPT_ENV:
        !           201:                prop_add_env(arg);
        !           202:                break;
        !           203:        }
        !           204: }
        !           205: 
        !           206: static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
        !           207: {
        !           208:        return sym2->type == S_INT || sym2->type == S_HEX ||
        !           209:               (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
        !           210: }
        !           211: 
        !           212: static void sym_check_prop(struct symbol *sym)
        !           213: {
        !           214:        struct property *prop;
        !           215:        struct symbol *sym2;
        !           216:        for (prop = sym->prop; prop; prop = prop->next) {
        !           217:                switch (prop->type) {
        !           218:                case P_DEFAULT:
        !           219:                        if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
        !           220:                            prop->expr->type != E_SYMBOL)
        !           221:                                prop_warn(prop,
        !           222:                                    "default for config symbol '%s'"
        !           223:                                    " must be a single symbol", sym->name);
        !           224:                        if (prop->expr->type != E_SYMBOL)
        !           225:                                break;
        !           226:                        sym2 = prop_get_symbol(prop);
        !           227:                        if (sym->type == S_HEX || sym->type == S_INT) {
        !           228:                                if (!menu_validate_number(sym, sym2))
        !           229:                                        prop_warn(prop,
        !           230:                                            "'%s': number is invalid",
        !           231:                                            sym->name);
        !           232:                        }
        !           233:                        break;
        !           234:                case P_SELECT:
        !           235:                        sym2 = prop_get_symbol(prop);
        !           236:                        if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
        !           237:                                prop_warn(prop,
        !           238:                                    "config symbol '%s' uses select, but is "
        !           239:                                    "not boolean or tristate", sym->name);
        !           240:                        else if (sym2->type != S_UNKNOWN &&
        !           241:                                 sym2->type != S_BOOLEAN &&
        !           242:                                 sym2->type != S_TRISTATE)
        !           243:                                prop_warn(prop,
        !           244:                                    "'%s' has wrong type. 'select' only "
        !           245:                                    "accept arguments of boolean and "
        !           246:                                    "tristate type", sym2->name);
        !           247:                        break;
        !           248:                case P_RANGE:
        !           249:                        if (sym->type != S_INT && sym->type != S_HEX)
        !           250:                                prop_warn(prop, "range is only allowed "
        !           251:                                                "for int or hex symbols");
        !           252:                        if (!menu_validate_number(sym, prop->expr->left.sym) ||
        !           253:                            !menu_validate_number(sym, prop->expr->right.sym))
        !           254:                                prop_warn(prop, "range is invalid");
        !           255:                        break;
        !           256:                default:
        !           257:                        ;
        !           258:                }
        !           259:        }
        !           260: }
        !           261: 
        !           262: void menu_finalize(struct menu *parent)
        !           263: {
        !           264:        struct menu *menu, *last_menu;
        !           265:        struct symbol *sym;
        !           266:        struct property *prop;
        !           267:        struct expr *parentdep, *basedep, *dep, *dep2, **ep;
        !           268: 
        !           269:        sym = parent->sym;
        !           270:        if (parent->list) {
        !           271:                if (sym && sym_is_choice(sym)) {
        !           272:                        if (sym->type == S_UNKNOWN) {
        !           273:                                /* find the first choice value to find out choice type */
        !           274:                                current_entry = parent;
        !           275:                                for (menu = parent->list; menu; menu = menu->next) {
        !           276:                                        if (menu->sym && menu->sym->type != S_UNKNOWN) {
        !           277:                                                menu_set_type(menu->sym->type);
        !           278:                                                break;
        !           279:                                        }
        !           280:                                }
        !           281:                        }
        !           282:                        /* set the type of the remaining choice values */
        !           283:                        for (menu = parent->list; menu; menu = menu->next) {
        !           284:                                current_entry = menu;
        !           285:                                if (menu->sym && menu->sym->type == S_UNKNOWN)
        !           286:                                        menu_set_type(sym->type);
        !           287:                        }
        !           288:                        parentdep = expr_alloc_symbol(sym);
        !           289:                } else if (parent->prompt)
        !           290:                        parentdep = parent->prompt->visible.expr;
        !           291:                else
        !           292:                        parentdep = parent->dep;
        !           293: 
        !           294:                for (menu = parent->list; menu; menu = menu->next) {
        !           295:                        basedep = expr_transform(menu->dep);
        !           296:                        basedep = expr_alloc_and(expr_copy(parentdep), basedep);
        !           297:                        basedep = expr_eliminate_dups(basedep);
        !           298:                        menu->dep = basedep;
        !           299:                        if (menu->sym)
        !           300:                                prop = menu->sym->prop;
        !           301:                        else
        !           302:                                prop = menu->prompt;
        !           303:                        for (; prop; prop = prop->next) {
        !           304:                                if (prop->menu != menu)
        !           305:                                        continue;
        !           306:                                dep = expr_transform(prop->visible.expr);
        !           307:                                dep = expr_alloc_and(expr_copy(basedep), dep);
        !           308:                                dep = expr_eliminate_dups(dep);
        !           309:                                if (menu->sym && menu->sym->type != S_TRISTATE)
        !           310:                                        dep = expr_trans_bool(dep);
        !           311:                                prop->visible.expr = dep;
        !           312:                                if (prop->type == P_SELECT) {
        !           313:                                        struct symbol *es = prop_get_symbol(prop);
        !           314:                                        es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
        !           315:                                                        expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
        !           316:                                }
        !           317:                        }
        !           318:                }
        !           319:                for (menu = parent->list; menu; menu = menu->next)
        !           320:                        menu_finalize(menu);
        !           321:        } else if (sym) {
        !           322:                basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
        !           323:                basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
        !           324:                basedep = expr_eliminate_dups(expr_transform(basedep));
        !           325:                last_menu = NULL;
        !           326:                for (menu = parent->next; menu; menu = menu->next) {
        !           327:                        dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
        !           328:                        if (!expr_contains_symbol(dep, sym))
        !           329:                                break;
        !           330:                        if (expr_depends_symbol(dep, sym))
        !           331:                                goto next;
        !           332:                        dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
        !           333:                        dep = expr_eliminate_dups(expr_transform(dep));
        !           334:                        dep2 = expr_copy(basedep);
        !           335:                        expr_eliminate_eq(&dep, &dep2);
        !           336:                        expr_free(dep);
        !           337:                        if (!expr_is_yes(dep2)) {
        !           338:                                expr_free(dep2);
        !           339:                                break;
        !           340:                        }
        !           341:                        expr_free(dep2);
        !           342:                next:
        !           343:                        menu_finalize(menu);
        !           344:                        menu->parent = parent;
        !           345:                        last_menu = menu;
        !           346:                }
        !           347:                if (last_menu) {
        !           348:                        parent->list = parent->next;
        !           349:                        parent->next = last_menu->next;
        !           350:                        last_menu->next = NULL;
        !           351:                }
        !           352: 
        !           353:                sym->dir_dep.expr = parent->dep;
        !           354:        }
        !           355:        for (menu = parent->list; menu; menu = menu->next) {
        !           356:                if (sym && sym_is_choice(sym) &&
        !           357:                    menu->sym && !sym_is_choice_value(menu->sym)) {
        !           358:                        current_entry = menu;
        !           359:                        menu->sym->flags |= SYMBOL_CHOICEVAL;
        !           360:                        if (!menu->prompt)
        !           361:                                menu_warn(menu, "choice value must have a prompt");
        !           362:                        for (prop = menu->sym->prop; prop; prop = prop->next) {
        !           363:                                if (prop->type == P_DEFAULT)
        !           364:                                        prop_warn(prop, "defaults for choice "
        !           365:                                                  "values not supported");
        !           366:                                if (prop->menu == menu)
        !           367:                                        continue;
        !           368:                                if (prop->type == P_PROMPT &&
        !           369:                                    prop->menu->parent->sym != sym)
        !           370:                                        prop_warn(prop, "choice value used outside its choice group");
        !           371:                        }
        !           372:                        /* Non-tristate choice values of tristate choices must
        !           373:                         * depend on the choice being set to Y. The choice
        !           374:                         * values' dependencies were propagated to their
        !           375:                         * properties above, so the change here must be re-
        !           376:                         * propagated.
        !           377:                         */
        !           378:                        if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
        !           379:                                basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
        !           380:                                menu->dep = expr_alloc_and(basedep, menu->dep);
        !           381:                                for (prop = menu->sym->prop; prop; prop = prop->next) {
        !           382:                                        if (prop->menu != menu)
        !           383:                                                continue;
        !           384:                                        prop->visible.expr = expr_alloc_and(expr_copy(basedep),
        !           385:                                                                            prop->visible.expr);
        !           386:                                }
        !           387:                        }
        !           388:                        menu_add_symbol(P_CHOICE, sym, NULL);
        !           389:                        prop = sym_get_choice_prop(sym);
        !           390:                        for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
        !           391:                                ;
        !           392:                        *ep = expr_alloc_one(E_LIST, NULL);
        !           393:                        (*ep)->right.sym = menu->sym;
        !           394:                }
        !           395:                if (menu->list && (!menu->prompt || !menu->prompt->text)) {
        !           396:                        for (last_menu = menu->list; ; last_menu = last_menu->next) {
        !           397:                                last_menu->parent = parent;
        !           398:                                if (!last_menu->next)
        !           399:                                        break;
        !           400:                        }
        !           401:                        last_menu->next = menu->next;
        !           402:                        menu->next = menu->list;
        !           403:                        menu->list = NULL;
        !           404:                }
        !           405:        }
        !           406: 
        !           407:        if (sym && !(sym->flags & SYMBOL_WARNED)) {
        !           408:                if (sym->type == S_UNKNOWN)
        !           409:                        menu_warn(parent, "config symbol defined without type");
        !           410: 
        !           411:                if (sym_is_choice(sym) && !parent->prompt)
        !           412:                        menu_warn(parent, "choice must have a prompt");
        !           413: 
        !           414:                /* Check properties connected to this symbol */
        !           415:                sym_check_prop(sym);
        !           416:                sym->flags |= SYMBOL_WARNED;
        !           417:        }
        !           418: 
        !           419:        if (sym && !sym_is_optional(sym) && parent->prompt) {
        !           420:                sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
        !           421:                                expr_alloc_and(parent->prompt->visible.expr,
        !           422:                                        expr_alloc_symbol(&symbol_mod)));
        !           423:        }
        !           424: }
        !           425: 
        !           426: bool menu_has_prompt(struct menu *menu)
        !           427: {
        !           428:        if (!menu->prompt)
        !           429:                return false;
        !           430:        return true;
        !           431: }
        !           432: 
        !           433: bool menu_is_visible(struct menu *menu)
        !           434: {
        !           435:        struct menu *child;
        !           436:        struct symbol *sym;
        !           437:        tristate visible;
        !           438: 
        !           439:        if (!menu->prompt)
        !           440:                return false;
        !           441: 
        !           442:        if (menu->visibility) {
        !           443:                if (expr_calc_value(menu->visibility) == no)
        !           444:                        return no;
        !           445:        }
        !           446: 
        !           447:        sym = menu->sym;
        !           448:        if (sym) {
        !           449:                sym_calc_value(sym);
        !           450:                visible = menu->prompt->visible.tri;
        !           451:        } else
        !           452:                visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
        !           453: 
        !           454:        if (visible != no)
        !           455:                return true;
        !           456: 
        !           457:        if (!sym || sym_get_tristate_value(menu->sym) == no)
        !           458:                return false;
        !           459: 
        !           460:        for (child = menu->list; child; child = child->next) {
        !           461:                if (menu_is_visible(child)) {
        !           462:                        if (sym)
        !           463:                                sym->flags |= SYMBOL_DEF_USER;
        !           464:                        return true;
        !           465:                }
        !           466:        }
        !           467: 
        !           468:        return false;
        !           469: }
        !           470: 
        !           471: const char *menu_get_prompt(struct menu *menu)
        !           472: {
        !           473:        if (menu->prompt)
        !           474:                return menu->prompt->text;
        !           475:        else if (menu->sym)
        !           476:                return menu->sym->name;
        !           477:        return NULL;
        !           478: }
        !           479: 
        !           480: struct menu *menu_get_root_menu(struct menu *menu)
        !           481: {
        !           482:        return &rootmenu;
        !           483: }
        !           484: 
        !           485: struct menu *menu_get_parent_menu(struct menu *menu)
        !           486: {
        !           487:        enum prop_type type;
        !           488: 
        !           489:        for (; menu != &rootmenu; menu = menu->parent) {
        !           490:                type = menu->prompt ? menu->prompt->type : 0;
        !           491:                if (type == P_MENU)
        !           492:                        break;
        !           493:        }
        !           494:        return menu;
        !           495: }
        !           496: 
        !           497: bool menu_has_help(struct menu *menu)
        !           498: {
        !           499:        return menu->help != NULL;
        !           500: }
        !           501: 
        !           502: const char *menu_get_help(struct menu *menu)
        !           503: {
        !           504:        if (menu->help)
        !           505:                return menu->help;
        !           506:        else
        !           507:                return "";
        !           508: }
        !           509: 
        !           510: static void get_prompt_str(struct gstr *r, struct property *prop)
        !           511: {
        !           512:        int i, j;
        !           513:        struct menu *submenu[8], *menu;
        !           514: 
        !           515:        str_printf(r, _("Prompt: %s\n"), _(prop->text));
        !           516:        str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name,
        !           517:                prop->menu->lineno);
        !           518:        if (!expr_is_yes(prop->visible.expr)) {
        !           519:                str_append(r, _("  Depends on: "));
        !           520:                expr_gstr_print(prop->visible.expr, r);
        !           521:                str_append(r, "\n");
        !           522:        }
        !           523:        menu = prop->menu->parent;
        !           524:        for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
        !           525:                submenu[i++] = menu;
        !           526:        if (i > 0) {
        !           527:                str_printf(r, _("  Location:\n"));
        !           528:                for (j = 4; --i >= 0; j += 2) {
        !           529:                        menu = submenu[i];
        !           530:                        str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
        !           531:                        if (menu->sym) {
        !           532:                                str_printf(r, " (%s [=%s])", menu->sym->name ?
        !           533:                                        menu->sym->name : _("<choice>"),
        !           534:                                        sym_get_string_value(menu->sym));
        !           535:                        }
        !           536:                        str_append(r, "\n");
        !           537:                }
        !           538:        }
        !           539: }
        !           540: 
        !           541: void get_symbol_str(struct gstr *r, struct symbol *sym)
        !           542: {
        !           543:        bool hit;
        !           544:        struct property *prop;
        !           545: 
        !           546:        if (sym && sym->name) {
        !           547:                str_printf(r, "Symbol: %s [=%s]\n", sym->name,
        !           548:                           sym_get_string_value(sym));
        !           549:                str_printf(r, "Type  : %s\n", sym_type_name(sym->type));
        !           550:                if (sym->type == S_INT || sym->type == S_HEX) {
        !           551:                        prop = sym_get_range_prop(sym);
        !           552:                        if (prop) {
        !           553:                                str_printf(r, "Range : ");
        !           554:                                expr_gstr_print(prop->expr, r);
        !           555:                                str_append(r, "\n");
        !           556:                        }
        !           557:                }
        !           558:        }
        !           559:        for_all_prompts(sym, prop)
        !           560:                get_prompt_str(r, prop);
        !           561:        hit = false;
        !           562:        for_all_properties(sym, prop, P_SELECT) {
        !           563:                if (!hit) {
        !           564:                        str_append(r, "  Selects: ");
        !           565:                        hit = true;
        !           566:                } else
        !           567:                        str_printf(r, " && ");
        !           568:                expr_gstr_print(prop->expr, r);
        !           569:        }
        !           570:        if (hit)
        !           571:                str_append(r, "\n");
        !           572:        if (sym->rev_dep.expr) {
        !           573:                str_append(r, _("  Selected by: "));
        !           574:                expr_gstr_print(sym->rev_dep.expr, r);
        !           575:                str_append(r, "\n");
        !           576:        }
        !           577:        str_append(r, "\n\n");
        !           578: }
        !           579: 
        !           580: struct gstr get_relations_str(struct symbol **sym_arr)
        !           581: {
        !           582:        struct symbol *sym;
        !           583:        struct gstr res = str_new();
        !           584:        int i;
        !           585: 
        !           586:        for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
        !           587:                get_symbol_str(&res, sym);
        !           588:        if (!i)
        !           589:                str_append(&res, _("No matches found.\n"));
        !           590:        return res;
        !           591: }
        !           592: 
        !           593: 
        !           594: void menu_get_ext_help(struct menu *menu, struct gstr *help)
        !           595: {
        !           596:        struct symbol *sym = menu->sym;
        !           597: 
        !           598:        if (menu_has_help(menu)) {
        !           599:                if (sym->name) {
        !           600:                        str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
        !           601:                        str_append(help, _(menu_get_help(menu)));
        !           602:                        str_append(help, "\n");
        !           603:                }
        !           604:        } else {
        !           605:                str_append(help, nohelp_text);
        !           606:        }
        !           607:        if (sym)
        !           608:                get_symbol_str(help, sym);
        !           609: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.