Merged menuconfig code from experimental.
Added clfs2 symlink (required by menuconfig)
This commit is contained in:
parent
daa9b6c5e7
commit
a7057086d9
34 changed files with 15961 additions and 3 deletions
700
Config.in
Normal file
700
Config.in
Normal file
|
@ -0,0 +1,700 @@
|
||||||
|
menu "--- BOOK Settings"
|
||||||
|
|
||||||
|
#--- BOOK/script
|
||||||
|
choice
|
||||||
|
prompt "Use BOOK"
|
||||||
|
default BOOK_LFS
|
||||||
|
help
|
||||||
|
#-- Select the BOOK/Build style you wish to configure.
|
||||||
|
|
||||||
|
config BOOK_LFS
|
||||||
|
bool "Linux From Scratch"
|
||||||
|
|
||||||
|
config BOOK_CLFS
|
||||||
|
bool "Cross-Compiled Linux From Scratch"
|
||||||
|
|
||||||
|
config BOOK_CLFS2
|
||||||
|
bool "Cross-Compiled Linux From Scratch (Version 2)"
|
||||||
|
|
||||||
|
# config BOOK_CLFS3
|
||||||
|
# bool "Cross-Compiled Linux From Scratch (Embedded Systems)"
|
||||||
|
|
||||||
|
config BOOK_HLFS
|
||||||
|
bool "Hardened Linux From Scratch"
|
||||||
|
|
||||||
|
# config BOOK_BLFS
|
||||||
|
# bool "Beyond Linux From Scratch"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config RUN_ME
|
||||||
|
string
|
||||||
|
default "./lfs" if BOOK_LFS
|
||||||
|
default "./clfs" if BOOK_CLFS
|
||||||
|
default "./clfs2" if BOOK_CLFS2
|
||||||
|
# default "./clfs3" if BOOK_CLFS3
|
||||||
|
default "./hlfs" if BOOK_HLFS
|
||||||
|
# default "./blfs" if BOOK_BLFS
|
||||||
|
#--- End BOOK/script
|
||||||
|
|
||||||
|
#--- Book version
|
||||||
|
choice
|
||||||
|
prompt "Release"
|
||||||
|
default relSVN
|
||||||
|
config relSVN
|
||||||
|
bool "SVN"
|
||||||
|
help
|
||||||
|
#-- Current development version as in trunk
|
||||||
|
|
||||||
|
config WORKING_COPY
|
||||||
|
bool "Working Copy"
|
||||||
|
help
|
||||||
|
#-- A local working copy
|
||||||
|
|
||||||
|
config BRANCH
|
||||||
|
bool "Branch or stable book" if !BOOK_HLFS && !BOOK_CLFS2
|
||||||
|
help
|
||||||
|
#-- A supported SVN branch or stable released book
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config BRANCH_ID
|
||||||
|
string "Branch (mandatory)"
|
||||||
|
default "**EDIT ME**"
|
||||||
|
depends BRANCH
|
||||||
|
help
|
||||||
|
#-- A list of valid branches and stable books ID's is available here.
|
||||||
|
# http://wiki.linuxfromscratch.org/alfs/wiki/SupportedBooks
|
||||||
|
|
||||||
|
config BOOK
|
||||||
|
string "Loc of working copy (mandatory)"
|
||||||
|
default "**EDIT ME**"
|
||||||
|
depends WORKING_COPY
|
||||||
|
help
|
||||||
|
#-- The full path to a local copy of the book XML sources
|
||||||
|
#
|
||||||
|
#--- End BOOK version
|
||||||
|
|
||||||
|
#--- CLFS specific params
|
||||||
|
choice
|
||||||
|
prompt "Target architecture"
|
||||||
|
default ARCH_X86
|
||||||
|
depends BOOK_CLFS || BOOK_CLFS2
|
||||||
|
help
|
||||||
|
#-- Choose a base architecture
|
||||||
|
|
||||||
|
config ARCH_X86
|
||||||
|
bool "x86"
|
||||||
|
|
||||||
|
config ARCH_MIPS
|
||||||
|
bool "mips" if !BOOK_CLFS2
|
||||||
|
|
||||||
|
config ARCH_PPC
|
||||||
|
bool "ppc" if !BOOK_CLFS2
|
||||||
|
|
||||||
|
config ARCH_SPARC
|
||||||
|
bool "sparc" if !BOOK_CLFS2
|
||||||
|
|
||||||
|
config ARCH_ALPHA
|
||||||
|
bool "alpha" if !BOOK_CLFS2
|
||||||
|
|
||||||
|
config ARCH_ARM
|
||||||
|
bool "arm" if !BOOK_CLFS
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Library"
|
||||||
|
depends (BOOK_CLFS || BOOK_CLFS2)
|
||||||
|
default DATA_32 if !ARCH_ALPHA
|
||||||
|
default DATA_64 if ARCH_ALPHA
|
||||||
|
|
||||||
|
config DATA_32
|
||||||
|
bool "32-bit" if !ARCH_ALPHA
|
||||||
|
|
||||||
|
config DATA_64
|
||||||
|
bool "64-bit" if !ARCH_PPC && !ARCH_ARM && !(BOOK_CLFS2 && ARCH_X86)
|
||||||
|
|
||||||
|
config DATA_MULTI
|
||||||
|
bool "multilib" if !ARCH_ALPHA && !ARCH_ARM && !(BOOK_CLFS2 && ARCH_X86)
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Target"
|
||||||
|
depends (BOOK_CLFS || BOOK_CLFS2) && ((ARCH_X86 && DATA_32) || ARCH_MIPS)
|
||||||
|
|
||||||
|
config PROC_i486
|
||||||
|
bool "i486" if ARCH_X86 && DATA_32
|
||||||
|
|
||||||
|
config PROC_i586
|
||||||
|
bool "i586" if ARCH_X86 && DATA_32
|
||||||
|
|
||||||
|
config PROC_i686
|
||||||
|
bool "i686" if ARCH_X86 && DATA_32
|
||||||
|
|
||||||
|
config PROC_mipsel
|
||||||
|
bool "mips -little endian" if ARCH_MIPS
|
||||||
|
|
||||||
|
config PROC_mips
|
||||||
|
bool "mips" if ARCH_MIPS
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config TARGET
|
||||||
|
string
|
||||||
|
depends DATA_32
|
||||||
|
default "i486-pc-linux-gnu" if ARCH_X86 && PROC_i486
|
||||||
|
default "i586-pc-linux-gnu" if ARCH_X86 && PROC_i586
|
||||||
|
default "i686-pc-linux-gnu" if ARCH_X86 && PROC_i686
|
||||||
|
default "mipsel-unknown-linux-gnu" if ARCH_MIPS && PROC_mipsel
|
||||||
|
default "mips-unknown-linux-gnu" if ARCH_MIPS && PROC_mips
|
||||||
|
default "powerpc-unknown-linux-gnu" if ARCH_PPC
|
||||||
|
default "sparc-unknown-linux-gnu" if ARCH_SPARC
|
||||||
|
default "arm-unknown-linux-gnu" if ARCH_ARM
|
||||||
|
|
||||||
|
config TARGET
|
||||||
|
string
|
||||||
|
depends DATA_64
|
||||||
|
default "x86_64-unknown-linux-gnu" if ARCH_X86
|
||||||
|
default "mips64el-unknown-linux-gnu" if ARCH_MIPS && PROC_mipsel
|
||||||
|
default "mips64-unknown-linux-gnu" if ARCH_MIPS && PROC_mips
|
||||||
|
default "sparc64-unknown-linux-gnu" if ARCH_SPARC
|
||||||
|
default "alpha-unknown-linux-gnu" if ARCH_ALPHA
|
||||||
|
|
||||||
|
config TARGET
|
||||||
|
string
|
||||||
|
depends DATA_MULTI
|
||||||
|
default "x86_64-unknown-linux-gnu" if ARCH_X86
|
||||||
|
default "mips64el-unknown-linux-gnu" if ARCH_MIPS && PROC_mipsel
|
||||||
|
default "mips64-unknown-linux-gnu" if ARCH_MIPS && PROC_mips
|
||||||
|
default "sparc64-unknown-linux-gnu" if ARCH_SPARC
|
||||||
|
default "powerpc64-unknown-linux-gnu" if ARCH_PPC
|
||||||
|
|
||||||
|
|
||||||
|
config TARGET32
|
||||||
|
string
|
||||||
|
depends DATA_MULTI
|
||||||
|
default "i686-pc-linux-gnu" if ARCH_X86
|
||||||
|
default "mipsel-unknown-linux-gnu" if ARCH_MIPS && PROC_mipsel
|
||||||
|
default "mips-unknown-linux-gnu" if ARCH_MIPS && PROC_mips
|
||||||
|
default "sparc-unknown-linux-gnu" if ARCH_SPARC
|
||||||
|
default "powerpc-unknown-linux-gnu" if ARCH_PPC
|
||||||
|
|
||||||
|
config ARCH
|
||||||
|
string
|
||||||
|
depends DATA_32
|
||||||
|
default "x86" if ARCH_X86
|
||||||
|
default "ppc" if ARCH_PPC
|
||||||
|
default "mips" if ARCH_MIPS
|
||||||
|
default "sparc" if ARCH_SPARC
|
||||||
|
default "arm" if ARCH_ARM
|
||||||
|
|
||||||
|
config ARCH
|
||||||
|
string
|
||||||
|
depends DATA_64
|
||||||
|
default "x86_64-64" if ARCH_X86
|
||||||
|
default "mips64-64" if ARCH_MIPS
|
||||||
|
default "sparc64-64" if ARCH_SPARC
|
||||||
|
default "alpha" if ARCH_ALPHA
|
||||||
|
|
||||||
|
config ARCH
|
||||||
|
string
|
||||||
|
depends DATA_MULTI
|
||||||
|
default "x86_64" if ARCH_X86
|
||||||
|
default "mips64" if ARCH_MIPS
|
||||||
|
default "sparc64" if ARCH_SPARC
|
||||||
|
default "ppc64" if ARCH_PPC
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Build method"
|
||||||
|
depends BOOK_CLFS
|
||||||
|
help
|
||||||
|
#-- What build method should be used: a chroot jail or minimal boot system
|
||||||
|
# Review the Cross-LFS book chap6 "TO BOOT OR CHROOT" for a full explanation.
|
||||||
|
|
||||||
|
config BUILD_CHROOT
|
||||||
|
bool "chroot"
|
||||||
|
|
||||||
|
config BUILD_BOOT
|
||||||
|
bool "boot"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config METHOD
|
||||||
|
string
|
||||||
|
default "chroot" if BUILD_CHROOT
|
||||||
|
default "boot" if BUILD_BOOT
|
||||||
|
|
||||||
|
config BOOT_CONFIG
|
||||||
|
string "BOOT kernel config file (mandatory)"
|
||||||
|
default "***EDIT ME***"
|
||||||
|
depends on BUILD_BOOT
|
||||||
|
help
|
||||||
|
#-- If METHOD=boot, location of boot-kernel config file
|
||||||
|
# The config file will be copied to ${BUILD_DIR}/sources
|
||||||
|
# and renamed 'bootkernel-config'
|
||||||
|
#
|
||||||
|
# NOTE: this setting is required
|
||||||
|
|
||||||
|
config BOOT_KEYMAP
|
||||||
|
string "BOOT kernel keyboard map (see help)"
|
||||||
|
default "none"
|
||||||
|
depends on BUILD_BOOT
|
||||||
|
help
|
||||||
|
#-- Include the keymap in the kernel if defined. Path to the
|
||||||
|
# keymap file relative to /usr/share/kbd/keymaps/
|
||||||
|
# (e.g., i386/qwerty/us.map.gz) or "none" if you do not want
|
||||||
|
# a keymap included in the kernel
|
||||||
|
|
||||||
|
=== Note about CLFS ===
|
||||||
|
If building the SVN or 1.0.0rc3 version using the boot method and
|
||||||
|
compiling the keymap into the kernel, you MUST manually edit the
|
||||||
|
"loadkeys" command found in $JHALFSDIR/clfs-commands/boot/066-kernel
|
||||||
|
to set the full path in your host to the keymap file.
|
||||||
|
#--- End CLFS specific params
|
||||||
|
|
||||||
|
#--- HLFS specific params
|
||||||
|
config GRSECURITY_HOST
|
||||||
|
bool "Building on grsecurity enabled host?"
|
||||||
|
default n
|
||||||
|
depends on BOOK_HLFS
|
||||||
|
help
|
||||||
|
#-- If your build system has grsecurity patches applied
|
||||||
|
# you MUST enable this switch.
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Library"
|
||||||
|
depends on BOOK_HLFS
|
||||||
|
help
|
||||||
|
#-- Which library model to use: uClibc/glibc
|
||||||
|
|
||||||
|
config LIB_GLIBC
|
||||||
|
bool "glibc"
|
||||||
|
|
||||||
|
config LIB_UCLIBC
|
||||||
|
bool "uClibc"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config MODEL
|
||||||
|
depends on BOOK_HLFS
|
||||||
|
string
|
||||||
|
default "glibc" if LIB_GLIBC
|
||||||
|
default "uclibc" if LIB_UCLIBC
|
||||||
|
#--- End HLFS specific params
|
||||||
|
|
||||||
|
#--- End BOOK Settings
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
menu "--- General Settings"
|
||||||
|
|
||||||
|
#--- Set User Account
|
||||||
|
config CONFIG_USER
|
||||||
|
bool "Change the default user/group for this build"
|
||||||
|
default n
|
||||||
|
help #-- Unprivileged user and group name
|
||||||
|
# If you do not have the priv to create/delete
|
||||||
|
# users and groups you can specifiy your own
|
||||||
|
# user id for the build
|
||||||
|
#
|
||||||
|
# default values for each book
|
||||||
|
# LFS lfs
|
||||||
|
# CLFS clfs
|
||||||
|
# CLFS2 clfs
|
||||||
|
# HLFS hlfs
|
||||||
|
|
||||||
|
config DEF_USER
|
||||||
|
string
|
||||||
|
default "lfs" if BOOK_LFS
|
||||||
|
default "clfs" if BOOK_CLFS || BOOK_CLFS2
|
||||||
|
default "hlfs" if BOOK_HLFS
|
||||||
|
|
||||||
|
config SET_USER
|
||||||
|
string "User account"
|
||||||
|
depends CONFIG_USER
|
||||||
|
default DEF_USER
|
||||||
|
|
||||||
|
|
||||||
|
config CONFIG_GROUP
|
||||||
|
bool "Set Group?"
|
||||||
|
default n
|
||||||
|
depends CONFIG_USER
|
||||||
|
|
||||||
|
config SET_GROUP
|
||||||
|
string "GROUP account"
|
||||||
|
depends CONFIG_GROUP
|
||||||
|
default DEF_USER
|
||||||
|
|
||||||
|
config LUSER
|
||||||
|
string
|
||||||
|
default DEF_USER if !CONFIG_USER
|
||||||
|
default SET_USER if CONFIG_USER
|
||||||
|
|
||||||
|
config LGROUP
|
||||||
|
string
|
||||||
|
default LUSER if !CONFIG_GROUP
|
||||||
|
default SET_GROUP if CONFIG_GROUP
|
||||||
|
#--- End Set User Account
|
||||||
|
|
||||||
|
config BUILDDIR
|
||||||
|
string "Build Directory"
|
||||||
|
default "/mnt/build_dir"
|
||||||
|
help
|
||||||
|
#-- The directory where the created system will be located.
|
||||||
|
|
||||||
|
config CONFIG_GETPKG
|
||||||
|
bool "Retrieve source files"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
#-- Download all packages and patches required by the book selected
|
||||||
|
# NOTE: Looks for files in the local archive defined by SRC_ARCHIVE
|
||||||
|
# first and if necessary retrieve them from the 'net.
|
||||||
|
# Files will be transfered to $BUILDDIR/sources.
|
||||||
|
|
||||||
|
config SRC_ARCHIVE
|
||||||
|
string "Package Archive Directory"
|
||||||
|
default "$SRC_ARCHIVE"
|
||||||
|
depends CONFIG_GETPKG
|
||||||
|
help
|
||||||
|
#-- A local archive for packages/file (not $BUILDDIR/sources)
|
||||||
|
# Used only if GETPKG = 1
|
||||||
|
# Any missing file will be downloaded and archived here,
|
||||||
|
# if the user has the right priviledges.
|
||||||
|
|
||||||
|
config CONFIG_GETKERNEL
|
||||||
|
bool "Always retrieve kernel package"
|
||||||
|
default n
|
||||||
|
depends CONFIG_GETPKG
|
||||||
|
help
|
||||||
|
#-- Get the kernel package and patches even if no configuration
|
||||||
|
# file has been supplied.
|
||||||
|
|
||||||
|
config CONFIG_RUNMAKE
|
||||||
|
bool "Run the makefile"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
#-- Automatically run the makefile once it has been created
|
||||||
|
|
||||||
|
config CONFIG_REBUILD
|
||||||
|
bool "Rebuild files"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
#-- Clean the build directory before performing any other task.
|
||||||
|
# The directory is cleaned only if it was populated by a
|
||||||
|
# previous JHALFS run.
|
||||||
|
#
|
||||||
|
# NOTE::You must be 'root' for this function to work
|
||||||
|
|
||||||
|
#--- End General Settings
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
menu "--- Build Settings"
|
||||||
|
|
||||||
|
#--- Test Suites
|
||||||
|
config CONFIG_TESTS
|
||||||
|
bool "Run testsuites"
|
||||||
|
depends !BOOK_CLFS2
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
#-- Run test suites
|
||||||
|
#
|
||||||
|
# You will can to select between:
|
||||||
|
#
|
||||||
|
# - Only final system Glibc, GCC and Binutils testsuites
|
||||||
|
# - All final system testsuites
|
||||||
|
# - Both temporary tools and final system testsuites
|
||||||
|
#
|
||||||
|
# HLFS and CLFS has no testsuites available in the
|
||||||
|
# temporary tools phase
|
||||||
|
|
||||||
|
# You will be promt also about the "flavour" of the
|
||||||
|
# testsuites run:
|
||||||
|
#
|
||||||
|
# - Don't stop on test suite failures
|
||||||
|
# - Abort the build at the first test suite failure
|
||||||
|
#
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Tests ->"
|
||||||
|
depends CONFIG_TESTS
|
||||||
|
default TEST_1
|
||||||
|
|
||||||
|
config TST_1
|
||||||
|
bool "Only final system Glibc, GCC and Binutils testsuites"
|
||||||
|
|
||||||
|
config TST_2
|
||||||
|
bool "All final system testsuites"
|
||||||
|
|
||||||
|
config TST_3
|
||||||
|
bool "Both temporary tools and final system testsuites" if !BOOK_HLFS && !BOOK_CLFS
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config TEST
|
||||||
|
int
|
||||||
|
default "0" if !CONFIG_TESTS
|
||||||
|
default "1" if TST_1
|
||||||
|
default "2" if TST_2
|
||||||
|
default "3" if TST_3
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Flavour ->"
|
||||||
|
depends CONFIG_TESTS
|
||||||
|
default NO_BOMB
|
||||||
|
|
||||||
|
config NO_BOMB
|
||||||
|
bool "Don't stop on test suite failures"
|
||||||
|
|
||||||
|
config BOMB
|
||||||
|
bool "Abort the build at the first test suite failure"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config BOMB_TEST
|
||||||
|
int
|
||||||
|
default "0" if NO_BOMB
|
||||||
|
default "1" if BOMB
|
||||||
|
#--- End Test Suites
|
||||||
|
|
||||||
|
#--- FSTAB
|
||||||
|
config HAVE_FSTAB
|
||||||
|
bool "Use a custom fstab file"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
#-- Select this if you have ready a proper fstab file
|
||||||
|
|
||||||
|
config FSTAB
|
||||||
|
string "Fstab file (optional)"
|
||||||
|
default "***EDIT ME***"
|
||||||
|
depends on HAVE_FSTAB
|
||||||
|
help
|
||||||
|
#-- The location of fstab file (if empty, a template is created)
|
||||||
|
#--- End FSTAB
|
||||||
|
|
||||||
|
#--- Kernel
|
||||||
|
config CONFIG_BUILD_KERNEL
|
||||||
|
bool "Build the kernel"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
#-- Select this option if you wish to build the kernel.
|
||||||
|
#
|
||||||
|
# You will be prompted for the full path to the .config
|
||||||
|
# file. It will be copied to the 'sources' directory and
|
||||||
|
# rename kernel-config
|
||||||
|
|
||||||
|
config CONFIG
|
||||||
|
string "Kernel config file"
|
||||||
|
default "***EDIT ME***"
|
||||||
|
depends on CONFIG_BUILD_KERNEL
|
||||||
|
help
|
||||||
|
#-- Fully qualified path to a kernel config file
|
||||||
|
# The config file will be copied to ${BUILD_DIR}/sources
|
||||||
|
# and renamed 'kernel-config'
|
||||||
|
|
||||||
|
config KEYMAP
|
||||||
|
string "Keyboard map"
|
||||||
|
default "none"
|
||||||
|
depends on !BOOK_LFS && CONFIG_BUILD_KERNEL
|
||||||
|
help
|
||||||
|
#-- Include the keymap in the kernel if defined. Path to the
|
||||||
|
# keymap file relative to /usr/share/kbd/keymaps/
|
||||||
|
# (e.g., i386/qwerty/us.map.gz) or "none" if you do not want
|
||||||
|
# a keymap included in the kernel
|
||||||
|
#--- End Kernel
|
||||||
|
|
||||||
|
config CONFIG_STRIP
|
||||||
|
bool "Strip Installed Binaries/Libraries"
|
||||||
|
default y
|
||||||
|
|
||||||
|
config CONFIG_VIMLANG
|
||||||
|
bool "Install vim-lang package"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
#-- install the optional vim-lang package
|
||||||
|
|
||||||
|
config TIMEZONE
|
||||||
|
string "TimeZone"
|
||||||
|
default "GMT"
|
||||||
|
help
|
||||||
|
#-- The timezone as output by tzselect
|
||||||
|
# This will be copied to /etc/localtime
|
||||||
|
|
||||||
|
config LANG
|
||||||
|
string "Language"
|
||||||
|
default "$LANG"
|
||||||
|
help
|
||||||
|
#-- Language information in /etc/profile See <locale -a> for values
|
||||||
|
|
||||||
|
config LC_ALL
|
||||||
|
string "Language"
|
||||||
|
default "$LC_ALL"
|
||||||
|
depends on !BOOK_LFS
|
||||||
|
help
|
||||||
|
#-- Language information in /etc/profile See <locale -a> for values
|
||||||
|
|
||||||
|
#--- Groff page
|
||||||
|
choice
|
||||||
|
prompt "Groff page size"
|
||||||
|
default PAGE_LETTER
|
||||||
|
help
|
||||||
|
#-- Page definition for groff: letter or A4
|
||||||
|
|
||||||
|
config PAGE_LETTER
|
||||||
|
bool "letter"
|
||||||
|
|
||||||
|
config PAGE_A4
|
||||||
|
bool "A4"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config PAGE
|
||||||
|
string
|
||||||
|
default "letter" if PAGE_LETTER
|
||||||
|
default "A4" if PAGE_A4
|
||||||
|
#--- End Groff page
|
||||||
|
|
||||||
|
#--- End Build Settings
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
menu "--- Advanced Features"
|
||||||
|
|
||||||
|
config CONFIG_REPORT
|
||||||
|
bool "Create SBU and disk usage report"
|
||||||
|
default y
|
||||||
|
|
||||||
|
#--- ICA/farce
|
||||||
|
config CONFIG_COMPARE
|
||||||
|
bool "Run comparison analysis on final stage"
|
||||||
|
depends !BOOK_CLFS2
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
#-- Should some iterative comparison analysis by made?
|
||||||
|
#
|
||||||
|
# Unless you are familiar with ICA and/or FARCE do not
|
||||||
|
# select this option
|
||||||
|
#
|
||||||
|
# ICA and FARCE are analysis tools for comparing one
|
||||||
|
# build to the next. Builds mays differ from one iteration
|
||||||
|
# to another due to the build order and these tools try
|
||||||
|
# to ferret out those differences by examining the stored
|
||||||
|
# build logs and binary files.
|
||||||
|
#
|
||||||
|
# The scripts are well commented and can be found in ./extras/*
|
||||||
|
#
|
||||||
|
|
||||||
|
config ITERATIONS
|
||||||
|
int "Number of test runs (2,3,4,5)"
|
||||||
|
depends on CONFIG_COMPARE
|
||||||
|
range 2 5
|
||||||
|
default 3
|
||||||
|
|
||||||
|
config CONFIG_ICA
|
||||||
|
bool "ICA testing"
|
||||||
|
depends on CONFIG_COMPARE
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
#-- Run ICA testing
|
||||||
|
|
||||||
|
config CONFIG_FARCE
|
||||||
|
bool "farce testing"
|
||||||
|
depends on CONFIG_COMPARE
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
#-- Run farce testing
|
||||||
|
#--- End ICA/farce
|
||||||
|
|
||||||
|
#-- Optimizations
|
||||||
|
config CONFIG_OPTIMIZE
|
||||||
|
bool "Use optimization "
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
#-- Actual optimzation flags MUST be defined in ./optimize/*
|
||||||
|
# files before activate this option.
|
||||||
|
#
|
||||||
|
# WARNING: The use of build optimizations may be dangerous.
|
||||||
|
# You should know what you are doing and be sure that the
|
||||||
|
# optimization settings listed below are what you want.
|
||||||
|
# It there are build issues or the system doesn't work as
|
||||||
|
# expected, please rebuild without optimizations before
|
||||||
|
# asking for support.
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Optimization level "
|
||||||
|
default OPT_1
|
||||||
|
depends CONFIG_OPTIMIZE
|
||||||
|
help
|
||||||
|
#-- Optimization values are set in optimize/* files
|
||||||
|
|
||||||
|
config OPT_1
|
||||||
|
bool "Final system only"
|
||||||
|
|
||||||
|
config OPT_2
|
||||||
|
bool "Both temp tools and final system"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config OPTIMIZE
|
||||||
|
int
|
||||||
|
default "0" if !CONFIG_OPTIMIZE
|
||||||
|
default "1" if OPT_1
|
||||||
|
default "2" if OPT_2
|
||||||
|
#--- End Optimizations
|
||||||
|
|
||||||
|
#--- End Advanced Features
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
# config CONFIG_BLFS_CMDS
|
||||||
|
# bool "Add BLFS packages to current build"
|
||||||
|
# default n
|
||||||
|
# depends !BOOK_HLFS && XXX
|
||||||
|
# help
|
||||||
|
# #--- Select this option if you wish to install any BLFS packages
|
||||||
|
# # as part of your {c,h}lfs build.
|
||||||
|
# # Any needed packages will be downloaded to the /sources dir
|
||||||
|
# config BLFS_CMDLINE
|
||||||
|
# string "BLFS packages"
|
||||||
|
# default "none"
|
||||||
|
# depends CONFIG_BLFS_CMDS
|
||||||
|
|
||||||
|
|
||||||
|
# convert CONFIG_XXXX n/y to XXXX 0/1
|
||||||
|
|
||||||
|
config COMPARE
|
||||||
|
int
|
||||||
|
default 0 if !CONFIG_COMPARE
|
||||||
|
default 1 if CONFIG_COMPARE
|
||||||
|
|
||||||
|
config GETPKG
|
||||||
|
int
|
||||||
|
default 0 if !CONFIG_GETPKG
|
||||||
|
default 1 if CONFIG_GETPKG
|
||||||
|
|
||||||
|
config GETKERNEL
|
||||||
|
int
|
||||||
|
default 0 if !CONFIG_GETKERNEL
|
||||||
|
default 1 if CONFIG_GETKERNEL
|
||||||
|
|
||||||
|
config RUNMAKE
|
||||||
|
int
|
||||||
|
default 0 if !CONFIG_RUNMAKE
|
||||||
|
default 1 if CONFIG_RUNMAKE
|
||||||
|
|
||||||
|
config STRIP
|
||||||
|
int
|
||||||
|
default 0 if !CONFIG_STRIP
|
||||||
|
default 1 if CONFIG_STRIP
|
||||||
|
|
||||||
|
config REPORT
|
||||||
|
int
|
||||||
|
default 0 if !CONFIG_REPORT
|
||||||
|
default 1 if CONFIG_REPORT
|
||||||
|
|
||||||
|
config VIMLANG
|
||||||
|
int
|
||||||
|
default 0 if !CONFIG_VIMLANG
|
||||||
|
default 1 if CONFIG_VIMLANG
|
||||||
|
|
||||||
|
config RUN_ICA
|
||||||
|
int
|
||||||
|
default 0 if !CONFIG_ICA
|
||||||
|
default 1 if CONFIG_ICA
|
||||||
|
|
||||||
|
config RUN_FARCE
|
||||||
|
int
|
||||||
|
default 0 if !CONFIG_FARCE
|
||||||
|
default 1 if CONFIG_FARCE
|
||||||
|
|
||||||
|
config CLEAN
|
||||||
|
int
|
||||||
|
default 0 if !CONFIG_REBUILD
|
||||||
|
default 1 if CONFIG_REBUILD
|
37
Makefile
Normal file
37
Makefile
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# From the Build Scripts Written By: Jim Gifford <lfs@jg555.com>
|
||||||
|
# Modified By: Joe Ciccone <jciccone@linuxfromscratch.org
|
||||||
|
# Additional changes: George Boudreau <georgeb@linuxfromscratch.org>
|
||||||
|
|
||||||
|
TOPDIR=$(shell pwd)
|
||||||
|
CONFIG_CONFIG_IN = Config.in
|
||||||
|
CONFIG = menu
|
||||||
|
|
||||||
|
all: menuconfig
|
||||||
|
@touch using_menuconfig
|
||||||
|
@`grep RUN_ME configuration | sed -e 's@RUN_ME=\"@@' -e 's@\"@@' ` || rm -f using_menuconfig
|
||||||
|
@rm -f using_menuconfig
|
||||||
|
|
||||||
|
|
||||||
|
$(CONFIG)/conf:
|
||||||
|
$(MAKE) -C $(CONFIG) conf
|
||||||
|
|
||||||
|
$(CONFIG)/mconf:
|
||||||
|
$(MAKE) -C $(CONFIG) ncurses conf mconf
|
||||||
|
|
||||||
|
menuconfig: $(CONFIG)/mconf
|
||||||
|
@$(CONFIG)/mconf $(CONFIG_CONFIG_IN)
|
||||||
|
|
||||||
|
config: $(CONFIG)/conf
|
||||||
|
@$(CONFIG)/conf $(CONFIG_CONFIG_IN)
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f configuration configuration.old error
|
||||||
|
- $(MAKE) -C $(CONFIG) clean
|
||||||
|
|
||||||
|
clean-target:
|
||||||
|
rm -f error
|
||||||
|
- $(MAKE) -C $(CONFIG) clean
|
||||||
|
|
||||||
|
.PHONY: all menuconfig config clean clean-target
|
19
README
19
README
|
@ -29,6 +29,25 @@ $Id$
|
||||||
Each book in the LFS series has its own set of configurable parameters
|
Each book in the LFS series has its own set of configurable parameters
|
||||||
as well as the common parameters file.
|
as well as the common parameters file.
|
||||||
|
|
||||||
|
::NEWS:: There is new configuration method for jhalfs.
|
||||||
|
|
||||||
|
We have installed the familiar menu based configuration tool driven by
|
||||||
|
make. If you type the command
|
||||||
|
make
|
||||||
|
you will be presented with a list of configurable parameters (starting
|
||||||
|
with the book you wish to use). All the parameters found in the individual
|
||||||
|
config files are available. Once you have finished setting the parameters
|
||||||
|
and exit the make file will launch the chosen book version of jhalfs.
|
||||||
|
JHALFS will import your created file and overider the values found in normal
|
||||||
|
"config" files.
|
||||||
|
..note.. The generated file <configuration> is only used by jhalfs if you
|
||||||
|
run jhalfs via make otherwise it is ignored.
|
||||||
|
|
||||||
|
If you want to try out the new configuration system without running jhalfs
|
||||||
|
issue the following.
|
||||||
|
make menuconfig
|
||||||
|
This will create a new file named configuration but will not launch jhalfs.
|
||||||
|
|
||||||
4. RUNNING::
|
4. RUNNING::
|
||||||
The script master.sh cannot be invoked directly but only via the
|
The script master.sh cannot be invoked directly but only via the
|
||||||
supplied symlinks. After editing the config file for the project you wish
|
supplied symlinks. After editing the config file for the project you wish
|
||||||
|
|
1
clfs2
Symbolic link
1
clfs2
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
master.sh
|
|
@ -695,7 +695,7 @@ extract_commands() { #
|
||||||
--stringparam timezone $TIMEZONE \
|
--stringparam timezone $TIMEZONE \
|
||||||
--stringparam page $PAGE \
|
--stringparam page $PAGE \
|
||||||
--stringparam lang $LANG \
|
--stringparam lang $LANG \
|
||||||
--stringparam keymap $KEYMAP \
|
--stringparam keymap ${KEYMAP:-"none"} \
|
||||||
-o ./${PROGNAME}-commands/ $XSL $BOOK/$ARCH-index.xml >>$LOGDIR/$LOG 2>&1
|
-o ./${PROGNAME}-commands/ $XSL $BOOK/$ARCH-index.xml >>$LOGDIR/$LOG 2>&1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
@ -707,7 +707,7 @@ extract_commands() { #
|
||||||
--stringparam timezone $TIMEZONE \
|
--stringparam timezone $TIMEZONE \
|
||||||
--stringparam page $PAGE \
|
--stringparam page $PAGE \
|
||||||
--stringparam lang $LANG \
|
--stringparam lang $LANG \
|
||||||
--stringparam keymap $KEYMAP \
|
--stringparam keymap ${KEYMAP:-"none"} \
|
||||||
-o ./${PROGNAME}-commands/ $XSL $BOOK/$ARCH-index.xml >>$LOGDIR/$LOG 2>&1
|
-o ./${PROGNAME}-commands/ $XSL $BOOK/$ARCH-index.xml >>$LOGDIR/$LOG 2>&1
|
||||||
;;
|
;;
|
||||||
hlfs)
|
hlfs)
|
||||||
|
@ -721,7 +721,7 @@ extract_commands() { #
|
||||||
--stringparam page $PAGE \
|
--stringparam page $PAGE \
|
||||||
--stringparam lang $LANG \
|
--stringparam lang $LANG \
|
||||||
--stringparam lc_all $LC_ALL \
|
--stringparam lc_all $LC_ALL \
|
||||||
--stringparam keymap $KEYMAP \
|
--stringparam keymap ${KEYMAP:-"none"} \
|
||||||
--stringparam grsecurity_host $GRSECURITY_HOST \
|
--stringparam grsecurity_host $GRSECURITY_HOST \
|
||||||
-o ./${PROGNAME}-commands/ $XSL $BOOK/index.xml >>$LOGDIR/$LOG 2>&1
|
-o ./${PROGNAME}-commands/ $XSL $BOOK/index.xml >>$LOGDIR/$LOG 2>&1
|
||||||
;;
|
;;
|
||||||
|
|
45
master.sh
45
master.sh
|
@ -68,6 +68,51 @@ source $MODULE
|
||||||
#
|
#
|
||||||
[[ $VERBOSITY > 0 ]] && echo "${SD_BORDER}${nl_}"
|
[[ $VERBOSITY > 0 ]] && echo "${SD_BORDER}${nl_}"
|
||||||
|
|
||||||
|
if [[ -e using_menuconfig ]]; then
|
||||||
|
[[ $VERBOSITY > 0 ]] && echo -n "Loading config params from <configuration>..."
|
||||||
|
source configuration
|
||||||
|
[[ $? > 0 ]] && echo "file:configuration did not load.." && exit 1
|
||||||
|
[[ $VERBOSITY > 0 ]] && echo "OK"
|
||||||
|
|
||||||
|
#--- Working directories
|
||||||
|
SCRIPT_ROOT=jhalfs
|
||||||
|
JHALFSDIR=$BUILDDIR/$SCRIPT_ROOT
|
||||||
|
LOGDIR=$JHALFSDIR/logs
|
||||||
|
TESTLOGDIR=$JHALFSDIR/test-logs
|
||||||
|
MKFILE=$JHALFSDIR/Makefile
|
||||||
|
#--- ICA report log directory
|
||||||
|
ICALOGDIR=$LOGDIR/ICA
|
||||||
|
#--- farce report log directory
|
||||||
|
FARCELOGDIR=$LOGDIR/farce
|
||||||
|
|
||||||
|
if [[ ! -z ${BRANCH_ID} ]]; then
|
||||||
|
case $BRANCH_ID in
|
||||||
|
dev* | SVN | trunk )
|
||||||
|
case $PROGNAME in
|
||||||
|
clfs2 ) TREE=branches/clfs-2.0/BOOK ;;
|
||||||
|
*) TREE=trunk/BOOK ;;
|
||||||
|
esac
|
||||||
|
LFSVRS=development
|
||||||
|
;;
|
||||||
|
branch-* )
|
||||||
|
LFSVRS=${BRANCH_ID}
|
||||||
|
TREE=branches/${BRANCH_ID#branch-}/BOOK
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
case $PROGNAME in
|
||||||
|
lfs | hlfs )
|
||||||
|
LFSVRS=${BRANCH_ID}
|
||||||
|
TREE=tags/${BRANCH_ID}/BOOK
|
||||||
|
;;
|
||||||
|
clfs | clfs2 )
|
||||||
|
LFSVRS=${BRANCH_ID}
|
||||||
|
TREE=tags/${BRANCH_ID}
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
#===========================================================
|
#===========================================================
|
||||||
# If the var BOOK contains something then, maybe, it points
|
# If the var BOOK contains something then, maybe, it points
|
||||||
|
|
507
menu/BusyBox-1.1.3-menu.patch
Normal file
507
menu/BusyBox-1.1.3-menu.patch
Normal file
|
@ -0,0 +1,507 @@
|
||||||
|
diff -Npr menu-bb/conf.c menu/conf.c
|
||||||
|
*** menu-bb/conf.c 2006-03-22 16:16:18.000000000 -0500
|
||||||
|
--- menu/conf.c 2006-07-26 17:26:45.000000000 -0400
|
||||||
|
*************** int main(int ac, char **av)
|
||||||
|
*** 535,554 ****
|
||||||
|
conf_parse(name);
|
||||||
|
//zconfdump(stdout);
|
||||||
|
switch (input_mode) {
|
||||||
|
- case set_default:
|
||||||
|
- if (!defconfig_file)
|
||||||
|
- defconfig_file = conf_get_default_confname();
|
||||||
|
- if (conf_read(defconfig_file)) {
|
||||||
|
- printf("***\n"
|
||||||
|
- "*** Can't find default configuration \"%s\"!\n"
|
||||||
|
- "***\n", defconfig_file);
|
||||||
|
- exit(1);
|
||||||
|
- }
|
||||||
|
- break;
|
||||||
|
case ask_silent:
|
||||||
|
if (stat(".config", &tmpstat)) {
|
||||||
|
printf("***\n"
|
||||||
|
! "*** You have not yet configured BusyBox!\n"
|
||||||
|
"***\n"
|
||||||
|
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
|
||||||
|
"*** \"make menuconfig\" or \"make config\").\n"
|
||||||
|
--- 535,544 ----
|
||||||
|
conf_parse(name);
|
||||||
|
//zconfdump(stdout);
|
||||||
|
switch (input_mode) {
|
||||||
|
case ask_silent:
|
||||||
|
if (stat(".config", &tmpstat)) {
|
||||||
|
printf("***\n"
|
||||||
|
! "*** You have not yet configured JHALFS!\n"
|
||||||
|
"***\n"
|
||||||
|
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
|
||||||
|
"*** \"make menuconfig\" or \"make config\").\n"
|
||||||
|
*************** int main(int ac, char **av)
|
||||||
|
*** 576,582 ****
|
||||||
|
check_conf(&rootmenu);
|
||||||
|
} while (conf_cnt);
|
||||||
|
if (conf_write(NULL)) {
|
||||||
|
! fprintf(stderr, "\n*** Error during writing of the BusyBox configuration.\n\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
--- 566,572 ----
|
||||||
|
check_conf(&rootmenu);
|
||||||
|
} while (conf_cnt);
|
||||||
|
if (conf_write(NULL)) {
|
||||||
|
! fprintf(stderr, "\n*** Error during writing of the JHALFS configuration.\n\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
diff -Npr menu-bb/confdata.c menu/confdata.c
|
||||||
|
*** menu-bb/confdata.c 2006-03-22 16:16:18.000000000 -0500
|
||||||
|
--- menu/confdata.c 2006-07-26 17:26:45.000000000 -0400
|
||||||
|
***************
|
||||||
|
*** 13,24 ****
|
||||||
|
#define LKC_DIRECT_LINK
|
||||||
|
#include "lkc.h"
|
||||||
|
|
||||||
|
! const char conf_def_filename[] = ".config";
|
||||||
|
|
||||||
|
const char conf_defname[] = "defconfig";
|
||||||
|
|
||||||
|
const char *conf_confnames[] = {
|
||||||
|
! ".config",
|
||||||
|
conf_defname,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
--- 13,24 ----
|
||||||
|
#define LKC_DIRECT_LINK
|
||||||
|
#include "lkc.h"
|
||||||
|
|
||||||
|
! const char conf_def_filename[] = "configuration";
|
||||||
|
|
||||||
|
const char conf_defname[] = "defconfig";
|
||||||
|
|
||||||
|
const char *conf_confnames[] = {
|
||||||
|
! "configuration",
|
||||||
|
conf_defname,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
*************** static char *conf_expand_value(const cha
|
||||||
|
*** 49,70 ****
|
||||||
|
return res_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
- char *conf_get_default_confname(void)
|
||||||
|
- {
|
||||||
|
- struct stat buf;
|
||||||
|
- static char fullname[PATH_MAX+1];
|
||||||
|
- char *env, *name;
|
||||||
|
-
|
||||||
|
- name = conf_expand_value(conf_defname);
|
||||||
|
- env = getenv(SRCTREE);
|
||||||
|
- if (env) {
|
||||||
|
- sprintf(fullname, "%s/%s", env, name);
|
||||||
|
- if (!stat(fullname, &buf))
|
||||||
|
- return fullname;
|
||||||
|
- }
|
||||||
|
- return name;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
int conf_read(const char *name)
|
||||||
|
{
|
||||||
|
FILE *in = NULL;
|
||||||
|
--- 49,54 ----
|
||||||
|
*************** struct menu *next_menu(struct menu *menu
|
||||||
|
*** 271,277 ****
|
||||||
|
|
||||||
|
int conf_write(const char *name)
|
||||||
|
{
|
||||||
|
! FILE *out, *out_h;
|
||||||
|
struct symbol *sym;
|
||||||
|
struct menu *menu;
|
||||||
|
const char *basename;
|
||||||
|
--- 255,261 ----
|
||||||
|
|
||||||
|
int conf_write(const char *name)
|
||||||
|
{
|
||||||
|
! FILE *out;
|
||||||
|
struct symbol *sym;
|
||||||
|
struct menu *menu;
|
||||||
|
const char *basename;
|
||||||
|
*************** int conf_write(const char *name)
|
||||||
|
*** 279,288 ****
|
||||||
|
int type, l;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
- /* busybox`s code */
|
||||||
|
- const char *opt_name;
|
||||||
|
- int use_flg;
|
||||||
|
-
|
||||||
|
dirname[0] = 0;
|
||||||
|
if (name && name[0]) {
|
||||||
|
struct stat st;
|
||||||
|
--- 263,268 ----
|
||||||
|
*************** int conf_write(const char *name)
|
||||||
|
*** 309,342 ****
|
||||||
|
out = fopen(newname, "w");
|
||||||
|
if (!out)
|
||||||
|
return 1;
|
||||||
|
- out_h = NULL;
|
||||||
|
- if (!name) {
|
||||||
|
- out_h = fopen(".tmpconfig.h", "w");
|
||||||
|
- if (!out_h)
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
fprintf(out, "#\n"
|
||||||
|
! "# Automatically generated make config: don't edit\n"
|
||||||
|
"#\n");
|
||||||
|
|
||||||
|
- /* busybox`s code */
|
||||||
|
- if (out_h) {
|
||||||
|
- fprintf(out_h, "#ifndef BB_CONFIG_H\n#define BB_CONFIG_H\n");
|
||||||
|
- fprintf(out_h, "/*\n"
|
||||||
|
- " * Automatically generated header file: don't edit\n"
|
||||||
|
- " */\n\n"
|
||||||
|
- "/* Version Number */\n"
|
||||||
|
- "#define BB_VER \"%s\"\n"
|
||||||
|
- "#define BB_BT \"%s\"\n",
|
||||||
|
- getenv("VERSION"),
|
||||||
|
- getenv("BUILDTIME"));
|
||||||
|
- if (getenv("EXTRA_VERSION"))
|
||||||
|
- fprintf(out_h, "#define BB_EXTRA_VERSION \"%s\"\n",
|
||||||
|
- getenv("EXTRA_VERSION"));
|
||||||
|
- fprintf(out_h, "\n");
|
||||||
|
- }
|
||||||
|
- /* end busybox`s code */
|
||||||
|
-
|
||||||
|
if (!sym_change_count)
|
||||||
|
sym_clear_all_valid();
|
||||||
|
|
||||||
|
--- 289,299 ----
|
||||||
|
out = fopen(newname, "w");
|
||||||
|
if (!out)
|
||||||
|
return 1;
|
||||||
|
fprintf(out, "#\n"
|
||||||
|
! "# Automatically generated configuration: don't edit\n"
|
||||||
|
! "# use make menuconfig or make config to make changes\n"
|
||||||
|
"#\n");
|
||||||
|
|
||||||
|
if (!sym_change_count)
|
||||||
|
sym_clear_all_valid();
|
||||||
|
|
||||||
|
*************** int conf_write(const char *name)
|
||||||
|
*** 357,367 ****
|
||||||
|
"#\n"
|
||||||
|
"# %s\n"
|
||||||
|
"#\n", str);
|
||||||
|
- if (out_h)
|
||||||
|
- fprintf(out_h, "\n"
|
||||||
|
- "/*\n"
|
||||||
|
- " * %s\n"
|
||||||
|
- " */\n", str);
|
||||||
|
} else if (!(sym->flags & SYMBOL_CHOICE)) {
|
||||||
|
sym_calc_value(sym);
|
||||||
|
if (!(sym->flags & SYMBOL_FORCEWRITE))
|
||||||
|
--- 314,319 ----
|
||||||
|
*************** int conf_write(const char *name)
|
||||||
|
*** 375,388 ****
|
||||||
|
type = S_BOOLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* busybox`s code */
|
||||||
|
- opt_name = strchr(sym->name, '_');
|
||||||
|
- if(opt_name == NULL)
|
||||||
|
- opt_name = sym->name;
|
||||||
|
- else
|
||||||
|
- opt_name++;
|
||||||
|
- use_flg = 1;
|
||||||
|
- /* end busybox`s code */
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case S_BOOLEAN:
|
||||||
|
--- 327,332 ----
|
||||||
|
*************** int conf_write(const char *name)
|
||||||
|
*** 390,410 ****
|
||||||
|
switch (sym_get_tristate_value(sym)) {
|
||||||
|
case no:
|
||||||
|
fprintf(out, "# %s is not set\n", sym->name);
|
||||||
|
- if (out_h)
|
||||||
|
- fprintf(out_h, "#undef %s\n", sym->name);
|
||||||
|
- use_flg = 0; /* busybox`s code */
|
||||||
|
break;
|
||||||
|
case mod:
|
||||||
|
- #if 0 /* busybox`s code */
|
||||||
|
fprintf(out, "%s=m\n", sym->name);
|
||||||
|
- if (out_h)
|
||||||
|
- fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
|
||||||
|
- #endif /* busybox`s code */
|
||||||
|
break;
|
||||||
|
case yes:
|
||||||
|
fprintf(out, "%s=y\n", sym->name);
|
||||||
|
- if (out_h)
|
||||||
|
- fprintf(out_h, "#define %s 1\n", sym->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
--- 334,345 ----
|
||||||
|
*************** int conf_write(const char *name)
|
||||||
|
*** 412,473 ****
|
||||||
|
// fix me
|
||||||
|
str = sym_get_string_value(sym);
|
||||||
|
fprintf(out, "%s=\"", sym->name);
|
||||||
|
- if (out_h)
|
||||||
|
- fprintf(out_h, "#define %s \"", sym->name);
|
||||||
|
do {
|
||||||
|
l = strcspn(str, "\"\\");
|
||||||
|
if (l) {
|
||||||
|
fwrite(str, l, 1, out);
|
||||||
|
- if (out_h)
|
||||||
|
- fwrite(str, l, 1, out_h);
|
||||||
|
}
|
||||||
|
str += l;
|
||||||
|
while (*str == '\\' || *str == '"') {
|
||||||
|
fprintf(out, "\\%c", *str);
|
||||||
|
- if (out_h)
|
||||||
|
- fprintf(out_h, "\\%c", *str);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
} while (*str);
|
||||||
|
fputs("\"\n", out);
|
||||||
|
- if (out_h)
|
||||||
|
- fputs("\"\n", out_h);
|
||||||
|
break;
|
||||||
|
case S_HEX:
|
||||||
|
str = sym_get_string_value(sym);
|
||||||
|
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
|
||||||
|
fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
|
||||||
|
- if (out_h)
|
||||||
|
- fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case S_INT:
|
||||||
|
str = sym_get_string_value(sym);
|
||||||
|
fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
|
||||||
|
- if (out_h)
|
||||||
|
- fprintf(out_h, "#define %s %s\n", sym->name, str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- /* busybox`s code */
|
||||||
|
- if (out_h) {
|
||||||
|
- fprintf(out_h, "#define ENABLE_%s %d\n", opt_name, use_flg);
|
||||||
|
- fprintf(out_h, "#define USE_%s(...)%s\n", opt_name,
|
||||||
|
- (use_flg ? " __VA_ARGS__" : ""));
|
||||||
|
- fprintf(out_h, "#define SKIP_%s(...)%s\n\n", opt_name,
|
||||||
|
- (use_flg ? "" : " __VA_ARGS__"));
|
||||||
|
- }
|
||||||
|
- /* end busybox`s code */
|
||||||
|
}
|
||||||
|
next:
|
||||||
|
menu = next_menu(menu);
|
||||||
|
}
|
||||||
|
fclose(out);
|
||||||
|
- if (out_h) {
|
||||||
|
- fprintf(out_h, "#endif /* BB_CONFIG_H */\n"); /* busybox`s code */
|
||||||
|
- fclose(out_h);
|
||||||
|
- rename(".tmpconfig.h", "include/bb_config.h"); /* busybox`s config name */
|
||||||
|
- file_write_dep(NULL);
|
||||||
|
- }
|
||||||
|
if (!name || basename != conf_def_filename) {
|
||||||
|
if (!name)
|
||||||
|
name = conf_def_filename;
|
||||||
|
--- 347,381 ----
|
||||||
|
diff -Npr menu-bb/Makefile menu/Makefile
|
||||||
|
*** menu-bb/Makefile 2006-03-22 16:16:18.000000000 -0500
|
||||||
|
--- menu/Makefile 2006-07-26 18:06:25.000000000 -0400
|
||||||
|
***************
|
||||||
|
*** 1,11 ****
|
||||||
|
# Makefile for BusyBox
|
||||||
|
#
|
||||||
|
# Copyright (C) 2002 Erik Andersen <andersen@codepoet.org>
|
||||||
|
|
||||||
|
- top_srcdir=../..
|
||||||
|
- top_builddir=../..
|
||||||
|
- srcdir=$(top_srcdir)/scripts/config
|
||||||
|
- include $(top_srcdir)/Rules.mak
|
||||||
|
|
||||||
|
all: ncurses conf mconf
|
||||||
|
|
||||||
|
--- 1,30 ----
|
||||||
|
# Makefile for BusyBox
|
||||||
|
#
|
||||||
|
# Copyright (C) 2002 Erik Andersen <andersen@codepoet.org>
|
||||||
|
+ # Modified by George Boudreau georgeb@LinuxFromScratch.org
|
||||||
|
+
|
||||||
|
+ top_srcdir=.
|
||||||
|
+ top_builddir=.
|
||||||
|
+ srcdir=$(top_srcdir)
|
||||||
|
+
|
||||||
|
+ # Select the compiler needed to build binaries for your development system
|
||||||
|
+ HOSTCC = gcc
|
||||||
|
+ HOSTCFLAGS= -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
|
||||||
|
+
|
||||||
|
+ # Ensure consistent sort order, 'gcc -print-search-dirs' behavior, etc.
|
||||||
|
+ LC_ALL:= C
|
||||||
|
+
|
||||||
|
+ SED ?= sed
|
||||||
|
+ SECHO := @-false
|
||||||
|
+ DISP := pur
|
||||||
|
+ Q := @
|
||||||
|
+
|
||||||
|
+ show_objs = $(subst $(top_builddir)/,,$(subst ../,,$@))
|
||||||
|
+ pur_disp_compile.h = echo " "HOSTCC $(show_objs)
|
||||||
|
+ disp_compile.h = $($(DISP)_disp_compile.h)
|
||||||
|
+ cmd_compile.h = $(HOSTCC) $(HOSTCFLAGS) -c -o $@ $<
|
||||||
|
+ compile.h = @$(disp_compile.h) ; $(cmd_compile.h)
|
||||||
|
|
||||||
|
|
||||||
|
all: ncurses conf mconf
|
||||||
|
|
||||||
|
diff -Npr menu-bb/mconf.c menu/mconf.c
|
||||||
|
*** menu-bb/mconf.c 2006-03-22 16:16:18.000000000 -0500
|
||||||
|
--- menu/mconf.c 2006-07-26 17:26:45.000000000 -0400
|
||||||
|
*************** static char menu_backtitle[128];
|
||||||
|
*** 32,38 ****
|
||||||
|
static const char mconf_readme[] =
|
||||||
|
"Overview\n"
|
||||||
|
"--------\n"
|
||||||
|
! "Some features may be built directly into BusyBox. Some features\n"
|
||||||
|
"may be completely removed altogether. There are also certain\n"
|
||||||
|
"parameters which are not really features, but must be\n"
|
||||||
|
"entered in as decimal or hexadecimal numbers or possibly text.\n"
|
||||||
|
--- 32,38 ----
|
||||||
|
static const char mconf_readme[] =
|
||||||
|
"Overview\n"
|
||||||
|
"--------\n"
|
||||||
|
! "Some features may be built directly into JHALFS. Some features\n"
|
||||||
|
"may be completely removed altogether. There are also certain\n"
|
||||||
|
"parameters which are not really features, but must be\n"
|
||||||
|
"entered in as decimal or hexadecimal numbers or possibly text.\n"
|
||||||
|
*************** load_config_text[] =
|
||||||
|
*** 194,204 ****
|
||||||
|
"last retrieved. Leave blank to abort.",
|
||||||
|
load_config_help[] =
|
||||||
|
"\n"
|
||||||
|
! "For various reasons, one may wish to keep several different BusyBox\n"
|
||||||
|
"configurations available on a single machine.\n"
|
||||||
|
"\n"
|
||||||
|
"If you have saved a previous configuration in a file other than the\n"
|
||||||
|
! "BusyBox's default, entering the name of the file here will allow you\n"
|
||||||
|
"to modify that configuration.\n"
|
||||||
|
"\n"
|
||||||
|
"If you are uncertain, then you have probably never used alternate\n"
|
||||||
|
--- 194,204 ----
|
||||||
|
"last retrieved. Leave blank to abort.",
|
||||||
|
load_config_help[] =
|
||||||
|
"\n"
|
||||||
|
! "For various reasons, one may wish to keep several different JHALFS\n"
|
||||||
|
"configurations available on a single machine.\n"
|
||||||
|
"\n"
|
||||||
|
"If you have saved a previous configuration in a file other than the\n"
|
||||||
|
! "JHALFS's default, entering the name of the file here will allow you\n"
|
||||||
|
"to modify that configuration.\n"
|
||||||
|
"\n"
|
||||||
|
"If you are uncertain, then you have probably never used alternate\n"
|
||||||
|
*************** save_config_text[] =
|
||||||
|
*** 208,214 ****
|
||||||
|
"as an alternate. Leave blank to abort.",
|
||||||
|
save_config_help[] =
|
||||||
|
"\n"
|
||||||
|
! "For various reasons, one may wish to keep different BusyBox\n"
|
||||||
|
"configurations available on a single machine.\n"
|
||||||
|
"\n"
|
||||||
|
"Entering a file name here will allow you to later retrieve, modify\n"
|
||||||
|
--- 208,214 ----
|
||||||
|
"as an alternate. Leave blank to abort.",
|
||||||
|
save_config_help[] =
|
||||||
|
"\n"
|
||||||
|
! "For various reasons, one may wish to keep different JHALFS\n"
|
||||||
|
"configurations available on a single machine.\n"
|
||||||
|
"\n"
|
||||||
|
"Entering a file name here will allow you to later retrieve, modify\n"
|
||||||
|
*************** int main(int ac, char **av)
|
||||||
|
*** 940,946 ****
|
||||||
|
|
||||||
|
sym = sym_lookup("VERSION", 0);
|
||||||
|
sym_calc_value(sym);
|
||||||
|
! snprintf(menu_backtitle, 128, "BusyBox v%s Configuration",
|
||||||
|
sym_get_string_value(sym));
|
||||||
|
|
||||||
|
mode = getenv("MENUCONFIG_MODE");
|
||||||
|
--- 940,946 ----
|
||||||
|
|
||||||
|
sym = sym_lookup("VERSION", 0);
|
||||||
|
sym_calc_value(sym);
|
||||||
|
! snprintf(menu_backtitle, 128, "JHALFS v%s Configuration",
|
||||||
|
sym_get_string_value(sym));
|
||||||
|
|
||||||
|
mode = getenv("MENUCONFIG_MODE");
|
||||||
|
*************** int main(int ac, char **av)
|
||||||
|
*** 961,976 ****
|
||||||
|
init_dialog();
|
||||||
|
do {
|
||||||
|
stat = dialog_yesno(NULL,
|
||||||
|
! "Do you wish to save your new BusyBox configuration?", 5, 60);
|
||||||
|
} while (stat < 0);
|
||||||
|
end_dialog();
|
||||||
|
|
||||||
|
if (stat == 0) {
|
||||||
|
conf_write(NULL);
|
||||||
|
printf("\n"
|
||||||
|
! "*** End of BusyBox configuration.\n");
|
||||||
|
} else
|
||||||
|
! printf("\n\nYour BusyBox configuration changes were NOT saved.\n\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
--- 961,976 ----
|
||||||
|
init_dialog();
|
||||||
|
do {
|
||||||
|
stat = dialog_yesno(NULL,
|
||||||
|
! "Do you wish to save your new JHALFS configuration?", 5, 60);
|
||||||
|
} while (stat < 0);
|
||||||
|
end_dialog();
|
||||||
|
|
||||||
|
if (stat == 0) {
|
||||||
|
conf_write(NULL);
|
||||||
|
printf("\n"
|
||||||
|
! "*** End of JHALFS configuration.\n");
|
||||||
|
} else
|
||||||
|
! printf("\n\nYour JHALFS configuration changes were NOT saved.\n\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff -Npr menu-bb/zconf.tab.c_shipped menu/zconf.tab.c_shipped
|
||||||
|
*** menu-bb/zconf.tab.c_shipped 2006-03-22 16:16:18.000000000 -0500
|
||||||
|
--- menu/zconf.tab.c_shipped 2006-07-26 17:26:45.000000000 -0400
|
||||||
|
*************** void conf_parse(const char *name)
|
||||||
|
*** 1925,1931 ****
|
||||||
|
sym_init();
|
||||||
|
menu_init();
|
||||||
|
modules_sym = sym_lookup("MODULES", 0);
|
||||||
|
! rootmenu.prompt = menu_add_prop(P_MENU, "BusyBox Configuration", NULL, NULL);
|
||||||
|
|
||||||
|
//zconfdebug = 1;
|
||||||
|
zconfparse();
|
||||||
|
--- 1925,1931 ----
|
||||||
|
sym_init();
|
||||||
|
menu_init();
|
||||||
|
modules_sym = sym_lookup("MODULES", 0);
|
||||||
|
! rootmenu.prompt = menu_add_prop(P_MENU, "JHALFS Configuration", NULL, NULL);
|
||||||
|
|
||||||
|
//zconfdebug = 1;
|
||||||
|
zconfparse();
|
||||||
|
diff -Npr menu-bb/zconf.y menu/zconf.y
|
||||||
|
*** menu-bb/zconf.y 2006-03-22 16:16:18.000000000 -0500
|
||||||
|
--- menu/zconf.y 2006-07-26 17:26:45.000000000 -0400
|
||||||
|
*************** void conf_parse(const char *name)
|
||||||
|
*** 487,493 ****
|
||||||
|
sym_init();
|
||||||
|
menu_init();
|
||||||
|
modules_sym = sym_lookup("MODULES", 0);
|
||||||
|
! rootmenu.prompt = menu_add_prop(P_MENU, "BusyBox Configuration", NULL, NULL);
|
||||||
|
|
||||||
|
//zconfdebug = 1;
|
||||||
|
zconfparse();
|
||||||
|
--- 487,493 ----
|
||||||
|
sym_init();
|
||||||
|
menu_init();
|
||||||
|
modules_sym = sym_lookup("MODULES", 0);
|
||||||
|
! rootmenu.prompt = menu_add_prop(P_MENU, "JHALFS Configuration", NULL, NULL);
|
||||||
|
|
||||||
|
//zconfdebug = 1;
|
||||||
|
zconfparse();
|
255
menu/Kconfig-language.txt
Normal file
255
menu/Kconfig-language.txt
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
The configuration database is collection of configuration options
|
||||||
|
organized in a tree structure:
|
||||||
|
|
||||||
|
+- Code maturity level options
|
||||||
|
| +- Prompt for development and/or incomplete code/drivers
|
||||||
|
+- General setup
|
||||||
|
| +- Networking support
|
||||||
|
| +- System V IPC
|
||||||
|
| +- BSD Process Accounting
|
||||||
|
| +- Sysctl support
|
||||||
|
+- Loadable module support
|
||||||
|
| +- Enable loadable module support
|
||||||
|
| +- Set version information on all module symbols
|
||||||
|
| +- Kernel module loader
|
||||||
|
+- ...
|
||||||
|
|
||||||
|
Every entry has its own dependencies. These dependencies are used
|
||||||
|
to determine the visible of an entry. Any child entry is only
|
||||||
|
visible if its parent entry is also visible.
|
||||||
|
|
||||||
|
Menu entries
|
||||||
|
------------
|
||||||
|
|
||||||
|
Most entries define a config option, all other entries help to organize
|
||||||
|
them. A single configuration option is defined like this:
|
||||||
|
|
||||||
|
config MODVERSIONS
|
||||||
|
bool "Set version information on all module symbols"
|
||||||
|
depends MODULES
|
||||||
|
help
|
||||||
|
Usually, modules have to be recompiled whenever you switch to a new
|
||||||
|
kernel. ...
|
||||||
|
|
||||||
|
Every line starts with a key word and can be followed by multiple
|
||||||
|
arguments. "config" starts a new config entry. The following lines
|
||||||
|
define attributes for this config option. Attributes can be the type of
|
||||||
|
the config option, input prompt, dependencies, help text and default
|
||||||
|
values. A config option can be defined multiple times with the same
|
||||||
|
name, but every definition can have only a single input prompt and the
|
||||||
|
type must not conflict.
|
||||||
|
|
||||||
|
Menu attributes
|
||||||
|
---------------
|
||||||
|
|
||||||
|
A menu entry can have a number of attributes. Not all of them are
|
||||||
|
applicable everywhere (see syntax).
|
||||||
|
|
||||||
|
- type definition: "bool"/"tristate"/"string"/"hex"/"integer"
|
||||||
|
Every config option must have a type. There are only two basic types:
|
||||||
|
tristate and string, the other types base on these two. The type
|
||||||
|
definition optionally accepts an input prompt, so these two examples
|
||||||
|
are equivalent:
|
||||||
|
|
||||||
|
bool "Networking support"
|
||||||
|
and
|
||||||
|
bool
|
||||||
|
prompt "Networking support"
|
||||||
|
|
||||||
|
- input prompt: "prompt" <prompt> ["if" <expr>]
|
||||||
|
Every menu entry can have at most one prompt, which is used to display
|
||||||
|
to the user. Optionally dependencies only for this prompt can be added
|
||||||
|
with "if".
|
||||||
|
|
||||||
|
- default value: "default" <symbol> ["if" <expr>]
|
||||||
|
A config option can have any number of default values. If multiple
|
||||||
|
default values are visible, only the first defined one is active.
|
||||||
|
Default values are not limited to the menu entry, where they are
|
||||||
|
defined, this means the default can be defined somewhere else or be
|
||||||
|
overriden by an earlier definition.
|
||||||
|
The default value is only assigned to the config symbol if no other
|
||||||
|
value was set by the user (via the input prompt above). If an input
|
||||||
|
prompt is visible the default value is presented to the user and can
|
||||||
|
be overridden by him.
|
||||||
|
Optionally dependencies only for this default value can be added with
|
||||||
|
"if".
|
||||||
|
|
||||||
|
- dependencies: "depends on"/"requires" <expr>
|
||||||
|
This defines a dependency for this menu entry. If multiple
|
||||||
|
dependencies are defined they are connected with '&&'. Dependencies
|
||||||
|
are applied to all other options within this menu entry (which also
|
||||||
|
accept "if" expression), so these two examples are equivalent:
|
||||||
|
|
||||||
|
bool "foo" if BAR
|
||||||
|
default y if BAR
|
||||||
|
and
|
||||||
|
depends on BAR
|
||||||
|
bool "foo"
|
||||||
|
default y
|
||||||
|
|
||||||
|
- help text: "help"
|
||||||
|
This defines a help text. The end of the help text is determined by
|
||||||
|
the level indentation, this means it ends at the first line which has
|
||||||
|
a smaller indentation than the first line of the help text.
|
||||||
|
|
||||||
|
|
||||||
|
Menu dependencies
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Dependencies define the visibility of a menu entry and can also reduce
|
||||||
|
the input range of tristate symbols. The tristate logic used in the
|
||||||
|
expressions uses one more state than normal boolean logic to express the
|
||||||
|
module state. Dependency expressions have the following syntax:
|
||||||
|
|
||||||
|
<expr> ::= <symbol> (1)
|
||||||
|
<symbol> '=' <symbol> (2)
|
||||||
|
<symbol> '!=' <symbol> (3)
|
||||||
|
'(' <expr> ')' (4)
|
||||||
|
'!' <expr> (5)
|
||||||
|
<expr> '||' <expr> (6)
|
||||||
|
<expr> '&&' <expr> (7)
|
||||||
|
|
||||||
|
Expressions are listed in decreasing order of precedence.
|
||||||
|
|
||||||
|
(1) Convert the symbol into an expression. Boolean and tristate symbols
|
||||||
|
are simply converted into the respective expression values. All
|
||||||
|
other symbol types result in 'n'.
|
||||||
|
(2) If the values of both symbols are equal, it returns 'y',
|
||||||
|
otherwise 'n'.
|
||||||
|
(3) If the values of both symbols are equal, it returns 'n',
|
||||||
|
otherwise 'y'.
|
||||||
|
(4) Returns the value of the expression. Used to override precedence.
|
||||||
|
(5) Returns the result of (2-/expr/).
|
||||||
|
(6) Returns the result of min(/expr/, /expr/).
|
||||||
|
(7) Returns the result of max(/expr/, /expr/).
|
||||||
|
|
||||||
|
An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2
|
||||||
|
respectively for calculations). A menu entry becomes visible when it's
|
||||||
|
expression evaluates to 'm' or 'y'.
|
||||||
|
|
||||||
|
There are two type of symbols: constant and nonconstant symbols.
|
||||||
|
Nonconstant symbols are the most common ones and are defined with the
|
||||||
|
'config' statement. Nonconstant symbols consist entirely of alphanumeric
|
||||||
|
characters or underscores.
|
||||||
|
Constant symbols are only part of expressions. Constant symbols are
|
||||||
|
always surrounded by single or double quotes. Within the quote any
|
||||||
|
other character is allowed and the quotes can be escaped using '\'.
|
||||||
|
|
||||||
|
Menu structure
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The position of a menu entry in the tree is determined in two ways. First
|
||||||
|
it can be specified explicitely:
|
||||||
|
|
||||||
|
menu "Network device support"
|
||||||
|
depends NET
|
||||||
|
|
||||||
|
config NETDEVICES
|
||||||
|
...
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
All entries within the "menu" ... "endmenu" block become a submenu of
|
||||||
|
"Network device support". All subentries inherit the dependencies from
|
||||||
|
the menu entry, e.g. this means the dependency "NET" is added to the
|
||||||
|
dependency list of the config option NETDEVICES.
|
||||||
|
|
||||||
|
The other way to generate the menu structure is done by analyzing the
|
||||||
|
dependencies. If a menu entry somehow depends on the previous entry, it
|
||||||
|
can be made a submenu of it. First the the previous (parent) symbol must
|
||||||
|
be part of the dependency list and then one of these two condititions
|
||||||
|
must be true:
|
||||||
|
- the child entry must become invisible, if the parent is set to 'n'
|
||||||
|
- the child entry must only be visible, if the parent is visible
|
||||||
|
|
||||||
|
config MODULES
|
||||||
|
bool "Enable loadable module support"
|
||||||
|
|
||||||
|
config MODVERSIONS
|
||||||
|
bool "Set version information on all module symbols"
|
||||||
|
depends MODULES
|
||||||
|
|
||||||
|
comment "module support disabled"
|
||||||
|
depends !MODULES
|
||||||
|
|
||||||
|
MODVERSIONS directly depends on MODULES, this means it's only visible if
|
||||||
|
MODULES is different from 'n'. The comment on the other hand is always
|
||||||
|
visible when MODULES it's visible (the (empty) dependency of MODULES is
|
||||||
|
also part of the comment dependencies).
|
||||||
|
|
||||||
|
|
||||||
|
Kconfig syntax
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The configuration file describes a series of menu entries, where every
|
||||||
|
line starts with a keyword (except help texts). The following keywords
|
||||||
|
end a menu entry:
|
||||||
|
- config
|
||||||
|
- choice/endchoice
|
||||||
|
- comment
|
||||||
|
- menu/endmenu
|
||||||
|
- if/endif
|
||||||
|
- source
|
||||||
|
The first four also start the definition of a menu entry.
|
||||||
|
|
||||||
|
config:
|
||||||
|
|
||||||
|
"config" <symbol>
|
||||||
|
<config options>
|
||||||
|
|
||||||
|
This defines a config symbol <symbol> and accepts any of above
|
||||||
|
attributes as options.
|
||||||
|
|
||||||
|
choices:
|
||||||
|
|
||||||
|
"choice"
|
||||||
|
<choice options>
|
||||||
|
<choice block>
|
||||||
|
"endchoice"
|
||||||
|
|
||||||
|
This defines a choice group and accepts any of above attributes as
|
||||||
|
options. A choice can only be of type bool or tristate, while a boolean
|
||||||
|
choice only allows a single config entry to be selected, a tristate
|
||||||
|
choice also allows any number of config entries to be set to 'm'. This
|
||||||
|
can be used if multiple drivers for a single hardware exists and only a
|
||||||
|
single driver can be compiled/loaded into the kernel, but all drivers
|
||||||
|
can be compiled as modules.
|
||||||
|
A choice accepts another option "optional", which allows to set the
|
||||||
|
choice to 'n' and no entry needs to be selected.
|
||||||
|
|
||||||
|
comment:
|
||||||
|
|
||||||
|
"comment" <prompt>
|
||||||
|
<comment options>
|
||||||
|
|
||||||
|
This defines a comment which is displayed to the user during the
|
||||||
|
configuration process and is also echoed to the output files. The only
|
||||||
|
possible options are dependencies.
|
||||||
|
|
||||||
|
menu:
|
||||||
|
|
||||||
|
"menu" <prompt>
|
||||||
|
<menu options>
|
||||||
|
<menu block>
|
||||||
|
"endmenu"
|
||||||
|
|
||||||
|
This defines a menu block, see "Menu structure" above for more
|
||||||
|
information. The only possible options are dependencies.
|
||||||
|
|
||||||
|
if:
|
||||||
|
|
||||||
|
"if" <expr>
|
||||||
|
<if block>
|
||||||
|
"endif"
|
||||||
|
|
||||||
|
This defines an if block. The dependency expression <expr> is appended
|
||||||
|
to all enclosed menu entries.
|
||||||
|
|
||||||
|
source:
|
||||||
|
|
||||||
|
"source" <prompt>
|
||||||
|
|
||||||
|
This reads the specified configuration file. This file is always parsed.
|
141
menu/Makefile
Normal file
141
menu/Makefile
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
# Makefile for BusyBox
|
||||||
|
#
|
||||||
|
# Copyright (C) 2002 Erik Andersen <andersen@codepoet.org>
|
||||||
|
# Modified by George Boudreau georgeb@LinuxFromScratch.org
|
||||||
|
|
||||||
|
top_srcdir=.
|
||||||
|
top_builddir=.
|
||||||
|
srcdir=$(top_srcdir)
|
||||||
|
|
||||||
|
# Select the compiler needed to build binaries for your development system
|
||||||
|
HOSTCC = gcc
|
||||||
|
HOSTCFLAGS= -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
|
||||||
|
|
||||||
|
# Ensure consistent sort order, 'gcc -print-search-dirs' behavior, etc.
|
||||||
|
LC_ALL:= C
|
||||||
|
|
||||||
|
SED ?= sed
|
||||||
|
SECHO := @-false
|
||||||
|
DISP := pur
|
||||||
|
Q := @
|
||||||
|
|
||||||
|
show_objs = $(subst $(top_builddir)/,,$(subst ../,,$@))
|
||||||
|
pur_disp_compile.h = echo " "HOSTCC $(show_objs)
|
||||||
|
disp_compile.h = $($(DISP)_disp_compile.h)
|
||||||
|
cmd_compile.h = $(HOSTCC) $(HOSTCFLAGS) -c -o $@ $<
|
||||||
|
compile.h = @$(disp_compile.h) ; $(cmd_compile.h)
|
||||||
|
|
||||||
|
|
||||||
|
all: ncurses conf mconf
|
||||||
|
|
||||||
|
ifeq ($(shell uname),SunOS)
|
||||||
|
LIBS = -lcurses
|
||||||
|
else
|
||||||
|
LIBS = -lncurses
|
||||||
|
endif
|
||||||
|
ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
|
||||||
|
HOSTNCURSES += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
|
||||||
|
else
|
||||||
|
ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
|
||||||
|
HOSTNCURSES += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
|
||||||
|
else
|
||||||
|
ifeq (/usr/local/include/ncurses/ncurses.h, $(wildcard /usr/local/include/ncurses/ncurses.h))
|
||||||
|
HOSTCFLAGS += -I/usr/local/include/ncurses -DCURSES_LOC="<ncurses.h>"
|
||||||
|
else
|
||||||
|
ifeq (/usr/local/include/ncurses/curses.h, $(wildcard /usr/local/include/ncurses/curses.h))
|
||||||
|
HOSTCFLAGS += -I/usr/local/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
|
||||||
|
else
|
||||||
|
ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
|
||||||
|
HOSTNCURSES += -DCURSES_LOC="<ncurses.h>"
|
||||||
|
else
|
||||||
|
HOSTNCURSES += -DCURSES_LOC="<curses.h>"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
CONF_SRC = conf.c
|
||||||
|
MCONF_SRC = mconf.c
|
||||||
|
LXD_SRC = lxdialog/checklist.c lxdialog/menubox.c lxdialog/textbox.c \
|
||||||
|
lxdialog/yesno.c lxdialog/inputbox.c lxdialog/util.c \
|
||||||
|
lxdialog/msgbox.c
|
||||||
|
|
||||||
|
SHARED_SRC = zconf.tab.c
|
||||||
|
SHARED_DEPS := $(srcdir)/lkc.h $(srcdir)/lkc_proto.h \
|
||||||
|
lkc_defs.h $(srcdir)/expr.h zconf.tab.h
|
||||||
|
CONF_OBJS = $(patsubst %.c,%.o, $(CONF_SRC))
|
||||||
|
MCONF_OBJS = $(patsubst %.c,%.o, $(MCONF_SRC) $(LXD_SRC))
|
||||||
|
SHARED_OBJS = $(patsubst %.c,%.o, $(SHARED_SRC))
|
||||||
|
|
||||||
|
conf: $(CONF_OBJS) $(SHARED_OBJS)
|
||||||
|
$(SECHO) " "HOSTCC $@ ; true
|
||||||
|
$(Q)$(HOSTCC) $(NATIVE_LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
mconf: $(MCONF_OBJS) $(SHARED_OBJS)
|
||||||
|
$(SECHO) " "HOSTCC $@ ; true
|
||||||
|
$(Q)$(HOSTCC) $(NATIVE_LDFLAGS) $^ -o $@ $(LIBS)
|
||||||
|
|
||||||
|
$(CONF_OBJS): %.o : $(srcdir)/%.c $(SHARED_DEPS)
|
||||||
|
$(compile.h) -I.
|
||||||
|
|
||||||
|
$(MCONF_OBJS): %.o : $(srcdir)/%.c $(SHARED_DEPS)
|
||||||
|
@[ -d $(@D) ] || mkdir $(@D)
|
||||||
|
$(compile.h) $(HOSTNCURSES) -I.
|
||||||
|
|
||||||
|
lkc_defs.h: $(srcdir)/lkc_proto.h
|
||||||
|
@$(SED) < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
|
||||||
|
|
||||||
|
###
|
||||||
|
# The following requires flex/bison
|
||||||
|
# By default we use the _shipped versions, uncomment the
|
||||||
|
# following line if you are modifying the flex/bison src.
|
||||||
|
#LKC_GENPARSER := 1
|
||||||
|
|
||||||
|
ifdef LKC_GENPARSER
|
||||||
|
|
||||||
|
%.tab.c %.tab.h: $(srcdir)/%.y
|
||||||
|
bison -t -d -v -b $* -p $(notdir $*) $<
|
||||||
|
|
||||||
|
lex.%.c: $(srcdir)/%.l
|
||||||
|
flex -P$(notdir $*) -o$@ $<
|
||||||
|
else
|
||||||
|
|
||||||
|
lex.zconf.o: lex.zconf.c $(SHARED_DEPS)
|
||||||
|
$(compile.h) -I$(srcdir)
|
||||||
|
|
||||||
|
lex.zconf.c: $(srcdir)/lex.zconf.c_shipped
|
||||||
|
$(Q)cp $< $@
|
||||||
|
|
||||||
|
zconf.tab.c: $(srcdir)/zconf.tab.c_shipped
|
||||||
|
$(Q)cp $< $@
|
||||||
|
|
||||||
|
zconf.tab.h: $(srcdir)/zconf.tab.h_shipped
|
||||||
|
$(Q)cp $< $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
zconf.tab.o: zconf.tab.c lex.zconf.c $(srcdir)/confdata.c $(srcdir)/expr.c \
|
||||||
|
$(srcdir)/symbol.c $(srcdir)/menu.c $(SHARED_DEPS)
|
||||||
|
$(compile.h) -I$(srcdir) -I.
|
||||||
|
|
||||||
|
.PHONY: ncurses
|
||||||
|
|
||||||
|
ncurses:
|
||||||
|
@echo "main() {}" > lxtemp.c
|
||||||
|
@if $(HOSTCC) lxtemp.c $(LIBS) ; 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 *.o *~ core $(TARGETS) $(MCONF_OBJS) $(CONF_OBJS) \
|
||||||
|
conf mconf zconf.tab.c zconf.tab.h lex.zconf.c lkc_defs.h
|
||||||
|
|
573
menu/conf.c
Normal file
573
menu/conf.c
Normal file
|
@ -0,0 +1,573 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||||
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#define LKC_DIRECT_LINK
|
||||||
|
#include "lkc.h"
|
||||||
|
|
||||||
|
static void conf(struct menu *menu);
|
||||||
|
static void check_conf(struct menu *menu);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ask_all,
|
||||||
|
ask_new,
|
||||||
|
ask_silent,
|
||||||
|
set_default,
|
||||||
|
set_yes,
|
||||||
|
set_mod,
|
||||||
|
set_no,
|
||||||
|
set_random
|
||||||
|
} input_mode = ask_all;
|
||||||
|
char *defconfig_file;
|
||||||
|
|
||||||
|
static int indent = 1;
|
||||||
|
static int valid_stdin = 1;
|
||||||
|
static int conf_cnt;
|
||||||
|
static char line[128];
|
||||||
|
static struct menu *rootEntry;
|
||||||
|
|
||||||
|
static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
|
||||||
|
|
||||||
|
static void strip(char *str)
|
||||||
|
{
|
||||||
|
char *p = str;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
while ((isspace(*p)))
|
||||||
|
p++;
|
||||||
|
l = strlen(p);
|
||||||
|
if (p != str)
|
||||||
|
memmove(str, p, l + 1);
|
||||||
|
if (!l)
|
||||||
|
return;
|
||||||
|
p = str + l - 1;
|
||||||
|
while ((isspace(*p)))
|
||||||
|
*p-- = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_stdin(void)
|
||||||
|
{
|
||||||
|
if (!valid_stdin && input_mode == ask_silent) {
|
||||||
|
printf("aborted!\n\n");
|
||||||
|
printf("Console input/output is redirected. ");
|
||||||
|
printf("Run 'make oldconfig' to update configuration.\n\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void conf_askvalue(struct symbol *sym, const char *def)
|
||||||
|
{
|
||||||
|
enum symbol_type type = sym_get_type(sym);
|
||||||
|
tristate val;
|
||||||
|
|
||||||
|
if (!sym_has_value(sym))
|
||||||
|
printf("(NEW) ");
|
||||||
|
|
||||||
|
line[0] = '\n';
|
||||||
|
line[1] = 0;
|
||||||
|
|
||||||
|
if (!sym_is_changable(sym)) {
|
||||||
|
printf("%s\n", def);
|
||||||
|
line[0] = '\n';
|
||||||
|
line[1] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (input_mode) {
|
||||||
|
case ask_new:
|
||||||
|
case ask_silent:
|
||||||
|
if (sym_has_value(sym)) {
|
||||||
|
printf("%s\n", def);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
check_stdin();
|
||||||
|
case ask_all:
|
||||||
|
fflush(stdout);
|
||||||
|
fgets(line, 128, stdin);
|
||||||
|
return;
|
||||||
|
case set_default:
|
||||||
|
printf("%s\n", def);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case S_INT:
|
||||||
|
case S_HEX:
|
||||||
|
case S_STRING:
|
||||||
|
printf("%s\n", def);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
switch (input_mode) {
|
||||||
|
case set_yes:
|
||||||
|
if (sym_tristate_within_range(sym, yes)) {
|
||||||
|
line[0] = 'y';
|
||||||
|
line[1] = '\n';
|
||||||
|
line[2] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case set_mod:
|
||||||
|
if (type == S_TRISTATE) {
|
||||||
|
if (sym_tristate_within_range(sym, mod)) {
|
||||||
|
line[0] = 'm';
|
||||||
|
line[1] = '\n';
|
||||||
|
line[2] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (sym_tristate_within_range(sym, yes)) {
|
||||||
|
line[0] = 'y';
|
||||||
|
line[1] = '\n';
|
||||||
|
line[2] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case set_no:
|
||||||
|
if (sym_tristate_within_range(sym, no)) {
|
||||||
|
line[0] = 'n';
|
||||||
|
line[1] = '\n';
|
||||||
|
line[2] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case set_random:
|
||||||
|
do {
|
||||||
|
val = (tristate)(random() % 3);
|
||||||
|
} while (!sym_tristate_within_range(sym, val));
|
||||||
|
switch (val) {
|
||||||
|
case no: line[0] = 'n'; break;
|
||||||
|
case mod: line[0] = 'm'; break;
|
||||||
|
case yes: line[0] = 'y'; break;
|
||||||
|
}
|
||||||
|
line[1] = '\n';
|
||||||
|
line[2] = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("%s", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
int conf_string(struct menu *menu)
|
||||||
|
{
|
||||||
|
struct symbol *sym = menu->sym;
|
||||||
|
const char *def, *help;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
printf("%*s%s ", indent - 1, "", menu->prompt->text);
|
||||||
|
printf("(%s) ", sym->name);
|
||||||
|
def = sym_get_string_value(sym);
|
||||||
|
if (sym_get_string_value(sym))
|
||||||
|
printf("[%s] ", def);
|
||||||
|
conf_askvalue(sym, def);
|
||||||
|
switch (line[0]) {
|
||||||
|
case '\n':
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
/* print help */
|
||||||
|
if (line[1] == '\n') {
|
||||||
|
help = nohelp_text;
|
||||||
|
if (menu->sym->help)
|
||||||
|
help = menu->sym->help;
|
||||||
|
printf("\n%s\n", menu->sym->help);
|
||||||
|
def = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
line[strlen(line)-1] = 0;
|
||||||
|
def = line;
|
||||||
|
}
|
||||||
|
if (def && sym_set_string_value(sym, def))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int conf_sym(struct menu *menu)
|
||||||
|
{
|
||||||
|
struct symbol *sym = menu->sym;
|
||||||
|
int type;
|
||||||
|
tristate oldval, newval;
|
||||||
|
const char *help;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
printf("%*s%s ", indent - 1, "", menu->prompt->text);
|
||||||
|
if (sym->name)
|
||||||
|
printf("(%s) ", sym->name);
|
||||||
|
type = sym_get_type(sym);
|
||||||
|
putchar('[');
|
||||||
|
oldval = sym_get_tristate_value(sym);
|
||||||
|
switch (oldval) {
|
||||||
|
case no:
|
||||||
|
putchar('N');
|
||||||
|
break;
|
||||||
|
case mod:
|
||||||
|
putchar('M');
|
||||||
|
break;
|
||||||
|
case yes:
|
||||||
|
putchar('Y');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (oldval != no && sym_tristate_within_range(sym, no))
|
||||||
|
printf("/n");
|
||||||
|
if (oldval != mod && sym_tristate_within_range(sym, mod))
|
||||||
|
printf("/m");
|
||||||
|
if (oldval != yes && sym_tristate_within_range(sym, yes))
|
||||||
|
printf("/y");
|
||||||
|
if (sym->help)
|
||||||
|
printf("/?");
|
||||||
|
printf("] ");
|
||||||
|
conf_askvalue(sym, sym_get_string_value(sym));
|
||||||
|
strip(line);
|
||||||
|
|
||||||
|
switch (line[0]) {
|
||||||
|
case 'n':
|
||||||
|
case 'N':
|
||||||
|
newval = no;
|
||||||
|
if (!line[1] || !strcmp(&line[1], "o"))
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
newval = mod;
|
||||||
|
if (!line[1])
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
case 'y':
|
||||||
|
case 'Y':
|
||||||
|
newval = yes;
|
||||||
|
if (!line[1] || !strcmp(&line[1], "es"))
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
case 0:
|
||||||
|
newval = oldval;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
goto help;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sym_set_tristate_value(sym, newval))
|
||||||
|
return 0;
|
||||||
|
help:
|
||||||
|
help = nohelp_text;
|
||||||
|
if (sym->help)
|
||||||
|
help = sym->help;
|
||||||
|
printf("\n%s\n", help);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int conf_choice(struct menu *menu)
|
||||||
|
{
|
||||||
|
struct symbol *sym, *def_sym;
|
||||||
|
struct menu *child;
|
||||||
|
int type;
|
||||||
|
bool is_new;
|
||||||
|
|
||||||
|
sym = menu->sym;
|
||||||
|
type = sym_get_type(sym);
|
||||||
|
is_new = !sym_has_value(sym);
|
||||||
|
if (sym_is_changable(sym)) {
|
||||||
|
conf_sym(menu);
|
||||||
|
sym_calc_value(sym);
|
||||||
|
switch (sym_get_tristate_value(sym)) {
|
||||||
|
case no:
|
||||||
|
return 1;
|
||||||
|
case mod:
|
||||||
|
return 0;
|
||||||
|
case yes:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (sym_get_tristate_value(sym)) {
|
||||||
|
case no:
|
||||||
|
return 1;
|
||||||
|
case mod:
|
||||||
|
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
|
||||||
|
return 0;
|
||||||
|
case yes:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int cnt, def;
|
||||||
|
|
||||||
|
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
|
||||||
|
def_sym = sym_get_choice_value(sym);
|
||||||
|
cnt = def = 0;
|
||||||
|
line[0] = '0';
|
||||||
|
line[1] = 0;
|
||||||
|
for (child = menu->list; child; child = child->next) {
|
||||||
|
if (!menu_is_visible(child))
|
||||||
|
continue;
|
||||||
|
if (!child->sym) {
|
||||||
|
printf("%*c %s\n", indent, '*', menu_get_prompt(child));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cnt++;
|
||||||
|
if (child->sym == def_sym) {
|
||||||
|
def = cnt;
|
||||||
|
printf("%*c", indent, '>');
|
||||||
|
} else
|
||||||
|
printf("%*c", indent, ' ');
|
||||||
|
printf(" %d. %s", cnt, menu_get_prompt(child));
|
||||||
|
if (child->sym->name)
|
||||||
|
printf(" (%s)", child->sym->name);
|
||||||
|
if (!sym_has_value(child->sym))
|
||||||
|
printf(" (NEW)");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("%*schoice", indent - 1, "");
|
||||||
|
if (cnt == 1) {
|
||||||
|
printf("[1]: 1\n");
|
||||||
|
goto conf_childs;
|
||||||
|
}
|
||||||
|
printf("[1-%d", cnt);
|
||||||
|
if (sym->help)
|
||||||
|
printf("?");
|
||||||
|
printf("]: ");
|
||||||
|
switch (input_mode) {
|
||||||
|
case ask_new:
|
||||||
|
case ask_silent:
|
||||||
|
if (!is_new) {
|
||||||
|
cnt = def;
|
||||||
|
printf("%d\n", cnt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
check_stdin();
|
||||||
|
case ask_all:
|
||||||
|
fflush(stdout);
|
||||||
|
fgets(line, 128, stdin);
|
||||||
|
strip(line);
|
||||||
|
if (line[0] == '?') {
|
||||||
|
printf("\n%s\n", menu->sym->help ?
|
||||||
|
menu->sym->help : nohelp_text);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!line[0])
|
||||||
|
cnt = def;
|
||||||
|
else if (isdigit(line[0]))
|
||||||
|
cnt = atoi(line);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case set_random:
|
||||||
|
def = (random() % cnt) + 1;
|
||||||
|
case set_default:
|
||||||
|
case set_yes:
|
||||||
|
case set_mod:
|
||||||
|
case set_no:
|
||||||
|
cnt = def;
|
||||||
|
printf("%d\n", cnt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf_childs:
|
||||||
|
for (child = menu->list; child; child = child->next) {
|
||||||
|
if (!child->sym || !menu_is_visible(child))
|
||||||
|
continue;
|
||||||
|
if (!--cnt)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!child)
|
||||||
|
continue;
|
||||||
|
if (line[strlen(line) - 1] == '?') {
|
||||||
|
printf("\n%s\n", child->sym->help ?
|
||||||
|
child->sym->help : nohelp_text);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sym_set_choice_value(sym, child->sym);
|
||||||
|
if (child->list) {
|
||||||
|
indent += 2;
|
||||||
|
conf(child->list);
|
||||||
|
indent -= 2;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void conf(struct menu *menu)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
struct property *prop;
|
||||||
|
struct menu *child;
|
||||||
|
|
||||||
|
if (!menu_is_visible(menu))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sym = menu->sym;
|
||||||
|
prop = menu->prompt;
|
||||||
|
if (prop) {
|
||||||
|
const char *prompt;
|
||||||
|
|
||||||
|
switch (prop->type) {
|
||||||
|
case P_MENU:
|
||||||
|
if (input_mode == ask_silent && rootEntry != menu) {
|
||||||
|
check_conf(menu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case P_COMMENT:
|
||||||
|
prompt = menu_get_prompt(menu);
|
||||||
|
if (prompt)
|
||||||
|
printf("%*c\n%*c %s\n%*c\n",
|
||||||
|
indent, '*',
|
||||||
|
indent, '*', prompt,
|
||||||
|
indent, '*');
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sym)
|
||||||
|
goto conf_childs;
|
||||||
|
|
||||||
|
if (sym_is_choice(sym)) {
|
||||||
|
conf_choice(menu);
|
||||||
|
if (sym->curr.tri != mod)
|
||||||
|
return;
|
||||||
|
goto conf_childs;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_INT:
|
||||||
|
case S_HEX:
|
||||||
|
case S_STRING:
|
||||||
|
conf_string(menu);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
conf_sym(menu);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf_childs:
|
||||||
|
if (sym)
|
||||||
|
indent += 2;
|
||||||
|
for (child = menu->list; child; child = child->next)
|
||||||
|
conf(child);
|
||||||
|
if (sym)
|
||||||
|
indent -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_conf(struct menu *menu)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
struct menu *child;
|
||||||
|
|
||||||
|
if (!menu_is_visible(menu))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sym = menu->sym;
|
||||||
|
if (sym) {
|
||||||
|
if (sym_is_changable(sym) && !sym_has_value(sym)) {
|
||||||
|
if (!conf_cnt++)
|
||||||
|
printf("*\n* Restart config...\n*\n");
|
||||||
|
rootEntry = menu_get_parent_menu(menu);
|
||||||
|
conf(rootEntry);
|
||||||
|
}
|
||||||
|
if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (child = menu->list; child; child = child->next)
|
||||||
|
check_conf(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int ac, char **av)
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
const char *name;
|
||||||
|
struct stat tmpstat;
|
||||||
|
|
||||||
|
if (ac > i && av[i][0] == '-') {
|
||||||
|
switch (av[i++][1]) {
|
||||||
|
case 'o':
|
||||||
|
input_mode = ask_new;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
input_mode = ask_silent;
|
||||||
|
valid_stdin = isatty(0) && isatty(1) && isatty(2);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
input_mode = set_default;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
input_mode = set_default;
|
||||||
|
defconfig_file = av[i++];
|
||||||
|
if (!defconfig_file) {
|
||||||
|
printf("%s: No default config file specified\n",
|
||||||
|
av[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
input_mode = set_no;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
input_mode = set_mod;
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
input_mode = set_yes;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
input_mode = set_random;
|
||||||
|
srandom(time(NULL));
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
case '?':
|
||||||
|
printf("%s [-o|-s] config\n", av[0]);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name = av[i];
|
||||||
|
if (!name) {
|
||||||
|
printf("%s: configuration file missing\n", av[0]);
|
||||||
|
}
|
||||||
|
conf_parse(name);
|
||||||
|
//zconfdump(stdout);
|
||||||
|
switch (input_mode) {
|
||||||
|
case ask_silent:
|
||||||
|
if (stat(".config", &tmpstat)) {
|
||||||
|
printf("***\n"
|
||||||
|
"*** You have not yet configured JHALFS!\n"
|
||||||
|
"***\n"
|
||||||
|
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
|
||||||
|
"*** \"make menuconfig\" or \"make config\").\n"
|
||||||
|
"***\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
case ask_all:
|
||||||
|
case ask_new:
|
||||||
|
conf_read(NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_mode != ask_silent) {
|
||||||
|
rootEntry = &rootmenu;
|
||||||
|
conf(&rootmenu);
|
||||||
|
if (input_mode == ask_all) {
|
||||||
|
input_mode = ask_silent;
|
||||||
|
valid_stdin = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
conf_cnt = 0;
|
||||||
|
check_conf(&rootmenu);
|
||||||
|
} while (conf_cnt);
|
||||||
|
if (conf_write(NULL)) {
|
||||||
|
fprintf(stderr, "\n*** Error during writing of the JHALFS configuration.\n\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
392
menu/confdata.c
Normal file
392
menu/confdata.c
Normal file
|
@ -0,0 +1,392 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||||
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define LKC_DIRECT_LINK
|
||||||
|
#include "lkc.h"
|
||||||
|
|
||||||
|
const char conf_def_filename[] = "configuration";
|
||||||
|
|
||||||
|
const char conf_defname[] = "defconfig";
|
||||||
|
|
||||||
|
const char *conf_confnames[] = {
|
||||||
|
"configuration",
|
||||||
|
conf_defname,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *conf_expand_value(const char *in)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
const char *src;
|
||||||
|
static char res_value[SYMBOL_MAXLENGTH];
|
||||||
|
char *dst, name[SYMBOL_MAXLENGTH];
|
||||||
|
|
||||||
|
res_value[0] = 0;
|
||||||
|
dst = name;
|
||||||
|
while ((src = strchr(in, '$'))) {
|
||||||
|
strncat(res_value, in, src - in);
|
||||||
|
src++;
|
||||||
|
dst = name;
|
||||||
|
while (isalnum(*src) || *src == '_')
|
||||||
|
*dst++ = *src++;
|
||||||
|
*dst = 0;
|
||||||
|
sym = sym_lookup(name, 0);
|
||||||
|
sym_calc_value(sym);
|
||||||
|
strcat(res_value, sym_get_string_value(sym));
|
||||||
|
in = src;
|
||||||
|
}
|
||||||
|
strcat(res_value, in);
|
||||||
|
|
||||||
|
return res_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int conf_read(const char *name)
|
||||||
|
{
|
||||||
|
FILE *in = NULL;
|
||||||
|
char line[1024];
|
||||||
|
char *p, *p2;
|
||||||
|
int lineno = 0;
|
||||||
|
struct symbol *sym;
|
||||||
|
struct property *prop;
|
||||||
|
struct expr *e;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
in = zconf_fopen(name);
|
||||||
|
} else {
|
||||||
|
const char **names = conf_confnames;
|
||||||
|
while ((name = *names++)) {
|
||||||
|
name = conf_expand_value(name);
|
||||||
|
in = zconf_fopen(name);
|
||||||
|
if (in) {
|
||||||
|
printf("#\n"
|
||||||
|
"# using defaults found in %s\n"
|
||||||
|
"#\n", name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for_all_symbols(i, sym) {
|
||||||
|
sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
|
||||||
|
sym->flags &= ~SYMBOL_VALID;
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_INT:
|
||||||
|
case S_HEX:
|
||||||
|
case S_STRING:
|
||||||
|
free(sym->user.val);
|
||||||
|
default:
|
||||||
|
sym->user.val = NULL;
|
||||||
|
sym->user.tri = no;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), in)) {
|
||||||
|
lineno++;
|
||||||
|
sym = NULL;
|
||||||
|
switch (line[0]) {
|
||||||
|
case '#':
|
||||||
|
if (line[1]!=' ')
|
||||||
|
continue;
|
||||||
|
p = strchr(line + 2, ' ');
|
||||||
|
if (!p)
|
||||||
|
continue;
|
||||||
|
*p++ = 0;
|
||||||
|
if (strncmp(p, "is not set", 10))
|
||||||
|
continue;
|
||||||
|
sym = sym_find(line + 2);
|
||||||
|
if (!sym) {
|
||||||
|
fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_BOOLEAN:
|
||||||
|
case S_TRISTATE:
|
||||||
|
sym->user.tri = no;
|
||||||
|
sym->flags &= ~SYMBOL_NEW;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'A' ... 'Z':
|
||||||
|
p = strchr(line, '=');
|
||||||
|
if (!p)
|
||||||
|
continue;
|
||||||
|
*p++ = 0;
|
||||||
|
p2 = strchr(p, '\n');
|
||||||
|
if (p2)
|
||||||
|
*p2 = 0;
|
||||||
|
sym = sym_find(line);
|
||||||
|
if (!sym) {
|
||||||
|
fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_TRISTATE:
|
||||||
|
if (p[0] == 'm') {
|
||||||
|
sym->user.tri = mod;
|
||||||
|
sym->flags &= ~SYMBOL_NEW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case S_BOOLEAN:
|
||||||
|
if (p[0] == 'y') {
|
||||||
|
sym->user.tri = yes;
|
||||||
|
sym->flags &= ~SYMBOL_NEW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (p[0] == 'n') {
|
||||||
|
sym->user.tri = no;
|
||||||
|
sym->flags &= ~SYMBOL_NEW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case S_STRING:
|
||||||
|
if (*p++ != '"')
|
||||||
|
break;
|
||||||
|
for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
|
||||||
|
if (*p2 == '"') {
|
||||||
|
*p2 = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memmove(p2, p2 + 1, strlen(p2));
|
||||||
|
}
|
||||||
|
if (!p2) {
|
||||||
|
fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
case S_INT:
|
||||||
|
case S_HEX:
|
||||||
|
if (sym_string_valid(sym, p)) {
|
||||||
|
sym->user.val = strdup(p);
|
||||||
|
sym->flags &= ~SYMBOL_NEW;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sym && sym_is_choice_value(sym)) {
|
||||||
|
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
|
||||||
|
switch (sym->user.tri) {
|
||||||
|
case no:
|
||||||
|
break;
|
||||||
|
case mod:
|
||||||
|
if (cs->user.tri == yes)
|
||||||
|
/* warn? */;
|
||||||
|
break;
|
||||||
|
case yes:
|
||||||
|
if (cs->user.tri != no)
|
||||||
|
/* warn? */;
|
||||||
|
cs->user.val = sym;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
|
||||||
|
cs->flags &= ~SYMBOL_NEW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(in);
|
||||||
|
|
||||||
|
if (modules_sym)
|
||||||
|
sym_calc_value(modules_sym);
|
||||||
|
for_all_symbols(i, sym) {
|
||||||
|
sym_calc_value(sym);
|
||||||
|
if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
|
||||||
|
if (sym->visible == no)
|
||||||
|
sym->flags |= SYMBOL_NEW;
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_STRING:
|
||||||
|
case S_INT:
|
||||||
|
case S_HEX:
|
||||||
|
if (!sym_string_within_range(sym, sym->user.val))
|
||||||
|
sym->flags |= SYMBOL_NEW;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!sym_is_choice(sym))
|
||||||
|
continue;
|
||||||
|
prop = sym_get_choice_prop(sym);
|
||||||
|
for (e = prop->expr; e; e = e->left.expr)
|
||||||
|
if (e->right.sym->visible != no)
|
||||||
|
sym->flags |= e->right.sym->flags & SYMBOL_NEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym_change_count = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct menu *next_menu(struct menu *menu)
|
||||||
|
{
|
||||||
|
if (menu->list) return menu->list;
|
||||||
|
do {
|
||||||
|
if (menu->next) {
|
||||||
|
menu = menu->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ((menu = menu->parent));
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SYMBOL_FORCEWRITE (1<<31)
|
||||||
|
|
||||||
|
int conf_write(const char *name)
|
||||||
|
{
|
||||||
|
FILE *out;
|
||||||
|
struct symbol *sym;
|
||||||
|
struct menu *menu;
|
||||||
|
const char *basename;
|
||||||
|
char dirname[128], tmpname[128], newname[128];
|
||||||
|
int type, l;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
dirname[0] = 0;
|
||||||
|
if (name && name[0]) {
|
||||||
|
struct stat st;
|
||||||
|
char *slash;
|
||||||
|
|
||||||
|
if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
|
||||||
|
strcpy(dirname, name);
|
||||||
|
strcat(dirname, "/");
|
||||||
|
basename = conf_def_filename;
|
||||||
|
} else if ((slash = strrchr(name, '/'))) {
|
||||||
|
int size = slash - name + 1;
|
||||||
|
memcpy(dirname, name, size);
|
||||||
|
dirname[size] = 0;
|
||||||
|
if (slash[1])
|
||||||
|
basename = slash + 1;
|
||||||
|
else
|
||||||
|
basename = conf_def_filename;
|
||||||
|
} else
|
||||||
|
basename = name;
|
||||||
|
} else
|
||||||
|
basename = conf_def_filename;
|
||||||
|
|
||||||
|
sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
|
||||||
|
out = fopen(newname, "w");
|
||||||
|
if (!out)
|
||||||
|
return 1;
|
||||||
|
fprintf(out, "#\n"
|
||||||
|
"# Automatically generated configuration: don't edit\n"
|
||||||
|
"# use make menuconfig or make config to make changes\n"
|
||||||
|
"#\n");
|
||||||
|
|
||||||
|
if (!sym_change_count)
|
||||||
|
sym_clear_all_valid();
|
||||||
|
|
||||||
|
/* Force write of all non-duplicate symbols. */
|
||||||
|
|
||||||
|
/* Write out everything by default. */
|
||||||
|
for(menu = rootmenu.list; menu; menu = next_menu(menu))
|
||||||
|
if (menu->sym) menu->sym->flags |= SYMBOL_FORCEWRITE;
|
||||||
|
|
||||||
|
menu = rootmenu.list;
|
||||||
|
while (menu) {
|
||||||
|
sym = menu->sym;
|
||||||
|
if (!sym) {
|
||||||
|
if (!menu_is_visible(menu))
|
||||||
|
goto next;
|
||||||
|
str = menu_get_prompt(menu);
|
||||||
|
fprintf(out, "\n"
|
||||||
|
"#\n"
|
||||||
|
"# %s\n"
|
||||||
|
"#\n", str);
|
||||||
|
} else if (!(sym->flags & SYMBOL_CHOICE)) {
|
||||||
|
sym_calc_value(sym);
|
||||||
|
if (!(sym->flags & SYMBOL_FORCEWRITE))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
sym->flags &= ~SYMBOL_FORCEWRITE;
|
||||||
|
type = sym->type;
|
||||||
|
if (type == S_TRISTATE) {
|
||||||
|
sym_calc_value(modules_sym);
|
||||||
|
if (modules_sym->curr.tri == no)
|
||||||
|
type = S_BOOLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case S_BOOLEAN:
|
||||||
|
case S_TRISTATE:
|
||||||
|
switch (sym_get_tristate_value(sym)) {
|
||||||
|
case no:
|
||||||
|
fprintf(out, "# %s is not set\n", sym->name);
|
||||||
|
break;
|
||||||
|
case mod:
|
||||||
|
fprintf(out, "%s=m\n", sym->name);
|
||||||
|
break;
|
||||||
|
case yes:
|
||||||
|
fprintf(out, "%s=y\n", sym->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case S_STRING:
|
||||||
|
// fix me
|
||||||
|
str = sym_get_string_value(sym);
|
||||||
|
fprintf(out, "%s=\"", sym->name);
|
||||||
|
do {
|
||||||
|
l = strcspn(str, "\"\\");
|
||||||
|
if (l) {
|
||||||
|
fwrite(str, l, 1, out);
|
||||||
|
}
|
||||||
|
str += l;
|
||||||
|
while (*str == '\\' || *str == '"') {
|
||||||
|
fprintf(out, "\\%c", *str);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
} while (*str);
|
||||||
|
fputs("\"\n", out);
|
||||||
|
break;
|
||||||
|
case S_HEX:
|
||||||
|
str = sym_get_string_value(sym);
|
||||||
|
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
|
||||||
|
fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case S_INT:
|
||||||
|
str = sym_get_string_value(sym);
|
||||||
|
fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next:
|
||||||
|
menu = next_menu(menu);
|
||||||
|
}
|
||||||
|
fclose(out);
|
||||||
|
if (!name || basename != conf_def_filename) {
|
||||||
|
if (!name)
|
||||||
|
name = conf_def_filename;
|
||||||
|
sprintf(tmpname, "%s.old", name);
|
||||||
|
rename(name, tmpname);
|
||||||
|
}
|
||||||
|
sprintf(tmpname, "%s%s", dirname, basename);
|
||||||
|
if (rename(newname, tmpname))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sym_change_count = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
1099
menu/expr.c
Normal file
1099
menu/expr.c
Normal file
File diff suppressed because it is too large
Load diff
195
menu/expr.h
Normal file
195
menu/expr.h
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||||
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXPR_H
|
||||||
|
#define EXPR_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdbool.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct file {
|
||||||
|
struct file *next;
|
||||||
|
struct file *parent;
|
||||||
|
char *name;
|
||||||
|
int lineno;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FILE_BUSY 0x0001
|
||||||
|
#define FILE_SCANNED 0x0002
|
||||||
|
#define FILE_PRINTED 0x0004
|
||||||
|
|
||||||
|
typedef enum tristate {
|
||||||
|
no, mod, yes
|
||||||
|
} tristate;
|
||||||
|
|
||||||
|
enum expr_type {
|
||||||
|
E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE
|
||||||
|
};
|
||||||
|
|
||||||
|
union expr_data {
|
||||||
|
struct expr *expr;
|
||||||
|
struct symbol *sym;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct expr {
|
||||||
|
enum expr_type type;
|
||||||
|
union expr_data left, right;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define E_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
|
||||||
|
#define E_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
|
||||||
|
#define E_NOT(dep) (2-(dep))
|
||||||
|
|
||||||
|
struct expr_value {
|
||||||
|
struct expr *expr;
|
||||||
|
tristate tri;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct symbol_value {
|
||||||
|
void *val;
|
||||||
|
tristate tri;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum symbol_type {
|
||||||
|
S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
|
||||||
|
};
|
||||||
|
|
||||||
|
struct symbol {
|
||||||
|
struct symbol *next;
|
||||||
|
char *name;
|
||||||
|
char *help;
|
||||||
|
enum symbol_type type;
|
||||||
|
struct symbol_value curr, user;
|
||||||
|
tristate visible;
|
||||||
|
int flags;
|
||||||
|
struct property *prop;
|
||||||
|
struct expr *dep, *dep2;
|
||||||
|
struct expr_value rev_dep;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
|
||||||
|
|
||||||
|
#define SYMBOL_YES 0x0001
|
||||||
|
#define SYMBOL_MOD 0x0002
|
||||||
|
#define SYMBOL_NO 0x0004
|
||||||
|
#define SYMBOL_CONST 0x0007
|
||||||
|
#define SYMBOL_CHECK 0x0008
|
||||||
|
#define SYMBOL_CHOICE 0x0010
|
||||||
|
#define SYMBOL_CHOICEVAL 0x0020
|
||||||
|
#define SYMBOL_PRINTED 0x0040
|
||||||
|
#define SYMBOL_VALID 0x0080
|
||||||
|
#define SYMBOL_OPTIONAL 0x0100
|
||||||
|
#define SYMBOL_WRITE 0x0200
|
||||||
|
#define SYMBOL_CHANGED 0x0400
|
||||||
|
#define SYMBOL_NEW 0x0800
|
||||||
|
#define SYMBOL_AUTO 0x1000
|
||||||
|
#define SYMBOL_CHECKED 0x2000
|
||||||
|
#define SYMBOL_CHECK_DONE 0x4000
|
||||||
|
#define SYMBOL_WARNED 0x8000
|
||||||
|
|
||||||
|
#define SYMBOL_MAXLENGTH 256
|
||||||
|
#define SYMBOL_HASHSIZE 257
|
||||||
|
#define SYMBOL_HASHMASK 0xff
|
||||||
|
|
||||||
|
enum prop_type {
|
||||||
|
P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_SELECT, P_RANGE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct property {
|
||||||
|
struct property *next;
|
||||||
|
struct symbol *sym;
|
||||||
|
enum prop_type type;
|
||||||
|
const char *text;
|
||||||
|
struct expr_value visible;
|
||||||
|
struct expr *expr;
|
||||||
|
struct menu *menu;
|
||||||
|
struct file *file;
|
||||||
|
int lineno;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define for_all_properties(sym, st, tok) \
|
||||||
|
for (st = sym->prop; st; st = st->next) \
|
||||||
|
if (st->type == (tok))
|
||||||
|
#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
|
||||||
|
#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
|
||||||
|
#define for_all_prompts(sym, st) \
|
||||||
|
for (st = sym->prop; st; st = st->next) \
|
||||||
|
if (st->text)
|
||||||
|
|
||||||
|
struct menu {
|
||||||
|
struct menu *next;
|
||||||
|
struct menu *parent;
|
||||||
|
struct menu *list;
|
||||||
|
struct symbol *sym;
|
||||||
|
struct property *prompt;
|
||||||
|
struct expr *dep;
|
||||||
|
unsigned int flags;
|
||||||
|
//char *help;
|
||||||
|
struct file *file;
|
||||||
|
int lineno;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MENU_CHANGED 0x0001
|
||||||
|
#define MENU_ROOT 0x0002
|
||||||
|
|
||||||
|
#ifndef SWIG
|
||||||
|
|
||||||
|
extern struct file *file_list;
|
||||||
|
extern struct file *current_file;
|
||||||
|
struct file *lookup_file(const char *name);
|
||||||
|
|
||||||
|
extern struct symbol symbol_yes, symbol_no, symbol_mod;
|
||||||
|
extern struct symbol *modules_sym;
|
||||||
|
extern int cdebug;
|
||||||
|
struct expr *expr_alloc_symbol(struct symbol *sym);
|
||||||
|
struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
|
||||||
|
struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);
|
||||||
|
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
|
||||||
|
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
|
||||||
|
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
|
||||||
|
struct expr *expr_copy(struct expr *org);
|
||||||
|
void expr_free(struct expr *e);
|
||||||
|
int expr_eq(struct expr *e1, struct expr *e2);
|
||||||
|
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
|
||||||
|
tristate expr_calc_value(struct expr *e);
|
||||||
|
struct expr *expr_eliminate_yn(struct expr *e);
|
||||||
|
struct expr *expr_trans_bool(struct expr *e);
|
||||||
|
struct expr *expr_eliminate_dups(struct expr *e);
|
||||||
|
struct expr *expr_transform(struct expr *e);
|
||||||
|
int expr_contains_symbol(struct expr *dep, struct symbol *sym);
|
||||||
|
bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
|
||||||
|
struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
|
||||||
|
struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
|
||||||
|
void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
|
||||||
|
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
|
||||||
|
|
||||||
|
void expr_fprint(struct expr *e, FILE *out);
|
||||||
|
struct gstr; /* forward */
|
||||||
|
void expr_gstr_print(struct expr *e, struct gstr *gs);
|
||||||
|
|
||||||
|
static inline int expr_is_yes(struct expr *e)
|
||||||
|
{
|
||||||
|
return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int expr_is_no(struct expr *e)
|
||||||
|
{
|
||||||
|
return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* EXPR_H */
|
3688
menu/lex.zconf.c_shipped
Normal file
3688
menu/lex.zconf.c_shipped
Normal file
File diff suppressed because it is too large
Load diff
123
menu/lkc.h
Normal file
123
menu/lkc.h
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||||
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LKC_H
|
||||||
|
#define LKC_H
|
||||||
|
|
||||||
|
#include "expr.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LKC_DIRECT_LINK
|
||||||
|
#define P(name,type,arg) extern type name arg
|
||||||
|
#else
|
||||||
|
#include "lkc_defs.h"
|
||||||
|
#define P(name,type,arg) extern type (*name ## _p) arg
|
||||||
|
#endif
|
||||||
|
#include "lkc_proto.h"
|
||||||
|
#undef P
|
||||||
|
|
||||||
|
#define SRCTREE "srctree"
|
||||||
|
|
||||||
|
int zconfparse(void);
|
||||||
|
void zconfdump(FILE *out);
|
||||||
|
|
||||||
|
extern int zconfdebug;
|
||||||
|
void zconf_starthelp(void);
|
||||||
|
FILE *zconf_fopen(const char *name);
|
||||||
|
void zconf_initscan(const char *name);
|
||||||
|
void zconf_nextfile(const char *name);
|
||||||
|
int zconf_lineno(void);
|
||||||
|
char *zconf_curname(void);
|
||||||
|
|
||||||
|
/* confdata.c */
|
||||||
|
extern const char conf_def_filename[];
|
||||||
|
extern char conf_filename[];
|
||||||
|
|
||||||
|
char *conf_get_default_confname(void);
|
||||||
|
|
||||||
|
/* kconfig_load.c */
|
||||||
|
void kconfig_load(void);
|
||||||
|
|
||||||
|
/* menu.c */
|
||||||
|
void menu_init(void);
|
||||||
|
void menu_add_menu(void);
|
||||||
|
void menu_end_menu(void);
|
||||||
|
void menu_add_entry(struct symbol *sym);
|
||||||
|
void menu_end_entry(void);
|
||||||
|
void menu_add_dep(struct expr *dep);
|
||||||
|
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
|
||||||
|
void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
|
||||||
|
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
|
||||||
|
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
|
||||||
|
void menu_finalize(struct menu *parent);
|
||||||
|
void menu_set_type(int type);
|
||||||
|
|
||||||
|
/* util.c */
|
||||||
|
struct file *file_lookup(const char *name);
|
||||||
|
int file_write_dep(const char *name);
|
||||||
|
|
||||||
|
struct gstr {
|
||||||
|
size_t len;
|
||||||
|
char *s;
|
||||||
|
};
|
||||||
|
struct gstr str_new(void);
|
||||||
|
struct gstr str_assign(const char *s);
|
||||||
|
void str_free(struct gstr *gs);
|
||||||
|
void str_append(struct gstr *gs, const char *s);
|
||||||
|
void str_printf(struct gstr *gs, const char *fmt, ...);
|
||||||
|
const char *str_get(struct gstr *gs);
|
||||||
|
|
||||||
|
/* symbol.c */
|
||||||
|
void sym_init(void);
|
||||||
|
void sym_clear_all_valid(void);
|
||||||
|
void sym_set_changed(struct symbol *sym);
|
||||||
|
struct symbol *sym_check_deps(struct symbol *sym);
|
||||||
|
struct property *prop_alloc(enum prop_type type, struct symbol *sym);
|
||||||
|
struct symbol *prop_get_symbol(struct property *prop);
|
||||||
|
|
||||||
|
static inline tristate sym_get_tristate_value(struct symbol *sym)
|
||||||
|
{
|
||||||
|
return sym->curr.tri;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline struct symbol *sym_get_choice_value(struct symbol *sym)
|
||||||
|
{
|
||||||
|
return (struct symbol *)sym->curr.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
|
||||||
|
{
|
||||||
|
return sym_set_tristate_value(chval, yes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool sym_is_choice(struct symbol *sym)
|
||||||
|
{
|
||||||
|
return sym->flags & SYMBOL_CHOICE ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool sym_is_choice_value(struct symbol *sym)
|
||||||
|
{
|
||||||
|
return sym->flags & SYMBOL_CHOICEVAL ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool sym_is_optional(struct symbol *sym)
|
||||||
|
{
|
||||||
|
return sym->flags & SYMBOL_OPTIONAL ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool sym_has_value(struct symbol *sym)
|
||||||
|
{
|
||||||
|
return sym->flags & SYMBOL_NEW ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LKC_H */
|
40
menu/lkc_proto.h
Normal file
40
menu/lkc_proto.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
/* confdata.c */
|
||||||
|
P(conf_parse,void,(const char *name));
|
||||||
|
P(conf_read,int,(const char *name));
|
||||||
|
P(conf_write,int,(const char *name));
|
||||||
|
|
||||||
|
/* menu.c */
|
||||||
|
P(rootmenu,struct menu,);
|
||||||
|
|
||||||
|
P(menu_is_visible,bool,(struct menu *menu));
|
||||||
|
P(menu_get_prompt,const char *,(struct menu *menu));
|
||||||
|
P(menu_get_root_menu,struct menu *,(struct menu *menu));
|
||||||
|
P(menu_get_parent_menu,struct menu *,(struct menu *menu));
|
||||||
|
|
||||||
|
/* symbol.c */
|
||||||
|
P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
|
||||||
|
P(sym_change_count,int,);
|
||||||
|
|
||||||
|
P(sym_lookup,struct symbol *,(const char *name, int isconst));
|
||||||
|
P(sym_find,struct symbol *,(const char *name));
|
||||||
|
P(sym_re_search,struct symbol **,(const char *pattern));
|
||||||
|
P(sym_type_name,const char *,(enum symbol_type type));
|
||||||
|
P(sym_calc_value,void,(struct symbol *sym));
|
||||||
|
P(sym_get_type,enum symbol_type,(struct symbol *sym));
|
||||||
|
P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
|
||||||
|
P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
|
||||||
|
P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
|
||||||
|
P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
|
||||||
|
P(sym_string_within_range,bool,(struct symbol *sym, const char *str));
|
||||||
|
P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
|
||||||
|
P(sym_is_changable,bool,(struct symbol *sym));
|
||||||
|
P(sym_get_choice_prop,struct property *,(struct symbol *sym));
|
||||||
|
P(sym_get_default_prop,struct property *,(struct symbol *sym));
|
||||||
|
P(sym_get_string_value,const char *,(struct symbol *sym));
|
||||||
|
|
||||||
|
P(prop_get_type_name,const char *,(enum prop_type type));
|
||||||
|
|
||||||
|
/* expr.c */
|
||||||
|
P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
|
||||||
|
P(expr_print,void,(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken));
|
4
menu/lxdialog/BIG.FAT.WARNING
Normal file
4
menu/lxdialog/BIG.FAT.WARNING
Normal file
|
@ -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.
|
372
menu/lxdialog/checklist.c
Normal file
372
menu/lxdialog/checklist.c
Normal file
|
@ -0,0 +1,372 @@
|
||||||
|
/*
|
||||||
|
* 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, struct dialog_list_item ** 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] = (items[i]->selected == 1); /* ON */
|
||||||
|
if ((!choice && status[i]) || items[i]->selected == 2) /* SELECTED */
|
||||||
|
choice = i + 1;
|
||||||
|
}
|
||||||
|
if (choice)
|
||||||
|
choice--;
|
||||||
|
|
||||||
|
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]->name) + 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]->name,
|
||||||
|
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]->name[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]->name,
|
||||||
|
status[scroll], 0, FALSE);
|
||||||
|
scrollok (list, TRUE);
|
||||||
|
wscrl (list, -1);
|
||||||
|
scrollok (list, FALSE);
|
||||||
|
}
|
||||||
|
scroll--;
|
||||||
|
print_item (list, items[scroll]->name,
|
||||||
|
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]->name,
|
||||||
|
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]->name,
|
||||||
|
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]->name,
|
||||||
|
status[scroll + choice], choice, FALSE);
|
||||||
|
/* Highlight new item */
|
||||||
|
choice = i;
|
||||||
|
print_item (list, items[scroll + choice]->name,
|
||||||
|
status[scroll + choice], choice, TRUE);
|
||||||
|
wnoutrefresh (list);
|
||||||
|
wrefresh (dialog);
|
||||||
|
}
|
||||||
|
continue; /* wait for another key press */
|
||||||
|
}
|
||||||
|
switch (key) {
|
||||||
|
case 'H':
|
||||||
|
case 'h':
|
||||||
|
case '?':
|
||||||
|
for (i = 0; i < item_no; i++)
|
||||||
|
items[i]->selected = 0;
|
||||||
|
items[scroll + choice]->selected = 1;
|
||||||
|
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]->name,
|
||||||
|
status[scroll + i], i, i == choice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wnoutrefresh (list);
|
||||||
|
wrefresh (dialog);
|
||||||
|
|
||||||
|
for (i = 0; i < item_no; i++) {
|
||||||
|
items[i]->selected = status[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < item_no; i++)
|
||||||
|
items[i]->selected = 0;
|
||||||
|
items[scroll + choice]->selected = 1;
|
||||||
|
}
|
||||||
|
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 */
|
||||||
|
}
|
161
menu/lxdialog/colors.h
Normal file
161
menu/lxdialog/colors.h
Normal file
|
@ -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];
|
199
menu/lxdialog/dialog.h
Normal file
199
menu/lxdialog/dialog.h
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
|
||||||
|
#ifdef CURSES_LOC
|
||||||
|
#ifdef __sun__
|
||||||
|
#define CURS_MACROS
|
||||||
|
#endif
|
||||||
|
#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 chtype attributes[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern const char *backtitle;
|
||||||
|
|
||||||
|
struct dialog_list_item {
|
||||||
|
char *name;
|
||||||
|
int namelen;
|
||||||
|
char *tag;
|
||||||
|
int selected; /* Set to 1 by dialog_*() function. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function prototypes
|
||||||
|
*/
|
||||||
|
|
||||||
|
void init_dialog (void);
|
||||||
|
void end_dialog (void);
|
||||||
|
void dialog_clear (void);
|
||||||
|
#ifdef CURSES_LOC
|
||||||
|
void attr_clear (WINDOW * win, int height, int width, chtype attr);
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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,
|
||||||
|
struct dialog_list_item ** items);
|
||||||
|
int dialog_checklist (const char *title, const char *prompt, int height,
|
||||||
|
int width, int list_height, int item_no,
|
||||||
|
struct dialog_list_item ** 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);
|
||||||
|
|
||||||
|
struct dialog_list_item *first_sel_item(int item_no,
|
||||||
|
struct dialog_list_item ** items);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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')
|
||||||
|
*/
|
||||||
|
#ifdef CURSES_LOC
|
||||||
|
#define M_EVENT (KEY_MAX+1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The `flag' parameter in checklist is used to select between
|
||||||
|
* radiolist and checklist
|
||||||
|
*/
|
||||||
|
#define FLAG_CHECK 1
|
||||||
|
#define FLAG_RADIO 0
|
240
menu/lxdialog/inputbox.c
Normal file
240
menu/lxdialog/inputbox.c
Normal file
|
@ -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 */
|
||||||
|
}
|
438
menu/lxdialog/menubox.c
Normal file
438
menu/lxdialog/menubox.c
Normal file
|
@ -0,0 +1,438 @@
|
||||||
|
/*
|
||||||
|
* 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, "YyNnMmHh");
|
||||||
|
|
||||||
|
/* 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,
|
||||||
|
struct dialog_list_item ** 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]->name) + 2));
|
||||||
|
if (strcmp(current, items[i]->tag) == 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]->name, i, i == choice,
|
||||||
|
(items[first_item + i]->tag[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("ynmh", key))
|
||||||
|
i = max_choice;
|
||||||
|
else {
|
||||||
|
for (i = choice+1; i < max_choice; i++) {
|
||||||
|
j = first_alpha(items[scroll + i]->name, "YyNnMmHh");
|
||||||
|
if (key == tolower(items[scroll + i]->name[j]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == max_choice)
|
||||||
|
for (i = 0; i < max_choice; i++) {
|
||||||
|
j = first_alpha(items[scroll + i]->name, "YyNnMmHh");
|
||||||
|
if (key == tolower(items[scroll + i]->name[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]->name, choice, FALSE,
|
||||||
|
(items[scroll + choice]->tag[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]->name, 0, FALSE,
|
||||||
|
(items[scroll]->tag[0] != ':'));
|
||||||
|
} else
|
||||||
|
choice = MAX(choice - 1, 0);
|
||||||
|
|
||||||
|
} else if (key == KEY_DOWN || key == '+') {
|
||||||
|
|
||||||
|
print_item (menu, items[scroll + choice]->name, choice, FALSE,
|
||||||
|
(items[scroll + choice]->tag[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]->name,
|
||||||
|
max_choice-1, FALSE,
|
||||||
|
(items[scroll + max_choice - 1]->tag[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]->name, 0, FALSE,
|
||||||
|
(items[scroll]->tag[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]->name,
|
||||||
|
max_choice-1, FALSE,
|
||||||
|
(items[scroll + max_choice - 1]->tag[0] != ':'));
|
||||||
|
} else {
|
||||||
|
if (choice+1 < max_choice)
|
||||||
|
choice++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else
|
||||||
|
choice = i;
|
||||||
|
|
||||||
|
print_item (menu, items[scroll + choice]->name, choice, TRUE,
|
||||||
|
(items[scroll + choice]->tag[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':
|
||||||
|
case '/':
|
||||||
|
/* save scroll info */
|
||||||
|
if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
|
||||||
|
fprintf(f,"%d\n",scroll);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
delwin (dialog);
|
||||||
|
items[scroll + choice]->selected = 1;
|
||||||
|
switch (key) {
|
||||||
|
case 's': return 3;
|
||||||
|
case 'y': return 3;
|
||||||
|
case 'n': return 4;
|
||||||
|
case 'm': return 5;
|
||||||
|
case ' ': return 6;
|
||||||
|
case '/': return 7;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case 'h':
|
||||||
|
case '?':
|
||||||
|
button = 2;
|
||||||
|
case '\n':
|
||||||
|
delwin (dialog);
|
||||||
|
items[scroll + choice]->selected = 1;
|
||||||
|
|
||||||
|
remove("lxdialog.scrltmp");
|
||||||
|
return button;
|
||||||
|
case 'e':
|
||||||
|
case 'x':
|
||||||
|
key = ESC;
|
||||||
|
case ESC:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delwin (dialog);
|
||||||
|
remove("lxdialog.scrltmp");
|
||||||
|
return -1; /* ESC pressed */
|
||||||
|
}
|
85
menu/lxdialog/msgbox.c
Normal file
85
menu/lxdialog/msgbox.c
Normal file
|
@ -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;
|
||||||
|
}
|
556
menu/lxdialog/textbox.c
Normal file
556
menu/lxdialog/textbox.c
Normal file
|
@ -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, fd, file_size, bytes_read;
|
||||||
|
static int begin_reached = 1, end_reached, 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);
|
||||||
|
}
|
375
menu/lxdialog/util.c
Normal file
375
menu/lxdialog/util.c
Normal file
|
@ -0,0 +1,375 @@
|
||||||
|
/*
|
||||||
|
* 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 > 0) --in_paren;
|
||||||
|
|
||||||
|
if ((! in_paren) && isalpha(c) &&
|
||||||
|
strchr(exempt, c) == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the first selected item in the dialog_list_item list.
|
||||||
|
*/
|
||||||
|
struct dialog_list_item *
|
||||||
|
first_sel_item(int item_no, struct dialog_list_item ** items)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < item_no; i++) {
|
||||||
|
if (items[i]->selected)
|
||||||
|
return items[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
118
menu/lxdialog/yesno.c
Normal file
118
menu/lxdialog/yesno.c
Normal file
|
@ -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 */
|
||||||
|
}
|
976
menu/mconf.c
Normal file
976
menu/mconf.c
Normal file
|
@ -0,0 +1,976 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||||
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
|
*
|
||||||
|
* Introduced single menu mode (show all sub-menus in one large tree).
|
||||||
|
* 2002-11-06 Petr Baudis <pasky@ucw.cz>
|
||||||
|
*
|
||||||
|
* Directly use liblxdialog library routines.
|
||||||
|
* 2002-11-14 Petr Baudis <pasky@ucw.cz>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/termios.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lxdialog/dialog.h"
|
||||||
|
|
||||||
|
#define LKC_DIRECT_LINK
|
||||||
|
#include "lkc.h"
|
||||||
|
|
||||||
|
static char menu_backtitle[128];
|
||||||
|
static const char mconf_readme[] =
|
||||||
|
"Overview\n"
|
||||||
|
"--------\n"
|
||||||
|
"Some features may be built directly into JHALFS. Some features\n"
|
||||||
|
"may be completely removed altogether. There are also certain\n"
|
||||||
|
"parameters which are not really features, but must be\n"
|
||||||
|
"entered in as decimal or hexadecimal numbers or possibly text.\n"
|
||||||
|
"\n"
|
||||||
|
"Menu items beginning with [*] or [ ] represent features\n"
|
||||||
|
"configured to be built in or removed respectively.\n"
|
||||||
|
"\n"
|
||||||
|
"To change any of these features, highlight it with the cursor\n"
|
||||||
|
"keys and press <Y> to build it in or <N> to removed it.\n"
|
||||||
|
"You may also press the <Space Bar> to cycle\n"
|
||||||
|
"through the available options (ie. Y->N->Y).\n"
|
||||||
|
"\n"
|
||||||
|
"Some additional keyboard hints:\n"
|
||||||
|
"\n"
|
||||||
|
"Menus\n"
|
||||||
|
"----------\n"
|
||||||
|
"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
|
||||||
|
" you wish to change or submenu wish to select and press <Enter>.\n"
|
||||||
|
" Submenus are designated by \"--->\".\n"
|
||||||
|
"\n"
|
||||||
|
" Shortcut: Press the option's highlighted letter (hotkey).\n"
|
||||||
|
" Pressing a hotkey more than once will sequence\n"
|
||||||
|
" through all visible items which use that hotkey.\n"
|
||||||
|
"\n"
|
||||||
|
" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
|
||||||
|
" unseen options into view.\n"
|
||||||
|
"\n"
|
||||||
|
"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
|
||||||
|
" and press <ENTER>.\n"
|
||||||
|
"\n"
|
||||||
|
" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
|
||||||
|
" using those letters. You may press a single <ESC>, but\n"
|
||||||
|
" there is a delayed response which you may find annoying.\n"
|
||||||
|
"\n"
|
||||||
|
" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
|
||||||
|
" <Exit> and <Help>\n"
|
||||||
|
"\n"
|
||||||
|
"o To get help with an item, use the cursor keys to highlight <Help>\n"
|
||||||
|
" and Press <ENTER>.\n"
|
||||||
|
"\n"
|
||||||
|
" Shortcut: Press <H> or <?>.\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"Radiolists (Choice lists)\n"
|
||||||
|
"-----------\n"
|
||||||
|
"o Use the cursor keys to select the option you wish to set and press\n"
|
||||||
|
" <S> or the <SPACE BAR>.\n"
|
||||||
|
"\n"
|
||||||
|
" Shortcut: Press the first letter of the option you wish to set then\n"
|
||||||
|
" press <S> or <SPACE BAR>.\n"
|
||||||
|
"\n"
|
||||||
|
"o To see available help for the item, use the cursor keys to highlight\n"
|
||||||
|
" <Help> and Press <ENTER>.\n"
|
||||||
|
"\n"
|
||||||
|
" Shortcut: Press <H> or <?>.\n"
|
||||||
|
"\n"
|
||||||
|
" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
|
||||||
|
" <Help>\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"Data Entry\n"
|
||||||
|
"-----------\n"
|
||||||
|
"o Enter the requested information and press <ENTER>\n"
|
||||||
|
" If you are entering hexadecimal values, it is not necessary to\n"
|
||||||
|
" add the '0x' prefix to the entry.\n"
|
||||||
|
"\n"
|
||||||
|
"o For help, use the <TAB> or cursor keys to highlight the help option\n"
|
||||||
|
" and press <ENTER>. You can try <TAB><H> as well.\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"Text Box (Help Window)\n"
|
||||||
|
"--------\n"
|
||||||
|
"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
|
||||||
|
" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
|
||||||
|
" who are familiar with less and lynx.\n"
|
||||||
|
"\n"
|
||||||
|
"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"Alternate Configuration Files\n"
|
||||||
|
"-----------------------------\n"
|
||||||
|
"Menuconfig supports the use of alternate configuration files for\n"
|
||||||
|
"those who, for various reasons, find it necessary to switch\n"
|
||||||
|
"between different configurations.\n"
|
||||||
|
"\n"
|
||||||
|
"At the end of the main menu you will find two options. One is\n"
|
||||||
|
"for saving the current configuration to a file of your choosing.\n"
|
||||||
|
"The other option is for loading a previously saved alternate\n"
|
||||||
|
"configuration.\n"
|
||||||
|
"\n"
|
||||||
|
"Even if you don't use alternate configuration files, but you\n"
|
||||||
|
"find during a Menuconfig session that you have completely messed\n"
|
||||||
|
"up your settings, you may use the \"Load Alternate...\" option to\n"
|
||||||
|
"restore your previously saved settings from \".config\" without\n"
|
||||||
|
"restarting Menuconfig.\n"
|
||||||
|
"\n"
|
||||||
|
"Other information\n"
|
||||||
|
"-----------------\n"
|
||||||
|
"If you use Menuconfig in an XTERM window make sure you have your\n"
|
||||||
|
"$TERM variable set to point to a xterm definition which supports color.\n"
|
||||||
|
"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
|
||||||
|
"display correctly in a RXVT window because rxvt displays only one\n"
|
||||||
|
"intensity of color, bright.\n"
|
||||||
|
"\n"
|
||||||
|
"Menuconfig will display larger menus on screens or xterms which are\n"
|
||||||
|
"set to display more than the standard 25 row by 80 column geometry.\n"
|
||||||
|
"In order for this to work, the \"stty size\" command must be able to\n"
|
||||||
|
"display the screen's current row and column geometry. I STRONGLY\n"
|
||||||
|
"RECOMMEND that you make sure you do NOT have the shell variables\n"
|
||||||
|
"LINES and COLUMNS exported into your environment. Some distributions\n"
|
||||||
|
"export those variables via /etc/profile. Some ncurses programs can\n"
|
||||||
|
"become confused when those variables (LINES & COLUMNS) don't reflect\n"
|
||||||
|
"the true screen size.\n"
|
||||||
|
"\n"
|
||||||
|
"Optional personality available\n"
|
||||||
|
"------------------------------\n"
|
||||||
|
"If you prefer to have all of the options listed in a single\n"
|
||||||
|
"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
|
||||||
|
"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
|
||||||
|
"\n"
|
||||||
|
"make MENUCONFIG_MODE=single_menu menuconfig\n"
|
||||||
|
"\n"
|
||||||
|
"<Enter> will then unroll the appropriate category, or enfold it if it\n"
|
||||||
|
"is already unrolled.\n"
|
||||||
|
"\n"
|
||||||
|
"Note that this mode can eventually be a little more CPU expensive\n"
|
||||||
|
"(especially with a larger number of unrolled categories) than the\n"
|
||||||
|
"default mode.\n",
|
||||||
|
menu_instructions[] =
|
||||||
|
"Arrow keys navigate the menu. "
|
||||||
|
"<Enter> selects submenus --->. "
|
||||||
|
"Highlighted letters are hotkeys. "
|
||||||
|
"Pressing <Y> selectes a feature, while <N> will exclude a feature. "
|
||||||
|
"Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
|
||||||
|
"Legend: [*] feature is selected [ ] feature is excluded",
|
||||||
|
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.",
|
||||||
|
setmod_text[] =
|
||||||
|
"This feature depends on another which has been configured as a module.\n"
|
||||||
|
"As a result, this feature will be built as a module.",
|
||||||
|
nohelp_text[] =
|
||||||
|
"There is no help available for this option.\n",
|
||||||
|
load_config_text[] =
|
||||||
|
"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.",
|
||||||
|
load_config_help[] =
|
||||||
|
"\n"
|
||||||
|
"For various reasons, one may wish to keep several different JHALFS\n"
|
||||||
|
"configurations available on a single machine.\n"
|
||||||
|
"\n"
|
||||||
|
"If you have saved a previous configuration in a file other than the\n"
|
||||||
|
"JHALFS's default, entering the name of the file here will allow you\n"
|
||||||
|
"to modify that configuration.\n"
|
||||||
|
"\n"
|
||||||
|
"If you are uncertain, then you have probably never used alternate\n"
|
||||||
|
"configuration files. You should therefor leave this blank to abort.\n",
|
||||||
|
save_config_text[] =
|
||||||
|
"Enter a filename to which this configuration should be saved "
|
||||||
|
"as an alternate. Leave blank to abort.",
|
||||||
|
save_config_help[] =
|
||||||
|
"\n"
|
||||||
|
"For various reasons, one may wish to keep different JHALFS\n"
|
||||||
|
"configurations available on a single machine.\n"
|
||||||
|
"\n"
|
||||||
|
"Entering a file name here will allow you to later retrieve, modify\n"
|
||||||
|
"and use the current configuration as an alternate to whatever\n"
|
||||||
|
"configuration options you have selected at that time.\n"
|
||||||
|
"\n"
|
||||||
|
"If you are uncertain what all this means then you should probably\n"
|
||||||
|
"leave this blank.\n",
|
||||||
|
search_help[] =
|
||||||
|
"\n"
|
||||||
|
"Search for CONFIG_ symbols and display their relations.\n"
|
||||||
|
"Example: search for \"^FOO\"\n"
|
||||||
|
"Result:\n"
|
||||||
|
"-----------------------------------------------------------------\n"
|
||||||
|
"Symbol: FOO [=m]\n"
|
||||||
|
"Prompt: Foo bus is used to drive the bar HW\n"
|
||||||
|
"Defined at drivers/pci/Kconfig:47\n"
|
||||||
|
"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
|
||||||
|
"Location:\n"
|
||||||
|
" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
|
||||||
|
" -> PCI support (PCI [=y])\n"
|
||||||
|
" -> PCI access mode (<choice> [=y])\n"
|
||||||
|
"Selects: LIBCRC32\n"
|
||||||
|
"Selected by: BAR\n"
|
||||||
|
"-----------------------------------------------------------------\n"
|
||||||
|
"o The line 'Prompt:' shows the text used in the menu structure for\n"
|
||||||
|
" this CONFIG_ symbol\n"
|
||||||
|
"o The 'Defined at' line tell at what file / line number the symbol\n"
|
||||||
|
" is defined\n"
|
||||||
|
"o The 'Depends on:' line tell what symbols needs to be defined for\n"
|
||||||
|
" this symbol to be visible in the menu (selectable)\n"
|
||||||
|
"o The 'Location:' lines tell where in the menu structure this symbol\n"
|
||||||
|
" is located\n"
|
||||||
|
" A location followed by a [=y] indicate that this is a selectable\n"
|
||||||
|
" menu item - and current value is displayed inside brackets.\n"
|
||||||
|
"o The 'Selects:' line tell what symbol will be automatically\n"
|
||||||
|
" selected if this symbol is selected (y or m)\n"
|
||||||
|
"o The 'Selected by' line tell what symbol has selected this symbol\n"
|
||||||
|
"\n"
|
||||||
|
"Only relevant lines are shown.\n"
|
||||||
|
"\n\n"
|
||||||
|
"Search examples:\n"
|
||||||
|
"Examples: USB => find all CONFIG_ symbols containing USB\n"
|
||||||
|
" ^USB => find all CONFIG_ symbols starting with USB\n"
|
||||||
|
" USB$ => find all CONFIG_ symbols ending with USB\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
static char filename[PATH_MAX+1] = ".config";
|
||||||
|
static int indent;
|
||||||
|
static struct termios ios_org;
|
||||||
|
static int rows = 0, cols = 0;
|
||||||
|
static struct menu *current_menu;
|
||||||
|
static int child_count;
|
||||||
|
static int single_menu_mode;
|
||||||
|
|
||||||
|
static struct dialog_list_item *items[16384]; /* FIXME: This ought to be dynamic. */
|
||||||
|
static int item_no;
|
||||||
|
|
||||||
|
static void conf(struct menu *menu);
|
||||||
|
static void conf_choice(struct menu *menu);
|
||||||
|
static void conf_string(struct menu *menu);
|
||||||
|
static void conf_load(void);
|
||||||
|
static void conf_save(void);
|
||||||
|
static void show_textbox(const char *title, const char *text, int r, int c);
|
||||||
|
static void show_helptext(const char *title, const char *text);
|
||||||
|
static void show_help(struct menu *menu);
|
||||||
|
static void show_file(const char *filename, const char *title, int r, int c);
|
||||||
|
|
||||||
|
static void init_wsize(void)
|
||||||
|
{
|
||||||
|
struct winsize ws;
|
||||||
|
char *env;
|
||||||
|
|
||||||
|
if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
|
||||||
|
rows = ws.ws_row;
|
||||||
|
cols = ws.ws_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rows) {
|
||||||
|
env = getenv("LINES");
|
||||||
|
if (env)
|
||||||
|
rows = atoi(env);
|
||||||
|
if (!rows)
|
||||||
|
rows = 24;
|
||||||
|
}
|
||||||
|
if (!cols) {
|
||||||
|
env = getenv("COLUMNS");
|
||||||
|
if (env)
|
||||||
|
cols = atoi(env);
|
||||||
|
if (!cols)
|
||||||
|
cols = 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows < 19 || cols < 80) {
|
||||||
|
fprintf(stderr, "Your display is too small to run Menuconfig!\n");
|
||||||
|
fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
rows -= 4;
|
||||||
|
cols -= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cinit(void)
|
||||||
|
{
|
||||||
|
item_no = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmake(void)
|
||||||
|
{
|
||||||
|
items[item_no] = malloc(sizeof(struct dialog_list_item));
|
||||||
|
memset(items[item_no], 0, sizeof(struct dialog_list_item));
|
||||||
|
items[item_no]->tag = malloc(32); items[item_no]->tag[0] = 0;
|
||||||
|
items[item_no]->name = malloc(512); items[item_no]->name[0] = 0;
|
||||||
|
items[item_no]->namelen = 0;
|
||||||
|
item_no++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cprint_name(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (!item_no)
|
||||||
|
cmake();
|
||||||
|
va_start(ap, fmt);
|
||||||
|
res = vsnprintf(items[item_no - 1]->name + items[item_no - 1]->namelen,
|
||||||
|
512 - items[item_no - 1]->namelen, fmt, ap);
|
||||||
|
if (res > 0)
|
||||||
|
items[item_no - 1]->namelen += res;
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cprint_tag(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (!item_no)
|
||||||
|
cmake();
|
||||||
|
va_start(ap, fmt);
|
||||||
|
res = vsnprintf(items[item_no - 1]->tag, 32, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cdone(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < item_no; i++) {
|
||||||
|
free(items[i]->tag);
|
||||||
|
free(items[i]->name);
|
||||||
|
free(items[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
item_no = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_prompt_str(struct gstr *r, struct property *prop)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
struct menu *submenu[8], *menu;
|
||||||
|
|
||||||
|
str_printf(r, "Prompt: %s\n", prop->text);
|
||||||
|
str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
|
||||||
|
prop->menu->lineno);
|
||||||
|
if (!expr_is_yes(prop->visible.expr)) {
|
||||||
|
str_append(r, " Depends on: ");
|
||||||
|
expr_gstr_print(prop->visible.expr, r);
|
||||||
|
str_append(r, "\n");
|
||||||
|
}
|
||||||
|
menu = prop->menu->parent;
|
||||||
|
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
|
||||||
|
submenu[i++] = menu;
|
||||||
|
if (i > 0) {
|
||||||
|
str_printf(r, " Location:\n");
|
||||||
|
for (j = 4; --i >= 0; j += 2) {
|
||||||
|
menu = submenu[i];
|
||||||
|
str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
|
||||||
|
if (menu->sym) {
|
||||||
|
str_printf(r, " (%s [=%s])", menu->sym->name ?
|
||||||
|
menu->sym->name : "<choice>",
|
||||||
|
sym_get_string_value(menu->sym));
|
||||||
|
}
|
||||||
|
str_append(r, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_symbol_str(struct gstr *r, struct symbol *sym)
|
||||||
|
{
|
||||||
|
bool hit;
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
str_printf(r, "Symbol: %s [=%s]\n", sym->name,
|
||||||
|
sym_get_string_value(sym));
|
||||||
|
for_all_prompts(sym, prop)
|
||||||
|
get_prompt_str(r, prop);
|
||||||
|
hit = false;
|
||||||
|
for_all_properties(sym, prop, P_SELECT) {
|
||||||
|
if (!hit) {
|
||||||
|
str_append(r, " Selects: ");
|
||||||
|
hit = true;
|
||||||
|
} else
|
||||||
|
str_printf(r, " && ");
|
||||||
|
expr_gstr_print(prop->expr, r);
|
||||||
|
}
|
||||||
|
if (hit)
|
||||||
|
str_append(r, "\n");
|
||||||
|
if (sym->rev_dep.expr) {
|
||||||
|
str_append(r, " Selected by: ");
|
||||||
|
expr_gstr_print(sym->rev_dep.expr, r);
|
||||||
|
str_append(r, "\n");
|
||||||
|
}
|
||||||
|
str_append(r, "\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct gstr get_relations_str(struct symbol **sym_arr)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
struct gstr res = str_new();
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
|
||||||
|
get_symbol_str(&res, sym);
|
||||||
|
if (!i)
|
||||||
|
str_append(&res, "No matches found.\n");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void search_conf(void)
|
||||||
|
{
|
||||||
|
struct symbol **sym_arr;
|
||||||
|
struct gstr res;
|
||||||
|
|
||||||
|
again:
|
||||||
|
switch (dialog_inputbox("Search Configuration Parameter",
|
||||||
|
"Enter Keyword", 10, 75,
|
||||||
|
NULL)) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
show_helptext("Search Configuration", search_help);
|
||||||
|
goto again;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym_arr = sym_re_search(dialog_input_result);
|
||||||
|
res = get_relations_str(sym_arr);
|
||||||
|
free(sym_arr);
|
||||||
|
show_textbox("Search Results", str_get(&res), 0, 0);
|
||||||
|
str_free(&res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_conf(struct menu *menu)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
struct property *prop;
|
||||||
|
struct menu *child;
|
||||||
|
int type, tmp, doint = 2;
|
||||||
|
tristate val;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
if (!menu_is_visible(menu))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sym = menu->sym;
|
||||||
|
prop = menu->prompt;
|
||||||
|
if (!sym) {
|
||||||
|
if (prop && menu != current_menu) {
|
||||||
|
const char *prompt = menu_get_prompt(menu);
|
||||||
|
switch (prop->type) {
|
||||||
|
case P_MENU:
|
||||||
|
child_count++;
|
||||||
|
cmake();
|
||||||
|
cprint_tag("m%p", menu);
|
||||||
|
|
||||||
|
if (single_menu_mode) {
|
||||||
|
cprint_name("%s%*c%s",
|
||||||
|
menu->data ? "-->" : "++>",
|
||||||
|
indent + 1, ' ', prompt);
|
||||||
|
} else {
|
||||||
|
cprint_name(" %*c%s --->", indent + 1, ' ', prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (single_menu_mode && menu->data)
|
||||||
|
goto conf_childs;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
if (prompt) {
|
||||||
|
child_count++;
|
||||||
|
cmake();
|
||||||
|
cprint_tag(":%p", menu);
|
||||||
|
cprint_name("---%*c%s", indent + 1, ' ', prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
doint = 0;
|
||||||
|
goto conf_childs;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmake();
|
||||||
|
type = sym_get_type(sym);
|
||||||
|
if (sym_is_choice(sym)) {
|
||||||
|
struct symbol *def_sym = sym_get_choice_value(sym);
|
||||||
|
struct menu *def_menu = NULL;
|
||||||
|
|
||||||
|
child_count++;
|
||||||
|
for (child = menu->list; child; child = child->next) {
|
||||||
|
if (menu_is_visible(child) && child->sym == def_sym)
|
||||||
|
def_menu = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = sym_get_tristate_value(sym);
|
||||||
|
if (sym_is_changable(sym)) {
|
||||||
|
cprint_tag("t%p", menu);
|
||||||
|
switch (type) {
|
||||||
|
case S_BOOLEAN:
|
||||||
|
cprint_name("[%c]", val == no ? ' ' : '*');
|
||||||
|
break;
|
||||||
|
case S_TRISTATE:
|
||||||
|
switch (val) {
|
||||||
|
case yes: ch = '*'; break;
|
||||||
|
case mod: ch = 'M'; break;
|
||||||
|
default: ch = ' '; break;
|
||||||
|
}
|
||||||
|
cprint_name("<%c>", ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cprint_tag("%c%p", def_menu ? 't' : ':', menu);
|
||||||
|
cprint_name(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
cprint_name("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
|
||||||
|
if (val == yes) {
|
||||||
|
if (def_menu) {
|
||||||
|
cprint_name(" (%s)", menu_get_prompt(def_menu));
|
||||||
|
cprint_name(" --->");
|
||||||
|
if (def_menu->list) {
|
||||||
|
indent += 2;
|
||||||
|
build_conf(def_menu);
|
||||||
|
indent -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (menu == current_menu) {
|
||||||
|
cprint_tag(":%p", menu);
|
||||||
|
cprint_name("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
|
||||||
|
goto conf_childs;
|
||||||
|
}
|
||||||
|
child_count++;
|
||||||
|
val = sym_get_tristate_value(sym);
|
||||||
|
if (sym_is_choice_value(sym) && val == yes) {
|
||||||
|
cprint_tag(":%p", menu);
|
||||||
|
cprint_name(" ");
|
||||||
|
} else {
|
||||||
|
switch (type) {
|
||||||
|
case S_BOOLEAN:
|
||||||
|
cprint_tag("t%p", menu);
|
||||||
|
if (sym_is_changable(sym))
|
||||||
|
cprint_name("[%c]", val == no ? ' ' : '*');
|
||||||
|
else
|
||||||
|
cprint_name("---");
|
||||||
|
break;
|
||||||
|
case S_TRISTATE:
|
||||||
|
cprint_tag("t%p", menu);
|
||||||
|
switch (val) {
|
||||||
|
case yes: ch = '*'; break;
|
||||||
|
case mod: ch = 'M'; break;
|
||||||
|
default: ch = ' '; break;
|
||||||
|
}
|
||||||
|
if (sym_is_changable(sym))
|
||||||
|
cprint_name("<%c>", ch);
|
||||||
|
else
|
||||||
|
cprint_name("---");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cprint_tag("s%p", menu);
|
||||||
|
tmp = cprint_name("(%s)", sym_get_string_value(sym));
|
||||||
|
tmp = indent - tmp + 4;
|
||||||
|
if (tmp < 0)
|
||||||
|
tmp = 0;
|
||||||
|
cprint_name("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
|
||||||
|
(sym_has_value(sym) || !sym_is_changable(sym)) ?
|
||||||
|
"" : " (NEW)");
|
||||||
|
goto conf_childs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cprint_name("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
|
||||||
|
(sym_has_value(sym) || !sym_is_changable(sym)) ?
|
||||||
|
"" : " (NEW)");
|
||||||
|
if (menu->prompt->type == P_MENU) {
|
||||||
|
cprint_name(" --->");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conf_childs:
|
||||||
|
indent += doint;
|
||||||
|
for (child = menu->list; child; child = child->next)
|
||||||
|
build_conf(child);
|
||||||
|
indent -= doint;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void conf(struct menu *menu)
|
||||||
|
{
|
||||||
|
struct dialog_list_item *active_item = NULL;
|
||||||
|
struct menu *submenu;
|
||||||
|
const char *prompt = menu_get_prompt(menu);
|
||||||
|
struct symbol *sym;
|
||||||
|
char active_entry[40];
|
||||||
|
int stat, type;
|
||||||
|
|
||||||
|
unlink("lxdialog.scrltmp");
|
||||||
|
active_entry[0] = 0;
|
||||||
|
while (1) {
|
||||||
|
indent = 0;
|
||||||
|
child_count = 0;
|
||||||
|
current_menu = menu;
|
||||||
|
cdone(); cinit();
|
||||||
|
build_conf(menu);
|
||||||
|
if (!child_count)
|
||||||
|
break;
|
||||||
|
if (menu == &rootmenu) {
|
||||||
|
cmake(); cprint_tag(":"); cprint_name("--- ");
|
||||||
|
cmake(); cprint_tag("L"); cprint_name("Load an Alternate Configuration File");
|
||||||
|
cmake(); cprint_tag("S"); cprint_name("Save Configuration to an Alternate File");
|
||||||
|
}
|
||||||
|
dialog_clear();
|
||||||
|
stat = dialog_menu(prompt ? prompt : "Main Menu",
|
||||||
|
menu_instructions, rows, cols, rows - 10,
|
||||||
|
active_entry, item_no, items);
|
||||||
|
if (stat < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (stat == 1 || stat == 255)
|
||||||
|
break;
|
||||||
|
|
||||||
|
active_item = first_sel_item(item_no, items);
|
||||||
|
if (!active_item)
|
||||||
|
continue;
|
||||||
|
active_item->selected = 0;
|
||||||
|
strncpy(active_entry, active_item->tag, sizeof(active_entry));
|
||||||
|
active_entry[sizeof(active_entry)-1] = 0;
|
||||||
|
type = active_entry[0];
|
||||||
|
if (!type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sym = NULL;
|
||||||
|
submenu = NULL;
|
||||||
|
if (sscanf(active_entry + 1, "%p", &submenu) == 1)
|
||||||
|
sym = submenu->sym;
|
||||||
|
|
||||||
|
switch (stat) {
|
||||||
|
case 0:
|
||||||
|
switch (type) {
|
||||||
|
case 'm':
|
||||||
|
if (single_menu_mode)
|
||||||
|
submenu->data = (void *) (long) !submenu->data;
|
||||||
|
else
|
||||||
|
conf(submenu);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
|
||||||
|
conf_choice(submenu);
|
||||||
|
else if (submenu->prompt->type == P_MENU)
|
||||||
|
conf(submenu);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
conf_string(submenu);
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
conf_load();
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
conf_save();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (sym)
|
||||||
|
show_help(submenu);
|
||||||
|
else
|
||||||
|
show_helptext("README", mconf_readme);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (type == 't') {
|
||||||
|
if (sym_set_tristate_value(sym, yes))
|
||||||
|
break;
|
||||||
|
if (sym_set_tristate_value(sym, mod))
|
||||||
|
show_textbox(NULL, setmod_text, 6, 74);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (type == 't')
|
||||||
|
sym_set_tristate_value(sym, no);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
if (type == 't')
|
||||||
|
sym_set_tristate_value(sym, mod);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
if (type == 't')
|
||||||
|
sym_toggle_tristate_value(sym);
|
||||||
|
else if (type == 'm')
|
||||||
|
conf(submenu);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
search_conf();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_textbox(const char *title, const char *text, int r, int c)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = creat(".help.tmp", 0777);
|
||||||
|
write(fd, text, strlen(text));
|
||||||
|
close(fd);
|
||||||
|
show_file(".help.tmp", title, r, c);
|
||||||
|
unlink(".help.tmp");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_helptext(const char *title, const char *text)
|
||||||
|
{
|
||||||
|
show_textbox(title, text, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_help(struct menu *menu)
|
||||||
|
{
|
||||||
|
struct gstr help = str_new();
|
||||||
|
struct symbol *sym = menu->sym;
|
||||||
|
|
||||||
|
if (sym->help)
|
||||||
|
{
|
||||||
|
if (sym->name) {
|
||||||
|
str_printf(&help, "%s:\n\n", sym->name);
|
||||||
|
str_append(&help, sym->help);
|
||||||
|
str_append(&help, "\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str_append(&help, nohelp_text);
|
||||||
|
}
|
||||||
|
get_symbol_str(&help, sym);
|
||||||
|
show_helptext(menu_get_prompt(menu), str_get(&help));
|
||||||
|
str_free(&help);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_file(const char *filename, const char *title, int r, int c)
|
||||||
|
{
|
||||||
|
while (dialog_textbox(title, filename, r ? r : rows, c ? c : cols) < 0)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void conf_choice(struct menu *menu)
|
||||||
|
{
|
||||||
|
const char *prompt = menu_get_prompt(menu);
|
||||||
|
struct menu *child;
|
||||||
|
struct symbol *active;
|
||||||
|
|
||||||
|
active = sym_get_choice_value(menu->sym);
|
||||||
|
while (1) {
|
||||||
|
current_menu = menu;
|
||||||
|
cdone(); cinit();
|
||||||
|
for (child = menu->list; child; child = child->next) {
|
||||||
|
if (!menu_is_visible(child))
|
||||||
|
continue;
|
||||||
|
cmake();
|
||||||
|
cprint_tag("%p", child);
|
||||||
|
cprint_name("%s", menu_get_prompt(child));
|
||||||
|
if (child->sym == sym_get_choice_value(menu->sym))
|
||||||
|
items[item_no - 1]->selected = 1; /* ON */
|
||||||
|
else if (child->sym == active)
|
||||||
|
items[item_no - 1]->selected = 2; /* SELECTED */
|
||||||
|
else
|
||||||
|
items[item_no - 1]->selected = 0; /* OFF */
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dialog_checklist(prompt ? prompt : "Main Menu",
|
||||||
|
radiolist_instructions, 15, 70, 6,
|
||||||
|
item_no, items, FLAG_RADIO)) {
|
||||||
|
case 0:
|
||||||
|
if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) != 1)
|
||||||
|
break;
|
||||||
|
sym_set_tristate_value(child->sym, yes);
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) == 1) {
|
||||||
|
show_help(child);
|
||||||
|
active = child->sym;
|
||||||
|
} else
|
||||||
|
show_help(menu);
|
||||||
|
break;
|
||||||
|
case 255:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void conf_string(struct menu *menu)
|
||||||
|
{
|
||||||
|
const char *prompt = menu_get_prompt(menu);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
char *heading;
|
||||||
|
|
||||||
|
switch (sym_get_type(menu->sym)) {
|
||||||
|
case S_INT:
|
||||||
|
heading = (char *) inputbox_instructions_int;
|
||||||
|
break;
|
||||||
|
case S_HEX:
|
||||||
|
heading = (char *) inputbox_instructions_hex;
|
||||||
|
break;
|
||||||
|
case S_STRING:
|
||||||
|
heading = (char *) inputbox_instructions_string;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
heading = "Internal mconf error!";
|
||||||
|
/* panic? */;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dialog_inputbox(prompt ? prompt : "Main Menu",
|
||||||
|
heading, 10, 75,
|
||||||
|
sym_get_string_value(menu->sym))) {
|
||||||
|
case 0:
|
||||||
|
if (sym_set_string_value(menu->sym, dialog_input_result))
|
||||||
|
return;
|
||||||
|
show_textbox(NULL, "You have made an invalid entry.", 5, 43);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
show_help(menu);
|
||||||
|
break;
|
||||||
|
case 255:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void conf_load(void)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
switch (dialog_inputbox(NULL, load_config_text, 11, 55,
|
||||||
|
filename)) {
|
||||||
|
case 0:
|
||||||
|
if (!dialog_input_result[0])
|
||||||
|
return;
|
||||||
|
if (!conf_read(dialog_input_result))
|
||||||
|
return;
|
||||||
|
show_textbox(NULL, "File does not exist!", 5, 38);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
show_helptext("Load Alternate Configuration", load_config_help);
|
||||||
|
break;
|
||||||
|
case 255:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void conf_save(void)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
switch (dialog_inputbox(NULL, save_config_text, 11, 55,
|
||||||
|
filename)) {
|
||||||
|
case 0:
|
||||||
|
if (!dialog_input_result[0])
|
||||||
|
return;
|
||||||
|
if (!conf_write(dialog_input_result))
|
||||||
|
return;
|
||||||
|
show_textbox(NULL, "Can't create file! Probably a nonexistent directory.", 5, 60);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
show_helptext("Save Alternate Configuration", save_config_help);
|
||||||
|
break;
|
||||||
|
case 255:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void conf_cleanup(void)
|
||||||
|
{
|
||||||
|
tcsetattr(1, TCSAFLUSH, &ios_org);
|
||||||
|
unlink(".help.tmp");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void winch_handler(int sig)
|
||||||
|
{
|
||||||
|
struct winsize ws;
|
||||||
|
|
||||||
|
if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
|
||||||
|
rows = 24;
|
||||||
|
cols = 80;
|
||||||
|
} else {
|
||||||
|
rows = ws.ws_row;
|
||||||
|
cols = ws.ws_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows < 19 || cols < 80) {
|
||||||
|
end_dialog();
|
||||||
|
fprintf(stderr, "Your display is too small to run Menuconfig!\n");
|
||||||
|
fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
rows -= 4;
|
||||||
|
cols -= 5;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int ac, char **av)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
char *mode;
|
||||||
|
int stat;
|
||||||
|
|
||||||
|
conf_parse(av[1]);
|
||||||
|
conf_read(NULL);
|
||||||
|
|
||||||
|
sym = sym_lookup("VERSION", 0);
|
||||||
|
sym_calc_value(sym);
|
||||||
|
snprintf(menu_backtitle, 128, "JHALFS v%s Configuration",
|
||||||
|
sym_get_string_value(sym));
|
||||||
|
|
||||||
|
mode = getenv("MENUCONFIG_MODE");
|
||||||
|
if (mode) {
|
||||||
|
if (!strcasecmp(mode, "single_menu"))
|
||||||
|
single_menu_mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcgetattr(1, &ios_org);
|
||||||
|
atexit(conf_cleanup);
|
||||||
|
init_wsize();
|
||||||
|
init_dialog();
|
||||||
|
signal(SIGWINCH, winch_handler);
|
||||||
|
conf(&rootmenu);
|
||||||
|
end_dialog();
|
||||||
|
|
||||||
|
/* Restart dialog to act more like when lxdialog was still separate */
|
||||||
|
init_dialog();
|
||||||
|
do {
|
||||||
|
stat = dialog_yesno(NULL,
|
||||||
|
"Do you wish to save your new JHALFS configuration?", 5, 60);
|
||||||
|
} while (stat < 0);
|
||||||
|
end_dialog();
|
||||||
|
|
||||||
|
if (stat == 0) {
|
||||||
|
conf_write(NULL);
|
||||||
|
printf("\n"
|
||||||
|
"*** End of JHALFS configuration.\n");
|
||||||
|
} else
|
||||||
|
printf("\n\nYour JHALFS configuration changes were NOT saved.\n\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
390
menu/menu.c
Normal file
390
menu/menu.c
Normal file
|
@ -0,0 +1,390 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||||
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define LKC_DIRECT_LINK
|
||||||
|
#include "lkc.h"
|
||||||
|
|
||||||
|
struct menu rootmenu;
|
||||||
|
static struct menu **last_entry_ptr;
|
||||||
|
|
||||||
|
struct file *file_list;
|
||||||
|
struct file *current_file;
|
||||||
|
|
||||||
|
static void menu_warn(struct menu *menu, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prop_warn(struct property *prop, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_init(void)
|
||||||
|
{
|
||||||
|
current_entry = current_menu = &rootmenu;
|
||||||
|
last_entry_ptr = &rootmenu.list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_add_entry(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct menu *menu;
|
||||||
|
|
||||||
|
menu = malloc(sizeof(*menu));
|
||||||
|
memset(menu, 0, sizeof(*menu));
|
||||||
|
menu->sym = sym;
|
||||||
|
menu->parent = current_menu;
|
||||||
|
menu->file = current_file;
|
||||||
|
menu->lineno = zconf_lineno();
|
||||||
|
|
||||||
|
*last_entry_ptr = menu;
|
||||||
|
last_entry_ptr = &menu->next;
|
||||||
|
current_entry = menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_end_entry(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_add_menu(void)
|
||||||
|
{
|
||||||
|
current_menu = current_entry;
|
||||||
|
last_entry_ptr = ¤t_entry->list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_end_menu(void)
|
||||||
|
{
|
||||||
|
last_entry_ptr = ¤t_menu->next;
|
||||||
|
current_menu = current_menu->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct expr *menu_check_dep(struct expr *e)
|
||||||
|
{
|
||||||
|
if (!e)
|
||||||
|
return e;
|
||||||
|
|
||||||
|
switch (e->type) {
|
||||||
|
case E_NOT:
|
||||||
|
e->left.expr = menu_check_dep(e->left.expr);
|
||||||
|
break;
|
||||||
|
case E_OR:
|
||||||
|
case E_AND:
|
||||||
|
e->left.expr = menu_check_dep(e->left.expr);
|
||||||
|
e->right.expr = menu_check_dep(e->right.expr);
|
||||||
|
break;
|
||||||
|
case E_SYMBOL:
|
||||||
|
/* change 'm' into 'm' && MODULES */
|
||||||
|
if (e->left.sym == &symbol_mod)
|
||||||
|
return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_add_dep(struct expr *dep)
|
||||||
|
{
|
||||||
|
current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_set_type(int type)
|
||||||
|
{
|
||||||
|
struct symbol *sym = current_entry->sym;
|
||||||
|
|
||||||
|
if (sym->type == type)
|
||||||
|
return;
|
||||||
|
if (sym->type == S_UNKNOWN) {
|
||||||
|
sym->type = type;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n",
|
||||||
|
sym->name ? sym->name : "<choice>",
|
||||||
|
sym_type_name(sym->type), sym_type_name(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
|
||||||
|
{
|
||||||
|
struct property *prop = prop_alloc(type, current_entry->sym);
|
||||||
|
|
||||||
|
prop->menu = current_entry;
|
||||||
|
prop->text = prompt;
|
||||||
|
prop->expr = expr;
|
||||||
|
prop->visible.expr = menu_check_dep(dep);
|
||||||
|
|
||||||
|
if (prompt) {
|
||||||
|
if (current_entry->prompt)
|
||||||
|
menu_warn(current_entry, "prompt redefined\n");
|
||||||
|
current_entry->prompt = prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
|
||||||
|
{
|
||||||
|
menu_add_prop(type, prompt, NULL, dep);
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
|
||||||
|
{
|
||||||
|
menu_add_prop(type, NULL, expr, dep);
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
|
||||||
|
{
|
||||||
|
menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sym_check_prop(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
struct symbol *sym2;
|
||||||
|
for (prop = sym->prop; prop; prop = prop->next) {
|
||||||
|
switch (prop->type) {
|
||||||
|
case P_DEFAULT:
|
||||||
|
if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
|
||||||
|
prop->expr->type != E_SYMBOL)
|
||||||
|
prop_warn(prop,
|
||||||
|
"default for config symbol '%'"
|
||||||
|
" must be a single symbol", sym->name);
|
||||||
|
break;
|
||||||
|
case P_SELECT:
|
||||||
|
sym2 = prop_get_symbol(prop);
|
||||||
|
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
|
||||||
|
prop_warn(prop,
|
||||||
|
"config symbol '%s' uses select, but is "
|
||||||
|
"not boolean or tristate", sym->name);
|
||||||
|
else if (sym2->type == S_UNKNOWN)
|
||||||
|
prop_warn(prop,
|
||||||
|
"'select' used by config symbol '%s' "
|
||||||
|
"refer to undefined symbol '%s'",
|
||||||
|
sym->name, sym2->name);
|
||||||
|
else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
|
||||||
|
prop_warn(prop,
|
||||||
|
"'%s' has wrong type. 'select' only "
|
||||||
|
"accept arguments of boolean and "
|
||||||
|
"tristate type", sym2->name);
|
||||||
|
break;
|
||||||
|
case P_RANGE:
|
||||||
|
if (sym->type != S_INT && sym->type != S_HEX)
|
||||||
|
prop_warn(prop, "range is only allowed "
|
||||||
|
"for int or hex symbols");
|
||||||
|
if (!sym_string_valid(sym, prop->expr->left.sym->name) ||
|
||||||
|
!sym_string_valid(sym, prop->expr->right.sym->name))
|
||||||
|
prop_warn(prop, "range is invalid");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_finalize(struct menu *parent)
|
||||||
|
{
|
||||||
|
struct menu *menu, *last_menu;
|
||||||
|
struct symbol *sym;
|
||||||
|
struct property *prop;
|
||||||
|
struct expr *parentdep, *basedep, *dep, *dep2, **ep;
|
||||||
|
|
||||||
|
sym = parent->sym;
|
||||||
|
if (parent->list) {
|
||||||
|
if (sym && sym_is_choice(sym)) {
|
||||||
|
/* find the first choice value and find out choice type */
|
||||||
|
for (menu = parent->list; menu; menu = menu->next) {
|
||||||
|
if (menu->sym) {
|
||||||
|
current_entry = parent;
|
||||||
|
menu_set_type(menu->sym->type);
|
||||||
|
current_entry = menu;
|
||||||
|
menu_set_type(sym->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parentdep = expr_alloc_symbol(sym);
|
||||||
|
} else if (parent->prompt)
|
||||||
|
parentdep = parent->prompt->visible.expr;
|
||||||
|
else
|
||||||
|
parentdep = parent->dep;
|
||||||
|
|
||||||
|
for (menu = parent->list; menu; menu = menu->next) {
|
||||||
|
basedep = expr_transform(menu->dep);
|
||||||
|
basedep = expr_alloc_and(expr_copy(parentdep), basedep);
|
||||||
|
basedep = expr_eliminate_dups(basedep);
|
||||||
|
menu->dep = basedep;
|
||||||
|
if (menu->sym)
|
||||||
|
prop = menu->sym->prop;
|
||||||
|
else
|
||||||
|
prop = menu->prompt;
|
||||||
|
for (; prop; prop = prop->next) {
|
||||||
|
if (prop->menu != menu)
|
||||||
|
continue;
|
||||||
|
dep = expr_transform(prop->visible.expr);
|
||||||
|
dep = expr_alloc_and(expr_copy(basedep), dep);
|
||||||
|
dep = expr_eliminate_dups(dep);
|
||||||
|
if (menu->sym && menu->sym->type != S_TRISTATE)
|
||||||
|
dep = expr_trans_bool(dep);
|
||||||
|
prop->visible.expr = dep;
|
||||||
|
if (prop->type == P_SELECT) {
|
||||||
|
struct symbol *es = prop_get_symbol(prop);
|
||||||
|
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
|
||||||
|
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (menu = parent->list; menu; menu = menu->next)
|
||||||
|
menu_finalize(menu);
|
||||||
|
} else if (sym) {
|
||||||
|
basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
|
||||||
|
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
|
||||||
|
basedep = expr_eliminate_dups(expr_transform(basedep));
|
||||||
|
last_menu = NULL;
|
||||||
|
for (menu = parent->next; menu; menu = menu->next) {
|
||||||
|
dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
|
||||||
|
if (!expr_contains_symbol(dep, sym))
|
||||||
|
break;
|
||||||
|
if (expr_depends_symbol(dep, sym))
|
||||||
|
goto next;
|
||||||
|
dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
|
||||||
|
dep = expr_eliminate_dups(expr_transform(dep));
|
||||||
|
dep2 = expr_copy(basedep);
|
||||||
|
expr_eliminate_eq(&dep, &dep2);
|
||||||
|
expr_free(dep);
|
||||||
|
if (!expr_is_yes(dep2)) {
|
||||||
|
expr_free(dep2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
expr_free(dep2);
|
||||||
|
next:
|
||||||
|
menu_finalize(menu);
|
||||||
|
menu->parent = parent;
|
||||||
|
last_menu = menu;
|
||||||
|
}
|
||||||
|
if (last_menu) {
|
||||||
|
parent->list = parent->next;
|
||||||
|
parent->next = last_menu->next;
|
||||||
|
last_menu->next = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (menu = parent->list; menu; menu = menu->next) {
|
||||||
|
if (sym && sym_is_choice(sym) && menu->sym) {
|
||||||
|
menu->sym->flags |= SYMBOL_CHOICEVAL;
|
||||||
|
if (!menu->prompt)
|
||||||
|
menu_warn(menu, "choice value must have a prompt");
|
||||||
|
for (prop = menu->sym->prop; prop; prop = prop->next) {
|
||||||
|
if (prop->type == P_PROMPT && prop->menu != menu) {
|
||||||
|
prop_warn(prop, "choice values "
|
||||||
|
"currently only support a "
|
||||||
|
"single prompt");
|
||||||
|
}
|
||||||
|
if (prop->type == P_DEFAULT)
|
||||||
|
prop_warn(prop, "defaults for choice "
|
||||||
|
"values not supported");
|
||||||
|
}
|
||||||
|
current_entry = menu;
|
||||||
|
menu_set_type(sym->type);
|
||||||
|
menu_add_symbol(P_CHOICE, sym, NULL);
|
||||||
|
prop = sym_get_choice_prop(sym);
|
||||||
|
for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
|
||||||
|
;
|
||||||
|
*ep = expr_alloc_one(E_CHOICE, NULL);
|
||||||
|
(*ep)->right.sym = menu->sym;
|
||||||
|
}
|
||||||
|
if (menu->list && (!menu->prompt || !menu->prompt->text)) {
|
||||||
|
for (last_menu = menu->list; ; last_menu = last_menu->next) {
|
||||||
|
last_menu->parent = parent;
|
||||||
|
if (!last_menu->next)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last_menu->next = menu->next;
|
||||||
|
menu->next = menu->list;
|
||||||
|
menu->list = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sym && !(sym->flags & SYMBOL_WARNED)) {
|
||||||
|
if (sym->type == S_UNKNOWN)
|
||||||
|
menu_warn(parent, "config symbol defined "
|
||||||
|
"without type\n");
|
||||||
|
|
||||||
|
if (sym_is_choice(sym) && !parent->prompt)
|
||||||
|
menu_warn(parent, "choice must have a prompt\n");
|
||||||
|
|
||||||
|
/* Check properties connected to this symbol */
|
||||||
|
sym_check_prop(sym);
|
||||||
|
sym->flags |= SYMBOL_WARNED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sym && !sym_is_optional(sym) && parent->prompt) {
|
||||||
|
sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
|
||||||
|
expr_alloc_and(parent->prompt->visible.expr,
|
||||||
|
expr_alloc_symbol(&symbol_mod)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool menu_is_visible(struct menu *menu)
|
||||||
|
{
|
||||||
|
struct menu *child;
|
||||||
|
struct symbol *sym;
|
||||||
|
tristate visible;
|
||||||
|
|
||||||
|
if (!menu->prompt)
|
||||||
|
return false;
|
||||||
|
sym = menu->sym;
|
||||||
|
if (sym) {
|
||||||
|
sym_calc_value(sym);
|
||||||
|
visible = menu->prompt->visible.tri;
|
||||||
|
} else
|
||||||
|
visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
|
||||||
|
|
||||||
|
if (visible != no)
|
||||||
|
return true;
|
||||||
|
if (!sym || sym_get_tristate_value(menu->sym) == no)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (child = menu->list; child; child = child->next)
|
||||||
|
if (menu_is_visible(child))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *menu_get_prompt(struct menu *menu)
|
||||||
|
{
|
||||||
|
if (menu->prompt)
|
||||||
|
return menu->prompt->text;
|
||||||
|
else if (menu->sym)
|
||||||
|
return menu->sym->name;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct menu *menu_get_root_menu(struct menu *menu)
|
||||||
|
{
|
||||||
|
return &rootmenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct menu *menu_get_parent_menu(struct menu *menu)
|
||||||
|
{
|
||||||
|
enum prop_type type;
|
||||||
|
|
||||||
|
for (; menu != &rootmenu; menu = menu->parent) {
|
||||||
|
type = menu->prompt ? menu->prompt->type : 0;
|
||||||
|
if (type == P_MENU)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
809
menu/symbol.c
Normal file
809
menu/symbol.c
Normal file
|
@ -0,0 +1,809 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||||
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
|
#define LKC_DIRECT_LINK
|
||||||
|
#include "lkc.h"
|
||||||
|
|
||||||
|
struct symbol symbol_yes = {
|
||||||
|
.name = "y",
|
||||||
|
.curr = { "y", yes },
|
||||||
|
.flags = SYMBOL_YES|SYMBOL_VALID,
|
||||||
|
}, symbol_mod = {
|
||||||
|
.name = "m",
|
||||||
|
.curr = { "m", mod },
|
||||||
|
.flags = SYMBOL_MOD|SYMBOL_VALID,
|
||||||
|
}, symbol_no = {
|
||||||
|
.name = "n",
|
||||||
|
.curr = { "n", no },
|
||||||
|
.flags = SYMBOL_NO|SYMBOL_VALID,
|
||||||
|
}, symbol_empty = {
|
||||||
|
.name = "",
|
||||||
|
.curr = { "", no },
|
||||||
|
.flags = SYMBOL_VALID,
|
||||||
|
};
|
||||||
|
|
||||||
|
int sym_change_count;
|
||||||
|
struct symbol *modules_sym;
|
||||||
|
tristate modules_val;
|
||||||
|
|
||||||
|
void sym_add_default(struct symbol *sym, const char *def)
|
||||||
|
{
|
||||||
|
struct property *prop = prop_alloc(P_DEFAULT, sym);
|
||||||
|
|
||||||
|
prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sym_init(void)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
char *p;
|
||||||
|
static bool inited = false;
|
||||||
|
|
||||||
|
if (inited)
|
||||||
|
return;
|
||||||
|
inited = true;
|
||||||
|
|
||||||
|
sym = sym_lookup("VERSION", 0);
|
||||||
|
sym->type = S_STRING;
|
||||||
|
sym->flags |= SYMBOL_AUTO;
|
||||||
|
p = getenv("VERSION");
|
||||||
|
if (p)
|
||||||
|
sym_add_default(sym, p);
|
||||||
|
|
||||||
|
sym = sym_lookup("TARGET_ARCH", 0);
|
||||||
|
sym->type = S_STRING;
|
||||||
|
sym->flags |= SYMBOL_AUTO;
|
||||||
|
p = getenv("TARGET_ARCH");
|
||||||
|
if (p)
|
||||||
|
sym_add_default(sym, p);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum symbol_type sym_get_type(struct symbol *sym)
|
||||||
|
{
|
||||||
|
enum symbol_type type = sym->type;
|
||||||
|
|
||||||
|
if (type == S_TRISTATE) {
|
||||||
|
if (sym_is_choice_value(sym) && sym->visible == yes)
|
||||||
|
type = S_BOOLEAN;
|
||||||
|
else if (modules_val == no)
|
||||||
|
type = S_BOOLEAN;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *sym_type_name(enum symbol_type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case S_BOOLEAN:
|
||||||
|
return "boolean";
|
||||||
|
case S_TRISTATE:
|
||||||
|
return "tristate";
|
||||||
|
case S_INT:
|
||||||
|
return "integer";
|
||||||
|
case S_HEX:
|
||||||
|
return "hex";
|
||||||
|
case S_STRING:
|
||||||
|
return "string";
|
||||||
|
case S_UNKNOWN:
|
||||||
|
return "unknown";
|
||||||
|
case S_OTHER:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct property *sym_get_choice_prop(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
for_all_choices(sym, prop)
|
||||||
|
return prop;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct property *sym_get_default_prop(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
for_all_defaults(sym, prop) {
|
||||||
|
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
||||||
|
if (prop->visible.tri != no)
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct property *sym_get_range_prop(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
for_all_properties(sym, prop, P_RANGE) {
|
||||||
|
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
||||||
|
if (prop->visible.tri != no)
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sym_calc_visibility(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
tristate tri;
|
||||||
|
|
||||||
|
/* any prompt visible? */
|
||||||
|
tri = no;
|
||||||
|
for_all_prompts(sym, prop) {
|
||||||
|
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
||||||
|
tri = E_OR(tri, prop->visible.tri);
|
||||||
|
}
|
||||||
|
if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
|
||||||
|
tri = yes;
|
||||||
|
if (sym->visible != tri) {
|
||||||
|
sym->visible = tri;
|
||||||
|
sym_set_changed(sym);
|
||||||
|
}
|
||||||
|
if (sym_is_choice_value(sym))
|
||||||
|
return;
|
||||||
|
tri = no;
|
||||||
|
if (sym->rev_dep.expr)
|
||||||
|
tri = expr_calc_value(sym->rev_dep.expr);
|
||||||
|
if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
||||||
|
tri = yes;
|
||||||
|
if (sym->rev_dep.tri != tri) {
|
||||||
|
sym->rev_dep.tri = tri;
|
||||||
|
sym_set_changed(sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct symbol *sym_calc_choice(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct symbol *def_sym;
|
||||||
|
struct property *prop;
|
||||||
|
struct expr *e;
|
||||||
|
|
||||||
|
/* is the user choice visible? */
|
||||||
|
def_sym = sym->user.val;
|
||||||
|
if (def_sym) {
|
||||||
|
sym_calc_visibility(def_sym);
|
||||||
|
if (def_sym->visible != no)
|
||||||
|
return def_sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* any of the defaults visible? */
|
||||||
|
for_all_defaults(sym, prop) {
|
||||||
|
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
||||||
|
if (prop->visible.tri == no)
|
||||||
|
continue;
|
||||||
|
def_sym = prop_get_symbol(prop);
|
||||||
|
sym_calc_visibility(def_sym);
|
||||||
|
if (def_sym->visible != no)
|
||||||
|
return def_sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* just get the first visible value */
|
||||||
|
prop = sym_get_choice_prop(sym);
|
||||||
|
for (e = prop->expr; e; e = e->left.expr) {
|
||||||
|
def_sym = e->right.sym;
|
||||||
|
sym_calc_visibility(def_sym);
|
||||||
|
if (def_sym->visible != no)
|
||||||
|
return def_sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no choice? reset tristate value */
|
||||||
|
sym->curr.tri = no;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sym_calc_value(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct symbol_value newval, oldval;
|
||||||
|
struct property *prop;
|
||||||
|
struct expr *e;
|
||||||
|
|
||||||
|
if (!sym)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sym->flags & SYMBOL_VALID)
|
||||||
|
return;
|
||||||
|
sym->flags |= SYMBOL_VALID;
|
||||||
|
|
||||||
|
oldval = sym->curr;
|
||||||
|
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_INT:
|
||||||
|
case S_HEX:
|
||||||
|
case S_STRING:
|
||||||
|
newval = symbol_empty.curr;
|
||||||
|
break;
|
||||||
|
case S_BOOLEAN:
|
||||||
|
case S_TRISTATE:
|
||||||
|
newval = symbol_no.curr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sym->curr.val = sym->name;
|
||||||
|
sym->curr.tri = no;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!sym_is_choice_value(sym))
|
||||||
|
sym->flags &= ~SYMBOL_WRITE;
|
||||||
|
|
||||||
|
sym_calc_visibility(sym);
|
||||||
|
|
||||||
|
/* set default if recursively called */
|
||||||
|
sym->curr = newval;
|
||||||
|
|
||||||
|
switch (sym_get_type(sym)) {
|
||||||
|
case S_BOOLEAN:
|
||||||
|
case S_TRISTATE:
|
||||||
|
if (sym_is_choice_value(sym) && sym->visible == yes) {
|
||||||
|
prop = sym_get_choice_prop(sym);
|
||||||
|
newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
|
||||||
|
} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
|
||||||
|
sym->flags |= SYMBOL_WRITE;
|
||||||
|
if (sym_has_value(sym))
|
||||||
|
newval.tri = sym->user.tri;
|
||||||
|
else if (!sym_is_choice(sym)) {
|
||||||
|
prop = sym_get_default_prop(sym);
|
||||||
|
if (prop)
|
||||||
|
newval.tri = expr_calc_value(prop->expr);
|
||||||
|
}
|
||||||
|
newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
|
||||||
|
} else if (!sym_is_choice(sym)) {
|
||||||
|
prop = sym_get_default_prop(sym);
|
||||||
|
if (prop) {
|
||||||
|
sym->flags |= SYMBOL_WRITE;
|
||||||
|
newval.tri = expr_calc_value(prop->expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
||||||
|
newval.tri = yes;
|
||||||
|
break;
|
||||||
|
case S_STRING:
|
||||||
|
case S_HEX:
|
||||||
|
case S_INT:
|
||||||
|
if (sym->visible != no) {
|
||||||
|
sym->flags |= SYMBOL_WRITE;
|
||||||
|
if (sym_has_value(sym)) {
|
||||||
|
newval.val = sym->user.val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prop = sym_get_default_prop(sym);
|
||||||
|
if (prop) {
|
||||||
|
struct symbol *ds = prop_get_symbol(prop);
|
||||||
|
if (ds) {
|
||||||
|
sym->flags |= SYMBOL_WRITE;
|
||||||
|
sym_calc_value(ds);
|
||||||
|
newval.val = ds->curr.val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym->curr = newval;
|
||||||
|
if (sym_is_choice(sym) && newval.tri == yes)
|
||||||
|
sym->curr.val = sym_calc_choice(sym);
|
||||||
|
|
||||||
|
if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
|
||||||
|
sym_set_changed(sym);
|
||||||
|
if (modules_sym == sym)
|
||||||
|
modules_val = modules_sym->curr.tri;
|
||||||
|
|
||||||
|
if (sym_is_choice(sym)) {
|
||||||
|
int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
|
||||||
|
prop = sym_get_choice_prop(sym);
|
||||||
|
for (e = prop->expr; e; e = e->left.expr) {
|
||||||
|
e->right.sym->flags |= flags;
|
||||||
|
if (flags & SYMBOL_CHANGED)
|
||||||
|
sym_set_changed(e->right.sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sym_clear_all_valid(void)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for_all_symbols(i, sym)
|
||||||
|
sym->flags &= ~SYMBOL_VALID;
|
||||||
|
sym_change_count++;
|
||||||
|
if (modules_sym)
|
||||||
|
sym_calc_value(modules_sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sym_set_changed(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
sym->flags |= SYMBOL_CHANGED;
|
||||||
|
for (prop = sym->prop; prop; prop = prop->next) {
|
||||||
|
if (prop->menu)
|
||||||
|
prop->menu->flags |= MENU_CHANGED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sym_set_all_changed(void)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for_all_symbols(i, sym)
|
||||||
|
sym_set_changed(sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sym_tristate_within_range(struct symbol *sym, tristate val)
|
||||||
|
{
|
||||||
|
int type = sym_get_type(sym);
|
||||||
|
|
||||||
|
if (sym->visible == no)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (type != S_BOOLEAN && type != S_TRISTATE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (type == S_BOOLEAN && val == mod)
|
||||||
|
return false;
|
||||||
|
if (sym->visible <= sym->rev_dep.tri)
|
||||||
|
return false;
|
||||||
|
if (sym_is_choice_value(sym) && sym->visible == yes)
|
||||||
|
return val == yes;
|
||||||
|
return val >= sym->rev_dep.tri && val <= sym->visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sym_set_tristate_value(struct symbol *sym, tristate val)
|
||||||
|
{
|
||||||
|
tristate oldval = sym_get_tristate_value(sym);
|
||||||
|
|
||||||
|
if (oldval != val && !sym_tristate_within_range(sym, val))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (sym->flags & SYMBOL_NEW) {
|
||||||
|
sym->flags &= ~SYMBOL_NEW;
|
||||||
|
sym_set_changed(sym);
|
||||||
|
}
|
||||||
|
if (sym_is_choice_value(sym) && val == yes) {
|
||||||
|
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
|
||||||
|
|
||||||
|
cs->user.val = sym;
|
||||||
|
cs->flags &= ~SYMBOL_NEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym->user.tri = val;
|
||||||
|
if (oldval != val) {
|
||||||
|
sym_clear_all_valid();
|
||||||
|
if (sym == modules_sym)
|
||||||
|
sym_set_all_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
tristate sym_toggle_tristate_value(struct symbol *sym)
|
||||||
|
{
|
||||||
|
tristate oldval, newval;
|
||||||
|
|
||||||
|
oldval = newval = sym_get_tristate_value(sym);
|
||||||
|
do {
|
||||||
|
switch (newval) {
|
||||||
|
case no:
|
||||||
|
newval = mod;
|
||||||
|
break;
|
||||||
|
case mod:
|
||||||
|
newval = yes;
|
||||||
|
break;
|
||||||
|
case yes:
|
||||||
|
newval = no;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sym_set_tristate_value(sym, newval))
|
||||||
|
break;
|
||||||
|
} while (oldval != newval);
|
||||||
|
return newval;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sym_string_valid(struct symbol *sym, const char *str)
|
||||||
|
{
|
||||||
|
signed char ch;
|
||||||
|
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_STRING:
|
||||||
|
return true;
|
||||||
|
case S_INT:
|
||||||
|
ch = *str++;
|
||||||
|
if (ch == '-')
|
||||||
|
ch = *str++;
|
||||||
|
if (!isdigit(ch))
|
||||||
|
return false;
|
||||||
|
if (ch == '0' && *str != 0)
|
||||||
|
return false;
|
||||||
|
while ((ch = *str++)) {
|
||||||
|
if (!isdigit(ch))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case S_HEX:
|
||||||
|
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
|
||||||
|
str += 2;
|
||||||
|
ch = *str++;
|
||||||
|
do {
|
||||||
|
if (!isxdigit(ch))
|
||||||
|
return false;
|
||||||
|
} while ((ch = *str++));
|
||||||
|
return true;
|
||||||
|
case S_BOOLEAN:
|
||||||
|
case S_TRISTATE:
|
||||||
|
switch (str[0]) {
|
||||||
|
case 'y': case 'Y':
|
||||||
|
case 'm': case 'M':
|
||||||
|
case 'n': case 'N':
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sym_string_within_range(struct symbol *sym, const char *str)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_STRING:
|
||||||
|
return sym_string_valid(sym, str);
|
||||||
|
case S_INT:
|
||||||
|
if (!sym_string_valid(sym, str))
|
||||||
|
return false;
|
||||||
|
prop = sym_get_range_prop(sym);
|
||||||
|
if (!prop)
|
||||||
|
return true;
|
||||||
|
val = strtol(str, NULL, 10);
|
||||||
|
return val >= strtol(prop->expr->left.sym->name, NULL, 10) &&
|
||||||
|
val <= strtol(prop->expr->right.sym->name, NULL, 10);
|
||||||
|
case S_HEX:
|
||||||
|
if (!sym_string_valid(sym, str))
|
||||||
|
return false;
|
||||||
|
prop = sym_get_range_prop(sym);
|
||||||
|
if (!prop)
|
||||||
|
return true;
|
||||||
|
val = strtol(str, NULL, 16);
|
||||||
|
return val >= strtol(prop->expr->left.sym->name, NULL, 16) &&
|
||||||
|
val <= strtol(prop->expr->right.sym->name, NULL, 16);
|
||||||
|
case S_BOOLEAN:
|
||||||
|
case S_TRISTATE:
|
||||||
|
switch (str[0]) {
|
||||||
|
case 'y': case 'Y':
|
||||||
|
return sym_tristate_within_range(sym, yes);
|
||||||
|
case 'm': case 'M':
|
||||||
|
return sym_tristate_within_range(sym, mod);
|
||||||
|
case 'n': case 'N':
|
||||||
|
return sym_tristate_within_range(sym, no);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sym_set_string_value(struct symbol *sym, const char *newval)
|
||||||
|
{
|
||||||
|
const char *oldval;
|
||||||
|
char *val;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_BOOLEAN:
|
||||||
|
case S_TRISTATE:
|
||||||
|
switch (newval[0]) {
|
||||||
|
case 'y': case 'Y':
|
||||||
|
return sym_set_tristate_value(sym, yes);
|
||||||
|
case 'm': case 'M':
|
||||||
|
return sym_set_tristate_value(sym, mod);
|
||||||
|
case 'n': case 'N':
|
||||||
|
return sym_set_tristate_value(sym, no);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sym_string_within_range(sym, newval))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (sym->flags & SYMBOL_NEW) {
|
||||||
|
sym->flags &= ~SYMBOL_NEW;
|
||||||
|
sym_set_changed(sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
oldval = sym->user.val;
|
||||||
|
size = strlen(newval) + 1;
|
||||||
|
if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
|
||||||
|
size += 2;
|
||||||
|
sym->user.val = val = malloc(size);
|
||||||
|
*val++ = '0';
|
||||||
|
*val++ = 'x';
|
||||||
|
} else if (!oldval || strcmp(oldval, newval))
|
||||||
|
sym->user.val = val = malloc(size);
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
|
||||||
|
strcpy(val, newval);
|
||||||
|
free((void *)oldval);
|
||||||
|
sym_clear_all_valid();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *sym_get_string_value(struct symbol *sym)
|
||||||
|
{
|
||||||
|
tristate val;
|
||||||
|
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_BOOLEAN:
|
||||||
|
case S_TRISTATE:
|
||||||
|
val = sym_get_tristate_value(sym);
|
||||||
|
switch (val) {
|
||||||
|
case no:
|
||||||
|
return "n";
|
||||||
|
case mod:
|
||||||
|
return "m";
|
||||||
|
case yes:
|
||||||
|
return "y";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
return (const char *)sym->curr.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sym_is_changable(struct symbol *sym)
|
||||||
|
{
|
||||||
|
return sym->visible > sym->rev_dep.tri;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct symbol *sym_lookup(const char *name, int isconst)
|
||||||
|
{
|
||||||
|
struct symbol *symbol;
|
||||||
|
const char *ptr;
|
||||||
|
char *new_name;
|
||||||
|
int hash = 0;
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
if (name[0] && !name[1]) {
|
||||||
|
switch (name[0]) {
|
||||||
|
case 'y': return &symbol_yes;
|
||||||
|
case 'm': return &symbol_mod;
|
||||||
|
case 'n': return &symbol_no;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ptr = name; *ptr; ptr++)
|
||||||
|
hash += *ptr;
|
||||||
|
hash &= 0xff;
|
||||||
|
|
||||||
|
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
|
||||||
|
if (!strcmp(symbol->name, name)) {
|
||||||
|
if ((isconst && symbol->flags & SYMBOL_CONST) ||
|
||||||
|
(!isconst && !(symbol->flags & SYMBOL_CONST)))
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_name = strdup(name);
|
||||||
|
} else {
|
||||||
|
new_name = NULL;
|
||||||
|
hash = 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol = malloc(sizeof(*symbol));
|
||||||
|
memset(symbol, 0, sizeof(*symbol));
|
||||||
|
symbol->name = new_name;
|
||||||
|
symbol->type = S_UNKNOWN;
|
||||||
|
symbol->flags = SYMBOL_NEW;
|
||||||
|
if (isconst)
|
||||||
|
symbol->flags |= SYMBOL_CONST;
|
||||||
|
|
||||||
|
symbol->next = symbol_hash[hash];
|
||||||
|
symbol_hash[hash] = symbol;
|
||||||
|
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct symbol *sym_find(const char *name)
|
||||||
|
{
|
||||||
|
struct symbol *symbol = NULL;
|
||||||
|
const char *ptr;
|
||||||
|
int hash = 0;
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (name[0] && !name[1]) {
|
||||||
|
switch (name[0]) {
|
||||||
|
case 'y': return &symbol_yes;
|
||||||
|
case 'm': return &symbol_mod;
|
||||||
|
case 'n': return &symbol_no;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ptr = name; *ptr; ptr++)
|
||||||
|
hash += *ptr;
|
||||||
|
hash &= 0xff;
|
||||||
|
|
||||||
|
for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
|
||||||
|
if (!strcmp(symbol->name, name) &&
|
||||||
|
!(symbol->flags & SYMBOL_CONST))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct symbol **sym_re_search(const char *pattern)
|
||||||
|
{
|
||||||
|
struct symbol *sym, **sym_arr = NULL;
|
||||||
|
int i, cnt, size;
|
||||||
|
regex_t re;
|
||||||
|
|
||||||
|
cnt = size = 0;
|
||||||
|
/* Skip if empty */
|
||||||
|
if (strlen(pattern) == 0)
|
||||||
|
return NULL;
|
||||||
|
if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for_all_symbols(i, sym) {
|
||||||
|
if (sym->flags & SYMBOL_CONST || !sym->name)
|
||||||
|
continue;
|
||||||
|
if (regexec(&re, sym->name, 0, NULL, 0))
|
||||||
|
continue;
|
||||||
|
if (cnt + 1 >= size) {
|
||||||
|
void *tmp = sym_arr;
|
||||||
|
size += 16;
|
||||||
|
sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
|
||||||
|
if (!sym_arr) {
|
||||||
|
free(tmp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sym_arr[cnt++] = sym;
|
||||||
|
}
|
||||||
|
if (sym_arr)
|
||||||
|
sym_arr[cnt] = NULL;
|
||||||
|
regfree(&re);
|
||||||
|
|
||||||
|
return sym_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct symbol *sym_check_deps(struct symbol *sym);
|
||||||
|
|
||||||
|
static struct symbol *sym_check_expr_deps(struct expr *e)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
|
||||||
|
if (!e)
|
||||||
|
return NULL;
|
||||||
|
switch (e->type) {
|
||||||
|
case E_OR:
|
||||||
|
case E_AND:
|
||||||
|
sym = sym_check_expr_deps(e->left.expr);
|
||||||
|
if (sym)
|
||||||
|
return sym;
|
||||||
|
return sym_check_expr_deps(e->right.expr);
|
||||||
|
case E_NOT:
|
||||||
|
return sym_check_expr_deps(e->left.expr);
|
||||||
|
case E_EQUAL:
|
||||||
|
case E_UNEQUAL:
|
||||||
|
sym = sym_check_deps(e->left.sym);
|
||||||
|
if (sym)
|
||||||
|
return sym;
|
||||||
|
return sym_check_deps(e->right.sym);
|
||||||
|
case E_SYMBOL:
|
||||||
|
return sym_check_deps(e->left.sym);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("Oops! How to check %d?\n", e->type);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct symbol *sym_check_deps(struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct symbol *sym2;
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
if (sym->flags & SYMBOL_CHECK_DONE)
|
||||||
|
return NULL;
|
||||||
|
if (sym->flags & SYMBOL_CHECK) {
|
||||||
|
printf("Warning! Found recursive dependency: %s", sym->name);
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
|
||||||
|
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
|
||||||
|
if (sym2)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
for (prop = sym->prop; prop; prop = prop->next) {
|
||||||
|
if (prop->type == P_CHOICE || prop->type == P_SELECT)
|
||||||
|
continue;
|
||||||
|
sym2 = sym_check_expr_deps(prop->visible.expr);
|
||||||
|
if (sym2)
|
||||||
|
goto out;
|
||||||
|
if (prop->type != P_DEFAULT || sym_is_choice(sym))
|
||||||
|
continue;
|
||||||
|
sym2 = sym_check_expr_deps(prop->expr);
|
||||||
|
if (sym2)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (sym2)
|
||||||
|
printf(" %s", sym->name);
|
||||||
|
sym->flags &= ~SYMBOL_CHECK;
|
||||||
|
return sym2;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct property *prop_alloc(enum prop_type type, struct symbol *sym)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
struct property **propp;
|
||||||
|
|
||||||
|
prop = malloc(sizeof(*prop));
|
||||||
|
memset(prop, 0, sizeof(*prop));
|
||||||
|
prop->type = type;
|
||||||
|
prop->sym = sym;
|
||||||
|
prop->file = current_file;
|
||||||
|
prop->lineno = zconf_lineno();
|
||||||
|
|
||||||
|
/* append property to the prop list of symbol */
|
||||||
|
if (sym) {
|
||||||
|
for (propp = &sym->prop; *propp; propp = &(*propp)->next)
|
||||||
|
;
|
||||||
|
*propp = prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct symbol *prop_get_symbol(struct property *prop)
|
||||||
|
{
|
||||||
|
if (prop->expr && (prop->expr->type == E_SYMBOL ||
|
||||||
|
prop->expr->type == E_CHOICE))
|
||||||
|
return prop->expr->left.sym;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *prop_get_type_name(enum prop_type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case P_PROMPT:
|
||||||
|
return "prompt";
|
||||||
|
case P_COMMENT:
|
||||||
|
return "comment";
|
||||||
|
case P_MENU:
|
||||||
|
return "menu";
|
||||||
|
case P_DEFAULT:
|
||||||
|
return "default";
|
||||||
|
case P_CHOICE:
|
||||||
|
return "choice";
|
||||||
|
case P_SELECT:
|
||||||
|
return "select";
|
||||||
|
case P_RANGE:
|
||||||
|
return "range";
|
||||||
|
case P_UNKNOWN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
109
menu/util.c
Normal file
109
menu/util.c
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
|
||||||
|
* Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
|
||||||
|
*
|
||||||
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "lkc.h"
|
||||||
|
|
||||||
|
/* file already present in list? If not add it */
|
||||||
|
struct file *file_lookup(const char *name)
|
||||||
|
{
|
||||||
|
struct file *file;
|
||||||
|
|
||||||
|
for (file = file_list; file; file = file->next) {
|
||||||
|
if (!strcmp(name, file->name))
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = malloc(sizeof(*file));
|
||||||
|
memset(file, 0, sizeof(*file));
|
||||||
|
file->name = strdup(name);
|
||||||
|
file->next = file_list;
|
||||||
|
file_list = file;
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write a dependency file as used by kbuild to track dependencies */
|
||||||
|
int file_write_dep(const char *name)
|
||||||
|
{
|
||||||
|
struct file *file;
|
||||||
|
FILE *out;
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
name = ".config.cmd";
|
||||||
|
out = fopen(".config.tmp", "w");
|
||||||
|
if (!out)
|
||||||
|
return 1;
|
||||||
|
fprintf(out, "deps_config := \\\n");
|
||||||
|
for (file = file_list; file; file = file->next) {
|
||||||
|
if (file->next)
|
||||||
|
fprintf(out, "\t%s \\\n", file->name);
|
||||||
|
else
|
||||||
|
fprintf(out, "\t%s\n", file->name);
|
||||||
|
}
|
||||||
|
fprintf(out, "\n.config include/config.h: $(deps_config)\n\n$(deps_config):\n");
|
||||||
|
fclose(out);
|
||||||
|
rename(".config.tmp", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Allocate initial growable sting */
|
||||||
|
struct gstr str_new(void)
|
||||||
|
{
|
||||||
|
struct gstr gs;
|
||||||
|
gs.s = malloc(sizeof(char) * 64);
|
||||||
|
gs.len = 16;
|
||||||
|
strcpy(gs.s, "\0");
|
||||||
|
return gs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate and assign growable string */
|
||||||
|
struct gstr str_assign(const char *s)
|
||||||
|
{
|
||||||
|
struct gstr gs;
|
||||||
|
gs.s = strdup(s);
|
||||||
|
gs.len = strlen(s) + 1;
|
||||||
|
return gs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free storage for growable string */
|
||||||
|
void str_free(struct gstr *gs)
|
||||||
|
{
|
||||||
|
if (gs->s)
|
||||||
|
free(gs->s);
|
||||||
|
gs->s = NULL;
|
||||||
|
gs->len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append to growable string */
|
||||||
|
void str_append(struct gstr *gs, const char *s)
|
||||||
|
{
|
||||||
|
size_t l = strlen(gs->s) + strlen(s) + 1;
|
||||||
|
if (l > gs->len) {
|
||||||
|
gs->s = realloc(gs->s, l);
|
||||||
|
gs->len = l;
|
||||||
|
}
|
||||||
|
strcat(gs->s, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append printf formatted string to growable string */
|
||||||
|
void str_printf(struct gstr *gs, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char s[10000]; /* big enough... */
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(s, sizeof(s), fmt, ap);
|
||||||
|
str_append(gs, s);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retreive value of growable string */
|
||||||
|
const char *str_get(struct gstr *gs)
|
||||||
|
{
|
||||||
|
return gs->s;
|
||||||
|
}
|
||||||
|
|
366
menu/zconf.l
Normal file
366
menu/zconf.l
Normal file
|
@ -0,0 +1,366 @@
|
||||||
|
%option backup nostdinit noyywrap never-interactive full ecs
|
||||||
|
%option 8bit backup nodefault perf-report perf-report
|
||||||
|
%x COMMAND HELP STRING PARAM
|
||||||
|
%{
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||||
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define LKC_DIRECT_LINK
|
||||||
|
#include "lkc.h"
|
||||||
|
|
||||||
|
#define START_STRSIZE 16
|
||||||
|
|
||||||
|
char *text;
|
||||||
|
static char *text_ptr;
|
||||||
|
static int text_size, text_asize;
|
||||||
|
|
||||||
|
struct buffer {
|
||||||
|
struct buffer *parent;
|
||||||
|
YY_BUFFER_STATE state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct buffer *current_buf;
|
||||||
|
|
||||||
|
static int last_ts, first_ts;
|
||||||
|
|
||||||
|
static void zconf_endhelp(void);
|
||||||
|
static struct buffer *zconf_endfile(void);
|
||||||
|
|
||||||
|
void new_string(void)
|
||||||
|
{
|
||||||
|
text = malloc(START_STRSIZE);
|
||||||
|
text_asize = START_STRSIZE;
|
||||||
|
text_ptr = text;
|
||||||
|
text_size = 0;
|
||||||
|
*text_ptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_string(const char *str, int size)
|
||||||
|
{
|
||||||
|
int new_size = text_size + size + 1;
|
||||||
|
if (new_size > text_asize) {
|
||||||
|
text = realloc(text, new_size);
|
||||||
|
text_asize = new_size;
|
||||||
|
text_ptr = text + text_size;
|
||||||
|
}
|
||||||
|
memcpy(text_ptr, str, size);
|
||||||
|
text_ptr += size;
|
||||||
|
text_size += size;
|
||||||
|
*text_ptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void alloc_string(const char *str, int size)
|
||||||
|
{
|
||||||
|
text = malloc(size + 1);
|
||||||
|
memcpy(text, str, size);
|
||||||
|
text[size] = 0;
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
ws [ \n\t]
|
||||||
|
n [A-Za-z0-9_]
|
||||||
|
|
||||||
|
%%
|
||||||
|
int str = 0;
|
||||||
|
int ts, i;
|
||||||
|
|
||||||
|
[ \t]*#.*\n current_file->lineno++;
|
||||||
|
[ \t]*#.*
|
||||||
|
|
||||||
|
[ \t]*\n current_file->lineno++; return T_EOL;
|
||||||
|
|
||||||
|
[ \t]+ {
|
||||||
|
BEGIN(COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
. {
|
||||||
|
unput(yytext[0]);
|
||||||
|
BEGIN(COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<COMMAND>{
|
||||||
|
"mainmenu" BEGIN(PARAM); return T_MAINMENU;
|
||||||
|
"menu" BEGIN(PARAM); return T_MENU;
|
||||||
|
"endmenu" BEGIN(PARAM); return T_ENDMENU;
|
||||||
|
"source" BEGIN(PARAM); return T_SOURCE;
|
||||||
|
"choice" BEGIN(PARAM); return T_CHOICE;
|
||||||
|
"endchoice" BEGIN(PARAM); return T_ENDCHOICE;
|
||||||
|
"comment" BEGIN(PARAM); return T_COMMENT;
|
||||||
|
"config" BEGIN(PARAM); return T_CONFIG;
|
||||||
|
"menuconfig" BEGIN(PARAM); return T_MENUCONFIG;
|
||||||
|
"help" BEGIN(PARAM); return T_HELP;
|
||||||
|
"if" BEGIN(PARAM); return T_IF;
|
||||||
|
"endif" BEGIN(PARAM); return T_ENDIF;
|
||||||
|
"depends" BEGIN(PARAM); return T_DEPENDS;
|
||||||
|
"requires" BEGIN(PARAM); return T_REQUIRES;
|
||||||
|
"optional" BEGIN(PARAM); return T_OPTIONAL;
|
||||||
|
"default" BEGIN(PARAM); return T_DEFAULT;
|
||||||
|
"prompt" BEGIN(PARAM); return T_PROMPT;
|
||||||
|
"tristate" BEGIN(PARAM); return T_TRISTATE;
|
||||||
|
"def_tristate" BEGIN(PARAM); return T_DEF_TRISTATE;
|
||||||
|
"bool" BEGIN(PARAM); return T_BOOLEAN;
|
||||||
|
"boolean" BEGIN(PARAM); return T_BOOLEAN;
|
||||||
|
"def_bool" BEGIN(PARAM); return T_DEF_BOOLEAN;
|
||||||
|
"def_boolean" BEGIN(PARAM); return T_DEF_BOOLEAN;
|
||||||
|
"int" BEGIN(PARAM); return T_INT;
|
||||||
|
"hex" BEGIN(PARAM); return T_HEX;
|
||||||
|
"string" BEGIN(PARAM); return T_STRING;
|
||||||
|
"select" BEGIN(PARAM); return T_SELECT;
|
||||||
|
"enable" BEGIN(PARAM); return T_SELECT;
|
||||||
|
"range" BEGIN(PARAM); return T_RANGE;
|
||||||
|
{n}+ {
|
||||||
|
alloc_string(yytext, yyleng);
|
||||||
|
zconflval.string = text;
|
||||||
|
return T_WORD;
|
||||||
|
}
|
||||||
|
.
|
||||||
|
\n current_file->lineno++; BEGIN(INITIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
<PARAM>{
|
||||||
|
"&&" return T_AND;
|
||||||
|
"||" return T_OR;
|
||||||
|
"(" return T_OPEN_PAREN;
|
||||||
|
")" return T_CLOSE_PAREN;
|
||||||
|
"!" return T_NOT;
|
||||||
|
"=" return T_EQUAL;
|
||||||
|
"!=" return T_UNEQUAL;
|
||||||
|
"if" return T_IF;
|
||||||
|
"on" return T_ON;
|
||||||
|
\"|\' {
|
||||||
|
str = yytext[0];
|
||||||
|
new_string();
|
||||||
|
BEGIN(STRING);
|
||||||
|
}
|
||||||
|
\n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
|
||||||
|
--- /* ignore */
|
||||||
|
({n}|[-/.])+ {
|
||||||
|
alloc_string(yytext, yyleng);
|
||||||
|
zconflval.string = text;
|
||||||
|
return T_WORD;
|
||||||
|
}
|
||||||
|
#.* /* comment */
|
||||||
|
\\\n current_file->lineno++;
|
||||||
|
.
|
||||||
|
<<EOF>> {
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<STRING>{
|
||||||
|
[^'"\\\n]+/\n {
|
||||||
|
append_string(yytext, yyleng);
|
||||||
|
zconflval.string = text;
|
||||||
|
return T_WORD_QUOTE;
|
||||||
|
}
|
||||||
|
[^'"\\\n]+ {
|
||||||
|
append_string(yytext, yyleng);
|
||||||
|
}
|
||||||
|
\\.?/\n {
|
||||||
|
append_string(yytext + 1, yyleng - 1);
|
||||||
|
zconflval.string = text;
|
||||||
|
return T_WORD_QUOTE;
|
||||||
|
}
|
||||||
|
\\.? {
|
||||||
|
append_string(yytext + 1, yyleng - 1);
|
||||||
|
}
|
||||||
|
\'|\" {
|
||||||
|
if (str == yytext[0]) {
|
||||||
|
BEGIN(PARAM);
|
||||||
|
zconflval.string = text;
|
||||||
|
return T_WORD_QUOTE;
|
||||||
|
} else
|
||||||
|
append_string(yytext, 1);
|
||||||
|
}
|
||||||
|
\n {
|
||||||
|
printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
|
||||||
|
current_file->lineno++;
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
return T_EOL;
|
||||||
|
}
|
||||||
|
<<EOF>> {
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<HELP>{
|
||||||
|
[ \t]+ {
|
||||||
|
ts = 0;
|
||||||
|
for (i = 0; i < yyleng; i++) {
|
||||||
|
if (yytext[i] == '\t')
|
||||||
|
ts = (ts & ~7) + 8;
|
||||||
|
else
|
||||||
|
ts++;
|
||||||
|
}
|
||||||
|
last_ts = ts;
|
||||||
|
if (first_ts) {
|
||||||
|
if (ts < first_ts) {
|
||||||
|
zconf_endhelp();
|
||||||
|
return T_HELPTEXT;
|
||||||
|
}
|
||||||
|
ts -= first_ts;
|
||||||
|
while (ts > 8) {
|
||||||
|
append_string(" ", 8);
|
||||||
|
ts -= 8;
|
||||||
|
}
|
||||||
|
append_string(" ", ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[ \t]*\n/[^ \t\n] {
|
||||||
|
current_file->lineno++;
|
||||||
|
zconf_endhelp();
|
||||||
|
return T_HELPTEXT;
|
||||||
|
}
|
||||||
|
[ \t]*\n {
|
||||||
|
current_file->lineno++;
|
||||||
|
append_string("\n", 1);
|
||||||
|
}
|
||||||
|
[^ \t\n].* {
|
||||||
|
append_string(yytext, yyleng);
|
||||||
|
if (!first_ts)
|
||||||
|
first_ts = last_ts;
|
||||||
|
}
|
||||||
|
<<EOF>> {
|
||||||
|
zconf_endhelp();
|
||||||
|
return T_HELPTEXT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<<EOF>> {
|
||||||
|
if (current_buf) {
|
||||||
|
zconf_endfile();
|
||||||
|
return T_EOF;
|
||||||
|
}
|
||||||
|
fclose(yyin);
|
||||||
|
yyterminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
%%
|
||||||
|
void zconf_starthelp(void)
|
||||||
|
{
|
||||||
|
new_string();
|
||||||
|
last_ts = first_ts = 0;
|
||||||
|
BEGIN(HELP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zconf_endhelp(void)
|
||||||
|
{
|
||||||
|
zconflval.string = text;
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to open specified file with following names:
|
||||||
|
* ./name
|
||||||
|
* $(srctree)/name
|
||||||
|
* The latter is used when srctree is separate from objtree
|
||||||
|
* when compiling the kernel.
|
||||||
|
* Return NULL if file is not found.
|
||||||
|
*/
|
||||||
|
FILE *zconf_fopen(const char *name)
|
||||||
|
{
|
||||||
|
char *env, fullname[PATH_MAX+1];
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
f = fopen(name, "r");
|
||||||
|
if (!f && name[0] != '/') {
|
||||||
|
env = getenv(SRCTREE);
|
||||||
|
if (env) {
|
||||||
|
sprintf(fullname, "%s/%s", env, name);
|
||||||
|
f = fopen(fullname, "r");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zconf_initscan(const char *name)
|
||||||
|
{
|
||||||
|
yyin = zconf_fopen(name);
|
||||||
|
if (!yyin) {
|
||||||
|
printf("can't find file %s\n", name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_buf = malloc(sizeof(*current_buf));
|
||||||
|
memset(current_buf, 0, sizeof(*current_buf));
|
||||||
|
|
||||||
|
current_file = file_lookup(name);
|
||||||
|
current_file->lineno = 1;
|
||||||
|
current_file->flags = FILE_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zconf_nextfile(const char *name)
|
||||||
|
{
|
||||||
|
struct file *file = file_lookup(name);
|
||||||
|
struct buffer *buf = malloc(sizeof(*buf));
|
||||||
|
memset(buf, 0, sizeof(*buf));
|
||||||
|
|
||||||
|
current_buf->state = YY_CURRENT_BUFFER;
|
||||||
|
yyin = zconf_fopen(name);
|
||||||
|
if (!yyin) {
|
||||||
|
printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
|
||||||
|
buf->parent = current_buf;
|
||||||
|
current_buf = buf;
|
||||||
|
|
||||||
|
if (file->flags & FILE_BUSY) {
|
||||||
|
printf("recursive scan (%s)?\n", name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (file->flags & FILE_SCANNED) {
|
||||||
|
printf("file %s already scanned?\n", name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
file->flags |= FILE_BUSY;
|
||||||
|
file->lineno = 1;
|
||||||
|
file->parent = current_file;
|
||||||
|
current_file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buffer *zconf_endfile(void)
|
||||||
|
{
|
||||||
|
struct buffer *parent;
|
||||||
|
|
||||||
|
current_file->flags |= FILE_SCANNED;
|
||||||
|
current_file->flags &= ~FILE_BUSY;
|
||||||
|
current_file = current_file->parent;
|
||||||
|
|
||||||
|
parent = current_buf->parent;
|
||||||
|
if (parent) {
|
||||||
|
fclose(yyin);
|
||||||
|
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||||
|
yy_switch_to_buffer(parent->state);
|
||||||
|
}
|
||||||
|
free(current_buf);
|
||||||
|
current_buf = parent;
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zconf_lineno(void)
|
||||||
|
{
|
||||||
|
if (current_buf)
|
||||||
|
return current_file->lineno - 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *zconf_curname(void)
|
||||||
|
{
|
||||||
|
if (current_buf)
|
||||||
|
return current_file->name;
|
||||||
|
else
|
||||||
|
return "<none>";
|
||||||
|
}
|
2130
menu/zconf.tab.c_shipped
Normal file
2130
menu/zconf.tab.c_shipped
Normal file
File diff suppressed because it is too large
Load diff
125
menu/zconf.tab.h_shipped
Normal file
125
menu/zconf.tab.h_shipped
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/* A Bison parser, made from zconf.y, by GNU bison 1.75. */
|
||||||
|
|
||||||
|
/* Skeleton parser for Yacc-like parsing with Bison,
|
||||||
|
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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, 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., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
/* As a special exception, when this file is copied by Bison into a
|
||||||
|
Bison output file, you may use that output file without restriction.
|
||||||
|
This special exception was added by the Free Software Foundation
|
||||||
|
in version 1.24 of Bison. */
|
||||||
|
|
||||||
|
#ifndef BISON_ZCONF_TAB_H
|
||||||
|
# define BISON_ZCONF_TAB_H
|
||||||
|
|
||||||
|
/* Tokens. */
|
||||||
|
#ifndef YYTOKENTYPE
|
||||||
|
# define YYTOKENTYPE
|
||||||
|
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||||
|
know about them. */
|
||||||
|
enum yytokentype {
|
||||||
|
T_MAINMENU = 258,
|
||||||
|
T_MENU = 259,
|
||||||
|
T_ENDMENU = 260,
|
||||||
|
T_SOURCE = 261,
|
||||||
|
T_CHOICE = 262,
|
||||||
|
T_ENDCHOICE = 263,
|
||||||
|
T_COMMENT = 264,
|
||||||
|
T_CONFIG = 265,
|
||||||
|
T_HELP = 266,
|
||||||
|
T_HELPTEXT = 267,
|
||||||
|
T_IF = 268,
|
||||||
|
T_ENDIF = 269,
|
||||||
|
T_DEPENDS = 270,
|
||||||
|
T_REQUIRES = 271,
|
||||||
|
T_OPTIONAL = 272,
|
||||||
|
T_PROMPT = 273,
|
||||||
|
T_DEFAULT = 274,
|
||||||
|
T_TRISTATE = 275,
|
||||||
|
T_BOOLEAN = 276,
|
||||||
|
T_INT = 277,
|
||||||
|
T_HEX = 278,
|
||||||
|
T_WORD = 279,
|
||||||
|
T_STRING = 280,
|
||||||
|
T_UNEQUAL = 281,
|
||||||
|
T_EOF = 282,
|
||||||
|
T_EOL = 283,
|
||||||
|
T_CLOSE_PAREN = 284,
|
||||||
|
T_OPEN_PAREN = 285,
|
||||||
|
T_ON = 286,
|
||||||
|
T_OR = 287,
|
||||||
|
T_AND = 288,
|
||||||
|
T_EQUAL = 289,
|
||||||
|
T_NOT = 290
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
#define T_MAINMENU 258
|
||||||
|
#define T_MENU 259
|
||||||
|
#define T_ENDMENU 260
|
||||||
|
#define T_SOURCE 261
|
||||||
|
#define T_CHOICE 262
|
||||||
|
#define T_ENDCHOICE 263
|
||||||
|
#define T_COMMENT 264
|
||||||
|
#define T_CONFIG 265
|
||||||
|
#define T_HELP 266
|
||||||
|
#define T_HELPTEXT 267
|
||||||
|
#define T_IF 268
|
||||||
|
#define T_ENDIF 269
|
||||||
|
#define T_DEPENDS 270
|
||||||
|
#define T_REQUIRES 271
|
||||||
|
#define T_OPTIONAL 272
|
||||||
|
#define T_PROMPT 273
|
||||||
|
#define T_DEFAULT 274
|
||||||
|
#define T_TRISTATE 275
|
||||||
|
#define T_BOOLEAN 276
|
||||||
|
#define T_INT 277
|
||||||
|
#define T_HEX 278
|
||||||
|
#define T_WORD 279
|
||||||
|
#define T_STRING 280
|
||||||
|
#define T_UNEQUAL 281
|
||||||
|
#define T_EOF 282
|
||||||
|
#define T_EOL 283
|
||||||
|
#define T_CLOSE_PAREN 284
|
||||||
|
#define T_OPEN_PAREN 285
|
||||||
|
#define T_ON 286
|
||||||
|
#define T_OR 287
|
||||||
|
#define T_AND 288
|
||||||
|
#define T_EQUAL 289
|
||||||
|
#define T_NOT 290
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef YYSTYPE
|
||||||
|
#line 33 "zconf.y"
|
||||||
|
typedef union {
|
||||||
|
int token;
|
||||||
|
char *string;
|
||||||
|
struct symbol *symbol;
|
||||||
|
struct expr *expr;
|
||||||
|
struct menu *menu;
|
||||||
|
} yystype;
|
||||||
|
/* Line 1281 of /usr/share/bison/yacc.c. */
|
||||||
|
#line 118 "zconf.tab.h"
|
||||||
|
# define YYSTYPE yystype
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern YYSTYPE zconflval;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* not BISON_ZCONF_TAB_H */
|
||||||
|
|
690
menu/zconf.y
Normal file
690
menu/zconf.y
Normal file
|
@ -0,0 +1,690 @@
|
||||||
|
%{
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
||||||
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
|
||||||
|
|
||||||
|
#define PRINTD 0x0001
|
||||||
|
#define DEBUG_PARSE 0x0002
|
||||||
|
|
||||||
|
int cdebug = PRINTD;
|
||||||
|
|
||||||
|
extern int zconflex(void);
|
||||||
|
static void zconfprint(const char *err, ...);
|
||||||
|
static void zconferror(const char *err);
|
||||||
|
static bool zconf_endtoken(int token, int starttoken, int endtoken);
|
||||||
|
|
||||||
|
struct symbol *symbol_hash[257];
|
||||||
|
|
||||||
|
static struct menu *current_menu, *current_entry;
|
||||||
|
|
||||||
|
#define YYERROR_VERBOSE
|
||||||
|
%}
|
||||||
|
%expect 40
|
||||||
|
|
||||||
|
%union
|
||||||
|
{
|
||||||
|
int token;
|
||||||
|
char *string;
|
||||||
|
struct symbol *symbol;
|
||||||
|
struct expr *expr;
|
||||||
|
struct menu *menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token T_MAINMENU
|
||||||
|
%token T_MENU
|
||||||
|
%token T_ENDMENU
|
||||||
|
%token T_SOURCE
|
||||||
|
%token T_CHOICE
|
||||||
|
%token T_ENDCHOICE
|
||||||
|
%token T_COMMENT
|
||||||
|
%token T_CONFIG
|
||||||
|
%token T_MENUCONFIG
|
||||||
|
%token T_HELP
|
||||||
|
%token <string> T_HELPTEXT
|
||||||
|
%token T_IF
|
||||||
|
%token T_ENDIF
|
||||||
|
%token T_DEPENDS
|
||||||
|
%token T_REQUIRES
|
||||||
|
%token T_OPTIONAL
|
||||||
|
%token T_PROMPT
|
||||||
|
%token T_DEFAULT
|
||||||
|
%token T_TRISTATE
|
||||||
|
%token T_DEF_TRISTATE
|
||||||
|
%token T_BOOLEAN
|
||||||
|
%token T_DEF_BOOLEAN
|
||||||
|
%token T_STRING
|
||||||
|
%token T_INT
|
||||||
|
%token T_HEX
|
||||||
|
%token <string> T_WORD
|
||||||
|
%token <string> T_WORD_QUOTE
|
||||||
|
%token T_UNEQUAL
|
||||||
|
%token T_EOF
|
||||||
|
%token T_EOL
|
||||||
|
%token T_CLOSE_PAREN
|
||||||
|
%token T_OPEN_PAREN
|
||||||
|
%token T_ON
|
||||||
|
%token T_SELECT
|
||||||
|
%token T_RANGE
|
||||||
|
|
||||||
|
%left T_OR
|
||||||
|
%left T_AND
|
||||||
|
%left T_EQUAL T_UNEQUAL
|
||||||
|
%nonassoc T_NOT
|
||||||
|
|
||||||
|
%type <string> prompt
|
||||||
|
%type <string> source
|
||||||
|
%type <symbol> symbol
|
||||||
|
%type <expr> expr
|
||||||
|
%type <expr> if_expr
|
||||||
|
%type <token> end
|
||||||
|
|
||||||
|
%{
|
||||||
|
#define LKC_DIRECT_LINK
|
||||||
|
#include "lkc.h"
|
||||||
|
%}
|
||||||
|
%%
|
||||||
|
input: /* empty */
|
||||||
|
| input block
|
||||||
|
;
|
||||||
|
|
||||||
|
block: common_block
|
||||||
|
| choice_stmt
|
||||||
|
| menu_stmt
|
||||||
|
| T_MAINMENU prompt nl_or_eof
|
||||||
|
| T_ENDMENU { zconfprint("unexpected 'endmenu' statement"); }
|
||||||
|
| T_ENDIF { zconfprint("unexpected 'endif' statement"); }
|
||||||
|
| T_ENDCHOICE { zconfprint("unexpected 'endchoice' statement"); }
|
||||||
|
| error nl_or_eof { zconfprint("syntax error"); yyerrok; }
|
||||||
|
;
|
||||||
|
|
||||||
|
common_block:
|
||||||
|
if_stmt
|
||||||
|
| comment_stmt
|
||||||
|
| config_stmt
|
||||||
|
| menuconfig_stmt
|
||||||
|
| source_stmt
|
||||||
|
| nl_or_eof
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
/* config/menuconfig entry */
|
||||||
|
|
||||||
|
config_entry_start: T_CONFIG T_WORD T_EOL
|
||||||
|
{
|
||||||
|
struct symbol *sym = sym_lookup($2, 0);
|
||||||
|
sym->flags |= SYMBOL_OPTIONAL;
|
||||||
|
menu_add_entry(sym);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||||
|
};
|
||||||
|
|
||||||
|
config_stmt: config_entry_start config_option_list
|
||||||
|
{
|
||||||
|
menu_end_entry();
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
|
||||||
|
{
|
||||||
|
struct symbol *sym = sym_lookup($2, 0);
|
||||||
|
sym->flags |= SYMBOL_OPTIONAL;
|
||||||
|
menu_add_entry(sym);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||||
|
};
|
||||||
|
|
||||||
|
menuconfig_stmt: menuconfig_entry_start config_option_list
|
||||||
|
{
|
||||||
|
if (current_entry->prompt)
|
||||||
|
current_entry->prompt->type = P_MENU;
|
||||||
|
else
|
||||||
|
zconfprint("warning: menuconfig statement without prompt");
|
||||||
|
menu_end_entry();
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option_list:
|
||||||
|
/* empty */
|
||||||
|
| config_option_list config_option
|
||||||
|
| config_option_list depends
|
||||||
|
| config_option_list help
|
||||||
|
| config_option_list T_EOL
|
||||||
|
;
|
||||||
|
|
||||||
|
config_option: T_TRISTATE prompt_stmt_opt T_EOL
|
||||||
|
{
|
||||||
|
menu_set_type(S_TRISTATE);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option: T_DEF_TRISTATE expr if_expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_expr(P_DEFAULT, $2, $3);
|
||||||
|
menu_set_type(S_TRISTATE);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option: T_BOOLEAN prompt_stmt_opt T_EOL
|
||||||
|
{
|
||||||
|
menu_set_type(S_BOOLEAN);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option: T_DEF_BOOLEAN expr if_expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_expr(P_DEFAULT, $2, $3);
|
||||||
|
menu_set_type(S_BOOLEAN);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option: T_INT prompt_stmt_opt T_EOL
|
||||||
|
{
|
||||||
|
menu_set_type(S_INT);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option: T_HEX prompt_stmt_opt T_EOL
|
||||||
|
{
|
||||||
|
menu_set_type(S_HEX);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option: T_STRING prompt_stmt_opt T_EOL
|
||||||
|
{
|
||||||
|
menu_set_type(S_STRING);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option: T_PROMPT prompt if_expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_prompt(P_PROMPT, $2, $3);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option: T_DEFAULT expr if_expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_expr(P_DEFAULT, $2, $3);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option: T_SELECT T_WORD if_expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
config_option: T_RANGE symbol symbol if_expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
/* choice entry */
|
||||||
|
|
||||||
|
choice: T_CHOICE T_EOL
|
||||||
|
{
|
||||||
|
struct symbol *sym = sym_lookup(NULL, 0);
|
||||||
|
sym->flags |= SYMBOL_CHOICE;
|
||||||
|
menu_add_entry(sym);
|
||||||
|
menu_add_expr(P_CHOICE, NULL, NULL);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
choice_entry: choice choice_option_list
|
||||||
|
{
|
||||||
|
menu_end_entry();
|
||||||
|
menu_add_menu();
|
||||||
|
};
|
||||||
|
|
||||||
|
choice_end: end
|
||||||
|
{
|
||||||
|
if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
|
||||||
|
menu_end_menu();
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
choice_stmt:
|
||||||
|
choice_entry choice_block choice_end
|
||||||
|
| choice_entry choice_block
|
||||||
|
{
|
||||||
|
printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
|
||||||
|
zconfnerrs++;
|
||||||
|
};
|
||||||
|
|
||||||
|
choice_option_list:
|
||||||
|
/* empty */
|
||||||
|
| choice_option_list choice_option
|
||||||
|
| choice_option_list depends
|
||||||
|
| choice_option_list help
|
||||||
|
| choice_option_list T_EOL
|
||||||
|
;
|
||||||
|
|
||||||
|
choice_option: T_PROMPT prompt if_expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_prompt(P_PROMPT, $2, $3);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
choice_option: T_TRISTATE prompt_stmt_opt T_EOL
|
||||||
|
{
|
||||||
|
menu_set_type(S_TRISTATE);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
choice_option: T_BOOLEAN prompt_stmt_opt T_EOL
|
||||||
|
{
|
||||||
|
menu_set_type(S_BOOLEAN);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
choice_option: T_OPTIONAL T_EOL
|
||||||
|
{
|
||||||
|
current_entry->sym->flags |= SYMBOL_OPTIONAL;
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
choice_option: T_DEFAULT T_WORD if_expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
choice_block:
|
||||||
|
/* empty */
|
||||||
|
| choice_block common_block
|
||||||
|
;
|
||||||
|
|
||||||
|
/* if entry */
|
||||||
|
|
||||||
|
if: T_IF expr T_EOL
|
||||||
|
{
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
|
||||||
|
menu_add_entry(NULL);
|
||||||
|
menu_add_dep($2);
|
||||||
|
menu_end_entry();
|
||||||
|
menu_add_menu();
|
||||||
|
};
|
||||||
|
|
||||||
|
if_end: end
|
||||||
|
{
|
||||||
|
if (zconf_endtoken($1, T_IF, T_ENDIF)) {
|
||||||
|
menu_end_menu();
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if_stmt:
|
||||||
|
if if_block if_end
|
||||||
|
| if if_block
|
||||||
|
{
|
||||||
|
printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
|
||||||
|
zconfnerrs++;
|
||||||
|
};
|
||||||
|
|
||||||
|
if_block:
|
||||||
|
/* empty */
|
||||||
|
| if_block common_block
|
||||||
|
| if_block menu_stmt
|
||||||
|
| if_block choice_stmt
|
||||||
|
;
|
||||||
|
|
||||||
|
/* menu entry */
|
||||||
|
|
||||||
|
menu: T_MENU prompt T_EOL
|
||||||
|
{
|
||||||
|
menu_add_entry(NULL);
|
||||||
|
menu_add_prop(P_MENU, $2, NULL, NULL);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
menu_entry: menu depends_list
|
||||||
|
{
|
||||||
|
menu_end_entry();
|
||||||
|
menu_add_menu();
|
||||||
|
};
|
||||||
|
|
||||||
|
menu_end: end
|
||||||
|
{
|
||||||
|
if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
|
||||||
|
menu_end_menu();
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
menu_stmt:
|
||||||
|
menu_entry menu_block menu_end
|
||||||
|
| menu_entry menu_block
|
||||||
|
{
|
||||||
|
printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
|
||||||
|
zconfnerrs++;
|
||||||
|
};
|
||||||
|
|
||||||
|
menu_block:
|
||||||
|
/* empty */
|
||||||
|
| menu_block common_block
|
||||||
|
| menu_block menu_stmt
|
||||||
|
| menu_block choice_stmt
|
||||||
|
| menu_block error T_EOL { zconfprint("invalid menu option"); yyerrok; }
|
||||||
|
;
|
||||||
|
|
||||||
|
source: T_SOURCE prompt T_EOL
|
||||||
|
{
|
||||||
|
$$ = $2;
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||||
|
};
|
||||||
|
|
||||||
|
source_stmt: source
|
||||||
|
{
|
||||||
|
zconf_nextfile($1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* comment entry */
|
||||||
|
|
||||||
|
comment: T_COMMENT prompt T_EOL
|
||||||
|
{
|
||||||
|
menu_add_entry(NULL);
|
||||||
|
menu_add_prop(P_COMMENT, $2, NULL, NULL);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
comment_stmt: comment depends_list
|
||||||
|
{
|
||||||
|
menu_end_entry();
|
||||||
|
};
|
||||||
|
|
||||||
|
/* help option */
|
||||||
|
|
||||||
|
help_start: T_HELP T_EOL
|
||||||
|
{
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
|
||||||
|
zconf_starthelp();
|
||||||
|
};
|
||||||
|
|
||||||
|
help: help_start T_HELPTEXT
|
||||||
|
{
|
||||||
|
current_entry->sym->help = $2;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* depends option */
|
||||||
|
|
||||||
|
depends_list: /* empty */
|
||||||
|
| depends_list depends
|
||||||
|
| depends_list T_EOL
|
||||||
|
;
|
||||||
|
|
||||||
|
depends: T_DEPENDS T_ON expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_dep($3);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
|
||||||
|
}
|
||||||
|
| T_DEPENDS expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_dep($2);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
|
||||||
|
}
|
||||||
|
| T_REQUIRES expr T_EOL
|
||||||
|
{
|
||||||
|
menu_add_dep($2);
|
||||||
|
printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
|
||||||
|
};
|
||||||
|
|
||||||
|
/* prompt statement */
|
||||||
|
|
||||||
|
prompt_stmt_opt:
|
||||||
|
/* empty */
|
||||||
|
| prompt if_expr
|
||||||
|
{
|
||||||
|
menu_add_prop(P_PROMPT, $1, NULL, $2);
|
||||||
|
};
|
||||||
|
|
||||||
|
prompt: T_WORD
|
||||||
|
| T_WORD_QUOTE
|
||||||
|
;
|
||||||
|
|
||||||
|
end: T_ENDMENU nl_or_eof { $$ = T_ENDMENU; }
|
||||||
|
| T_ENDCHOICE nl_or_eof { $$ = T_ENDCHOICE; }
|
||||||
|
| T_ENDIF nl_or_eof { $$ = T_ENDIF; }
|
||||||
|
;
|
||||||
|
|
||||||
|
nl_or_eof:
|
||||||
|
T_EOL | T_EOF;
|
||||||
|
|
||||||
|
if_expr: /* empty */ { $$ = NULL; }
|
||||||
|
| T_IF expr { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
expr: symbol { $$ = expr_alloc_symbol($1); }
|
||||||
|
| symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
|
||||||
|
| symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
|
||||||
|
| T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
|
||||||
|
| T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
|
||||||
|
| expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
|
||||||
|
| expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
|
||||||
|
| T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
void conf_parse(const char *name)
|
||||||
|
{
|
||||||
|
struct symbol *sym;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
zconf_initscan(name);
|
||||||
|
|
||||||
|
sym_init();
|
||||||
|
menu_init();
|
||||||
|
modules_sym = sym_lookup("MODULES", 0);
|
||||||
|
rootmenu.prompt = menu_add_prop(P_MENU, "JHALFS Configuration", NULL, NULL);
|
||||||
|
|
||||||
|
//zconfdebug = 1;
|
||||||
|
zconfparse();
|
||||||
|
if (zconfnerrs)
|
||||||
|
exit(1);
|
||||||
|
menu_finalize(&rootmenu);
|
||||||
|
for_all_symbols(i, sym) {
|
||||||
|
if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym))
|
||||||
|
printf("\n");
|
||||||
|
else
|
||||||
|
sym->flags |= SYMBOL_CHECK_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym_change_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *zconf_tokenname(int token)
|
||||||
|
{
|
||||||
|
switch (token) {
|
||||||
|
case T_MENU: return "menu";
|
||||||
|
case T_ENDMENU: return "endmenu";
|
||||||
|
case T_CHOICE: return "choice";
|
||||||
|
case T_ENDCHOICE: return "endchoice";
|
||||||
|
case T_IF: return "if";
|
||||||
|
case T_ENDIF: return "endif";
|
||||||
|
}
|
||||||
|
return "<token>";
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool zconf_endtoken(int token, int starttoken, int endtoken)
|
||||||
|
{
|
||||||
|
if (token != endtoken) {
|
||||||
|
zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken));
|
||||||
|
zconfnerrs++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (current_menu->file != current_file) {
|
||||||
|
zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken));
|
||||||
|
zconfprint("location of the '%s'", zconf_tokenname(starttoken));
|
||||||
|
zconfnerrs++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zconfprint(const char *err, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1);
|
||||||
|
va_start(ap, err);
|
||||||
|
vfprintf(stderr, err, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zconferror(const char *err)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_quoted_string(FILE *out, const char *str)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
putc('"', out);
|
||||||
|
while ((p = strchr(str, '"'))) {
|
||||||
|
len = p - str;
|
||||||
|
if (len)
|
||||||
|
fprintf(out, "%.*s", len, str);
|
||||||
|
fputs("\\\"", out);
|
||||||
|
str = p + 1;
|
||||||
|
}
|
||||||
|
fputs(str, out);
|
||||||
|
putc('"', out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_symbol(FILE *out, struct menu *menu)
|
||||||
|
{
|
||||||
|
struct symbol *sym = menu->sym;
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
if (sym_is_choice(sym))
|
||||||
|
fprintf(out, "choice\n");
|
||||||
|
else
|
||||||
|
fprintf(out, "config %s\n", sym->name);
|
||||||
|
switch (sym->type) {
|
||||||
|
case S_BOOLEAN:
|
||||||
|
fputs(" boolean\n", out);
|
||||||
|
break;
|
||||||
|
case S_TRISTATE:
|
||||||
|
fputs(" tristate\n", out);
|
||||||
|
break;
|
||||||
|
case S_STRING:
|
||||||
|
fputs(" string\n", out);
|
||||||
|
break;
|
||||||
|
case S_INT:
|
||||||
|
fputs(" integer\n", out);
|
||||||
|
break;
|
||||||
|
case S_HEX:
|
||||||
|
fputs(" hex\n", out);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fputs(" ???\n", out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (prop = sym->prop; prop; prop = prop->next) {
|
||||||
|
if (prop->menu != menu)
|
||||||
|
continue;
|
||||||
|
switch (prop->type) {
|
||||||
|
case P_PROMPT:
|
||||||
|
fputs(" prompt ", out);
|
||||||
|
print_quoted_string(out, prop->text);
|
||||||
|
if (!expr_is_yes(prop->visible.expr)) {
|
||||||
|
fputs(" if ", out);
|
||||||
|
expr_fprint(prop->visible.expr, out);
|
||||||
|
}
|
||||||
|
fputc('\n', out);
|
||||||
|
break;
|
||||||
|
case P_DEFAULT:
|
||||||
|
fputs( " default ", out);
|
||||||
|
expr_fprint(prop->expr, out);
|
||||||
|
if (!expr_is_yes(prop->visible.expr)) {
|
||||||
|
fputs(" if ", out);
|
||||||
|
expr_fprint(prop->visible.expr, out);
|
||||||
|
}
|
||||||
|
fputc('\n', out);
|
||||||
|
break;
|
||||||
|
case P_CHOICE:
|
||||||
|
fputs(" #choice value\n", out);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(out, " unknown prop %d!\n", prop->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sym->help) {
|
||||||
|
int len = strlen(sym->help);
|
||||||
|
while (sym->help[--len] == '\n')
|
||||||
|
sym->help[len] = 0;
|
||||||
|
fprintf(out, " help\n%s\n", sym->help);
|
||||||
|
}
|
||||||
|
fputc('\n', out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zconfdump(FILE *out)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
struct symbol *sym;
|
||||||
|
struct menu *menu;
|
||||||
|
|
||||||
|
menu = rootmenu.list;
|
||||||
|
while (menu) {
|
||||||
|
if ((sym = menu->sym))
|
||||||
|
print_symbol(out, menu);
|
||||||
|
else if ((prop = menu->prompt)) {
|
||||||
|
switch (prop->type) {
|
||||||
|
case P_COMMENT:
|
||||||
|
fputs("\ncomment ", out);
|
||||||
|
print_quoted_string(out, prop->text);
|
||||||
|
fputs("\n", out);
|
||||||
|
break;
|
||||||
|
case P_MENU:
|
||||||
|
fputs("\nmenu ", out);
|
||||||
|
print_quoted_string(out, prop->text);
|
||||||
|
fputs("\n", out);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
if (!expr_is_yes(prop->visible.expr)) {
|
||||||
|
fputs(" depends ", out);
|
||||||
|
expr_fprint(prop->visible.expr, out);
|
||||||
|
fputc('\n', out);
|
||||||
|
}
|
||||||
|
fputs("\n", out);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (menu->list)
|
||||||
|
menu = menu->list;
|
||||||
|
else if (menu->next)
|
||||||
|
menu = menu->next;
|
||||||
|
else while ((menu = menu->parent)) {
|
||||||
|
if (menu->prompt && menu->prompt->type == P_MENU)
|
||||||
|
fputs("\nendmenu\n", out);
|
||||||
|
if (menu->next) {
|
||||||
|
menu = menu->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "lex.zconf.c"
|
||||||
|
#include "util.c"
|
||||||
|
#include "confdata.c"
|
||||||
|
#include "expr.c"
|
||||||
|
#include "symbol.c"
|
||||||
|
#include "menu.c"
|
Reference in a new issue