blob: 26156cb38ba044bd0e86ee29191ddb93b8fec0fb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
EGRY Gabor534a4502008-01-11 23:44:39 +01006#include <locale.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07007#include <ctype.h>
Markus Mayer74dba802015-12-09 14:56:12 -08008#include <limits.h>
Randy Dunlap9dfb5632006-04-18 22:21:53 -07009#include <stdio.h>
Ladislav Michl75ff4302008-01-09 16:36:19 +010010#include <stdlib.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <string.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <time.h>
Ladislav Michl75ff4302008-01-09 16:36:19 +010013#include <unistd.h>
Sam Ravnborg4062f1a2010-07-31 23:35:26 +020014#include <getopt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <sys/stat.h>
Ingo Molnarb0fe5512009-03-12 15:15:31 +010016#include <sys/time.h>
Yann E. MORIN0d8024c2013-04-13 22:49:13 +020017#include <errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include "lkc.h"
20
21static void conf(struct menu *menu);
22static void check_conf(struct menu *menu);
Arnaud Lacombeab63f582011-07-02 00:59:41 -040023static void xfgets(char *str, int size, FILE *in);
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
Sam Ravnborg4062f1a2010-07-31 23:35:26 +020025enum input_mode {
26 oldaskconfig,
27 silentoldconfig,
28 oldconfig,
29 allnoconfig,
30 allyesconfig,
31 allmodconfig,
Sam Ravnborg0748cb32010-07-31 23:35:31 +020032 alldefconfig,
Sam Ravnborg4062f1a2010-07-31 23:35:26 +020033 randconfig,
34 defconfig,
Sam Ravnborg7cf3d732010-07-31 23:35:34 +020035 savedefconfig,
Sam Ravnborg861b4ea2010-07-31 23:35:28 +020036 listnewconfig,
Adam Leefb16d892012-09-01 01:05:17 +080037 olddefconfig,
Masahiro Yamada52e58a32018-01-11 22:39:39 +090038};
39static enum input_mode input_mode = oldaskconfig;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +020040
Linus Torvalds1da177e2005-04-16 15:20:36 -070041static int indent = 1;
Ben Hutchings62dc9892013-02-19 02:24:26 +020042static int tty_stdio;
Linus Torvalds1da177e2005-04-16 15:20:36 -070043static int valid_stdin = 1;
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +020044static int sync_kconfig;
Linus Torvalds1da177e2005-04-16 15:20:36 -070045static int conf_cnt;
Markus Mayer74dba802015-12-09 14:56:12 -080046static char line[PATH_MAX];
Linus Torvalds1da177e2005-04-16 15:20:36 -070047static struct menu *rootEntry;
48
Cheng Renquan66c4bd82009-07-12 16:11:48 +080049static void print_help(struct menu *menu)
Sam Ravnborg03d29122007-07-21 00:00:36 +020050{
Cheng Renquan66c4bd82009-07-12 16:11:48 +080051 struct gstr help = str_new();
52
53 menu_get_ext_help(menu, &help);
54
55 printf("\n%s\n", str_get(&help));
56 str_free(&help);
Sam Ravnborg03d29122007-07-21 00:00:36 +020057}
58
J.A. Magallon48b9d032005-06-25 14:59:22 -070059static void strip(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060{
J.A. Magallon48b9d032005-06-25 14:59:22 -070061 char *p = str;
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 int l;
63
64 while ((isspace(*p)))
65 p++;
66 l = strlen(p);
67 if (p != str)
68 memmove(str, p, l + 1);
69 if (!l)
70 return;
71 p = str + l - 1;
72 while ((isspace(*p)))
73 *p-- = 0;
74}
75
76static void check_stdin(void)
77{
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +020078 if (!valid_stdin) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -070079 printf(_("aborted!\n\n"));
80 printf(_("Console input/output is redirected. "));
81 printf(_("Run 'make oldconfig' to update configuration.\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 exit(1);
83 }
84}
85
Roman Zippelf82f3f92007-08-30 05:06:17 +020086static int conf_askvalue(struct symbol *sym, const char *def)
Linus Torvalds1da177e2005-04-16 15:20:36 -070087{
88 enum symbol_type type = sym_get_type(sym);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
90 if (!sym_has_value(sym))
EGRY Gabor534a4502008-01-11 23:44:39 +010091 printf(_("(NEW) "));
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
93 line[0] = '\n';
94 line[1] = 0;
95
96 if (!sym_is_changable(sym)) {
97 printf("%s\n", def);
98 line[0] = '\n';
99 line[1] = 0;
Roman Zippelf82f3f92007-08-30 05:06:17 +0200100 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 }
102
103 switch (input_mode) {
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200104 case oldconfig:
105 case silentoldconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 if (sym_has_value(sym)) {
107 printf("%s\n", def);
Roman Zippelf82f3f92007-08-30 05:06:17 +0200108 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 }
110 check_stdin();
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400111 /* fall through */
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200112 case oldaskconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 fflush(stdout);
Markus Mayer74dba802015-12-09 14:56:12 -0800114 xfgets(line, sizeof(line), stdin);
Ben Hutchings62dc9892013-02-19 02:24:26 +0200115 if (!tty_stdio)
116 printf("\n");
Roman Zippelf82f3f92007-08-30 05:06:17 +0200117 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 default:
119 break;
120 }
121
122 switch (type) {
123 case S_INT:
124 case S_HEX:
125 case S_STRING:
126 printf("%s\n", def);
Roman Zippelf82f3f92007-08-30 05:06:17 +0200127 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 default:
129 ;
130 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 printf("%s", line);
Roman Zippelf82f3f92007-08-30 05:06:17 +0200132 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133}
134
Trevor Keith4356f482009-09-18 12:49:23 -0700135static int conf_string(struct menu *menu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
137 struct symbol *sym = menu->sym;
Sam Ravnborg03d29122007-07-21 00:00:36 +0200138 const char *def;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140 while (1) {
EGRY Gabor534a4502008-01-11 23:44:39 +0100141 printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 printf("(%s) ", sym->name);
143 def = sym_get_string_value(sym);
144 if (sym_get_string_value(sym))
145 printf("[%s] ", def);
Roman Zippelf82f3f92007-08-30 05:06:17 +0200146 if (!conf_askvalue(sym, def))
147 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 switch (line[0]) {
149 case '\n':
150 break;
151 case '?':
152 /* print help */
153 if (line[1] == '\n') {
Cheng Renquan66c4bd82009-07-12 16:11:48 +0800154 print_help(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 def = NULL;
156 break;
157 }
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400158 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 default:
160 line[strlen(line)-1] = 0;
161 def = line;
162 }
163 if (def && sym_set_string_value(sym, def))
164 return 0;
165 }
166}
167
168static int conf_sym(struct menu *menu)
169{
170 struct symbol *sym = menu->sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 tristate oldval, newval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
173 while (1) {
EGRY Gabor534a4502008-01-11 23:44:39 +0100174 printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 if (sym->name)
176 printf("(%s) ", sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 putchar('[');
178 oldval = sym_get_tristate_value(sym);
179 switch (oldval) {
180 case no:
181 putchar('N');
182 break;
183 case mod:
184 putchar('M');
185 break;
186 case yes:
187 putchar('Y');
188 break;
189 }
190 if (oldval != no && sym_tristate_within_range(sym, no))
191 printf("/n");
192 if (oldval != mod && sym_tristate_within_range(sym, mod))
193 printf("/m");
194 if (oldval != yes && sym_tristate_within_range(sym, yes))
195 printf("/y");
Sam Ravnborg03d29122007-07-21 00:00:36 +0200196 if (menu_has_help(menu))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 printf("/?");
198 printf("] ");
Roman Zippelf82f3f92007-08-30 05:06:17 +0200199 if (!conf_askvalue(sym, sym_get_string_value(sym)))
200 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 strip(line);
202
203 switch (line[0]) {
204 case 'n':
205 case 'N':
206 newval = no;
207 if (!line[1] || !strcmp(&line[1], "o"))
208 break;
209 continue;
210 case 'm':
211 case 'M':
212 newval = mod;
213 if (!line[1])
214 break;
215 continue;
216 case 'y':
217 case 'Y':
218 newval = yes;
219 if (!line[1] || !strcmp(&line[1], "es"))
220 break;
221 continue;
222 case 0:
223 newval = oldval;
224 break;
225 case '?':
226 goto help;
227 default:
228 continue;
229 }
230 if (sym_set_tristate_value(sym, newval))
231 return 0;
232help:
Cheng Renquan66c4bd82009-07-12 16:11:48 +0800233 print_help(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 }
235}
236
237static int conf_choice(struct menu *menu)
238{
239 struct symbol *sym, *def_sym;
240 struct menu *child;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 bool is_new;
242
243 sym = menu->sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 is_new = !sym_has_value(sym);
245 if (sym_is_changable(sym)) {
246 conf_sym(menu);
247 sym_calc_value(sym);
248 switch (sym_get_tristate_value(sym)) {
249 case no:
250 return 1;
251 case mod:
252 return 0;
253 case yes:
254 break;
255 }
256 } else {
257 switch (sym_get_tristate_value(sym)) {
258 case no:
259 return 1;
260 case mod:
EGRY Gabor534a4502008-01-11 23:44:39 +0100261 printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 return 0;
263 case yes:
264 break;
265 }
266 }
267
268 while (1) {
269 int cnt, def;
270
EGRY Gabor534a4502008-01-11 23:44:39 +0100271 printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 def_sym = sym_get_choice_value(sym);
273 cnt = def = 0;
Roman Zippel40aee722006-04-09 17:26:39 +0200274 line[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 for (child = menu->list; child; child = child->next) {
276 if (!menu_is_visible(child))
277 continue;
278 if (!child->sym) {
EGRY Gabor534a4502008-01-11 23:44:39 +0100279 printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 continue;
281 }
282 cnt++;
283 if (child->sym == def_sym) {
284 def = cnt;
285 printf("%*c", indent, '>');
286 } else
287 printf("%*c", indent, ' ');
EGRY Gabor534a4502008-01-11 23:44:39 +0100288 printf(" %d. %s", cnt, _(menu_get_prompt(child)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 if (child->sym->name)
290 printf(" (%s)", child->sym->name);
291 if (!sym_has_value(child->sym))
EGRY Gabor534a4502008-01-11 23:44:39 +0100292 printf(_(" (NEW)"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 printf("\n");
294 }
EGRY Gabor534a4502008-01-11 23:44:39 +0100295 printf(_("%*schoice"), indent - 1, "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 if (cnt == 1) {
297 printf("[1]: 1\n");
298 goto conf_childs;
299 }
300 printf("[1-%d", cnt);
Sam Ravnborg03d29122007-07-21 00:00:36 +0200301 if (menu_has_help(menu))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 printf("?");
303 printf("]: ");
304 switch (input_mode) {
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200305 case oldconfig:
306 case silentoldconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 if (!is_new) {
308 cnt = def;
309 printf("%d\n", cnt);
310 break;
311 }
312 check_stdin();
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400313 /* fall through */
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200314 case oldaskconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 fflush(stdout);
Markus Mayer74dba802015-12-09 14:56:12 -0800316 xfgets(line, sizeof(line), stdin);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 strip(line);
318 if (line[0] == '?') {
Cheng Renquan66c4bd82009-07-12 16:11:48 +0800319 print_help(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 continue;
321 }
322 if (!line[0])
323 cnt = def;
324 else if (isdigit(line[0]))
325 cnt = atoi(line);
326 else
327 continue;
328 break;
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200329 default:
330 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 }
332
333 conf_childs:
334 for (child = menu->list; child; child = child->next) {
335 if (!child->sym || !menu_is_visible(child))
336 continue;
337 if (!--cnt)
338 break;
339 }
340 if (!child)
341 continue;
Ben Hutchings3ba41622011-04-23 18:42:56 +0100342 if (line[0] && line[strlen(line) - 1] == '?') {
Cheng Renquan66c4bd82009-07-12 16:11:48 +0800343 print_help(child);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 continue;
345 }
346 sym_set_choice_value(sym, child->sym);
Jan Beulichf5eaa322008-01-24 11:54:23 +0000347 for (child = child->list; child; child = child->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 indent += 2;
Jan Beulichf5eaa322008-01-24 11:54:23 +0000349 conf(child);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 indent -= 2;
351 }
352 return 1;
353 }
354}
355
356static void conf(struct menu *menu)
357{
358 struct symbol *sym;
359 struct property *prop;
360 struct menu *child;
361
362 if (!menu_is_visible(menu))
363 return;
364
365 sym = menu->sym;
366 prop = menu->prompt;
367 if (prop) {
368 const char *prompt;
369
370 switch (prop->type) {
371 case P_MENU:
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200372 if ((input_mode == silentoldconfig ||
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200373 input_mode == listnewconfig ||
Adam Leefb16d892012-09-01 01:05:17 +0800374 input_mode == olddefconfig) &&
Aristeu Rozanskif0778c82010-05-06 12:48:34 -0400375 rootEntry != menu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 check_conf(menu);
377 return;
378 }
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400379 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 case P_COMMENT:
381 prompt = menu_get_prompt(menu);
382 if (prompt)
383 printf("%*c\n%*c %s\n%*c\n",
384 indent, '*',
EGRY Gabor534a4502008-01-11 23:44:39 +0100385 indent, '*', _(prompt),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 indent, '*');
387 default:
388 ;
389 }
390 }
391
392 if (!sym)
393 goto conf_childs;
394
395 if (sym_is_choice(sym)) {
396 conf_choice(menu);
397 if (sym->curr.tri != mod)
398 return;
399 goto conf_childs;
400 }
401
402 switch (sym->type) {
403 case S_INT:
404 case S_HEX:
405 case S_STRING:
406 conf_string(menu);
407 break;
408 default:
409 conf_sym(menu);
410 break;
411 }
412
413conf_childs:
414 if (sym)
415 indent += 2;
416 for (child = menu->list; child; child = child->next)
417 conf(child);
418 if (sym)
419 indent -= 2;
420}
421
422static void check_conf(struct menu *menu)
423{
424 struct symbol *sym;
425 struct menu *child;
426
427 if (!menu_is_visible(menu))
428 return;
429
430 sym = menu->sym;
Roman Zippel3f23ca22005-11-08 21:34:48 -0800431 if (sym && !sym_has_value(sym)) {
432 if (sym_is_changable(sym) ||
433 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200434 if (input_mode == listnewconfig) {
435 if (sym->name && !sym_is_choice_value(sym)) {
Arnaud Lacombeffb59572010-08-14 23:57:43 -0400436 printf("%s%s\n", CONFIG_, sym->name);
Aristeu Rozanskif0778c82010-05-06 12:48:34 -0400437 }
Adam Leefb16d892012-09-01 01:05:17 +0800438 } else if (input_mode != olddefconfig) {
Aristeu Rozanskif0778c82010-05-06 12:48:34 -0400439 if (!conf_cnt++)
440 printf(_("*\n* Restart config...\n*\n"));
441 rootEntry = menu_get_parent_menu(menu);
442 conf(rootEntry);
443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 }
446
447 for (child = menu->list; child; child = child->next)
448 check_conf(child);
449}
450
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200451static struct option long_opts[] = {
452 {"oldaskconfig", no_argument, NULL, oldaskconfig},
453 {"oldconfig", no_argument, NULL, oldconfig},
454 {"silentoldconfig", no_argument, NULL, silentoldconfig},
455 {"defconfig", optional_argument, NULL, defconfig},
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200456 {"savedefconfig", required_argument, NULL, savedefconfig},
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200457 {"allnoconfig", no_argument, NULL, allnoconfig},
458 {"allyesconfig", no_argument, NULL, allyesconfig},
459 {"allmodconfig", no_argument, NULL, allmodconfig},
Sam Ravnborg0748cb32010-07-31 23:35:31 +0200460 {"alldefconfig", no_argument, NULL, alldefconfig},
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200461 {"randconfig", no_argument, NULL, randconfig},
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200462 {"listnewconfig", no_argument, NULL, listnewconfig},
Adam Leefb16d892012-09-01 01:05:17 +0800463 {"olddefconfig", no_argument, NULL, olddefconfig},
464 /*
465 * oldnoconfig is an alias of olddefconfig, because people already
466 * are dependent on its behavior(sets new symbols to their default
467 * value but not 'n') with the counter-intuitive name.
468 */
469 {"oldnoconfig", no_argument, NULL, olddefconfig},
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200470 {NULL, 0, NULL, 0}
471};
472
Arnaud Lacombe32543992010-11-02 00:26:33 -0400473static void conf_usage(const char *progname)
474{
475
Michal Marek0a1f00a2015-04-08 13:30:42 +0200476 printf("Usage: %s [-s] [option] <kconfig-file>\n", progname);
Arnaud Lacombe32543992010-11-02 00:26:33 -0400477 printf("[option] is _one_ of the following:\n");
478 printf(" --listnewconfig List new options\n");
479 printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
480 printf(" --oldconfig Update a configuration using a provided .config as base\n");
481 printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n");
Adam Leefb16d892012-09-01 01:05:17 +0800482 printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n");
483 printf(" --oldnoconfig An alias of olddefconfig\n");
Arnaud Lacombe32543992010-11-02 00:26:33 -0400484 printf(" --defconfig <file> New config with default defined in <file>\n");
485 printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
486 printf(" --allnoconfig New config where all options are answered with no\n");
487 printf(" --allyesconfig New config where all options are answered with yes\n");
488 printf(" --allmodconfig New config where all options are answered with mod\n");
489 printf(" --alldefconfig New config with all symbols set to default\n");
490 printf(" --randconfig New config with random answer to all options\n");
491}
492
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493int main(int ac, char **av)
494{
Arnaud Lacombe32543992010-11-02 00:26:33 -0400495 const char *progname = av[0];
Andres Salomon2f4b4892007-12-17 01:34:58 -0500496 int opt;
Arnaud Lacombe275744c2010-10-13 20:43:28 -0400497 const char *name, *defconfig_file = NULL /* gcc uninit */;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 struct stat tmpstat;
499
EGRY Gabor534a4502008-01-11 23:44:39 +0100500 setlocale(LC_ALL, "");
501 bindtextdomain(PACKAGE, LOCALEDIR);
502 textdomain(PACKAGE);
503
Ben Hutchings62dc9892013-02-19 02:24:26 +0200504 tty_stdio = isatty(0) && isatty(1) && isatty(2);
505
Michal Marek0a1f00a2015-04-08 13:30:42 +0200506 while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
507 if (opt == 's') {
508 conf_set_message_callback(NULL);
509 continue;
510 }
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200511 input_mode = (enum input_mode)opt;
Andres Salomon2f4b4892007-12-17 01:34:58 -0500512 switch (opt) {
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200513 case silentoldconfig:
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200514 sync_kconfig = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200516 case defconfig:
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200517 case savedefconfig:
Andres Salomon2f4b4892007-12-17 01:34:58 -0500518 defconfig_file = optarg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200520 case randconfig:
Ingo Molnarb0fe5512009-03-12 15:15:31 +0100521 {
522 struct timeval now;
523 unsigned int seed;
Yann E. MORIN0d8024c2013-04-13 22:49:13 +0200524 char *seed_env;
Ingo Molnarb0fe5512009-03-12 15:15:31 +0100525
526 /*
527 * Use microseconds derived seed,
528 * compensate for systems where it may be zero
529 */
530 gettimeofday(&now, NULL);
Ingo Molnarb0fe5512009-03-12 15:15:31 +0100531 seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
Yann E. MORIN0d8024c2013-04-13 22:49:13 +0200532
533 seed_env = getenv("KCONFIG_SEED");
534 if( seed_env && *seed_env ) {
535 char *endp;
Yann E. MORINe85ac122013-05-20 23:17:34 +0200536 int tmp = (int)strtol(seed_env, &endp, 0);
Yann E. MORIN0d8024c2013-04-13 22:49:13 +0200537 if (*endp == '\0') {
538 seed = tmp;
539 }
540 }
Yann E. MORINa5f6d792013-05-20 23:09:03 +0200541 fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
Ingo Molnarb0fe5512009-03-12 15:15:31 +0100542 srand(seed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 break;
Ingo Molnarb0fe5512009-03-12 15:15:31 +0100544 }
Arnaud Lacombe32543992010-11-02 00:26:33 -0400545 case oldaskconfig:
546 case oldconfig:
547 case allnoconfig:
548 case allyesconfig:
549 case allmodconfig:
550 case alldefconfig:
551 case listnewconfig:
Adam Leefb16d892012-09-01 01:05:17 +0800552 case olddefconfig:
Arnaud Lacombe32543992010-11-02 00:26:33 -0400553 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200554 case '?':
Arnaud Lacombe32543992010-11-02 00:26:33 -0400555 conf_usage(progname);
Andres Salomon2f4b4892007-12-17 01:34:58 -0500556 exit(1);
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200557 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 }
559 }
Andres Salomon2f4b4892007-12-17 01:34:58 -0500560 if (ac == optind) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700561 printf(_("%s: Kconfig file missing\n"), av[0]);
Arnaud Lacombe32543992010-11-02 00:26:33 -0400562 conf_usage(progname);
Randy Dunlap250725a2006-06-08 22:12:50 -0700563 exit(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 }
Andres Salomon2f4b4892007-12-17 01:34:58 -0500565 name = av[optind];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 conf_parse(name);
567 //zconfdump(stdout);
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200568 if (sync_kconfig) {
Markus Heidelberg284026c2009-05-18 01:36:53 +0200569 name = conf_get_configname();
570 if (stat(name, &tmpstat)) {
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200571 fprintf(stderr, _("***\n"
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400572 "*** Configuration file \"%s\" not found!\n"
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200573 "***\n"
574 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
575 "*** \"make menuconfig\" or \"make xconfig\").\n"
Markus Heidelberg284026c2009-05-18 01:36:53 +0200576 "***\n"), name);
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200577 exit(1);
578 }
579 }
580
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 switch (input_mode) {
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200582 case defconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 if (!defconfig_file)
584 defconfig_file = conf_get_default_confname();
585 if (conf_read(defconfig_file)) {
EGRY Gabor534a4502008-01-11 23:44:39 +0100586 printf(_("***\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 "*** Can't find default configuration \"%s\"!\n"
EGRY Gabor534a4502008-01-11 23:44:39 +0100588 "***\n"), defconfig_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 exit(1);
590 }
591 break;
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200592 case savedefconfig:
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200593 case silentoldconfig:
594 case oldaskconfig:
595 case oldconfig:
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200596 case listnewconfig:
Adam Leefb16d892012-09-01 01:05:17 +0800597 case olddefconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 conf_read(NULL);
599 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200600 case allnoconfig:
601 case allyesconfig:
602 case allmodconfig:
Sam Ravnborg0748cb32010-07-31 23:35:31 +0200603 case alldefconfig:
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200604 case randconfig:
Roman Zippel90389162005-11-08 21:34:49 -0800605 name = getenv("KCONFIG_ALLCONFIG");
Eric W. Biederman9f420bf2012-05-07 05:37:45 -0700606 if (!name)
607 break;
608 if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
Eric W. Biederman5efe2412012-04-26 01:51:32 -0700609 if (conf_read_simple(name, S_DEF_USER)) {
610 fprintf(stderr,
611 _("*** Can't read seed configuration \"%s\"!\n"),
612 name);
613 exit(1);
614 }
Roman Zippel90389162005-11-08 21:34:49 -0800615 break;
616 }
617 switch (input_mode) {
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200618 case allnoconfig: name = "allno.config"; break;
619 case allyesconfig: name = "allyes.config"; break;
620 case allmodconfig: name = "allmod.config"; break;
Sam Ravnborg0748cb32010-07-31 23:35:31 +0200621 case alldefconfig: name = "alldef.config"; break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200622 case randconfig: name = "allrandom.config"; break;
Roman Zippel90389162005-11-08 21:34:49 -0800623 default: break;
624 }
Eric W. Biederman5efe2412012-04-26 01:51:32 -0700625 if (conf_read_simple(name, S_DEF_USER) &&
626 conf_read_simple("all.config", S_DEF_USER)) {
627 fprintf(stderr,
628 _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
629 name);
630 exit(1);
631 }
Roman Zippel90389162005-11-08 21:34:49 -0800632 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 default:
634 break;
635 }
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200636
637 if (sync_kconfig) {
638 if (conf_get_changed()) {
639 name = getenv("KCONFIG_NOSILENTUPDATE");
640 if (name && *name) {
641 fprintf(stderr,
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400642 _("\n*** The configuration requires explicit update.\n\n"));
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200643 return 1;
644 }
645 }
Ben Hutchings62dc9892013-02-19 02:24:26 +0200646 valid_stdin = tty_stdio;
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200647 }
648
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200649 switch (input_mode) {
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200650 case allnoconfig:
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200651 conf_set_all_new_symbols(def_no);
652 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200653 case allyesconfig:
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200654 conf_set_all_new_symbols(def_yes);
655 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200656 case allmodconfig:
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200657 conf_set_all_new_symbols(def_mod);
658 break;
Sam Ravnborg0748cb32010-07-31 23:35:31 +0200659 case alldefconfig:
660 conf_set_all_new_symbols(def_default);
661 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200662 case randconfig:
Yann E. MORIN3b9a19e2013-04-28 22:36:38 +0200663 /* Really nothing to do in this loop */
664 while (conf_set_all_new_symbols(def_random)) ;
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200665 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200666 case defconfig:
Sam Ravnborg09748e12008-06-30 23:02:59 +0200667 conf_set_all_new_symbols(def_default);
668 break;
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200669 case savedefconfig:
670 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200671 case oldaskconfig:
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200672 rootEntry = &rootmenu;
673 conf(&rootmenu);
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200674 input_mode = silentoldconfig;
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200675 /* fall through */
Sam Ravnborg14828342010-08-06 07:13:54 +0200676 case oldconfig:
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200677 case listnewconfig:
Adam Leefb16d892012-09-01 01:05:17 +0800678 case olddefconfig:
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200679 case silentoldconfig:
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200680 /* Update until a loop caused no more changes */
681 do {
682 conf_cnt = 0;
683 check_conf(&rootmenu);
Aristeu Rozanskif0778c82010-05-06 12:48:34 -0400684 } while (conf_cnt &&
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200685 (input_mode != listnewconfig &&
Adam Leefb16d892012-09-01 01:05:17 +0800686 input_mode != olddefconfig));
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200687 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 }
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200689
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200690 if (sync_kconfig) {
691 /* silentoldconfig is used during the build so we shall update autoconf.
692 * All other commands are only used to generate a config.
693 */
694 if (conf_get_changed() && conf_write(NULL)) {
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400695 fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200696 exit(1);
697 }
698 if (conf_write_autoconf()) {
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400699 fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200700 return 1;
701 }
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200702 } else if (input_mode == savedefconfig) {
703 if (conf_write_defconfig(defconfig_file)) {
704 fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
Masahiro Yamadabb66fc62014-06-10 19:08:13 +0900705 defconfig_file);
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200706 return 1;
707 }
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200708 } else if (input_mode != listnewconfig) {
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200709 if (conf_write(NULL)) {
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400710 fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200711 exit(1);
712 }
Roman Zippelc955cca2006-06-08 22:12:39 -0700713 }
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200714 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715}
Arnaud Lacombeab63f582011-07-02 00:59:41 -0400716
Jean Sacren4418a2b2010-08-04 16:03:16 -0600717/*
718 * Helper function to facilitate fgets() by Jean Sacren.
719 */
Arnaud Lacombeab63f582011-07-02 00:59:41 -0400720void xfgets(char *str, int size, FILE *in)
Jean Sacren4418a2b2010-08-04 16:03:16 -0600721{
722 if (fgets(str, size, in) == NULL)
723 fprintf(stderr, "\nError in reading or end of file.\n");
724}