1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <ctype.h>
7*4882a593Smuzhiyun #include <limits.h>
8*4882a593Smuzhiyun #include <stdio.h>
9*4882a593Smuzhiyun #include <stdlib.h>
10*4882a593Smuzhiyun #include <string.h>
11*4882a593Smuzhiyun #include <time.h>
12*4882a593Smuzhiyun #include <unistd.h>
13*4882a593Smuzhiyun #include <getopt.h>
14*4882a593Smuzhiyun #include <sys/stat.h>
15*4882a593Smuzhiyun #include <sys/time.h>
16*4882a593Smuzhiyun #include <errno.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include "lkc.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun static void conf(struct menu *menu);
21*4882a593Smuzhiyun static void check_conf(struct menu *menu);
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun enum input_mode {
24*4882a593Smuzhiyun oldaskconfig,
25*4882a593Smuzhiyun syncconfig,
26*4882a593Smuzhiyun oldconfig,
27*4882a593Smuzhiyun allnoconfig,
28*4882a593Smuzhiyun allyesconfig,
29*4882a593Smuzhiyun allmodconfig,
30*4882a593Smuzhiyun alldefconfig,
31*4882a593Smuzhiyun randconfig,
32*4882a593Smuzhiyun defconfig,
33*4882a593Smuzhiyun savedefconfig,
34*4882a593Smuzhiyun listnewconfig,
35*4882a593Smuzhiyun helpnewconfig,
36*4882a593Smuzhiyun olddefconfig,
37*4882a593Smuzhiyun yes2modconfig,
38*4882a593Smuzhiyun mod2yesconfig,
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun static enum input_mode input_mode = oldaskconfig;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun static int indent = 1;
43*4882a593Smuzhiyun static int tty_stdio;
44*4882a593Smuzhiyun static int sync_kconfig;
45*4882a593Smuzhiyun static int conf_cnt;
46*4882a593Smuzhiyun static char line[PATH_MAX];
47*4882a593Smuzhiyun static struct menu *rootEntry;
48*4882a593Smuzhiyun
print_help(struct menu * menu)49*4882a593Smuzhiyun static void print_help(struct menu *menu)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun struct gstr help = str_new();
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun menu_get_ext_help(menu, &help);
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun printf("\n%s\n", str_get(&help));
56*4882a593Smuzhiyun str_free(&help);
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
strip(char * str)59*4882a593Smuzhiyun static void strip(char *str)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun char *p = str;
62*4882a593Smuzhiyun int l;
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun while ((isspace(*p)))
65*4882a593Smuzhiyun p++;
66*4882a593Smuzhiyun l = strlen(p);
67*4882a593Smuzhiyun if (p != str)
68*4882a593Smuzhiyun memmove(str, p, l + 1);
69*4882a593Smuzhiyun if (!l)
70*4882a593Smuzhiyun return;
71*4882a593Smuzhiyun p = str + l - 1;
72*4882a593Smuzhiyun while ((isspace(*p)))
73*4882a593Smuzhiyun *p-- = 0;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* Helper function to facilitate fgets() by Jean Sacren. */
xfgets(char * str,int size,FILE * in)77*4882a593Smuzhiyun static void xfgets(char *str, int size, FILE *in)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun if (!fgets(str, size, in))
80*4882a593Smuzhiyun fprintf(stderr, "\nError in reading or end of file.\n");
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun if (!tty_stdio)
83*4882a593Smuzhiyun printf("%s", str);
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
conf_askvalue(struct symbol * sym,const char * def)86*4882a593Smuzhiyun static int conf_askvalue(struct symbol *sym, const char *def)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun enum symbol_type type = sym_get_type(sym);
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (!sym_has_value(sym))
91*4882a593Smuzhiyun printf("(NEW) ");
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun line[0] = '\n';
94*4882a593Smuzhiyun line[1] = 0;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun if (!sym_is_changeable(sym)) {
97*4882a593Smuzhiyun printf("%s\n", def);
98*4882a593Smuzhiyun line[0] = '\n';
99*4882a593Smuzhiyun line[1] = 0;
100*4882a593Smuzhiyun return 0;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun switch (input_mode) {
104*4882a593Smuzhiyun case oldconfig:
105*4882a593Smuzhiyun case syncconfig:
106*4882a593Smuzhiyun if (sym_has_value(sym)) {
107*4882a593Smuzhiyun printf("%s\n", def);
108*4882a593Smuzhiyun return 0;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun /* fall through */
111*4882a593Smuzhiyun case oldaskconfig:
112*4882a593Smuzhiyun fflush(stdout);
113*4882a593Smuzhiyun xfgets(line, sizeof(line), stdin);
114*4882a593Smuzhiyun return 1;
115*4882a593Smuzhiyun default:
116*4882a593Smuzhiyun break;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun switch (type) {
120*4882a593Smuzhiyun case S_INT:
121*4882a593Smuzhiyun case S_HEX:
122*4882a593Smuzhiyun case S_STRING:
123*4882a593Smuzhiyun printf("%s\n", def);
124*4882a593Smuzhiyun return 1;
125*4882a593Smuzhiyun default:
126*4882a593Smuzhiyun ;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun printf("%s", line);
129*4882a593Smuzhiyun return 1;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
conf_string(struct menu * menu)132*4882a593Smuzhiyun static int conf_string(struct menu *menu)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun struct symbol *sym = menu->sym;
135*4882a593Smuzhiyun const char *def;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun while (1) {
138*4882a593Smuzhiyun printf("%*s%s ", indent - 1, "", menu->prompt->text);
139*4882a593Smuzhiyun printf("(%s) ", sym->name);
140*4882a593Smuzhiyun def = sym_get_string_value(sym);
141*4882a593Smuzhiyun if (sym_get_string_value(sym))
142*4882a593Smuzhiyun printf("[%s] ", def);
143*4882a593Smuzhiyun if (!conf_askvalue(sym, def))
144*4882a593Smuzhiyun return 0;
145*4882a593Smuzhiyun switch (line[0]) {
146*4882a593Smuzhiyun case '\n':
147*4882a593Smuzhiyun break;
148*4882a593Smuzhiyun case '?':
149*4882a593Smuzhiyun /* print help */
150*4882a593Smuzhiyun if (line[1] == '\n') {
151*4882a593Smuzhiyun print_help(menu);
152*4882a593Smuzhiyun def = NULL;
153*4882a593Smuzhiyun break;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun /* fall through */
156*4882a593Smuzhiyun default:
157*4882a593Smuzhiyun line[strlen(line)-1] = 0;
158*4882a593Smuzhiyun def = line;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun if (def && sym_set_string_value(sym, def))
161*4882a593Smuzhiyun return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun
conf_sym(struct menu * menu)165*4882a593Smuzhiyun static int conf_sym(struct menu *menu)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun struct symbol *sym = menu->sym;
168*4882a593Smuzhiyun tristate oldval, newval;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun while (1) {
171*4882a593Smuzhiyun printf("%*s%s ", indent - 1, "", menu->prompt->text);
172*4882a593Smuzhiyun if (sym->name)
173*4882a593Smuzhiyun printf("(%s) ", sym->name);
174*4882a593Smuzhiyun putchar('[');
175*4882a593Smuzhiyun oldval = sym_get_tristate_value(sym);
176*4882a593Smuzhiyun switch (oldval) {
177*4882a593Smuzhiyun case no:
178*4882a593Smuzhiyun putchar('N');
179*4882a593Smuzhiyun break;
180*4882a593Smuzhiyun case mod:
181*4882a593Smuzhiyun putchar('M');
182*4882a593Smuzhiyun break;
183*4882a593Smuzhiyun case yes:
184*4882a593Smuzhiyun putchar('Y');
185*4882a593Smuzhiyun break;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun if (oldval != no && sym_tristate_within_range(sym, no))
188*4882a593Smuzhiyun printf("/n");
189*4882a593Smuzhiyun if (oldval != mod && sym_tristate_within_range(sym, mod))
190*4882a593Smuzhiyun printf("/m");
191*4882a593Smuzhiyun if (oldval != yes && sym_tristate_within_range(sym, yes))
192*4882a593Smuzhiyun printf("/y");
193*4882a593Smuzhiyun printf("/?] ");
194*4882a593Smuzhiyun if (!conf_askvalue(sym, sym_get_string_value(sym)))
195*4882a593Smuzhiyun return 0;
196*4882a593Smuzhiyun strip(line);
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun switch (line[0]) {
199*4882a593Smuzhiyun case 'n':
200*4882a593Smuzhiyun case 'N':
201*4882a593Smuzhiyun newval = no;
202*4882a593Smuzhiyun if (!line[1] || !strcmp(&line[1], "o"))
203*4882a593Smuzhiyun break;
204*4882a593Smuzhiyun continue;
205*4882a593Smuzhiyun case 'm':
206*4882a593Smuzhiyun case 'M':
207*4882a593Smuzhiyun newval = mod;
208*4882a593Smuzhiyun if (!line[1])
209*4882a593Smuzhiyun break;
210*4882a593Smuzhiyun continue;
211*4882a593Smuzhiyun case 'y':
212*4882a593Smuzhiyun case 'Y':
213*4882a593Smuzhiyun newval = yes;
214*4882a593Smuzhiyun if (!line[1] || !strcmp(&line[1], "es"))
215*4882a593Smuzhiyun break;
216*4882a593Smuzhiyun continue;
217*4882a593Smuzhiyun case 0:
218*4882a593Smuzhiyun newval = oldval;
219*4882a593Smuzhiyun break;
220*4882a593Smuzhiyun case '?':
221*4882a593Smuzhiyun goto help;
222*4882a593Smuzhiyun default:
223*4882a593Smuzhiyun continue;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun if (sym_set_tristate_value(sym, newval))
226*4882a593Smuzhiyun return 0;
227*4882a593Smuzhiyun help:
228*4882a593Smuzhiyun print_help(menu);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
conf_choice(struct menu * menu)232*4882a593Smuzhiyun static int conf_choice(struct menu *menu)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun struct symbol *sym, *def_sym;
235*4882a593Smuzhiyun struct menu *child;
236*4882a593Smuzhiyun bool is_new;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun sym = menu->sym;
239*4882a593Smuzhiyun is_new = !sym_has_value(sym);
240*4882a593Smuzhiyun if (sym_is_changeable(sym)) {
241*4882a593Smuzhiyun conf_sym(menu);
242*4882a593Smuzhiyun sym_calc_value(sym);
243*4882a593Smuzhiyun switch (sym_get_tristate_value(sym)) {
244*4882a593Smuzhiyun case no:
245*4882a593Smuzhiyun return 1;
246*4882a593Smuzhiyun case mod:
247*4882a593Smuzhiyun return 0;
248*4882a593Smuzhiyun case yes:
249*4882a593Smuzhiyun break;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun } else {
252*4882a593Smuzhiyun switch (sym_get_tristate_value(sym)) {
253*4882a593Smuzhiyun case no:
254*4882a593Smuzhiyun return 1;
255*4882a593Smuzhiyun case mod:
256*4882a593Smuzhiyun printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
257*4882a593Smuzhiyun return 0;
258*4882a593Smuzhiyun case yes:
259*4882a593Smuzhiyun break;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun while (1) {
264*4882a593Smuzhiyun int cnt, def;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
267*4882a593Smuzhiyun def_sym = sym_get_choice_value(sym);
268*4882a593Smuzhiyun cnt = def = 0;
269*4882a593Smuzhiyun line[0] = 0;
270*4882a593Smuzhiyun for (child = menu->list; child; child = child->next) {
271*4882a593Smuzhiyun if (!menu_is_visible(child))
272*4882a593Smuzhiyun continue;
273*4882a593Smuzhiyun if (!child->sym) {
274*4882a593Smuzhiyun printf("%*c %s\n", indent, '*', menu_get_prompt(child));
275*4882a593Smuzhiyun continue;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun cnt++;
278*4882a593Smuzhiyun if (child->sym == def_sym) {
279*4882a593Smuzhiyun def = cnt;
280*4882a593Smuzhiyun printf("%*c", indent, '>');
281*4882a593Smuzhiyun } else
282*4882a593Smuzhiyun printf("%*c", indent, ' ');
283*4882a593Smuzhiyun printf(" %d. %s", cnt, menu_get_prompt(child));
284*4882a593Smuzhiyun if (child->sym->name)
285*4882a593Smuzhiyun printf(" (%s)", child->sym->name);
286*4882a593Smuzhiyun if (!sym_has_value(child->sym))
287*4882a593Smuzhiyun printf(" (NEW)");
288*4882a593Smuzhiyun printf("\n");
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun printf("%*schoice", indent - 1, "");
291*4882a593Smuzhiyun if (cnt == 1) {
292*4882a593Smuzhiyun printf("[1]: 1\n");
293*4882a593Smuzhiyun goto conf_childs;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun printf("[1-%d?]: ", cnt);
296*4882a593Smuzhiyun switch (input_mode) {
297*4882a593Smuzhiyun case oldconfig:
298*4882a593Smuzhiyun case syncconfig:
299*4882a593Smuzhiyun if (!is_new) {
300*4882a593Smuzhiyun cnt = def;
301*4882a593Smuzhiyun printf("%d\n", cnt);
302*4882a593Smuzhiyun break;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun /* fall through */
305*4882a593Smuzhiyun case oldaskconfig:
306*4882a593Smuzhiyun fflush(stdout);
307*4882a593Smuzhiyun xfgets(line, sizeof(line), stdin);
308*4882a593Smuzhiyun strip(line);
309*4882a593Smuzhiyun if (line[0] == '?') {
310*4882a593Smuzhiyun print_help(menu);
311*4882a593Smuzhiyun continue;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun if (!line[0])
314*4882a593Smuzhiyun cnt = def;
315*4882a593Smuzhiyun else if (isdigit(line[0]))
316*4882a593Smuzhiyun cnt = atoi(line);
317*4882a593Smuzhiyun else
318*4882a593Smuzhiyun continue;
319*4882a593Smuzhiyun break;
320*4882a593Smuzhiyun default:
321*4882a593Smuzhiyun break;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun conf_childs:
325*4882a593Smuzhiyun for (child = menu->list; child; child = child->next) {
326*4882a593Smuzhiyun if (!child->sym || !menu_is_visible(child))
327*4882a593Smuzhiyun continue;
328*4882a593Smuzhiyun if (!--cnt)
329*4882a593Smuzhiyun break;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun if (!child)
332*4882a593Smuzhiyun continue;
333*4882a593Smuzhiyun if (line[0] && line[strlen(line) - 1] == '?') {
334*4882a593Smuzhiyun print_help(child);
335*4882a593Smuzhiyun continue;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun sym_set_choice_value(sym, child->sym);
338*4882a593Smuzhiyun for (child = child->list; child; child = child->next) {
339*4882a593Smuzhiyun indent += 2;
340*4882a593Smuzhiyun conf(child);
341*4882a593Smuzhiyun indent -= 2;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun return 1;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
conf(struct menu * menu)347*4882a593Smuzhiyun static void conf(struct menu *menu)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun struct symbol *sym;
350*4882a593Smuzhiyun struct property *prop;
351*4882a593Smuzhiyun struct menu *child;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun if (!menu_is_visible(menu))
354*4882a593Smuzhiyun return;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun sym = menu->sym;
357*4882a593Smuzhiyun prop = menu->prompt;
358*4882a593Smuzhiyun if (prop) {
359*4882a593Smuzhiyun const char *prompt;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun switch (prop->type) {
362*4882a593Smuzhiyun case P_MENU:
363*4882a593Smuzhiyun /*
364*4882a593Smuzhiyun * Except in oldaskconfig mode, we show only menus that
365*4882a593Smuzhiyun * contain new symbols.
366*4882a593Smuzhiyun */
367*4882a593Smuzhiyun if (input_mode != oldaskconfig && rootEntry != menu) {
368*4882a593Smuzhiyun check_conf(menu);
369*4882a593Smuzhiyun return;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun /* fall through */
372*4882a593Smuzhiyun case P_COMMENT:
373*4882a593Smuzhiyun prompt = menu_get_prompt(menu);
374*4882a593Smuzhiyun if (prompt)
375*4882a593Smuzhiyun printf("%*c\n%*c %s\n%*c\n",
376*4882a593Smuzhiyun indent, '*',
377*4882a593Smuzhiyun indent, '*', prompt,
378*4882a593Smuzhiyun indent, '*');
379*4882a593Smuzhiyun default:
380*4882a593Smuzhiyun ;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun if (!sym)
385*4882a593Smuzhiyun goto conf_childs;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun if (sym_is_choice(sym)) {
388*4882a593Smuzhiyun conf_choice(menu);
389*4882a593Smuzhiyun if (sym->curr.tri != mod)
390*4882a593Smuzhiyun return;
391*4882a593Smuzhiyun goto conf_childs;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun switch (sym->type) {
395*4882a593Smuzhiyun case S_INT:
396*4882a593Smuzhiyun case S_HEX:
397*4882a593Smuzhiyun case S_STRING:
398*4882a593Smuzhiyun conf_string(menu);
399*4882a593Smuzhiyun break;
400*4882a593Smuzhiyun default:
401*4882a593Smuzhiyun conf_sym(menu);
402*4882a593Smuzhiyun break;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun conf_childs:
406*4882a593Smuzhiyun if (sym)
407*4882a593Smuzhiyun indent += 2;
408*4882a593Smuzhiyun for (child = menu->list; child; child = child->next)
409*4882a593Smuzhiyun conf(child);
410*4882a593Smuzhiyun if (sym)
411*4882a593Smuzhiyun indent -= 2;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
check_conf(struct menu * menu)414*4882a593Smuzhiyun static void check_conf(struct menu *menu)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun struct symbol *sym;
417*4882a593Smuzhiyun struct menu *child;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun if (!menu_is_visible(menu))
420*4882a593Smuzhiyun return;
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun sym = menu->sym;
423*4882a593Smuzhiyun if (sym && !sym_has_value(sym)) {
424*4882a593Smuzhiyun if (sym_is_changeable(sym) ||
425*4882a593Smuzhiyun (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
426*4882a593Smuzhiyun if (input_mode == listnewconfig) {
427*4882a593Smuzhiyun if (sym->name) {
428*4882a593Smuzhiyun const char *str;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun if (sym->type == S_STRING) {
431*4882a593Smuzhiyun str = sym_get_string_value(sym);
432*4882a593Smuzhiyun str = sym_escape_string_value(str);
433*4882a593Smuzhiyun printf("%s%s=%s\n", CONFIG_, sym->name, str);
434*4882a593Smuzhiyun free((void *)str);
435*4882a593Smuzhiyun } else {
436*4882a593Smuzhiyun str = sym_get_string_value(sym);
437*4882a593Smuzhiyun printf("%s%s=%s\n", CONFIG_, sym->name, str);
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun } else if (input_mode == helpnewconfig) {
441*4882a593Smuzhiyun printf("-----\n");
442*4882a593Smuzhiyun print_help(menu);
443*4882a593Smuzhiyun printf("-----\n");
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun } else {
446*4882a593Smuzhiyun if (!conf_cnt++)
447*4882a593Smuzhiyun printf("*\n* Restart config...\n*\n");
448*4882a593Smuzhiyun rootEntry = menu_get_parent_menu(menu);
449*4882a593Smuzhiyun conf(rootEntry);
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun for (child = menu->list; child; child = child->next)
455*4882a593Smuzhiyun check_conf(child);
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun static struct option long_opts[] = {
459*4882a593Smuzhiyun {"oldaskconfig", no_argument, NULL, oldaskconfig},
460*4882a593Smuzhiyun {"oldconfig", no_argument, NULL, oldconfig},
461*4882a593Smuzhiyun {"syncconfig", no_argument, NULL, syncconfig},
462*4882a593Smuzhiyun {"defconfig", required_argument, NULL, defconfig},
463*4882a593Smuzhiyun {"savedefconfig", required_argument, NULL, savedefconfig},
464*4882a593Smuzhiyun {"allnoconfig", no_argument, NULL, allnoconfig},
465*4882a593Smuzhiyun {"allyesconfig", no_argument, NULL, allyesconfig},
466*4882a593Smuzhiyun {"allmodconfig", no_argument, NULL, allmodconfig},
467*4882a593Smuzhiyun {"alldefconfig", no_argument, NULL, alldefconfig},
468*4882a593Smuzhiyun {"randconfig", no_argument, NULL, randconfig},
469*4882a593Smuzhiyun {"listnewconfig", no_argument, NULL, listnewconfig},
470*4882a593Smuzhiyun {"helpnewconfig", no_argument, NULL, helpnewconfig},
471*4882a593Smuzhiyun {"olddefconfig", no_argument, NULL, olddefconfig},
472*4882a593Smuzhiyun {"yes2modconfig", no_argument, NULL, yes2modconfig},
473*4882a593Smuzhiyun {"mod2yesconfig", no_argument, NULL, mod2yesconfig},
474*4882a593Smuzhiyun {NULL, 0, NULL, 0}
475*4882a593Smuzhiyun };
476*4882a593Smuzhiyun
conf_usage(const char * progname)477*4882a593Smuzhiyun static void conf_usage(const char *progname)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun printf("Usage: %s [-s] [option] <kconfig-file>\n", progname);
481*4882a593Smuzhiyun printf("[option] is _one_ of the following:\n");
482*4882a593Smuzhiyun printf(" --listnewconfig List new options\n");
483*4882a593Smuzhiyun printf(" --helpnewconfig List new options and help text\n");
484*4882a593Smuzhiyun printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
485*4882a593Smuzhiyun printf(" --oldconfig Update a configuration using a provided .config as base\n");
486*4882a593Smuzhiyun printf(" --syncconfig Similar to oldconfig but generates configuration in\n"
487*4882a593Smuzhiyun " include/{generated/,config/}\n");
488*4882a593Smuzhiyun printf(" --olddefconfig Same as oldconfig but sets new symbols to their default value\n");
489*4882a593Smuzhiyun printf(" --defconfig <file> New config with default defined in <file>\n");
490*4882a593Smuzhiyun printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
491*4882a593Smuzhiyun printf(" --allnoconfig New config where all options are answered with no\n");
492*4882a593Smuzhiyun printf(" --allyesconfig New config where all options are answered with yes\n");
493*4882a593Smuzhiyun printf(" --allmodconfig New config where all options are answered with mod\n");
494*4882a593Smuzhiyun printf(" --alldefconfig New config with all symbols set to default\n");
495*4882a593Smuzhiyun printf(" --randconfig New config with random answer to all options\n");
496*4882a593Smuzhiyun printf(" --yes2modconfig Change answers from yes to mod if possible\n");
497*4882a593Smuzhiyun printf(" --mod2yesconfig Change answers from mod to yes if possible\n");
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun
main(int ac,char ** av)500*4882a593Smuzhiyun int main(int ac, char **av)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun const char *progname = av[0];
503*4882a593Smuzhiyun int opt;
504*4882a593Smuzhiyun const char *name, *defconfig_file = NULL /* gcc uninit */;
505*4882a593Smuzhiyun int no_conf_write = 0;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun tty_stdio = isatty(0) && isatty(1);
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
510*4882a593Smuzhiyun if (opt == 's') {
511*4882a593Smuzhiyun conf_set_message_callback(NULL);
512*4882a593Smuzhiyun continue;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun input_mode = (enum input_mode)opt;
515*4882a593Smuzhiyun switch (opt) {
516*4882a593Smuzhiyun case syncconfig:
517*4882a593Smuzhiyun /*
518*4882a593Smuzhiyun * syncconfig is invoked during the build stage.
519*4882a593Smuzhiyun * Suppress distracting "configuration written to ..."
520*4882a593Smuzhiyun */
521*4882a593Smuzhiyun conf_set_message_callback(NULL);
522*4882a593Smuzhiyun sync_kconfig = 1;
523*4882a593Smuzhiyun break;
524*4882a593Smuzhiyun case defconfig:
525*4882a593Smuzhiyun case savedefconfig:
526*4882a593Smuzhiyun defconfig_file = optarg;
527*4882a593Smuzhiyun break;
528*4882a593Smuzhiyun case randconfig:
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun struct timeval now;
531*4882a593Smuzhiyun unsigned int seed;
532*4882a593Smuzhiyun char *seed_env;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun /*
535*4882a593Smuzhiyun * Use microseconds derived seed,
536*4882a593Smuzhiyun * compensate for systems where it may be zero
537*4882a593Smuzhiyun */
538*4882a593Smuzhiyun gettimeofday(&now, NULL);
539*4882a593Smuzhiyun seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun seed_env = getenv("KCONFIG_SEED");
542*4882a593Smuzhiyun if( seed_env && *seed_env ) {
543*4882a593Smuzhiyun char *endp;
544*4882a593Smuzhiyun int tmp = (int)strtol(seed_env, &endp, 0);
545*4882a593Smuzhiyun if (*endp == '\0') {
546*4882a593Smuzhiyun seed = tmp;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
550*4882a593Smuzhiyun srand(seed);
551*4882a593Smuzhiyun break;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun case oldaskconfig:
554*4882a593Smuzhiyun case oldconfig:
555*4882a593Smuzhiyun case allnoconfig:
556*4882a593Smuzhiyun case allyesconfig:
557*4882a593Smuzhiyun case allmodconfig:
558*4882a593Smuzhiyun case alldefconfig:
559*4882a593Smuzhiyun case listnewconfig:
560*4882a593Smuzhiyun case helpnewconfig:
561*4882a593Smuzhiyun case olddefconfig:
562*4882a593Smuzhiyun case yes2modconfig:
563*4882a593Smuzhiyun case mod2yesconfig:
564*4882a593Smuzhiyun break;
565*4882a593Smuzhiyun case '?':
566*4882a593Smuzhiyun conf_usage(progname);
567*4882a593Smuzhiyun exit(1);
568*4882a593Smuzhiyun break;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun if (ac == optind) {
572*4882a593Smuzhiyun fprintf(stderr, "%s: Kconfig file missing\n", av[0]);
573*4882a593Smuzhiyun conf_usage(progname);
574*4882a593Smuzhiyun exit(1);
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun name = av[optind];
577*4882a593Smuzhiyun conf_parse(name);
578*4882a593Smuzhiyun //zconfdump(stdout);
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun switch (input_mode) {
581*4882a593Smuzhiyun case defconfig:
582*4882a593Smuzhiyun if (conf_read(defconfig_file)) {
583*4882a593Smuzhiyun fprintf(stderr,
584*4882a593Smuzhiyun "***\n"
585*4882a593Smuzhiyun "*** Can't find default configuration \"%s\"!\n"
586*4882a593Smuzhiyun "***\n",
587*4882a593Smuzhiyun defconfig_file);
588*4882a593Smuzhiyun exit(1);
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun break;
591*4882a593Smuzhiyun case savedefconfig:
592*4882a593Smuzhiyun case syncconfig:
593*4882a593Smuzhiyun case oldaskconfig:
594*4882a593Smuzhiyun case oldconfig:
595*4882a593Smuzhiyun case listnewconfig:
596*4882a593Smuzhiyun case helpnewconfig:
597*4882a593Smuzhiyun case olddefconfig:
598*4882a593Smuzhiyun case yes2modconfig:
599*4882a593Smuzhiyun case mod2yesconfig:
600*4882a593Smuzhiyun conf_read(NULL);
601*4882a593Smuzhiyun break;
602*4882a593Smuzhiyun case allnoconfig:
603*4882a593Smuzhiyun case allyesconfig:
604*4882a593Smuzhiyun case allmodconfig:
605*4882a593Smuzhiyun case alldefconfig:
606*4882a593Smuzhiyun case randconfig:
607*4882a593Smuzhiyun name = getenv("KCONFIG_ALLCONFIG");
608*4882a593Smuzhiyun if (!name)
609*4882a593Smuzhiyun break;
610*4882a593Smuzhiyun if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
611*4882a593Smuzhiyun if (conf_read_simple(name, S_DEF_USER)) {
612*4882a593Smuzhiyun fprintf(stderr,
613*4882a593Smuzhiyun "*** Can't read seed configuration \"%s\"!\n",
614*4882a593Smuzhiyun name);
615*4882a593Smuzhiyun exit(1);
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun break;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun switch (input_mode) {
620*4882a593Smuzhiyun case allnoconfig: name = "allno.config"; break;
621*4882a593Smuzhiyun case allyesconfig: name = "allyes.config"; break;
622*4882a593Smuzhiyun case allmodconfig: name = "allmod.config"; break;
623*4882a593Smuzhiyun case alldefconfig: name = "alldef.config"; break;
624*4882a593Smuzhiyun case randconfig: name = "allrandom.config"; break;
625*4882a593Smuzhiyun default: break;
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun if (conf_read_simple(name, S_DEF_USER) &&
628*4882a593Smuzhiyun conf_read_simple("all.config", S_DEF_USER)) {
629*4882a593Smuzhiyun fprintf(stderr,
630*4882a593Smuzhiyun "*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n",
631*4882a593Smuzhiyun name);
632*4882a593Smuzhiyun exit(1);
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun break;
635*4882a593Smuzhiyun default:
636*4882a593Smuzhiyun break;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun if (sync_kconfig) {
640*4882a593Smuzhiyun name = getenv("KCONFIG_NOSILENTUPDATE");
641*4882a593Smuzhiyun if (name && *name) {
642*4882a593Smuzhiyun if (conf_get_changed()) {
643*4882a593Smuzhiyun fprintf(stderr,
644*4882a593Smuzhiyun "\n*** The configuration requires explicit update.\n\n");
645*4882a593Smuzhiyun return 1;
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun no_conf_write = 1;
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun }
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun switch (input_mode) {
652*4882a593Smuzhiyun case allnoconfig:
653*4882a593Smuzhiyun conf_set_all_new_symbols(def_no);
654*4882a593Smuzhiyun break;
655*4882a593Smuzhiyun case allyesconfig:
656*4882a593Smuzhiyun conf_set_all_new_symbols(def_yes);
657*4882a593Smuzhiyun break;
658*4882a593Smuzhiyun case allmodconfig:
659*4882a593Smuzhiyun conf_set_all_new_symbols(def_mod);
660*4882a593Smuzhiyun break;
661*4882a593Smuzhiyun case alldefconfig:
662*4882a593Smuzhiyun conf_set_all_new_symbols(def_default);
663*4882a593Smuzhiyun break;
664*4882a593Smuzhiyun case randconfig:
665*4882a593Smuzhiyun /* Really nothing to do in this loop */
666*4882a593Smuzhiyun while (conf_set_all_new_symbols(def_random)) ;
667*4882a593Smuzhiyun break;
668*4882a593Smuzhiyun case defconfig:
669*4882a593Smuzhiyun conf_set_all_new_symbols(def_default);
670*4882a593Smuzhiyun break;
671*4882a593Smuzhiyun case savedefconfig:
672*4882a593Smuzhiyun break;
673*4882a593Smuzhiyun case yes2modconfig:
674*4882a593Smuzhiyun conf_rewrite_mod_or_yes(def_y2m);
675*4882a593Smuzhiyun break;
676*4882a593Smuzhiyun case mod2yesconfig:
677*4882a593Smuzhiyun conf_rewrite_mod_or_yes(def_m2y);
678*4882a593Smuzhiyun break;
679*4882a593Smuzhiyun case oldaskconfig:
680*4882a593Smuzhiyun rootEntry = &rootmenu;
681*4882a593Smuzhiyun conf(&rootmenu);
682*4882a593Smuzhiyun input_mode = oldconfig;
683*4882a593Smuzhiyun /* fall through */
684*4882a593Smuzhiyun case oldconfig:
685*4882a593Smuzhiyun case listnewconfig:
686*4882a593Smuzhiyun case helpnewconfig:
687*4882a593Smuzhiyun case syncconfig:
688*4882a593Smuzhiyun /* Update until a loop caused no more changes */
689*4882a593Smuzhiyun do {
690*4882a593Smuzhiyun conf_cnt = 0;
691*4882a593Smuzhiyun check_conf(&rootmenu);
692*4882a593Smuzhiyun } while (conf_cnt);
693*4882a593Smuzhiyun break;
694*4882a593Smuzhiyun case olddefconfig:
695*4882a593Smuzhiyun default:
696*4882a593Smuzhiyun break;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun if (input_mode == savedefconfig) {
700*4882a593Smuzhiyun if (conf_write_defconfig(defconfig_file)) {
701*4882a593Smuzhiyun fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
702*4882a593Smuzhiyun defconfig_file);
703*4882a593Smuzhiyun return 1;
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun } else if (input_mode != listnewconfig && input_mode != helpnewconfig) {
706*4882a593Smuzhiyun if (!no_conf_write && conf_write(NULL)) {
707*4882a593Smuzhiyun fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
708*4882a593Smuzhiyun exit(1);
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun /*
712*4882a593Smuzhiyun * Create auto.conf if it does not exist.
713*4882a593Smuzhiyun * This prevents GNU Make 4.1 or older from emitting
714*4882a593Smuzhiyun * "include/config/auto.conf: No such file or directory"
715*4882a593Smuzhiyun * in the top-level Makefile
716*4882a593Smuzhiyun *
717*4882a593Smuzhiyun * syncconfig always creates or updates auto.conf because it is
718*4882a593Smuzhiyun * used during the build.
719*4882a593Smuzhiyun */
720*4882a593Smuzhiyun if (conf_write_autoconf(sync_kconfig) && sync_kconfig) {
721*4882a593Smuzhiyun fprintf(stderr,
722*4882a593Smuzhiyun "\n*** Error during sync of the configuration.\n\n");
723*4882a593Smuzhiyun return 1;
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun }
726*4882a593Smuzhiyun return 0;
727*4882a593Smuzhiyun }
728