00001
00002
00003
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
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
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 }