conf.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /*
  2. * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  3. * Released under the terms of the GNU GPL v2.0.
  4. */
  5. #include <locale.h>
  6. #include <ctype.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <time.h>
  11. #include <unistd.h>
  12. #include <sys/stat.h>
  13. #define LKC_DIRECT_LINK
  14. #include "lkc.h"
  15. static void conf(struct menu *menu);
  16. static void check_conf(struct menu *menu);
  17. enum {
  18. ask_all,
  19. ask_new,
  20. ask_silent,
  21. set_default,
  22. set_yes,
  23. set_mod,
  24. set_no,
  25. set_random
  26. } input_mode = ask_all;
  27. char *defconfig_file;
  28. static int indent = 1;
  29. static int valid_stdin = 1;
  30. static int conf_cnt;
  31. static char line[128];
  32. static struct menu *rootEntry;
  33. static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
  34. static const char *get_help(struct menu *menu)
  35. {
  36. if (menu_has_help(menu))
  37. return _(menu_get_help(menu));
  38. else
  39. return nohelp_text;
  40. }
  41. static void strip(char *str)
  42. {
  43. char *p = str;
  44. int l;
  45. while ((isspace(*p)))
  46. p++;
  47. l = strlen(p);
  48. if (p != str)
  49. memmove(str, p, l + 1);
  50. if (!l)
  51. return;
  52. p = str + l - 1;
  53. while ((isspace(*p)))
  54. *p-- = 0;
  55. }
  56. static void check_stdin(void)
  57. {
  58. if (!valid_stdin && input_mode == ask_silent) {
  59. printf(_("aborted!\n\n"));
  60. printf(_("Console input/output is redirected. "));
  61. printf(_("Run 'make oldconfig' to update configuration.\n\n"));
  62. exit(1);
  63. }
  64. }
  65. static int conf_askvalue(struct symbol *sym, const char *def)
  66. {
  67. enum symbol_type type = sym_get_type(sym);
  68. tristate val;
  69. if (!sym_has_value(sym))
  70. printf(_("(NEW) "));
  71. line[0] = '\n';
  72. line[1] = 0;
  73. if (!sym_is_changable(sym)) {
  74. printf("%s\n", def);
  75. line[0] = '\n';
  76. line[1] = 0;
  77. return 0;
  78. }
  79. switch (input_mode) {
  80. case set_no:
  81. case set_mod:
  82. case set_yes:
  83. case set_random:
  84. if (sym_has_value(sym)) {
  85. printf("%s\n", def);
  86. return 0;
  87. }
  88. break;
  89. case ask_new:
  90. case ask_silent:
  91. if (sym_has_value(sym)) {
  92. printf("%s\n", def);
  93. return 0;
  94. }
  95. check_stdin();
  96. case ask_all:
  97. fflush(stdout);
  98. fgets(line, 128, stdin);
  99. return 1;
  100. case set_default:
  101. printf("%s\n", def);
  102. return 1;
  103. default:
  104. break;
  105. }
  106. switch (type) {
  107. case S_INT:
  108. case S_HEX:
  109. case S_STRING:
  110. printf("%s\n", def);
  111. return 1;
  112. default:
  113. ;
  114. }
  115. switch (input_mode) {
  116. case set_yes:
  117. if (sym_tristate_within_range(sym, yes)) {
  118. line[0] = 'y';
  119. line[1] = '\n';
  120. line[2] = 0;
  121. break;
  122. }
  123. case set_mod:
  124. if (type == S_TRISTATE) {
  125. if (sym_tristate_within_range(sym, mod)) {
  126. line[0] = 'm';
  127. line[1] = '\n';
  128. line[2] = 0;
  129. break;
  130. }
  131. } else {
  132. if (sym_tristate_within_range(sym, yes)) {
  133. line[0] = 'y';
  134. line[1] = '\n';
  135. line[2] = 0;
  136. break;
  137. }
  138. }
  139. case set_no:
  140. if (sym_tristate_within_range(sym, no)) {
  141. line[0] = 'n';
  142. line[1] = '\n';
  143. line[2] = 0;
  144. break;
  145. }
  146. case set_random:
  147. do {
  148. val = (tristate)(rand() % 3);
  149. } while (!sym_tristate_within_range(sym, val));
  150. switch (val) {
  151. case no: line[0] = 'n'; break;
  152. case mod: line[0] = 'm'; break;
  153. case yes: line[0] = 'y'; break;
  154. }
  155. line[1] = '\n';
  156. line[2] = 0;
  157. break;
  158. default:
  159. break;
  160. }
  161. printf("%s", line);
  162. return 1;
  163. }
  164. int conf_string(struct menu *menu)
  165. {
  166. struct symbol *sym = menu->sym;
  167. const char *def;
  168. while (1) {
  169. printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
  170. printf("(%s) ", sym->name);
  171. def = sym_get_string_value(sym);
  172. if (sym_get_string_value(sym))
  173. printf("[%s] ", def);
  174. if (!conf_askvalue(sym, def))
  175. return 0;
  176. switch (line[0]) {
  177. case '\n':
  178. break;
  179. case '?':
  180. /* print help */
  181. if (line[1] == '\n') {
  182. printf("\n%s\n", get_help(menu));
  183. def = NULL;
  184. break;
  185. }
  186. default:
  187. line[strlen(line)-1] = 0;
  188. def = line;
  189. }
  190. if (def && sym_set_string_value(sym, def))
  191. return 0;
  192. }
  193. }
  194. static int conf_sym(struct menu *menu)
  195. {
  196. struct symbol *sym = menu->sym;
  197. int type;
  198. tristate oldval, newval;
  199. while (1) {
  200. printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
  201. if (sym->name)
  202. printf("(%s) ", sym->name);
  203. type = sym_get_type(sym);
  204. putchar('[');
  205. oldval = sym_get_tristate_value(sym);
  206. switch (oldval) {
  207. case no:
  208. putchar('N');
  209. break;
  210. case mod:
  211. putchar('M');
  212. break;
  213. case yes:
  214. putchar('Y');
  215. break;
  216. }
  217. if (oldval != no && sym_tristate_within_range(sym, no))
  218. printf("/n");
  219. if (oldval != mod && sym_tristate_within_range(sym, mod))
  220. printf("/m");
  221. if (oldval != yes && sym_tristate_within_range(sym, yes))
  222. printf("/y");
  223. if (menu_has_help(menu))
  224. printf("/?");
  225. printf("] ");
  226. if (!conf_askvalue(sym, sym_get_string_value(sym)))
  227. return 0;
  228. strip(line);
  229. switch (line[0]) {
  230. case 'n':
  231. case 'N':
  232. newval = no;
  233. if (!line[1] || !strcmp(&line[1], "o"))
  234. break;
  235. continue;
  236. case 'm':
  237. case 'M':
  238. newval = mod;
  239. if (!line[1])
  240. break;
  241. continue;
  242. case 'y':
  243. case 'Y':
  244. newval = yes;
  245. if (!line[1] || !strcmp(&line[1], "es"))
  246. break;
  247. continue;
  248. case 0:
  249. newval = oldval;
  250. break;
  251. case '?':
  252. goto help;
  253. default:
  254. continue;
  255. }
  256. if (sym_set_tristate_value(sym, newval))
  257. return 0;
  258. help:
  259. printf("\n%s\n", get_help(menu));
  260. }
  261. }
  262. static int conf_choice(struct menu *menu)
  263. {
  264. struct symbol *sym, *def_sym;
  265. struct menu *child;
  266. int type;
  267. bool is_new;
  268. sym = menu->sym;
  269. type = sym_get_type(sym);
  270. is_new = !sym_has_value(sym);
  271. if (sym_is_changable(sym)) {
  272. conf_sym(menu);
  273. sym_calc_value(sym);
  274. switch (sym_get_tristate_value(sym)) {
  275. case no:
  276. return 1;
  277. case mod:
  278. return 0;
  279. case yes:
  280. break;
  281. }
  282. } else {
  283. switch (sym_get_tristate_value(sym)) {
  284. case no:
  285. return 1;
  286. case mod:
  287. printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
  288. return 0;
  289. case yes:
  290. break;
  291. }
  292. }
  293. while (1) {
  294. int cnt, def;
  295. printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
  296. def_sym = sym_get_choice_value(sym);
  297. cnt = def = 0;
  298. line[0] = 0;
  299. for (child = menu->list; child; child = child->next) {
  300. if (!menu_is_visible(child))
  301. continue;
  302. if (!child->sym) {
  303. printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
  304. continue;
  305. }
  306. cnt++;
  307. if (child->sym == def_sym) {
  308. def = cnt;
  309. printf("%*c", indent, '>');
  310. } else
  311. printf("%*c", indent, ' ');
  312. printf(" %d. %s", cnt, _(menu_get_prompt(child)));
  313. if (child->sym->name)
  314. printf(" (%s)", child->sym->name);
  315. if (!sym_has_value(child->sym))
  316. printf(_(" (NEW)"));
  317. printf("\n");
  318. }
  319. printf(_("%*schoice"), indent - 1, "");
  320. if (cnt == 1) {
  321. printf("[1]: 1\n");
  322. goto conf_childs;
  323. }
  324. printf("[1-%d", cnt);
  325. if (menu_has_help(menu))
  326. printf("?");
  327. printf("]: ");
  328. switch (input_mode) {
  329. case ask_new:
  330. case ask_silent:
  331. if (!is_new) {
  332. cnt = def;
  333. printf("%d\n", cnt);
  334. break;
  335. }
  336. check_stdin();
  337. case ask_all:
  338. fflush(stdout);
  339. fgets(line, 128, stdin);
  340. strip(line);
  341. if (line[0] == '?') {
  342. printf("\n%s\n", get_help(menu));
  343. continue;
  344. }
  345. if (!line[0])
  346. cnt = def;
  347. else if (isdigit(line[0]))
  348. cnt = atoi(line);
  349. else
  350. continue;
  351. break;
  352. case set_random:
  353. if (is_new)
  354. def = (rand() % cnt) + 1;
  355. case set_default:
  356. case set_yes:
  357. case set_mod:
  358. case set_no:
  359. cnt = def;
  360. printf("%d\n", cnt);
  361. break;
  362. }
  363. conf_childs:
  364. for (child = menu->list; child; child = child->next) {
  365. if (!child->sym || !menu_is_visible(child))
  366. continue;
  367. if (!--cnt)
  368. break;
  369. }
  370. if (!child)
  371. continue;
  372. if (line[strlen(line) - 1] == '?') {
  373. printf("\n%s\n", get_help(child));
  374. continue;
  375. }
  376. sym_set_choice_value(sym, child->sym);
  377. for (child = child->list; child; child = child->next) {
  378. indent += 2;
  379. conf(child);
  380. indent -= 2;
  381. }
  382. return 1;
  383. }
  384. }
  385. static void conf(struct menu *menu)
  386. {
  387. struct symbol *sym;
  388. struct property *prop;
  389. struct menu *child;
  390. if (!menu_is_visible(menu))
  391. return;
  392. sym = menu->sym;
  393. prop = menu->prompt;
  394. if (prop) {
  395. const char *prompt;
  396. switch (prop->type) {
  397. case P_MENU:
  398. if (input_mode == ask_silent && rootEntry != menu) {
  399. check_conf(menu);
  400. return;
  401. }
  402. case P_COMMENT:
  403. prompt = menu_get_prompt(menu);
  404. if (prompt)
  405. printf("%*c\n%*c %s\n%*c\n",
  406. indent, '*',
  407. indent, '*', _(prompt),
  408. indent, '*');
  409. default:
  410. ;
  411. }
  412. }
  413. if (!sym)
  414. goto conf_childs;
  415. if (sym_is_choice(sym)) {
  416. conf_choice(menu);
  417. if (sym->curr.tri != mod)
  418. return;
  419. goto conf_childs;
  420. }
  421. switch (sym->type) {
  422. case S_INT:
  423. case S_HEX:
  424. case S_STRING:
  425. conf_string(menu);
  426. break;
  427. default:
  428. conf_sym(menu);
  429. break;
  430. }
  431. conf_childs:
  432. if (sym)
  433. indent += 2;
  434. for (child = menu->list; child; child = child->next)
  435. conf(child);
  436. if (sym)
  437. indent -= 2;
  438. }
  439. static void check_conf(struct menu *menu)
  440. {
  441. struct symbol *sym;
  442. struct menu *child;
  443. if (!menu_is_visible(menu))
  444. return;
  445. sym = menu->sym;
  446. if (sym && !sym_has_value(sym)) {
  447. if (sym_is_changable(sym) ||
  448. (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
  449. if (!conf_cnt++)
  450. printf(_("*\n* Restart config...\n*\n"));
  451. rootEntry = menu_get_parent_menu(menu);
  452. conf(rootEntry);
  453. }
  454. }
  455. for (child = menu->list; child; child = child->next)
  456. check_conf(child);
  457. }
  458. int main(int ac, char **av)
  459. {
  460. int opt;
  461. const char *name;
  462. struct stat tmpstat;
  463. setlocale(LC_ALL, "");
  464. bindtextdomain(PACKAGE, LOCALEDIR);
  465. textdomain(PACKAGE);
  466. while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
  467. switch (opt) {
  468. case 'o':
  469. input_mode = ask_new;
  470. break;
  471. case 's':
  472. input_mode = ask_silent;
  473. valid_stdin = isatty(0) && isatty(1) && isatty(2);
  474. break;
  475. case 'd':
  476. input_mode = set_default;
  477. break;
  478. case 'D':
  479. input_mode = set_default;
  480. defconfig_file = optarg;
  481. break;
  482. case 'n':
  483. input_mode = set_no;
  484. break;
  485. case 'm':
  486. input_mode = set_mod;
  487. break;
  488. case 'y':
  489. input_mode = set_yes;
  490. break;
  491. case 'r':
  492. input_mode = set_random;
  493. srand(time(NULL));
  494. break;
  495. case 'h':
  496. printf(_("See README for usage info\n"));
  497. exit(0);
  498. break;
  499. default:
  500. fprintf(stderr, _("See README for usage info\n"));
  501. exit(1);
  502. }
  503. }
  504. if (ac == optind) {
  505. printf(_("%s: Kconfig file missing\n"), av[0]);
  506. exit(1);
  507. }
  508. name = av[optind];
  509. conf_parse(name);
  510. //zconfdump(stdout);
  511. switch (input_mode) {
  512. case set_default:
  513. if (!defconfig_file)
  514. defconfig_file = conf_get_default_confname();
  515. if (conf_read(defconfig_file)) {
  516. printf(_("***\n"
  517. "*** Can't find default configuration \"%s\"!\n"
  518. "***\n"), defconfig_file);
  519. exit(1);
  520. }
  521. break;
  522. case ask_silent:
  523. if (stat(".config", &tmpstat)) {
  524. printf(_("***\n"
  525. "*** You have not yet configured!\n"
  526. "*** (missing .config file)\n"
  527. "***\n"
  528. "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
  529. "*** \"make menuconfig\" or \"make xconfig\").\n"
  530. "***\n"));
  531. exit(1);
  532. }
  533. case ask_all:
  534. case ask_new:
  535. conf_read(NULL);
  536. break;
  537. case set_no:
  538. case set_mod:
  539. case set_yes:
  540. case set_random:
  541. name = getenv("KCONFIG_ALLCONFIG");
  542. if (name && !stat(name, &tmpstat)) {
  543. conf_read_simple(name, S_DEF_USER);
  544. break;
  545. }
  546. switch (input_mode) {
  547. case set_no: name = "allno.config"; break;
  548. case set_mod: name = "allmod.config"; break;
  549. case set_yes: name = "allyes.config"; break;
  550. case set_random: name = "allrandom.config"; break;
  551. default: break;
  552. }
  553. if (!stat(name, &tmpstat))
  554. conf_read_simple(name, S_DEF_USER);
  555. else if (!stat("all.config", &tmpstat))
  556. conf_read_simple("all.config", S_DEF_USER);
  557. break;
  558. default:
  559. break;
  560. }
  561. if (input_mode != ask_silent) {
  562. rootEntry = &rootmenu;
  563. conf(&rootmenu);
  564. if (input_mode == ask_all) {
  565. input_mode = ask_silent;
  566. valid_stdin = 1;
  567. }
  568. } else if (conf_get_changed()) {
  569. name = getenv("KCONFIG_NOSILENTUPDATE");
  570. if (name && *name) {
  571. fprintf(stderr, _("\n*** configuration requires explicit update.\n\n"));
  572. return 1;
  573. }
  574. } else
  575. goto skip_check;
  576. do {
  577. conf_cnt = 0;
  578. check_conf(&rootmenu);
  579. } while (conf_cnt);
  580. if (conf_write(NULL)) {
  581. fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
  582. return 1;
  583. }
  584. skip_check:
  585. if (/*input_mode == ask_silent &&*/ conf_write_autoconf()) {
  586. fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
  587. return 1;
  588. }
  589. return 0;
  590. }