OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [extra/] [config/] [mconf.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/*
2
 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3
 * Released under the terms of the GNU GPL v2.0.
4
 *
5
 * Introduced single menu mode (show all sub-menus in one large tree).
6
 * 2002-11-06 Petr Baudis <pasky@ucw.cz>
7
 *
8
 * Directly use liblxdialog library routines.
9
 * 2002-11-14 Petr Baudis <pasky@ucw.cz>
10
 */
11
 
12
#include <sys/ioctl.h>
13
#include <sys/wait.h>
14
#include <sys/termios.h>
15
#include <ctype.h>
16
#include <errno.h>
17
#include <fcntl.h>
18
#include <limits.h>
19
#include <signal.h>
20
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <string.h>
23
#include <termios.h>
24
#include <unistd.h>
25
 
26
#include "dialog.h"
27
 
28
#define LKC_DIRECT_LINK
29
#include "lkc.h"
30
 
31
static char menu_backtitle[128];
32
static const char menu_instructions[] =
33
        "Arrow keys navigate the menu.  "
34
        "<Enter> selects submenus --->.  "
35
        "Highlighted letters are hotkeys.  "
36
        "Pressing <Y> selectes a feature, while <N> will exclude a feature.  "
37
        "Press <Esc><Esc> to exit, <?> for Help.  "
38
        "Legend: [*] feature is selected  [ ] feature is excluded",
39
radiolist_instructions[] =
40
        "Use the arrow keys to navigate this window or "
41
        "press the hotkey of the item you wish to select "
42
        "followed by the <SPACE BAR>. "
43
        "Press <?> for additional information about this option.",
44
inputbox_instructions_int[] =
45
        "Please enter a decimal value. "
46
        "Fractions will not be accepted.  "
47
        "Use the <TAB> key to move from the input field to the buttons below it.",
48
inputbox_instructions_hex[] =
49
        "Please enter a hexadecimal value. "
50
        "Use the <TAB> key to move from the input field to the buttons below it.",
51
inputbox_instructions_string[] =
52
        "Please enter a string value. "
53
        "Use the <TAB> key to move from the input field to the buttons below it.",
54
setmod_text[] =
55
        "This feature depends on another which has been configured as a module.\n"
56
        "As a result, this feature will be built as a module.",
57
nohelp_text[] =
58
        "There is no help available for this option.\n",
59
load_config_text[] =
60
        "Enter the name of the configuration file you wish to load.  "
61
        "Accept the name shown to restore the configuration you "
62
        "last retrieved.  Leave blank to abort.",
63
load_config_help[] =
64
        "\n"
65
        "For various reasons, one may wish to keep several different uClibc\n"
66
        "configurations available on a single machine.\n"
67
        "\n"
68
        "If you have saved a previous configuration in a file other than the\n"
69
        "uClibc's default, entering the name of the file here will allow you\n"
70
        "to modify that configuration.\n"
71
        "\n"
72
        "If you are uncertain, then you have probably never used alternate\n"
73
        "configuration files.  You should therefor leave this blank to abort.\n",
74
save_config_text[] =
75
        "Enter a filename to which this configuration should be saved "
76
        "as an alternate.  Leave blank to abort.",
77
save_config_help[] =
78
        "\n"
79
        "For various reasons, one may wish to keep different uClibc\n"
80
        "configurations available on a single machine.\n"
81
        "\n"
82
        "Entering a file name here will allow you to later retrieve, modify\n"
83
        "and use the current configuration as an alternate to whatever\n"
84
        "configuration options you have selected at that time.\n"
85
        "\n"
86
        "If you are uncertain what all this means then you should probably\n"
87
        "leave this blank.\n",
88
top_menu_help[] =
89
        "\n"
90
        "Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
91
        "you wish to change or submenu wish to select and press <Enter>.\n"
92
        "Submenus are designated by \"--->\".\n"
93
        "\n"
94
        "Shortcut: Press the option's highlighted letter (hotkey).\n"
95
        "\n"
96
        "You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
97
        "unseen options into view.\n"
98
;
99
 
100
static char filename[PATH_MAX+1] = ".config";
101
static int indent = 0;
102
static struct termios ios_org;
103
static int rows, cols;
104
static struct menu *current_menu;
105
static int child_count;
106
static int single_menu_mode;
107
 
108
static struct dialog_list_item *items[16384]; /* FIXME: This ought to be dynamic. */
109
static int item_no;
110
 
111
static void conf(struct menu *menu);
112
static void conf_choice(struct menu *menu);
113
static void conf_string(struct menu *menu);
114
static void conf_load(void);
115
static void conf_save(void);
116
static void show_textbox(const char *title, const char *text, int r, int c);
117
static void show_helptext(const char *title, const char *text);
118
static void show_help(struct menu *menu);
119
static void show_readme(void);
120
 
121
static void init_wsize(void)
122
{
123
        struct winsize ws;
124
        char *env;
125
 
126
        if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
127
                rows = 24;
128
                cols = 80;
129
        } else {
130
                rows = ws.ws_row;
131
                cols = ws.ws_col;
132
                if (!rows) {
133
                        env = getenv("LINES");
134
                        if (env)
135
                                rows = atoi(env);
136
                        if (!rows)
137
                                rows = 24;
138
                }
139
                if (!cols) {
140
                        env = getenv("COLUMNS");
141
                        if (env)
142
                                cols = atoi(env);
143
                        if (!cols)
144
                                cols = 80;
145
                }
146
        }
147
 
148
        if (rows < 19 || cols < 80) {
149
                fprintf(stderr, "Your display is too small to run Menuconfig!\n");
150
                fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
151
                exit(1);
152
        }
153
 
154
        rows -= 4;
155
        cols -= 5;
156
}
157
 
158
static void cinit(void)
159
{
160
        item_no = 0;
161
}
162
 
163
static void cmake(void)
164
{
165
        items[item_no] = malloc(sizeof(struct dialog_list_item));
166
        memset(items[item_no], 0, sizeof(struct dialog_list_item));
167
        items[item_no]->tag = malloc(32); items[item_no]->tag[0] = 0;
168
        items[item_no]->name = malloc(512); items[item_no]->name[0] = 0;
169
        items[item_no]->namelen = 0;
170
        item_no++;
171
}
172
 
173
static int cprint_name(const char *fmt, ...)
174
{
175
        va_list ap;
176
        int res;
177
 
178
        if (!item_no)
179
                cmake();
180
        va_start(ap, fmt);
181
        res = vsnprintf(items[item_no - 1]->name + items[item_no - 1]->namelen,
182
                        512 - items[item_no - 1]->namelen, fmt, ap);
183
        if (res > 0)
184
                items[item_no - 1]->namelen += res;
185
        va_end(ap);
186
 
187
        return res;
188
}
189
 
190
static int cprint_tag(const char *fmt, ...)
191
{
192
        va_list ap;
193
        int res;
194
 
195
        if (!item_no)
196
                cmake();
197
        va_start(ap, fmt);
198
        res = vsnprintf(items[item_no - 1]->tag, 32, fmt, ap);
199
        va_end(ap);
200
 
201
        return res;
202
}
203
 
204
static void cdone(void)
205
{
206
        int i;
207
 
208
        for (i = 0; i < item_no; i++) {
209
                free(items[i]->tag);
210
                free(items[i]->name);
211
                free(items[i]);
212
        }
213
 
214
        item_no = 0;
215
}
216
 
217
static void build_conf(struct menu *menu)
218
{
219
        struct symbol *sym;
220
        struct property *prop;
221
        struct menu *child;
222
        int type, tmp, doint = 2;
223
        tristate val;
224
        char ch;
225
 
226
        if (!menu_is_visible(menu))
227
                return;
228
 
229
        sym = menu->sym;
230
        prop = menu->prompt;
231
        if (!sym) {
232
                if (prop && menu != current_menu) {
233
                        const char *prompt = menu_get_prompt(menu);
234
                        switch (prop->type) {
235
                        case P_MENU:
236
                                child_count++;
237
                                cmake();
238
                                cprint_tag("m%p", menu);
239
 
240
                                if (single_menu_mode) {
241
                                        cprint_name("%s%*c%s",
242
                                                menu->data ? "-->" : "++>",
243
                                                indent + 1, ' ', prompt);
244
                                } else {
245
                                        cprint_name("   %*c%s  --->", indent + 1, ' ', prompt);
246
                                }
247
 
248
                                if (single_menu_mode && menu->data)
249
                                        goto conf_childs;
250
                                return;
251
                        default:
252
                                if (prompt) {
253
                                        child_count++;
254
                                        cmake();
255
                                        cprint_tag(":%p", menu);
256
                                        cprint_name("---%*c%s", indent + 1, ' ', prompt);
257
                                }
258
                        }
259
                } else
260
                        doint = 0;
261
                goto conf_childs;
262
        }
263
 
264
        cmake();
265
        type = sym_get_type(sym);
266
        if (sym_is_choice(sym)) {
267
                struct symbol *def_sym = sym_get_choice_value(sym);
268
                struct menu *def_menu = NULL;
269
 
270
                child_count++;
271
                for (child = menu->list; child; child = child->next) {
272
                        if (menu_is_visible(child) && child->sym == def_sym)
273
                                def_menu = child;
274
                }
275
 
276
                val = sym_get_tristate_value(sym);
277
                if (sym_is_changable(sym)) {
278
                        cprint_tag("t%p", menu);
279
                        switch (type) {
280
                        case S_BOOLEAN:
281
                                cprint_name("[%c]", val == no ? ' ' : '*');
282
                                break;
283
                        case S_TRISTATE:
284
                                switch (val) {
285
                                case yes: ch = '*'; break;
286
                                case mod: ch = 'M'; break;
287
                                default:  ch = ' '; break;
288
                                }
289
                                cprint_name("<%c>", ch);
290
                                break;
291
                        }
292
                } else {
293
                        cprint_tag("%c%p", def_menu ? 't' : ':', menu);
294
                        cprint_name("   ");
295
                }
296
 
297
                cprint_name("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
298
                if (val == yes) {
299
                        if (def_menu) {
300
                                cprint_name(" (%s)", menu_get_prompt(def_menu));
301
                                cprint_name("  --->");
302
                                if (def_menu->list) {
303
                                        indent += 2;
304
                                        build_conf(def_menu);
305
                                        indent -= 2;
306
                                }
307
                        }
308
                        return;
309
                }
310
        } else {
311
                child_count++;
312
                val = sym_get_tristate_value(sym);
313
                if (sym_is_choice_value(sym) && val == yes) {
314
                        cprint_tag(":%p", menu);
315
                        cprint_name("   ");
316
                } else {
317
                        switch (type) {
318
                        case S_BOOLEAN:
319
                                cprint_tag("t%p", menu);
320
                                if (sym_is_changable(sym))
321
                                        cprint_name("[%c]", val == no ? ' ' : '*');
322
                                else
323
                                        cprint_name("---");
324
                                break;
325
                        case S_TRISTATE:
326
                                cprint_tag("t%p", menu);
327
                                switch (val) {
328
                                case yes: ch = '*'; break;
329
                                case mod: ch = 'M'; break;
330
                                default:  ch = ' '; break;
331
                                }
332
                                if (sym_is_changable(sym))
333
                                        cprint_name("<%c>", ch);
334
                                else
335
                                        cprint_name("---");
336
                                break;
337
                        default:
338
                                cprint_tag("s%p", menu);
339
                                tmp = cprint_name("(%s)", sym_get_string_value(sym));
340
                                tmp = indent - tmp + 4;
341
                                if (tmp < 0)
342
                                        tmp = 0;
343
                                cprint_name("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
344
                                        (sym_has_value(sym) || !sym_is_changable(sym)) ?
345
                                        "" : " (NEW)");
346
                                goto conf_childs;
347
                        }
348
                }
349
                cprint_name("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
350
                        (sym_has_value(sym) || !sym_is_changable(sym)) ?
351
                        "" : " (NEW)");
352
                if (menu->prompt->type == P_MENU) {
353
                        cprint_name("  --->");
354
                        return;
355
                }
356
        }
357
 
358
conf_childs:
359
        indent += doint;
360
        for (child = menu->list; child; child = child->next)
361
                build_conf(child);
362
        indent -= doint;
363
}
364
 
365
static void conf(struct menu *menu)
366
{
367
        struct dialog_list_item *active_item = NULL;
368
        struct menu *submenu;
369
        const char *prompt = menu_get_prompt(menu);
370
        struct symbol *sym;
371
        char active_entry[40];
372
        int stat, type;
373
 
374
        unlink("lxdialog.scrltmp");
375
        active_entry[0] = 0;
376
        while (1) {
377
                indent = 0;
378
                child_count = 0;
379
                current_menu = menu;
380
                cdone(); cinit();
381
                build_conf(menu);
382
                if (!child_count)
383
                        break;
384
                if (menu == &rootmenu) {
385
                        cmake(); cprint_tag(":"); cprint_name("--- ");
386
                        cmake(); cprint_tag("L"); cprint_name("Load an Alternate Configuration File");
387
                        cmake(); cprint_tag("S"); cprint_name("Save Configuration to an Alternate File");
388
                }
389
                dialog_clear();
390
                stat = dialog_menu(prompt ? prompt : "Main Menu",
391
                                menu_instructions, rows, cols, rows - 10,
392
                                active_entry, item_no, items);
393
                if (stat < 0)
394
                        return;
395
 
396
                if (stat == 1 || stat == 255)
397
                        break;
398
 
399
                active_item = first_sel_item(item_no, items);
400
                if (!active_item)
401
                        continue;
402
                active_item->selected = 0;
403
                strncpy(active_entry, active_item->tag, sizeof(active_entry));
404
                active_entry[sizeof(active_entry)-1] = 0;
405
                type = active_entry[0];
406
                if (!type)
407
                        continue;
408
 
409
                sym = NULL;
410
                submenu = NULL;
411
                if (sscanf(active_entry + 1, "%p", &submenu) == 1)
412
                        sym = submenu->sym;
413
 
414
                switch (stat) {
415
                case 0:
416
                        switch (type) {
417
                        case 'm':
418
                                if (single_menu_mode)
419
                                        submenu->data = (void *) (long) !submenu->data;
420
                                else
421
                                        conf(submenu);
422
                                break;
423
                        case 't':
424
                                if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
425
                                        conf_choice(submenu);
426
                                else if (submenu->prompt->type == P_MENU)
427
                                        conf(submenu);
428
                                break;
429
                        case 's':
430
                                conf_string(submenu);
431
                                break;
432
                        case 'L':
433
                                conf_load();
434
                                break;
435
                        case 'S':
436
                                conf_save();
437
                                break;
438
                        }
439
                        break;
440
                case 2:
441
                        if (sym)
442
                                show_help(submenu);
443
                        else
444
                                show_readme();
445
                        break;
446
                case 3:
447
                        if (type == 't') {
448
                                if (sym_set_tristate_value(sym, yes))
449
                                        break;
450
                                if (sym_set_tristate_value(sym, mod))
451
                                        show_textbox(NULL, setmod_text, 6, 74);
452
                        }
453
                        break;
454
                case 4:
455
                        if (type == 't')
456
                                sym_set_tristate_value(sym, no);
457
                        break;
458
                case 5:
459
                        if (type == 't')
460
                                sym_set_tristate_value(sym, mod);
461
                        break;
462
                case 6:
463
                        if (type == 't')
464
                                sym_toggle_tristate_value(sym);
465
                        else if (type == 'm')
466
                                conf(submenu);
467
                        break;
468
                }
469
        }
470
}
471
 
472
static void show_textbox(const char *title, const char *text, int r, int c)
473
{
474
        int fd;
475
 
476
        fd = creat(".help.tmp", 0777);
477
        write(fd, text, strlen(text));
478
        close(fd);
479
        while (dialog_textbox(title, ".help.tmp", r, c) < 0)
480
                ;
481
        unlink(".help.tmp");
482
}
483
 
484
static void show_helptext(const char *title, const char *text)
485
{
486
        show_textbox(title, text, rows, cols);
487
}
488
 
489
static void show_help(struct menu *menu)
490
{
491
        const char *help;
492
        char *helptext;
493
        struct symbol *sym = menu->sym;
494
 
495
        help = sym->help;
496
        if (!help)
497
                help = nohelp_text;
498
        if (sym->name) {
499
                helptext = malloc(strlen(sym->name) + strlen(help) + 16);
500
                sprintf(helptext, "%s:\n\n%s", sym->name, help);
501
                show_helptext(menu_get_prompt(menu), helptext);
502
                free(helptext);
503
        } else
504
                show_helptext(menu_get_prompt(menu), help);
505
}
506
 
507
static void show_readme(void)
508
{
509
        show_helptext("Help", top_menu_help);
510
}
511
 
512
static void conf_choice(struct menu *menu)
513
{
514
        const char *prompt = menu_get_prompt(menu);
515
        struct menu *child;
516
        struct symbol *active;
517
 
518
        while (1) {
519
                current_menu = menu;
520
                active = sym_get_choice_value(menu->sym);
521
                cdone(); cinit();
522
                for (child = menu->list; child; child = child->next) {
523
                        if (!menu_is_visible(child))
524
                                continue;
525
                        cmake();
526
                        cprint_tag("%p", child);
527
                        cprint_name("%s", menu_get_prompt(child));
528
                        items[item_no - 1]->selected = (child->sym == active);
529
                }
530
 
531
                switch (dialog_checklist(prompt ? prompt : "Main Menu",
532
                                        radiolist_instructions, 15, 70, 6,
533
                                        item_no, items, FLAG_RADIO)) {
534
                case 0:
535
                        if (sscanf(first_sel_item(item_no, items)->tag, "%p", &menu) != 1)
536
                                break;
537
                        sym_set_tristate_value(menu->sym, yes);
538
                        return;
539
                case 1:
540
                        show_help(menu);
541
                        break;
542
                case 255:
543
                        return;
544
                }
545
        }
546
}
547
 
548
static void conf_string(struct menu *menu)
549
{
550
        const char *prompt = menu_get_prompt(menu);
551
 
552
        while (1) {
553
                char *heading;
554
 
555
                switch (sym_get_type(menu->sym)) {
556
                case S_INT:
557
                        heading = (char *) inputbox_instructions_int;
558
                        break;
559
                case S_HEX:
560
                        heading = (char *) inputbox_instructions_hex;
561
                        break;
562
                case S_STRING:
563
                        heading = (char *) inputbox_instructions_string;
564
                        break;
565
                default:
566
                        heading = "Internal mconf error!";
567
                        /* panic? */;
568
                }
569
 
570
                switch (dialog_inputbox(prompt ? prompt : "Main Menu",
571
                                        heading, 10, 75,
572
                                        sym_get_string_value(menu->sym))) {
573
                case 0:
574
                        if (sym_set_string_value(menu->sym, dialog_input_result))
575
                                return;
576
                        show_textbox(NULL, "You have made an invalid entry.", 5, 43);
577
                        break;
578
                case 1:
579
                        show_help(menu);
580
                        break;
581
                case 255:
582
                        return;
583
                }
584
        }
585
}
586
 
587
static void conf_load(void)
588
{
589
        while (1) {
590
                switch (dialog_inputbox(NULL, load_config_text, 11, 55,
591
                                        filename)) {
592
                case 0:
593
                        if (!dialog_input_result[0])
594
                                return;
595
                        if (!conf_read(dialog_input_result))
596
                                return;
597
                        show_textbox(NULL, "File does not exist!", 5, 38);
598
                        break;
599
                case 1:
600
                        show_helptext("Load Alternate Configuration", load_config_help);
601
                        break;
602
                case 255:
603
                        return;
604
                }
605
        }
606
}
607
 
608
static void conf_save(void)
609
{
610
        while (1) {
611
                switch (dialog_inputbox(NULL, save_config_text, 11, 55,
612
                                        filename)) {
613
                case 0:
614
                        if (!dialog_input_result[0])
615
                                return;
616
                        if (!conf_write(dialog_input_result))
617
                                return;
618
                        show_textbox(NULL, "Can't create file!  Probably a nonexistent directory.", 5, 60);
619
                        break;
620
                case 1:
621
                        show_helptext("Save Alternate Configuration", save_config_help);
622
                        break;
623
                case 255:
624
                        return;
625
                }
626
        }
627
}
628
 
629
static void conf_cleanup(void)
630
{
631
        tcsetattr(1, TCSAFLUSH, &ios_org);
632
        unlink(".help.tmp");
633
}
634
 
635
static void winch_handler(int sig)
636
{
637
        struct winsize ws;
638
 
639
        if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
640
                rows = 24;
641
                cols = 80;
642
        } else {
643
                rows = ws.ws_row;
644
                cols = ws.ws_col;
645
        }
646
 
647
        if (rows < 19 || cols < 80) {
648
                end_dialog();
649
                fprintf(stderr, "Your display is too small to run Menuconfig!\n");
650
                fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
651
                exit(1);
652
        }
653
 
654
        rows -= 4;
655
        cols -= 5;
656
 
657
}
658
 
659
int main(int ac, char **av)
660
{
661
        int stat;
662
        char *mode;
663
        struct symbol *sym;
664
 
665
        conf_parse(av[1]);
666
        conf_read(NULL);
667
 
668
        sym = sym_lookup("VERSION", 0);
669
        sym_calc_value(sym);
670
        snprintf(menu_backtitle, 128, "uClibc v%s Configuration",
671
                sym_get_string_value(sym));
672
 
673
        mode = getenv("MENUCONFIG_MODE");
674
        if (mode) {
675
                if (!strcasecmp(mode, "single_menu"))
676
                        single_menu_mode = 1;
677
        }
678
 
679
        tcgetattr(1, &ios_org);
680
        atexit(conf_cleanup);
681
        init_wsize();
682
        init_dialog();
683
        signal(SIGWINCH, winch_handler);
684
        conf(&rootmenu);
685
        end_dialog();
686
 
687
        /* Restart dialog to act more like when lxdialog was still separate */
688
        init_dialog();
689
        do {
690
                stat = dialog_yesno(NULL,
691
                                "Do you wish to save your new uClibc configuration?", 5, 60);
692
        } while (stat < 0);
693
        end_dialog();
694
 
695
        if (stat == 0) {
696
                conf_write(NULL);
697
                printf("\n\n"
698
                        "*** End of uClibc configuration.\n"
699
                        "*** Check the top-level Makefile for additional configuration options.\n\n");
700
        } else
701
                printf("\n\nYour uClibc configuration changes were NOT saved.\n\n");
702
 
703
        return 0;
704
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.