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