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

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/trunk/linux/linux-2.4/scripts
    from Rev 1275 to Rev 1765
    Reverse comparison

Rev 1275 → Rev 1765

/README.Menuconfig
0,0 → 1,194
Menuconfig gives the Linux kernel configuration a long needed face
lift. Featuring text based color menus and dialogs, it does not
require X Windows. With this utility you can easily select a kernel
option to modify without sifting through 100 other options.
 
Overview
--------
Some kernel features may be built directly into the kernel.
Some may be made into loadable runtime modules. Some features
may be completely removed altogether. There are also certain
kernel parameters which are not really features, but must be
entered in as decimal or hexadecimal numbers or possibly text.
 
Menu items beginning with [*], <M> or [ ] represent features
configured to be built in, modularized or removed respectively.
Pointed brackets <> represent module capable features.
more...
 
To change any of these features, highlight it with the cursor
keys and press <Y> to build it in, <M> to make it a module or
<N> to removed it. You may also press the <Space Bar> to cycle
through the available options (ie. Y->N->M->Y).
 
Items beginning with numbers or other text within parenthesis can
be changed by highlighting the item and pressing <Enter>. Then
enter the new parameter into the dialog box that pops up.
 
 
Some additional keyboard hints:
 
Menus
----------
o Use the Up/Down arrow keys (cursor keys) to highlight the item
you wish to change or submenu wish to select and press <Enter>.
Submenus are designated by "--->".
 
Shortcut: Press the option's highlighted letter (hotkey).
Pressing a hotkey more than once will sequence
through all visible items which use that hotkey.
 
You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll
unseen options into view.
 
o To exit a menu use the cursor keys to highlight the <Exit> button
and press <ENTER>.
 
Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey
using those letters. You may press a single <ESC>, but
there is a delayed response which you may find annoying.
 
Also, the <TAB> and cursor keys will cycle between <Select>,
<Exit> and <Help>
 
o To get help with an item, use the cursor keys to highlight <Help>
and Press <ENTER>.
 
Shortcut: Press <H> or <?>.
 
 
Radiolists (Choice lists)
-----------
o Use the cursor keys to select the option you wish to set and press
<S> or the <SPACE BAR>.
 
Shortcut: Press the first letter of the option you wish to set then
press <S> or <SPACE BAR>.
 
o To see available help for the item, use the cursor keys to highlight
<Help> and Press <ENTER>.
 
Shortcut: Press <H> or <?>.
 
Also, the <TAB> and cursor keys will cycle between <Select> and
<Help>
 
 
Data Entry
-----------
o Enter the requested information and press <ENTER>
If you are entering hexadecimal values, it is not necessary to
add the '0x' prefix to the entry.
 
o For help, use the <TAB> or cursor keys to highlight the help option
and press <ENTER>. You can try <TAB><H> as well.
 
 
Text Box (Help Window)
--------
o Use the cursor keys to scroll up/down/left/right. The VI editor
keys h,j,k,l function here as do <SPACE BAR> and <B> for those
who are familiar with less and lynx.
 
o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.
 
 
Final Acceptance
----------------
With the exception of the old style sound configuration,
YOUR CHANGES ARE NOT FINAL. You will be given a last chance to
confirm them prior to exiting Menuconfig.
 
If Menuconfig quits with an error while saving your configuration,
you may look in the file /usr/src/linux/.menuconfig.log for
information which may help you determine the cause.
 
Alternate Configuration Files
-----------------------------
Menuconfig supports the use of alternate configuration files for
those who, for various reasons, find it necessary to switch
between different kernel configurations.
 
At the end of the main menu you will find two options. One is
for saving the current configuration to a file of your choosing.
The other option is for loading a previously saved alternate
configuration.
 
Even if you don't use alternate configuration files, but you
find during a Menuconfig session that you have completely messed
up your settings, you may use the "Load Alternate..." option to
restore your previously saved settings from ".config" without
restarting Menuconfig.
 
Other information
-----------------
The windowing utility, lxdialog, will only be rebuilt if your kernel
source tree is fresh, or changes are patched into it via a kernel
patch or you do 'make mrproper'. If changes to lxdialog are patched
in, most likely the rebuild time will be short. You may force a
complete rebuild of lxdialog by changing to it's directory and doing
'make clean all'
 
If you use Menuconfig in an XTERM window make sure you have your
$TERM variable set to point to a xterm definition which supports color.
Otherwise, Menuconfig will look rather bad. Menuconfig will not
display correctly in a RXVT window because rxvt displays only one
intensity of color, bright.
 
Menuconfig will display larger menus on screens or xterms which are
set to display more than the standard 25 row by 80 column geometry.
In order for this to work, the "stty size" command must be able to
display the screen's current row and column geometry. I STRONGLY
RECOMMEND that you make sure you do NOT have the shell variables
LINES and COLUMNS exported into your environment. Some distributions
export those variables via /etc/profile. Some ncurses programs can
become confused when those variables (LINES & COLUMNS) don't reflect
the true screen size.
 
 
NOTICE: lxdialog requires the ncurses libraries to compile. If you
don't already have ncurses you really should get it.
 
The makefile for lxdialog attempts to find your ncurses
header file. Although it should find the header for older
versions of ncurses, it is probably a good idea to get the
latest ncurses anyway.
 
If you have upgraded your ncurses libraries, MAKE SURE you
remove the old ncurses header files. If you don't you
will most certainly get a segmentation fault.
 
WARNING: It is not recommended that you change any defines in
lxdialog's header files. If you have a grayscale display and
are brave, you may tinker with color.h to tune the colors to
your preference.
 
COMPATIBILITY ISSUE:
There have been some compatibility problems reported with
older versions of bash and sed. I am trying to work these
out but it is preferable that you upgrade those utilities.
 
 
******** IMPORTANT, OPTIONAL ALTERNATE PERSONALITY AVAILABLE ********
******** ********
If you prefer to have all of the kernel options listed in a single
menu, rather than the default multimenu hierarchy, you may edit the
Menuconfig script and change the line "single_menu_mode=" to
"single_menu_mode=TRUE".
 
This mode is not recommended unless you have a fairly fast machine.
*********************************************************************
 
 
Propaganda
----------
The windowing support utility (lxdialog) is a VERY modified version of
the dialog utility by Savio Lam <lam836@cs.cuhk.hk>. Although lxdialog
is significantly different from dialog, I have left Savio's copyrights
intact. Please DO NOT contact Savio with questions about lxdialog.
He will not be able to assist.
 
William Roadcap was the original author of Menuconfig.
Michael Elizabeth Chastain <mec@shout.net> is the current maintainer.
 
<END OF FILE>
/mkuboot.sh
0,0 → 1,16
#!/bin/bash
 
#
# Build U-Boot image when `mkimage' tool is available.
#
 
MKIMAGE=$(type -path mkimage)
 
if [ -z "${MKIMAGE}" ]; then
# Doesn't exist
echo '"mkimage" command not found - U-Boot images will not be built' >&2
exit 0;
fi
 
# Call "mkimage" to create U-Boot image
${MKIMAGE} "$@"
/split-include.c
0,0 → 1,226
/*
* split-include.c
*
* Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
* This is a C version of syncdep.pl by Werner Almesberger.
*
* This program takes autoconf.h as input and outputs a directory full
* of one-line include files, merging onto the old values.
*
* Think of the configuration options as key-value pairs. Then there
* are five cases:
*
* key old value new value action
*
* KEY-1 VALUE-1 VALUE-1 leave file alone
* KEY-2 VALUE-2A VALUE-2B write VALUE-2B into file
* KEY-3 - VALUE-3 write VALUE-3 into file
* KEY-4 VALUE-4 - write an empty file
* KEY-5 (empty) - leave old empty file alone
*/
 
#include <sys/types.h>
#include <sys/stat.h>
 
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#define ERROR_EXIT(strExit) \
{ \
const int errnoSave = errno; \
fprintf(stderr, "%s: ", str_my_name); \
errno = errnoSave; \
perror((strExit)); \
exit(1); \
}
 
 
 
int main(int argc, const char * argv [])
{
const char * str_my_name;
const char * str_file_autoconf;
const char * str_dir_config;
 
FILE * fp_config;
FILE * fp_target;
FILE * fp_find;
 
int buffer_size;
 
char * line;
char * old_line;
char * list_target;
char * ptarget;
 
struct stat stat_buf;
 
/* Check arg count. */
if (argc != 3)
{
fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]);
exit(1);
}
 
str_my_name = argv[0];
str_file_autoconf = argv[1];
str_dir_config = argv[2];
 
/* Find a buffer size. */
if (stat(str_file_autoconf, &stat_buf) != 0)
ERROR_EXIT(str_file_autoconf);
buffer_size = 2 * stat_buf.st_size + 4096;
 
/* Allocate buffers. */
if ( (line = malloc(buffer_size)) == NULL
|| (old_line = malloc(buffer_size)) == NULL
|| (list_target = malloc(buffer_size)) == NULL )
ERROR_EXIT(str_file_autoconf);
 
/* Open autoconfig file. */
if ((fp_config = fopen(str_file_autoconf, "r")) == NULL)
ERROR_EXIT(str_file_autoconf);
 
/* Make output directory if needed. */
if (stat(str_dir_config, &stat_buf) != 0)
{
if (mkdir(str_dir_config, 0755) != 0)
ERROR_EXIT(str_dir_config);
}
 
/* Change to output directory. */
if (chdir(str_dir_config) != 0)
ERROR_EXIT(str_dir_config);
/* Put initial separator into target list. */
ptarget = list_target;
*ptarget++ = '\n';
 
/* Read config lines. */
while (fgets(line, buffer_size, fp_config))
{
const char * str_config;
int is_same;
int itarget;
 
if (line[0] != '#')
continue;
if ((str_config = strstr(line, "CONFIG_")) == NULL)
continue;
 
/* Make the output file name. */
str_config += sizeof("CONFIG_") - 1;
for (itarget = 0; !isspace((int)str_config[itarget]); itarget++)
{
char c = str_config[itarget];
if (isupper((int)c)) c = tolower((int)c);
if (c == '_') c = '/';
ptarget[itarget] = c;
}
ptarget[itarget++] = '.';
ptarget[itarget++] = 'h';
ptarget[itarget++] = '\0';
 
/* Check for existing file. */
is_same = 0;
if ((fp_target = fopen(ptarget, "r")) != NULL)
{
fgets(old_line, buffer_size, fp_target);
if (fclose(fp_target) != 0)
ERROR_EXIT(ptarget);
if (!strcmp(line, old_line))
is_same = 1;
}
 
if (!is_same)
{
/* Auto-create directories. */
int islash;
for (islash = 0; islash < itarget; islash++)
{
if (ptarget[islash] == '/')
{
ptarget[islash] = '\0';
if (stat(ptarget, &stat_buf) != 0
&& mkdir(ptarget, 0755) != 0)
ERROR_EXIT( ptarget );
ptarget[islash] = '/';
}
}
 
/* Write the file. */
if ((fp_target = fopen(ptarget, "w" )) == NULL)
ERROR_EXIT(ptarget);
fputs(line, fp_target);
if (ferror(fp_target) || fclose(fp_target) != 0)
ERROR_EXIT(ptarget);
}
 
/* Update target list */
ptarget += itarget;
*(ptarget-1) = '\n';
}
 
/*
* Close autoconfig file.
* Terminate the target list.
*/
if (fclose(fp_config) != 0)
ERROR_EXIT(str_file_autoconf);
*ptarget = '\0';
 
/*
* Fix up existing files which have no new value.
* This is Case 4 and Case 5.
*
* I re-read the tree and filter it against list_target.
* This is crude. But it avoids data copies. Also, list_target
* is compact and contiguous, so it easily fits into cache.
*
* Notice that list_target contains strings separated by \n,
* with a \n before the first string and after the last.
* fgets gives the incoming names a terminating \n.
* So by having an initial \n, strstr will find exact matches.
*/
 
fp_find = popen("find * -type f -name \"*.h\" -print", "r");
if (fp_find == 0)
ERROR_EXIT( "find" );
 
line[0] = '\n';
while (fgets(line+1, buffer_size, fp_find))
{
if (strstr(list_target, line) == NULL)
{
/*
* This is an old file with no CONFIG_* flag in autoconf.h.
*/
 
/* First strip the \n. */
line[strlen(line)-1] = '\0';
 
/* Grab size. */
if (stat(line+1, &stat_buf) != 0)
ERROR_EXIT(line);
 
/* If file is not empty, make it empty and give it a fresh date. */
if (stat_buf.st_size != 0)
{
if ((fp_target = fopen(line+1, "w")) == NULL)
ERROR_EXIT(line);
if (fclose(fp_target) != 0)
ERROR_EXIT(line);
}
}
}
 
if (pclose(fp_find) != 0)
ERROR_EXIT("find");
 
return 0;
}
/pathdown.sh
0,0 → 1,13
#!/bin/sh
UP=
DN=${PWD:?}
TP=${TOPDIR:?}
 
while [ ! $TP/$UP/. -ef $DN ] ;do
UP=`basename $PWD`/$UP
cd ..
if [ "$PWD" = "/" ]; then echo "Lost"; exit 1; fi
done
 
echo $UP
exit 0
/makelst
0,0 → 1,22
#!/bin/bash
# A script to dump mixed source code & assembly
# with correct relocations from System.map
# Requires the following lines in Rules.make.
# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
# William Stearns <wstearns@pobox.com>
#%.lst: %.c
# $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $<
# $(TOPDIR)/scripts/makelst $* $(TOPDIR) $(OBJDUMP)
#
# Copyright (C) 2000 IBM Corporation
# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
#
 
t1=`$3 --syms $2/$1.o | grep .text | grep " F " | head -n 1`
t2=`echo $t1 | gawk '{ print $6 }'`
t3=`grep $t2 $2/System.map`
t4=`echo $t3 | gawk '{ print $1 }'`
t5=`echo $t1 | gawk '{ print $1 }'`
t6=`echo $t4 - $t5 | sed -e s/a/A/g -e s/b/B/g -e s/c/C/g -e s/d/D/g -e s/e/E/g -e s/f/F/g`
t7=`( echo ibase=16 ; echo $t6 ) | bc`
$3 --source --adjust-vma=$t7 $2/$1.o > $2/$1.lst
/extract-ikconfig
0,0 → 1,17
#! /bin/bash -x
# extracts .config info from a [b]zImage file
# uses: binoffset (new), dd, zcat, strings, grep
# $arg1 is [b]zImage filename
 
HDR=`binoffset $1 0x1f 0x8b 0x08 0x0`
PID=$$
TMPFILE="$1.vmlin.$PID"
 
# dd if=$1 bs=1 skip=$HDR | zcat - | strings /dev/stdin \
# | grep "[A-Za-z_0-9]=[ynm]$" | sed "s/^/CONFIG_/" > $1.oldconfig.$PID
# exit
 
dd if=$1 bs=1 skip=$HDR | zcat - > $TMPFILE
strings $TMPFILE | grep "^[\#[:blank:]]*CONFIG_[A-Za-z_0-9]*" > $1.oldconfig.$PID
wc $1.oldconfig.$PID
rm $TMPFILE
/lxdialog/msgbox.c
0,0 → 1,85
/*
* msgbox.c -- implements the message box and info box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#include "dialog.h"
 
/*
* Display a message box. Program will pause and display an "OK" button
* if the parameter 'pause' is non-zero.
*/
int
dialog_msgbox (const char *title, const char *prompt, int height, int width,
int pause)
{
int i, x, y, key = 0;
WINDOW *dialog;
 
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
 
draw_shadow (stdscr, y, x, height, width);
 
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
 
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
 
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
 
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 2);
 
if (pause) {
wattrset (dialog, border_attr);
mvwaddch (dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
 
print_button (dialog, " Ok ",
height - 2, width / 2 - 4, TRUE);
 
wrefresh (dialog);
while (key != ESC && key != '\n' && key != ' ' &&
key != 'O' && key != 'o' && key != 'X' && key != 'x')
key = wgetch (dialog);
} else {
key = '\n';
wrefresh (dialog);
}
 
delwin (dialog);
return key == ESC ? -1 : 0;
}
/lxdialog/lxdialog.c
0,0 → 1,226
/*
* dialog - Display simple dialog boxes from shell scripts
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#include "dialog.h"
 
static void Usage (const char *name);
 
typedef int (jumperFn) (const char *title, int argc, const char * const * argv);
 
struct Mode {
char *name;
int argmin, argmax, argmod;
jumperFn *jumper;
};
 
jumperFn j_menu, j_checklist, j_radiolist, j_yesno, j_textbox, j_inputbox;
jumperFn j_msgbox, j_infobox;
 
static struct Mode modes[] =
{
{"--menu", 9, 0, 3, j_menu},
{"--checklist", 9, 0, 3, j_checklist},
{"--radiolist", 9, 0, 3, j_radiolist},
{"--yesno", 5,5,1, j_yesno},
{"--textbox", 5,5,1, j_textbox},
{"--inputbox", 5, 6, 1, j_inputbox},
{"--msgbox", 5, 5, 1, j_msgbox},
{"--infobox", 5, 5, 1, j_infobox},
{NULL, 0, 0, 0, NULL}
};
 
static struct Mode *modePtr;
 
#ifdef LOCALE
#include <locale.h>
#endif
 
int
main (int argc, const char * const * argv)
{
int offset = 0, clear_screen = 0, end_common_opts = 0, retval;
const char *title = NULL;
 
#ifdef LOCALE
(void) setlocale (LC_ALL, "");
#endif
 
#ifdef TRACE
trace(TRACE_CALLS|TRACE_UPDATE);
#endif
if (argc < 2) {
Usage (argv[0]);
exit (-1);
}
 
while (offset < argc - 1 && !end_common_opts) { /* Common options */
if (!strcmp (argv[offset + 1], "--title")) {
if (argc - offset < 3 || title != NULL) {
Usage (argv[0]);
exit (-1);
} else {
title = argv[offset + 2];
offset += 2;
}
} else if (!strcmp (argv[offset + 1], "--backtitle")) {
if (backtitle != NULL) {
Usage (argv[0]);
exit (-1);
} else {
backtitle = argv[offset + 2];
offset += 2;
}
} else if (!strcmp (argv[offset + 1], "--clear")) {
if (clear_screen) { /* Hey, "--clear" can't appear twice! */
Usage (argv[0]);
exit (-1);
} else if (argc == 2) { /* we only want to clear the screen */
init_dialog ();
refresh (); /* init_dialog() will clear the screen for us */
end_dialog ();
return 0;
} else {
clear_screen = 1;
offset++;
}
} else /* no more common options */
end_common_opts = 1;
}
 
if (argc - 1 == offset) { /* no more options */
Usage (argv[0]);
exit (-1);
}
/* use a table to look for the requested mode, to avoid code duplication */
 
for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
if (!strcmp (argv[offset + 1], modePtr->name))
break;
 
if (!modePtr->name)
Usage (argv[0]);
if (argc - offset < modePtr->argmin)
Usage (argv[0]);
if (modePtr->argmax && argc - offset > modePtr->argmax)
Usage (argv[0]);
 
 
 
init_dialog ();
retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
 
if (clear_screen) { /* clear screen before exit */
attr_clear (stdscr, LINES, COLS, screen_attr);
refresh ();
}
end_dialog();
 
exit (retval);
}
 
/*
* Print program usage
*/
static void
Usage (const char *name)
{
fprintf (stderr, "\
\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
\n modified/gutted for use as a Linux kernel config tool by \
\n William Roadcap (roadcapw@cfw.com)\
\n\
\n* Display dialog boxes from shell scripts *\
\n\
\nUsage: %s --clear\
\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
\n\
\nBox options:\
\n\
\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
\n --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
\n --textbox <file> <height> <width>\
\n --inputbox <text> <height> <width> [<init>]\
\n --yesno <text> <height> <width>\
\n", name, name);
exit (-1);
}
 
/*
* These are the program jumpers
*/
 
int
j_menu (const char *t, int ac, const char * const * av)
{
return dialog_menu (t, av[2], atoi (av[3]), atoi (av[4]),
atoi (av[5]), av[6], (ac - 6) / 2, av + 7);
}
 
int
j_checklist (const char *t, int ac, const char * const * av)
{
return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_CHECK);
}
 
int
j_radiolist (const char *t, int ac, const char * const * av)
{
return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_RADIO);
}
 
int
j_textbox (const char *t, int ac, const char * const * av)
{
return dialog_textbox (t, av[2], atoi (av[3]), atoi (av[4]));
}
 
int
j_yesno (const char *t, int ac, const char * const * av)
{
return dialog_yesno (t, av[2], atoi (av[3]), atoi (av[4]));
}
 
int
j_inputbox (const char *t, int ac, const char * const * av)
{
int ret = dialog_inputbox (t, av[2], atoi (av[3]), atoi (av[4]),
ac == 6 ? av[5] : (char *) NULL);
if (ret == 0)
fprintf(stderr, dialog_input_result);
return ret;
}
 
int
j_msgbox (const char *t, int ac, const char * const * av)
{
return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 1);
}
 
int
j_infobox (const char *t, int ac, const char * const * av)
{
return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 0);
}
 
/lxdialog/dialog.h
0,0 → 1,184
 
/*
* dialog.h -- common declarations for all dialog modules
*
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
 
#include CURSES_LOC
 
/*
* Colors in ncurses 1.9.9e do not work properly since foreground and
* background colors are OR'd rather than separately masked. This version
* of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
* with standard curses. The simplest fix (to make this work with standard
* curses) uses the wbkgdset() function, not used in the original hack.
* Turn it off if we're building with 1.9.9e, since it just confuses things.
*/
#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
#define OLD_NCURSES 1
#undef wbkgdset
#define wbkgdset(w,p) /*nothing*/
#else
#define OLD_NCURSES 0
#endif
 
#define TR(params) _tracef params
 
#define ESC 27
#define TAB 9
#define MAX_LEN 2048
#define BUF_SIZE (10*1024)
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
 
 
#ifndef ACS_ULCORNER
#define ACS_ULCORNER '+'
#endif
#ifndef ACS_LLCORNER
#define ACS_LLCORNER '+'
#endif
#ifndef ACS_URCORNER
#define ACS_URCORNER '+'
#endif
#ifndef ACS_LRCORNER
#define ACS_LRCORNER '+'
#endif
#ifndef ACS_HLINE
#define ACS_HLINE '-'
#endif
#ifndef ACS_VLINE
#define ACS_VLINE '|'
#endif
#ifndef ACS_LTEE
#define ACS_LTEE '+'
#endif
#ifndef ACS_RTEE
#define ACS_RTEE '+'
#endif
#ifndef ACS_UARROW
#define ACS_UARROW '^'
#endif
#ifndef ACS_DARROW
#define ACS_DARROW 'v'
#endif
 
/*
* Attribute names
*/
#define screen_attr attributes[0]
#define shadow_attr attributes[1]
#define dialog_attr attributes[2]
#define title_attr attributes[3]
#define border_attr attributes[4]
#define button_active_attr attributes[5]
#define button_inactive_attr attributes[6]
#define button_key_active_attr attributes[7]
#define button_key_inactive_attr attributes[8]
#define button_label_active_attr attributes[9]
#define button_label_inactive_attr attributes[10]
#define inputbox_attr attributes[11]
#define inputbox_border_attr attributes[12]
#define searchbox_attr attributes[13]
#define searchbox_title_attr attributes[14]
#define searchbox_border_attr attributes[15]
#define position_indicator_attr attributes[16]
#define menubox_attr attributes[17]
#define menubox_border_attr attributes[18]
#define item_attr attributes[19]
#define item_selected_attr attributes[20]
#define tag_attr attributes[21]
#define tag_selected_attr attributes[22]
#define tag_key_attr attributes[23]
#define tag_key_selected_attr attributes[24]
#define check_attr attributes[25]
#define check_selected_attr attributes[26]
#define uarrow_attr attributes[27]
#define darrow_attr attributes[28]
 
/* number of attributes */
#define ATTRIBUTE_COUNT 29
 
/*
* Global variables
*/
extern bool use_colors;
extern bool use_shadow;
 
extern chtype attributes[];
 
extern const char *backtitle;
 
/*
* Function prototypes
*/
extern void create_rc (const char *filename);
extern int parse_rc (void);
 
 
void init_dialog (void);
void end_dialog (void);
void attr_clear (WINDOW * win, int height, int width, chtype attr);
void dialog_clear (void);
void color_setup (void);
void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x);
void print_button (WINDOW * win, const char *label, int y, int x, int selected);
void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box,
chtype border);
void draw_shadow (WINDOW * win, int y, int x, int height, int width);
 
int first_alpha (const char *string, const char *exempt);
int dialog_yesno (const char *title, const char *prompt, int height, int width);
int dialog_msgbox (const char *title, const char *prompt, int height,
int width, int pause);
int dialog_textbox (const char *title, const char *file, int height, int width);
int dialog_menu (const char *title, const char *prompt, int height, int width,
int menu_height, const char *choice, int item_no,
const char * const * items);
int dialog_checklist (const char *title, const char *prompt, int height,
int width, int list_height, int item_no,
const char * const * items, int flag);
extern unsigned char dialog_input_result[];
int dialog_inputbox (const char *title, const char *prompt, int height,
int width, const char *init);
 
/*
* This is the base for fictitious keys, which activate
* the buttons.
*
* Mouse-generated keys are the following:
* -- the first 32 are used as numbers, in addition to '0'-'9'
* -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
* -- uppercase chars are used to invoke the button (M_EVENT + 'O')
*/
#define M_EVENT (KEY_MAX+1)
 
 
/*
* The `flag' parameter in checklist is used to select between
* radiolist and checklist
*/
#define FLAG_CHECK 1
#define FLAG_RADIO 0
/lxdialog/colors.h
0,0 → 1,161
/*
* colors.h -- color attribute definitions
*
* AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
 
/*
* Default color definitions
*
* *_FG = foreground
* *_BG = background
* *_HL = highlight?
*/
#define SCREEN_FG COLOR_CYAN
#define SCREEN_BG COLOR_BLUE
#define SCREEN_HL TRUE
 
#define SHADOW_FG COLOR_BLACK
#define SHADOW_BG COLOR_BLACK
#define SHADOW_HL TRUE
 
#define DIALOG_FG COLOR_BLACK
#define DIALOG_BG COLOR_WHITE
#define DIALOG_HL FALSE
 
#define TITLE_FG COLOR_YELLOW
#define TITLE_BG COLOR_WHITE
#define TITLE_HL TRUE
 
#define BORDER_FG COLOR_WHITE
#define BORDER_BG COLOR_WHITE
#define BORDER_HL TRUE
 
#define BUTTON_ACTIVE_FG COLOR_WHITE
#define BUTTON_ACTIVE_BG COLOR_BLUE
#define BUTTON_ACTIVE_HL TRUE
 
#define BUTTON_INACTIVE_FG COLOR_BLACK
#define BUTTON_INACTIVE_BG COLOR_WHITE
#define BUTTON_INACTIVE_HL FALSE
 
#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE
#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE
#define BUTTON_KEY_ACTIVE_HL TRUE
 
#define BUTTON_KEY_INACTIVE_FG COLOR_RED
#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE
#define BUTTON_KEY_INACTIVE_HL FALSE
 
#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW
#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE
#define BUTTON_LABEL_ACTIVE_HL TRUE
 
#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK
#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE
#define BUTTON_LABEL_INACTIVE_HL TRUE
 
#define INPUTBOX_FG COLOR_BLACK
#define INPUTBOX_BG COLOR_WHITE
#define INPUTBOX_HL FALSE
 
#define INPUTBOX_BORDER_FG COLOR_BLACK
#define INPUTBOX_BORDER_BG COLOR_WHITE
#define INPUTBOX_BORDER_HL FALSE
 
#define SEARCHBOX_FG COLOR_BLACK
#define SEARCHBOX_BG COLOR_WHITE
#define SEARCHBOX_HL FALSE
 
#define SEARCHBOX_TITLE_FG COLOR_YELLOW
#define SEARCHBOX_TITLE_BG COLOR_WHITE
#define SEARCHBOX_TITLE_HL TRUE
 
#define SEARCHBOX_BORDER_FG COLOR_WHITE
#define SEARCHBOX_BORDER_BG COLOR_WHITE
#define SEARCHBOX_BORDER_HL TRUE
 
#define POSITION_INDICATOR_FG COLOR_YELLOW
#define POSITION_INDICATOR_BG COLOR_WHITE
#define POSITION_INDICATOR_HL TRUE
 
#define MENUBOX_FG COLOR_BLACK
#define MENUBOX_BG COLOR_WHITE
#define MENUBOX_HL FALSE
 
#define MENUBOX_BORDER_FG COLOR_WHITE
#define MENUBOX_BORDER_BG COLOR_WHITE
#define MENUBOX_BORDER_HL TRUE
 
#define ITEM_FG COLOR_BLACK
#define ITEM_BG COLOR_WHITE
#define ITEM_HL FALSE
 
#define ITEM_SELECTED_FG COLOR_WHITE
#define ITEM_SELECTED_BG COLOR_BLUE
#define ITEM_SELECTED_HL TRUE
 
#define TAG_FG COLOR_YELLOW
#define TAG_BG COLOR_WHITE
#define TAG_HL TRUE
 
#define TAG_SELECTED_FG COLOR_YELLOW
#define TAG_SELECTED_BG COLOR_BLUE
#define TAG_SELECTED_HL TRUE
 
#define TAG_KEY_FG COLOR_YELLOW
#define TAG_KEY_BG COLOR_WHITE
#define TAG_KEY_HL TRUE
 
#define TAG_KEY_SELECTED_FG COLOR_YELLOW
#define TAG_KEY_SELECTED_BG COLOR_BLUE
#define TAG_KEY_SELECTED_HL TRUE
 
#define CHECK_FG COLOR_BLACK
#define CHECK_BG COLOR_WHITE
#define CHECK_HL FALSE
 
#define CHECK_SELECTED_FG COLOR_WHITE
#define CHECK_SELECTED_BG COLOR_BLUE
#define CHECK_SELECTED_HL TRUE
 
#define UARROW_FG COLOR_GREEN
#define UARROW_BG COLOR_WHITE
#define UARROW_HL TRUE
 
#define DARROW_FG COLOR_GREEN
#define DARROW_BG COLOR_WHITE
#define DARROW_HL TRUE
 
/* End of default color definitions */
 
#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
#define COLOR_NAME_LEN 10
#define COLOR_COUNT 8
 
/*
* Global variables
*/
 
typedef struct {
char name[COLOR_NAME_LEN];
int value;
} color_names_st;
 
extern color_names_st color_names[];
extern int color_table[][3];
/lxdialog/inputbox.c
0,0 → 1,240
/*
* inputbox.c -- implements the input box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#include "dialog.h"
 
unsigned char dialog_input_result[MAX_LEN + 1];
 
/*
* Print the termination buttons
*/
static void
print_buttons(WINDOW *dialog, int height, int width, int selected)
{
int x = width / 2 - 11;
int y = height - 2;
 
print_button (dialog, " Ok ", y, x, selected==0);
print_button (dialog, " Help ", y, x + 14, selected==1);
 
wmove(dialog, y, x+1+14*selected);
wrefresh(dialog);
}
 
/*
* Display a dialog box for inputing a string
*/
int
dialog_inputbox (const char *title, const char *prompt, int height, int width,
const char *init)
{
int i, x, y, box_y, box_x, box_width;
int input_x = 0, scroll = 0, key = 0, button = -1;
unsigned char *instr = dialog_input_result;
WINDOW *dialog;
 
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
 
 
draw_shadow (stdscr, y, x, height, width);
 
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
 
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
 
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
 
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
 
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
 
/* Draw the input field box */
box_width = width - 6;
getyx (dialog, y, x);
box_y = y + 2;
box_x = (width - box_width) / 2;
draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2,
border_attr, dialog_attr);
 
print_buttons(dialog, height, width, 0);
 
/* Set up the initial value */
wmove (dialog, box_y, box_x);
wattrset (dialog, inputbox_attr);
 
if (!init)
instr[0] = '\0';
else
strcpy (instr, init);
 
input_x = strlen (instr);
 
if (input_x >= box_width) {
scroll = input_x - box_width + 1;
input_x = box_width - 1;
for (i = 0; i < box_width - 1; i++)
waddch (dialog, instr[scroll + i]);
} else
waddstr (dialog, instr);
 
wmove (dialog, box_y, box_x + input_x);
 
wrefresh (dialog);
 
while (key != ESC) {
key = wgetch (dialog);
 
if (button == -1) { /* Input box selected */
switch (key) {
case TAB:
case KEY_UP:
case KEY_DOWN:
break;
case KEY_LEFT:
continue;
case KEY_RIGHT:
continue;
case KEY_BACKSPACE:
case 127:
if (input_x || scroll) {
wattrset (dialog, inputbox_attr);
if (!input_x) {
scroll = scroll < box_width - 1 ?
0 : scroll - (box_width - 1);
wmove (dialog, box_y, box_x);
for (i = 0; i < box_width; i++)
waddch (dialog, instr[scroll + input_x + i] ?
instr[scroll + input_x + i] : ' ');
input_x = strlen (instr) - scroll;
} else
input_x--;
instr[scroll + input_x] = '\0';
mvwaddch (dialog, box_y, input_x + box_x, ' ');
wmove (dialog, box_y, input_x + box_x);
wrefresh (dialog);
}
continue;
default:
if (key < 0x100 && isprint (key)) {
if (scroll + input_x < MAX_LEN) {
wattrset (dialog, inputbox_attr);
instr[scroll + input_x] = key;
instr[scroll + input_x + 1] = '\0';
if (input_x == box_width - 1) {
scroll++;
wmove (dialog, box_y, box_x);
for (i = 0; i < box_width - 1; i++)
waddch (dialog, instr[scroll + i]);
} else {
wmove (dialog, box_y, input_x++ + box_x);
waddch (dialog, key);
}
wrefresh (dialog);
} else
flash (); /* Alarm user about overflow */
continue;
}
}
}
switch (key) {
case 'O':
case 'o':
delwin (dialog);
return 0;
case 'H':
case 'h':
delwin (dialog);
return 1;
case KEY_UP:
case KEY_LEFT:
switch (button) {
case -1:
button = 1; /* Indicates "Cancel" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 0:
button = -1; /* Indicates input box is selected */
print_buttons(dialog, height, width, 0);
wmove (dialog, box_y, box_x + input_x);
wrefresh (dialog);
break;
case 1:
button = 0; /* Indicates "OK" button is selected */
print_buttons(dialog, height, width, 0);
break;
}
break;
case TAB:
case KEY_DOWN:
case KEY_RIGHT:
switch (button) {
case -1:
button = 0; /* Indicates "OK" button is selected */
print_buttons(dialog, height, width, 0);
break;
case 0:
button = 1; /* Indicates "Cancel" button is selected */
print_buttons(dialog, height, width, 1);
break;
case 1:
button = -1; /* Indicates input box is selected */
print_buttons(dialog, height, width, 0);
wmove (dialog, box_y, box_x + input_x);
wrefresh (dialog);
break;
}
break;
case ' ':
case '\n':
delwin (dialog);
return (button == -1 ? 0 : button);
case 'X':
case 'x':
key = ESC;
case ESC:
break;
}
}
 
delwin (dialog);
return -1; /* ESC pressed */
}
/lxdialog/checklist.c
0,0 → 1,369
/*
* checklist.c -- implements the checklist box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
* Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#include "dialog.h"
 
static int list_width, check_x, item_x, checkflag;
 
/*
* Print list item
*/
static void
print_item (WINDOW * win, const char *item, int status,
int choice, int selected)
{
int i;
 
/* Clear 'residue' of last item */
wattrset (win, menubox_attr);
wmove (win, choice, 0);
for (i = 0; i < list_width; i++)
waddch (win, ' ');
 
wmove (win, choice, check_x);
wattrset (win, selected ? check_selected_attr : check_attr);
if (checkflag == FLAG_CHECK)
wprintw (win, "[%c]", status ? 'X' : ' ');
else
wprintw (win, "(%c)", status ? 'X' : ' ');
 
wattrset (win, selected ? tag_selected_attr : tag_attr);
mvwaddch(win, choice, item_x, item[0]);
wattrset (win, selected ? item_selected_attr : item_attr);
waddstr (win, (char *)item+1);
if (selected) {
wmove (win, choice, check_x+1);
wrefresh (win);
}
}
 
/*
* Print the scroll indicators.
*/
static void
print_arrows (WINDOW * win, int choice, int item_no, int scroll,
int y, int x, int height)
{
wmove(win, y, x);
 
if (scroll > 0) {
wattrset (win, uarrow_attr);
waddch (win, ACS_UARROW);
waddstr (win, "(-)");
}
else {
wattrset (win, menubox_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
 
y = y + height + 1;
wmove(win, y, x);
 
if ((height < item_no) && (scroll + choice < item_no - 1)) {
wattrset (win, darrow_attr);
waddch (win, ACS_DARROW);
waddstr (win, "(+)");
}
else {
wattrset (win, menubox_border_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
}
 
/*
* Display the termination buttons
*/
static void
print_buttons( WINDOW *dialog, int height, int width, int selected)
{
int x = width / 2 - 11;
int y = height - 2;
 
print_button (dialog, "Select", y, x, selected == 0);
print_button (dialog, " Help ", y, x + 14, selected == 1);
 
wmove(dialog, y, x+1 + 14*selected);
wrefresh (dialog);
}
 
/*
* Display a dialog box with a list of options that can be turned on or off
* The `flag' parameter is used to select between radiolist and checklist.
*/
int
dialog_checklist (const char *title, const char *prompt, int height, int width,
int list_height, int item_no, const char * const * items, int flag)
{
int i, x, y, box_x, box_y;
int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
WINDOW *dialog, *list;
 
checkflag = flag;
 
/* Allocate space for storing item on/off status */
if ((status = malloc (sizeof (int) * item_no)) == NULL) {
endwin ();
fprintf (stderr,
"\nCan't allocate memory in dialog_checklist().\n");
exit (-1);
}
 
/* Initializes status */
for (i = 0; i < item_no; i++) {
status[i] = !strcasecmp (items[i * 3 + 2], "on");
if (!choice && status[i])
choice = i;
}
 
max_choice = MIN (list_height, item_no);
 
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
 
draw_shadow (stdscr, y, x, height, width);
 
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
 
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
 
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
 
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
 
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
 
list_width = width - 6;
box_y = height - list_height - 5;
box_x = (width - list_width) / 2 - 1;
 
/* create new window for the list */
list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1);
 
keypad (list, TRUE);
 
/* draw a box around the list items */
draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2,
menubox_border_attr, menubox_attr);
 
/* Find length of longest item in order to center checklist */
check_x = 0;
for (i = 0; i < item_no; i++)
check_x = MAX (check_x, + strlen (items[i * 3 + 1]) + 4);
 
check_x = (list_width - check_x) / 2;
item_x = check_x + 4;
 
if (choice >= list_height) {
scroll = choice - list_height + 1;
choice -= scroll;
}
 
/* Print the list */
for (i = 0; i < max_choice; i++) {
print_item (list, items[(scroll+i) * 3 + 1],
status[i+scroll], i, i == choice);
}
 
print_arrows(dialog, choice, item_no, scroll,
box_y, box_x + check_x + 5, list_height);
 
print_buttons(dialog, height, width, 0);
 
wnoutrefresh (list);
wnoutrefresh (dialog);
doupdate ();
 
while (key != ESC) {
key = wgetch (dialog);
 
for (i = 0; i < max_choice; i++)
if (toupper(key) == toupper(items[(scroll+i)*3+1][0]))
break;
 
 
if ( i < max_choice || key == KEY_UP || key == KEY_DOWN ||
key == '+' || key == '-' ) {
if (key == KEY_UP || key == '-') {
if (!choice) {
if (!scroll)
continue;
/* Scroll list down */
if (list_height > 1) {
/* De-highlight current first item */
print_item (list, items[scroll * 3 + 1],
status[scroll], 0, FALSE);
scrollok (list, TRUE);
wscrl (list, -1);
scrollok (list, FALSE);
}
scroll--;
print_item (list, items[scroll * 3 + 1],
status[scroll], 0, TRUE);
wnoutrefresh (list);
 
print_arrows(dialog, choice, item_no, scroll,
box_y, box_x + check_x + 5, list_height);
 
wrefresh (dialog);
 
continue; /* wait for another key press */
} else
i = choice - 1;
} else if (key == KEY_DOWN || key == '+') {
if (choice == max_choice - 1) {
if (scroll + choice >= item_no - 1)
continue;
/* Scroll list up */
if (list_height > 1) {
/* De-highlight current last item before scrolling up */
print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
status[scroll + max_choice - 1],
max_choice - 1, FALSE);
scrollok (list, TRUE);
scroll (list);
scrollok (list, FALSE);
}
scroll++;
print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
status[scroll + max_choice - 1],
max_choice - 1, TRUE);
wnoutrefresh (list);
 
print_arrows(dialog, choice, item_no, scroll,
box_y, box_x + check_x + 5, list_height);
 
wrefresh (dialog);
 
continue; /* wait for another key press */
} else
i = choice + 1;
}
if (i != choice) {
/* De-highlight current item */
print_item (list, items[(scroll + choice) * 3 + 1],
status[scroll + choice], choice, FALSE);
/* Highlight new item */
choice = i;
print_item (list, items[(scroll + choice) * 3 + 1],
status[scroll + choice], choice, TRUE);
wnoutrefresh (list);
wrefresh (dialog);
}
continue; /* wait for another key press */
}
switch (key) {
case 'H':
case 'h':
case '?':
delwin (dialog);
free (status);
return 1;
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 1 : (button > 1 ? 0 : button);
 
print_buttons(dialog, height, width, button);
wrefresh (dialog);
break;
case 'S':
case 's':
case ' ':
case '\n':
if (!button) {
if (flag == FLAG_CHECK) {
status[scroll + choice] = !status[scroll + choice];
wmove (list, choice, check_x);
wattrset (list, check_selected_attr);
wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' ');
} else {
if (!status[scroll + choice]) {
for (i = 0; i < item_no; i++)
status[i] = 0;
status[scroll + choice] = 1;
for (i = 0; i < max_choice; i++)
print_item (list, items[(scroll + i) * 3 + 1],
status[scroll + i], i, i == choice);
}
}
wnoutrefresh (list);
wrefresh (dialog);
for (i = 0; i < item_no; i++) {
if (status[i]) {
if (flag == FLAG_CHECK) {
fprintf (stderr, "\"%s\" ", items[i * 3]);
} else {
fprintf (stderr, "%s", items[i * 3]);
}
 
}
}
}
delwin (dialog);
free (status);
return button;
case 'X':
case 'x':
key = ESC;
case ESC:
break;
}
 
/* Now, update everything... */
doupdate ();
}
 
delwin (dialog);
free (status);
return -1; /* ESC pressed */
}
/lxdialog/Makefile
0,0 → 1,46
HOSTCFLAGS += -DLOCALE
LIBS = -lncurses
 
ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
else
ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
else
ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
HOSTCFLAGS += -DCURSES_LOC="<ncurses.h>"
else
HOSTCFLAGS += -DCURSES_LOC="<curses.h>"
endif
endif
endif
 
 
OBJS = checklist.o menubox.o textbox.o yesno.o inputbox.o \
util.o lxdialog.o msgbox.o
 
%.o: %.c
$(HOSTCC) $(HOSTCFLAGS) -c -o $@ $<
 
all: ncurses lxdialog
 
lxdialog: $(OBJS)
$(HOSTCC) -o lxdialog $(OBJS) $(LIBS)
 
ncurses:
@echo "main() {}" > lxtemp.c
@if $(HOSTCC) -lncurses lxtemp.c ; then \
rm -f lxtemp.c a.out; \
else \
rm -f lxtemp.c; \
echo -e "\007" ;\
echo ">> Unable to find the Ncurses libraries." ;\
echo ">>" ;\
echo ">> You must have Ncurses installed in order" ;\
echo ">> to use 'make menuconfig'" ;\
echo ;\
exit 1 ;\
fi
 
clean:
rm -f core *.o *~ lxdialog
/lxdialog/menubox.c
0,0 → 1,443
/*
* menubox.c -- implements the menu box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
/*
* Changes by Clifford Wolf (god@clifford.at)
*
* [ 1998-06-13 ]
*
* *) A bugfix for the Page-Down problem
*
* *) Formerly when I used Page Down and Page Up, the cursor would be set
* to the first position in the menu box. Now lxdialog is a bit
* smarter and works more like other menu systems (just have a look at
* it).
*
* *) Formerly if I selected something my scrolling would be broken because
* lxdialog is re-invoked by the Menuconfig shell script, can't
* remember the last scrolling position, and just sets it so that the
* cursor is at the bottom of the box. Now it writes the temporary file
* lxdialog.scrltmp which contains this information. The file is
* deleted by lxdialog if the user leaves a submenu or enters a new
* one, but it would be nice if Menuconfig could make another "rm -f"
* just to be sure. Just try it out - you will recognise a difference!
*
* [ 1998-06-14 ]
*
* *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
* and menus change their size on the fly.
*
* *) If for some reason the last scrolling position is not saved by
* lxdialog, it sets the scrolling so that the selected item is in the
* middle of the menu box, not at the bottom.
*
* 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
* Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
* This fixes a bug in Menuconfig where using ' ' to descend into menus
* would leave mis-synchronized lxdialog.scrltmp files lying around,
* fscanf would read in 'scroll', and eventually that value would get used.
*/
 
#include "dialog.h"
 
static int menu_width, item_x;
 
/*
* Print menu item
*/
static void
print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
{
int j;
char menu_item[menu_width+1];
 
strncpy(menu_item, item, menu_width);
menu_item[menu_width] = 0;
j = first_alpha(menu_item, "YyNnMm");
 
/* Clear 'residue' of last item */
wattrset (win, menubox_attr);
wmove (win, choice, 0);
#if OLD_NCURSES
{
int i;
for (i = 0; i < menu_width; i++)
waddch (win, ' ');
}
#else
wclrtoeol(win);
#endif
wattrset (win, selected ? item_selected_attr : item_attr);
mvwaddstr (win, choice, item_x, menu_item);
if (hotkey) {
wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
mvwaddch(win, choice, item_x+j, menu_item[j]);
}
if (selected) {
wmove (win, choice, item_x+1);
wrefresh (win);
}
}
 
/*
* Print the scroll indicators.
*/
static void
print_arrows (WINDOW * win, int item_no, int scroll,
int y, int x, int height)
{
int cur_y, cur_x;
 
getyx(win, cur_y, cur_x);
 
wmove(win, y, x);
 
if (scroll > 0) {
wattrset (win, uarrow_attr);
waddch (win, ACS_UARROW);
waddstr (win, "(-)");
}
else {
wattrset (win, menubox_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
 
y = y + height + 1;
wmove(win, y, x);
 
if ((height < item_no) && (scroll + height < item_no)) {
wattrset (win, darrow_attr);
waddch (win, ACS_DARROW);
waddstr (win, "(+)");
}
else {
wattrset (win, menubox_border_attr);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
waddch (win, ACS_HLINE);
}
 
wmove(win, cur_y, cur_x);
}
 
/*
* Display the termination buttons.
*/
static void
print_buttons (WINDOW *win, int height, int width, int selected)
{
int x = width / 2 - 16;
int y = height - 2;
 
print_button (win, "Select", y, x, selected == 0);
print_button (win, " Exit ", y, x + 12, selected == 1);
print_button (win, " Help ", y, x + 24, selected == 2);
 
wmove(win, y, x+1+12*selected);
wrefresh (win);
}
 
/*
* Display a menu for choosing among a number of options
*/
int
dialog_menu (const char *title, const char *prompt, int height, int width,
int menu_height, const char *current, int item_no,
const char * const * items)
 
{
int i, j, x, y, box_x, box_y;
int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
WINDOW *dialog, *menu;
FILE *f;
 
max_choice = MIN (menu_height, item_no);
 
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
 
draw_shadow (stdscr, y, x, height, width);
 
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
 
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height - 3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
wbkgdset (dialog, dialog_attr & A_COLOR);
waddch (dialog, ACS_RTEE);
 
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
 
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
 
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
 
menu_width = width - 6;
box_y = height - menu_height - 5;
box_x = (width - menu_width) / 2 - 1;
 
/* create new window for the menu */
menu = subwin (dialog, menu_height, menu_width,
y + box_y + 1, x + box_x + 1);
keypad (menu, TRUE);
 
/* draw a box around the menu items */
draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2,
menubox_border_attr, menubox_attr);
 
/*
* Find length of longest item in order to center menu.
* Set 'choice' to default item.
*/
item_x = 0;
for (i = 0; i < item_no; i++) {
item_x = MAX (item_x, MIN(menu_width, strlen (items[i * 2 + 1]) + 2));
if (strcmp(current, items[i*2]) == 0) choice = i;
}
 
item_x = (menu_width - item_x) / 2;
 
/* get the scroll info from the temp file */
if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) {
if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) &&
(scroll+max_choice > choice) && (scroll >= 0) &&
(scroll+max_choice <= item_no) ) {
first_item = scroll;
choice = choice - scroll;
fclose(f);
} else {
scroll=0;
remove("lxdialog.scrltmp");
fclose(f);
f=NULL;
}
}
if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) {
if (choice >= item_no-max_choice/2)
scroll = first_item = item_no-max_choice;
else
scroll = first_item = choice - max_choice/2;
choice = choice - scroll;
}
 
/* Print the menu */
for (i=0; i < max_choice; i++) {
print_item (menu, items[(first_item + i) * 2 + 1], i, i == choice,
(items[(first_item + i)*2][0] != ':'));
}
 
wnoutrefresh (menu);
 
print_arrows(dialog, item_no, scroll,
box_y, box_x+item_x+1, menu_height);
 
print_buttons (dialog, height, width, 0);
wmove (menu, choice, item_x+1);
wrefresh (menu);
 
while (key != ESC) {
key = wgetch(menu);
 
if (key < 256 && isalpha(key)) key = tolower(key);
 
if (strchr("ynm", key))
i = max_choice;
else {
for (i = choice+1; i < max_choice; i++) {
j = first_alpha(items[(scroll+i)*2+1], "YyNnMm");
if (key == tolower(items[(scroll+i)*2+1][j]))
break;
}
if (i == max_choice)
for (i = 0; i < max_choice; i++) {
j = first_alpha(items[(scroll+i)*2+1], "YyNnMm");
if (key == tolower(items[(scroll+i)*2+1][j]))
break;
}
}
 
if (i < max_choice ||
key == KEY_UP || key == KEY_DOWN ||
key == '-' || key == '+' ||
key == KEY_PPAGE || key == KEY_NPAGE) {
 
print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
(items[(scroll+choice)*2][0] != ':'));
 
if (key == KEY_UP || key == '-') {
if (choice < 2 && scroll) {
/* Scroll menu down */
scrollok (menu, TRUE);
wscrl (menu, -1);
scrollok (menu, FALSE);
 
scroll--;
 
print_item (menu, items[scroll * 2 + 1], 0, FALSE,
(items[scroll*2][0] != ':'));
} else
choice = MAX(choice - 1, 0);
 
} else if (key == KEY_DOWN || key == '+') {
 
print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
(items[(scroll+choice)*2][0] != ':'));
 
if ((choice > max_choice-3) &&
(scroll + max_choice < item_no)
) {
/* Scroll menu up */
scrollok (menu, TRUE);
scroll (menu);
scrollok (menu, FALSE);
 
scroll++;
 
print_item (menu, items[(scroll+max_choice-1)*2+1],
max_choice-1, FALSE,
(items[(scroll+max_choice-1)*2][0] != ':'));
} else
choice = MIN(choice+1, max_choice-1);
 
} else if (key == KEY_PPAGE) {
scrollok (menu, TRUE);
for (i=0; (i < max_choice); i++) {
if (scroll > 0) {
wscrl (menu, -1);
scroll--;
print_item (menu, items[scroll * 2 + 1], 0, FALSE,
(items[scroll*2][0] != ':'));
} else {
if (choice > 0)
choice--;
}
}
scrollok (menu, FALSE);
 
} else if (key == KEY_NPAGE) {
for (i=0; (i < max_choice); i++) {
if (scroll+max_choice < item_no) {
scrollok (menu, TRUE);
scroll(menu);
scrollok (menu, FALSE);
scroll++;
print_item (menu, items[(scroll+max_choice-1)*2+1],
max_choice-1, FALSE,
(items[(scroll+max_choice-1)*2][0] != ':'));
} else {
if (choice+1 < max_choice)
choice++;
}
}
 
} else
choice = i;
 
print_item (menu, items[(scroll+choice)*2+1], choice, TRUE,
(items[(scroll+choice)*2][0] != ':'));
 
print_arrows(dialog, item_no, scroll,
box_y, box_x+item_x+1, menu_height);
 
wnoutrefresh (dialog);
wrefresh (menu);
 
continue; /* wait for another key press */
}
 
switch (key) {
case KEY_LEFT:
case TAB:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 2 : (button > 2 ? 0 : button);
 
print_buttons(dialog, height, width, button);
wrefresh (menu);
break;
case ' ':
case 's':
case 'y':
case 'n':
case 'm':
/* save scroll info */
if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
fprintf(f,"%d\n",scroll);
fclose(f);
}
delwin (dialog);
fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
switch (key) {
case 's': return 3;
case 'y': return 3;
case 'n': return 4;
case 'm': return 5;
case ' ': return 6;
}
return 0;
case 'h':
case '?':
button = 2;
case '\n':
delwin (dialog);
if (button == 2)
fprintf(stderr, "%s \"%s\"\n",
items[(scroll + choice) * 2],
items[(scroll + choice) * 2 + 1] +
first_alpha(items[(scroll + choice) * 2 + 1],""));
else
fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
 
remove("lxdialog.scrltmp");
return button;
case 'e':
case 'x':
key = ESC;
case ESC:
break;
}
}
 
delwin (dialog);
remove("lxdialog.scrltmp");
return -1; /* ESC pressed */
}
/lxdialog/yesno.c
0,0 → 1,118
/*
* yesno.c -- implements the yes/no box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#include "dialog.h"
 
/*
* Display termination buttons
*/
static void
print_buttons(WINDOW *dialog, int height, int width, int selected)
{
int x = width / 2 - 10;
int y = height - 2;
 
print_button (dialog, " Yes ", y, x, selected == 0);
print_button (dialog, " No ", y, x + 13, selected == 1);
 
wmove(dialog, y, x+1 + 13*selected );
wrefresh (dialog);
}
 
/*
* Display a dialog box with two buttons - Yes and No
*/
int
dialog_yesno (const char *title, const char *prompt, int height, int width)
{
int i, x, y, key = 0, button = 0;
WINDOW *dialog;
 
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
 
draw_shadow (stdscr, y, x, height, width);
 
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
 
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
waddch (dialog, ACS_RTEE);
 
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
 
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
 
wattrset (dialog, dialog_attr);
print_autowrap (dialog, prompt, width - 2, 1, 3);
 
print_buttons(dialog, height, width, 0);
 
while (key != ESC) {
key = wgetch (dialog);
switch (key) {
case 'Y':
case 'y':
delwin (dialog);
return 0;
case 'N':
case 'n':
delwin (dialog);
return 1;
 
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0)
? 1 : (button > 1 ? 0 : button);
 
print_buttons(dialog, height, width, button);
wrefresh (dialog);
break;
case ' ':
case '\n':
delwin (dialog);
return button;
case ESC:
break;
}
}
 
delwin (dialog);
return -1; /* ESC pressed */
}
/lxdialog/BIG.FAT.WARNING
0,0 → 1,4
This is NOT the official version of dialog. This version has been
significantly modified from the original. It is for use by the Linux
kernel configuration script. Please do not bother Savio Lam with
questions about this program.
/lxdialog/textbox.c
0,0 → 1,556
/*
* textbox.c -- implements the text box
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#include "dialog.h"
 
static void back_lines (int n);
static void print_page (WINDOW * win, int height, int width);
static void print_line (WINDOW * win, int row, int width);
static char *get_line (void);
static void print_position (WINDOW * win, int height, int width);
 
static int hscroll = 0, fd, file_size, bytes_read;
static int begin_reached = 1, end_reached = 0, page_length;
static char *buf, *page;
 
/*
* Display text from a file in a dialog box.
*/
int
dialog_textbox (const char *title, const char *file, int height, int width)
{
int i, x, y, cur_x, cur_y, fpos, key = 0;
int passed_end;
char search_term[MAX_LEN + 1];
WINDOW *dialog, *text;
 
search_term[0] = '\0'; /* no search term entered yet */
 
/* Open input file for reading */
if ((fd = open (file, O_RDONLY)) == -1) {
endwin ();
fprintf (stderr,
"\nCan't open input file in dialog_textbox().\n");
exit (-1);
}
/* Get file size. Actually, 'file_size' is the real file size - 1,
since it's only the last byte offset from the beginning */
if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
endwin ();
fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
exit (-1);
}
/* Restore file pointer to beginning of file after getting file size */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
/* Allocate space for read buffer */
if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
endwin ();
fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
exit (-1);
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in dialog_textbox().\n");
exit (-1);
}
buf[bytes_read] = '\0'; /* mark end of valid data */
page = buf; /* page is pointer to start of page to be displayed */
 
/* center dialog box on screen */
x = (COLS - width) / 2;
y = (LINES - height) / 2;
 
 
draw_shadow (stdscr, y, x, height, width);
 
dialog = newwin (height, width, y, x);
keypad (dialog, TRUE);
 
/* Create window for text region, used for scrolling text */
text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
wattrset (text, dialog_attr);
wbkgdset (text, dialog_attr & A_COLOR);
 
keypad (text, TRUE);
 
/* register the new window, along with its borders */
draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
 
wattrset (dialog, border_attr);
mvwaddch (dialog, height-3, 0, ACS_LTEE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
wbkgdset (dialog, dialog_attr & A_COLOR);
waddch (dialog, ACS_RTEE);
 
if (title != NULL && strlen(title) >= width-2 ) {
/* truncate long title -- mec */
char * title2 = malloc(width-2+1);
memcpy( title2, title, width-2 );
title2[width-2] = '\0';
title = title2;
}
 
if (title != NULL) {
wattrset (dialog, title_attr);
mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
waddstr (dialog, (char *)title);
waddch (dialog, ' ');
}
print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
wnoutrefresh (dialog);
getyx (dialog, cur_y, cur_x); /* Save cursor position */
 
/* Print first page of text */
attr_clear (text, height - 4, width - 2, dialog_attr);
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
 
while ((key != ESC) && (key != '\n')) {
key = wgetch (dialog);
switch (key) {
case 'E': /* Exit */
case 'e':
case 'X':
case 'x':
delwin (dialog);
free (buf);
close (fd);
return 0;
case 'g': /* First page */
case KEY_HOME:
if (!begin_reached) {
begin_reached = 1;
/* First page not in buffer? */
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
if (fpos > bytes_read) { /* Yes, we have to read it in */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"dialog_textbox().\n");
exit (-1);
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr,
"\nError reading file in dialog_textbox().\n");
exit (-1);
}
buf[bytes_read] = '\0';
}
page = buf;
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
}
break;
case 'G': /* Last page */
case KEY_END:
 
end_reached = 1;
/* Last page not in buffer? */
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
if (fpos < file_size) { /* Yes, we have to read it in */
if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in dialog_textbox().\n");
exit (-1);
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr,
"\nError reading file in dialog_textbox().\n");
exit (-1);
}
buf[bytes_read] = '\0';
}
page = buf + bytes_read;
back_lines (height - 4);
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
break;
case 'K': /* Previous line */
case 'k':
case KEY_UP:
if (!begin_reached) {
back_lines (page_length + 1);
 
/* We don't call print_page() here but use scrolling to ensure
faster screen update. However, 'end_reached' and
'page_length' should still be updated, and 'page' should
point to start of next page. This is done by calling
get_line() in the following 'for' loop. */
scrollok (text, TRUE);
wscrl (text, -1); /* Scroll text region down one line */
scrollok (text, FALSE);
page_length = 0;
passed_end = 0;
for (i = 0; i < height - 4; i++) {
if (!i) {
/* print first line of page */
print_line (text, 0, width - 2);
wnoutrefresh (text);
} else
/* Called to update 'end_reached' and 'page' */
get_line ();
if (!passed_end)
page_length++;
if (end_reached && !passed_end)
passed_end = 1;
}
 
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
}
break;
case 'B': /* Previous page */
case 'b':
case KEY_PPAGE:
if (begin_reached)
break;
back_lines (page_length + height - 4);
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case 'J': /* Next line */
case 'j':
case KEY_DOWN:
if (!end_reached) {
begin_reached = 0;
scrollok (text, TRUE);
scroll (text); /* Scroll text region up one line */
scrollok (text, FALSE);
print_line (text, height - 5, width - 2);
wnoutrefresh (text);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh (dialog);
}
break;
case KEY_NPAGE: /* Next page */
case ' ':
if (end_reached)
break;
 
begin_reached = 0;
print_page (text, height - 4, width - 2);
print_position (dialog, height, width);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case '0': /* Beginning of line */
case 'H': /* Scroll left */
case 'h':
case KEY_LEFT:
if (hscroll <= 0)
break;
 
if (key == '0')
hscroll = 0;
else
hscroll--;
/* Reprint current page to scroll horizontally */
back_lines (page_length);
print_page (text, height - 4, width - 2);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case 'L': /* Scroll right */
case 'l':
case KEY_RIGHT:
if (hscroll >= MAX_LEN)
break;
hscroll++;
/* Reprint current page to scroll horizontally */
back_lines (page_length);
print_page (text, height - 4, width - 2);
wmove (dialog, cur_y, cur_x);
wrefresh (dialog);
break;
case ESC:
break;
}
}
 
delwin (dialog);
free (buf);
close (fd);
return -1; /* ESC pressed */
}
 
/*
* Go back 'n' lines in text file. Called by dialog_textbox().
* 'page' will be updated to point to the desired line in 'buf'.
*/
static void
back_lines (int n)
{
int i, fpos;
 
begin_reached = 0;
/* We have to distinguish between end_reached and !end_reached
since at end of file, the line is not ended by a '\n'.
The code inside 'if' basically does a '--page' to move one
character backward so as to skip '\n' of the previous line */
if (!end_reached) {
/* Either beginning of buffer or beginning of file reached? */
if (page == buf) {
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"back_lines().\n");
exit (-1);
}
if (fpos > bytes_read) { /* Not beginning of file yet */
/* We've reached beginning of buffer, but not beginning of
file yet, so read previous part of file into buffer.
Note that we only move backward for BUF_SIZE/2 bytes,
but not BUF_SIZE bytes to avoid re-reading again in
print_page() later */
/* Really possible to move backward BUF_SIZE/2 bytes? */
if (fpos < BUF_SIZE / 2 + bytes_read) {
/* No, move less then */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"back_lines().\n");
exit (-1);
}
page = buf + fpos - bytes_read;
} else { /* Move backward BUF_SIZE/2 bytes */
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
== -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer "
"in back_lines().\n");
exit (-1);
}
page = buf + BUF_SIZE / 2;
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in back_lines().\n");
exit (-1);
}
buf[bytes_read] = '\0';
} else { /* Beginning of file reached */
begin_reached = 1;
return;
}
}
if (*(--page) != '\n') { /* '--page' here */
/* Something's wrong... */
endwin ();
fprintf (stderr, "\nInternal error in back_lines().\n");
exit (-1);
}
}
/* Go back 'n' lines */
for (i = 0; i < n; i++)
do {
if (page == buf) {
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr,
"\nError moving file pointer in back_lines().\n");
exit (-1);
}
if (fpos > bytes_read) {
/* Really possible to move backward BUF_SIZE/2 bytes? */
if (fpos < BUF_SIZE / 2 + bytes_read) {
/* No, move less then */
if (lseek (fd, 0, SEEK_SET) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer "
"in back_lines().\n");
exit (-1);
}
page = buf + fpos - bytes_read;
} else { /* Move backward BUF_SIZE/2 bytes */
if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
SEEK_CUR) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer"
" in back_lines().\n");
exit (-1);
}
page = buf + BUF_SIZE / 2;
}
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in "
"back_lines().\n");
exit (-1);
}
buf[bytes_read] = '\0';
} else { /* Beginning of file reached */
begin_reached = 1;
return;
}
}
} while (*(--page) != '\n');
page++;
}
 
/*
* Print a new page of text. Called by dialog_textbox().
*/
static void
print_page (WINDOW * win, int height, int width)
{
int i, passed_end = 0;
 
page_length = 0;
for (i = 0; i < height; i++) {
print_line (win, i, width);
if (!passed_end)
page_length++;
if (end_reached && !passed_end)
passed_end = 1;
}
wnoutrefresh (win);
}
 
/*
* Print a new line of text. Called by dialog_textbox() and print_page().
*/
static void
print_line (WINDOW * win, int row, int width)
{
int y, x;
char *line;
 
line = get_line ();
line += MIN (strlen (line), hscroll); /* Scroll horizontally */
wmove (win, row, 0); /* move cursor to correct line */
waddch (win, ' ');
waddnstr (win, line, MIN (strlen (line), width - 2));
 
getyx (win, y, x);
/* Clear 'residue' of previous line */
#if OLD_NCURSES
{
int i;
for (i = 0; i < width - x; i++)
waddch (win, ' ');
}
#else
wclrtoeol(win);
#endif
}
 
/*
* Return current line of text. Called by dialog_textbox() and print_line().
* 'page' should point to start of current line before calling, and will be
* updated to point to start of next line.
*/
static char *
get_line (void)
{
int i = 0, fpos;
static char line[MAX_LEN + 1];
 
end_reached = 0;
while (*page != '\n') {
if (*page == '\0') {
/* Either end of file or end of buffer reached */
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in "
"get_line().\n");
exit (-1);
}
if (fpos < file_size) { /* Not end of file yet */
/* We've reached end of buffer, but not end of file yet,
so read next part of file into buffer */
if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
endwin ();
fprintf (stderr, "\nError reading file in get_line().\n");
exit (-1);
}
buf[bytes_read] = '\0';
page = buf;
} else {
if (!end_reached)
end_reached = 1;
break;
}
} else if (i < MAX_LEN)
line[i++] = *(page++);
else {
/* Truncate lines longer than MAX_LEN characters */
if (i == MAX_LEN)
line[i++] = '\0';
page++;
}
}
if (i <= MAX_LEN)
line[i] = '\0';
if (!end_reached)
page++; /* move pass '\n' */
 
return line;
}
 
/*
* Print current position
*/
static void
print_position (WINDOW * win, int height, int width)
{
int fpos, percent;
 
if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
endwin ();
fprintf (stderr, "\nError moving file pointer in print_position().\n");
exit (-1);
}
wattrset (win, position_indicator_attr);
wbkgdset (win, position_indicator_attr & A_COLOR);
percent = !file_size ?
100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
wmove (win, height - 3, width - 9);
wprintw (win, "(%3d%%)", percent);
}
/lxdialog/util.c
0,0 → 1,359
/*
* util.c
*
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#include "dialog.h"
 
 
/* use colors by default? */
bool use_colors = 1;
 
const char *backtitle = NULL;
 
const char *dialog_result;
 
/*
* Attribute values, default is for mono display
*/
chtype attributes[] =
{
A_NORMAL, /* screen_attr */
A_NORMAL, /* shadow_attr */
A_NORMAL, /* dialog_attr */
A_BOLD, /* title_attr */
A_NORMAL, /* border_attr */
A_REVERSE, /* button_active_attr */
A_DIM, /* button_inactive_attr */
A_REVERSE, /* button_key_active_attr */
A_BOLD, /* button_key_inactive_attr */
A_REVERSE, /* button_label_active_attr */
A_NORMAL, /* button_label_inactive_attr */
A_NORMAL, /* inputbox_attr */
A_NORMAL, /* inputbox_border_attr */
A_NORMAL, /* searchbox_attr */
A_BOLD, /* searchbox_title_attr */
A_NORMAL, /* searchbox_border_attr */
A_BOLD, /* position_indicator_attr */
A_NORMAL, /* menubox_attr */
A_NORMAL, /* menubox_border_attr */
A_NORMAL, /* item_attr */
A_REVERSE, /* item_selected_attr */
A_BOLD, /* tag_attr */
A_REVERSE, /* tag_selected_attr */
A_BOLD, /* tag_key_attr */
A_REVERSE, /* tag_key_selected_attr */
A_BOLD, /* check_attr */
A_REVERSE, /* check_selected_attr */
A_BOLD, /* uarrow_attr */
A_BOLD /* darrow_attr */
};
 
 
#include "colors.h"
 
/*
* Table of color values
*/
int color_table[][3] =
{
{SCREEN_FG, SCREEN_BG, SCREEN_HL},
{SHADOW_FG, SHADOW_BG, SHADOW_HL},
{DIALOG_FG, DIALOG_BG, DIALOG_HL},
{TITLE_FG, TITLE_BG, TITLE_HL},
{BORDER_FG, BORDER_BG, BORDER_HL},
{BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
{BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
{BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
{BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL},
{BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL},
{BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
BUTTON_LABEL_INACTIVE_HL},
{INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
{INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
{SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
{SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
{SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
{POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
{MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
{MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
{ITEM_FG, ITEM_BG, ITEM_HL},
{ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
{TAG_FG, TAG_BG, TAG_HL},
{TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
{TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
{TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
{CHECK_FG, CHECK_BG, CHECK_HL},
{CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
{UARROW_FG, UARROW_BG, UARROW_HL},
{DARROW_FG, DARROW_BG, DARROW_HL},
}; /* color_table */
 
/*
* Set window to attribute 'attr'
*/
void
attr_clear (WINDOW * win, int height, int width, chtype attr)
{
int i, j;
 
wattrset (win, attr);
for (i = 0; i < height; i++) {
wmove (win, i, 0);
for (j = 0; j < width; j++)
waddch (win, ' ');
}
touchwin (win);
}
 
void dialog_clear (void)
{
attr_clear (stdscr, LINES, COLS, screen_attr);
/* Display background title if it exists ... - SLH */
if (backtitle != NULL) {
int i;
 
wattrset (stdscr, screen_attr);
mvwaddstr (stdscr, 0, 1, (char *)backtitle);
wmove (stdscr, 1, 1);
for (i = 1; i < COLS - 1; i++)
waddch (stdscr, ACS_HLINE);
}
wnoutrefresh (stdscr);
}
 
/*
* Do some initialization for dialog
*/
void
init_dialog (void)
{
initscr (); /* Init curses */
keypad (stdscr, TRUE);
cbreak ();
noecho ();
 
 
if (use_colors) /* Set up colors */
color_setup ();
 
 
dialog_clear ();
}
 
/*
* Setup for color display
*/
void
color_setup (void)
{
int i;
 
if (has_colors ()) { /* Terminal supports color? */
start_color ();
 
/* Initialize color pairs */
for (i = 0; i < ATTRIBUTE_COUNT; i++)
init_pair (i + 1, color_table[i][0], color_table[i][1]);
 
/* Setup color attributes */
for (i = 0; i < ATTRIBUTE_COUNT; i++)
attributes[i] = C_ATTR (color_table[i][2], i + 1);
}
}
 
/*
* End using dialog functions.
*/
void
end_dialog (void)
{
endwin ();
}
 
 
/*
* Print a string of text in a window, automatically wrap around to the
* next line if the string is too long to fit on one line. Newline
* characters '\n' are replaced by spaces. We start on a new line
* if there is no room for at least 4 nonblanks following a double-space.
*/
void
print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
{
int newl, cur_x, cur_y;
int i, prompt_len, room, wlen;
char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
 
strcpy (tempstr, prompt);
 
prompt_len = strlen(tempstr);
/*
* Remove newlines
*/
for(i=0; i<prompt_len; i++) {
if(tempstr[i] == '\n') tempstr[i] = ' ';
}
 
if (prompt_len <= width - x * 2) { /* If prompt is short */
wmove (win, y, (width - prompt_len) / 2);
waddstr (win, tempstr);
} else {
cur_x = x;
cur_y = y;
newl = 1;
word = tempstr;
while (word && *word) {
sp = index(word, ' ');
if (sp)
*sp++ = 0;
 
/* Wrap to next line if either the word does not fit,
or it is the first word of a new sentence, and it is
short, and the next word does not fit. */
room = width - cur_x;
wlen = strlen(word);
if (wlen > room ||
(newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
&& (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
cur_y++;
cur_x = x;
}
wmove (win, cur_y, cur_x);
waddstr (win, word);
getyx (win, cur_y, cur_x);
cur_x++;
if (sp && *sp == ' ') {
cur_x++; /* double space */
while (*++sp == ' ');
newl = 1;
} else
newl = 0;
word = sp;
}
}
}
 
/*
* Print a button
*/
void
print_button (WINDOW * win, const char *label, int y, int x, int selected)
{
int i, temp;
 
wmove (win, y, x);
wattrset (win, selected ? button_active_attr : button_inactive_attr);
waddstr (win, "<");
temp = strspn (label, " ");
label += temp;
wattrset (win, selected ? button_label_active_attr
: button_label_inactive_attr);
for (i = 0; i < temp; i++)
waddch (win, ' ');
wattrset (win, selected ? button_key_active_attr
: button_key_inactive_attr);
waddch (win, label[0]);
wattrset (win, selected ? button_label_active_attr
: button_label_inactive_attr);
waddstr (win, (char *)label + 1);
wattrset (win, selected ? button_active_attr : button_inactive_attr);
waddstr (win, ">");
wmove (win, y, x + temp + 1);
}
 
/*
* Draw a rectangular box with line drawing characters
*/
void
draw_box (WINDOW * win, int y, int x, int height, int width,
chtype box, chtype border)
{
int i, j;
 
wattrset (win, 0);
for (i = 0; i < height; i++) {
wmove (win, y + i, x);
for (j = 0; j < width; j++)
if (!i && !j)
waddch (win, border | ACS_ULCORNER);
else if (i == height - 1 && !j)
waddch (win, border | ACS_LLCORNER);
else if (!i && j == width - 1)
waddch (win, box | ACS_URCORNER);
else if (i == height - 1 && j == width - 1)
waddch (win, box | ACS_LRCORNER);
else if (!i)
waddch (win, border | ACS_HLINE);
else if (i == height - 1)
waddch (win, box | ACS_HLINE);
else if (!j)
waddch (win, border | ACS_VLINE);
else if (j == width - 1)
waddch (win, box | ACS_VLINE);
else
waddch (win, box | ' ');
}
}
 
/*
* Draw shadows along the right and bottom edge to give a more 3D look
* to the boxes
*/
void
draw_shadow (WINDOW * win, int y, int x, int height, int width)
{
int i;
 
if (has_colors ()) { /* Whether terminal supports color? */
wattrset (win, shadow_attr);
wmove (win, y + height, x + 2);
for (i = 0; i < width; i++)
waddch (win, winch (win) & A_CHARTEXT);
for (i = y + 1; i < y + height + 1; i++) {
wmove (win, i, x + width);
waddch (win, winch (win) & A_CHARTEXT);
waddch (win, winch (win) & A_CHARTEXT);
}
wnoutrefresh (win);
}
}
 
/*
* Return the position of the first alphabetic character in a string.
*/
int
first_alpha(const char *string, const char *exempt)
{
int i, in_paren=0, c;
 
for (i = 0; i < strlen(string); i++) {
c = tolower(string[i]);
 
if (strchr("<[(", c)) ++in_paren;
if (strchr(">])", c)) --in_paren;
 
if ((! in_paren) && isalpha(c) &&
strchr(exempt, c) == 0)
return i;
}
 
return 0;
}
/header.tk
0,0 → 1,637
# FILE: header.tk
# This file is boilerplate TCL/TK function definitions for 'make xconfig'.
#
# CHANGES
# =======
#
# 8 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
# - Remove unused do_cmd function (part of the 2.0 sound support).
# - Arrange buttons in three columns for better screen fitting.
# - Add CONSTANT_Y, CONSTANT_M, CONSTANT_N for commands like:
# dep_tristate 'foo' CONFIG_FOO m
#
# 23 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
# - Shut vfix the hell up.
#
# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
# - Improve the exit message (Jeff Ronne).
 
#
# This is a handy replacement for ".widget cget" that requires neither tk4
# nor additional source code uglification.
#
proc cget { w option } {
return "[lindex [$w configure $option] 4]"
}
 
#
# Function to compensate for broken config.in scripts like the sound driver,
# which make dependencies on variables that are never even conditionally
# defined.
#
proc vfix { var } {
global $var
if [ catch {eval concat $$var} ] {
set $var 4
}
}
 
#
# Constant values used by certain dep_tristate commands.
#
set CONSTANT_Y 1
set CONSTANT_M 2
set CONSTANT_N 0
set CONSTANT_E 4
 
#
# Create a "reference" object to steal colors from.
#
button .ref
 
#
# On monochrome displays, -disabledforeground is blank by default; that's
# bad. Fill it with -foreground instead.
#
if { [cget .ref -disabledforeground] == "" } {
.ref configure -disabledforeground [cget .ref -foreground]
}
 
 
#
# Define some macros we will need to parse the config.in file.
#
 
proc mainmenu_name { text } {
wm title . "$text"
}
 
proc menu_option { w menu_num text } {
global menus_per_column
global processed_top_level
set processed_top_level [expr $processed_top_level + 1]
if { $processed_top_level <= $menus_per_column } then {
set myframe left
} elseif { $processed_top_level <= [expr 2 * $menus_per_column] } then {
set myframe middle
} else {
set myframe right
}
button .f0.x$menu_num -anchor w -text "$text" \
-command "$w .$w \"$text\""
pack .f0.x$menu_num -pady 0 -side top -fill x -in .f0.$myframe
}
 
proc load_configfile { w title func } {
catch {destroy $w}
toplevel $w -class Dialog
global loadfile
frame $w.x
label $w.bm -bitmap questhead
pack $w.bm -pady 10 -side top -padx 10
label $w.x.l -text "Enter filename:" -relief raised
entry $w.x.x -width 35 -relief sunken -borderwidth 2 \
-textvariable loadfile
pack $w.x.l $w.x.x -anchor w -side left
pack $w.x -side top -pady 10
wm title $w "$title"
 
set oldFocus [focus]
frame $w.f
button $w.f.back -text "OK" -width 20 \
-command "destroy $w; focus $oldFocus;$func .fileio"
button $w.f.canc -text "Cancel" \
-width 20 -command "destroy $w; focus $oldFocus"
pack $w.f.back $w.f.canc -side left -pady 10 -padx 45
pack $w.f -pady 10 -side bottom -padx 10 -anchor w
focus $w
global winx; global winy
set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
wm geometry $w +$winx+$winy
}
 
bind all <Alt-q> {maybe_exit .maybe}
 
proc maybe_exit { w } {
catch {destroy $w}
toplevel $w -class Dialog
label $w.bm -bitmap questhead
pack $w.bm -pady 10 -side top -padx 10
message $w.m -width 400 -aspect 300 \
-text "Changes will be lost. Are you sure?" -relief flat
pack $w.m -pady 10 -side top -padx 10
wm title $w "Are you sure?"
 
set oldFocus [focus]
frame $w.f
button $w.f.back -text "OK" -width 20 \
-command "exit"
button $w.f.canc -text "Cancel" \
-width 20 -command "destroy $w; focus $oldFocus"
pack $w.f.back $w.f.canc -side left -pady 10 -padx 45
pack $w.f -pady 10 -side bottom -padx 10 -anchor w
bind $w <Return> "exit"
bind $w <Escape> "destroy $w; focus $oldFocus"
focus $w
global winx; global winy
set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
wm geometry $w +$winx+$winy
}
 
proc read_config_file { w } {
global loadfile
if { [string length $loadfile] != 0 && [file readable $loadfile] == 1 } then {
read_config $loadfile
} else {
catch {destroy $w}
toplevel $w -class Dialog
message $w.m -width 400 -aspect 300 -text \
"Unable to read file $loadfile" \
-relief raised
label $w.bm -bitmap error
pack $w.bm $w.m -pady 10 -side top -padx 10
wm title $w "Xconfig Internal Error"
 
set oldFocus [focus]
frame $w.f
button $w.f.back -text "Bummer" \
-width 10 -command "destroy $w; focus $oldFocus"
pack $w.f.back -side bottom -pady 10 -anchor s
pack $w.f -pady 10 -side top -padx 10 -anchor s
focus $w
global winx; global winy
set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
wm geometry $w +$winx+$winy
}
}
 
proc write_config_file { w } {
global loadfile
if { [string length $loadfile] != 0
&& ([file writable $loadfile] == 1 || ([file exists $loadfile] == 0 && [file writable [file dirname $loadfile]] == 1)) } then {
writeconfig $loadfile /dev/null
} else {
catch {destroy $w}
toplevel $w -class Dialog
message $w.m -width 400 -aspect 300 -text \
"Unable to write file $loadfile" \
-relief raised
label $w.bm -bitmap error
pack $w.bm $w.m -pady 10 -side top -padx 10
wm title $w "Xconfig Internal Error"
 
set oldFocus [focus]
frame $w.f
button $w.f.back -text "OK" \
-width 10 -command "destroy $w; focus $oldFocus"
pack $w.f.back -side bottom -pady 10 -anchor s
pack $w.f -pady 10 -side top -padx 10 -anchor s
focus $w
global winx; global winy
set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
wm geometry $w +$winx+$winy
}
}
 
proc read_config { filename } {
set file1 [open $filename r]
clear_choices
while { [gets $file1 line] >= 0} {
if [regexp {([0-9A-Za-z_]+)=([ynm])} $line foo var value] {
if { $value == "y" } then { set cmd "global $var; set $var 1" }
if { $value == "n" } then { set cmd "global $var; set $var 0" }
if { $value == "m" } then { set cmd "global $var; set $var 2" }
eval $cmd
}
if [regexp {# ([0-9A-Za-z_]+) is not set} $line foo var] {
set cmd "global $var; set $var 0"
eval $cmd
}
if [regexp {([0-9A-Za-z_]+)=([0-9A-Fa-f]+)} $line foo var value] {
set cmd "global $var; set $var $value"
eval $cmd
}
if [regexp {([0-9A-Za-z_]+)="([^"]*)"} $line foo var value] {
set cmd "global $var; set $var \"$value\""
eval $cmd
}
}
close $file1
update_choices
update_mainmenu
}
proc write_comment { file1 file2 text } {
puts $file1 ""
puts $file1 "#"
puts $file1 "# $text"
puts $file1 "#"
puts $file2 "/*"
puts $file2 " * $text"
puts $file2 " */"
}
 
proc effective_dep { deplist } {
global CONFIG_MODULES
set depend 1
foreach i $deplist {
if {$i == 0} then {set depend 0}
if {$i == 2 && $depend == 1} then {set depend 2}
}
if {$depend == 2 && $CONFIG_MODULES == 0} then {set depend 0}
return $depend
}
 
proc sync_tristate { var dep } {
global CONFIG_MODULES
if {$dep == 0 && ($var == 1 || $var == 2)} then {
set var 0
} elseif {$dep == 2 && $var == 1} then {
set var 2
} elseif {$var == 2 && $CONFIG_MODULES == 0} then {
if {$dep == 1} then {set var 1} else {set var 0}
}
return $var
}
 
proc sync_bool { var dep modset } {
set var [sync_tristate $var $dep]
if {$dep == 2 && $var == 2} then {
set var $modset
}
return $var
}
 
proc write_tristate { file1 file2 varname variable deplist modset } {
set variable [sync_tristate $variable [effective_dep $deplist]]
if { $variable == 2 } \
then { set variable $modset }
if { $variable == 1 } \
then { puts $file1 "$varname=y"; \
puts $file2 "#define $varname 1" } \
elseif { $variable == 2 } \
then { puts $file1 "$varname=m"; \
puts $file2 "#undef $varname"; \
puts $file2 "#define ${varname}_MODULE 1" } \
elseif { $variable == 0 } \
then { puts $file1 "# $varname is not set"; \
puts $file2 "#undef $varname"} \
else { \
puts stdout "ERROR - Attempting to write value for unconfigured variable ($varname)." \
}
}
 
proc write_int { file1 file2 varname variable dep } {
if { $dep == 0 } \
then { puts $file1 "# $varname is not set"; \
puts $file2 "#undef $varname"} \
else {
puts $file1 "$varname=$variable"; \
puts $file2 "#define $varname ($variable)"; \
}
}
 
proc write_hex { file1 file2 varname variable dep } {
if { $dep == 0 } \
then { puts $file1 "# $varname is not set"; \
puts $file2 "#undef $varname"} \
else {
puts $file1 "$varname=$variable"; \
puts -nonewline $file2 "#define $varname 0x"; \
puts $file2 [exec echo $variable | sed s/^0\[xX\]//]; \
}
}
 
proc write_string { file1 file2 varname variable dep } {
if { $dep == 0 } \
then { puts $file1 "# $varname is not set"; \
puts $file2 "#undef $varname"} \
else {
puts $file1 "$varname=\"$variable\""; \
puts $file2 "#define $varname \"$variable\""; \
}
}
 
proc option_name {w mnum line text helpidx} {
button $w.x$line.l -text "$text" -relief groove -anchor w
$w.x$line.l configure -activefore [cget $w.x$line.l -fg] \
-activeback [cget $w.x$line.l -bg]
button $w.x$line.help -text "Help" -relief raised \
-command "dohelp .dohelp $helpidx .menu$mnum"
pack $w.x$line.help -side right -fill y
pack $w.x$line.l -side right -fill both -expand on
}
 
proc toggle_switch2 {w mnum line text variable} {
frame $w.x$line -relief sunken
radiobutton $w.x$line.y -text "y" -variable $variable -value 1 \
-relief groove -width 2 -command "update_active"
radiobutton $w.x$line.m -text "-" -variable $variable -value 2 \
-relief groove -width 2 -command "update_active"
radiobutton $w.x$line.n -text "n" -variable $variable -value 0 \
-relief groove -width 2 -command "update_active"
 
option_name $w $mnum $line $text $variable
 
pack $w.x$line.n $w.x$line.m $w.x$line.y -side right -fill y
}
 
proc toggle_switch3 {w mnum line text variable} {
frame $w.x$line -relief sunken
radiobutton $w.x$line.y -text "y" -variable $variable -value 1 \
-relief groove -width 2 -command "update_active"
radiobutton $w.x$line.m -text "m" -variable $variable -value 2 \
-relief groove -width 2 -command "update_active"
radiobutton $w.x$line.n -text "n" -variable $variable -value 0 \
-relief groove -width 2 -command "update_active"
 
option_name $w $mnum $line $text $variable
 
global CONFIG_MODULES
if {($CONFIG_MODULES == 0)} then {
$w.x$line.m configure -state disabled
}
pack $w.x$line.n $w.x$line.m $w.x$line.y -side right -fill y
}
 
proc bool {w mnum line text variable} {
toggle_switch2 $w $mnum $line $text $variable
$w.x$line.m configure -state disabled
pack $w.x$line -anchor w -fill both -expand on
}
 
proc tristate {w mnum line text variable } {
toggle_switch3 $w $mnum $line $text $variable
pack $w.x$line -anchor w -fill both -expand on
}
 
proc dep_tristate {w mnum line text variable } {
tristate $w $mnum $line $text $variable
}
 
proc dep_bool {w mnum line text variable } {
bool $w $mnum $line $text $variable
}
 
proc int { w mnum line text variable } {
frame $w.x$line
entry $w.x$line.x -width 18 -relief sunken -borderwidth 2 \
-textvariable $variable
option_name $w $mnum $line $text $variable
pack $w.x$line.x -anchor w -side right -fill y
pack $w.x$line -anchor w -fill both -expand on
}
 
proc hex { w mnum line text variable } {
int $w $mnum $line $text $variable
}
 
proc istring { w mnum line text variable } {
frame $w.x$line
entry $w.x$line.x -width 18 -relief sunken -borderwidth 2 \
-textvariable $variable
option_name $w $mnum $line $text $variable
pack $w.x$line.x -anchor w -side right -fill y
pack $w.x$line -anchor w -fill both -expand on
}
 
proc minimenu { w mnum line text variable helpidx } {
frame $w.x$line
menubutton $w.x$line.x -textvariable $variable -menu \
$w.x$line.x.menu -relief raised \
-anchor w
option_name $w $mnum $line $text $helpidx
pack $w.x$line.x -anchor w -side right -fill y
pack $w.x$line -anchor w -fill both -expand on
}
 
proc menusplit {w m n} {
if { $n > 2 } then {
update idletasks
set menuoptsize [expr [$m yposition 2] - [$m yposition 1]]
set maxsize [winfo screenheight $w]
set splitpoint [expr $maxsize * 4 / 5 / $menuoptsize - 1]
for {set i [expr $splitpoint + 1]} {$i <= $n} {incr i $splitpoint} {
$m entryconfigure $i -columnbreak 1
}
}
}
 
proc menutitle {text menu w} {
wm title $w "$text"
}
 
proc submenu { w mnum line text subnum } {
frame $w.x$line
button $w.x$line.l -text "" -width 15 -relief groove
$w.x$line.l configure -activefore [cget $w.x$line.l -fg] \
-activeback [cget $w.x$line.l -bg] -state disabled
button $w.x$line.m -text "$text" -relief raised -anchor w \
-command "catch {destroy .menu$subnum}; menu$subnum .menu$subnum \"$text\""
pack $w.x$line.l -side left -fill both
pack $w.x$line.m -anchor w -side right -fill both -expand on
pack $w.x$line -anchor w -fill both -expand on
}
 
proc comment {w mnum line text } {
frame $w.x$line
button $w.x$line.l -text "" -width 15 -relief groove
$w.x$line.l configure -activefore [cget $w.x$line.l -fg] \
-activeback [cget $w.x$line.l -bg] -state disabled
button $w.x$line.m -text "$text" -relief groove -anchor w
$w.x$line.m configure -activefore [cget $w.x$line.m -fg] \
-activeback [cget $w.x$line.m -bg]
pack $w.x$line.l -side left -fill both
pack $w.x$line.m -anchor w -side right -fill both -expand on
pack $w.x$line -anchor w -fill both -expand on
}
 
proc dohelp {w var parent} {
catch {destroy $w}
toplevel $w -class Dialog
 
set filefound 0
set found 0
set lineno 0
 
if { [file readable Documentation/Configure.help] == 1} then {
set filefound 1
# First escape sed regexp special characters in var:
set var [exec echo "$var" | sed s/\[\]\[\/.^$*\]/\\\\&/g]
# Now pick out right help text:
set message [exec sed -n "
/^$var\[ \]*\$/,\${
/^$var\[ \]*\$/c\\
${var}:\\
 
/^#/b
/^\[^ \]/q
s/^ //
/<file:\\(\[^>\]*\\)>/s//\\1/g
p
}
" Documentation/Configure.help]
set found [expr [string length "$message"] > 0]
}
 
frame $w.f1
pack $w.f1 -fill both -expand on
 
# Do the OK button
#
set oldFocus [focus]
frame $w.f2
button $w.f2.ok -text "OK" \
-width 10 -command "destroy $w; catch {focus $oldFocus}"
pack $w.f2.ok -side bottom -pady 6 -anchor n
pack $w.f2 -side bottom -padx 10 -anchor s
 
scrollbar $w.f1.vscroll -command "$w.f1.canvas yview"
pack $w.f1.vscroll -side right -fill y
 
canvas $w.f1.canvas -relief flat -borderwidth 0 \
-yscrollcommand "$w.f1.vscroll set"
frame $w.f1.f
pack $w.f1.canvas -side right -fill y -expand on
 
if { $found == 0 } then {
if { $filefound == 0 } then {
message $w.f1.f.m -width 750 -aspect 300 -relief flat -text \
"No help available - unable to open file Documentation/Configure.help. This file should have come with your kernel."
} else {
message $w.f1.f.m -width 400 -aspect 300 -relief flat -text \
"No help available for $var"
}
label $w.f1.bm -bitmap error
wm title $w "RTFM"
} else {
text $w.f1.f.m -width 73 -relief flat -wrap word
$w.f1.f.m insert 0.0 $message
$w.f1.f.m conf -state disabled -height [$w.f1.f.m index end]
 
label $w.f1.bm -bitmap info
wm title $w "Configuration help"
}
pack $w.f1.f.m -side left
pack $w.f1.bm $w.f1.f -side left -padx 10
 
focus $w
set winx [expr [winfo x $parent]+20]
set winy [expr [winfo y $parent]+20]
wm geometry $w +$winx+$winy
set sizok [expr [winfo reqheight $w.f2.ok] + 12]
set maxy [expr [winfo screenheight .] * 3 / 4]
set canvtotal [winfo reqheight $w.f1.f.m]
if [expr $sizok + $canvtotal < $maxy] {
set sizy $canvtotal
} else {
set sizy [expr $maxy - $sizok]
}
$w.f1.canvas configure -height $sizy -width [winfo reqwidth $w.f1.f.m] \
-scrollregion "0 0 [winfo reqwidth $w.f1.f.m] \
[winfo reqheight $w.f1.f.m]"
$w.f1.canvas create window 0 0 -anchor nw -window $w.f1.f
update idletasks
 
set maxy [winfo screenheight .]
if [expr $sizok + $canvtotal < $maxy] {
set sizy [expr $sizok + $canvtotal]
} else {
set sizy $maxy
}
wm maxsize $w [winfo width $w] $sizy
}
 
bind all <Alt-s> { catch {exec cp -f .config .config.old}; \
writeconfig .config include/linux/autoconf.h; wrapup .wrap }
 
proc wrapup {w } {
catch {destroy $w}
toplevel $w -class Dialog
 
global CONFIG_MODVERSIONS; vfix CONFIG_MODVERSIONS
if { ([file exists .hdepend] != 1) || ($CONFIG_MODVERSIONS == 1) } then {
message $w.m -width 400 -aspect 300 -relief raised -text \
"End of Linux kernel configuration. Check the top-level Makefile for additional configuration. Next, you must run 'make dep'."
} else {
message $w.m -width 400 -aspect 300 -relief raised -text \
"End of Linux kernel configuration. Check the top-level Makefile for additional configuration. Next, you may 'make bzImage', 'make bzdisk', or 'make bzlilo.'"
}
label $w.bm -bitmap info
pack $w.bm $w.m -pady 10 -side top -padx 10
wm title $w "Kernel build instructions"
 
set oldFocus [focus]
frame $w.f
button $w.f.back -text "OK" \
-width 10 -command "exit"
pack $w.f.back -side bottom -pady 10 -anchor s
pack $w.f -pady 10 -side top -padx 10 -anchor s
focus $w
bind $w <Return> "exit"
global winx; global winy
set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
wm geometry $w +$winx+$winy
 
}
 
proc unregister_active {num} {
global active_menus
set index [lsearch -exact $active_menus $num]
if {$index != -1} then {set active_menus [lreplace $active_menus $index $index]}
}
 
proc update_active {} {
global active_menus total_menus
set max 0
if {[llength $active_menus] > 0} then {
set max [lindex $active_menus end]
update_define [toplevel_menu [lindex $active_menus 0]] $max 0
}
foreach i $active_menus {
if {[winfo exists .menu$i] == 0} then {
unregister_active $i
} else {
update_menu$i
}
}
update_define [expr $max + 1] $total_menus 1
update_mainmenu
}
 
proc configure_entry {w option items} {
foreach i $items {
$w.$i configure -state $option
}
}
 
proc validate_int {name val default} {
if {([exec echo $val | sed s/^-//g | tr -d \[:digit:\] ] != "")} then {
global $name; set $name $default
}
}
 
proc validate_hex {name val default} {
if {([exec echo $val | tr -d \[:xdigit:\] ] != "")} then {
global $name; set $name $default
}
}
 
proc update_define {first last allow_update} {
for {set i $first} {$i <= $last} {incr i} {
update_define_menu$i
if {$allow_update == 1} then update
}
}
 
#
# Next set up the particulars for the top level menu, and define a few
# buttons which we will stick down at the bottom.
#
 
frame .f0
frame .f0.left
frame .f0.middle
frame .f0.right
 
set active_menus [list]
set processed_top_level 0
/tail.tk
0,0 → 1,89
# FILE: tail.tk
# This file is boilerplate TCL/TK function definitions for 'make xconfig'.
#
# CHANGES
# =======
#
# 8 January 1998, Michael Elizabeth Chastain, <mec@shout.net>
# Arrange buttons in three columns for better screen fitting.
#
 
#
# Read the user's settings from .config. These will override whatever is
# in config.in. Don't do this if the user specified a -D to force
# the defaults.
#
if { [file readable .config] == 1} then {
if { $argc > 0 } then {
if { [lindex $argv 0] != "-D" } then {
read_config .config
}
else
{
read_config $defaults
}
} else {
read_config .config
}
} else {
read_config $defaults
}
 
update_define 1 $total_menus 0
update_mainmenu
 
button .f0.right.save -anchor w -text "Save and Exit" -underline 0\
-command { catch {exec cp -f .config .config.old}; \
writeconfig .config include/linux/autoconf.h; wrapup .wrap }
 
button .f0.right.quit -anchor w -text "Quit Without Saving" -underline 0\
-command { maybe_exit .maybe }
 
button .f0.right.load -anchor w -text "Load Configuration from File" \
-command { load_configfile .load "Load Configuration from file" read_config_file
}
 
button .f0.right.store -anchor w -text "Store Configuration to File" \
-command { load_configfile .load "Store Configuration to file" write_config_file }
 
#
# Now pack everything.
#
 
pack .f0.right.store .f0.right.load .f0.right.quit .f0.right.save \
-padx 0 -pady 0 -side bottom -fill x
pack .f0.left .f0.middle .f0.right -side left -padx 5 -pady 0 -fill y
pack .f0 -padx 5 -pady 5
 
update idletasks
set winy [expr 10 + [winfo reqheight .f0]]
set scry [lindex [wm maxsize .] 1]
set winx [expr 10 + [winfo reqwidth .f0]]
set scrx [lindex [wm maxsize .] 0]
if {$winx < $scrx} then {set maxx -1} else {set maxx $winx}
if {$winy < $scry} then {set maxy -1} else {set maxy $winy}
.f0 configure -width $winx -height $winy
wm maxsize . $maxx $maxy
 
#
# If we cannot write our config files, disable the write button.
#
if { [file exists .config] == 1 } then {
if { [file writable .config] == 0 } then {
.f0.right.save configure -state disabled
}
} else {
if { [file writable .] == 0 } then {
.f0.right.save configure -state disabled
}
}
 
if { [file exists include/linux/autoconf.h] == 1 } then {
if { [file writable include/linux/autoconf.h] == 0 } then {
.f0.right.save configure -state disabled
}
} else {
if { [file writable include/linux/] == 0 } then {
.f0.right.save configure -state disabled
}
}
/gen-all-syms
0,0 → 1,7
#!/bin/sh
for i in $*
do
grep "EXPORT_SYMBOL.*(.*)" "$i" \
| sed -e "s/EXPORT_SYMBOL.*(/ /" \
| sed -e "s/).*$//" | sed -e "s/^ //"
done
/ver_linux
0,0 → 1,85
#!/bin/sh
# Before running this script please ensure that your PATH is
# typical as you use for compilation/istallation. I use
# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may
# differ on your system.
#
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:$PATH
echo 'If some fields are empty or look unusual you may have an old version.'
echo 'Compare to the current minimal requirements in Documentation/Changes.'
echo ' '
 
uname -a
echo ' '
 
gcc --version 2>&1| head -n 1 | grep -v gcc | awk \
'NR==1{print "Gnu C ", $1}'
 
gcc --version 2>&1| grep gcc | awk \
'NR==1{print "Gnu C ", $3}'
 
make --version 2>&1 | awk -F, '{print $1}' | awk \
'/GNU Make/{print "Gnu make ",$NF}'
 
ld -v 2>&1 | awk -F\) '{print $1}' | awk \
'/BFD/{print "binutils ",$NF}'
 
fdformat --version | awk -F\- '{print "util-linux ", $NF}'
 
mount --version | awk -F\- '{print "mount ", $NF}'
 
insmod -V 2>&1 | awk 'NR==1 {print "modutils ",$NF}'
 
tune2fs 2>&1 | grep "^tune2fs" | sed 's/,//' | awk \
'NR==1 {print "e2fsprogs ", $2}'
 
fsck.jfs -V 2>&1 | grep version | sed 's/,//' | awk \
'NR==1 {print "jfsutils ", $3}'
 
reiserfsck -V 2>&1 | grep reiserfsprogs | awk \
'NR==1{print "reiserfsprogs ", $NF}'
 
xfs_db -V 2>&1 | grep version | awk \
'NR==1{print "xfsprogs ", $3}'
 
cardmgr -V 2>&1| grep version | awk \
'NR==1{print "pcmcia-cs ", $3}'
 
quota -V 2>&1 | grep version | awk \
'NR==1{print "quota-tools ", $NF}'
 
pppd --version 2>&1| grep version | awk \
'NR==1{print "PPP ", $3}'
 
isdnctrl 2>&1 | grep version | awk \
'NR==1{print "isdn4k-utils ", $NF}'
 
ls -l `ldd /bin/sh | awk '/libc/{print $3}'` | sed \
-e 's/\.so$//' | awk -F'[.-]' '{print "Linux C Library " \
$(NF-2)"."$(NF-1)"."$NF}'
 
ldd -v > /dev/null 2>&1 && ldd -v || ldd --version |head -1 | awk \
'NR==1{print "Dynamic linker (ldd) ", $NF}'
 
ls -l /usr/lib/lib{g,stdc}++.so 2>/dev/null | awk -F. \
'{print "Linux C++ Library " $4"."$5"."$6}'
 
ps --version 2>&1 | awk 'NR==1{print "Procps ", $NF}'
 
ifconfig --version 2>&1 | grep tools | awk \
'NR==1{print "Net-tools ", $NF}'
 
# Kbd needs 'loadkeys -h',
loadkeys -h 2>&1 | awk \
'(NR==1 && ($3 !~ /option/)) {print "Kbd ", $3}'
 
# while console-tools needs 'loadkeys -V'.
loadkeys -V 2>&1 | awk \
'(NR==1 && ($2 ~ /console-tools/)) {print "Console-tools ", $3}'
 
expr --v 2>&1 | awk 'NR==1{print "Sh-utils ", $NF}'
 
if [ -e /proc/modules ]; then
X=`cat /proc/modules | sed -e "s/ .*$//"`
echo "Modules Loaded "$X
fi
/mkversion
0,0 → 1,6
if [ ! -f .version ]
then
echo 1
else
expr 0`cat .version` + 1
fi
/Makefile
0,0 → 1,45
HEADER=header.tk
TAIL=tail.tk
 
# Previous versions always remade kconfig.tk because they always depended
# on soundscript. This runs fairly fast, and I can't find all the
# Config.in files to depend on anyways. So I'll force it to remake.
 
kconfig.tk: dummy
 
kconfig.tk: ${TOPDIR}/Makefile ${TOPDIR}/arch/${ARCH}/config.in \
tkparse ${HEADER} ${TAIL}
@if [ -f /usr/local/bin/wish ]; then \
echo '#!'"/usr/local/bin/wish -f" > kconfig.tk; \
else \
echo '#!'"/usr/bin/wish -f" > kconfig.tk; \
fi
cat ${HEADER} >> ./kconfig.tk
./tkparse < ../arch/${ARCH}/config.in >> kconfig.tk
echo "set defaults \"arch/${ARCH}/defconfig\"" >> kconfig.tk
echo "set ARCH \"${ARCH}\"" >> kconfig.tk
cat ${TAIL} >> kconfig.tk
chmod 755 kconfig.tk
 
tkparse: tkparse.o tkcond.o tkgen.o
${HOSTCC} -o tkparse tkparse.o tkcond.o tkgen.o
 
tkparse.o: tkparse.c tkparse.h
 
tkcond.o: tkcond.c tkparse.h
 
tkgen.o: tkgen.c tkparse.h
 
tkparse.o tkcond.o tkgen.o:
$(HOSTCC) $(HOSTCFLAGS) -c -o $@ $(@:.o=.c)
 
docproc.o: docproc.c
$(HOSTCC) $(HOSTCFLAGS) -c -o $@ $(@:.o=.c)
 
docproc: docproc.o
${HOSTCC} -o docproc docproc.o
 
clean:
rm -f *~ kconfig.tk *.o tkparse mkdep split-include docproc
 
include $(TOPDIR)/Rules.make
/checkconfig.pl
0,0 → 1,65
#! /usr/bin/perl
#
# checkconfig: find uses of CONFIG_* names without matching definitions.
# Copyright abandoned, 1998, Michael Elizabeth Chastain <mailto:mec@shout.net>.
 
use integer;
 
$| = 1;
 
foreach $file (@ARGV)
{
# Open this file.
open(FILE, $file) || die "Can't open $file: $!\n";
 
# Initialize variables.
my $fInComment = 0;
my $fInString = 0;
my $fUseConfig = 0;
my $iLinuxConfig = 0;
my %configList = ();
 
LINE: while ( <FILE> )
{
# Strip comments.
$fInComment && (s+^.*?\*/+ +o ? ($fInComment = 0) : next);
m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1)));
 
# Pick up definitions.
if ( m/^\s*#/o )
{
$iLinuxConfig = $. if m/^\s*#\s*include\s*"linux\/config\.h"/o;
$configList{uc $1} = 1 if m/^\s*#\s*include\s*"config\/(\S*)\.h"/o;
}
 
# Strip strings.
$fInString && (s+^.*?"+ +o ? ($fInString = 0) : next);
m+"+o && (s+".*?"+ +go, (s+".*$+ +o && ($fInString = 1)));
 
# Pick up definitions.
if ( m/^\s*#/o )
{
$iLinuxConfig = $. if m/^\s*#\s*include\s*<linux\/config\.h>/o;
$configList{uc $1} = 1 if m/^\s*#\s*include\s*<config\/(\S*)\.h>/o;
$configList{$1} = 1 if m/^\s*#\s*define\s+CONFIG_(\w*)/o;
$configList{$1} = 1 if m/^\s*#\s*undef\s+CONFIG_(\w*)/o;
}
 
# Look for usages.
next unless m/CONFIG_/o;
WORD: while ( m/\bCONFIG_(\w+)/og )
{
$fUseConfig = 1;
last LINE if $iLinuxConfig;
next WORD if exists $configList{$1};
print "$file: $.: need CONFIG_$1.\n";
$configList{$1} = 0;
}
}
 
# Report superfluous includes.
if ( $iLinuxConfig && ! $fUseConfig )
{ print "$file: $iLinuxConfig: linux/config.h not needed.\n"; }
 
close(FILE);
}
/checkincludes.pl
0,0 → 1,24
#!/usr/bin/perl
#
# checkincludes: Find files included more than once in (other) files.
# Copyright abandoned, 2000, Niels Kristian Bech Jensen <nkbj@image.dk>.
 
foreach $file (@ARGV) {
open(FILE, $file) or die "Cannot open $file: $!.\n";
 
my %includedfiles = ();
 
while (<FILE>) {
if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) {
++$includedfiles{$1};
}
}
foreach $filename (keys %includedfiles) {
if ($includedfiles{$filename} > 1) {
print "$file: $filename is included more than once.\n";
}
}
 
close(FILE);
}
/Configure
0,0 → 1,575
#! /bin/sh
#
# This script is used to configure the Linux kernel.
#
# It was inspired by the challenge in the original Configure script
# to ``do something better'', combined with the actual need to ``do
# something better'' because the old configure script wasn't flexible
# enough.
#
# Raymond Chen was the original author of Configure.
# Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
#
# 050793 - use IFS='@' to get around a bug in a pre-version of bash-1.13
# with an empty IFS.
#
# 030995 (storner@osiris.ping.dk) - added support for tri-state answers,
# for selecting modules to compile.
#
# 180995 Bernhard Kaindl (bkaindl@ping.at) - added dummy functions for
# use with a config.in modified for make menuconfig.
#
# 301195 (boldt@math.ucsb.edu) - added help text support
#
# 281295 Paul Gortmaker - make tri_state functions collapse to boolean
# if module support is not enabled.
#
# 010296 Aaron Ucko (ucko@vax1.rockhurst.edu) - fix int and hex to accept
# arbitrary ranges
#
# 150296 Dick Streefland (dicks@tasking.nl) - report new configuration
# items and ask for a value even when doing a "make oldconfig"
#
# 200396 Tom Dyas (tdyas@eden.rutgers.edu) - when the module option is
# chosen for an item, define the macro <option_name>_MODULE
#
# 090397 Axel Boldt (boldt@math.ucsb.edu) - avoid ? and + in regular
# expressions for GNU expr since version 1.15 and up use \? and \+.
#
# 300397 Phil Blundell (pjb27@cam.ac.uk) - added support for min/max
# arguments to "int", allow dep_tristate to take a list of dependencies
# rather than just one.
#
# 090398 Axel Boldt (boldt@math.ucsb.edu) - allow for empty lines in help
# texts.
#
# 102598 Michael Chastain (mec@shout.net) - put temporary files in
# current directory, not in /tmp.
#
# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
# - Improve the exit message (Jeff Ronne).
 
#
# Make sure we're really running bash.
#
# I would really have preferred to write this script in a language with
# better string handling, but alas, bash is the only scripting language
# that I can be reasonable sure everybody has on their linux machine.
#
[ -z "$BASH" ] && { echo "Configure requires bash" 1>&2; exit 1; }
 
# Disable filename globbing once and for all.
# Enable function cacheing.
set -f -h
 
#
# Dummy functions for use with a config.in modified for menuconf
#
function mainmenu_option () {
:
}
function mainmenu_name () {
:
}
function endmenu () {
:
}
 
#
# help prints the corresponding help text from Configure.help to stdout
#
# help variable
#
function help () {
if [ -f Documentation/Configure.help ]
then
#first escape regexp special characters in the argument:
var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g')
#now pick out the right help text:
text=$(sed -n "/^$var[ ]*\$/,\${
/^$var[ ]*\$/c\\
${var}:\\
 
/^#/b
/^[^ ]/q
/<file:\\([^>]*\\)>/s//\\1/g
p
}" Documentation/Configure.help)
if [ -z "$text" ]
then
echo; echo " Sorry, no help available for this option yet.";echo
else
(echo; echo "$text") | ${PAGER:-more}
fi
else
echo;
echo " Can't access the file Documentation/Configure.help which"
echo " should contain the help texts."
echo
fi
}
 
 
#
# readln reads a line into $ans.
#
# readln prompt default oldval
#
function readln () {
if [ "$DEFAULT" = "-d" -a -n "$3" ]; then
echo "$1"
ans=$2
else
echo -n "$1"
[ -z "$3" ] && echo -n "(NEW) "
IFS='@' read ans || exit 1
[ -z "$ans" ] && ans=$2
fi
}
 
#
# comment does some pretty-printing
#
# comment 'xxx'
#
function comment () {
echo "*"; echo "* $1" ; echo "*"
(echo "" ; echo "#"; echo "# $1" ; echo "#") >>$CONFIG
(echo "" ; echo "/*"; echo " * $1" ; echo " */") >>$CONFIG_H
}
 
#
# define_bool sets the value of a boolean argument
#
# define_bool define value
#
function define_bool () {
define_tristate $1 $2
}
 
function define_tristate () {
case "$2" in
"y")
echo "$1=y" >>$CONFIG
echo "#define $1 1" >>$CONFIG_H
;;
 
"m")
echo "$1=m" >>$CONFIG
echo "#undef $1" >>$CONFIG_H
echo "#define $1_MODULE 1" >>$CONFIG_H
;;
 
"n")
echo "# $1 is not set" >>$CONFIG
echo "#undef $1" >>$CONFIG_H
;;
esac
eval "$1=$2"
}
 
#
# bool processes a boolean argument
#
# bool question define
#
function bool () {
old=$(eval echo "\${$2}")
def=${old:-'n'}
case "$def" in
"y" | "m") defprompt="Y/n/?"
def="y"
;;
"n") defprompt="N/y/?"
;;
esac
while :; do
readln "$1 ($2) [$defprompt] " "$def" "$old"
case "$ans" in
[yY] | [yY]es ) define_bool "$2" "y"
break;;
[nN] | [nN]o ) define_bool "$2" "n"
break;;
* ) help "$2"
;;
esac
done
}
 
#
# tristate processes a tristate argument
#
# tristate question define
#
function tristate () {
if [ "$CONFIG_MODULES" != "y" ]; then
bool "$1" "$2"
else
old=$(eval echo "\${$2}")
def=${old:-'n'}
case "$def" in
"y") defprompt="Y/m/n/?"
;;
"m") defprompt="M/n/y/?"
;;
"n") defprompt="N/y/m/?"
;;
esac
while :; do
readln "$1 ($2) [$defprompt] " "$def" "$old"
case "$ans" in
[yY] | [yY]es ) define_tristate "$2" "y"
break ;;
[nN] | [nN]o ) define_tristate "$2" "n"
break ;;
[mM] ) define_tristate "$2" "m"
break ;;
* ) help "$2"
;;
esac
done
fi
}
 
#
# dep_tristate processes a tristate argument that depends upon
# another option or options. If any of the options we depend upon is a
# module, then the only allowable options are M or N. If all are Y, then
# this is a normal tristate. This is used in cases where modules
# are nested, and one module requires the presence of something
# else in the kernel.
#
# dep_tristate question define default ...
#
function dep_tristate () {
old=$(eval echo "\${$2}")
def=${old:-'n'}
ques=$1
var=$2
need_module=0
shift 2
while [ $# -gt 0 ]; do
case "$1" in
n)
define_tristate "$var" "n"
return
;;
m)
need_module=1
;;
esac
shift
done
 
if [ $need_module = 1 ]; then
if [ "$CONFIG_MODULES" = "y" ]; then
case "$def" in
"y" | "m") defprompt="M/n/?"
def="m"
;;
"n") defprompt="N/m/?"
;;
esac
while :; do
readln "$ques ($var) [$defprompt] " "$def" "$old"
case "$ans" in
[nN] | [nN]o ) define_tristate "$var" "n"
break ;;
[mM] ) define_tristate "$var" "m"
break ;;
[yY] | [yY]es ) echo
echo " This answer is not allowed, because it is not consistent with"
echo " your other choices."
echo " This driver depends on another one which you chose to compile"
echo " as a module. This means that you can either compile this one"
echo " as a module as well (with M) or leave it out altogether (N)."
echo
;;
* ) help "$var"
;;
esac
done
fi
else
tristate "$ques" "$var"
fi
}
 
function dep_bool () {
ques=$1
var=$2
shift 2
while [ $# -gt 0 ]; do
case "$1" in
m | n)
define_bool "$var" "n"
return
;;
esac
shift
done
 
bool "$ques" "$var"
}
 
function dep_mbool () {
ques=$1
var=$2
shift 2
while [ $# -gt 0 ]; do
case "$1" in
n)
define_bool "$var" "n"
return
;;
esac
shift
done
 
bool "$ques" "$var"
}
 
#
# define_int sets the value of a integer argument
#
# define_int define value
#
function define_int () {
echo "$1=$2" >>$CONFIG
echo "#define $1 ($2)" >>$CONFIG_H
eval "$1=$2"
}
 
#
# int processes an integer argument with optional limits
#
# int question define default
#
function int () {
old=$(eval echo "\${$2}")
def=${old:-$3}
while :; do
readln "$1 ($2) [$def] " "$def" "$old"
if expr "$ans" : '[0-9]*$' > /dev/null; then
define_int "$2" "$ans"
break
else
help "$2"
fi
done
}
 
#
# define_hex sets the value of a hexadecimal argument
#
# define_hex define value
#
function define_hex () {
echo "$1=$2" >>$CONFIG
echo "#define $1 0x${2#*[x,X]}" >>$CONFIG_H
eval "$1=$2"
}
 
#
# hex processes an hexadecimal argument
#
# hex question define default
#
function hex () {
old=$(eval echo "\${$2}")
def=${old:-$3}
def=${def#*[x,X]}
while :; do
readln "$1 ($2) [$def] " "$def" "$old"
ans=${ans#*[x,X]}
if expr "$ans" : '[0-9a-fA-F][0-9a-fA-F]*$' > /dev/null; then
define_hex "$2" "$ans"
break
else
help "$2"
fi
done
}
 
#
# define_string sets the value of a string argument
#
# define_string define value
#
function define_string () {
echo "$1=\"$2\"" >>$CONFIG
echo "#define $1 \"$2\"" >>$CONFIG_H
eval "$1=\"$2\""
}
 
#
# string processes a string argument
#
# string question define default
#
function string () {
old=$(eval echo "\${$2}")
def=${old:-$3}
while :; do
if [ "$old" = "?" ]; then
readln "$1 ($2) [$def] " "$def" ""
else
readln "$1 ($2) [$def] " "$def" "$old"
fi
if [ "$ans" = "?" ]; then
help "$2"
else
break
fi
done
define_string "$2" "$ans"
}
#
# choice processes a choice list (1-out-of-n)
#
# choice question choice-list default
#
# The choice list has a syntax of:
# NAME WHITESPACE VALUE { WHITESPACE NAME WHITESPACE VALUE }
# The user may enter any unique prefix of one of the NAMEs and
# choice will define VALUE as if it were a boolean option.
# VALUE must be in all uppercase. Normally, VALUE is of the
# form CONFIG_<something>. Thus, if the user selects <something>,
# the CPP symbol CONFIG_<something> will be defined and the
# shell variable CONFIG_<something> will be set to "y".
#
function choice () {
question="$1"
choices="$2"
old=
def=$3
 
# determine default answer:
names=""
set -- $choices
firstvar=$2
while [ -n "$2" ]; do
if [ -n "$names" ]; then
names="$names, $1"
else
names="$1"
fi
if [ "$(eval echo \"\${$2}\")" = "y" ]; then
old=$1
def=$1
fi
shift; shift
done
 
val=""
while [ -z "$val" ]; do
ambg=n
readln "$question ($names) [$def] " "$def" "$old"
ans=$(echo $ans | tr a-z A-Z)
set -- $choices
while [ -n "$1" ]; do
name=$(echo $1 | tr a-z A-Z)
case "$name" in
"$ans"* | */"$ans"* )
case "$name" in
"$ans" | */"$ans"/* | \
"$ans"/* | */"$ans" )
val="$2"
break # exact match
;;
esac
if [ -n "$val" ]; then
echo;echo \
" Sorry, \"$ans\" is ambiguous; please enter a longer string."
echo
val=""
ambg=y
break
else
val="$2"
fi;;
esac
shift; shift
done
if [ "$val" = "" -a "$ambg" = "n" ]; then
help "$firstvar"
fi
done
set -- $choices
while [ -n "$2" ]; do
if [ "$2" = "$val" ]; then
echo " defined $val"
define_bool "$2" "y"
else
define_bool "$2" "n"
fi
shift; shift
done
}
 
CONFIG=.tmpconfig
CONFIG_H=.tmpconfig.h
trap "rm -f $CONFIG $CONFIG_H ; exit 1" 1 2
 
#
# Make sure we start out with a clean slate.
#
echo "#" > $CONFIG
echo "# Automatically generated make config: don't edit" >> $CONFIG
echo "#" >> $CONFIG
 
echo "/*" > $CONFIG_H
echo " * Automatically generated C config: don't edit" >> $CONFIG_H
echo " */" >> $CONFIG_H
echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H
 
DEFAULT=""
if [ "$1" = "-d" ] ; then
DEFAULT="-d"
shift
fi
 
CONFIG_IN=./config.in
if [ "$1" != "" ] ; then
CONFIG_IN=$1
fi
 
DEFAULTS=arch/$ARCH/defconfig
if [ -f .config ]; then
DEFAULTS=.config
fi
 
if [ -f $DEFAULTS ]; then
echo "#"
echo "# Using defaults found in" $DEFAULTS
echo "#"
. $DEFAULTS
sed -e 's/# \(CONFIG_[^ ]*\) is not.*/\1=n/' <$DEFAULTS >.config-is-not.$$
. .config-is-not.$$
rm .config-is-not.$$
else
echo "#"
echo "# No defaults found"
echo "#"
fi
 
. $CONFIG_IN
 
rm -f .config.old
if [ -f .config ]; then
mv .config .config.old
fi
mv .tmpconfig .config
mv .tmpconfig.h include/linux/autoconf.h
 
echo
echo "*** End of Linux kernel configuration."
echo "*** Check the top-level Makefile for additional configuration."
if [ ! -f .hdepend -o "$CONFIG_MODVERSIONS" = "y" ] ; then
echo "*** Next, you must run 'make dep'."
else
echo "*** Next, you may run 'make bzImage', 'make bzdisk', or 'make install'."
fi
echo
 
exit 0
/mkdep.c
0,0 → 1,628
/*
* Originally by Linus Torvalds.
* Smart CONFIG_* processing by Werner Almesberger, Michael Chastain.
*
* Usage: mkdep cflags -- file ...
*
* Read source files and output makefile dependency lines for them.
* I make simple dependency lines for #include <*.h> and #include "*.h".
* I also find instances of CONFIG_FOO and generate dependencies
* like include/config/foo.h.
*
* 1 August 1999, Michael Elizabeth Chastain, <mec@shout.net>
* - Keith Owens reported a bug in smart config processing. There used
* to be an optimization for "#define CONFIG_FOO ... #ifdef CONFIG_FOO",
* so that the file would not depend on CONFIG_FOO because the file defines
* this symbol itself. But this optimization is bogus! Consider this code:
* "#if 0 \n #define CONFIG_FOO \n #endif ... #ifdef CONFIG_FOO". Here
* the definition is inactivated, but I still used it. It turns out this
* actually happens a few times in the kernel source. The simple way to
* fix this problem is to remove this particular optimization.
*
* 2.3.99-pre1, Andrew Morton <andrewm@uow.edu.au>
* - Changed so that 'filename.o' depends upon 'filename.[cS]'. This is so that
* missing source files are noticed, rather than silently ignored.
*
* 2.4.2-pre3, Keith Owens <kaos@ocs.com.au>
* - Accept cflags followed by '--' followed by filenames. mkdep extracts -I
* options from cflags and looks in the specified directories as well as the
* defaults. Only -I is supported, no attempt is made to handle -idirafter,
* -isystem, -I- etc.
*/
 
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#include <sys/fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
 
 
 
char __depname[512] = "\n\t@touch ";
#define depname (__depname+9)
int hasdep;
 
struct path_struct {
int len;
char *buffer;
};
struct path_struct *path_array;
int paths;
 
 
/* Current input file */
static const char *g_filename;
 
/*
* This records all the configuration options seen.
* In perl this would be a hash, but here it's a long string
* of values separated by newlines. This is simple and
* extremely fast.
*/
char * str_config = NULL;
int size_config = 0;
int len_config = 0;
 
static void
do_depname(void)
{
if (!hasdep) {
hasdep = 1;
printf("%s:", depname);
if (g_filename)
printf(" %s", g_filename);
}
}
 
/*
* Grow the configuration string to a desired length.
* Usually the first growth is plenty.
*/
void grow_config(int len)
{
while (len_config + len > size_config) {
if (size_config == 0)
size_config = 2048;
str_config = realloc(str_config, size_config *= 2);
if (str_config == NULL)
{ perror("malloc config"); exit(1); }
}
}
 
 
 
/*
* Lookup a value in the configuration string.
*/
int is_defined_config(const char * name, int len)
{
const char * pconfig;
const char * plast = str_config + len_config - len;
for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
if (pconfig[ -1] == '\n'
&& pconfig[len] == '\n'
&& !memcmp(pconfig, name, len))
return 1;
}
return 0;
}
 
 
 
/*
* Add a new value to the configuration string.
*/
void define_config(const char * name, int len)
{
grow_config(len + 1);
 
memcpy(str_config+len_config, name, len);
len_config += len;
str_config[len_config++] = '\n';
}
 
 
 
/*
* Clear the set of configuration strings.
*/
void clear_config(void)
{
len_config = 0;
define_config("", 0);
}
 
 
 
/*
* This records all the precious .h filenames. No need for a hash,
* it's a long string of values enclosed in tab and newline.
*/
char * str_precious = NULL;
int size_precious = 0;
int len_precious = 0;
 
 
 
/*
* Grow the precious string to a desired length.
* Usually the first growth is plenty.
*/
void grow_precious(int len)
{
while (len_precious + len > size_precious) {
if (size_precious == 0)
size_precious = 2048;
str_precious = realloc(str_precious, size_precious *= 2);
if (str_precious == NULL)
{ perror("malloc"); exit(1); }
}
}
 
 
 
/*
* Add a new value to the precious string.
*/
void define_precious(const char * filename)
{
int len = strlen(filename);
grow_precious(len + 4);
*(str_precious+len_precious++) = '\t';
memcpy(str_precious+len_precious, filename, len);
len_precious += len;
memcpy(str_precious+len_precious, " \\\n", 3);
len_precious += 3;
}
 
 
 
/*
* Handle an #include line.
*/
void handle_include(int start, const char * name, int len)
{
struct path_struct *path;
int i;
 
if (len == 14 && !memcmp(name, "linux/config.h", len))
return;
 
if (len >= 7 && !memcmp(name, "config/", 7))
define_config(name+7, len-7-2);
 
for (i = start, path = path_array+start; i < paths; ++i, ++path) {
memcpy(path->buffer+path->len, name, len);
path->buffer[path->len+len] = '\0';
if (access(path->buffer, F_OK) == 0) {
do_depname();
printf(" \\\n %s", path->buffer);
return;
}
}
 
}
 
 
 
/*
* Add a path to the list of include paths.
*/
void add_path(const char * name)
{
struct path_struct *path;
char resolved_path[PATH_MAX+1];
const char *name2;
 
if (strcmp(name, ".")) {
name2 = realpath(name, resolved_path);
if (!name2) {
fprintf(stderr, "realpath(%s) failed, %m\n", name);
exit(1);
}
}
else {
name2 = "";
}
 
path_array = realloc(path_array, (++paths)*sizeof(*path_array));
if (!path_array) {
fprintf(stderr, "cannot expand path_arry\n");
exit(1);
}
 
path = path_array+paths-1;
path->len = strlen(name2);
path->buffer = malloc(path->len+1+256+1);
if (!path->buffer) {
fprintf(stderr, "cannot allocate path buffer\n");
exit(1);
}
strcpy(path->buffer, name2);
if (path->len && *(path->buffer+path->len-1) != '/') {
*(path->buffer+path->len) = '/';
*(path->buffer+(++(path->len))) = '\0';
}
}
 
 
 
/*
* Record the use of a CONFIG_* word.
*/
void use_config(const char * name, int len)
{
char *pc;
int i;
 
pc = path_array[paths-1].buffer + path_array[paths-1].len;
memcpy(pc, "config/", 7);
pc += 7;
 
for (i = 0; i < len; i++) {
char c = name[i];
if (isupper((int)c)) c = tolower((int)c);
if (c == '_') c = '/';
pc[i] = c;
}
pc[len] = '\0';
 
if (is_defined_config(pc, len))
return;
 
define_config(pc, len);
 
do_depname();
printf(" \\\n $(wildcard %s.h)", path_array[paths-1].buffer);
}
 
 
 
/*
* Macros for stunningly fast map-based character access.
* __buf is a register which holds the current word of the input.
* Thus, there is one memory access per sizeof(unsigned long) characters.
*/
 
#if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__x86_64__) || defined(__MIPSEL__) \
|| defined(__arm__)
#define LE_MACHINE
#endif
 
#ifdef LE_MACHINE
#define next_byte(x) (x >>= 8)
#define current ((unsigned char) __buf)
#else
#define next_byte(x) (x <<= 8)
#define current (__buf >> 8*(sizeof(unsigned long)-1))
#endif
 
#define GETNEXT { \
next_byte(__buf); \
if ((unsigned long) next % sizeof(unsigned long) == 0) { \
if (next >= end) \
break; \
__buf = * (unsigned long *) next; \
} \
next++; \
}
 
/*
* State machine macros.
*/
#define CASE(c,label) if (current == c) goto label
#define NOTCASE(c,label) if (current != c) goto label
 
/*
* Yet another state machine speedup.
*/
#define MAX2(a,b) ((a)>(b)?(a):(b))
#define MIN2(a,b) ((a)<(b)?(a):(b))
#define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e)))))
#define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e)))))
 
 
 
/*
* The state machine looks for (approximately) these Perl regular expressions:
*
* m|\/\*.*?\*\/|
* m|\/\/.*|
* m|'.*?'|
* m|".*?"|
* m|#\s*include\s*"(.*?)"|
* m|#\s*include\s*<(.*?>"|
* m|#\s*(?define|undef)\s*CONFIG_(\w*)|
* m|(?!\w)CONFIG_|
*
* About 98% of the CPU time is spent here, and most of that is in
* the 'start' paragraph. Because the current characters are
* in a register, the start loop usually eats 4 or 8 characters
* per memory read. The MAX5 and MIN5 tests dispose of most
* input characters with 1 or 2 comparisons.
*/
void state_machine(const char * map, const char * end)
{
const char * next = map;
const char * map_dot;
unsigned long __buf = 0;
 
for (;;) {
start:
GETNEXT
__start:
if (current > MAX5('/','\'','"','#','C')) goto start;
if (current < MIN5('/','\'','"','#','C')) goto start;
CASE('/', slash);
CASE('\'', squote);
CASE('"', dquote);
CASE('#', pound);
CASE('C', cee);
goto start;
 
/* // */
slash_slash:
GETNEXT
CASE('\n', start);
NOTCASE('\\', slash_slash);
GETNEXT
goto slash_slash;
 
/* / */
slash:
GETNEXT
CASE('/', slash_slash);
NOTCASE('*', __start);
slash_star_dot_star:
GETNEXT
__slash_star_dot_star:
NOTCASE('*', slash_star_dot_star);
GETNEXT
NOTCASE('/', __slash_star_dot_star);
goto start;
 
/* '.*?' */
squote:
GETNEXT
CASE('\'', start);
NOTCASE('\\', squote);
GETNEXT
goto squote;
 
/* ".*?" */
dquote:
GETNEXT
CASE('"', start);
NOTCASE('\\', dquote);
GETNEXT
goto dquote;
 
/* #\s* */
pound:
GETNEXT
CASE(' ', pound);
CASE('\t', pound);
CASE('i', pound_i);
CASE('d', pound_d);
CASE('u', pound_u);
goto __start;
 
/* #\s*i */
pound_i:
GETNEXT NOTCASE('n', __start);
GETNEXT NOTCASE('c', __start);
GETNEXT NOTCASE('l', __start);
GETNEXT NOTCASE('u', __start);
GETNEXT NOTCASE('d', __start);
GETNEXT NOTCASE('e', __start);
goto pound_include;
 
/* #\s*include\s* */
pound_include:
GETNEXT
CASE(' ', pound_include);
CASE('\t', pound_include);
map_dot = next;
CASE('"', pound_include_dquote);
CASE('<', pound_include_langle);
goto __start;
 
/* #\s*include\s*"(.*)" */
pound_include_dquote:
GETNEXT
CASE('\n', start);
NOTCASE('"', pound_include_dquote);
handle_include(0, map_dot, next - map_dot - 1);
goto start;
 
/* #\s*include\s*<(.*)> */
pound_include_langle:
GETNEXT
CASE('\n', start);
NOTCASE('>', pound_include_langle);
handle_include(1, map_dot, next - map_dot - 1);
goto start;
 
/* #\s*d */
pound_d:
GETNEXT NOTCASE('e', __start);
GETNEXT NOTCASE('f', __start);
GETNEXT NOTCASE('i', __start);
GETNEXT NOTCASE('n', __start);
GETNEXT NOTCASE('e', __start);
goto pound_define_undef;
 
/* #\s*u */
pound_u:
GETNEXT NOTCASE('n', __start);
GETNEXT NOTCASE('d', __start);
GETNEXT NOTCASE('e', __start);
GETNEXT NOTCASE('f', __start);
goto pound_define_undef;
 
/*
* #\s*(define|undef)\s*CONFIG_(\w*)
*
* this does not define the word, because it could be inside another
* conditional (#if 0). But I do parse the word so that this instance
* does not count as a use. -- mec
*/
pound_define_undef:
GETNEXT
CASE(' ', pound_define_undef);
CASE('\t', pound_define_undef);
 
NOTCASE('C', __start);
GETNEXT NOTCASE('O', __start);
GETNEXT NOTCASE('N', __start);
GETNEXT NOTCASE('F', __start);
GETNEXT NOTCASE('I', __start);
GETNEXT NOTCASE('G', __start);
GETNEXT NOTCASE('_', __start);
 
map_dot = next;
pound_define_undef_CONFIG_word:
GETNEXT
if (isalnum(current) || current == '_')
goto pound_define_undef_CONFIG_word;
goto __start;
 
/* \<CONFIG_(\w*) */
cee:
if (next >= map+2 && (isalnum((int)next[-2]) || next[-2] == '_'))
goto start;
GETNEXT NOTCASE('O', __start);
GETNEXT NOTCASE('N', __start);
GETNEXT NOTCASE('F', __start);
GETNEXT NOTCASE('I', __start);
GETNEXT NOTCASE('G', __start);
GETNEXT NOTCASE('_', __start);
 
map_dot = next;
cee_CONFIG_word:
GETNEXT
if (isalnum(current) || current == '_')
goto cee_CONFIG_word;
use_config(map_dot, next - map_dot - 1);
goto __start;
}
}
 
 
 
/*
* Generate dependencies for one file.
*/
void do_depend(const char * filename, const char * command)
{
int mapsize;
int pagesizem1 = getpagesize()-1;
int fd;
struct stat st;
char * map;
 
fd = open(filename, O_RDONLY);
if (fd < 0) {
perror(filename);
return;
}
 
fstat(fd, &st);
if (st.st_size == 0) {
fprintf(stderr,"%s is empty\n",filename);
close(fd);
return;
}
 
mapsize = st.st_size;
mapsize = (mapsize+pagesizem1) & ~pagesizem1;
map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
if ((long) map == -1) {
perror("mkdep: mmap");
close(fd);
return;
}
if ((unsigned long) map % sizeof(unsigned long) != 0)
{
fprintf(stderr, "do_depend: map not aligned\n");
exit(1);
}
 
hasdep = 0;
clear_config();
state_machine(map, map+st.st_size);
if (hasdep) {
puts(command);
if (*command)
define_precious(filename);
}
 
munmap(map, mapsize);
close(fd);
}
 
 
 
/*
* Generate dependencies for all files.
*/
int main(int argc, char **argv)
{
int len;
const char *hpath;
 
hpath = getenv("HPATH");
if (!hpath) {
fputs("mkdep: HPATH not set in environment. "
"Don't bypass the top level Makefile.\n", stderr);
return 1;
}
 
add_path("."); /* for #include "..." */
 
while (++argv, --argc > 0) {
if (strncmp(*argv, "-I", 2) == 0) {
if (*((*argv)+2)) {
add_path((*argv)+2);
}
else {
++argv;
--argc;
add_path(*argv);
}
}
else if (strcmp(*argv, "--") == 0) {
break;
}
}
 
add_path(hpath); /* must be last entry, for config files */
 
while (--argc > 0) {
const char * filename = *++argv;
const char * command = __depname;
g_filename = 0;
len = strlen(filename);
memcpy(depname, filename, len+1);
if (len > 2 && filename[len-2] == '.') {
if (filename[len-1] == 'c' || filename[len-1] == 'S') {
depname[len-1] = 'o';
g_filename = filename;
command = "";
}
}
do_depend(filename, command);
}
if (len_precious) {
*(str_precious+len_precious) = '\0';
printf(".PRECIOUS:%s\n", str_precious);
}
return 0;
}
/mkspec
0,0 → 1,77
#!/bin/sh
#
# Output a simple RPM spec file that uses no fancy features requring
# RPM v4. This is intended to work with any RPM distro.
#
# The only gothic bit here is redefining install_post to avoid
# stripping the symbols from files in the kernel which we want
#
# Patched for non-x86 by Opencon (L) 2002 <opencon@rio.skydome.net>
#
# That's the voodoo to see if it's a x86.
ISX86=`arch | grep -ie i.86`
if [ ! -z $ISX86 ]; then
PC=1
else
PC=0
fi
# starting to output the spec
if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then
PROVIDES=kernel-drm
fi
 
PROVIDES="$PROVIDES kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
 
echo "Name: kernel"
echo "Summary: The Linux Kernel"
echo "Version: "$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION | sed -e "s/-//g"
# we need to determine the NEXT version number so that uname and
# rpm -q will agree
echo "Release: `. scripts/mkversion`"
echo "License: GPL"
echo "Group: System Environment/Kernel"
echo "Vendor: The Linux Community"
echo "URL: http://www.kernel.org"
echo -n "Source: kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL"
echo "$EXTRAVERSION.tar.gz" | sed -e "s/-//g"
echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
echo "Provides: $PROVIDES"
echo "%define __spec_install_post /usr/lib/rpm/brp-compress || :"
echo ""
echo "%description"
echo "The Linux Kernel, the operating system core itself"
echo ""
echo "%prep"
echo "%setup -q"
echo ""
echo "%build"
# This is the first 'disagreement' between x86 and other archs.
if [ $PC = 1 ]; then
echo "make oldconfig dep clean bzImage modules"
else
echo "make oldconfig dep clean vmlinux modules"
fi
# Back on track
echo ""
echo "%install"
echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make modules_install'
# And that's the second
if [ $PC = 1 ]; then
echo 'cp arch/i386/boot/bzImage $RPM_BUILD_ROOT'"/boot/vmlinuz-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
else
echo 'cp vmlinux $RPM_BUILD_ROOT'"/boot/vmlinux-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
fi
# Back on track, again
echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
echo ""
echo "%clean"
echo '#echo -rf $RPM_BUILD_ROOT'
echo ""
echo "%files"
echo '%defattr (-, root, root)'
echo "%dir /lib/modules"
echo "/lib/modules/$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
echo "/boot/*"
echo ""
/kernel-doc
0,0 → 1,1723
#!/usr/bin/perl -w
 
use strict;
 
## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ##
## Copyright (C) 2001 Simon Huggins ##
## ##
## #define enhancements by Armin Kuster <akuster@mvista.com> ##
## Copyright (c) 2000 MontaVista Software, Inc. ##
## ##
## This software falls under the GNU General Public License. ##
## Please read the COPYING file for more information ##
 
# w.o. 03-11-2000: added the '-filelist' option.
 
# 18/01/2001 - Cleanups
# Functions prototyped as foo(void) same as foo()
# Stop eval'ing where we don't need to.
# -- huggie@earth.li
 
# 27/06/2001 - Allowed whitespace after initial "/**" and
# allowed comments before function declarations.
# -- Christian Kreibich <ck@whoop.org>
 
# Still to do:
# - add perldoc documentation
# - Look more closely at some of the scarier bits :)
 
# 26/05/2001 - Support for separate source and object trees.
# Return error code.
# Keith Owens <kaos@ocs.com.au>
 
# 23/09/2001 - Added support for typedefs, structs, enums and unions
# Support for Context section; can be terminated using empty line
# Small fixes (like spaces vs. \s in regex)
# -- Tim Jansen <tim@tjansen.de>
 
 
#
# This will read a 'c' file and scan for embedded comments in the
# style of gnome comments (+minor extensions - see below).
#
 
# Note: This only supports 'c'.
 
# usage:
# kerneldoc [ -docbook | -html | -text | -man ]
# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
# or
# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
#
# Set output format using one of -docbook -html -text or -man. Default is man.
#
# -function funcname
# If set, then only generate documentation for the given function(s). All
# other functions are ignored.
#
# -nofunction funcname
# If set, then only generate documentation for the other function(s). All
# other functions are ignored. Cannot be used with -function together
# (yes thats a bug - perl hackers can fix it 8))
#
# c files - list of 'c' files to process
#
# All output goes to stdout, with errors to stderr.
 
#
# format of comments.
# In the following table, (...)? signifies optional structure.
# (...)* signifies 0 or more structure elements
# /**
# * function_name(:)? (- short description)?
# (* @parameterx: (description of parameter x)?)*
# (* a blank line)?
# * (Description:)? (Description of function)?
# * (section header: (section description)? )*
# (*)?*/
#
# So .. the trivial example would be:
#
# /**
# * my_function
# **/
#
# If the Description: header tag is ommitted, then there must be a blank line
# after the last parameter specification.
# e.g.
# /**
# * my_function - does my stuff
# * @my_arg: its mine damnit
# *
# * Does my stuff explained.
# */
#
# or, could also use:
# /**
# * my_function - does my stuff
# * @my_arg: its mine damnit
# * Description: Does my stuff explained.
# */
# etc.
#
# Beside functions you can also write documentation for structs, unions,
# enums and typedefs. Instead of the function name you must write the name
# of the declaration; the struct/union/enum/typedef must always precede
# the name. Nesting of declarations is not supported.
# Use the argument mechanism to document members or constants. In
# structs and unions you must declare one member per declaration
# (comma-separated members are not allowed - the parser does not support
# this).
# e.g.
# /**
# * struct my_struct - short description
# * @a: first member
# * @b: second member
# *
# * Longer description
# */
# struct my_struct {
# int a;
# int b;
# };
#
# All descriptions can be multiline, except the short function description.
#
# You can also add additional sections. When documenting kernel functions you
# should document the "Context:" of the function, e.g. whether the functions
# can be called form interrupts. Unlike other sections you can end it with an
# empty line.
# Example-sections should contain the string EXAMPLE so that they are marked
# appropriately in DocBook.
#
# Example:
# /**
# * user_function - function that can only be called in user context
# * @a: some argument
# * Context: !in_interrupt()
# *
# * Some description
# * Example:
# * user_function(22);
# */
# ...
#
#
# All descriptive text is further processed, scanning for the following special
# patterns, which are highlighted appropriately.
#
# 'funcname()' - function
# '$ENVVAR' - environmental variable
# '&struct_name' - name of a structure (up to two words including 'struct')
# '@parameter' - name of a parameter
# '%CONST' - name of a constant.
 
my $errors = 0;
 
# match expressions used to find embedded type information
my $type_constant = '\%([-_\w]+)';
my $type_func = '(\w+)\(\)';
my $type_param = '\@(\w+)';
my $type_struct = '\&((struct\s*)?[_\w]+)';
my $type_env = '(\$\w+)';
 
# Output conversion substitutions.
# One for each output format
 
# these work fairly well
my %highlights_html = ( $type_constant, "<i>\$1</i>",
$type_func, "<b>\$1</b>",
$type_struct, "<i>\$1</i>",
$type_param, "<tt><b>\$1</b></tt>" );
my $blankline_html = "<p>";
 
# sgml, docbook format
my %highlights_sgml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
$type_constant, "<constant>\$1</constant>",
$type_func, "<function>\$1</function>",
$type_struct, "<structname>\$1</structname>",
$type_env, "<envar>\$1</envar>",
$type_param, "<parameter>\$1</parameter>" );
my $blankline_sgml = "</para><para>\n";
 
# gnome, docbook format
my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
$type_func, "<function>\$1</function>",
$type_struct, "<structname>\$1</structname>",
$type_env, "<envar>\$1</envar>",
$type_param, "<parameter>\$1</parameter>" );
my $blankline_gnome = "</para><para>\n";
 
# these are pretty rough
my %highlights_man = ( $type_constant, "\$1",
$type_func, "\\\\fB\$1\\\\fP",
$type_struct, "\\\\fI\$1\\\\fP",
$type_param, "\\\\fI\$1\\\\fP" );
my $blankline_man = "";
 
# text-mode
my %highlights_text = ( $type_constant, "\$1",
$type_func, "\$1",
$type_struct, "\$1",
$type_param, "\$1" );
my $blankline_text = "";
 
 
sub usage {
print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";
print " [ -function funcname [ -function funcname ...] ]\n";
print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
print " c source file(s) > outputfile\n";
exit 1;
}
 
# read arguments
if ($#ARGV==-1) {
usage();
}
 
my $verbose = 0;
my $output_mode = "man";
my %highlights = %highlights_man;
my $blankline = $blankline_man;
my $modulename = "Kernel API";
my $function_only = 0;
my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October',
'November', 'December')[(localtime)[4]] .
" " . ((localtime)[5]+1900);
 
# Essentially these are globals
# They probably want to be tidied up made more localised or summat.
# CAVEAT EMPTOR! Some of the others I localised may not want to be which
# could cause "use of undefined value" or other bugs.
my ($function, %function_table,%parametertypes,$declaration_purpose);
my ($type,$declaration_name,$return_type);
my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map);
 
# Generated docbook code is inserted in a template at a point where
# docbook v3.1 requires a non-zero sequence of RefEntry's; see:
# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
# We keep track of number of generated entries and generate a dummy
# if needs be to ensure the expanded template can be postprocessed
# into html.
my $section_counter = 0;
 
my $lineprefix="";
 
# states
# 0 - normal code
# 1 - looking for function name
# 2 - scanning field start.
# 3 - scanning prototype.
# 4 - documentation block
my $state;
 
#declaration types: can be
# 'function', 'struct', 'union', 'enum', 'typedef'
my $decl_type;
 
my $doc_special = "\@\%\$\&";
 
my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
my $doc_end = '\*/';
my $doc_com = '\s*\*\s*';
my $doc_decl = $doc_com.'(\w+)';
my $doc_sect = $doc_com.'(['.$doc_special.']?[\w ]+):(.*)';
my $doc_content = $doc_com.'(.*)';
my $doc_block = $doc_com.'DOC:\s*(.*)?';
 
my %constants;
my %parameterdescs;
my @parameterlist;
my %sections;
my @sectionlist;
 
my $contents = "";
my $section_default = "Description"; # default section
my $section_intro = "Introduction";
my $section = $section_default;
my $section_context = "Context";
 
my $undescribed = "-- undescribed --";
 
reset_state();
 
while ($ARGV[0] =~ m/^-(.*)/) {
my $cmd = shift @ARGV;
if ($cmd eq "-html") {
$output_mode = "html";
%highlights = %highlights_html;
$blankline = $blankline_html;
} elsif ($cmd eq "-man") {
$output_mode = "man";
%highlights = %highlights_man;
$blankline = $blankline_man;
} elsif ($cmd eq "-text") {
$output_mode = "text";
%highlights = %highlights_text;
$blankline = $blankline_text;
} elsif ($cmd eq "-docbook") {
$output_mode = "sgml";
%highlights = %highlights_sgml;
$blankline = $blankline_sgml;
} elsif ($cmd eq "-gnome") {
$output_mode = "gnome";
%highlights = %highlights_gnome;
$blankline = $blankline_gnome;
} elsif ($cmd eq "-module") { # not needed for sgml, inherits from calling document
$modulename = shift @ARGV;
} elsif ($cmd eq "-function") { # to only output specific functions
$function_only = 1;
$function = shift @ARGV;
$function_table{$function} = 1;
} elsif ($cmd eq "-nofunction") { # to only output specific functions
$function_only = 2;
$function = shift @ARGV;
$function_table{$function} = 1;
} elsif ($cmd eq "-v") {
$verbose = 1;
} elsif (($cmd eq "-h") || ($cmd eq "--help")) {
usage();
} elsif ($cmd eq '-filelist') {
$filelist = shift @ARGV;
}
}
 
 
# generate a sequence of code that will splice in highlighting information
# using the s// operator.
my $dohighlight = "";
foreach my $pattern (keys %highlights) {
# print "scanning pattern $pattern ($highlights{$pattern})\n";
$dohighlight .= "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
}
 
##
# dumps section contents to arrays/hashes intended for that purpose.
#
sub dump_section {
my $name = shift;
my $contents = join "\n", @_;
 
if ($name =~ m/$type_constant/) {
$name = $1;
# print STDERR "constant section '$1' = '$contents'\n";
$constants{$name} = $contents;
} elsif ($name =~ m/$type_param/) {
# print STDERR "parameter def '$1' = '$contents'\n";
$name = $1;
$parameterdescs{$name} = $contents;
} else {
# print STDERR "other section '$name' = '$contents'\n";
$sections{$name} = $contents;
push @sectionlist, $name;
}
}
 
##
# output function
#
# parameterdescs, a hash.
# function => "function name"
# parameterlist => @list of parameters
# parameterdescs => %parameter descriptions
# sectionlist => @list of sections
# sections => %descriont descriptions
#
 
sub output_highlight {
my $contents = join "\n",@_;
my $line;
 
# DEBUG
# if (!defined $contents) {
# use Carp;
# confess "output_highlight got called with no args?\n";
# }
 
eval $dohighlight;
die $@ if $@;
foreach $line (split "\n", $contents) {
if ($line eq ""){
print $lineprefix, $blankline;
} else {
$line =~ s/\\\\\\/\&/g;
print $lineprefix, $line;
}
print "\n";
}
}
 
#output sections in html
sub output_section_html(%) {
my %args = %{$_[0]};
my $section;
 
foreach $section (@{$args{'sectionlist'}}) {
print "<h3>$section</h3>\n";
print "<blockquote>\n";
output_highlight($args{'sections'}{$section});
print "</blockquote>\n";
}
}
 
# output enum in html
sub output_enum_html(%) {
my %args = %{$_[0]};
my ($parameter);
my $count;
print "<h2>enum ".$args{'enum'}."</h2>\n";
 
print "<b>enum ".$args{'enum'}."</b> {<br>\n";
$count = 0;
foreach $parameter (@{$args{'parameterlist'}}) {
print " <b>".$parameter."</b>";
if ($count != $#{$args{'parameterlist'}}) {
$count++;
print ",\n";
}
print "<br>";
}
print "};<br>\n";
 
print "<h3>Constants</h3>\n";
print "<dl>\n";
foreach $parameter (@{$args{'parameterlist'}}) {
print "<dt><b>".$parameter."</b>\n";
print "<dd>";
output_highlight($args{'parameterdescs'}{$parameter});
}
print "</dl>\n";
output_section_html(@_);
print "<hr>\n";
}
 
# output tyepdef in html
sub output_typedef_html(%) {
my %args = %{$_[0]};
my ($parameter);
my $count;
print "<h2>typedef ".$args{'typedef'}."</h2>\n";
 
print "<b>typedef ".$args{'typedef'}."</b>\n";
output_section_html(@_);
print "<hr>\n";
}
 
# output struct in html
sub output_struct_html(%) {
my %args = %{$_[0]};
my ($parameter);
 
print "<h2>".$args{'type'}." ".$args{'struct'}."</h2>\n";
print "<b>".$args{'type'}." ".$args{'struct'}."</b> {<br>\n";
foreach $parameter (@{$args{'parameterlist'}}) {
($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
$type = $args{'parametertypes'}{$parameter};
if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
# pointer-to-function
print " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
} elsif ($type =~ m/^(.*?)\s*(:.*)/) {
print " <i>$1</i> <b>$parameter</b>$2;<br>\n";
} else {
print " <i>$type</i> <b>$parameter</b>;<br>\n";
}
}
print "};<br>\n";
 
print "<h3>Members</h3>\n";
print "<dl>\n";
foreach $parameter (@{$args{'parameterlist'}}) {
($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
print "<dt><b>".$parameter."</b>\n";
print "<dd>";
output_highlight($args{'parameterdescs'}{$parameter});
}
print "</dl>\n";
output_section_html(@_);
print "<hr>\n";
}
 
# output function in html
sub output_function_html(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
print "<h2>Function</h2>\n";
 
print "<i>".$args{'functiontype'}."</i>\n";
print "<b>".$args{'function'}."</b>\n";
print "(";
$count = 0;
foreach $parameter (@{$args{'parameterlist'}}) {
$type = $args{'parametertypes'}{$parameter};
if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
# pointer-to-function
print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
} else {
print "<i>".$type."</i> <b>".$parameter."</b>";
}
if ($count != $#{$args{'parameterlist'}}) {
$count++;
print ",\n";
}
}
print ")\n";
 
print "<h3>Arguments</h3>\n";
print "<dl>\n";
foreach $parameter (@{$args{'parameterlist'}}) {
($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
print "<dt><b>".$parameter."</b>\n";
print "<dd>";
output_highlight($args{'parameterdescs'}{$parameter});
}
print "</dl>\n";
output_section_html(@_);
print "<hr>\n";
}
 
# output intro in html
sub output_intro_html(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
 
foreach $section (@{$args{'sectionlist'}}) {
print "<h3>$section</h3>\n";
print "<ul>\n";
output_highlight($args{'sections'}{$section});
print "</ul>\n";
}
print "<hr>\n";
}
 
sub output_section_sgml(%) {
my %args = %{$_[0]};
my $section;
# print out each section
$lineprefix=" ";
foreach $section (@{$args{'sectionlist'}}) {
print "<refsect1>\n <title>$section</title>\n <para>\n";
if ($section =~ m/EXAMPLE/i) {
print "<example><para>\n";
}
output_highlight($args{'sections'}{$section});
if ($section =~ m/EXAMPLE/i) {
print "</para></example>\n";
}
print " </para>\n</refsect1>\n";
}
}
 
# output function in sgml DocBook
sub output_function_sgml(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
my $id;
 
$id = "API-".$args{'function'};
$id =~ s/[^A-Za-z0-9]/-/g;
 
print "<refentry>\n";
print "<refmeta>\n";
print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
print "</refmeta>\n";
print "<refnamediv>\n";
print " <refname>".$args{'function'}."</refname>\n";
print " <refpurpose>\n";
print " ";
output_highlight ($args{'purpose'});
print " </refpurpose>\n";
print "</refnamediv>\n";
 
print "<refsynopsisdiv>\n";
print " <title>Synopsis</title>\n";
print " <funcsynopsis><funcprototype>\n";
print " <funcdef>".$args{'functiontype'}." ";
print "<function>".$args{'function'}." </function></funcdef>\n";
 
$count = 0;
if ($#{$args{'parameterlist'}} >= 0) {
foreach $parameter (@{$args{'parameterlist'}}) {
$type = $args{'parametertypes'}{$parameter};
if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
# pointer-to-function
print " <paramdef>$1<parameter>$parameter</parameter>)\n";
print " <funcparams>$2</funcparams></paramdef>\n";
} else {
print " <paramdef>".$type;
print " <parameter>$parameter</parameter></paramdef>\n";
}
}
} else {
print " <void>\n";
}
print " </funcprototype></funcsynopsis>\n";
print "</refsynopsisdiv>\n";
 
# print parameters
print "<refsect1>\n <title>Arguments</title>\n";
if ($#{$args{'parameterlist'}} >= 0) {
print " <variablelist>\n";
foreach $parameter (@{$args{'parameterlist'}}) {
print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n";
print " <listitem>\n <para>\n";
$lineprefix=" ";
output_highlight($args{'parameterdescs'}{$parameter});
print " </para>\n </listitem>\n </varlistentry>\n";
}
print " </variablelist>\n";
} else {
print " <para>\n None\n </para>\n";
}
print "</refsect1>\n";
 
output_section_sgml(@_);
print "</refentry>\n\n";
}
 
# output struct in sgml DocBook
sub output_struct_sgml(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $id;
 
$id = "API-struct-".$args{'struct'};
$id =~ s/[^A-Za-z0-9]/-/g;
 
print "<refentry>\n";
print "<refmeta>\n";
print "<refentrytitle><phrase id=\"$id\">".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
print "</refmeta>\n";
print "<refnamediv>\n";
print " <refname>".$args{'type'}." ".$args{'struct'}."</refname>\n";
print " <refpurpose>\n";
print " ";
output_highlight ($args{'purpose'});
print " </refpurpose>\n";
print "</refnamediv>\n";
 
print "<refsynopsisdiv>\n";
print " <title>Synopsis</title>\n";
print " <programlisting>\n";
print $args{'type'}." ".$args{'struct'}." {\n";
foreach $parameter (@{$args{'parameterlist'}}) {
($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
$type = $args{'parametertypes'}{$parameter};
if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
# pointer-to-function
print " $1 $parameter ($2);\n";
} elsif ($type =~ m/^(.*?)\s*(:.*)/) {
print " $1 $parameter$2;\n";
} else {
print " ".$type." ".$parameter.";\n";
}
}
print "};";
print " </programlisting>\n";
print "</refsynopsisdiv>\n";
 
print " <refsect1>\n";
print " <title>Members</title>\n";
 
print " <variablelist>\n";
foreach $parameter (@{$args{'parameterlist'}}) {
($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
print " <varlistentry>";
print " <term>$parameter</term>\n";
print " <listitem><para>\n";
output_highlight($args{'parameterdescs'}{$parameter});
print " </para></listitem>\n";
print " </varlistentry>\n";
}
print " </variablelist>\n";
print " </refsect1>\n";
 
output_section_sgml(@_);
 
print "</refentry>\n\n";
}
 
# output enum in sgml DocBook
sub output_enum_sgml(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
my $id;
 
$id = "API-enum-".$args{'enum'};
$id =~ s/[^A-Za-z0-9]/-/g;
 
print "<refentry>\n";
print "<refmeta>\n";
print "<refentrytitle><phrase id=\"$id\">enum ".$args{'enum'}."</phrase></refentrytitle>\n";
print "</refmeta>\n";
print "<refnamediv>\n";
print " <refname>enum ".$args{'enum'}."</refname>\n";
print " <refpurpose>\n";
print " ";
output_highlight ($args{'purpose'});
print " </refpurpose>\n";
print "</refnamediv>\n";
 
print "<refsynopsisdiv>\n";
print " <title>Synopsis</title>\n";
print " <programlisting>\n";
print "enum ".$args{'enum'}." {\n";
$count = 0;
foreach $parameter (@{$args{'parameterlist'}}) {
print " $parameter";
if ($count != $#{$args{'parameterlist'}}) {
$count++;
print ",";
}
print "\n";
}
print "};";
print " </programlisting>\n";
print "</refsynopsisdiv>\n";
 
print "<refsect1>\n";
print " <title>Constants</title>\n";
print " <variablelist>\n";
foreach $parameter (@{$args{'parameterlist'}}) {
print " <varlistentry>";
print " <term>$parameter</term>\n";
print " <listitem><para>\n";
output_highlight($args{'parameterdescs'}{$parameter});
print " </para></listitem>\n";
print " </varlistentry>\n";
}
print " </variablelist>\n";
print "</refsect1>\n";
 
output_section_sgml(@_);
 
print "</refentry>\n\n";
}
 
# output typedef in sgml DocBook
sub output_typedef_sgml(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $id;
 
$id = "API-typedef-".$args{'typedef'};
$id =~ s/[^A-Za-z0-9]/-/g;
 
print "<refentry>\n";
print "<refmeta>\n";
print "<refentrytitle><phrase id=\"$id\">typedef ".$args{'typedef'}."</phrase></refentrytitle>\n";
print "</refmeta>\n";
print "<refnamediv>\n";
print " <refname>typedef ".$args{'typedef'}."</refname>\n";
print " <refpurpose>\n";
print " ";
output_highlight ($args{'purpose'});
print " </refpurpose>\n";
print "</refnamediv>\n";
 
print "<refsynopsisdiv>\n";
print " <title>Synopsis</title>\n";
print " <synopsis>typedef ".$args{'typedef'}.";</synopsis>\n";
print "</refsynopsisdiv>\n";
 
output_section_sgml(@_);
 
print "</refentry>\n\n";
}
 
# output in sgml DocBook
sub output_intro_sgml(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
 
my $id = $args{'module'};
$id =~ s/[^A-Za-z0-9]/-/g;
 
# print out each section
$lineprefix=" ";
foreach $section (@{$args{'sectionlist'}}) {
print "<refsect1>\n <title>$section</title>\n <para>\n";
if ($section =~ m/EXAMPLE/i) {
print "<example><para>\n";
}
output_highlight($args{'sections'}{$section});
if ($section =~ m/EXAMPLE/i) {
print "</para></example>\n";
}
print " </para>\n</refsect1>\n";
}
 
print "\n\n";
}
 
# output in sgml DocBook
sub output_function_gnome {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
my $id;
 
$id = $args{'module'}."-".$args{'function'};
$id =~ s/[^A-Za-z0-9]/-/g;
 
print "<sect2>\n";
print " <title id=\"$id\">".$args{'function'}."</title>\n";
 
print " <funcsynopsis>\n";
print " <funcdef>".$args{'functiontype'}." ";
print "<function>".$args{'function'}." ";
print "</function></funcdef>\n";
 
$count = 0;
if ($#{$args{'parameterlist'}} >= 0) {
foreach $parameter (@{$args{'parameterlist'}}) {
$type = $args{'parametertypes'}{$parameter};
if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
# pointer-to-function
print " <paramdef>$1 <parameter>$parameter</parameter>)\n";
print " <funcparams>$2</funcparams></paramdef>\n";
} else {
print " <paramdef>".$type;
print " <parameter>$parameter</parameter></paramdef>\n";
}
}
} else {
print " <void>\n";
}
print " </funcsynopsis>\n";
if ($#{$args{'parameterlist'}} >= 0) {
print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
print "<tgroup cols=\"2\">\n";
print "<colspec colwidth=\"2*\">\n";
print "<colspec colwidth=\"8*\">\n";
print "<tbody>\n";
foreach $parameter (@{$args{'parameterlist'}}) {
print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
print " <entry>\n";
$lineprefix=" ";
output_highlight($args{'parameterdescs'}{$parameter});
print " </entry></row>\n";
}
print " </tbody></tgroup></informaltable>\n";
} else {
print " <para>\n None\n </para>\n";
}
 
# print out each section
$lineprefix=" ";
foreach $section (@{$args{'sectionlist'}}) {
print "<simplesect>\n <title>$section</title>\n";
if ($section =~ m/EXAMPLE/i) {
print "<example><programlisting>\n";
} else {
}
print "<para>\n";
output_highlight($args{'sections'}{$section});
print "</para>\n";
if ($section =~ m/EXAMPLE/i) {
print "</programlisting></example>\n";
} else {
}
print " </simplesect>\n";
}
 
print "</sect2>\n\n";
}
 
##
# output function in man
sub output_function_man(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
 
print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"25 May 1998\" \"Kernel Hacker's Manual\" LINUX\n";
 
print ".SH NAME\n";
print $args{'function'}." \\- ".$args{'purpose'}."\n";
 
print ".SH SYNOPSIS\n";
print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n";
$count = 0;
my $parenth = "(";
my $post = ",";
foreach my $parameter (@{$args{'parameterlist'}}) {
if ($count == $#{$args{'parameterlist'}}) {
$post = ");";
}
$type = $args{'parametertypes'}{$parameter};
if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
# pointer-to-function
print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n";
} else {
$type =~ s/([^\*])$/$1 /;
print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n";
}
$count++;
$parenth = "";
}
 
print ".SH ARGUMENTS\n";
foreach $parameter (@{$args{'parameterlist'}}) {
print ".IP \"".$parameter."\" 12\n";
output_highlight($args{'parameterdescs'}{$parameter});
}
foreach $section (@{$args{'sectionlist'}}) {
print ".SH \"", uc $section, "\"\n";
output_highlight($args{'sections'}{$section});
}
}
 
##
# output enum in man
sub output_enum_man(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
 
print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
 
print ".SH NAME\n";
print "enum ".$args{'enum'}." \\- ".$args{'purpose'}."\n";
 
print ".SH SYNOPSIS\n";
print "enum ".$args{'enum'}." {\n";
$count = 0;
foreach my $parameter (@{$args{'parameterlist'}}) {
print ".br\n.BI \" $parameter\"\n";
if ($count == $#{$args{'parameterlist'}}) {
print "\n};\n";
last;
}
else {
print ", \n.br\n";
}
$count++;
}
 
print ".SH Constants\n";
foreach $parameter (@{$args{'parameterlist'}}) {
print ".IP \"".$parameter."\" 12\n";
output_highlight($args{'parameterdescs'}{$parameter});
}
foreach $section (@{$args{'sectionlist'}}) {
print ".SH \"$section\"\n";
output_highlight($args{'sections'}{$section});
}
}
 
##
# output struct in man
sub output_struct_man(%) {
my %args = %{$_[0]};
my ($parameter, $section);
 
print ".TH \"$args{'module'}\" 9 \"".$args{'type'}." ".$args{'struct'}."\" \"$man_date\" \"API Manual\" LINUX\n";
 
print ".SH NAME\n";
print $args{'type'}." ".$args{'struct'}." \\- ".$args{'purpose'}."\n";
 
print ".SH SYNOPSIS\n";
print $args{'type'}." ".$args{'struct'}." {\n";
 
foreach my $parameter (@{$args{'parameterlist'}}) {
($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
print "\n.br\n";
$type = $args{'parametertypes'}{$parameter};
if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
# pointer-to-function
print ".BI \" ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n";
} elsif ($type =~ m/^(.*?)\s*(:.*)/) {
print ".BI \" ".$1."\" ".$parameter.$2." \""."\"\n;\n";
} else {
$type =~ s/([^\*])$/$1 /;
print ".BI \" ".$type."\" ".$parameter." \""."\"\n;\n";
}
print "\n.br\n";
}
print "};\n.br\n";
 
print ".SH Arguments\n";
foreach $parameter (@{$args{'parameterlist'}}) {
($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
print ".IP \"".$parameter."\" 12\n";
output_highlight($args{'parameterdescs'}{$parameter});
}
foreach $section (@{$args{'sectionlist'}}) {
print ".SH \"$section\"\n";
output_highlight($args{'sections'}{$section});
}
}
 
##
# output typedef in man
sub output_typedef_man(%) {
my %args = %{$_[0]};
my ($parameter, $section);
 
print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
 
print ".SH NAME\n";
print "typedef ".$args{'typedef'}." \\- ".$args{'purpose'}."\n";
 
foreach $section (@{$args{'sectionlist'}}) {
print ".SH \"$section\"\n";
output_highlight($args{'sections'}{$section});
}
}
 
sub output_intro_man(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
 
print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
 
foreach $section (@{$args{'sectionlist'}}) {
print ".SH \"$section\"\n";
output_highlight($args{'sections'}{$section});
}
}
 
##
# output in text
sub output_function_text(%) {
my %args = %{$_[0]};
my ($parameter, $section);
 
print "Function:\n\n";
my $start=$args{'functiontype'}." ".$args{'function'}." (";
print $start;
my $count = 0;
foreach my $parameter (@{$args{'parameterlist'}}) {
$type = $args{'parametertypes'}{$parameter};
if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
# pointer-to-function
print $1.$parameter.") (".$2;
} else {
print $type." ".$parameter;
}
if ($count != $#{$args{'parameterlist'}}) {
$count++;
print ",\n";
print " " x length($start);
} else {
print ");\n\n";
}
}
 
print "Arguments:\n\n";
foreach $parameter (@{$args{'parameterlist'}}) {
print $parameter."\n\t".$args{'parameterdescs'}{$parameter}."\n";
}
output_section_text(@_);
}
 
#output sections in text
sub output_section_text(%) {
my %args = %{$_[0]};
my $section;
 
print "\n";
foreach $section (@{$args{'sectionlist'}}) {
print "$section:\n\n";
output_highlight($args{'sections'}{$section});
}
print "\n\n";
}
 
# output enum in text
sub output_enum_text(%) {
my %args = %{$_[0]};
my ($parameter);
my $count;
print "Enum:\n\n";
 
print "enum ".$args{'enum'}." {\n";
$count = 0;
foreach $parameter (@{$args{'parameterlist'}}) {
print "\t$parameter";
if ($count != $#{$args{'parameterlist'}}) {
$count++;
print ",";
}
print "\n";
}
print "};\n\n";
 
print "Constants:\n\n";
foreach $parameter (@{$args{'parameterlist'}}) {
print "$parameter\n\t";
print $args{'parameterdescs'}{$parameter}."\n";
}
 
output_section_text(@_);
}
 
# output typedef in text
sub output_typedef_text(%) {
my %args = %{$_[0]};
my ($parameter);
my $count;
print "Typedef:\n\n";
 
print "typedef ".$args{'typedef'}."\n";
output_section_text(@_);
}
 
# output struct as text
sub output_struct_text(%) {
my %args = %{$_[0]};
my ($parameter);
 
print $args{'type'}." ".$args{'struct'}.":\n\n";
print $args{'type'}." ".$args{'struct'}." {\n";
foreach $parameter (@{$args{'parameterlist'}}) {
($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
$type = $args{'parametertypes'}{$parameter};
if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
# pointer-to-function
print "\t$1 $parameter) ($2);\n";
} elsif ($type =~ m/^(.*?)\s*(:.*)/) {
print "\t$1 $parameter$2;\n";
} else {
print "\t".$type." ".$parameter.";\n";
}
}
print "};\n\n";
 
print "Members:\n\n";
foreach $parameter (@{$args{'parameterlist'}}) {
($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
print "$parameter\n\t";
print $args{'parameterdescs'}{$parameter}."\n";
}
print "\n";
output_section_text(@_);
}
 
sub output_intro_text(%) {
my %args = %{$_[0]};
my ($parameter, $section);
 
foreach $section (@{$args{'sectionlist'}}) {
print " $section:\n";
print " -> ";
output_highlight($args{'sections'}{$section});
}
}
 
##
# generic output function for typedefs
sub output_declaration {
no strict 'refs';
my $name = shift;
my $functype = shift;
my $func = "output_${functype}_$output_mode";
if (($function_only==0) ||
( $function_only == 1 && defined($function_table{$name})) ||
( $function_only == 2 && !defined($function_table{$name})))
{
&$func(@_);
$section_counter++;
}
}
 
##
# generic output function - calls the right one based
# on current output mode.
sub output_intro {
no strict 'refs';
my $func = "output_intro_".$output_mode;
&$func(@_);
$section_counter++;
}
 
##
# takes a declaration (struct, union, enum, typedef) and
# invokes the right handler. NOT called for functions.
sub dump_declaration($$) {
no strict 'refs';
my ($prototype, $file) = @_;
my $func = "dump_".$decl_type;
&$func(@_);
}
 
sub dump_union($$) {
dump_struct(@_);
}
 
sub dump_struct($$) {
my $x = shift;
my $file = shift;
 
if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
$declaration_name = $2;
my $members = $3;
 
# ignore embedded structs or unions
$members =~ s/{.*}//g;
 
create_parameterlist($members, ';', $file);
 
output_declaration($declaration_name,
'struct',
{'struct' => $declaration_name,
'module' => $modulename,
'parameterlist' => \@parameterlist,
'parameterdescs' => \%parameterdescs,
'parametertypes' => \%parametertypes,
'sectionlist' => \@sectionlist,
'sections' => \%sections,
'purpose' => $declaration_purpose,
'type' => $decl_type
});
}
else {
print STDERR "Error(${file}:$.): Cannot parse struct or union!\n";
++$errors;
}
}
 
sub dump_enum($$) {
my $x = shift;
my $file = shift;
 
if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
$declaration_name = $1;
my $members = $2;
 
foreach my $arg (split ',', $members) {
$arg =~ s/^\s*(\w+).*/$1/;
push @parameterlist, $arg;
if (!$parameterdescs{$arg}) {
$parameterdescs{$arg} = $undescribed;
print STDERR "Warning(${file}:$.): Enum value '$arg' ".
"not described in enum '$declaration_name'\n";
}
 
}
output_declaration($declaration_name,
'enum',
{'enum' => $declaration_name,
'module' => $modulename,
'parameterlist' => \@parameterlist,
'parameterdescs' => \%parameterdescs,
'sectionlist' => \@sectionlist,
'sections' => \%sections,
'purpose' => $declaration_purpose
});
}
else {
print STDERR "Error(${file}:$.): Cannot parse enum!\n";
++$errors;
}
}
 
sub dump_typedef($$) {
my $x = shift;
my $file = shift;
 
while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
$x =~ s/\(*.\)\s*;$/;/;
$x =~ s/\[*.\]\s*;$/;/;
}
 
if ($x =~ /typedef.*\s+(\w+)\s*;/) {
$declaration_name = $1;
 
output_declaration($declaration_name,
'typedef',
{'typedef' => $declaration_name,
'module' => $modulename,
'sectionlist' => \@sectionlist,
'sections' => \%sections,
'purpose' => $declaration_purpose
});
}
else {
print STDERR "Error(${file}:$.): Cannot parse typedef!\n";
++$errors;
}
}
 
sub create_parameterlist($$$) {
my $args = shift;
my $splitter = shift;
my $file = shift;
my $type;
my $param;
 
while ($args =~ /(\([^\),]+),/) {
$args =~ s/(\([^\),]+),/$1#/g;
}
foreach my $arg (split($splitter, $args)) {
# strip leading/trailing spaces
$arg =~ s/^\s*//;
$arg =~ s/\s*$//;
$arg =~ s/\s+/ /;
 
if ($arg =~ m/\(/) {
# pointer-to-function
$arg =~ tr/#/,/;
$arg =~ m/[^\(]+\(\*([^\)]+)\)/;
$param = $1;
$type = $arg;
$type =~ s/([^\(]+\(\*)$param/$1/;
} else {
# evil magic to get fixed array parameters to work
$arg =~ s/(.+\s+)(.+)\[.*/$1* $2/;
my @args = split('\s', $arg);
$param = pop @args;
if ($param =~ m/^(\*+)(.*)/) {
$param = $2;
push @args, $1;
}
elsif ($param =~ m/(.*?)\s*:\s*(\d+)/) {
$param = $1;
push @args, ":$2";
}
$type = join " ", @args;
}
 
if ($type eq "" && $param eq "...")
{
$type="...";
$param="...";
$parameterdescs{"..."} = "variable arguments";
}
elsif ($type eq "" && ($param eq "" or $param eq "void"))
{
$type="";
$param="void";
$parameterdescs{void} = "no arguments";
}
if (defined $type && $type && !defined $parameterdescs{$param}) {
$parameterdescs{$param} = $undescribed;
 
if (($type eq 'function') || ($type eq 'enum')) {
print STDERR "Warning(${file}:$.): Function parameter ".
"or member '$param' not " .
"described in '$declaration_name'\n";
}
++$errors;
}
 
push @parameterlist, $param;
$parametertypes{$param} = $type;
}
}
 
##
# takes a function prototype and the name of the current file being
# processed and spits out all the details stored in the global
# arrays/hashes.
sub dump_function($$) {
my $prototype = shift;
my $file = shift;
 
$prototype =~ s/^static +//;
$prototype =~ s/^extern +//;
$prototype =~ s/^inline +//;
$prototype =~ s/^__inline__ +//;
$prototype =~ s/^#define +//; #ak added
 
# Yes, this truly is vile. We are looking for:
# 1. Return type (may be nothing if we're looking at a macro)
# 2. Function name
# 3. Function parameters.
#
# All the while we have to watch out for function pointer parameters
# (which IIRC is what the two sections are for), C types (these
# regexps don't even start to express all the possibilities), and
# so on.
#
# If you mess with these regexps, it's a good idea to check that
# the following functions' documentation still comes out right:
# - parport_register_device (function pointer parameters)
# - atomic_set (macro)
# - pci_match_device (long return type)
 
if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) {
$return_type = $1;
$declaration_name = $2;
my $args = $3;
 
create_parameterlist($args, ',', $file);
} else {
print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n";
++$errors;
return;
}
 
output_declaration($declaration_name,
'function',
{'function' => $declaration_name,
'module' => $modulename,
'functiontype' => $return_type,
'parameterlist' => \@parameterlist,
'parameterdescs' => \%parameterdescs,
'parametertypes' => \%parametertypes,
'sectionlist' => \@sectionlist,
'sections' => \%sections,
'purpose' => $declaration_purpose
});
}
 
sub process_file($);
 
# Read the file that maps relative names to absolute names for
# separate source and object directories and for shadow trees.
if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
my ($relname, $absname);
while(<SOURCE_MAP>) {
chop();
($relname, $absname) = (split())[0..1];
$relname =~ s:^/+::;
$source_map{$relname} = $absname;
}
close(SOURCE_MAP);
}
 
if ($filelist) {
open(FLIST,"<$filelist") or die "Can't open file list $filelist";
while(<FLIST>) {
chop;
process_file($_);
}
}
 
foreach (@ARGV) {
chomp;
process_file($_);
}
 
exit($errors);
 
sub reset_state {
$function = "";
%constants = ();
%parameterdescs = ();
%parametertypes = ();
@parameterlist = ();
%sections = ();
@sectionlist = ();
$prototype = "";
$state = 0;
}
 
sub process_state3_function($$) {
my $x = shift;
my $file = shift;
 
if ($x =~ m#\s*/\*\s+MACDOC\s*#io) {
# do nothing
}
elsif ($x =~ /([^\{]*)/) {
$prototype .= $1;
}
if (($x =~ /\{/) || ($x =~ /\#/) || ($x =~ /;/)) {
$prototype =~ s@/\*.*?\*/@@gos; # strip comments.
$prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
$prototype =~ s@^\s+@@gos; # strip leading spaces
dump_function($prototype,$file);
reset_state();
}
}
 
sub process_state3_type($$) {
my $x = shift;
my $file = shift;
 
$x =~ s@/\*.*?\*/@@gos; # strip comments.
$x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
$x =~ s@^\s+@@gos; # strip leading spaces
$x =~ s@\s+$@@gos; # strip trailing spaces
 
while (1) {
if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
$prototype .= $1 . $2;
($2 eq '{') && $brcount++;
($2 eq '}') && $brcount--;
if (($2 eq ';') && ($brcount == 0)) {
dump_declaration($prototype,$file);
reset_state();
last;
}
$x = $3;
} else {
$prototype .= $x;
last;
}
}
}
 
sub process_file($) {
my ($file) = @_;
my $identifier;
my $func;
my $initial_section_counter = $section_counter;
 
if (defined($source_map{$file})) {
$file = $source_map{$file};
}
 
if (!open(IN,"<$file")) {
print STDERR "Error: Cannot open file $file\n";
++$errors;
return;
}
 
$section_counter = 0;
while (<IN>) {
if ($state == 0) {
if (/$doc_start/o) {
$state = 1; # next line is always the function name
}
} elsif ($state == 1) { # this line is the function name (always)
if (/$doc_block/o) {
$state = 4;
$contents = "";
if ( $1 eq "" ) {
$section = $section_intro;
} else {
$section = $1;
}
}
elsif (/$doc_decl/o) {
$identifier = $1;
if (/\s*([\w\s]+?)\s*-/) {
$identifier = $1;
}
 
$state = 2;
if (/-(.*)/) {
$declaration_purpose = $1;
} else {
$declaration_purpose = "";
}
if ($identifier =~ m/^struct/) {
$decl_type = 'struct';
} elsif ($identifier =~ m/^union/) {
$decl_type = 'union';
} elsif ($identifier =~ m/^enum/) {
$decl_type = 'enum';
} elsif ($identifier =~ m/^typedef/) {
$decl_type = 'typedef';
} else {
$decl_type = 'function';
}
 
if ($verbose) {
print STDERR "Info(${file}:$.): Scanning doc for $identifier\n";
}
} else {
print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.",
" - I thought it was a doc line\n";
++$errors;
$state = 0;
}
} elsif ($state == 2) { # look for head: lines, and include content
if (/$doc_sect/o) {
$newsection = $1;
$newcontents = $2;
 
if ($contents ne "") {
$contents =~ s/\&/\\\\\\amp;/g;
$contents =~ s/\</\\\\\\lt;/g;
$contents =~ s/\>/\\\\\\gt;/g;
dump_section($section, $contents);
$section = $section_default;
}
 
$contents = $newcontents;
if ($contents ne "") {
$contents .= "\n";
}
$section = $newsection;
} elsif (/$doc_end/) {
 
if ($contents ne "") {
$contents =~ s/\&/\\\\\\amp;/g;
$contents =~ s/\</\\\\\\lt;/g;
$contents =~ s/\>/\\\\\\gt;/g;
dump_section($section, $contents);
$section = $section_default;
$contents = "";
}
 
$prototype = "";
$state = 3;
$brcount = 0;
# print STDERR "end of doc comment, looking for prototype\n";
} elsif (/$doc_content/) {
# miguel-style comment kludge, look for blank lines after
# @parameter line to signify start of description
if ($1 eq "" &&
($section =~ m/^@/ || $section eq $section_context)) {
$contents =~ s/\&/\\\\\\amp;/g;
$contents =~ s/\</\\\\\\lt;/g;
$contents =~ s/\>/\\\\\\gt;/g;
dump_section($section, $contents);
$section = $section_default;
$contents = "";
} else {
$contents .= $1."\n";
}
} else {
# i dont know - bad line? ignore.
print STDERR "Warning(${file}:$.): bad line: $_";
++$errors;
}
} elsif ($state == 3) { # scanning for function { (end of prototype)
if ($decl_type eq 'function') {
process_state3_function($_, $file);
} else {
process_state3_type($_, $file);
}
} elsif ($state == 4) {
# Documentation block
if (/$doc_block/) {
dump_section($section, $contents);
output_intro({'sectionlist' => \@sectionlist,
'sections' => \%sections });
$contents = "";
$function = "";
%constants = ();
%parameterdescs = ();
%parametertypes = ();
@parameterlist = ();
%sections = ();
@sectionlist = ();
$prototype = "";
if ( $1 eq "" ) {
$section = $section_intro;
} else {
$section = $1;
}
}
elsif (/$doc_end/)
{
dump_section($section, $contents);
output_intro({'sectionlist' => \@sectionlist,
'sections' => \%sections });
$contents = "";
$function = "";
%constants = ();
%parameterdescs = ();
%parametertypes = ();
@parameterlist = ();
%sections = ();
@sectionlist = ();
$prototype = "";
$state = 0;
}
elsif (/$doc_content/)
{
if ( $1 eq "" )
{
$contents .= $blankline;
}
else
{
$contents .= $1 . "\n";
}
}
}
}
if ($initial_section_counter == $section_counter) {
print STDERR "Warning(${file}): no structured comments found\n";
if ($output_mode eq "sgml") {
# The template wants at least one RefEntry here; make one.
print "<refentry>\n";
print " <refnamediv>\n";
print " <refname>\n";
print " ${file}\n";
print " </refname>\n";
print " <refpurpose>\n";
print " Document generation inconsistency\n";
print " </refpurpose>\n";
print " </refnamediv>\n";
print " <refsect1>\n";
print " <title>\n";
print " Oops\n";
print " </title>\n";
print " <warning>\n";
print " <para>\n";
print " The template for this document tried to insert\n";
print " the structured comment from the file\n";
print " <filename>${file}</filename> at this point,\n";
print " but none was found.\n";
print " This dummy section is inserted to allow\n";
print " generation to continue.\n";
print " </para>\n";
print " </warning>\n";
print " </refsect1>\n";
print "</refentry>\n";
}
}
}
/ksymoops/README
0,0 → 1,8
ksymoops has been removed from the kernel. It was always meant to be a
free standing utility, not linked to any particular kernel version.
The latest version can be found in
ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops together
with patches to other utilities in order to give more accurate Oops
debugging.
 
Keith Owens <kaos@ocs.com.au> Sat Jun 19 10:30:34 EST 1999
/tkgen.c
0,0 → 1,1521
/* Generate tk script based upon config.in
*
* Version 1.0
* Eric Youngdale
* 10/95
*
* 1996 01 04
* Avery Pennarun - Aesthetic improvements.
*
* 1996 01 24
* Avery Pennarun - Bugfixes and more aesthetics.
*
* 1996 03 08
* Avery Pennarun - The int and hex config.in commands work right.
* - Choice buttons are more user-friendly.
* - Disabling a text entry line greys it out properly.
* - dep_tristate now works like in Configure. (not pretty)
* - No warnings in gcc -Wall. (Fixed some "interesting" bugs.)
* - Faster/prettier "Help" lookups.
*
* 1996 03 15
* Avery Pennarun - Added new sed script from Axel Boldt to make help even
* faster. (Actually awk is downright slow on some machines.)
* - Fixed a bug I introduced into Choice dependencies. Thanks
* to Robert Krawitz for pointing this out.
*
* 1996 03 16
* Avery Pennarun - basic "do_make" support added to let sound config work.
*
* 1996 03 25
* Axel Boldt - Help now works on "choice" buttons.
*
* 1996 04 06
* Avery Pennarun - Improved sound config stuff. (I think it actually works
* now!)
* - Window-resize-limits don't use ugly /usr/lib/tk4.0 hack.
* - int/hex work with tk3 again. (The "cget" error.)
* - Next/Prev buttons switch between menus. I can't take
* much credit for this; the code was already there, but
* ifdef'd out for some reason. It flickers a lot, but
* I suspect there's no "easy" fix for that.
* - Labels no longer highlight as you move the mouse over
* them (although you can still press them... oh well.)
* - Got rid of the last of the literal color settings, to
* help out people with mono X-Windows systems.
* (Apparently there still are some out there!)
* - Tabstops seem sensible now.
*
* 1996 04 14
* Avery Pennarun - Reduced flicker when creating windows, even with "update
* idletasks" hack.
*
* 1997 12 08
* Michael Chastain - Remove sound driver special cases.
*
* 1997 11 15
* Michael Chastain - For choice buttons, write values for all options,
* not just the single chosen one. This is compatible
* with 'make config' and 'make oldconfig', and is
* needed so smart-config dependencies work if the
* user switches from one configuration method to
* another.
*
* 1998 03 09
* Axel Boldt - Smaller layout of main menu - it's still too big for 800x600.
* - Display help in text window to allow for cut and paste.
* - Allow for empty lines in help texts.
* - update_define should not set all variables unconditionally to
* 0: they may have been set to 1 elsewhere. CONFIG_NETLINK is
* an example.
*
* 1999 01 04
* Michael Elizabeth Chastain <mec@shout.net>
* - Call clear_globalflags when writing out update_mainmenu.
* This fixes the missing global/vfix lines for ARCH=alpha on 2.2.0-pre4.
*
* 8 January 1999, Michael Elizabeth Chastain <mec@shout.net>
* - Emit menus_per_column
*
* 14 January 1999, Michael Elizabeth Chastain <mec@shout.net>
* - Steam-clean this file. I tested this by generating kconfig.tk for every
* architecture and comparing it character-for-character against the output
* of the old tkparse.
* - Fix flattening of nested menus. The old code simply assigned items to
* the most recent token_mainmenu_option, without paying attention to scope.
* For example: "menu-1 bool-a menu-2 bool-b endmenu bool-c bool-d endmenu".
* The old code would put bool-a in menu-1, bool-b in menu-2, and bool-c
* and bool-d in *menu-2*. This hosed the nested submenus in
* drives/net/Config.in and other places.
* - Fix menu line wraparound at 128 menus (some fool used a 'char' for
* a counter).
*
* 23 January 1999, Michael Elizabeth Chastain <mec@shout.net>
* - Remove bug-compatible code.
*
* 07 July 1999, Andrzej M. Krzysztofowicz <ankry@mif.pg.gda.pl>
* Some bugfixes, including
* - disabling "m" options when CONFIG_MODULES is set to "n" as well as "y"
* option in dep_tristate when dependency is set to "m",
* - deactivating choices which should not be available,
* - basic validation for int and hex introduced if the entered one is not
* valid,
* - updates of all opened menus instead of the active only. I was afraid
* that it would slow down updates, but I don't even see any speed difference
* on my machine. If it slows you can still work with only a single menu
* opened,
* - fixed error when focussing non-existent window (especially Help windows),
* Higher level submenus implemented.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "tkparse.h"
 
 
/*
* Total number of menus.
*/
static int tot_menu_num = 0;
 
/*
* Pointers to mainmenu_option and endmenu of each menu.
*/
struct kconfig * menu_first [100];
struct kconfig * menu_last [100];
 
/*
* Generate portion of wish script for the beginning of a submenu.
* The guts get filled in with the various options.
*/
static void start_proc( char * label, int menu_num, int toplevel )
{
if ( toplevel )
printf( "menu_option menu%d %d \"%s\"\n", menu_num, menu_num, label );
printf( "proc menu%d {w title} {\n", menu_num );
printf( "\tset oldFocus [focus]\n" );
if ( menu_first[menu_num]->menu_number != 0 )
printf( "\tcatch {focus .menu%d}\n",
menu_first[menu_num]->menu_number );
printf( "\tcatch {destroy $w; unregister_active %d}\n", menu_num );
printf( "\ttoplevel $w -class Dialog\n" );
printf( "\twm withdraw $w\n" );
printf( "\tglobal active_menus\n" );
printf( "\tset active_menus [lsort -integer [linsert $active_menus end %d]]\n", menu_num );
printf( "\tmessage $w.m -width 400 -aspect 300 -text \\\n" );
printf( "\t\t\"%s\" -relief raised\n", label );
printf( "\tpack $w.m -pady 10 -side top -padx 10\n" );
printf( "\twm title $w \"%s\" \n\n", label );
 
printf( "\tbind $w <Escape> \"catch {focus $oldFocus}; destroy $w; unregister_active %d; break\"\n", menu_num);
 
printf("\tset nextscript ");
printf("\"catch {focus $oldFocus}; " );
/*
* We are checking which windows should be destroyed and which are
* common parents with the next one. Remember that menu_num field
* in mainmenu_option record reports number of its *parent* menu.
*/
if ( menu_num < tot_menu_num
&& menu_first[menu_num + 1]->menu_number != menu_num )
{
int to_destr;
 
printf( "destroy $w; unregister_active %d; ", menu_num );
to_destr = menu_first[menu_num]->menu_number;
while ( to_destr > 0 && menu_first[menu_num + 1]->menu_number != to_destr )
{
printf( "catch {destroy .menu%d}; unregister_active %d; ",
to_destr, to_destr );
to_destr = menu_first[to_destr]->menu_number;
}
}
printf( "menu%d .menu%d \\\"$title\\\"\"\n",
menu_num+1, menu_num+1 );
 
/*
* Attach the "Prev", "Next" and "OK" buttons at the end of the window.
*/
printf( "\tframe $w.f\n" );
if ( toplevel )
printf( "\tbutton $w.f.back -text \"Main Menu\" \\\n" );
else
printf( "\tbutton $w.f.back -text \"OK\" \\\n" );
printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; destroy $w; unregister_active %d\"\n",
menu_num );
printf( "\tbutton $w.f.next -text \"Next\" -underline 0\\\n" );
printf( "\t\t-width 15 -command $nextscript\n");
 
if ( menu_num == tot_menu_num ) {
printf( "\t$w.f.next configure -state disabled\n" );
/*
* this is a bit hackish but Alt-n must be rebound
* otherwise if the user press Alt-n on the last menu
* it will give him/her the next menu of one of the
* previous options
*/
printf( "\tbind all <Alt-n> \"puts \\\"no more menus\\\" \"\n");
}
else
{
/*
* I should be binding to $w not all - but if I do nehat I get the error "unknown path"
*/
printf( "\tbind all <Alt-n> $nextscript\n");
}
printf( "\tbutton $w.f.prev -text \"Prev\" -underline 0\\\n" );
printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; destroy $w; unregister_active %d; menu%d .menu%d \\\"$title\\\"\"\n",
menu_num, menu_num-1, menu_num-1 );
if ( menu_num == 1 ) {
printf( "\t$w.f.prev configure -state disabled\n" );
}
else
{
printf( "\tbind $w <Alt-p> \"catch {focus $oldFocus}; destroy $w; unregister_active %d; menu%d .menu%d \\\"$title\\\";break\"\n",
menu_num, menu_num-1, menu_num-1 );
}
printf( "\tpack $w.f.back $w.f.next $w.f.prev -side left -expand on\n" );
printf( "\tpack $w.f -pady 10 -side bottom -anchor w -fill x\n" );
 
/*
* Lines between canvas and other areas of the window.
*/
printf( "\tframe $w.topline -relief ridge -borderwidth 2 -height 2\n" );
printf( "\tpack $w.topline -side top -fill x\n\n" );
printf( "\tframe $w.botline -relief ridge -borderwidth 2 -height 2\n" );
printf( "\tpack $w.botline -side bottom -fill x\n\n" );
 
/*
* The "config" frame contains the canvas and a scrollbar.
*/
printf( "\tframe $w.config\n" );
printf( "\tpack $w.config -fill y -expand on\n\n" );
printf( "\tscrollbar $w.config.vscroll -command \"$w.config.canvas yview\"\n" );
printf( "\tpack $w.config.vscroll -side right -fill y\n\n" );
 
/*
* The scrollable canvas itself, where the real work (and mess) gets done.
*/
printf( "\tcanvas $w.config.canvas -height 1\\\n" );
printf( "\t\t-relief flat -borderwidth 0 -yscrollcommand \"$w.config.vscroll set\" \\\n" );
printf( "\t\t-width [expr [winfo screenwidth .] * 1 / 2] \n" );
printf( "\tframe $w.config.f\n" );
printf( "\tbind $w <Key-Down> \"$w.config.canvas yview scroll 1 unit;break;\"\n");
printf( "\tbind $w <Key-Up> \"$w.config.canvas yview scroll -1 unit;break;\"\n");
printf( "\tbind $w <Key-Next> \"$w.config.canvas yview scroll 1 page;break;\"\n");
printf( "\tbind $w <Key-Prior> \"$w.config.canvas yview scroll -1 page;break;\"\n");
printf( "\tbind $w <Key-Home> \"$w.config.canvas yview moveto 0;break;\"\n");
printf( "\tbind $w <Key-End> \"$w.config.canvas yview moveto 1 ;break;\"\n");
printf( "\tpack $w.config.canvas -side right -fill y\n" );
printf("\n\n");
}
 
 
 
/*
* Each proc we create needs a global declaration for any global variables we
* use. To minimize the size of the file, we set a flag each time we output
* a global declaration so we know whether we need to insert one for a
* given function or not.
*/
static void clear_globalflags(void)
{
int i;
for ( i = 1; i <= max_varnum; i++ )
vartable[i].global_written = 0;
}
 
 
 
/*
* Output a "global" line for a given variable. Also include the
* call to "vfix". (If vfix is not needed, then it's fine to just printf
* a "global" line).
*/
void global( const char *var )
{
printf( "\tglobal %s\n", var );
}
 
 
 
/*
* This function walks the chain of conditions that we got from cond.c
* and creates a TCL conditional to enable/disable a given widget.
*/
void generate_if( struct kconfig * cfg, struct condition * ocond,
int menu_num, int line_num )
{
struct condition * cond;
struct dependency * tmp;
struct kconfig * cfg1;
 
if ( line_num >= -1 )
{
if ( cfg->token == token_define_bool || cfg->token == token_define_hex
|| cfg->token == token_define_int || cfg->token == token_define_string
|| cfg->token == token_define_tristate || cfg->token == token_unset )
return;
if ( cfg->token == token_comment && line_num == -1 )
return;
}
else
{
if ( cfg->token == token_string || cfg->token == token_mainmenu_option )
return;
}
 
/*
* First write any global declarations we need for this conditional.
*/
for ( cond = ocond; cond != NULL; cond = cond->next )
{
switch ( cond->op )
{
default:
break;
 
case op_variable:
if ( ! vartable[cond->nameindex].global_written )
{
vartable[cond->nameindex].global_written = 1;
global( vartable[cond->nameindex].name );
}
break;
}
}
 
/*
* Now write this option.
*/
if ( cfg->nameindex > 0 && ! vartable[cfg->nameindex].global_written )
{
vartable[cfg->nameindex].global_written = 1;
global( vartable[cfg->nameindex].name );
}
 
/*
* Generate the body of the conditional.
*/
printf( "\tif {" );
for ( cond = ocond; cond != NULL; cond = cond->next )
{
switch ( cond->op )
{
default:
break;
 
case op_bang: printf( " ! " ); break;
case op_eq: printf( " == " ); break;
case op_neq: printf( " != " ); break;
case op_and: printf( " && " ); break;
case op_and1: printf( " && " ); break;
case op_or: printf( " || " ); break;
case op_lparen: printf( "(" ); break;
case op_rparen: printf( ")" ); break;
 
case op_variable:
printf( "$%s", vartable[cond->nameindex].name );
break;
 
case op_constant:
if ( strcmp( cond->str, "y" ) == 0 ) printf( "1" );
else if ( strcmp( cond->str, "n" ) == 0 ) printf( "0" );
else if ( strcmp( cond->str, "m" ) == 0 ) printf( "2" );
else if ( strcmp( cond->str, "" ) == 0 ) printf( "4" );
else
printf( "\"%s\"", cond->str );
break;
}
}
printf( "} then {" );
 
/*
* Generate a procedure call to write the value.
* This code depends on procedures in header.tk.
*/
if ( line_num >= -1 )
{
int modtoyes = 0;
 
switch ( cfg->token )
{
default:
printf( " }\n" );
break;
 
case token_dep_mbool:
modtoyes = 1;
case token_dep_bool:
printf( "\n" );
for ( tmp = cfg->depend; tmp; tmp = tmp->next )
if ( ! vartable[get_varnum( tmp->name )].global_written )
{
global( tmp->name );
}
printf( "\tset tmpvar_dep [effective_dep [list" );
for ( tmp = cfg->depend; tmp; tmp = tmp->next )
printf( " $%s", tmp->name );
printf( "]];set %s [sync_bool $%s $tmpvar_dep %d];",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name,
modtoyes );
printf( "if {$tmpvar_dep != 1" );
if (modtoyes)
printf( " && $tmpvar_dep != 2" );
printf( "} then {configure_entry .menu%d.config.f.x%d disabled {y};",
menu_num, line_num );
printf( "} else {" );
printf( "configure_entry .menu%d.config.f.x%d normal {y};",
menu_num, line_num );
printf( "}; " );
case token_bool:
if ( cfg->token == token_bool )
printf( "\n\t" );
printf( "configure_entry .menu%d.config.f.x%d normal {n l",
menu_num, line_num );
if ( cfg->token == token_bool )
printf( " y" );
printf( "}" );
printf( "} else {");
printf( "configure_entry .menu%d.config.f.x%d disabled {y n l}}\n",
menu_num, line_num );
break;
 
case token_choice_header:
printf( "configure_entry .menu%d.config.f.x%d normal {x l}",
menu_num, line_num );
printf( "} else {" );
printf( "configure_entry .menu%d.config.f.x%d disabled {x l}",
menu_num, line_num );
printf( "}\n" );
break;
 
case token_choice_item:
fprintf( stderr, "Internal error on token_choice_item\n" );
exit( 1 );
 
case token_dep_tristate:
printf( "\n" );
for ( tmp = cfg->depend; tmp; tmp = tmp->next )
if ( ! vartable[get_varnum( tmp->name )].global_written )
{
global( tmp->name );
}
printf( "\tset tmpvar_dep [effective_dep [list" );
for ( tmp = cfg->depend; tmp; tmp = tmp->next )
printf( " $%s", tmp->name );
printf( "]];set %s [sync_tristate $%s $tmpvar_dep];",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
printf( "\tif {$tmpvar_dep != 1} then {" );
printf( "configure_entry .menu%d.config.f.x%d disabled {y}",
menu_num, line_num );
printf( "} else {" );
printf( "configure_entry .menu%d.config.f.x%d normal {y}",
menu_num, line_num );
printf( "}; " );
printf( "if {$tmpvar_dep == 0} then {" );
printf( "configure_entry .menu%d.config.f.x%d disabled {m}",
menu_num, line_num );
printf( "} else {" );
printf( "configure_entry .menu%d.config.f.x%d normal {m}",
menu_num, line_num );
printf( "}; " );
case token_tristate:
if ( cfg->token == token_tristate )
{
printf( "\n\tconfigure_entry .menu%d.config.f.x%d normal {y}; ",
menu_num, line_num );
}
printf( "if {($CONFIG_MODULES == 1)} then {" );
printf( "configure_entry .menu%d.config.f.x%d normal {m}} else {",
menu_num, line_num );
printf( "configure_entry .menu%d.config.f.x%d disabled {m}}; ",
menu_num, line_num );
printf( "configure_entry .menu%d.config.f.x%d normal {n l}",
menu_num, line_num );
 
/*
* Or in a bit to the variable - this causes all of the radiobuttons
* to be deselected (i.e. not be red).
*/
printf( "} else {" );
printf( "configure_entry .menu%d.config.f.x%d disabled {y n m l}}\n",
menu_num, line_num );
break;
 
case token_hex:
case token_int:
case token_string:
printf( ".menu%d.config.f.x%d.x configure -state normal -foreground [ cget .ref -foreground ]; ",
menu_num, line_num );
printf( ".menu%d.config.f.x%d.l configure -state normal; ",
menu_num, line_num );
printf( "} else {" );
printf( ".menu%d.config.f.x%d.x configure -state disabled -foreground [ cget .ref -disabledforeground ]; ",
menu_num, line_num );
printf( ".menu%d.config.f.x%d.l configure -state disabled}\n",
menu_num, line_num );
break;
 
case token_comment:
case token_mainmenu_option:
if ( line_num >= 0 )
{
printf( "configure_entry .menu%d.config.f.x%d normal {m}",
menu_num, line_num );
printf( "} else {" );
printf( "configure_entry .menu%d.config.f.x%d disabled {m}}\n",
menu_num, line_num );
}
else
printf( ".f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n",
menu_num, menu_num );
break;
}
}
else
{
int modtoyes = 0;
 
switch ( cfg->token )
{
default:
printf( " }\n" );
break;
 
case token_dep_mbool:
modtoyes = 1;
case token_dep_bool:
printf( "\n" );
for ( tmp = cfg->depend; tmp; tmp = tmp->next )
if ( ! vartable[get_varnum( tmp->name )].global_written )
{
global( tmp->name );
}
printf( "\tset tmpvar_dep [effective_dep [list" );
for ( tmp = cfg->depend; tmp; tmp = tmp->next )
printf( " $%s", tmp->name );
printf( "]];set %s [sync_bool $%s $tmpvar_dep %d];",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name,
modtoyes );
case token_bool:
if ( cfg->token == token_bool )
printf( "\n\t" );
printf( "set %s [expr $%s&15]",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
printf( "} else {");
printf( "set %s [expr $%s|16]}\n",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
break;
 
case token_choice_header:
printf( "} else {" );
for ( cfg1 = cfg->next;
cfg1 != NULL && cfg1->token == token_choice_item;
cfg1 = cfg1->next )
printf( "set %s 4;", vartable[cfg1->nameindex].name );
printf( "}\n" );
break;
 
case token_choice_item:
fprintf( stderr, "Internal error on token_choice_item\n" );
exit( 1 );
 
case token_define_bool:
case token_define_tristate:
if ( ! vartable[get_varnum( cfg->value )].global_written )
{
global( cfg->value );
}
printf( "set %s $%s }\n",
vartable[cfg->nameindex].name, cfg->value );
break;
 
case token_define_hex:
case token_define_int:
printf( "set %s %s }\n",
vartable[cfg->nameindex].name, cfg->value );
break;
 
case token_define_string:
printf( "set %s \"%s\" }\n",
vartable[cfg->nameindex].name, cfg->value );
break;
 
case token_dep_tristate:
printf( "\n" );
for ( tmp = cfg->depend; tmp; tmp = tmp->next )
if ( ! vartable[get_varnum( tmp->name )].global_written )
{
global( tmp->name );
}
printf( "\tset tmpvar_dep [effective_dep [list" );
for ( tmp = cfg->depend; tmp; tmp = tmp->next )
printf( " $%s", tmp->name );
printf( "]]; set %s [sync_tristate $%s $tmpvar_dep]; ",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
case token_tristate:
if ( cfg->token == token_tristate )
printf( "if {($CONFIG_MODULES == 0) && ($%s == 2)} then {set %s 1}; ",
vartable[cfg->nameindex].name,
vartable[cfg->nameindex].name );
/*
* Or in a bit to the variable - this causes all of the radiobuttons
* to be deselected (i.e. not be red).
*/
printf( "set %s [expr $%s&15]",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
printf( "} else {" );
 
/*
* Clear the disable bit to enable the correct radiobutton.
*/
printf( "set %s [expr $%s|16]}\n",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
break;
 
case token_hex:
case token_int:
if ( cfg->value && *cfg->value == '$' )
{
int i = get_varnum( cfg->value+1 );
printf( "\n" );
if ( ! vartable[i].global_written )
{
global( vartable[i].name );
}
printf( "\t" );
}
if ( cfg->token == token_hex )
printf( "validate_hex " );
else if ( cfg->token == token_int )
printf( "validate_int " );
printf( "%s \"$%s\" %s}\n",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name,
cfg->value );
break;
 
case token_unset:
printf( "set %s 4}\n", vartable[cfg->nameindex].name );
break;
}
}
}
 
 
/*
* Generate a line that writes a variable to the output file.
*/
void generate_writeconfig( struct kconfig * cfg )
{
struct condition * cond;
struct dependency * tmp;
int depmod = 2;
/*
* Generate global declaration for this symbol.
*/
if ( cfg->token != token_comment )
{
if ( cfg->nameindex > 0 && ! vartable[cfg->nameindex].global_written )
{
vartable[cfg->nameindex].global_written = 1;
global( vartable[cfg->nameindex].name );
}
if ( cfg->token == token_define_tristate || cfg->token == token_define_bool )
{
if ( ! vartable[get_varnum( cfg->value )].global_written )
{
vartable[get_varnum( cfg->value )].global_written = 1;
global( cfg->value );
}
}
else if ( cfg->nameindex <= 0 && cfg->token == token_choice_header )
{
printf( "\tglobal tmpvar_%d\n", -(cfg->nameindex) );
}
}
 
/*
* Generate global declarations for the condition chain.
*/
for ( cond = cfg->cond; cond != NULL; cond = cond->next )
{
switch( cond->op )
{
default:
break;
 
case op_variable:
if ( ! vartable[cond->nameindex].global_written )
{
vartable[cond->nameindex].global_written = 1;
global( vartable[cond->nameindex].name );
}
break;
}
}
 
/*
* Generate indentation.
*/
printf( "\t" );
 
/*
* Generate the conditional.
*/
if ( cfg->cond != NULL )
{
printf( "if {" );
for ( cond = cfg->cond; cond != NULL; cond = cond->next )
{
switch ( cond->op )
{
default: break;
case op_bang: printf( " ! " ); break;
case op_eq: printf( " == " ); break;
case op_neq: printf( " != " ); break;
case op_and: printf( " && " ); break;
case op_and1: printf( " && " ); break;
case op_or: printf( " || " ); break;
case op_lparen: printf( "(" ); break;
case op_rparen: printf( ")" ); break;
 
case op_variable:
printf( "$%s", vartable[cond->nameindex].name );
break;
 
case op_constant:
if ( strcmp( cond->str, "n" ) == 0 ) printf( "0" );
else if ( strcmp( cond->str, "y" ) == 0 ) printf( "1" );
else if ( strcmp( cond->str, "m" ) == 0 ) printf( "2" );
else if ( strcmp( cond->str, "" ) == 0 ) printf( "4" );
else
printf( "\"%s\"", cond->str );
break;
}
}
printf( "} then {" );
}
 
/*
* Generate a procedure call to write the value.
* This code depends on the write_* procedures in header.tk.
*/
switch ( cfg->token )
{
default:
if ( cfg->cond != NULL )
printf( " }" );
printf( "\n" );
break;
 
case token_bool:
case token_tristate:
printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
if ( cfg->cond != NULL )
printf( " }" );
printf( "\n" );
break;
 
case token_choice_header:
/*
* This is funky code -- it fails if there were any conditionals.
* Fortunately all the conditionals got stripped off somewhere
* else.
*/
{
struct kconfig * cfg1;
for ( cfg1 = cfg->next;
cfg1 != NULL && cfg1->token == token_choice_item;
cfg1 = cfg1->next )
{
printf("\n\tif { $tmpvar_%d == \"%s\" } then { write_tristate $cfg $autocfg %s 1 [list $notmod] 2 } else { write_tristate $cfg $autocfg %s 0 [list $notmod] 2 }",
-(cfg->nameindex), cfg1->label,
vartable[cfg1->nameindex].name,
vartable[cfg1->nameindex].name );
}
}
if ( cfg->cond != NULL )
printf( "}" );
printf( "\n" );
break;
 
case token_choice_item:
fprintf( stderr, "Internal error on token_choice_item\n" );
exit( 1 );
 
case token_comment:
printf( "write_comment $cfg $autocfg \"%s\"",
cfg->label );
if ( cfg->cond != NULL )
printf( "}" );
printf( "\n" );
break;
 
case token_define_bool:
case token_define_tristate:
if ( cfg->cond == NULL )
{
printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2\n",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
}
else
{
printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2 }\n",
vartable[cfg->nameindex].name, cfg->value );
}
break;
 
case token_dep_mbool:
depmod = 1;
case token_dep_bool:
case token_dep_tristate:
printf( "write_tristate $cfg $autocfg %s $%s [list",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
for ( tmp = cfg->depend; tmp; tmp = tmp->next )
printf( " $%s", tmp->name );
printf( "] %d", depmod );
if ( cfg->cond != NULL )
printf( " }" );
printf( "\n" );
break;
 
case token_define_hex:
printf( "write_hex $cfg $autocfg %s %s $notmod",
vartable[cfg->nameindex].name, cfg->value );
if ( cfg->cond != NULL )
printf( " }" );
printf( "\n" );
break;
 
case token_define_int:
printf( "write_int $cfg $autocfg %s %s $notmod",
vartable[cfg->nameindex].name, cfg->value );
if ( cfg->cond != NULL )
printf( " }" );
printf( "\n" );
break;
 
case token_define_string:
printf( "write_string $cfg $autocfg %s \"%s\" $notmod",
vartable[cfg->nameindex].name, cfg->value );
if ( cfg->cond != NULL )
printf( " }" );
printf( "\n" );
break;
 
case token_hex:
printf( "write_hex $cfg $autocfg %s $%s $notmod",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
if ( cfg->cond != NULL )
printf( " }" );
printf( "\n" );
break;
 
case token_int:
printf( "write_int $cfg $autocfg %s $%s $notmod",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
if ( cfg->cond != NULL )
printf( " }" );
printf( "\n" );
break;
 
case token_string:
printf( "write_string $cfg $autocfg %s \"$%s\" $notmod",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
if ( cfg->cond != NULL )
printf( " }" );
printf( "\n" );
break;
}
}
 
static void generate_update_var( struct kconfig * scfg, int menu_num )
{
struct kconfig * cfg;
 
if ( menu_num>0 )
{
printf( "proc update_define_menu%d {} {\n", menu_num );
printf( "\tupdate_define_mainmenu\n" );
}
else
printf( "proc update_define_mainmenu {} {\n" );
clear_globalflags();
global( "CONFIG_MODULES" );
vartable[ get_varnum( "CONFIG_MODULES" ) ].global_written = 1;
for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
{
if ( cfg->menu_number == menu_num && (cfg->token == token_define_bool || cfg->token == token_define_tristate
|| cfg->token == token_define_hex || cfg->token == token_define_int
|| cfg->token == token_define_string || cfg->token == token_unset
|| cfg->token == token_tristate) )
{
if ( ! vartable[cfg->nameindex].global_written )
{
vartable[cfg->nameindex].global_written = 1;
global( vartable[cfg->nameindex].name );
}
}
}
 
for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
{
char tmp[20];
struct kconfig * cfg1;
 
if ( cfg->menu_number == menu_num )
{
switch ( cfg->token )
{
default:
case token_choice_item:
break;
case token_choice_header:
sprintf( tmp, "tmpvar_%d", -(cfg->nameindex) );
global( tmp );
for ( cfg1 = cfg->next;
cfg1 != NULL && cfg1->token == token_choice_item;
cfg1 = cfg1->next )
{
vartable[cfg1->nameindex].global_written = 1;
global( vartable[cfg1->nameindex].name );
printf( "\tif {$tmpvar_%d == \"%s\"} then {set %s 1} else {set %s 0}\n",
-(cfg->nameindex), cfg1->label,
vartable[cfg1->nameindex].name,
vartable[cfg1->nameindex].name );
}
break;
case token_bool:
case token_define_bool:
case token_define_tristate:
case token_define_hex:
case token_define_int:
case token_define_string:
case token_dep_bool:
case token_dep_tristate:
case token_dep_mbool:
case token_int:
case token_hex:
case token_mainmenu_option:
case token_tristate:
case token_unset:
if ( cfg->cond != NULL )
generate_if( cfg, cfg->cond, menu_num, -2 );
else switch ( cfg->token )
{
case token_tristate:
printf( "\n\tif {($CONFIG_MODULES == 0)} then {if {($%s == 2)} then {set %s 1}}\n",
vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
break;
case token_define_bool:
case token_define_tristate:
if ( ! vartable[get_varnum( cfg->value )].global_written )
{
vartable[get_varnum( cfg->value )].global_written = 1;
global( cfg->value );
}
printf( "\tset %s $%s\n", vartable[cfg->nameindex].name,
cfg->value );
break;
case token_define_hex:
case token_define_int:
printf( "\tset %s %s\n", vartable[cfg->nameindex].name,
cfg->value );
break;
case token_define_string:
printf( "\tset %s \"%s\"\n", vartable[cfg->nameindex].name,
cfg->value );
break;
case token_unset:
printf( "\tset %s 4\n", vartable[cfg->nameindex].name );
default:
break;
}
}
}
}
printf( "}\n\n\n" );
}
 
 
/*
* Generates the end of a menu procedure.
*/
static void end_proc( struct kconfig * scfg, int menu_num )
{
struct kconfig * cfg;
 
printf( "\n\n\n" );
printf( "\tfocus $w\n" );
printf( "\tupdate_active\n" );
printf( "\tglobal winx; global winy\n" );
if ( menu_first[menu_num]->menu_number != 0 )
{
printf( "\tif {[winfo exists .menu%d] == 0} then ",
menu_first[menu_num]->menu_number );
printf( "{menu%d .menu%d \"%s\"}\n",
menu_first[menu_num]->menu_number, menu_first[menu_num]->menu_number,
menu_first[menu_first[menu_num]->menu_number]->label );
printf( "\tset winx [expr [winfo x .menu%d]+30]; set winy [expr [winfo y .menu%d]+30]\n",
menu_first[menu_num]->menu_number, menu_first[menu_num]->menu_number );
}
else
printf( "\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n" );
printf( "\tif {[winfo exists $w]} then {wm geometry $w +$winx+$winy}\n" );
 
/*
* Now that the whole window is in place, we need to wait for an "update"
* so we can tell the canvas what its virtual size should be.
*
* Unfortunately, this causes some ugly screen-flashing because the whole
* window is drawn, and then it is immediately resized. It seems
* unavoidable, though, since "frame" objects won't tell us their size
* until after an update, and "canvas" objects can't automatically pack
* around frames. Sigh.
*/
printf( "\tupdate idletasks\n" );
printf( "\tif {[winfo exists $w]} then {$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n" );
printf( "\t$w.config.canvas configure \\\n" );
printf( "\t\t-width [expr [winfo reqwidth $w.config.f] + 1]\\\n" );
printf( "\t\t-scrollregion \"-1 -1 [expr [winfo reqwidth $w.config.f] + 1] \\\n" );
printf( "\t\t\t [expr [winfo reqheight $w.config.f] + 1]\"\n\n" );
/*
* If the whole canvas will fit in 3/4 of the screen height, do it;
* otherwise, resize to around 1/2 the screen and let us scroll.
*/
printf( "\tset winy [expr [winfo reqh $w] - [winfo reqh $w.config.canvas]]\n" );
printf( "\tset scry [expr [winfo screenh $w] / 2]\n" );
printf( "\tset maxy [expr [winfo screenh $w] * 3 / 4]\n" );
printf( "\tset canvtotal [expr [winfo reqh $w.config.f] + 2]\n" );
printf( "\tif [expr $winy + $canvtotal < $maxy] {\n" );
printf( "\t\t$w.config.canvas configure -height $canvtotal\n" );
printf( "\t} else {\n" );
printf( "\t\t$w.config.canvas configure -height [expr $scry - $winy]\n" );
printf( "\t\t}\n\t}\n" );
 
/*
* Limit the min/max window size. Height can vary, but not width,
* because of the limitations of canvas and our laziness.
*/
printf( "\tupdate idletasks\n" );
printf( "\tif {[winfo exists $w]} then {\n\twm maxsize $w [winfo width $w] [winfo screenheight $w]\n" );
printf( "\twm minsize $w [winfo width $w] 100\n\n" );
printf( "\twm deiconify $w\n" );
printf( "}\n}\n\n" );
 
/*
* Now we generate the companion procedure for the menu we just
* generated. This procedure contains all of the code to
* disable/enable widgets based upon the settings of the other
* widgets, and will be called first when the window is mapped,
* and each time one of the buttons in the window are clicked.
*/
printf( "proc update_menu%d {} {\n", menu_num );
 
/*
* Clear all of the booleans that are defined in this menu.
*/
clear_globalflags();
for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
{
if ( cfg->menu_number == menu_num
&& cfg->token != token_mainmenu_option
&& cfg->token != token_choice_item )
{
if ( cfg->cond != NULL )
{
int i;
if ( (cfg->token == token_tristate || cfg->token == token_dep_tristate)
&& ! vartable[i = get_varnum( "CONFIG_MODULES" )].global_written )
{
global( "CONFIG_MODULES" );
vartable[i].global_written = 1;
}
generate_if( cfg, cfg->cond, cfg->menu_number, cfg->menu_line );
}
else
{
if ( cfg->token == token_tristate )
{
int i;
if ( ! vartable[cfg->nameindex].global_written )
{
vartable[cfg->nameindex].global_written = 1;
printf( "\tglobal %s\n", vartable[cfg->nameindex].name );
}
if ( ! vartable[i = get_varnum( "CONFIG_MODULES" )].global_written )
{
global( "CONFIG_MODULES" );
vartable[i].global_written = 1;
}
printf( "\n\tif {($CONFIG_MODULES == 1)} then {configure_entry .menu%d.config.f.x%d normal {m}} else {configure_entry .menu%d.config.f.x%d disabled {m}}\n",
menu_num, cfg->menu_line,
menu_num, cfg->menu_line );
}
}
}
else if ( cfg->token == token_mainmenu_option
&& cfg->menu_number == menu_num
&& cfg->cond != NULL )
{
generate_if( cfg, cfg->cond, menu_num, cfg->menu_line );
}
}
printf("}\n\n\n");
 
generate_update_var( scfg, menu_num );
}
 
/*
* This is the top level function for generating the tk script.
*/
void dump_tk_script( struct kconfig * scfg )
{
int menu_depth;
int menu_num [64];
int imenu, i;
int top_level_num = 0;
struct kconfig * cfg;
struct kconfig * cfg1 = NULL;
const char * name = "No Name";
 
/*
* Mark begin and end of each menu so I can omit submenus when walking
* over a parent menu.
*/
tot_menu_num = 0;
menu_depth = 0;
menu_num [0] = 0;
 
for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
{
switch ( cfg->token )
{
default:
break;
 
case token_mainmenu_name:
name = cfg->label;
break;
 
case token_mainmenu_option:
if ( ++menu_depth >= 64 )
{ fprintf( stderr, "menus too deep\n" ); exit( 1 ); }
if ( ++tot_menu_num >= 100 )
{ fprintf( stderr, "too many menus\n" ); exit( 1 ); }
menu_num [menu_depth] = tot_menu_num;
menu_first [tot_menu_num] = cfg;
menu_last [tot_menu_num] = cfg;
/*
* Note, that menu_number is set to the number of parent
* (upper level) menu.
*/
cfg->menu_number = menu_num[menu_depth - 1];
if ( menu_depth == 1 )
++top_level_num;
break;
 
case token_endmenu:
menu_last [menu_num [menu_depth]] = cfg;
/* flatten menus with proper scoping */
if ( --menu_depth < 0 )
{ fprintf( stderr, "unmatched endmenu\n" ); exit( 1 ); }
break;
 
case token_bool:
case token_choice_header:
case token_choice_item:
case token_comment:
case token_dep_bool:
case token_dep_tristate:
case token_dep_mbool:
case token_hex:
case token_int:
case token_string:
case token_tristate:
cfg->menu_number = menu_num[menu_depth];
if ( menu_depth == 0 )
{ fprintf( stderr, "statement not in menu\n" ); exit( 1 ); }
break;
 
case token_define_bool:
case token_define_hex:
case token_define_int:
case token_define_string:
case token_define_tristate:
case token_unset:
cfg->menu_number = menu_num[menu_depth];
break;
}
}
 
/*
* Generate menus per column setting.
* There are:
* four extra buttons for save/quit/load/store;
* one blank button
* add two to round up for division
*/
printf( "set menus_per_column %d\n", (top_level_num + 4 + 1 + 2) / 3 );
printf( "set total_menus %d\n\n", tot_menu_num );
 
printf( "proc toplevel_menu {num} {\n" );
for ( imenu = 1; imenu <= tot_menu_num; ++imenu )
{
int parent = 1;
 
if ( menu_first[imenu]->menu_number == 0 )
parent = menu_first[imenu]->menu_number;
else
printf( "\tif {$num == %d} then {return %d}\n",
imenu, menu_first[imenu]->menu_number );
}
printf( "\treturn $num\n}\n\n" );
 
/*
* Generate the menus.
*/
printf( "mainmenu_name \"%s\"\n", name );
for ( imenu = 1; imenu <= tot_menu_num; ++imenu )
{
int menu_line = 0;
int nr_submenu = imenu;
int menu_name_omitted = 0;
int opt_count = 0;
 
clear_globalflags();
start_proc( menu_first[imenu]->label, imenu,
!menu_first[imenu]->menu_number );
 
for ( cfg = menu_first[imenu]->next; cfg != NULL && cfg != menu_last[imenu]; cfg = cfg->next )
{
switch ( cfg->token )
{
default:
break;
 
case token_mainmenu_option:
while ( menu_first[++nr_submenu]->menu_number > imenu )
;
cfg->menu_line = menu_line++;
printf( "\tsubmenu $w.config.f %d %d \"%s\" %d\n",
cfg->menu_number, cfg->menu_line, cfg->label, nr_submenu );
cfg = menu_last[nr_submenu];
break;
 
case token_comment:
if ( !cfg->menu_line && !menu_name_omitted )
{
cfg->menu_line = -1;
menu_name_omitted = 1;
}
else
{
menu_name_omitted = 1;
cfg->menu_line = menu_line++;
printf( "\tcomment $w.config.f %d %d \"%s\"\n",
cfg->menu_number, cfg->menu_line, cfg->label );
}
break;
 
case token_bool:
cfg->menu_line = menu_line++;
printf( "\tbool $w.config.f %d %d \"%s\" %s\n",
cfg->menu_number, cfg->menu_line, cfg->label,
vartable[cfg->nameindex].name );
break;
 
case token_choice_header:
/*
* I need the first token_choice_item to pick out the right
* help text from Documentation/Configure.help.
*/
cfg->menu_line = menu_line++;
printf( "\tglobal tmpvar_%d\n", -(cfg->nameindex) );
printf( "\tminimenu $w.config.f %d %d \"%s\" tmpvar_%d %s\n",
cfg->menu_number, cfg->menu_line, cfg->label,
-(cfg->nameindex), vartable[cfg->next->nameindex].name );
printf( "\tmenu $w.config.f.x%d.x.menu -tearoffcommand \"menutitle \\\"%s\\\"\"\n",
cfg->menu_line, cfg->label );
cfg1 = cfg;
opt_count = 0;
break;
 
case token_choice_item:
/* note: no menu line; uses choice header menu line */
printf( "\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable tmpvar_%d -value \"%s\" -command \"update_active\"\n",
cfg1->menu_line, cfg->label, -(cfg1->nameindex),
cfg->label );
opt_count++;
if ( cfg->next && cfg->next->token != token_choice_item ) {
/* last option in the menu */
printf( "\tmenusplit $w $w.config.f.x%d.x.menu %d\n",
cfg1->menu_line, opt_count );
}
break;
 
case token_dep_bool:
case token_dep_mbool:
cfg->menu_line = menu_line++;
printf( "\tdep_bool $w.config.f %d %d \"%s\" %s\n",
cfg->menu_number, cfg->menu_line, cfg->label,
vartable[cfg->nameindex].name );
break;
 
case token_dep_tristate:
cfg->menu_line = menu_line++;
printf( "\tdep_tristate $w.config.f %d %d \"%s\" %s\n",
cfg->menu_number, cfg->menu_line, cfg->label,
vartable[cfg->nameindex].name );
break;
 
case token_hex:
cfg->menu_line = menu_line++;
printf( "\thex $w.config.f %d %d \"%s\" %s\n",
cfg->menu_number, cfg->menu_line, cfg->label,
vartable[cfg->nameindex].name );
break;
 
case token_int:
cfg->menu_line = menu_line++;
printf( "\tint $w.config.f %d %d \"%s\" %s\n",
cfg->menu_number, cfg->menu_line, cfg->label,
vartable[cfg->nameindex].name );
break;
 
case token_string:
cfg->menu_line = menu_line++;
printf( "\tistring $w.config.f %d %d \"%s\" %s\n",
cfg->menu_number, cfg->menu_line, cfg->label,
vartable[cfg->nameindex].name );
break;
 
case token_tristate:
cfg->menu_line = menu_line++;
printf( "\ttristate $w.config.f %d %d \"%s\" %s\n",
cfg->menu_number, cfg->menu_line, cfg->label,
vartable[cfg->nameindex].name );
break;
}
}
 
end_proc( scfg, imenu );
}
 
/*
* The top level menu also needs an update function. When we update a
* submenu, we may need to disable one or more of the submenus on
* the top level menu, and this procedure will ensure that things are
* correct.
*/
clear_globalflags();
printf( "proc update_mainmenu {} {\n" );
for ( imenu = 1; imenu <= tot_menu_num; imenu++ )
{
if ( menu_first[imenu]->cond != NULL && menu_first[imenu]->menu_number == 0 )
generate_if( menu_first[imenu], menu_first[imenu]->cond, imenu, -1 );
}
printf( "}\n\n\n" );
 
clear_globalflags();
/*
* Generate code to load the default settings into the variables.
* The script in tail.tk will attempt to load .config,
* which may override these settings, but that's OK.
*/
for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
{
switch ( cfg->token )
{
default:
break;
 
case token_bool:
case token_choice_item:
case token_dep_bool:
case token_dep_tristate:
case token_dep_mbool:
case token_tristate:
if ( ! vartable[cfg->nameindex].global_written )
{
printf( "set %s 0\n", vartable[cfg->nameindex].name );
vartable[cfg->nameindex].global_written = 1;
}
break;
 
case token_choice_header:
printf( "set tmpvar_%d \"(not set)\"\n", -(cfg->nameindex) );
break;
 
case token_hex:
case token_int:
if ( ! vartable[cfg->nameindex].global_written )
{
printf( "set %s %s\n", vartable[cfg->nameindex].name, cfg->value ? cfg->value : "0" );
vartable[cfg->nameindex].global_written = 1;
}
break;
 
case token_string:
if ( ! vartable[cfg->nameindex].global_written )
{
printf( "set %s \"%s\"\n", vartable[cfg->nameindex].name, cfg->value );
vartable[cfg->nameindex].global_written = 1;
}
break;
}
}
 
/*
* Define to an empty value all other variables (which are never defined)
*/
for ( i = 1; i <= max_varnum; i++ )
{
if ( ! vartable[i].global_written
&& strncmp( vartable[i].name, "CONSTANT_", 9 ) )
printf( "set %s 4\n", vartable[i].name );
}
 
/*
* Generate a function to write all of the variables to a file.
*/
printf( "proc writeconfig {file1 file2} {\n" );
printf( "\tset cfg [open $file1 w]\n" );
printf( "\tset autocfg [open $file2 w]\n" );
printf( "\tset notmod 1\n" );
printf( "\tset notset 0\n" );
printf( "\tputs $cfg \"#\"\n");
printf( "\tputs $cfg \"# Automatically generated make config: don't edit\"\n");
printf( "\tputs $cfg \"#\"\n" );
 
printf( "\tputs $autocfg \"/*\"\n" );
printf( "\tputs $autocfg \" * Automatically generated C config: don't edit\"\n" );
printf( "\tputs $autocfg \" */\"\n" );
printf( "\tputs $autocfg \"#define AUTOCONF_INCLUDED\"\n" );
 
clear_globalflags();
for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
{
switch ( cfg->token )
{
default:
break;
 
case token_bool:
case token_choice_header:
case token_comment:
case token_define_bool:
case token_define_hex:
case token_define_int:
case token_define_string:
case token_define_tristate:
case token_dep_bool:
case token_dep_tristate:
case token_dep_mbool:
case token_hex:
case token_int:
case token_string:
case token_tristate:
generate_writeconfig( cfg );
break;
}
}
printf( "\tclose $cfg\n" );
printf( "\tclose $autocfg\n" );
printf( "}\n\n\n" );
 
/*
* Generate a simple function that updates the master choice
* variable depending upon what values were loaded from a .config
* file.
*/
printf( "proc clear_choices { } {\n" );
for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
{
if ( cfg->token == token_choice_header )
{
for ( cfg1 = cfg->next;
cfg1 != NULL && cfg1->token == token_choice_item;
cfg1 = cfg1->next )
{
printf( "\tglobal %s; set %s 0\n",
vartable[cfg1->nameindex].name,
vartable[cfg1->nameindex].name );
}
}
}
printf( "}\n\n\n" );
 
printf( "proc update_choices { } {\n" );
for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
{
if ( cfg->token == token_choice_header )
{
printf( "\tglobal tmpvar_%d\n", -(cfg->nameindex) );
printf("\tset tmpvar_%d \"%s\"\n", -(cfg->nameindex), cfg->value);
for ( cfg1 = cfg->next;
cfg1 != NULL && cfg1->token == token_choice_item;
cfg1 = cfg1->next )
{
printf( "\tglobal %s\n", vartable[cfg1->nameindex].name );
printf( "\tif { $%s == 1 } then { set tmpvar_%d \"%s\" }\n",
vartable[cfg1->nameindex].name,
-(cfg->nameindex), cfg1->label );
}
}
}
printf( "}\n\n\n" );
 
generate_update_var( scfg, 0 );
 
/*
* That's it. We are done. The output of this file will have header.tk
* prepended and tail.tk appended to create an executable wish script.
*/
}
/tkparse.c
0,0 → 1,828
/*
* tkparse.c
*
* Eric Youngdale was the original author of xconfig.
* Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
*
* Parse a config.in file and translate it to a wish script.
* This task has three parts:
*
* tkparse.c tokenize the input
* tkcond.c transform 'if ...' statements
* tkgen.c generate output
*
* Change History
*
* 7 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
* - Teach dep_tristate about a few literals, such as:
* dep_tristate 'foo' CONFIG_FOO m
* Also have it print an error message and exit on some parse failures.
*
* 14 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
* - Don't fclose stdin. Thanks to Tony Hoyle for nailing this one.
*
* 14 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
* - Steam-clean this file. I tested this by generating kconfig.tk for
* every architecture and comparing it character-for-character against
* the output of the old tkparse.
*
* 23 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
* - Remove bug-compatible code.
*
* 07 July 1999, Andrzej M. Krzysztofowicz, <ankry@mif.pg.gda.pl>
* - Submenus implemented,
* - plenty of option updating/displaying fixes,
* - dep_bool, define_hex, define_int, define_string, define_tristate and
* undef implemented,
* - dep_tristate fixed to support multiple dependencies,
* - handling of variables with an empty value implemented,
* - value checking for int and hex fields,
* - more checking during condition parsing; choice variables are treated as
* all others now,
*
* TO DO:
* - xconfig is at the end of its life cycle. Contact <mec@shout.net> if
* you are interested in working on the replacement.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "tkparse.h"
 
static struct kconfig * config_list = NULL;
static struct kconfig * config_last = NULL;
static const char * current_file = "<unknown file>";
static int lineno = 0;
 
static void do_source( const char * );
 
#undef strcmp
int my_strcmp( const char * s1, const char * s2 ) { return strcmp( s1, s2 ); }
#define strcmp my_strcmp
 
/*
* Report a syntax error.
*/
static void syntax_error( const char * msg )
{
fprintf( stderr, "%s: %d: %s\n", current_file, lineno, msg );
exit( 1 );
}
 
 
 
/*
* Find index of a specific variable in the symbol table.
* Create a new entry if it does not exist yet.
*/
struct variable *vartable;
int max_varnum = 0;
static int vartable_size = 0;
 
int get_varnum( char * name )
{
int i;
for ( i = 1; i <= max_varnum; i++ )
if ( strcmp( vartable[i].name, name ) == 0 )
return i;
while (max_varnum+1 >= vartable_size) {
vartable = realloc(vartable, (vartable_size += 1000)*sizeof(*vartable));
if (!vartable) {
fprintf(stderr, "tkparse realloc vartable failed\n");
exit(1);
}
}
vartable[++max_varnum].name = malloc( strlen( name )+1 );
strcpy( vartable[max_varnum].name, name );
return max_varnum;
}
 
 
 
/*
* Get a string.
*/
static const char * get_string( const char * pnt, char ** label )
{
const char * word;
 
word = pnt;
for ( ; ; )
{
if ( *pnt == '\0' || *pnt == ' ' || *pnt == '\t' )
break;
pnt++;
}
 
*label = malloc( pnt - word + 1 );
memcpy( *label, word, pnt - word );
(*label)[pnt - word] = '\0';
 
if ( *pnt != '\0' )
pnt++;
return pnt;
}
 
 
 
/*
* Get a quoted string.
* Insert a '\' before any characters that need quoting.
*/
static const char * get_qstring( const char * pnt, char ** label )
{
char quote_char;
char newlabel [2048];
char * pnt1;
 
/* advance to the open quote */
for ( ; ; )
{
if ( *pnt == '\0' )
return pnt;
quote_char = *pnt++;
if ( quote_char == '"' || quote_char == '\'' )
break;
}
 
/* copy into an intermediate buffer */
pnt1 = newlabel;
for ( ; ; )
{
if ( *pnt == '\0' )
syntax_error( "unterminated quoted string" );
if ( *pnt == quote_char && pnt[-1] != '\\' )
break;
 
/* copy the character, quoting if needed */
if ( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']' )
*pnt1++ = '\\';
*pnt1++ = *pnt++;
}
 
/* copy the label into a permanent location */
*pnt1++ = '\0';
*label = (char *) malloc( pnt1 - newlabel );
memcpy( *label, newlabel, pnt1 - newlabel );
 
/* skip over last quote and next whitespace */
pnt++;
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
return pnt;
}
 
 
 
/*
* Get a quoted or unquoted string. It is recognized by the first
* non-white character. '"' and '"' are not allowed inside the string.
*/
static const char * get_qnqstring( const char * pnt, char ** label )
{
char quote_char;
 
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
 
if ( *pnt == '\0' )
return pnt;
quote_char = *pnt;
if ( quote_char == '"' || quote_char == '\'' )
return get_qstring( pnt, label );
else
return get_string( pnt, label );
}
 
 
 
/*
* Tokenize an 'if' statement condition.
*/
static struct condition * tokenize_if( const char * pnt )
{
struct condition * list;
struct condition * last;
struct condition * prev;
 
/* eat the open bracket */
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
if ( *pnt != '[' )
syntax_error( "bad 'if' condition" );
pnt++;
 
list = last = NULL;
for ( ; ; )
{
struct condition * cond;
 
/* advance to the next token */
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
if ( *pnt == '\0' )
syntax_error( "unterminated 'if' condition" );
if ( *pnt == ']' )
return list;
 
/* allocate a new token */
cond = malloc( sizeof(*cond) );
memset( cond, 0, sizeof(*cond) );
if ( last == NULL )
{ list = last = cond; prev = NULL; }
else
{ prev = last; last->next = cond; last = cond; }
 
/* determine the token value */
if ( *pnt == '-' && pnt[1] == 'a' )
{
if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
syntax_error( "incorrect argument" );
cond->op = op_and; pnt += 2; continue;
}
 
if ( *pnt == '-' && pnt[1] == 'o' )
{
if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
syntax_error( "incorrect argument" );
cond->op = op_or; pnt += 2; continue;
}
 
if ( *pnt == '!' && pnt[1] == '=' )
{
if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
syntax_error( "incorrect argument" );
cond->op = op_neq; pnt += 2; continue;
}
 
if ( *pnt == '=' )
{
if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
syntax_error( "incorrect argument" );
cond->op = op_eq; pnt += 1; continue;
}
 
if ( *pnt == '!' )
{
if ( prev && ( prev->op != op_and && prev->op != op_or
&& prev->op != op_bang ) )
syntax_error( "incorrect argument" );
cond->op = op_bang; pnt += 1; continue;
}
 
if ( *pnt == '"' )
{
const char * word;
 
if ( prev && ( prev->op == op_variable || prev->op == op_constant ) )
syntax_error( "incorrect argument" );
/* advance to the word */
pnt++;
if ( *pnt == '$' )
{ cond->op = op_variable; pnt++; }
else
{ cond->op = op_constant; }
 
/* find the end of the word */
word = pnt;
for ( ; ; )
{
if ( *pnt == '\0' )
syntax_error( "unterminated double quote" );
if ( *pnt == '"' )
break;
pnt++;
}
 
/* store a copy of this word */
{
char * str = malloc( pnt - word + 1 );
memcpy( str, word, pnt - word );
str [pnt - word] = '\0';
if ( cond->op == op_variable )
{
cond->nameindex = get_varnum( str );
free( str );
}
else /* op_constant */
{
cond->str = str;
}
}
 
pnt++;
continue;
}
 
/* unknown token */
syntax_error( "bad if condition" );
}
}
 
 
 
/*
* Tokenize a choice list. Choices appear as pairs of strings;
* note that I am parsing *inside* the double quotes. Ugh.
*/
static const char * tokenize_choices( struct kconfig * cfg_choose,
const char * pnt )
{
int default_checked = 0;
for ( ; ; )
{
struct kconfig * cfg;
char * buffer = malloc( 64 );
 
/* skip whitespace */
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
if ( *pnt == '\0' )
return pnt;
 
/* allocate a new kconfig line */
cfg = malloc( sizeof(*cfg) );
memset( cfg, 0, sizeof(*cfg) );
if ( config_last == NULL )
{ config_last = config_list = cfg; }
else
{ config_last->next = cfg; config_last = cfg; }
 
/* fill out the line */
cfg->token = token_choice_item;
cfg->cfg_parent = cfg_choose;
pnt = get_string( pnt, &cfg->label );
if ( ! default_checked &&
! strncmp( cfg->label, cfg_choose->value, strlen( cfg_choose->value ) ) )
{
default_checked = 1;
free( cfg_choose->value );
cfg_choose->value = cfg->label;
}
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
pnt = get_string( pnt, &buffer );
cfg->nameindex = get_varnum( buffer );
}
if ( ! default_checked )
syntax_error( "bad 'choice' default value" );
return pnt;
}
 
 
 
/*
* Tokenize one line.
*/
static void tokenize_line( const char * pnt )
{
static struct kconfig * last_menuoption = NULL;
enum e_token token;
struct kconfig * cfg;
struct dependency ** dep_ptr;
char * buffer = malloc( 64 );
 
/* skip white space */
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
 
/*
* categorize the next token
*/
 
#define match_token(t, s) \
if (strncmp(pnt, s, strlen(s)) == 0) { token = t; pnt += strlen(s); break; }
 
token = token_UNKNOWN;
switch ( *pnt )
{
default:
break;
 
case '#':
case '\0':
return;
 
case 'b':
match_token( token_bool, "bool" );
break;
 
case 'c':
match_token( token_choice_header, "choice" );
match_token( token_comment, "comment" );
break;
 
case 'd':
match_token( token_define_bool, "define_bool" );
match_token( token_define_hex, "define_hex" );
match_token( token_define_int, "define_int" );
match_token( token_define_string, "define_string" );
match_token( token_define_tristate, "define_tristate" );
match_token( token_dep_bool, "dep_bool" );
match_token( token_dep_mbool, "dep_mbool" );
match_token( token_dep_tristate, "dep_tristate" );
break;
 
case 'e':
match_token( token_else, "else" );
match_token( token_endmenu, "endmenu" );
break;
 
case 'f':
match_token( token_fi, "fi" );
break;
 
case 'h':
match_token( token_hex, "hex" );
break;
 
case 'i':
match_token( token_if, "if" );
match_token( token_int, "int" );
break;
 
case 'm':
match_token( token_mainmenu_name, "mainmenu_name" );
match_token( token_mainmenu_option, "mainmenu_option" );
break;
 
case 's':
match_token( token_source, "source" );
match_token( token_string, "string" );
break;
 
case 't':
match_token( token_then, "then" );
match_token( token_tristate, "tristate" );
break;
 
case 'u':
match_token( token_unset, "unset" );
break;
}
 
#undef match_token
 
if ( token == token_source )
{
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
do_source( pnt );
return;
}
 
if ( token == token_then )
{
if ( config_last != NULL && config_last->token == token_if )
return;
syntax_error( "bogus 'then'" );
}
 
#if 0
if ( token == token_unset )
{
fprintf( stderr, "Ignoring 'unset' command\n" );
return;
}
#endif
 
if ( token == token_UNKNOWN )
syntax_error( "unknown command" );
 
/*
* Allocate an item.
*/
cfg = malloc( sizeof(*cfg) );
memset( cfg, 0, sizeof(*cfg) );
if ( config_last == NULL )
{ config_last = config_list = cfg; }
else
{ config_last->next = cfg; config_last = cfg; }
 
/*
* Tokenize the arguments.
*/
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
 
cfg->token = token;
switch ( token )
{
default:
syntax_error( "unknown token" );
 
case token_bool:
case token_tristate:
pnt = get_qstring ( pnt, &cfg->label );
pnt = get_string ( pnt, &buffer );
cfg->nameindex = get_varnum( buffer );
break;
 
case token_choice_header:
{
static int choose_number = 0;
char * choice_list;
 
pnt = get_qstring ( pnt, &cfg->label );
pnt = get_qstring ( pnt, &choice_list );
pnt = get_string ( pnt, &cfg->value );
cfg->nameindex = -(choose_number++);
tokenize_choices( cfg, choice_list );
free( choice_list );
}
break;
 
case token_comment:
pnt = get_qstring(pnt, &cfg->label);
if ( last_menuoption != NULL )
{
pnt = get_qstring(pnt, &cfg->label);
if (cfg->label == NULL)
syntax_error( "missing comment text" );
last_menuoption->label = cfg->label;
last_menuoption = NULL;
}
break;
 
case token_define_bool:
case token_define_tristate:
pnt = get_string( pnt, &buffer );
cfg->nameindex = get_varnum( buffer );
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
if ( ( pnt[0] == 'Y' || pnt[0] == 'M' || pnt[0] == 'N'
|| pnt[0] == 'y' || pnt[0] == 'm' || pnt[0] == 'n' )
&& ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) )
{
if ( *pnt == 'n' || *pnt == 'N' ) cfg->value = strdup( "CONSTANT_N" );
else if ( *pnt == 'y' || *pnt == 'Y' ) cfg->value = strdup( "CONSTANT_Y" );
else if ( *pnt == 'm' || *pnt == 'M' ) cfg->value = strdup( "CONSTANT_M" );
}
else if ( *pnt == '$' )
{
pnt++;
pnt = get_string( pnt, &cfg->value );
}
else
{
syntax_error( "unknown define_bool value" );
}
get_varnum( cfg->value );
break;
 
case token_define_hex:
case token_define_int:
pnt = get_string( pnt, &buffer );
cfg->nameindex = get_varnum( buffer );
pnt = get_string( pnt, &cfg->value );
break;
 
case token_define_string:
pnt = get_string( pnt, &buffer );
cfg->nameindex = get_varnum( buffer );
pnt = get_qnqstring( pnt, &cfg->value );
if (cfg->value == NULL)
syntax_error( "missing value" );
break;
 
case token_dep_bool:
case token_dep_mbool:
case token_dep_tristate:
pnt = get_qstring ( pnt, &cfg->label );
pnt = get_string ( pnt, &buffer );
cfg->nameindex = get_varnum( buffer );
 
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
 
dep_ptr = &(cfg->depend);
 
do {
*dep_ptr = (struct dependency *) malloc( sizeof( struct dependency ) );
(*dep_ptr)->next = NULL;
 
if ( ( pnt[0] == 'Y' || pnt[0] == 'M' || pnt[0] == 'N'
|| pnt[0] == 'y' || pnt[0] == 'm' || pnt[0] == 'n' )
&& ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) )
{
/* dep_tristate 'foo' CONFIG_FOO m */
if ( pnt[0] == 'Y' || pnt[0] == 'y' )
(*dep_ptr)->name = strdup( "CONSTANT_Y" );
else if ( pnt[0] == 'N' || pnt[0] == 'n' )
(*dep_ptr)->name = strdup( "CONSTANT_N" );
else
(*dep_ptr)->name = strdup( "CONSTANT_M" );
pnt++;
get_varnum( (*dep_ptr)->name );
}
else if ( *pnt == '$' )
{
pnt++;
pnt = get_string( pnt, &(*dep_ptr)->name );
get_varnum( (*dep_ptr)->name );
}
else
{
syntax_error( "can't handle dep_bool/dep_mbool/dep_tristate condition" );
}
dep_ptr = &(*dep_ptr)->next;
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
} while ( *pnt );
 
/*
* Create a conditional for this object's dependencies.
*/
{
char fake_if [1024];
struct dependency * dep;
struct condition ** cond_ptr;
int first = 1;
 
cond_ptr = &(cfg->cond);
for ( dep = cfg->depend; dep; dep = dep->next )
{
if ( token == token_dep_tristate
&& ! strcmp( dep->name, "CONSTANT_M" ) )
{
continue;
}
if ( first )
{
first = 0;
}
else
{
*cond_ptr = malloc( sizeof(struct condition) );
memset( *cond_ptr, 0, sizeof(struct condition) );
(*cond_ptr)->op = op_and;
cond_ptr = &(*cond_ptr)->next;
}
*cond_ptr = malloc( sizeof(struct condition) );
memset( *cond_ptr, 0, sizeof(struct condition) );
(*cond_ptr)->op = op_lparen;
if ( token == token_dep_bool )
sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"\" ]; then",
dep->name, dep->name );
else
sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" -o \"$%s\" = \"\" ]; then",
dep->name, dep->name, dep->name );
(*cond_ptr)->next = tokenize_if( fake_if );
while ( *cond_ptr )
cond_ptr = &(*cond_ptr)->next;
*cond_ptr = malloc( sizeof(struct condition) );
memset( *cond_ptr, 0, sizeof(struct condition) );
(*cond_ptr)->op = op_rparen;
cond_ptr = &(*cond_ptr)->next;
}
}
break;
 
case token_else:
case token_endmenu:
case token_fi:
break;
 
case token_hex:
case token_int:
pnt = get_qstring ( pnt, &cfg->label );
pnt = get_string ( pnt, &buffer );
cfg->nameindex = get_varnum( buffer );
pnt = get_string ( pnt, &cfg->value );
break;
 
case token_string:
pnt = get_qstring ( pnt, &cfg->label );
pnt = get_string ( pnt, &buffer );
cfg->nameindex = get_varnum( buffer );
pnt = get_qnqstring ( pnt, &cfg->value );
if (cfg->value == NULL)
syntax_error( "missing initial value" );
break;
 
case token_if:
cfg->cond = tokenize_if( pnt );
break;
 
case token_mainmenu_name:
pnt = get_qstring( pnt, &cfg->label );
break;
 
case token_mainmenu_option:
if ( strncmp( pnt, "next_comment", 12 ) == 0 )
last_menuoption = cfg;
else
pnt = get_qstring( pnt, &cfg->label );
break;
 
case token_unset:
pnt = get_string( pnt, &buffer );
cfg->nameindex = get_varnum( buffer );
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
while (*pnt)
{
cfg->next = (struct kconfig *) malloc( sizeof(struct kconfig) );
memset( cfg->next, 0, sizeof(struct kconfig) );
cfg = cfg->next;
cfg->token = token_unset;
pnt = get_string( pnt, &buffer );
cfg->nameindex = get_varnum( buffer );
while ( *pnt == ' ' || *pnt == '\t' )
pnt++;
}
break;
}
return;
}
 
 
 
/*
* Implement the "source" command.
*/
static void do_source( const char * filename )
{
char buffer [2048];
FILE * infile;
const char * old_file;
int old_lineno;
int offset;
 
/* open the file */
if ( strcmp( filename, "-" ) == 0 )
infile = stdin;
else
infile = fopen( filename, "r" );
 
/* if that failed, try ../filename */
if ( infile == NULL )
{
sprintf( buffer, "../%s", filename );
infile = fopen( buffer, "r" );
}
 
if ( infile == NULL )
{
sprintf( buffer, "unable to open %s", filename );
syntax_error( buffer );
}
 
/* push the new file name and line number */
old_file = current_file;
old_lineno = lineno;
current_file = filename;
lineno = 0;
 
/* read and process lines */
for ( offset = 0; ; )
{
char * pnt;
 
/* read a line */
fgets( buffer + offset, sizeof(buffer) - offset, infile );
if ( feof( infile ) )
break;
lineno++;
 
/* strip the trailing return character */
pnt = buffer + strlen(buffer) - 1;
if ( *pnt == '\n' )
*pnt-- = '\0';
 
/* eat \ NL pairs */
if ( *pnt == '\\' )
{
offset = pnt - buffer;
continue;
}
 
/* tokenize this line */
tokenize_line( buffer );
offset = 0;
}
 
/* that's all, folks */
if ( infile != stdin )
fclose( infile );
current_file = old_file;
lineno = old_lineno;
return;
}
 
 
 
/*
* Main program.
*/
int main( int argc, const char * argv [] )
{
do_source ( "-" );
fix_conditionals ( config_list );
dump_tk_script ( config_list );
free(vartable);
return 0;
}
/Menuconfig
0,0 → 1,1474
#! /bin/sh
#
# This script is used to configure the linux kernel.
#
# It was inspired by a desire to not have to hit <enter> 9 million times
# or startup the X server just to change a single kernel parameter.
#
# This script attempts to parse the configuration files, which are
# scattered throughout the kernel source tree, and creates a temporary
# set of mini scripts which are in turn used to create nested menus and
# radiolists.
#
# It uses a very modified/mutilated version of the "dialog" utility
# written by Savio Lam (lam836@cs.cuhk.hk). Savio is not responsible
# for this script or the version of dialog used by this script.
# Please do not contact him with questions. The official version of
# dialog is available at sunsite.unc.edu or a sunsite mirror.
#
# Portions of this script were borrowed from the original Configure
# script.
#
# William Roadcap was the original author of Menuconfig.
# Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
#
# 070497 Bernhard Kaindl (bkaindl@netway.at) - get default values for
# new bool, tristate and dep_tristate parameters from the defconfig file.
# new configuration parameters are marked with '(NEW)' as in make config.
#
# 180697 Bernhard Kaindl (bkaindl@netway.at) - added the needed support
# for string options. They are handled like the int and hex options.
#
# 081297 Pavel Machek (pavel@atrey.karlin.mff.cuni.cz) - better error
# handling
#
# 131197 Michael Chastain (mec@shout.net) - output all lines for a
# choice list, not just the selected one. This makes the output
# the same as Configure output, which is important for smart config
# dependencies.
#
# 101297 Michael Chastain (mec@shout.net) - remove sound driver cruft.
#
# 221297 Michael Chastain (mec@shout.net) - make define_bool actually
# define its arguments so that later tests on them work right.
#
# 160198 Michael Chastain (mec@shout.net) - fix bug with 'c' command
# (complement existing value) when used on virgin uninitialized variables.
#
# 090398 Axel Boldt (boldt@math.ucsb.edu) - allow for empty lines in help
# texts.
#
# 12 Dec 1998, Michael Elizabeth Chastain (mec@shout.net)
# Remove a /tmp security hole in get_def (also makes it faster).
# Give uninitialized variables canonical values rather than null value.
# Change a lot of places to call set_x_info uniformly.
# Take out message about preparing version (old sound driver cruft).
#
# 13 Dec 1998, Riley H Williams <Riley@Williams.Name>
# When an error occurs, actually display the error message as well as
# our comments thereon.
#
# 31 Dec 1998, Michael Elizabeth Chastain (mec@shout.net)
# Fix mod_bool to honor $CONFIG_MODULES.
# Fix dep_tristate to call define_bool when dependency is "n".
#
# 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
# Blow away lxdialog.scrltmp on entry to activate_menu. This protects
# against people who use commands like ' ' to select menus.
#
# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
# - Improve the exit message (Jeff Ronne).
#
# 06 July 1999, Andrzej M. Krzysztofowicz, <ankry@mif.pg.gda.pl>
# - Support for multiple conditions in dep_tristate().
# - Implemented new functions: define_tristate(), define_int(), define_hex(),
# define_string(), dep_bool().
#
# 12 November 2001, Keith Owens <kaos@ocs.com.au>
# Escape double quotes on eval so the quotes are still there on the second
# evaluation, required to handle strings with special characters.
#
 
 
#
# Change this to TRUE if you prefer all kernel options listed
# in a single menu rather than the standard menu hierarchy.
#
single_menu_mode=
 
#
# Make sure we're really running bash.
#
[ -z "$BASH" ] && { echo "Menuconfig requires bash" 1>&2; exit 1; }
 
#
# Cache function definitions, turn off posix compliance
#
set -h +o posix
 
 
 
# Given a configuration variable, set the global variable $x to its value,
# and the global variable $info to the string " (NEW)" if this is a new
# variable.
#
# This function looks for: (1) the current value, or (2) the default value
# from the arch-dependent defconfig file, or (3) a default passed by the caller.
 
function set_x_info () {
eval x=\$$1
if [ -z "$x" ]; then
eval `sed -n -e 's/# \(.*\) is not set.*/\1=n/' -e "/^$1=/p" arch/$ARCH/defconfig`
eval x=\${$1:-\"$2\"}
eval $1=$x
eval INFO_$1="' (NEW)'"
fi
eval info=\"\$INFO_$1\"
}
 
#
# Load the functions used by the config.in files.
#
# I do this because these functions must be redefined depending
# on whether they are being called for interactive use or for
# saving a configuration to a file.
#
# Thank the heavens bash supports nesting function definitions.
#
load_functions () {
 
#
# Additional comments
#
function comment () {
comment_ctr=$[ comment_ctr + 1 ]
echo -ne "': $comment_ctr' '--- $1' " >>MCmenu
}
 
#
# Define a boolean to a specific value.
#
function define_bool () {
eval $1=$2
}
 
function define_tristate () {
eval $1=$2
}
 
function define_hex () {
eval $1=$2
}
 
function define_int () {
eval $1=$2
}
 
function define_string () {
eval $1=\"$2\"
}
 
#
# Create a boolean (Yes/No) function for our current menu
# which calls our local bool function.
#
function bool () {
set_x_info "$2" "n"
 
case $x in
y|m) flag="*" ;;
n) flag=" " ;;
esac
 
echo -ne "'$2' '[$flag] $1$info' " >>MCmenu
 
echo -e "function $2 () { l_bool '$2' \"\$1\" ;}\n" >>MCradiolists
}
 
#
# Create a tristate (Yes/No/Module) radiolist function
# which calls our local tristate function.
#
# Collapses to a boolean (Yes/No) if module support is disabled.
#
function tristate () {
if [ "$CONFIG_MODULES" != "y" ]
then
bool "$1" "$2"
else
set_x_info "$2" "n"
case $x in
y) flag="*" ;;
m) flag="M" ;;
*) flag=" " ;;
esac
echo -ne "'$2' '<$flag> $1$info' " >>MCmenu
echo -e "
function $2 () { l_tristate '$2' \"\$1\" ;}" >>MCradiolists
fi
}
 
#
# Create a tristate radiolist function which is dependent on
# another kernel configuration option.
#
# Quote from the original configure script:
#
# If the option we depend upon is a module,
# then the only allowable options are M or N. If Y, then
# this is a normal tristate. This is used in cases where modules
# are nested, and one module requires the presence of something
# else in the kernel.
#
function dep_tristate () {
ques="$1"
var="$2"
dep=y
shift 2
while [ $# -gt 0 ]; do
if [ "$1" = y ]; then
shift
elif [ "$1" = m ]; then
dep=m
shift
else
dep=n
shift $#
fi
done
if [ "$dep" = y ]; then
tristate "$ques" "$var"
elif [ "$dep" = m ]; then
mod_bool "$ques" "$var"
else
define_tristate "$var" n
fi
}
 
#
# Same as above, but now only Y and N are allowed as dependency
# (i.e. third and next arguments).
#
function dep_bool () {
ques="$1"
var="$2"
dep=y
shift 2
while [ $# -gt 0 ]; do
if [ "$1" = y ]; then
shift
else
dep=n
shift $#
fi
done
if [ "$dep" = y ]; then
bool "$ques" "$var"
else
define_bool "$var" n
fi
}
 
function dep_mbool () {
ques="$1"
var="$2"
dep=y
shift 2
while [ $# -gt 0 ]; do
if [ "$1" = y -o "$1" = m ]; then
shift
else
dep=n
shift $#
fi
done
if [ "$dep" = y ]; then
bool "$ques" "$var"
else
define_bool "$var" n
fi
}
 
#
# Add a menu item which will call our local int function.
#
function int () {
set_x_info "$2" "$3"
 
echo -ne "'$2' '($x) $1$info' " >>MCmenu
 
echo -e "function $2 () { l_int '$1' '$2' '$3' '$x' ;}" >>MCradiolists
}
 
#
# Add a menu item which will call our local hex function.
#
function hex () {
set_x_info "$2" "$3"
x=${x##*[x,X]}
 
echo -ne "'$2' '($x) $1$info' " >>MCmenu
 
echo -e "function $2 () { l_hex '$1' '$2' '$3' '$x' ;}" >>MCradiolists
}
 
#
# Add a menu item which will call our local string function.
#
function string () {
set_x_info "$2" "$3"
 
echo -ne "'$2' ' $1: \"$x\"$info' " >>MCmenu
 
echo -e "function $2 () { l_string '$1' '$2' '$3' '$x' ;}" >>MCradiolists
}
 
#
# Add a menu item which will call our local One-of-Many choice list.
#
function choice () {
#
# Need to remember params cause they're gonna get reset.
#
title=$1
choices=$2
default=$3
current=
 
#
# Find out if one of the choices is already set.
# If it's not then make it the default.
#
set -- $choices
firstchoice=$2
 
while [ -n "$2" ]
do
if eval [ \"_\$$2\" = \"_y\" ]
then
current=$1
break
fi
shift ; shift
done
 
: ${current:=$default}
 
echo -ne "'$firstchoice' '($current) $title' " >>MCmenu
 
echo -e "
function $firstchoice () \
{ l_choice '$title' \"$choices\" \"$current\" ;}" >>MCradiolists
}
 
} # END load_functions()
 
 
 
 
 
#
# Extract available help for an option from Configure.help
# and send it to standard output.
#
# Most of this function was borrowed from the original kernel
# Configure script.
#
function extract_help () {
if [ -f Documentation/Configure.help ]
then
#first escape regexp special characters in the argument:
var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g')
#now pick out the right help text:
text=$(sed -n "/^$var[ ]*\$/,\${
/^$var[ ]*\$/c\\
${var}:\\
 
/^#/b
/^[^ ]/q
s/^ //
/<file:\\([^>]*\\)>/s//\\1/g
p
}" Documentation/Configure.help)
 
if [ -z "$text" ]
then
echo "There is no help available for this kernel option."
return 1
else
echo "$text"
fi
else
echo "There is no help available for this kernel option."
return 1
fi
}
 
#
# Activate a help dialog.
#
function help () {
if extract_help $1 >help.out
then
$DIALOG --backtitle "$backtitle" --title "$2"\
--textbox help.out $ROWS $COLS
else
$DIALOG --backtitle "$backtitle" \
--textbox help.out $ROWS $COLS
fi
rm -f help.out
}
 
#
# Show the README file.
#
function show_readme () {
$DIALOG --backtitle "$backtitle" \
--textbox scripts/README.Menuconfig $ROWS $COLS
}
 
#
# Begin building the dialog menu command and Initialize the
# Radiolist function file.
#
function menu_name () {
echo -ne "$DIALOG --title '$1'\
--backtitle '$backtitle' \
--menu '$menu_instructions' \
$ROWS $COLS $((ROWS-10)) \
'$default' " >MCmenu
>MCradiolists
}
 
#
# Add a submenu option to the menu currently under construction.
#
function submenu () {
echo -ne "'activate_menu $2' '$1 --->' " >>MCmenu
}
 
#
# Handle a boolean (Yes/No) option.
#
function l_bool () {
if [ -n "$2" ]
then
case "$2" in
y|m) eval $1=y ;;
c) eval x=\$$1
case $x in
y) eval $1=n ;;
n) eval $1=y ;;
*) eval $1=y ;;
esac ;;
*) eval $1=n ;;
esac
else
echo -ne "\007"
fi
}
 
#
# Same as bool() except options are (Module/No)
#
function mod_bool () {
if [ "$CONFIG_MODULES" != "y" ]; then
define_bool "$2" "n"
else
set_x_info "$2" "n"
case $x in
y|m) flag='M' ;;
*) flag=' ' ;;
esac
echo -ne "'$2' '<$flag> $1$info' " >>MCmenu
echo -e "function $2 () { l_mod_bool '$2' \"\$1\" ;}" >>MCradiolists
fi
}
 
#
# Same as l_bool() except options are (Module/No)
#
function l_mod_bool() {
if [ -n "$2" ]
then
case "$2" in
y) echo -en "\007"
${DIALOG} --backtitle "$backtitle" \
--infobox "\
This feature depends on another which has been configured as a module. \
As a result, this feature will be built as a module." 4 70
sleep 5
eval $1=m ;;
m) eval $1=m ;;
c) eval x=\$$1
case $x in
m) eval $1=n ;;
n) eval $1=m ;;
*) eval $1=m ;;
esac ;;
*) eval $1=n ;;
esac
else
echo -ne "\007"
fi
}
 
#
# Handle a tristate (Yes/No/Module) option.
#
function l_tristate () {
if [ -n "$2" ]
then
eval x=\$$1
 
case "$2" in
y) eval $1=y ;;
m) eval $1=m ;;
c) eval x=\$$1
case $x in
y) eval $1=n ;;
n) eval $1=m ;;
m) eval $1=y ;;
*) eval $1=y ;;
esac ;;
*) eval $1=n ;;
esac
else
echo -ne "\007"
fi
}
 
#
# Create a dialog for entering an integer into a kernel option.
#
function l_int () {
while true
do
if $DIALOG --title "$1" \
--backtitle "$backtitle" \
--inputbox "$inputbox_instructions_int" \
10 75 "$4" 2>MCdialog.out
then
answer="`cat MCdialog.out`"
answer="${answer:-$3}"
 
# Semantics of + and ? in GNU expr changed, so
# we avoid them:
if expr "$answer" : '0$' '|' "$answer" : '[1-9][0-9]*$' '|' "$answer" : '-[1-9][0-9]*$' >/dev/null
then
eval $2=\"$answer\"
else
eval $2=\"$3\"
echo -en "\007"
${DIALOG} --backtitle "$backtitle" \
--infobox "You have made an invalid entry." 3 43
sleep 2
fi
 
break
fi
 
help "$2" "$1"
done
}
 
#
# Create a dialog for entering a hexadecimal into a kernel option.
#
function l_hex () {
while true
do
if $DIALOG --title "$1" \
--backtitle "$backtitle" \
--inputbox "$inputbox_instructions_hex" \
10 75 "$4" 2>MCdialog.out
then
answer="`cat MCdialog.out`"
answer="${answer:-$3}"
answer="${answer##*[x,X]}"
 
if expr "$answer" : '[0-9a-fA-F][0-9a-fA-F]*$' >/dev/null
then
eval $2=\"$answer\"
else
eval $2=\"$3\"
echo -en "\007"
${DIALOG} --backtitle "$backtitle" \
--infobox "You have made an invalid entry." 3 43
sleep 2
fi
 
break
fi
 
help "$2" "$1"
done
}
 
#
# Create a dialog for entering a string into a kernel option.
#
function l_string () {
while true
do
if $DIALOG --title "$1" \
--backtitle "$backtitle" \
--inputbox "$inputbox_instructions_string" \
10 75 "$4" 2>MCdialog.out
then
answer="`cat MCdialog.out`"
answer="${answer:-$3}"
 
#
# Someone may add a nice check for the entered
# string here...
#
eval $2=\"$answer\"
 
break
fi
 
help "$2" "$1"
done
}
 
 
#
# Handle a one-of-many choice list.
#
function l_choice () {
#
# Need to remember params cause they're gonna get reset.
#
title="$1"
choices="$2"
current="$3"
chosen=
 
#
# Scan current value of choices and set radiolist switches.
#
list=
set -- $choices
firstchoice=$2
while [ -n "$2" ]
do
case "$1" in
"$current"*) if [ -z "$chosen" ]; then
list="$list $2 $1 ON "
chosen=1
else
list="$list $2 $1 OFF "
fi ;;
*) list="$list $2 $1 OFF " ;;
esac
shift ; shift
done
 
while true
do
if $DIALOG --title "$title" \
--backtitle "$backtitle" \
--radiolist "$radiolist_instructions" \
15 70 6 $list 2>MCdialog.out
then
choice=`cat MCdialog.out`
break
fi
 
help "$firstchoice" "$title"
done
 
#
# Now set the boolean value of each option based on
# the selection made from the radiolist.
#
set -- $choices
while [ -n "$2" ]
do
if [ "$2" = "$choice" ]
then
eval $2=\"y\"
else
eval $2=\"n\"
fi
shift ; shift
done
}
 
#
# Call awk, and watch for error codes, etc.
#
function callawk () {
awk "$1" || { echo "Awk died with error code $?. Giving up."; exit 1; }
}
 
#
# A faster awk based recursive parser. (I hope)
#
function parser1 () {
callawk '
BEGIN {
menu_no = 0
comment_is_option = 0
parser("'$CONFIG_IN'","MCmenu0")
}
 
function parser(ifile,menu) {
 
while (getline <ifile) {
if ($1 == "mainmenu_option") {
comment_is_option = "1"
}
else if ($1 == "comment" && comment_is_option == "1") {
comment_is_option= "0"
sub($1,"",$0)
++menu_no
 
printf("submenu %s MCmenu%s\n", $0, menu_no) >>menu
 
newmenu = sprintf("MCmenu%d", menu_no);
printf( "function MCmenu%s () {\n"\
"default=$1\n"\
"menu_name %s\n",\
menu_no, $0) >newmenu
 
parser(ifile, newmenu)
}
else if ($0 ~ /^#|\$MAKE|mainmenu_name/) {
printf("") >>menu
}
else if ($1 ~ "endmenu") {
printf("}\n") >>menu
return
}
else if ($1 == "source") {
parser($2,menu)
}
else {
print >>menu
}
}
}'
}
 
#
# Secondary parser for single menu mode.
#
function parser2 () {
callawk '
BEGIN {
parser("'$CONFIG_IN'","MCmenu0")
}
 
function parser(ifile,menu) {
 
while (getline <ifile) {
if ($0 ~ /^#|$MAKE|mainmenu_name/) {
printf("") >>menu
}
else if ($1 ~ /mainmenu_option|endmenu/) {
printf("") >>menu
}
else if ($1 == "source") {
parser($2,menu)
}
else {
print >>menu
}
}
}'
}
 
#
# Parse all the config.in files into mini scripts.
#
function parse_config_files () {
rm -f MCmenu*
 
echo "function MCmenu0 () {" >MCmenu0
echo 'default=$1' >>MCmenu0
echo "menu_name 'Main Menu'" >>MCmenu0
 
if [ "_$single_menu_mode" = "_TRUE" ]
then
parser2
else
parser1
fi
 
echo "comment ''" >>MCmenu0
echo "g_alt_config" >>MCmenu0
echo "s_alt_config" >>MCmenu0
 
echo "}" >>MCmenu0
 
#
# These mini scripts must be sourced into the current
# environment in order for all of this to work. Leaving
# them on the disk as executables screws up the recursion
# in activate_menu(), among other things. Once they are
# sourced we can discard them.
#
for i in MCmenu*
do
echo -n "."
source ./$i
done
rm -f MCmenu*
}
 
#
# This is the menu tree's bootstrap.
#
# Executes the parsed menus on demand and creates a set of functions,
# one per configuration option. These functions will in turn execute
# dialog commands or recursively call other menus.
#
function activate_menu () {
rm -f lxdialog.scrltmp
while true
do
comment_ctr=0 #So comment lines get unique tags
 
$1 "$default" 2> MCerror #Create the lxdialog menu & functions
 
if [ "$?" != "0" ]
then
clear
cat <<EOM
 
Menuconfig has encountered a possible error in one of the kernel's
configuration files and is unable to continue. Here is the error
report:
 
EOM
sed 's/^/ Q> /' MCerror
cat <<EOM
 
Please report this to the maintainer <mec@shout.net>. You may also
send a problem report to <linux-kernel@vger.kernel.org>.
 
Please indicate the kernel version you are trying to configure and
which menu you were trying to enter when this error occurred.
 
EOM
cleanup
exit 1
fi
rm -f MCerror
 
. ./MCradiolists #Source the menu's functions
 
. ./MCmenu 2>MCdialog.out #Activate the lxdialog menu
ret=$?
 
read selection <MCdialog.out
 
case "$ret" in
0|3|4|5|6)
defaults="$selection$defaults" #pseudo stack
case "$ret" in
0) eval $selection ;;
3) eval $selection y ;;
4) eval $selection n ;;
5) eval $selection m ;;
6) eval $selection c ;;
esac
default="${defaults%%*}" defaults="${defaults#*}"
;;
2)
default="${selection%%\ *}"
 
case "$selection" in
*"-->"*|*"alt_config"*)
show_readme ;;
*)
eval help $selection ;;
esac
;;
255|1)
break
;;
139)
stty sane
clear
cat <<EOM
 
There seems to be a problem with the lxdialog companion utility which is
built prior to running Menuconfig. Usually this is an indicator that you
have upgraded/downgraded your ncurses libraries and did not remove the
old ncurses header file(s) in /usr/include or /usr/include/ncurses.
 
It is VERY important that you have only one set of ncurses header files
and that those files are properly version matched to the ncurses libraries
installed on your machine.
 
You may also need to rebuild lxdialog. This can be done by moving to
the /usr/src/linux/scripts/lxdialog directory and issuing the
"make clean all" command.
 
If you have verified that your ncurses install is correct, you may email
the maintainer <mec@shout.net> or post a message to
<linux-kernel@vger.kernel.org> for additional assistance.
 
EOM
cleanup
exit 139
;;
esac
done
}
 
#
# Create a menu item to load an alternate configuration file.
#
g_alt_config () {
echo -n "get_alt_config 'Load an Alternate Configuration File' "\
>>MCmenu
}
 
#
# Get alternate config file name and load the
# configuration from it.
#
get_alt_config () {
set -f ## Switch file expansion OFF
 
while true
do
ALT_CONFIG="${ALT_CONFIG:-$DEFAULTS}"
 
$DIALOG --backtitle "$backtitle" \
--inputbox "\
Enter the name of the configuration file you wish to load. \
Accept the name shown to restore the configuration you \
last retrieved. Leave blank to abort."\
11 55 "$ALT_CONFIG" 2>MCdialog.out
 
if [ "$?" = "0" ]
then
ALT_CONFIG=`cat MCdialog.out`
 
[ "_" = "_$ALT_CONFIG" ] && break
 
if eval [ -r \"$ALT_CONFIG\" ]
then
eval load_config_file \"$ALT_CONFIG\"
break
else
echo -ne "\007"
$DIALOG --backtitle "$backtitle" \
--infobox "File does not exist!" 3 38
sleep 2
fi
else
cat <<EOM >help.out
 
For various reasons, one may wish to keep several different kernel
configurations available on a single machine.
 
If you have saved a previous configuration in a file other than the
kernel's default, entering the name of the file here will allow you
to modify that configuration.
 
If you are uncertain, then you have probably never used alternate
configuration files. You should therefor leave this blank to abort.
 
EOM
$DIALOG --backtitle "$backtitle"\
--title "Load Alternate Configuration"\
--textbox help.out $ROWS $COLS
fi
done
 
set +f ## Switch file expansion ON
rm -f help.out MCdialog.out
}
 
#
# Create a menu item to store an alternate config file.
#
s_alt_config () {
echo -n "save_alt_config 'Save Configuration to an Alternate File' "\
>>MCmenu
}
 
#
# Get an alternate config file name and save the current
# configuration to it.
#
save_alt_config () {
set -f ## Switch file expansion OFF
while true
do
$DIALOG --backtitle "$backtitle" \
--inputbox "\
Enter a filename to which this configuration should be saved \
as an alternate. Leave blank to abort."\
10 55 "$ALT_CONFIG" 2>MCdialog.out
 
if [ "$?" = "0" ]
then
ALT_CONFIG=`cat MCdialog.out`
 
[ "_" = "_$ALT_CONFIG" ] && break
 
if eval touch $ALT_CONFIG 2>/dev/null
then
eval save_configuration $ALT_CONFIG
load_functions ## RELOAD
break
else
echo -ne "\007"
$DIALOG --backtitle "$backtitle" \
--infobox "Can't create file! Probably a nonexistent directory." 3 60
sleep 2
fi
else
cat <<EOM >help.out
 
For various reasons, one may wish to keep different kernel
configurations available on a single machine.
 
Entering a file name here will allow you to later retrieve, modify
and use the current configuration as an alternate to whatever
configuration options you have selected at that time.
 
If you are uncertain what all this means then you should probably
leave this blank.
EOM
$DIALOG --backtitle "$backtitle"\
--title "Save Alternate Configuration"\
--textbox help.out $ROWS $COLS
fi
done
 
set +f ## Switch file expansion ON
rm -f help.out MCdialog.out
}
 
#
# Load config options from a file.
# Converts all "# OPTION is not set" lines to "OPTION=n" lines
#
function load_config_file () {
awk '
/# .* is not set.*/ { printf("%s=n\n", $2) }
! /# .* is not set.*/ { print }
' $1 >.tmpconfig
 
source ./.tmpconfig
rm -f .tmpconfig
}
 
#
# Just what it says.
#
save_configuration () {
echo
echo -n "Saving your kernel configuration."
 
#
# Now, let's redefine the configuration functions for final
# output to the config files.
#
# Nested function definitions, YIPEE!
#
function bool () {
set_x_info "$2" "n"
eval define_bool \"$2\" \"$x\"
}
 
function tristate () {
set_x_info "$2" "n"
eval define_tristate \"$2\" \"$x\"
}
 
function dep_tristate () {
set_x_info "$2" "n"
var="$2"
shift 2
while [ $# -gt 0 ]; do
if [ "$1" = y ]; then
shift
elif [ "$1" = m -a "$x" != n ]; then
x=m; shift
else
x=n; shift $#
fi
done
define_tristate "$var" "$x"
}
 
function dep_bool () {
set_x_info "$2" "n"
var="$2"
shift 2
while [ $# -gt 0 ]; do
if [ "$1" = y ]; then
shift
else
x=n; shift $#
fi
done
define_bool "$var" "$x"
}
 
function dep_mbool () {
set_x_info "$2" "n"
var="$2"
shift 2
while [ $# -gt 0 ]; do
if [ "$1" = y -o "$1" = m ]; then
shift
else
x=n; shift $#
fi
done
define_bool "$var" "$x"
}
 
function int () {
set_x_info "$2" "$3"
echo "$2=$x" >>$CONFIG
echo "#define $2 ($x)" >>$CONFIG_H
}
 
function hex () {
set_x_info "$2" "$3"
echo "$2=$x" >>$CONFIG
echo "#define $2 0x${x##*[x,X]}" >>$CONFIG_H
}
 
function string () {
set_x_info "$2" "$3"
echo "$2=\"$x\"" >>$CONFIG
echo "#define $2 \"$x\"" >>$CONFIG_H
}
 
function define_hex () {
eval $1=\"$2\"
echo "$1=$2" >>$CONFIG
echo "#define $1 0x${2##*[x,X]}" >>$CONFIG_H
}
 
function define_int () {
eval $1=\"$2\"
echo "$1=$2" >>$CONFIG
echo "#define $1 ($2)" >>$CONFIG_H
}
 
function define_string () {
eval $1=\"$2\"
echo "$1=\"$2\"" >>$CONFIG
echo "#define $1 \"$2\"" >>$CONFIG_H
}
 
function define_bool () {
define_tristate "$1" "$2"
}
 
function define_tristate () {
eval $1=\"$2\"
 
case "$2" in
y)
echo "$1=y" >>$CONFIG
echo "#define $1 1" >>$CONFIG_H
;;
 
m)
if [ "$CONFIG_MODULES" = "y" ]
then
echo "$1=m" >>$CONFIG
echo "#undef $1" >>$CONFIG_H
echo "#define $1_MODULE 1" >>$CONFIG_H
else
echo "$1=y" >>$CONFIG
echo "#define $1 1" >>$CONFIG_H
fi
;;
 
n)
echo "# $1 is not set" >>$CONFIG
echo "#undef $1" >>$CONFIG_H
;;
esac
}
 
function choice () {
#
# Find the first choice that's already set to 'y'
#
choices="$2"
default="$3"
current=
chosen=
 
set -- $choices
while [ -n "$2" ]
do
if eval [ \"_\$$2\" = \"_y\" ]
then
current=$1
break
fi
shift ; shift
done
 
#
# Use the default if none were set.
#
: ${current:=$default}
 
#
# Output all choices (to be compatible with other configs).
#
set -- $choices
while [ -n "$2" ]
do
case "$1" in
"$current"*) if [ -z "$chosen" ]; then
define_bool "$2" "y"
chosen=1
else
define_bool "$2" "n"
fi ;;
*) define_bool "$2" "n" ;;
esac
shift ; shift
done
}
 
function mainmenu_name () {
:
}
 
function mainmenu_option () {
comment_is_option=TRUE
}
 
function endmenu () {
:
}
 
function comment () {
if [ "$comment_is_option" ]
then
comment_is_option=
echo >>$CONFIG
echo "#" >>$CONFIG
echo "# $1" >>$CONFIG
echo "#" >>$CONFIG
 
echo >>$CONFIG_H
echo "/*" >>$CONFIG_H
echo " * $1" >>$CONFIG_H
echo " */" >>$CONFIG_H
fi
}
 
echo -n "."
 
DEF_CONFIG="${1:-.config}"
DEF_CONFIG_H="include/linux/autoconf.h"
 
CONFIG=.tmpconfig
CONFIG_H=.tmpconfig.h
 
echo "#" >$CONFIG
echo "# Automatically generated by make menuconfig: don't edit" >>$CONFIG
echo "#" >>$CONFIG
 
echo "/*" >$CONFIG_H
echo " * Automatically generated by make menuconfig: don't edit" >>$CONFIG_H
echo " */" >>$CONFIG_H
echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H
 
echo -n "."
if . $CONFIG_IN >>.menuconfig.log 2>&1
then
if [ "$DEF_CONFIG" = ".config" ]
then
mv $CONFIG_H $DEF_CONFIG_H
fi
 
if [ -f "$DEF_CONFIG" ]
then
rm -f ${DEF_CONFIG}.old
mv $DEF_CONFIG ${DEF_CONFIG}.old
fi
 
mv $CONFIG $DEF_CONFIG
return 0
else
return 1
fi
}
 
#
# Remove temporary files
#
cleanup () {
cleanup1
cleanup2
}
 
cleanup1 () {
rm -f MCmenu* MCradiolists MCdialog.out help.out
}
 
cleanup2 () {
rm -f .tmpconfig .tmpconfig.h
}
 
set_geometry () {
# Some distributions export these with incorrect values
# which can really screw up some ncurses programs.
LINES= COLUMNS=
 
ROWS=${1:-24} COLS=${2:-80}
 
# Just in case the nasty rlogin bug returns.
#
[ $ROWS = 0 ] && ROWS=24
[ $COLS = 0 ] && COLS=80
 
if [ $ROWS -lt 19 -o $COLS -lt 80 ]
then
echo -e "\n\007Your display is too small to run Menuconfig!"
echo "It must be at least 19 lines by 80 columns."
exit 1
fi
 
ROWS=$((ROWS-4)) COLS=$((COLS-5))
}
 
 
set_geometry `stty size 2>/dev/null`
 
menu_instructions="\
Arrow keys navigate the menu. \
<Enter> selects submenus --->. \
Highlighted letters are hotkeys. \
Pressing <Y> includes, <N> excludes, <M> modularizes features. \
Press <Esc><Esc> to exit, <?> for Help. \
Legend: [*] built-in [ ] excluded <M> module < > module capable"
 
radiolist_instructions="\
Use the arrow keys to navigate this window or \
press the hotkey of the item you wish to select \
followed by the <SPACE BAR>.
Press <?> for additional information about this option."
 
inputbox_instructions_int="\
Please enter a decimal value. \
Fractions will not be accepted. \
Use the <TAB> key to move from the input field to the buttons below it."
 
inputbox_instructions_hex="\
Please enter a hexadecimal value. \
Use the <TAB> key to move from the input field to the buttons below it."
 
inputbox_instructions_string="\
Please enter a string value. \
Use the <TAB> key to move from the input field to the buttons below it."
 
DIALOG="./scripts/lxdialog/lxdialog"
 
kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
 
backtitle="Linux Kernel v$kernel_version Configuration"
 
trap "cleanup ; exit 1" 1 2 15
 
 
#
# Locate default files.
#
CONFIG_IN=./config.in
if [ "$1" != "" ] ; then
CONFIG_IN=$1
fi
 
DEFAULTS=arch/$ARCH/defconfig
if [ -f .config ]; then
DEFAULTS=.config
fi
 
if [ -f $DEFAULTS ]
then
echo "Using defaults found in" $DEFAULTS
load_config_file $DEFAULTS
else
echo "No defaults found"
fi
 
 
# Fresh new log.
>.menuconfig.log
 
# Load the functions used by the config.in files.
echo -n "Preparing scripts: functions"
load_functions
 
if [ ! -e $CONFIG_IN ]
then
echo "Your main config.in file ($CONFIG_IN) does not exist"
exit 1
fi
 
if [ ! -x $DIALOG ]
then
echo "Your lxdialog utility does not exist"
exit 1
fi
 
#
# Read config.in files and parse them into one shell function per menu.
#
echo -n ", parsing"
parse_config_files $CONFIG_IN
 
echo "done."
#
# Start the ball rolling from the top.
#
activate_menu MCmenu0
 
#
# All done!
#
cleanup1
 
#
# Confirm and Save
#
if $DIALOG --backtitle "$backtitle" \
--yesno "Do you wish to save your new kernel configuration?" 5 60
then
save_configuration
echo
echo
echo "*** End of Linux kernel configuration."
echo "*** Check the top-level Makefile for additional configuration."
if [ ! -f .hdepend -o "$CONFIG_MODVERSIONS" = "y" ] ; then
echo "*** Next, you must run 'make dep'."
else
echo "*** Next, you may run 'make bzImage', 'make bzdisk', or 'make install'."
fi
echo
else
echo
echo
echo Your kernel configuration changes were NOT saved.
echo
fi
 
# Remove log if empty.
if [ ! -s .menuconfig.log ] ; then
rm -f .menuconfig.log
fi
 
exit 0
/Lindent
0,0 → 1,2
#!/bin/sh
indent -kr -i8 -ts8 -sob -l80 -ss -bs -psl "$@"
/tkparse.h
0,0 → 1,127
/*
* tkparse.h
*/
 
/*
* Token types (mostly statement types).
*/
 
enum e_token
{
token_UNKNOWN,
token_bool,
token_choice_header,
token_choice_item,
token_comment,
token_define_bool,
token_define_hex,
token_define_int,
token_define_string,
token_define_tristate,
token_dep_bool,
token_dep_mbool,
token_dep_tristate,
token_else,
token_endmenu,
token_fi,
token_hex,
token_if,
token_int,
token_mainmenu_name,
token_mainmenu_option,
token_source,
token_string,
token_then,
token_tristate,
token_unset,
};
 
/*
* Operator types for conditionals.
*/
 
enum operator
{
op_eq,
op_neq,
op_and,
op_and1,
op_or,
op_bang,
op_lparen,
op_rparen,
op_constant,
op_variable,
op_true,
op_false,
op_nuked
};
 
/*
* Conditions come in linked lists.
* Some operators take strings:
*
* op_constant "foo"
* op_variable "$ARCH", "$CONFIG_PMAC", "$CONFIG_EXPERIMENTAL"
*
* Most "$..." constructs refer to a variable which is defined somewhere
* in the script. Note that it is legal to test variables which are never
* defined, such as variables that are meaningful only on other architectures.
*/
 
struct condition
{
struct condition * next;
enum operator op;
const char * str; /* op_constant */
int nameindex; /* op_variable */
};
 
/*
* Dependency list for dep_bool, dep_mbool, dep_tristate
*/
 
struct dependency
{
char * name;
struct dependency * next;
};
 
/*
* A statement from a config.in file
*/
 
struct kconfig
{
struct kconfig * next;
enum e_token token;
int nameindex;
char * label;
char * value;
struct condition * cond;
struct dependency * depend; /* token_dep_tristate */
struct kconfig * cfg_parent; /* token_choice_item */
 
/* used only in tkgen.c */
int menu_number;
int menu_line;
struct kconfig * menu_next;
};
 
struct variable
{
char * name;
char defined;
char global_written;
};
 
extern struct variable *vartable;
extern int max_varnum;
 
/*
* Prototypes
*/
 
extern void fix_conditionals ( struct kconfig * scfg ); /* tkcond.c */
extern void dump_tk_script ( struct kconfig * scfg ); /* tkgen.c */
extern int get_varnum ( char * name ); /* tkparse.c */
/docgen
0,0 → 1,10
#!/bin/sh
set -e
if [ -z "$scripts_objtree" ]
then
X=`$TOPDIR/scripts/gen-all-syms "$*"`
$TOPDIR/scripts/docproc $X
else
X=`${scripts_objtree}gen-all-syms "$*"`
TOPDIR=. ${scripts_objtree}docproc $X
fi
/checkhelp.pl
0,0 → 1,30
#!/usr/bin/perl
# checkhelp.pl - finds configuration options that have no
# corresponding section in the help file
#
# made by Meelis Roos (mroos@tartu.cyber.ee)
 
# read the help file
@options=split /\n/, `grep '^CONFIG' Documentation/Configure.help`;
die "Can't read Documentation/Configure.help\n" if $#options == -1;
 
#read all the files
foreach $file (@ARGV)
{
open (FILE, $file) || die "Can't open $file: $!\n";
while (<FILE>) {
# repeat until no CONFIG_* are left
while (/^\s*(bool|tristate|dep_tristate|string|int|hex).*' *(.*)'.*(CONFIG_\w*)/) {
$what=$3;
$name=$2;
s/$3//;
@found = grep (/$what$/, @options);
if ($#found == -1) {
next if $nohelp{$what};
print "$name\n$what\n No help for $what\n\n";
$nohelp{$what}=1;
}
}
}
close (FILE);
}
/mkconfigs.c
0,0 → 1,181
/***************************************************************************
* mkconfigs.c
* (C) 2002 Randy Dunlap <rddunlap@osdl.org>
 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
# Rules for scripts/mkconfigs.c input.config output.c
# to generate configs.c from linux/.config:
# - drop lines that begin with '#'
# - drop blank lines
# - lines that use double-quotes must \\-escape-quote them
 
################## skeleton configs.c file: ####################
 
#include <linux/init.h>
#include <linux/module.h>
 
static char *configs[] __initdata =
 
<insert lines selected lines of .config, quoted, with added '\n'>,
 
;
 
################### end configs.c file ######################
 
* Changelog for ver. 0.2, 2002-02-15, rddunlap@osdl.org:
- strip leading "CONFIG_" from config option strings;
- use "static" and "__attribute__((unused))";
- don't use EXPORT_SYMBOL();
- separate each config line with \newline instead of space;
 
* Changelog for ver. 0.3, 2002-02-18, rddunlap@osdl.org:
- keep all "not set" comment lines from .config so that 'make *config'
will be happy, but don't keep other comments;
- keep leading "CONFIG_" on each line;
 
****************************************************************/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
 
#define VERSION "0.2"
#define LINE_SIZE 1000
 
int include_all_lines = 1; // whether to include "=n" lines in the output
 
void usage (const char *progname)
{
fprintf (stderr, "%s ver. %s\n", progname, VERSION);
fprintf (stderr, "usage: %s input.config.name path/configs.c\n",
progname);
exit (1);
}
 
void make_intro (FILE *sourcefile)
{
fprintf (sourcefile, "#include <linux/init.h>\n");
///// fprintf (sourcefile, "#include <linux/module.h>\n");
fprintf (sourcefile, "\n");
///// fprintf (sourcefile, "char *configs[] __initdata = {\n");
fprintf (sourcefile, "static char __attribute__ ((unused)) *configs[] __initdata = {\n");
fprintf (sourcefile, " \"CONFIG_BEGIN=n\\n\" ,\n");
}
 
void make_ending (FILE *sourcefile)
{
fprintf (sourcefile, " \"CONFIG_END=n\\n\"\n");
fprintf (sourcefile, "};\n");
///// fprintf (sourcefile, "EXPORT_SYMBOL (configs);\n");
}
 
void make_lines (FILE *configfile, FILE *sourcefile)
{
char cfgline[LINE_SIZE];
char *ch;
 
while (fgets (cfgline, LINE_SIZE, configfile)) {
/* kill the trailing newline in cfgline */
cfgline[strlen (cfgline) - 1] = '\0';
 
/* don't keep #-only line or an empty/blank line */
if ((cfgline[0] == '#' && cfgline[1] == '\0') ||
cfgline[0] == '\0')
continue;
 
if (!include_all_lines &&
cfgline[0] == '#') // strip out all comment lines
continue;
 
/* really only want to keep lines that begin with
* "CONFIG_" or "# CONFIG_" */
if (strncmp (cfgline, "CONFIG_", 7) &&
strncmp (cfgline, "# CONFIG_", 9))
continue;
 
/*
* use strchr() to check for "-quote in cfgline;
* if not found, output the line, quoted;
* if found, output a char at a time, with \\-quote
* preceding double-quote chars
*/
if (!strchr (cfgline, '"')) {
fprintf (sourcefile, " \"%s\\n\" ,\n", cfgline);
continue;
}
 
/* go to char-at-a-time mode for this config and
* precede any double-quote with a backslash */
fprintf (sourcefile, " \""); /* lead-in */
for (ch = cfgline; *ch; ch++) {
if (*ch == '"')
fputc ('\\', sourcefile);
fputc (*ch, sourcefile);
}
fprintf (sourcefile, "\\n\" ,\n");
}
}
 
void make_configs (FILE *configfile, FILE *sourcefile)
{
make_intro (sourcefile);
make_lines (configfile, sourcefile);
make_ending (sourcefile);
}
 
int main (int argc, char *argv[])
{
char *progname = argv[0];
char *configname, *sourcename;
FILE *configfile, *sourcefile;
 
if (argc != 3)
usage (progname);
 
configname = argv[1];
sourcename = argv[2];
 
configfile = fopen (configname, "r");
if (!configfile) {
fprintf (stderr, "%s: cannot open '%s'\n",
progname, configname);
exit (2);
}
sourcefile = fopen (sourcename, "w");
if (!sourcefile) {
fprintf (stderr, "%s: cannot open '%s'\n",
progname, sourcename);
exit (2);
}
 
make_configs (configfile, sourcefile);
 
if (fclose (sourcefile)) {
fprintf (stderr, "%s: error %d closing '%s'\n",
progname, errno, sourcename);
exit (3);
}
if (fclose (configfile)) {
fprintf (stderr, "%s: error %d closing '%s'\n",
progname, errno, configname);
exit (3);
}
 
exit (0);
}
 
/* end mkconfigs.c */
/tkcond.c
0,0 → 1,602
/*
* tkcond.c
*
* Eric Youngdale was the original author of xconfig.
* Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
*
* This file takes the tokenized statement list and transforms 'if ...'
* statements. For each simple statement, I find all of the 'if' statements
* that enclose it, and attach the aggregate conditionals of those 'if'
* statements to the cond list of the simple statement.
*
* 14 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
* - Steam-clean this file. I tested this by generating kconfig.tk for
* every architecture and comparing it character-for-character against
* the output of the old tkparse.
*
* 07 July 1999, Andrzej M. Krzysztofowicz <ankry@mif.pg.gda.pl>
* - kvariables removed; all variables are stored in a single table now
* - some elimination of options non-valid for current architecture
* implemented.
* - negation (!) eliminated from conditions
*
* TO DO:
* - xconfig is at the end of its life cycle. Contact <mec@shout.net> if
* you are interested in working on the replacement.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "tkparse.h"
 
 
 
/*
* Mark variables which are defined anywhere.
*/
static void mark_variables( struct kconfig * scfg )
{
struct kconfig * cfg;
int i;
 
for ( i = 1; i <= max_varnum; i++ )
vartable[i].defined = 0;
for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
{
if ( cfg->token == token_bool
|| cfg->token == token_choice_item
|| cfg->token == token_define_bool
|| cfg->token == token_define_hex
|| cfg->token == token_define_int
|| cfg->token == token_define_string
|| cfg->token == token_define_tristate
|| cfg->token == token_dep_bool
|| cfg->token == token_dep_mbool
|| cfg->token == token_dep_tristate
|| cfg->token == token_hex
|| cfg->token == token_int
|| cfg->token == token_string
|| cfg->token == token_tristate
|| cfg->token == token_unset )
{
if ( cfg->nameindex > 0 ) /* paranoid */
{
vartable[cfg->nameindex].defined = 1;
}
}
}
}
 
 
 
static void free_cond( struct condition *cond )
{
struct condition *tmp, *tmp1;
for ( tmp = cond; tmp; tmp = tmp1 )
{
tmp1 = tmp->next;
free( (void*)tmp );
}
}
 
 
 
/*
* Remove the bang operator from a condition to avoid priority problems.
* "!" has different priorities as "test" command argument and in
* a tk script.
*/
static struct condition * remove_bang( struct condition * condition )
{
struct condition * conda, * condb, * prev = NULL;
 
for ( conda = condition; conda; conda = conda->next )
{
if ( conda->op == op_bang && conda->next &&
( condb = conda->next->next ) )
{
if ( condb->op == op_eq || condb->op == op_neq )
{
condb->op = (condb->op == op_eq) ? op_neq : op_eq;
conda->op = op_nuked;
if ( prev )
{
prev->next = conda->next;
}
else
{
condition = conda->next;
}
conda->next = NULL;
free_cond( conda );
conda = condb;
}
}
prev = conda;
}
return condition;
}
 
 
 
/*
* Make a new condition chain by joining the current condition stack with
* the "&&" operator for glue.
*/
static struct condition * join_condition_stack( struct condition * conditions [],
int depth )
{
struct condition * cond_list;
struct condition * cond_last;
int i, is_first = 1;
 
cond_list = cond_last = NULL;
 
for ( i = 0; i < depth; i++ )
{
if ( conditions[i]->op == op_false )
{
struct condition * cnew;
 
/* It is always false condition */
cnew = malloc( sizeof(*cnew) );
memset( cnew, 0, sizeof(*cnew) );
cnew->op = op_false;
cond_list = cond_last = cnew;
goto join_done;
}
}
for ( i = 0; i < depth; i++ )
{
struct condition * cond;
struct condition * cnew;
int add_paren;
 
/* omit always true conditions */
if ( conditions[i]->op == op_true )
continue;
 
/* if i have another condition, add an '&&' operator */
if ( !is_first )
{
cnew = malloc( sizeof(*cnew) );
memset( cnew, 0, sizeof(*cnew) );
cnew->op = op_and;
cond_last->next = cnew;
cond_last = cnew;
}
 
if ( conditions[i]->op != op_lparen )
{
/* add a '(' */
add_paren = 1;
cnew = malloc( sizeof(*cnew) );
memset( cnew, 0, sizeof(*cnew) );
cnew->op = op_lparen;
if ( cond_last == NULL )
{ cond_list = cond_last = cnew; }
else
{ cond_last->next = cnew; cond_last = cnew; }
}
else
{
add_paren = 0;
}
 
/* duplicate the chain */
for ( cond = conditions [i]; cond != NULL; cond = cond->next )
{
cnew = malloc( sizeof(*cnew) );
cnew->next = NULL;
cnew->op = cond->op;
cnew->str = cond->str ? strdup( cond->str ) : NULL;
cnew->nameindex = cond->nameindex;
if ( cond_last == NULL )
{ cond_list = cond_last = cnew; }
else
{ cond_last->next = cnew; cond_last = cnew; }
}
 
if ( add_paren )
{
/* add a ')' */
cnew = malloc( sizeof(*cnew) );
memset( cnew, 0, sizeof(*cnew) );
cnew->op = op_rparen;
cond_last->next = cnew;
cond_last = cnew;
}
is_first = 0;
}
 
/*
* Remove duplicate conditions.
*/
{
struct condition *cond1, *cond1b, *cond1c, *cond1d, *cond1e, *cond1f;
 
for ( cond1 = cond_list; cond1 != NULL; cond1 = cond1->next )
{
if ( cond1->op == op_lparen )
{
cond1b = cond1 ->next; if ( cond1b == NULL ) break;
cond1c = cond1b->next; if ( cond1c == NULL ) break;
cond1d = cond1c->next; if ( cond1d == NULL ) break;
cond1e = cond1d->next; if ( cond1e == NULL ) break;
cond1f = cond1e->next; if ( cond1f == NULL ) break;
 
if ( cond1b->op == op_variable
&& ( cond1c->op == op_eq || cond1c->op == op_neq )
&& cond1d->op == op_constant
&& cond1e->op == op_rparen )
{
struct condition *cond2, *cond2b, *cond2c, *cond2d, *cond2e, *cond2f;
 
for ( cond2 = cond1f->next; cond2 != NULL; cond2 = cond2->next )
{
if ( cond2->op == op_lparen )
{
cond2b = cond2 ->next; if ( cond2b == NULL ) break;
cond2c = cond2b->next; if ( cond2c == NULL ) break;
cond2d = cond2c->next; if ( cond2d == NULL ) break;
cond2e = cond2d->next; if ( cond2e == NULL ) break;
cond2f = cond2e->next;
 
/* look for match */
if ( cond2b->op == op_variable
&& cond2b->nameindex == cond1b->nameindex
&& cond2c->op == cond1c->op
&& cond2d->op == op_constant
&& strcmp( cond2d->str, cond1d->str ) == 0
&& cond2e->op == op_rparen )
{
/* one of these must be followed by && */
if ( cond1f->op == op_and
|| ( cond2f != NULL && cond2f->op == op_and ) )
{
/* nuke the first duplicate */
cond1 ->op = op_nuked;
cond1b->op = op_nuked;
cond1c->op = op_nuked;
cond1d->op = op_nuked;
cond1e->op = op_nuked;
if ( cond1f->op == op_and )
cond1f->op = op_nuked;
else
cond2f->op = op_nuked;
}
}
}
}
}
}
}
}
 
join_done:
return cond_list;
}
 
 
 
static char * current_arch = NULL;
 
/*
* Eliminating conditions with ARCH = <not current>.
*/
static struct condition *eliminate_other_arch( struct condition *list )
{
struct condition *cond1a = list, *cond1b = NULL, *cond1c = NULL, *cond1d = NULL;
if ( current_arch == NULL )
current_arch = getenv( "ARCH" );
if ( current_arch == NULL )
{
fprintf( stderr, "error: ARCH undefined\n" );
exit( 1 );
}
if ( cond1a->op == op_variable
&& ! strcmp( vartable[cond1a->nameindex].name, "ARCH" ) )
{
cond1b = cond1a->next; if ( cond1b == NULL ) goto done;
cond1c = cond1b->next; if ( cond1c == NULL ) goto done;
cond1d = cond1c->next;
if ( cond1c->op == op_constant && cond1d == NULL )
{
if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
|| (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
{
/* This is for another architecture */
cond1a->op = op_false;
cond1a->next = NULL;
free_cond( cond1b );
return cond1a;
}
else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
|| (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
{
/* This is for current architecture */
cond1a->op = op_true;
cond1a->next = NULL;
free_cond( cond1b );
return cond1a;
}
}
else if ( cond1c->op == op_constant && cond1d->op == op_or )
{
if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
|| (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
{
/* This is for another architecture */
cond1b = cond1d->next;
cond1d->next = NULL;
free_cond( cond1a );
return eliminate_other_arch( cond1b );
}
else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
|| (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
{
/* This is for current architecture */
cond1a->op = op_true;
cond1a->next = NULL;
free_cond( cond1b );
return cond1a;
}
}
else if ( cond1c->op == op_constant && cond1d->op == op_and )
{
if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
|| (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
{
/* This is for another architecture */
int l_par = 0;
for ( cond1c = cond1d->next; cond1c; cond1c = cond1c->next )
{
if ( cond1c->op == op_lparen )
l_par++;
else if ( cond1c->op == op_rparen )
l_par--;
else if ( cond1c->op == op_or && l_par == 0 )
/* Expression too complex - don't touch */
return cond1a;
else if ( l_par < 0 )
{
fprintf( stderr, "incorrect condition: programming error ?\n" );
exit( 1 );
}
}
cond1a->op = op_false;
cond1a->next = NULL;
free_cond( cond1b );
return cond1a;
}
else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
|| (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
{
/* This is for current architecture */
cond1b = cond1d->next;
cond1d->next = NULL;
free_cond( cond1a );
return eliminate_other_arch( cond1b );
}
}
}
if ( cond1a->op == op_variable && ! vartable[cond1a->nameindex].defined )
{
cond1b = cond1a->next; if ( cond1b == NULL ) goto done;
cond1c = cond1b->next; if ( cond1c == NULL ) goto done;
cond1d = cond1c->next;
 
if ( cond1c->op == op_constant
&& ( cond1d == NULL || cond1d->op == op_and ) ) /*???*/
{
if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )
{
cond1a->op = op_false;
cond1a->next = NULL;
free_cond( cond1b );
return cond1a;
}
}
else if ( cond1c->op == op_constant && cond1d->op == op_or )
{
if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )
{
cond1b = cond1d->next;
cond1d->next = NULL;
free_cond( cond1a );
return eliminate_other_arch( cond1b );
}
}
}
done:
return list;
}
 
 
 
/*
* This is the main transformation function.
*/
void fix_conditionals( struct kconfig * scfg )
{
struct kconfig * cfg;
 
/*
* Transform op_variable to op_kvariable.
*/
mark_variables( scfg );
 
/*
* Walk the statement list, maintaining a stack of current conditions.
* token_if push its condition onto the stack.
* token_else invert the condition on the top of the stack.
* token_endif pop the stack.
*
* For a simple statement, create a condition chain by joining together
* all of the conditions on the stack.
*/
{
struct condition * cond_stack [32];
int depth = 0;
struct kconfig * prev = NULL;
 
for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
{
int good = 1;
switch ( cfg->token )
{
default:
break;
 
case token_if:
cond_stack [depth++] =
remove_bang( eliminate_other_arch( cfg->cond ) );
cfg->cond = NULL;
break;
 
case token_else:
{
/*
* Invert the condition chain.
*
* Be careful to transfrom op_or to op_and1, not op_and.
* I will need this later in the code that removes
* duplicate conditions.
*/
struct condition * cond;
 
for ( cond = cond_stack [depth-1];
cond != NULL;
cond = cond->next )
{
switch( cond->op )
{
default: break;
case op_and: cond->op = op_or; break;
case op_or: cond->op = op_and1; break;
case op_neq: cond->op = op_eq; break;
case op_eq: cond->op = op_neq; break;
case op_true: cond->op = op_false;break;
case op_false:cond->op = op_true; break;
}
}
}
break;
 
case token_fi:
--depth;
break;
 
case token_bool:
case token_choice_item:
case token_choice_header:
case token_comment:
case token_define_bool:
case token_define_hex:
case token_define_int:
case token_define_string:
case token_define_tristate:
case token_endmenu:
case token_hex:
case token_int:
case token_mainmenu_option:
case token_string:
case token_tristate:
case token_unset:
cfg->cond = join_condition_stack( cond_stack, depth );
if ( cfg->cond && cfg->cond->op == op_false )
{
good = 0;
if ( prev )
prev->next = cfg->next;
else
scfg = cfg->next;
}
break;
 
case token_dep_bool:
case token_dep_mbool:
case token_dep_tristate:
/*
* Same as the other simple statements, plus an additional
* condition for the dependency.
*/
if ( cfg->cond )
{
cond_stack [depth] = eliminate_other_arch( cfg->cond );
cfg->cond = join_condition_stack( cond_stack, depth+1 );
}
else
{
cfg->cond = join_condition_stack( cond_stack, depth );
}
if ( cfg->cond && cfg->cond->op == op_false )
{
good = 0;
if ( prev )
prev->next = cfg->next;
else
scfg = cfg->next;
}
break;
}
if ( good )
prev = cfg;
}
}
}
 
 
 
#if 0
void dump_condition( struct condition *list )
{
struct condition *tmp;
for ( tmp = list; tmp; tmp = tmp->next )
{
switch (tmp->op)
{
default:
break;
case op_variable:
printf( " %s", vartable[tmp->nameindex].name );
break;
case op_constant:
printf( " %s", tmp->str );
break;
case op_eq:
printf( " =" );
break;
case op_bang:
printf( " !" );
break;
case op_neq:
printf( " !=" );
break;
case op_and:
case op_and1:
printf( " -a" );
break;
case op_or:
printf( " -o" );
break;
case op_true:
printf( " TRUE" );
break;
case op_false:
printf( " FALSE" );
break;
case op_lparen:
printf( " (" );
break;
case op_rparen:
printf( " )" );
break;
}
}
printf( "\n" );
}
#endif
/split-man
0,0 → 1,33
#!/usr/bin/perl
#
# split-man: create man pages from kernel-doc -man output
#
# Author: Tim Waugh <twaugh@redhat.com>
# Modified by: Christoph Hellwig <hch@infradead.org>
#
 
use strict;
 
die "$0: where do I put the results?\n" unless ($#ARGV >= 0);
die "$0: can't create $ARGV[0]: $!\n" unless mkdir $ARGV[0], 0777;
 
my $state = 0;
 
while (<STDIN>) {
s/&amp;(\w+)/\\fB\1\\fP/g; # fix smgl uglinesses
if (/^\.TH \"[^\"]*\" 9 \"([^\"]*)\"/) {
close OUT unless ($state++ == 0);
my $fn = "$ARGV[0]/$1.9";
if (open OUT, ">$fn") {
print STDERR "creating $fn\n";
} else {
die "can't open $fn: $!\n";
}
 
print OUT $_;
} elsif ($state != 0) {
print OUT $_;
}
}
 
close OUT;
/docproc.c
0,0 → 1,104
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
 
/*
* A simple filter for the templates
*/
 
int main(int argc, char *argv[])
{
char buf[1024];
char *vec[8192];
char *fvec[200];
char **svec;
char type[64];
int i;
int vp=2;
int ret=0;
pid_t pid;
 
 
if(chdir(getenv("TOPDIR")))
{
perror("chdir");
exit(1);
}
/*
* Build the exec array ahead of time.
*/
vec[0]="kernel-doc";
vec[1]="-docbook";
for(i=1;vp<8189;i++)
{
if(argv[i]==NULL)
break;
vec[vp++]=type;
vec[vp++]=argv[i];
}
vec[vp++]=buf+2;
vec[vp++]=NULL;
/*
* Now process the template
*/
while(fgets(buf, 1024, stdin))
{
if(*buf!='!') {
printf("%s", buf);
continue;
}
 
fflush(stdout);
svec = vec;
if(buf[1]=='E')
strcpy(type, "-function");
else if(buf[1]=='I')
strcpy(type, "-nofunction");
else if(buf[1]=='F') {
int snarf = 0;
fvec[0] = "kernel-doc";
fvec[1] = "-docbook";
strcpy (type, "-function");
vp = 2;
for (i = 2; buf[i]; i++) {
if (buf[i] == ' ' || buf[i] == '\n') {
buf[i] = '\0';
snarf = 1;
continue;
}
 
if (snarf) {
snarf = 0;
fvec[vp++] = type;
fvec[vp++] = &buf[i];
}
}
fvec[vp++] = &buf[2];
fvec[vp] = NULL;
svec = fvec;
} else
{
fprintf(stderr, "Unknown ! escape.\n");
exit(1);
}
switch(pid=fork())
{
case -1:
perror("fork");
exit(1);
case 0:
execvp("scripts/kernel-doc", svec);
perror("exec scripts/kernel-doc");
exit(1);
default:
waitpid(pid, &ret ,0);
}
}
exit(ret);
}
/MAKEDEV.ide
0,0 → 1,49
#!/bin/sh
#
# This script creates the proper /dev/ entries for IDE devices
# on the primary, secondary, tertiary, and quaternary interfaces.
# See ../Documentation/ide.txt for more information.
#
makedev () {
rm -f /dev/$1
echo mknod /dev/$1 $2 $3 $4
mknod /dev/$1 $2 $3 $4
chown root:disk /dev/$1
chmod 660 /dev/$1
}
 
makedevs () {
rm -f /dev/$1*
makedev $1 b $2 $3
for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
do
makedev $1$part b $2 `expr $3 + $part`
done
}
 
makedevs hda 3 0
makedevs hdb 3 64
makedevs hdc 22 0
makedevs hdd 22 64
makedevs hde 33 0
makedevs hdf 33 64
makedevs hdg 34 0
makedevs hdh 34 64
makedevs hdi 56 0
makedevs hdj 56 64
makedevs hdk 57 0
makedevs hdl 57 64
makedevs hdm 88 0
makedevs hdn 88 64
makedevs hdo 89 0
makedevs hdp 89 64
makedevs hdq 90 0
makedevs hdr 90 64
makedevs hds 91 0
makedevs hdt 91 64
 
for tape in 0 1 2 3 4 5 6 7
do
makedev ht$tape c 37 $tape
makedev nht$tape c 37 `expr $tape + 128`
done
/patch-kernel
0,0 → 1,202
#! /bin/sh
# Script to apply kernel patches.
# usage: patch-kernel [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
# The source directory defaults to /usr/src/linux, and the patch
# directory defaults to the current directory.
# e.g.
# scripts/patch-kernel . ..
# Update the kernel tree in the current directory using patches in the
# directory above to the latest Linus kernel
# scripts/patch-kernel . .. -ac
# Get the latest Linux kernel and patch it with the latest ac patch
# scripts/patch-kernel . .. 2.4.9
# Gets standard kernel 2.4.9
# scripts/patch-kernel . .. 2.4.9 -ac
# Gets 2.4.9 with latest ac patches
# scripts/patch-kernel . .. 2.4.9 -ac11
# Gets 2.4.9 with ac patch ac11
# Note: It uses the patches relative to the Linus kernels, not the
# ac to ac relative patches
#
# It determines the current kernel version from the top-level Makefile.
# It then looks for patches for the next sublevel in the patch directory.
# This is applied using "patch -p1 -s" from within the kernel directory.
# A check is then made for "*.rej" files to see if the patch was
# successful. If it is, then all of the "*.orig" files are removed.
#
# Nick Holloway <Nick.Holloway@alfie.demon.co.uk>, 2nd January 1995.
#
# Added support for handling multiple types of compression. What includes
# gzip, bzip, bzip2, zip, compress, and plaintext.
#
# Adam Sulmicki <adam@cfar.umd.edu>, 1st January 1997.
#
# Added ability to stop at a given version number
# Put the full version number (i.e. 2.3.31) as the last parameter
# Dave Gilbert <linux@treblig.org>, 11th December 1999.
 
# Fixed previous patch so that if we are already at the correct version
# not to patch up.
#
# Added -ac option, use -ac or -ac9 (say) to stop at a particular version
# Dave Gilbert <linux@treblig.org>, 29th September 2001.
 
# Set directories from arguments, or use defaults.
sourcedir=${1-/usr/src/linux}
patchdir=${2-.}
stopvers=${3-imnotaversion}
 
if [ "$1" = -h -o "$1" = --help -o ! -r "$sourcedir/Makefile" ]; then
cat << USAGE
usage: patch-kernel [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
The source directory defaults to /usr/src/linux, and
the patch directory defaults to the current directory.
USAGE
exit 1
fi
 
# See if we have any -ac options
for PARM in $*
do
case $PARM in
-ac*)
gotac=$PARM;
 
esac;
done
 
# ---------------------------------------------------------------------------
# Find a file, first parameter is basename of file
# it tries many compression mechanisms and sets variables to say how to get it
findFile () {
filebase=$1;
 
if [ -r ${filebase}.gz ]; then
ext=".gz"
name="gzip"
uncomp="gunzip -dc"
elif [ -r ${filebase}.bz ]; then
ext=".bz"
name="bzip"
uncomp="bunzip -dc"
elif [ -r ${filebase}.bz2 ]; then
ext=".bz2"
name="bzip2"
uncomp="bunzip2 -dc"
elif [ -r ${filebase}.zip ]; then
ext=".zip"
name="zip"
uncomp="unzip -d"
elif [ -r ${filebase}.Z ]; then
ext=".Z"
name="uncompress"
uncomp="uncompress -c"
elif [ -r ${filebase} ]; then
ext=""
name="plaintext"
uncomp="cat"
else
return 1;
fi
 
return 0;
}
 
# ---------------------------------------------------------------------------
# Apply a patch and check it goes in cleanly
# First param is patch name (e.g. patch-2.4.9-ac5) - without path or extension
 
applyPatch () {
echo -n "Applying $1 (${name})... "
if $uncomp ${patchdir}/$1${ext} | patch -p1 -s -N -E -d $sourcedir
then
echo "done."
else
echo "failed. Clean up yourself."
return 1;
fi
if [ "`find $sourcedir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
then
echo "Aborting. Reject files found."
return 1;
fi
# Remove backup files
find $sourcedir/ '(' -name '*.orig' -o -name '.*.orig' ')' -exec rm -f {} \;
return 0;
}
 
# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTERVERSION
eval `sed -n -e 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' -e 's/^\([A-Z]*\) = \(-[-a-z0-9]*\)$/\1=\2/p' $sourcedir/Makefile`
if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ]
then
echo "unable to determine current kernel version" >&2
exit 1
fi
 
echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION}"
 
if [ x$EXTRAVERSION != "x" ]
then
echo "I'm sorry but patch-kernel can't work with a kernel source tree that is not a base version"
exit 1;
fi
 
while :
do
CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
if [ $stopvers = $CURRENTFULLVERSION ]
then
echo "Stoping at $CURRENTFULLVERSION base as requested."
break
fi
 
SUBLEVEL=`expr $SUBLEVEL + 1`
FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
 
patch=patch-$FULLVERSION
 
# See if the file exists and find extension
findFile $patchdir/${patch} || break
 
# Apply the patch and check all is OK
applyPatch $patch || break
done
 
if [ x$gotac != x ]; then
# Out great user wants the -ac patches
# They could have done -ac (get latest) or -acxx where xx=version they want
if [ $gotac == "-ac" ]
then
# They want the latest version
HIGHESTPATCH=0
for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.*
do
ACVALUE=`echo $PATCHNAMES | sed -e 's/^.*patch-[0-9.]*-ac\([0-9]*\).*/\1/'`
# Check it is actually a recognised patch type
findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${ACVALUE} || break
 
if [ $ACVALUE -gt $HIGHESTPATCH ]
then
HIGHESTPATCH=$ACVALUE
fi
done
 
if [ $HIGHESTPATCH -ne 0 ]
then
findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH} || break
applyPatch patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH}
else
echo "No ac patches found"
fi
else
# They want an exact version
findFile $patchdir/patch-${CURRENTFULLVERSION}${gotac} || {
echo "Sorry, I couldn't find the $gotac patch for $CURRENTFULLVERSION. Hohum."
exit 1
}
applyPatch patch-${CURRENTFULLVERSION}${gotac}
fi
fi
 
 
patch-kernel Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property

powered by: WebSVN 2.1.0

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