base/config/kconfig/conf.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
00003  * Released under the terms of the GNU GPL v2.0.
00004  */
00005 
00006 #include <ctype.h>
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <unistd.h>
00010 #include <time.h>
00011 #include <sys/stat.h>
00012 
00013 #define LKC_DIRECT_LINK
00014 #include "lkc.h"
00015 
00016 static void conf(struct menu *menu);
00017 static void check_conf(struct menu *menu);
00018 
00019 enum {
00020     ask_all,
00021     ask_new,
00022     ask_silent,
00023     set_default,
00024     set_yes,
00025     set_mod,
00026     set_no,
00027     set_random
00028 } input_mode = ask_all;
00029 char *defconfig_file;
00030 
00031 static int indent = 1;
00032 static int valid_stdin = 1;
00033 static int conf_cnt;
00034 static char line[128];
00035 static struct menu *rootEntry;
00036 
00037 static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
00038 
00039 static void strip(char *str)
00040 {
00041     char *p = str;
00042     int l;
00043 
00044     while ((isspace(*p)))
00045         p++;
00046     l = strlen(p);
00047     if (p != str)
00048         memmove(str, p, l + 1);
00049     if (!l)
00050         return;
00051     p = str + l - 1;
00052     while ((isspace(*p)))
00053         *p-- = 0;
00054 }
00055 
00056 static void check_stdin(void)
00057 {
00058     if (!valid_stdin && input_mode == ask_silent) {
00059         printf("aborted!\n\n");
00060         printf("Console input/output is redirected. ");
00061         printf("Run 'make oldconfig' to update configuration.\n\n");
00062         exit(1);
00063     }
00064 }
00065 
00066 static void conf_askvalue(struct symbol *sym, const char *def)
00067 {
00068     enum symbol_type type = sym_get_type(sym);
00069     tristate val;
00070 
00071     if (!sym_has_value(sym))
00072         printf("(NEW) ");
00073 
00074     line[0] = '\n';
00075     line[1] = 0;
00076 
00077     if (!sym_is_changable(sym)) {
00078         printf("%s\n", def);
00079         line[0] = '\n';
00080         line[1] = 0;
00081         return;
00082     }
00083 
00084     switch (input_mode) {
00085     case ask_new:
00086     case ask_silent:
00087         if (sym_has_value(sym)) {
00088             printf("%s\n", def);
00089             return;
00090         }
00091         check_stdin();
00092     case ask_all:
00093         fflush(stdout);
00094         fgets(line, 128, stdin);
00095         return;
00096     case set_default:
00097         printf("%s\n", def);
00098         return;
00099     default:
00100         break;
00101     }
00102 
00103     switch (type) {
00104     case S_INT:
00105     case S_HEX:
00106     case S_STRING:
00107         printf("%s\n", def);
00108         return;
00109     default:
00110         ;
00111     }
00112     switch (input_mode) {
00113     case set_yes:
00114         if (sym_tristate_within_range(sym, yes)) {
00115             line[0] = 'y';
00116             line[1] = '\n';
00117             line[2] = 0;
00118             break;
00119         }
00120     case set_mod:
00121         if (type == S_TRISTATE) {
00122             if (sym_tristate_within_range(sym, mod)) {
00123                 line[0] = 'm';
00124                 line[1] = '\n';
00125                 line[2] = 0;
00126                 break;
00127             }
00128         } else {
00129             if (sym_tristate_within_range(sym, yes)) {
00130                 line[0] = 'y';
00131                 line[1] = '\n';
00132                 line[2] = 0;
00133                 break;
00134             }
00135         }
00136     case set_no:
00137         if (sym_tristate_within_range(sym, no)) {
00138             line[0] = 'n';
00139             line[1] = '\n';
00140             line[2] = 0;
00141             break;
00142         }
00143     case set_random:
00144         do {
00145             val = (tristate)(random() % 3);
00146         } while (!sym_tristate_within_range(sym, val));
00147         switch (val) {
00148         case no: line[0] = 'n'; break;
00149         case mod: line[0] = 'm'; break;
00150         case yes: line[0] = 'y'; break;
00151         }
00152         line[1] = '\n';
00153         line[2] = 0;
00154         break;
00155     default:
00156         break;
00157     }
00158     printf("%s", line);
00159 }
00160 
00161 int conf_string(struct menu *menu)
00162 {
00163     struct symbol *sym = menu->sym;
00164     const char *def, *help;
00165 
00166     while (1) {
00167         printf("%*s%s ", indent - 1, "", menu->prompt->text);
00168         printf("(%s) ", sym->name);
00169         def = sym_get_string_value(sym);
00170         if (sym_get_string_value(sym))
00171             printf("[%s] ", def);
00172         conf_askvalue(sym, def);
00173         switch (line[0]) {
00174         case '\n':
00175             break;
00176         case '?':
00177             /* print help */
00178             if (line[1] == 0) {
00179                 help = nohelp_text;
00180                 if (menu->sym->help)
00181                     help = menu->sym->help;
00182                 printf("\n%s\n", menu->sym->help);
00183                 def = NULL;
00184                 break;
00185             }
00186         default:
00187             line[strlen(line)-1] = 0;
00188             def = line;
00189         }
00190         if (def && sym_set_string_value(sym, def))
00191             return 0;
00192     }
00193 }
00194 
00195 static int conf_sym(struct menu *menu)
00196 {
00197     struct symbol *sym = menu->sym;
00198     int type;
00199     tristate oldval, newval;
00200     const char *help;
00201 
00202     while (1) {
00203         printf("%*s%s ", indent - 1, "", menu->prompt->text);
00204         if (sym->name)
00205             printf("(%s) ", sym->name);
00206         type = sym_get_type(sym);
00207         putchar('[');
00208         oldval = sym_get_tristate_value(sym);
00209         switch (oldval) {
00210         case no:
00211             putchar('N');
00212             break;
00213         case mod:
00214             putchar('M');
00215             break;
00216         case yes:
00217             putchar('Y');
00218             break;
00219         }
00220         if (oldval != no && sym_tristate_within_range(sym, no))
00221             printf("/n");
00222         if (oldval != mod && sym_tristate_within_range(sym, mod))
00223             printf("/m");
00224         if (oldval != yes && sym_tristate_within_range(sym, yes))
00225             printf("/y");
00226         if (sym->help)
00227             printf("/?");
00228         printf("] ");
00229         conf_askvalue(sym, sym_get_string_value(sym));
00230         strip(line);
00231 
00232         switch (line[0]) {
00233         case 'n':
00234         case 'N':
00235             newval = no;
00236             if (!line[1] || !strcmp(&line[1], "o"))
00237                 break;
00238             continue;
00239         case 'm':
00240         case 'M':
00241             newval = mod;
00242             if (!line[1])
00243                 break;
00244             continue;
00245         case 'y':
00246         case 'Y':
00247             newval = yes;
00248             if (!line[1] || !strcmp(&line[1], "es"))
00249                 break;
00250             continue;
00251         case 0:
00252             newval = oldval;
00253             break;
00254         case '?':
00255             goto help;
00256         default:
00257             continue;
00258         }
00259         if (sym_set_tristate_value(sym, newval))
00260             return 0;
00261 help:
00262         help = nohelp_text;
00263         if (sym->help)
00264             help = sym->help;
00265         printf("\n%s\n", help);
00266     }
00267 }
00268 
00269 static int conf_choice(struct menu *menu)
00270 {
00271     struct symbol *sym, *def_sym;
00272     struct menu *child;
00273     int type;
00274     bool is_new;
00275 
00276     sym = menu->sym;
00277     type = sym_get_type(sym);
00278     is_new = !sym_has_value(sym);
00279     if (sym_is_changable(sym)) {
00280         conf_sym(menu);
00281         sym_calc_value(sym);
00282         switch (sym_get_tristate_value(sym)) {
00283         case no:
00284             return 1;
00285         case mod:
00286             return 0;
00287         case yes:
00288             break;
00289         }
00290     } else {
00291         switch (sym_get_tristate_value(sym)) {
00292         case no:
00293             return 1;
00294         case mod:
00295             printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
00296             return 0;
00297         case yes:
00298             break;
00299         }
00300     }
00301 
00302     while (1) {
00303         int cnt, def;
00304 
00305         printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
00306         def_sym = sym_get_choice_value(sym);
00307         cnt = def = 0;
00308         line[0] = '0';
00309         line[1] = 0;
00310         for (child = menu->list; child; child = child->next) {
00311             if (!menu_is_visible(child))
00312                 continue;
00313             if (!child->sym) {
00314                 printf("%*c %s\n", indent, '*', menu_get_prompt(child));
00315                 continue;
00316             }
00317             cnt++;
00318             if (child->sym == def_sym) {
00319                 def = cnt;
00320                 printf("%*c", indent, '>');
00321             } else
00322                 printf("%*c", indent, ' ');
00323             printf(" %d. %s", cnt, menu_get_prompt(child));
00324             if (child->sym->name)
00325                 printf(" (%s)", child->sym->name);
00326             if (!sym_has_value(child->sym))
00327                 printf(" (NEW)");
00328             printf("\n");
00329         }
00330         printf("%*schoice", indent - 1, "");
00331         if (cnt == 1) {
00332             printf("[1]: 1\n");
00333             goto conf_childs;
00334         }
00335         printf("[1-%d", cnt);
00336         if (sym->help)
00337             printf("?");
00338         printf("]: ");
00339         switch (input_mode) {
00340         case ask_new:
00341         case ask_silent:
00342             if (!is_new) {
00343                 cnt = def;
00344                 printf("%d\n", cnt);
00345                 break;
00346             }
00347             check_stdin();
00348         case ask_all:
00349             fflush(stdout);
00350             fgets(line, 128, stdin);
00351             strip(line);
00352             if (line[0] == '?') {
00353                 printf("\n%s\n", menu->sym->help ?
00354                     menu->sym->help : nohelp_text);
00355                 continue;
00356             }
00357             if (!line[0])
00358                 cnt = def;
00359             else if (isdigit(line[0]))
00360                 cnt = atoi(line);
00361             else
00362                 continue;
00363             break;
00364         case set_random:
00365             def = (random() % cnt) + 1;
00366         case set_default:
00367         case set_yes:
00368         case set_mod:
00369         case set_no:
00370             cnt = def;
00371             printf("%d\n", cnt);
00372             break;
00373         }
00374 
00375     conf_childs:
00376         for (child = menu->list; child; child = child->next) {
00377             if (!child->sym || !menu_is_visible(child))
00378                 continue;
00379             if (!--cnt)
00380                 break;
00381         }
00382         if (!child)
00383             continue;
00384         if (line[strlen(line) - 1] == '?') {
00385             printf("\n%s\n", child->sym->help ?
00386                 child->sym->help : nohelp_text);
00387             continue;
00388         }
00389         sym_set_choice_value(sym, child->sym);
00390         if (child->list) {
00391             indent += 2;
00392             conf(child->list);
00393             indent -= 2;
00394         }
00395         return 1;
00396     }
00397 }
00398 
00399 static void conf(struct menu *menu)
00400 {
00401     struct symbol *sym;
00402     struct property *prop;
00403     struct menu *child;
00404 
00405     if (!menu_is_visible(menu))
00406         return;
00407 
00408     sym = menu->sym;
00409     prop = menu->prompt;
00410     if (prop) {
00411         const char *prompt;
00412 
00413         switch (prop->type) {
00414         case P_MENU:
00415             if (input_mode == ask_silent && rootEntry != menu) {
00416                 check_conf(menu);
00417                 return;
00418             }
00419         case P_COMMENT:
00420             prompt = menu_get_prompt(menu);
00421             if (prompt)
00422                 printf("%*c\n%*c %s\n%*c\n",
00423                     indent, '*',
00424                     indent, '*', prompt,
00425                     indent, '*');
00426         default:
00427             ;
00428         }
00429     }
00430 
00431     if (!sym)
00432         goto conf_childs;
00433 
00434     if (sym_is_choice(sym)) {
00435         conf_choice(menu);
00436         if (sym->curr.tri != mod)
00437             return;
00438         goto conf_childs;
00439     }
00440 
00441     switch (sym->type) {
00442     case S_INT:
00443     case S_HEX:
00444     case S_STRING:
00445         conf_string(menu);
00446         break;
00447     default:
00448         conf_sym(menu);
00449         break;
00450     }
00451 
00452 conf_childs:
00453     if (sym)
00454         indent += 2;
00455     for (child = menu->list; child; child = child->next)
00456         conf(child);
00457     if (sym)
00458         indent -= 2;
00459 }
00460 
00461 static void check_conf(struct menu *menu)
00462 {
00463     struct symbol *sym;
00464     struct menu *child;
00465 
00466     if (!menu_is_visible(menu))
00467         return;
00468 
00469     sym = menu->sym;
00470     if (sym) {
00471         if (sym_is_changable(sym) && !sym_has_value(sym)) {
00472             if (!conf_cnt++)
00473                 printf("*\n* Restart config...\n*\n");
00474             rootEntry = menu_get_parent_menu(menu);
00475             conf(rootEntry);
00476         }
00477         if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod)
00478             return;
00479     }
00480 
00481     for (child = menu->list; child; child = child->next)
00482         check_conf(child);
00483 }
00484 
00485 int main(int ac, char **av)
00486 {
00487     int i = 1;
00488     const char *name;
00489     struct stat tmpstat;
00490 
00491     if (ac > i && av[i][0] == '-') {
00492         switch (av[i++][1]) {
00493         case 'o':
00494             input_mode = ask_new;
00495             break;
00496         case 's':
00497             input_mode = ask_silent;
00498             valid_stdin = isatty(0) && isatty(1) && isatty(2);
00499             break;
00500         case 'd':
00501             input_mode = set_default;
00502             break;
00503         case 'D':
00504             input_mode = set_default;
00505             defconfig_file = av[i++];
00506             if (!defconfig_file) {
00507                 printf("%s: No default config file specified\n",
00508                     av[0]);
00509                 exit(1);
00510             }
00511             break;
00512         case 'n':
00513             input_mode = set_no;
00514             break;
00515         case 'm':
00516             input_mode = set_mod;
00517             break;
00518         case 'y':
00519             input_mode = set_yes;
00520             break;
00521         case 'r':
00522             input_mode = set_random;
00523             srandom(time(NULL));
00524             break;
00525         case 'h':
00526         case '?':
00527             printf("%s [-o|-s] config\n", av[0]);
00528             exit(0);
00529         }
00530     }
00531     name = av[i];
00532     if (!name) {
00533         printf("%s: Kconfig file missing\n", av[0]);
00534     }
00535     conf_parse(name);
00536     //zconfdump(stdout);
00537     switch (input_mode) {
00538     case set_default:
00539         if (!defconfig_file)
00540             defconfig_file = conf_get_default_confname();
00541         if (conf_read(defconfig_file)) {
00542             printf("***\n"
00543                 "*** Can't find default configuration \"%s\"!\n"
00544                 "***\n", defconfig_file);
00545             exit(1);
00546         }
00547         break;
00548     case ask_silent:
00549         if (stat("../../../.rtai_config", &tmpstat)) {
00550             printf("***\n"
00551                 "*** You have not yet configured RTAI!\n"
00552                 "***\n"
00553                 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
00554                 "*** \"make menuconfig\" or \"make xconfig\").\n"
00555                 "***\n");
00556             exit(1);
00557         }
00558     case ask_all:
00559     case ask_new:
00560         conf_read(NULL);
00561         break;
00562     default:
00563         break;
00564     }
00565 
00566     if (input_mode != ask_silent) {
00567         rootEntry = &rootmenu;
00568         conf(&rootmenu);
00569         if (input_mode == ask_all) {
00570             input_mode = ask_silent;
00571             valid_stdin = 1;
00572         }
00573     }
00574     do {
00575         conf_cnt = 0;
00576         check_conf(&rootmenu);
00577     } while (conf_cnt);
00578     conf_write(NULL);
00579     return 0;
00580 }

Generated on Tue Feb 2 17:46:04 2010 for RTAI API by  doxygen 1.4.7