source: debwrt/trunk/config/mconf/conf.c @ 1

Last change on this file since 1 was 1, checked in by amain, 13 years ago

Initial import of the build environment for DebWrt

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