blob: f6e548b8f79556a2a799358730459686bd002f2f [file] [log] [blame]
Masahiro Yamada0c874102018-12-18 21:13:35 +09001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 */
5
6#include <ctype.h>
Markus Mayer74dba802015-12-09 14:56:12 -08007#include <limits.h>
Randy Dunlap9dfb5632006-04-18 22:21:53 -07008#include <stdio.h>
Ladislav Michl75ff4302008-01-09 16:36:19 +01009#include <stdlib.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <string.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <time.h>
Ladislav Michl75ff4302008-01-09 16:36:19 +010012#include <unistd.h>
Sam Ravnborg4062f1a2010-07-31 23:35:26 +020013#include <getopt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <sys/stat.h>
Ingo Molnarb0fe5512009-03-12 15:15:31 +010015#include <sys/time.h>
Yann E. MORIN0d8024c2013-04-13 22:49:13 +020016#include <errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include "lkc.h"
19
20static void conf(struct menu *menu);
21static void check_conf(struct menu *menu);
22
Sam Ravnborg4062f1a2010-07-31 23:35:26 +020023enum input_mode {
24 oldaskconfig,
Masahiro Yamada911a91c2018-03-01 15:34:37 +090025 syncconfig,
Sam Ravnborg4062f1a2010-07-31 23:35:26 +020026 oldconfig,
27 allnoconfig,
28 allyesconfig,
29 allmodconfig,
Sam Ravnborg0748cb32010-07-31 23:35:31 +020030 alldefconfig,
Sam Ravnborg4062f1a2010-07-31 23:35:26 +020031 randconfig,
32 defconfig,
Sam Ravnborg7cf3d732010-07-31 23:35:34 +020033 savedefconfig,
Sam Ravnborg861b4ea2010-07-31 23:35:28 +020034 listnewconfig,
Laura Abbott5d8b42a2019-11-04 17:10:08 -050035 helpnewconfig,
Adam Leefb16d892012-09-01 01:05:17 +080036 olddefconfig,
Tetsuo Handa89b90602019-12-17 18:42:06 +090037 yes2modconfig,
38 mod2yesconfig,
Masahiro Yamada52e58a32018-01-11 22:39:39 +090039};
40static enum input_mode input_mode = oldaskconfig;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +020041
Linus Torvalds1da177e2005-04-16 15:20:36 -070042static int indent = 1;
Ben Hutchings62dc9892013-02-19 02:24:26 +020043static int tty_stdio;
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
Masahiro Yamada5a3dc712018-01-11 22:39:40 +090076/* Helper function to facilitate fgets() by Jean Sacren. */
77static void xfgets(char *str, int size, FILE *in)
78{
79 if (!fgets(str, size, in))
80 fprintf(stderr, "\nError in reading or end of file.\n");
Masahiro Yamadaf3ff6fb2018-02-08 14:56:40 +090081
82 if (!tty_stdio)
83 printf("%s", str);
Masahiro Yamada5a3dc712018-01-11 22:39:40 +090084}
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))
Sam Ravnborg694c49a2018-05-22 21:36:12 +020091 printf("(NEW) ");
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
93 line[0] = '\n';
94 line[1] = 0;
95
Marco Ammonbaa23ec2019-07-04 12:50:41 +020096 if (!sym_is_changeable(sym)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 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:
Masahiro Yamada911a91c2018-03-01 15:34:37 +0900105 case syncconfig:
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 }
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400110 /* fall through */
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200111 case oldaskconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 fflush(stdout);
Markus Mayer74dba802015-12-09 14:56:12 -0800113 xfgets(line, sizeof(line), stdin);
Roman Zippelf82f3f92007-08-30 05:06:17 +0200114 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 default:
116 break;
117 }
118
119 switch (type) {
120 case S_INT:
121 case S_HEX:
122 case S_STRING:
123 printf("%s\n", def);
Roman Zippelf82f3f92007-08-30 05:06:17 +0200124 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 default:
126 ;
127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 printf("%s", line);
Roman Zippelf82f3f92007-08-30 05:06:17 +0200129 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130}
131
Trevor Keith4356f482009-09-18 12:49:23 -0700132static int conf_string(struct menu *menu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133{
134 struct symbol *sym = menu->sym;
Sam Ravnborg03d29122007-07-21 00:00:36 +0200135 const char *def;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
137 while (1) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200138 printf("%*s%s ", indent - 1, "", menu->prompt->text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 printf("(%s) ", sym->name);
140 def = sym_get_string_value(sym);
141 if (sym_get_string_value(sym))
142 printf("[%s] ", def);
Roman Zippelf82f3f92007-08-30 05:06:17 +0200143 if (!conf_askvalue(sym, def))
144 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 switch (line[0]) {
146 case '\n':
147 break;
148 case '?':
149 /* print help */
150 if (line[1] == '\n') {
Cheng Renquan66c4bd82009-07-12 16:11:48 +0800151 print_help(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 def = NULL;
153 break;
154 }
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400155 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 default:
157 line[strlen(line)-1] = 0;
158 def = line;
159 }
160 if (def && sym_set_string_value(sym, def))
161 return 0;
162 }
163}
164
165static int conf_sym(struct menu *menu)
166{
167 struct symbol *sym = menu->sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 tristate oldval, newval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169
170 while (1) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200171 printf("%*s%s ", indent - 1, "", menu->prompt->text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 if (sym->name)
173 printf("(%s) ", sym->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 putchar('[');
175 oldval = sym_get_tristate_value(sym);
176 switch (oldval) {
177 case no:
178 putchar('N');
179 break;
180 case mod:
181 putchar('M');
182 break;
183 case yes:
184 putchar('Y');
185 break;
186 }
187 if (oldval != no && sym_tristate_within_range(sym, no))
188 printf("/n");
189 if (oldval != mod && sym_tristate_within_range(sym, mod))
190 printf("/m");
191 if (oldval != yes && sym_tristate_within_range(sym, yes))
192 printf("/y");
Masahiro Yamada4f208f32018-02-06 09:34:43 +0900193 printf("/?] ");
Roman Zippelf82f3f92007-08-30 05:06:17 +0200194 if (!conf_askvalue(sym, sym_get_string_value(sym)))
195 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 strip(line);
197
198 switch (line[0]) {
199 case 'n':
200 case 'N':
201 newval = no;
202 if (!line[1] || !strcmp(&line[1], "o"))
203 break;
204 continue;
205 case 'm':
206 case 'M':
207 newval = mod;
208 if (!line[1])
209 break;
210 continue;
211 case 'y':
212 case 'Y':
213 newval = yes;
214 if (!line[1] || !strcmp(&line[1], "es"))
215 break;
216 continue;
217 case 0:
218 newval = oldval;
219 break;
220 case '?':
221 goto help;
222 default:
223 continue;
224 }
225 if (sym_set_tristate_value(sym, newval))
226 return 0;
227help:
Cheng Renquan66c4bd82009-07-12 16:11:48 +0800228 print_help(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 }
230}
231
232static int conf_choice(struct menu *menu)
233{
234 struct symbol *sym, *def_sym;
235 struct menu *child;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 bool is_new;
237
238 sym = menu->sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 is_new = !sym_has_value(sym);
Marco Ammonbaa23ec2019-07-04 12:50:41 +0200240 if (sym_is_changeable(sym)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 conf_sym(menu);
242 sym_calc_value(sym);
243 switch (sym_get_tristate_value(sym)) {
244 case no:
245 return 1;
246 case mod:
247 return 0;
248 case yes:
249 break;
250 }
251 } else {
252 switch (sym_get_tristate_value(sym)) {
253 case no:
254 return 1;
255 case mod:
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200256 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 return 0;
258 case yes:
259 break;
260 }
261 }
262
263 while (1) {
264 int cnt, def;
265
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200266 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 def_sym = sym_get_choice_value(sym);
268 cnt = def = 0;
Roman Zippel40aee722006-04-09 17:26:39 +0200269 line[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 for (child = menu->list; child; child = child->next) {
271 if (!menu_is_visible(child))
272 continue;
273 if (!child->sym) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200274 printf("%*c %s\n", indent, '*', menu_get_prompt(child));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 continue;
276 }
277 cnt++;
278 if (child->sym == def_sym) {
279 def = cnt;
280 printf("%*c", indent, '>');
281 } else
282 printf("%*c", indent, ' ');
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200283 printf(" %d. %s", cnt, menu_get_prompt(child));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 if (child->sym->name)
285 printf(" (%s)", child->sym->name);
286 if (!sym_has_value(child->sym))
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200287 printf(" (NEW)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 printf("\n");
289 }
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200290 printf("%*schoice", indent - 1, "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 if (cnt == 1) {
292 printf("[1]: 1\n");
293 goto conf_childs;
294 }
Masahiro Yamada4f208f32018-02-06 09:34:43 +0900295 printf("[1-%d?]: ", cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 switch (input_mode) {
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200297 case oldconfig:
Masahiro Yamada911a91c2018-03-01 15:34:37 +0900298 case syncconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 if (!is_new) {
300 cnt = def;
301 printf("%d\n", cnt);
302 break;
303 }
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400304 /* fall through */
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200305 case oldaskconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 fflush(stdout);
Markus Mayer74dba802015-12-09 14:56:12 -0800307 xfgets(line, sizeof(line), stdin);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 strip(line);
309 if (line[0] == '?') {
Cheng Renquan66c4bd82009-07-12 16:11:48 +0800310 print_help(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 continue;
312 }
313 if (!line[0])
314 cnt = def;
315 else if (isdigit(line[0]))
316 cnt = atoi(line);
317 else
318 continue;
319 break;
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200320 default:
321 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 }
323
324 conf_childs:
325 for (child = menu->list; child; child = child->next) {
326 if (!child->sym || !menu_is_visible(child))
327 continue;
328 if (!--cnt)
329 break;
330 }
331 if (!child)
332 continue;
Ben Hutchings3ba41622011-04-23 18:42:56 +0100333 if (line[0] && line[strlen(line) - 1] == '?') {
Cheng Renquan66c4bd82009-07-12 16:11:48 +0800334 print_help(child);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 continue;
336 }
337 sym_set_choice_value(sym, child->sym);
Jan Beulichf5eaa322008-01-24 11:54:23 +0000338 for (child = child->list; child; child = child->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 indent += 2;
Jan Beulichf5eaa322008-01-24 11:54:23 +0000340 conf(child);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 indent -= 2;
342 }
343 return 1;
344 }
345}
346
347static void conf(struct menu *menu)
348{
349 struct symbol *sym;
350 struct property *prop;
351 struct menu *child;
352
353 if (!menu_is_visible(menu))
354 return;
355
356 sym = menu->sym;
357 prop = menu->prompt;
358 if (prop) {
359 const char *prompt;
360
361 switch (prop->type) {
362 case P_MENU:
Masahiro Yamada2aad9b82018-02-28 09:15:24 +0900363 /*
364 * Except in oldaskconfig mode, we show only menus that
365 * contain new symbols.
366 */
367 if (input_mode != oldaskconfig && rootEntry != menu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 check_conf(menu);
369 return;
370 }
Arnaud Lacombed8fc3202011-05-31 12:30:26 -0400371 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 case P_COMMENT:
373 prompt = menu_get_prompt(menu);
374 if (prompt)
375 printf("%*c\n%*c %s\n%*c\n",
376 indent, '*',
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200377 indent, '*', prompt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 indent, '*');
379 default:
380 ;
381 }
382 }
383
384 if (!sym)
385 goto conf_childs;
386
387 if (sym_is_choice(sym)) {
388 conf_choice(menu);
389 if (sym->curr.tri != mod)
390 return;
391 goto conf_childs;
392 }
393
394 switch (sym->type) {
395 case S_INT:
396 case S_HEX:
397 case S_STRING:
398 conf_string(menu);
399 break;
400 default:
401 conf_sym(menu);
402 break;
403 }
404
405conf_childs:
406 if (sym)
407 indent += 2;
408 for (child = menu->list; child; child = child->next)
409 conf(child);
410 if (sym)
411 indent -= 2;
412}
413
414static void check_conf(struct menu *menu)
415{
416 struct symbol *sym;
417 struct menu *child;
418
419 if (!menu_is_visible(menu))
420 return;
421
422 sym = menu->sym;
Roman Zippel3f23ca22005-11-08 21:34:48 -0800423 if (sym && !sym_has_value(sym)) {
Marco Ammonbaa23ec2019-07-04 12:50:41 +0200424 if (sym_is_changeable(sym) ||
Roman Zippel3f23ca22005-11-08 21:34:48 -0800425 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200426 if (input_mode == listnewconfig) {
Don Zickus17baab62018-04-11 15:15:37 -0400427 if (sym->name) {
428 const char *str;
429
430 if (sym->type == S_STRING) {
431 str = sym_get_string_value(sym);
432 str = sym_escape_string_value(str);
433 printf("%s%s=%s\n", CONFIG_, sym->name, str);
434 free((void *)str);
435 } else {
436 str = sym_get_string_value(sym);
437 printf("%s%s=%s\n", CONFIG_, sym->name, str);
438 }
Aristeu Rozanskif0778c82010-05-06 12:48:34 -0400439 }
Laura Abbott5d8b42a2019-11-04 17:10:08 -0500440 } else if (input_mode == helpnewconfig) {
441 printf("-----\n");
442 print_help(menu);
443 printf("-----\n");
444
Masahiro Yamada59a80b52018-02-28 09:15:21 +0900445 } else {
Aristeu Rozanskif0778c82010-05-06 12:48:34 -0400446 if (!conf_cnt++)
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200447 printf("*\n* Restart config...\n*\n");
Aristeu Rozanskif0778c82010-05-06 12:48:34 -0400448 rootEntry = menu_get_parent_menu(menu);
449 conf(rootEntry);
450 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 }
453
454 for (child = menu->list; child; child = child->next)
455 check_conf(child);
456}
457
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200458static struct option long_opts[] = {
459 {"oldaskconfig", no_argument, NULL, oldaskconfig},
460 {"oldconfig", no_argument, NULL, oldconfig},
Masahiro Yamada911a91c2018-03-01 15:34:37 +0900461 {"syncconfig", no_argument, NULL, syncconfig},
Masahiro Yamadab6f7e9f2019-05-27 23:37:22 +0900462 {"defconfig", required_argument, NULL, defconfig},
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200463 {"savedefconfig", required_argument, NULL, savedefconfig},
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200464 {"allnoconfig", no_argument, NULL, allnoconfig},
465 {"allyesconfig", no_argument, NULL, allyesconfig},
466 {"allmodconfig", no_argument, NULL, allmodconfig},
Sam Ravnborg0748cb32010-07-31 23:35:31 +0200467 {"alldefconfig", no_argument, NULL, alldefconfig},
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200468 {"randconfig", no_argument, NULL, randconfig},
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200469 {"listnewconfig", no_argument, NULL, listnewconfig},
Laura Abbott5d8b42a2019-11-04 17:10:08 -0500470 {"helpnewconfig", no_argument, NULL, helpnewconfig},
Adam Leefb16d892012-09-01 01:05:17 +0800471 {"olddefconfig", no_argument, NULL, olddefconfig},
Tetsuo Handa89b90602019-12-17 18:42:06 +0900472 {"yes2modconfig", no_argument, NULL, yes2modconfig},
473 {"mod2yesconfig", no_argument, NULL, mod2yesconfig},
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200474 {NULL, 0, NULL, 0}
475};
476
Arnaud Lacombe32543992010-11-02 00:26:33 -0400477static void conf_usage(const char *progname)
478{
479
Michal Marek0a1f00a2015-04-08 13:30:42 +0200480 printf("Usage: %s [-s] [option] <kconfig-file>\n", progname);
Arnaud Lacombe32543992010-11-02 00:26:33 -0400481 printf("[option] is _one_ of the following:\n");
482 printf(" --listnewconfig List new options\n");
Laura Abbott5d8b42a2019-11-04 17:10:08 -0500483 printf(" --helpnewconfig List new options and help text\n");
Arnaud Lacombe32543992010-11-02 00:26:33 -0400484 printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
485 printf(" --oldconfig Update a configuration using a provided .config as base\n");
Masahiro Yamada911a91c2018-03-01 15:34:37 +0900486 printf(" --syncconfig Similar to oldconfig but generates configuration in\n"
487 " include/{generated/,config/}\n");
Marc Herbertcedd55d2018-01-26 14:59:00 -0800488 printf(" --olddefconfig Same as oldconfig but sets new symbols to their default value\n");
Arnaud Lacombe32543992010-11-02 00:26:33 -0400489 printf(" --defconfig <file> New config with default defined in <file>\n");
490 printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
491 printf(" --allnoconfig New config where all options are answered with no\n");
492 printf(" --allyesconfig New config where all options are answered with yes\n");
493 printf(" --allmodconfig New config where all options are answered with mod\n");
494 printf(" --alldefconfig New config with all symbols set to default\n");
495 printf(" --randconfig New config with random answer to all options\n");
Tetsuo Handa89b90602019-12-17 18:42:06 +0900496 printf(" --yes2modconfig Change answers from yes to mod if possible\n");
497 printf(" --mod2yesconfig Change answers from mod to yes if possible\n");
Arnaud Lacombe32543992010-11-02 00:26:33 -0400498}
499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500int main(int ac, char **av)
501{
Arnaud Lacombe32543992010-11-02 00:26:33 -0400502 const char *progname = av[0];
Andres Salomon2f4b4892007-12-17 01:34:58 -0500503 int opt;
Arnaud Lacombe275744c2010-10-13 20:43:28 -0400504 const char *name, *defconfig_file = NULL /* gcc uninit */;
Masahiro Yamada16952b72018-07-20 16:46:30 +0900505 int no_conf_write = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Masahiro Yamadaf3ff6fb2018-02-08 14:56:40 +0900507 tty_stdio = isatty(0) && isatty(1);
Ben Hutchings62dc9892013-02-19 02:24:26 +0200508
Michal Marek0a1f00a2015-04-08 13:30:42 +0200509 while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
510 if (opt == 's') {
511 conf_set_message_callback(NULL);
512 continue;
513 }
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200514 input_mode = (enum input_mode)opt;
Andres Salomon2f4b4892007-12-17 01:34:58 -0500515 switch (opt) {
Masahiro Yamada911a91c2018-03-01 15:34:37 +0900516 case syncconfig:
Masahiro Yamada9a9ddcf2018-08-16 16:48:26 +0900517 /*
518 * syncconfig is invoked during the build stage.
519 * Suppress distracting "configuration written to ..."
520 */
521 conf_set_message_callback(NULL);
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200522 sync_kconfig = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200524 case defconfig:
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200525 case savedefconfig:
Andres Salomon2f4b4892007-12-17 01:34:58 -0500526 defconfig_file = optarg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200528 case randconfig:
Ingo Molnarb0fe5512009-03-12 15:15:31 +0100529 {
530 struct timeval now;
531 unsigned int seed;
Yann E. MORIN0d8024c2013-04-13 22:49:13 +0200532 char *seed_env;
Ingo Molnarb0fe5512009-03-12 15:15:31 +0100533
534 /*
535 * Use microseconds derived seed,
536 * compensate for systems where it may be zero
537 */
538 gettimeofday(&now, NULL);
Ingo Molnarb0fe5512009-03-12 15:15:31 +0100539 seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
Yann E. MORIN0d8024c2013-04-13 22:49:13 +0200540
541 seed_env = getenv("KCONFIG_SEED");
542 if( seed_env && *seed_env ) {
543 char *endp;
Yann E. MORINe85ac122013-05-20 23:17:34 +0200544 int tmp = (int)strtol(seed_env, &endp, 0);
Yann E. MORIN0d8024c2013-04-13 22:49:13 +0200545 if (*endp == '\0') {
546 seed = tmp;
547 }
548 }
Yann E. MORINa5f6d792013-05-20 23:09:03 +0200549 fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
Ingo Molnarb0fe5512009-03-12 15:15:31 +0100550 srand(seed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 break;
Ingo Molnarb0fe5512009-03-12 15:15:31 +0100552 }
Arnaud Lacombe32543992010-11-02 00:26:33 -0400553 case oldaskconfig:
554 case oldconfig:
555 case allnoconfig:
556 case allyesconfig:
557 case allmodconfig:
558 case alldefconfig:
559 case listnewconfig:
Laura Abbott5d8b42a2019-11-04 17:10:08 -0500560 case helpnewconfig:
Adam Leefb16d892012-09-01 01:05:17 +0800561 case olddefconfig:
Tetsuo Handa89b90602019-12-17 18:42:06 +0900562 case yes2modconfig:
563 case mod2yesconfig:
Arnaud Lacombe32543992010-11-02 00:26:33 -0400564 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200565 case '?':
Arnaud Lacombe32543992010-11-02 00:26:33 -0400566 conf_usage(progname);
Andres Salomon2f4b4892007-12-17 01:34:58 -0500567 exit(1);
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200568 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 }
570 }
Andres Salomon2f4b4892007-12-17 01:34:58 -0500571 if (ac == optind) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200572 fprintf(stderr, "%s: Kconfig file missing\n", av[0]);
Arnaud Lacombe32543992010-11-02 00:26:33 -0400573 conf_usage(progname);
Randy Dunlap250725a2006-06-08 22:12:50 -0700574 exit(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 }
Andres Salomon2f4b4892007-12-17 01:34:58 -0500576 name = av[optind];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 conf_parse(name);
578 //zconfdump(stdout);
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200579
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 switch (input_mode) {
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200581 case defconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 if (conf_read(defconfig_file)) {
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900583 fprintf(stderr,
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200584 "***\n"
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900585 "*** Can't find default configuration \"%s\"!\n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200586 "***\n",
Masahiro Yamada9e3e10c2018-02-06 09:34:41 +0900587 defconfig_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 exit(1);
589 }
590 break;
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200591 case savedefconfig:
Masahiro Yamada911a91c2018-03-01 15:34:37 +0900592 case syncconfig:
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200593 case oldaskconfig:
594 case oldconfig:
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200595 case listnewconfig:
Laura Abbott5d8b42a2019-11-04 17:10:08 -0500596 case helpnewconfig:
Adam Leefb16d892012-09-01 01:05:17 +0800597 case olddefconfig:
Tetsuo Handa89b90602019-12-17 18:42:06 +0900598 case yes2modconfig:
599 case mod2yesconfig:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 conf_read(NULL);
601 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200602 case allnoconfig:
603 case allyesconfig:
604 case allmodconfig:
Sam Ravnborg0748cb32010-07-31 23:35:31 +0200605 case alldefconfig:
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200606 case randconfig:
Roman Zippel90389162005-11-08 21:34:49 -0800607 name = getenv("KCONFIG_ALLCONFIG");
Eric W. Biederman9f420bf2012-05-07 05:37:45 -0700608 if (!name)
609 break;
610 if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
Eric W. Biederman5efe2412012-04-26 01:51:32 -0700611 if (conf_read_simple(name, S_DEF_USER)) {
612 fprintf(stderr,
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200613 "*** Can't read seed configuration \"%s\"!\n",
Eric W. Biederman5efe2412012-04-26 01:51:32 -0700614 name);
615 exit(1);
616 }
Roman Zippel90389162005-11-08 21:34:49 -0800617 break;
618 }
619 switch (input_mode) {
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200620 case allnoconfig: name = "allno.config"; break;
621 case allyesconfig: name = "allyes.config"; break;
622 case allmodconfig: name = "allmod.config"; break;
Sam Ravnborg0748cb32010-07-31 23:35:31 +0200623 case alldefconfig: name = "alldef.config"; break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200624 case randconfig: name = "allrandom.config"; break;
Roman Zippel90389162005-11-08 21:34:49 -0800625 default: break;
626 }
Eric W. Biederman5efe2412012-04-26 01:51:32 -0700627 if (conf_read_simple(name, S_DEF_USER) &&
628 conf_read_simple("all.config", S_DEF_USER)) {
629 fprintf(stderr,
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200630 "*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n",
Eric W. Biederman5efe2412012-04-26 01:51:32 -0700631 name);
632 exit(1);
633 }
Roman Zippel90389162005-11-08 21:34:49 -0800634 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 default:
636 break;
637 }
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200638
639 if (sync_kconfig) {
Masahiro Yamada16952b72018-07-20 16:46:30 +0900640 name = getenv("KCONFIG_NOSILENTUPDATE");
641 if (name && *name) {
642 if (conf_get_changed()) {
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200643 fprintf(stderr,
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200644 "\n*** The configuration requires explicit update.\n\n");
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200645 return 1;
646 }
Masahiro Yamada16952b72018-07-20 16:46:30 +0900647 no_conf_write = 1;
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200648 }
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200649 }
650
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200651 switch (input_mode) {
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200652 case allnoconfig:
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200653 conf_set_all_new_symbols(def_no);
654 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200655 case allyesconfig:
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200656 conf_set_all_new_symbols(def_yes);
657 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200658 case allmodconfig:
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200659 conf_set_all_new_symbols(def_mod);
660 break;
Sam Ravnborg0748cb32010-07-31 23:35:31 +0200661 case alldefconfig:
662 conf_set_all_new_symbols(def_default);
663 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200664 case randconfig:
Yann E. MORIN3b9a19e2013-04-28 22:36:38 +0200665 /* Really nothing to do in this loop */
666 while (conf_set_all_new_symbols(def_random)) ;
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200667 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200668 case defconfig:
Sam Ravnborg09748e12008-06-30 23:02:59 +0200669 conf_set_all_new_symbols(def_default);
670 break;
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200671 case savedefconfig:
672 break;
Tetsuo Handa89b90602019-12-17 18:42:06 +0900673 case yes2modconfig:
674 conf_rewrite_mod_or_yes(def_y2m);
675 break;
676 case mod2yesconfig:
677 conf_rewrite_mod_or_yes(def_m2y);
678 break;
Sam Ravnborg4062f1a2010-07-31 23:35:26 +0200679 case oldaskconfig:
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200680 rootEntry = &rootmenu;
681 conf(&rootmenu);
Masahiro Yamada2aad9b82018-02-28 09:15:24 +0900682 input_mode = oldconfig;
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200683 /* fall through */
Sam Ravnborg14828342010-08-06 07:13:54 +0200684 case oldconfig:
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200685 case listnewconfig:
Laura Abbott5d8b42a2019-11-04 17:10:08 -0500686 case helpnewconfig:
Masahiro Yamada911a91c2018-03-01 15:34:37 +0900687 case syncconfig:
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200688 /* Update until a loop caused no more changes */
689 do {
690 conf_cnt = 0;
691 check_conf(&rootmenu);
Masahiro Yamada99f0b652018-02-28 09:15:23 +0900692 } while (conf_cnt);
Masahiro Yamada59a80b52018-02-28 09:15:21 +0900693 break;
694 case olddefconfig:
695 default:
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200696 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 }
Sam Ravnborgf443d2e2008-06-30 22:45:38 +0200698
Masahiro Yamada00c864f2018-07-20 16:46:31 +0900699 if (input_mode == savedefconfig) {
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200700 if (conf_write_defconfig(defconfig_file)) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200701 fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
Masahiro Yamadabb66fc62014-06-10 19:08:13 +0900702 defconfig_file);
Sam Ravnborg7cf3d732010-07-31 23:35:34 +0200703 return 1;
704 }
Laura Abbott5d8b42a2019-11-04 17:10:08 -0500705 } else if (input_mode != listnewconfig && input_mode != helpnewconfig) {
Masahiro Yamada00c864f2018-07-20 16:46:31 +0900706 if (!no_conf_write && conf_write(NULL)) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200707 fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
zippel@linux-m68k.org204c96f2008-09-29 05:27:10 +0200708 exit(1);
709 }
Masahiro Yamada00c864f2018-07-20 16:46:31 +0900710
711 /*
712 * Create auto.conf if it does not exist.
713 * This prevents GNU Make 4.1 or older from emitting
714 * "include/config/auto.conf: No such file or directory"
715 * in the top-level Makefile
716 *
717 * syncconfig always creates or updates auto.conf because it is
718 * used during the build.
719 */
720 if (conf_write_autoconf(sync_kconfig) && sync_kconfig) {
721 fprintf(stderr,
722 "\n*** Error during sync of the configuration.\n\n");
723 return 1;
724 }
Roman Zippelc955cca2006-06-08 22:12:39 -0700725 }
Sam Ravnborg861b4ea2010-07-31 23:35:28 +0200726 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727}