Get rid of the GPLv2 license:

- Replace the menu system with the Kconfiglib, which has an ISC license
- Remove farce and any reference to it
- Rewrite the copyright notice, add the LICENSE files
- Adapt Config.in and a few other programs to the new menu system
This commit is contained in:
Pierre Labastie 2019-04-24 16:16:20 +00:00
parent 7fa93699d4
commit f596dde66c
46 changed files with 9994 additions and 16662 deletions

View file

@ -100,11 +100,9 @@ endif
$(BOOK_XML): $(CONFIG_OUT)
$(Q)$(TOPDIR)/gen_pkg_book.sh $(TOPDIR) $(BLFS_FULL) $(LFS_FULL)
$(CONFIG_OUT): $(CONFIG_CONFIG_IN) $(MENU)/mconf
$(Q)$(MENU)/mconf $(CONFIG_CONFIG_IN)
$(MENU)/mconf:
$(Q)$(MAKE) -C $(MENU) ncurses conf mconf
$(CONFIG_OUT): $(CONFIG_CONFIG_IN)
$(Q)CONFIG_="" KCONFIG_CONFIG=configuration \
$(MENU)/menuconfig.py $(CONFIG_CONFIG_IN)
$(CONFIG_CONFIG_IN): $(PACK_LIST) $(XSLDIR)/gen_config.xsl
$(Q)xsltproc --nonet -o $@ $(XSLDIR)/gen_config.xsl $(PACK_LIST)
@ -202,7 +200,6 @@ $(BLFS_XML):
clean:
rm -f $(CONFIG_OUT) $(CONFIG_OUT).old $(TOPDIR)/packages.xml $(XSLDIR)/specialCases.xsl $(CONFIG_CONFIG_IN) book.xml
rm -rf $(TOPDIR)/dependencies $(TOPDIR)/book-html $(TOPDIR)/scripts
- $(MAKE) -C $(MENU) clean
FORCE:
.PHONY: clean all update $(CONFIG_OUT) FORCE

View file

@ -112,7 +112,7 @@ default	n
menu "</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>"
depends MENU_</xsl:text>
depends on MENU_</xsl:text>
<xsl:value-of select="@id"/>
<xsl:text>
@ -140,7 +140,7 @@ depends MENU_</xsl:text>
&#9;menu "</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>"
&#9;depends MENU_</xsl:text>
&#9;depends on MENU_</xsl:text>
<xsl:value-of select="@id"/>
<xsl:text>
@ -187,7 +187,7 @@ depends MENU_</xsl:text>
&#9;&#9;menu "</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>"
&#9;&#9;depends MENU_</xsl:text>
&#9;&#9;depends on MENU_</xsl:text>
<xsl:value-of select="translate(name,' ()','___')"/>
<xsl:text>

View file

@ -41,7 +41,7 @@ menu "BOOK Settings"
endchoice
choice
depends BOOK_BLFS
depends on BOOK_BLFS
prompt "Init system"
config BLFS_SYSV
@ -107,7 +107,7 @@ menu "BOOK Settings"
config BRANCH_ID
string "Branch (preceded by \"branch-\"), stable Version, or tag"
default "**EDIT ME**"
depends BRANCH
depends on BRANCH
help
A list of valid branches and stable book IDs is available at
http://wiki.linuxfromscratch.org/alfs/wiki/SupportedBooks
@ -118,7 +118,7 @@ menu "BOOK Settings"
config BOOK
string "Loc of working copy (mandatory)"
default "**EDIT ME**"
depends WORKING_COPY
depends on WORKING_COPY
help
The full path to a local copy of the book XML sources
@ -128,7 +128,7 @@ menu "BOOK Settings"
choice
prompt "Target architecture"
default ARCH_X86
depends BOOK_CLFS || BOOK_CLFS2 || BOOK_CLFS3
depends on BOOK_CLFS || BOOK_CLFS2 || BOOK_CLFS3
help
Choose the target system base architecture
@ -156,7 +156,7 @@ menu "BOOK Settings"
choice
prompt "Hardware Platform"
depends BOOK_CLFS3 && ARCH_MIPS
depends on BOOK_CLFS3 && ARCH_MIPS
default PLATFORM_GENERIC
help
Choose a destination platform
@ -171,7 +171,7 @@ menu "BOOK Settings"
choice
prompt "Library"
depends (BOOK_CLFS && !ARCH_ALPHA) || (BOOK_CLFS3 && ARCH_MIPS)
depends on (BOOK_CLFS && !ARCH_ALPHA) || (BOOK_CLFS3 && ARCH_MIPS)
default DATA_32
help
Choose the target system libraries type
@ -188,7 +188,7 @@ menu "BOOK Settings"
choice
prompt "Processor type"
depends (BOOK_CLFS || BOOK_CLFS2 || BOOK_CLFS3) && ((ARCH_X86 && !(DATA_64 || DATA_MULTI)) || ARCH_MIPS || ARCH_HPPA || ARCH_ALPHA || (ARCH_SPARC && (DATA_64 || DATA_MULTI)) || (ARCH_ARM && BOOK_CLFS3))
depends on (BOOK_CLFS || BOOK_CLFS2 || BOOK_CLFS3) && ((ARCH_X86 && !(DATA_64 || DATA_MULTI)) || ARCH_MIPS || ARCH_HPPA || ARCH_ALPHA || (ARCH_SPARC && (DATA_64 || DATA_MULTI)) || (ARCH_ARM && BOOK_CLFS3))
help
Choose the target system processor
@ -258,7 +258,7 @@ menu "BOOK Settings"
choice
prompt "MIPS 64 ABI"
depends BOOK_CLFS3 && ARCH_MIPS && DATA_64
depends on BOOK_CLFS3 && ARCH_MIPS && DATA_64
default ABI_64
help
Choose the target system ABI to use
@ -322,7 +322,7 @@ menu "BOOK Settings"
config TARGET32
string
depends DATA_MULTI
depends on DATA_MULTI
default "i686-pc-linux-gnu" if ARCH_X86
default "mipsel-unknown-linux-gnu" if PROC_mipsel
default "mips-unknown-linux-gnu" if PROC_mips
@ -368,13 +368,13 @@ menu "BOOK Settings"
config MIPS_LEVEL
string
depends BOOK_CLFS3 && ARCH_MIPS
depends on BOOK_CLFS3 && ARCH_MIPS
default "1" if DATA_32
default "3" if DATA_64
config ABI
string
depends BOOK_CLFS3
depends on BOOK_CLFS3
default "-m32" if ARCH_X86 || ARCH_ARM
# default "-m64" if NO USED YET IN THE BOOK
default "-mabi=32" if ABI_32 || (ARCH_MIPS && DATA_32)
@ -383,13 +383,13 @@ menu "BOOK Settings"
config ENDIAN
string
depends BOOK_CLFS3 && (ARCH_MIPS || ARCH_ARM)
depends on BOOK_CLFS3 && (ARCH_MIPS || ARCH_ARM)
default "little" if PROC_mipsel || PROC_ARM || PROC_ARM5L
default "big" if PROC_mips || PROC_ARM5B
choice
prompt "Build method"
depends BOOK_CLFS
depends on 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
@ -541,7 +541,7 @@ menu "BOOK Settings"
config BLFS_XML
string "BLFS sources directory (internal parameter)"
default "blfs-xml"
depends BLFS_TOOL || BOOK_BLFS
depends on BLFS_TOOL || BOOK_BLFS
help
The directory name under $BLFS_ROOT where the BLFS
book sources will be copied or checked out. Do not change that
@ -550,7 +550,7 @@ menu "BOOK Settings"
config LFS_XML
string "LFS sources directory (internal parameter)"
default "lfs-xml"
depends BLFS_TOOL || BOOK_BLFS
depends on BLFS_TOOL || BOOK_BLFS
help
The directory name under $BLFS_ROOT where the LFS
book sources will be copied or checked out. Do not change that
@ -558,8 +558,8 @@ menu "BOOK Settings"
choice
prompt "LFS Release"
default LFS_SVN
depends BOOK_BLFS
default LFS_relSVN
depends on BOOK_BLFS
config LFS_relSVN
bool "LFS SVN"
@ -595,7 +595,7 @@ menu "BOOK Settings"
#--- Custom Tools support
config CUSTOM_TOOLS
depends !BOOK_BLFS
depends on !BOOK_BLFS
bool "Add custom tools support"
default n
help
@ -630,7 +630,7 @@ menu "BOOK Settings"
endmenu
menu "General Settings"
depends !BOOK_BLFS
depends on !BOOK_BLFS
#--- {C,H,}LFS User Account
@ -671,7 +671,7 @@ depends !BOOK_BLFS
config SRC_ARCHIVE
string "Package Archive Directory"
default "$SRC_ARCHIVE"
depends GETPKG
depends on GETPKG
help
#-- A local archive for packages/files (not $BUILDDIR/sources)
# Any missing file will be downloaded and archived here,
@ -680,7 +680,7 @@ depends !BOOK_BLFS
config RETRYSRCDOWNLOAD
bool "Retry on 'connection refused' failure"
default n
depends GETPKG
depends on GETPKG
help
#-- Attempt to download a source package again if it fails
# with a 'connection refused' error. This can happen on
@ -689,14 +689,14 @@ depends !BOOK_BLFS
config RETRYDOWNLOADCNT
int "Number of retry attempts on download failures"
default 20
depends GETPKG
depends on GETPKG
help
#-- Number of times to retry a failed download.
config DOWNLOADTIMEOUT
int "Download timeout (in seconds)"
default 30
depends GETPKG
depends on GETPKG
help
#-- Number of seconds to wait for a download to start before
# timing out.
@ -704,7 +704,7 @@ depends !BOOK_BLFS
config SERVER
string "FTP mirror"
default "http://ftp.osuosl.org"
depends GETPKG
depends on GETPKG
help
#-- FTP mirror to download packages and patches if not found
# in $SRC_ARCHIVE
@ -729,12 +729,12 @@ depends !BOOK_BLFS
endmenu
menu "Build Settings"
depends !BOOK_BLFS
depends on !BOOK_BLFS
#--- Test Suites
config CONFIG_TESTS
bool "Run testsuites"
depends !BOOK_CLFS2 && !BOOK_CLFS3
depends on !BOOK_CLFS2 && !BOOK_CLFS3
default y
help
#-- Run test suites
@ -757,7 +757,7 @@ depends !BOOK_BLFS
# temporary tools phase
menu "Test settings"
depends CONFIG_TESTS
depends on CONFIG_TESTS
choice
prompt "Tests level"
default TST_1
@ -813,7 +813,7 @@ depends !BOOK_BLFS
#--- Package Management
config PKGMNGT
bool "Package management"
depends BOOK_LFS || BOOK_LFS_SYSD
depends on BOOK_LFS || BOOK_LFS_SYSD
default n
help
#-- Use package management
@ -838,7 +838,7 @@ depends !BOOK_BLFS
#
# For now, this only works with LFS
choice
depends PKGMNGT
depends on PKGMNGT
prompt "Package management style"
default PKG_PACK
@ -888,7 +888,7 @@ depends !BOOK_BLFS
endmenu
menu "System configuration"
depends !BOOK_BLFS
depends on !BOOK_BLFS
#--- FSTAB
config HAVE_FSTAB
@ -1066,7 +1066,7 @@ menu "System configuration"
config LOG_LEVEL
string "Default log level (1-8)"
default "4"
depends BOOK_LFS
depends on BOOK_LFS
help
This can be changed using dmesg. 1 means "no message",
8 shows every message sent by the kernel, which is very
@ -1077,26 +1077,26 @@ menu "System configuration"
endmenu #--- System configuration
menu "Advanced Features"
depends !BOOK_BLFS
depends on !BOOK_BLFS
config REPORT
bool "Create SBU and disk usage report"
default y
#--- ICA/farce
#--- ICA
config COMPARE
bool "Run comparison analysis on final stage"
depends !BOOK_CLFS2 && !BOOK_CLFS3
depends on !BOOK_CLFS2 && !BOOK_CLFS3
default n
help
#-- Should an iterative comparison analysis be performed?
#
# Unless you are familiar with ICA and/or FARCE do not
# Unless you are familiar with ICA, do not
# select this option
#
# ICA and FARCE are analysis tools for comparing one
# ICA is an analysis tool 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 another due to the build order and this tool try
# to ferret out those differences by examining the stored
# build logs and binary files.
#
@ -1110,19 +1110,10 @@ depends !BOOK_BLFS
default 3
config RUN_ICA
bool "ICA testing"
depends on COMPARE
default y
help
#-- Run ICA testing
bool
default y if COMPARE
config RUN_FARCE
bool "farce testing"
depends on COMPARE
default n
help
#-- Run farce testing
#--- End ICA/farce
#--- End ICA
#--- Optimizations
if !BOOK_CLFS2 && !BOOK_CLFS3
@ -1221,10 +1212,6 @@ endif
string "ICA logs directory"
default "$LOGDIR/ICA"
config FARCELOGDIR
string "farce logs directory"
default "$LOGDIR/farce"
config MKFILE
string "Makefile"
default "$JHALFSDIR/Makefile"
@ -1244,7 +1231,7 @@ endif
endmenu
config REBUILD_MAKEFILE
depends !BOOK_BLFS
depends on !BOOK_BLFS
bool "Rebuild the Makefile (see help)"
default n
help

View file

@ -182,10 +182,6 @@ wrt_do_ica_work():
From common/libs/func_compare.sh.
Description:
--------------------------------------------------------------------------
wrt_do_farce_work():
From common/libs/func_compare.sh.
Description:
--------------------------------------------------------------------------
wrt_logs():
From common/libs/func_compare.sh.
Description:
@ -246,62 +242,6 @@ clean_builddir():
From common/common-functions.
Description:
--------------------------------------------------------------------------
function dohelp():
From extras/farce.
Description:
--------------------------------------------------------------------------
function emessage():
From extras/farce.
Description:
--------------------------------------------------------------------------
function expected():
From extras/farce.
Description:
--------------------------------------------------------------------------
function failure():
From extras/farce.
Description:
--------------------------------------------------------------------------
function fatal():
From extras/farce.
Description:
--------------------------------------------------------------------------
function filetype():
From extras/farce.
Description:
--------------------------------------------------------------------------
function message():
From extras/farce.
Description:
--------------------------------------------------------------------------
function onlyone():
From extras/farce.
Description:
--------------------------------------------------------------------------
function testar():
From extras/farce.
Description:
--------------------------------------------------------------------------
function testgzip():
From extras/farce.
Description:
--------------------------------------------------------------------------
function testso():
From extras/farce.
Description:
--------------------------------------------------------------------------
function tokenize():
From extras/farce.
Description:
--------------------------------------------------------------------------
function tokenizeanddiff():
From extras/farce.
Description:
--------------------------------------------------------------------------
function validateargs():
From extras/farce.
Description:
--------------------------------------------------------------------------
process_toolchain():
From HLFS/master.sh.
Description: embryo,cocoon and butterfly need special handling

353
LICENSE
View file

@ -1,340 +1,19 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 2005-2019, jhalfs team
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Preamble
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE

View file

@ -5,35 +5,19 @@
# Manuel Canales Esparcia
# Pierre Labastie
TOPDIR=$(shell pwd)
CONFIG_CONFIG_IN = Config.in
CONFIG = menu
all: menuconfig
# @clear
@$$(grep RUN_ME configuration 2>/dev/null | sed -e 's@RUN_ME=\"@@' -e 's@\"@@')
$(CONFIG)/conf:
$(MAKE) -C $(CONFIG) conf
$(CONFIG)/mconf:
$(MAKE) -C $(CONFIG) ncurses conf mconf
menuconfig: $(CONFIG)/mconf
@cp -a configuration configuration.old 2>/dev/null || true
@$(CONFIG)/mconf $(CONFIG_CONFIG_IN)
config: $(CONFIG)/conf
@$(CONFIG)/conf $(CONFIG_CONFIG_IN)
menuconfig:
@cp -a configuration .configuration.old 2>/dev/null || true
@CONFIG_="" KCONFIG_CONFIG=configuration $(CONFIG)/menuconfig.py $(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
.PHONY: all menuconfig clean

2
README
View file

@ -204,8 +204,6 @@ $Id$
/extras/do_copy_files
/do_ica_prep
/do_ica_work
/farce
/filelist
/optimize/opt_config
/opt_override

View file

@ -58,7 +58,6 @@ wrt_compare_work() { #
local ROOT_DIR=/
local DEST_TOPDIR=/${SCRIPT_ROOT}
local ICALOGDIR=/${SCRIPT_ROOT}/logs/ICA
local FARCELOGDIR=/${SCRIPT_ROOT}/logs/farce
if [[ "$RUN_ICA" = "y" ]] ; then
local DEST_ICA=$DEST_TOPDIR/ICA && \
@ -73,18 +72,6 @@ EOF
fi
fi
if [[ "$RUN_FARCE" = "y" ]] ; then
local DEST_FARCE=$DEST_TOPDIR/farce && \
(
cat << EOF
@extras/do_copy_files "$PRUNEPATH" $ROOT_DIR $DEST_FARCE/$ITERATION >>logs/\$@ 2>&1 && \\
extras/filelist $DEST_FARCE/$ITERATION $DEST_FARCE/filelist-$ITERATION >>logs/\$@ 2>&1
EOF
) >> $MKFILE.tmp
if [[ "$ITERATION" != "iteration-1" ]] ; then
wrt_do_farce_work "$PREV_IT" "$ITERATION" "$DEST_FARCE"
fi
fi
}
#----------------------------------#
@ -93,17 +80,6 @@ wrt_do_ica_work() { #
echo -e "\t@extras/do_ica_work $1 $2 $ICALOGDIR $3 >>logs/\$@ 2>&1" >> $MKFILE.tmp
}
#----------------------------------#
wrt_do_farce_work() { #
#----------------------------------#
local OUTPUT=$FARCELOGDIR/${1}_V_${2}
local PREDIR=$3/$1
local PREFILE=$3/filelist-$1
local ITEDIR=$3/$2
local ITEFILE=$3/filelist-$2
echo -e "\t@extras/farce --directory $OUTPUT $PREDIR $PREFILE $ITEDIR $ITEFILE >>logs/\$@ 2>&1" >> $MKFILE.tmp
}
#----------------------------------#
wrt_logs() { #
#----------------------------------#

View file

@ -22,7 +22,6 @@ if [ "$WRAP_INSTALL" = y ]; then
fi
# Clean-up
make -C ${BUILDDIR}${BLFS_ROOT}/menu clean
rm -rf ${BUILDDIR}${BLFS_ROOT}/libs/.svn
rm -rf ${BUILDDIR}${BLFS_ROOT}/xsl/.svn
rm -rf ${BUILDDIR}${BLFS_ROOT}/menu/.svn

View file

@ -27,7 +27,7 @@ inline_doc
RUNMAKE"
local -r BUILD_chroot="TEST BOMB_TEST STRIP"
local -r BUILD_common="FSTAB CONFIG TIMEZONE PAGE LANG INSTALL_LOG"
local -r ADVANCED_chroot="COMPARE RUN_ICA RUN_FARCE ITERATIONS OPTIMIZE"
local -r ADVANCED_chroot="COMPARE RUN_ICA ITERATIONS OPTIMIZE"
local -r ADVANCED_common="REPORT REBUILD_MAKEFILE"
# BOOK Settings by book
@ -147,7 +147,6 @@ inline_doc
# Envvars that depend on other settings to be displayed
COMPARE) [[ ! "$COMPARE" = "y" ]] && echo -e "`eval echo $PARAM_VALS`" ;;
RUN_ICA) [[ "$COMPARE" = "y" ]] && echo -e "`eval echo $PARAM_VALS`" ;;
RUN_FARCE) [[ "$COMPARE" = "y" ]] && echo -e "`eval echo $PARAM_VALS`" ;;
ITERATIONS) [[ "$COMPARE" = "y" ]] && echo -e "`eval echo $PARAM_VALS`" ;;
BOMB_TEST) [[ ! "$TEST" = "0" ]] && echo -e "`eval echo $PARAM_VALS`" ;;
TARGET32) [[ -n "${TARGET32}" ]] && echo -e "`eval echo $PARAM_VALS`" ;;

View file

@ -1,897 +0,0 @@
#!/bin/bash
# $Id$
# Acknowledgment:
# The following code is a no-modified version (except for this comment,
# the `Id' comment, and the inline_doc fragment) of an original work written by
# Ken Moffat and is included here with his permission.
#
# FARCE: Farce Assists Rebuild Comparison Evaluation ;)
#
# to answer the question "can it rebuild itself?"
#
# We expect four arguments - first directory path, filelist
# containing the files in this directory which we wish to compare,
# second directory path, filelist for second directory.
#
# Yes, we could just compare everything in each tree, but the
# filelist script knows about files it can reasonably ignore,
# and this also allows us to build a sytem, boot it and get a
# list of files, build a full desktop environment, and only then
# build and boot the "can it build itself" test system and get
# _its_ filelist.
#
# What this script aims to do:
# ____________________________
#
# First, report files not in both builds.
#
# Then, confirm symlinks point to same targets.
#
# After that, compare individual files -
# if different, run the file name through 'expected'
# to pick out files that are unlikely to match (logs,
# pids, fstab [assumes '/' is a different device each time],
# count these as 'expected'.
#
# For whatever is left, check the file type - ar archives
# have their members extraced and compared (every member has
# a timestamp), gzipped files are compared beyond their
# timestamp, binaries, at least those using shared libs or
# which are shared objects, are copied and subjected to
# --strip-debug. If files match at this stage, count them as
# 'accepted'.
#
# As a last step for any file that doesn't match, copy it
# through some perl regexps to "process" it (convert any
# date, time, kernel-version information from standard formats
# into tokens, then see if the tokensi match.
#
# For details of the regexps, see the tokenize function.
# Those files that match after this are also counted as
# 'accepted'. Note that I don't always start from the kernel
# version that I'm going to build, so this copes with e.g. perl
# files that hardcode the kernel version.
#
# We now have files that don't match. A few of these seem to be
# common to all builds - some (members of) c++ libraries or ar
# archives, a few programs which perhaps use some sort of c++ code).
# The file name # is passed to the 'failure' function - these
# recognized filenames are labelled as 'predictable FAIL:',
# anything else is labelled as 'unexpected FAIL:'.
#
# output:
# stderr - files only in one of the builds, failure messages,
# and totals.
#
# farce-results - more details, including which files were treated
# as expected differences, files where neither copy could be read,
# files treated as accepted, with the reason (and member for ar
# archives). This data is typically up to 100 characters wide -
# sometimes it's a bit more, but it doesn't wrap too badly in a
# 100 character xterm.
#
# farce-extras - diffs for the files, or members, that didn't
# match. This file is to establish new regexps for picking up
# date/time/kernel-version formats.
#
# farce-identical - the names of the files which are identical
#
# farce-substitutions - whenever using tokenizeanddiff results in a
# difference being accepted, for both versions diff the before and
# after versions to show what got changed. If the file is a binary,
# the output may still be hard to read. Note that I _know_ glibc
# version strings pass one of the regexps looking for a kernel version
# - since I expect you to use the same version of glibc for each
# build, this is not a problem.
#
# farce-differ - the names of the files which could not be treated
# as matching (whether or not I regard the failure as predictable)
# for possible input to ICA processing.
#
# Copyright (C) 2005, 2006 Ken Moffat <ken@linuxfromscratch.org>
#
# All rights reserved.
#
# 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, GOOD TITLE or
# NON INFRINGEMENT. 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.
#
: <<inline_doc
desc: do farce analisys and report
usage: farce -directory $FARCELOGDIR/dir path1 list1 path2 list2
input vars: $1 farce log dir for this comparation
$2 full path to previous iteration
$3 full path to filelist for previos iteration
$4 full path to current iteration
$5 full path to filelist for current iteration
externals: --
modifies: --
returns: --
on error:
on success:
inline_doc
VERSION="002"
# variables for output files
RESULT=farce-results
EXTRAS=farce-extras
IDENTICAL=farce-identical
SUBS=farce-substitutions
DIFFER=farce-differ
# documenting the variables
# C1, C2 temp files to hold disassembled code
# D1, D2 temp directories for extracting member of ar archive
# DIFF temp file for diffing the filelists
# F1, F2 temp files for tokenizeanddiff
# FTYPE obsolete, commented out
# M1, M2 temp files to hold members of an ar archive
# MEMBERS temp file to list members of ar archive
# OP1, OP2 the original $PWD, needed when extracting members of ar
# archives
# P1, P2 paths to first and second build
# S1, S2 temp files for shared objects
# functions
function dohelp() {
echo "`basename $0`: compare trees of files from a build"
echo "and lists of the files they contained"
echo ""
echo "`basename $0` [ -help | -version ] || path1 list1 path2 list2"
}
function emessage() {
# write a string to both stderr and $RESULT
echo "$@" >&2
echo "$@" >&5
}
function expected() {
# if we expect it to differ because of its name,
# allow it and report, return true ; else return false
case $1 in
/boot/grub/menu.lst)
# just in case somebody puts this into the main filesystem
true;;
/etc/aliases.db)
# some sort of database for postfix, not parsable
true;;
/etc/blkid.tab)
# includes dev name for rootfs
true;;
/etc/fstab)
# fstab, e.g. ' / ' will differ
true;;
/etc/group*)
true;;
/etc/hosts)
# with dhcp client, I add current ip address to this in a hook
true;;
/etc/ld.so.*)
# .conf and .cache can vary,
# particularly if one system has a full build when I run this
true;;
/etc/lilo.conf|/etc/yaboot.conf)
# bootloader control, I assume grub will all be on a separate
true;;
/etc/mtab)
# at a minimum, different '/'
true;;
/etc/ntp.drift)
true;;
/etc/passwd*)
true;;
/etc/shadow*)
true;;
/etc/ssh/*key|/etc/ssh/*pub)
# openssh keys
true;;
/misc/*)
# where I put buildscripts (which mostly won't change)
# and stamps containing name/time/space which will differ in the times
true;;
/root/*)
# expect .bash_history etc to differ - if we can read them
true;;
/usr/bin/lynx)
# part of my inital builds, I guess this uses anonymous namespaces
true;;
/usr/include/c++/*/*/bits/stdc++.h.gch/*)
# precompiled headers
true;;
/usr/lib*/libstdc++.a|/usr/lib*/libstdc++.so*|/usr/lib*/libsupc++.a)
# probably, anonymous namespaces
# libstdc++.a, libstdc++.so.n.n.n, libsupc++.a
true;;
/usr/share/info/dir)
# if one system has had extra stuff built, this will likely be bigger
true;;
/usr/share/man/whatis)
# if one system has had extra stuff built, this will likely be bigger
true;;
/var/lib/locate/locatedb)
# if one system has had extra stuff built, this will likely be bigger
true;;
/var/lib/nfs/*)
# allow nfs bookkeeping
true;;
/var/log/*)
true;;
/var/run/utmp)
true;;
/var/spool/fcron*)
true;;
/var/state/*)
# allow dhcp leases
true;;
/var/tmp/random-seed)
true;;
# following start with wildcards
*Image*|*.PPCBoot*|*vmlinuz*|*lfskernel*)
# compressed kernels, sometimes just building at a different
# date/time is enough to change the length of them, because the
# long format date and time is part of the compressed data
true;;
*pid*)
# pids, including e.g. /var/spool/postfix/pid/*
true;;
*)
# nothing else is expected to be different
false;;
esac
if [ $? -eq 0 ]; then
message "expected difference in $1"
let expected=$expected+1
case $TYPE in
AR)
let EXPAR=$EXPAR+1
;;
ELF)
let EXPELF=$EXPELF+1
;;
UNK)
let EXPUNK=$EXPUNK+1
;;
# so far, no other valid types, so don't accumulate them
*)
emessage "internal error, expected difference for $1 of type $TYPE not allowed"
exit 2
;;
esac
true
else
false
fi
}
function failure() {
# first parm is filename or token
# second parm is the error message
# update the appropriate total
# and write to both stderr and the results
# by using emessage
let different=$different+1
case $TYPE in
AR)
let DIFAR=$DIFAR+1
;;
ELF)
let DIFELF=$DIFELF+1
;;
GZ)
let DIFGZ=$DIFGZ+1
;;
SYM)
let DIFSYM=$DIFSYM+1
;;
UNK)
let DIFUNK=$DIFUNK+1
;;
*)
emessage "internal error in failure() for TYPE $TYPE"
exit 2
;;
esac
test -f ${P1}$1 && echo $1 >&9
emessage "FAIL: $2"
}
function fatal() {
# unrecoverable error
echo $*
exit 1
}
function filetype() {
TYPE=`file ${P1}${FILE}`
case $TYPE in
*'current ar archive'*)
let TOTAR=$TOTAR+1
TYPE=AR
;;
*' ELF '*)
let TOTELF=$TOTELF+1
TYPE=ELF
;;
*'gzip compressed data'*)
let TOTGZ=$TOTGZ+1
TYPE=GZ
;;
*)
let TOTUNK=$TOTUNK+1
TYPE=UNK
;;
esac
}
function message() {
# write a string to $RESULT
echo $* >&5
}
function onlyone() {
#report files only in one build
# text should go to both stderr and the results,
# but blank lines only go to the results
if [ $1 == '<' ]; then
emessage "File(s) only in the first build"
else
emessage "File(s) only in the second build"
fi
message ""
FILES=`cat $DIFF | grep "^$1" | cut -d ' ' -f 2`
for F in $FILES; do
emessage $F
let only=$only+1
done
message ""
}
# 'test' functions are called with three arguments:
# the two pathes and the filename
# - we know the file is of this type, so see if we
# can get it to match by reasonalbe means.
# if not, treat it as different.
#
# NB if pathes are absolute, we need to prefix them
# with the original $PWD to access the .a files
#
function testar() {
# ar archives include timestamps for the members,
# but diff doesn't show file timestamps unless the data differs
# put out a message to help locate which archive any messages
# about the members refer to.
# try just stripping them U1,2 undebuggable
U1=`mktemp` || fatal "cannot create a temporary file"
U2=`mktemp` || fatal "cannot create a temporary file"
cp ${1}${3} $U1
cp ${2}${3} $U2
strip --strip-debug $U1
strip --strip-debug $U2
cmp -s $U1 $U2
rm $U1 $U2
if [ $? -eq 0 ]; then
let accepted=$accepted+1
let ACCAR=$ACCAR+1
message "archive $3 matches after strip --strip-debug"
return
fi
# rest of this function retained primarily for pathologically bad builds
# put out a message in the log to help identify which archive has issues.
message "examining ar archive $3"
D1=`mktemp -d` || fatal "cannot create a temporary directory"
D2=`mktemp -d` || fatal "cannot create a temporary directory"
cd $D1
ar -x ${OP1}${1}${3}
cd $D2
ar -x ${OP2}${2}${3}
cd
# diff the members - true means they match
diff -Na $D1 $D2 >/dev/null
if [ $? -eq 0 ]; then
message "accept: $3 after diffing the members"
let accepted=$accepted+1
let ACCAR=$ACCAR+1
else
# process individual members to eliminate date/time/kernel-version
# first, check the members are the same
M1=`mktemp` || fatal "cannot create a temporary file"
M2=`mktemp` || fatal "cannot create a temporary file"
cd $D1
MEMBERS=
for F in *; do
MEMBERS="$MEMBERS $F"
done
cd
echo $MEMBERS | sort >$M1
cd $D2
MEMBERS=
for F in *; do
MEMBERS="$MEMBERS $F"
done
cd
echo $MEMBERS | sort >$M2
cmp -s $M1 $M2
if [ $? -ne 0 ]; then
# oh dear, different members
echo "list of members differs for archive $3" >&6
diff $M1 $M2 >&6
failure $3 "$3 list of members differs"
else
# members (names) are same,
# process each one
STATUS=0
for M in $MEMBERS; do
#avoid firing up perl on matching members
cmp -s $D1/$M $D2/$M
if [ $? -ne 0 ]; then
tokenizeanddiff $D1/$M $D2/$M $FILE:$M
if [ $? -eq 0 ]; then
message "member $M matches after processing"
else
message "member $M DIFFERS after processing"
STATUS=1
fi
fi
done
if [ $STATUS -eq 0 ]; then
let accepted=$accepted+1
let ACCAR=$ACCAR+1
else
let different=$different+1
let DIFAR=$DIFAR+1
echo $3 >&9
emessage "FAIL: in $3"
fi
fi
rm $M1 $M2
fi
rm -rf $D1 $D2
}
function testgzip() {
# bytes 4,5,6,7 are the timestamp, so ignore these
cmp -s -i 8 ${1}${3} ${2}${3}
if [ $? -eq 0 ]; then
message "accept: $3 after ignoring gzip timestamp"
let accepted=$accepted+1
let ACCGZ=$ACCGZ+1
else
failure $3 " $3 even after ignoring gzip timestamp"
fi
}
function testso() {
# shared object - first try stripping it
# in fact, this now handles ALL ELF files
S1=`mktemp` || fatal "cannot create a temporary file"
S2=`mktemp` || fatal "cannot create a temporary file"
cp ${1}${3} $S1
strip --strip-debug $S1
cp ${2}${3} $S2
strip --strip-debug $S2
cmp -s $S1 $S2
if [ $? -eq 0 ]; then
message "accept: $3 after --strip-debug"
let accepted=$accepted+1
let ACCELF=$ACCELF+1
else
tokenizeanddiff $S1 $S2 $3
if [ $? -ne 0 ]; then
failure $3 " $3 differs after stripping and processing"
else
message "accept: $3 after --strip-debug and processing"
let accepted=$accepted+1
let ACCELF=$ACCELF+1
fi
fi
rm $S1 $S2
}
function tokenize() {
# use regexes to replace date/time/kernel-version text
# with tokens which may allow files to match even though
# they have hardcoded date/time/kernel-version.
# arguments are file to process, and where to put it.
# these regexes are somewhat long, and the order they
# are applied in is important (to stop short ones being
# used when a longer version would match).
# KV00 linux version date (e.g. as in the kernel itself)
# allow 2 or 3 groups of three alphas here - optional smp, with day, mon
# KV01 kernel version, including possible cpu details (that is for cdda2wav)
# KV02 just the version, in quotes e.g. "2.6.12.6" or '2.6.13', for perl stuff
# except that "|' gives me grif, so try a boundary
# also, it might need local version on the end, I really want
# quote2.\d+.\d+.{0,32}quote - it is the quotes that don't work.
# DT00 Day Mon .d+ hh:mm:ss TZN CCYY variations include non-caps and 'mon d'
# DT01 Mon .d+ CCYY hh:mm:ss
# DT02 hh:mm:ss Mon .d CCYY
# DT03 Mon .d CCYY
# DT04 Day Mon { ,d}d hh:mm:ss CCYY - for groff example postscript files
# (somewhat similar to DT00, but ' d' or ' dd' for day of month and no TZN )
# DT05 hh:mm:ss
# DT06 ISO date using space as separator
# DT07 ISO date using dash as separator
# DT08 ISO date using slash as separator
# DT09 fullmonth (capitalised), day number, comma, 4-digit year (groff 1.18.1 ps)
# DT10 dd, fullmonth (capitalised), 4-digit year (groff 1.18.1 manpages)
# DT11 '(xample comma space digit(s) backslash ) in groff memef.ps which is
# quite clearly the day of the month when it was compiled, preceded by 'example'
# with something weird between the e and the x.
if [ $# -ne 2 ]; then
fatal "tokenizing called with $# arguments : $*"
fi
cat $1 | perl -p \
-e 's/(L|l)inux.*\d\.\d\.\d+.* \#\d+( [A-Za-z][a-z]{2}){2,3} \d+ \d\d:\d\d:\d\d [A-Za-z]{3} \d{4}\b/%KV00%/g;' \
-e 's/(L|l)inux( (\w|_)+)?(-| |_)\d\.\d(\.\d+){1,2}((-|_)?(\w|_)+)?( |\000)*/%KV01%/g;' \
-e 's/\W2(\.\d+){2,3}(-|_)?((\w|_)+)?\s*\W/%KV02%/g;' \
-e 's/\b([A-Za-z][a-z]{2} ){2}( |\d)?\d \d\d:\d\d:\d\d [A-Za-z]{3} \d{4}\b/%DT00%/g;' \
-e 's/\b[A-Z][a-z]{2} ( |\d)\d \d{4} \d\d:\d\d:\d\d\b/%DT01%/g;' \
-e 's/\b\d\d:\d\d:\d\d [A-Z][a-z]{2} ( |\d)\d \d{4}\b/%DT02%/g;' \
-e 's/\b[A-Z][a-z]{2} ( |\d)\d \d{4}\b/%DT03%/g;' \
-e 's/\b([A-Z][a-z]{2} ){2}( |\d)\d \d\d:\d\d:\d\d \d{4}/%DT04%/g;' \
-e 's/\b\d\d:\d\d:\d\d\b/%DT05%/g;' \
-e 's/\b\d{4} \d\d \d\d\b/%DT06%/g;' \
-e 's/\b\d{4}-\d\d-\d\d\b/%DT07%/g;' \
-e 's/\b\d{4}\/\d\d\/\d\d\b/%DT08%/g;' \
-e 's/\b[A-Z][a-z]{2,} \d{1,2}, \d{4}/%DT09%/g;' \
-e 's/\b\d\d [A-Z][a-z]{2,} \d{4}/%DT10%/g;' \
-e 's/\(xample, \d{1,2}\\\)/%DT11%/g;' \
>$2
}
function tokenizeanddiff() {
# Call tokenize for the inputs, then compare the results
# Input arguments are path/filename for old and new versions
# third parm is readable name (filename, or archivename:member)
# to help understand what is in the extras output.
# - sometimes called for files, but other times called for
# members of ar archives extracted into temporary directories
#message tokenizeanddiff called for $1 $2 $3
F1=`mktemp` || fatal "cannot create a temporary file"
F2=`mktemp` || fatal "cannot create a temporary file"
tokenize $1 $F1
tokenize $2 $F2
# actually, cmp is probably more efficient
# but for picking up the pieces it will be better to
# use diff to see what got through.
cmp -s $F1 $F2
TOKENRESULT=$?
if [ $TOKENRESULT -ne 0 ]; then
echo "failure in $3..." >&6
diff -a $F1 $F2 >&6
rm $F1 $F2
false
else
# show what we did
echo "substitutions for $3" >&8
echo "build one" >&8
diff -a $1 $F1 >&8
echo "build two" >&8
diff -a $2 $F2 >&8
rm $F1 $F2
true
fi
}
function validateargs() {
# validate the arguments
BAD=0
if ! [ -d $1 ]; then
echo "Error: first argument is not a directory" >&2
let BAD=$BAD+1
fi
NAME=`basename ${2%%-*}`
if [ $NAME != filelist ]; then
echo "Error: second argument is not a recognized filelist" >&2
let BAD=$BAD+1
fi
if ! [ -d $3 ]; then
echo "Error: third argument is not a directory" >&2
let BAD=$BAD+1
fi
NAME=`basename ${4%%-*}`
if [ $NAME != filelist ]; then
echo "Error: fourth argument is not a recognized filelist" >&2
let BAD=$BAD+1
fi
for I in $1 $2 $3 $4; do
if ! [ -r $I ]; then
echo "Error: cannot read $I" >&2
let BAD=$BAD+1
fi
done
if [ $1 == $3 ]; then
echo "Error: directory pathes are identical" >&2
let BAD=$BAD+1
fi
if [ $2 == $4 ]; then
echo "Error: filelist names are identical" >&2
let BAD=$BAD+1
fi
if [ $BAD -eq 0 ]; then
ARGS=valid
fi
}
# Mainline
ARGS=unproven
OUTDIR=
if [ $# -eq 1 ]; then
case $1 in
-version|--version)
echo "`basename $0` version $VERSION"
exit 0
;;
-help|--help)
dohelp
exit 0
;;
esac
fi
if [ $1 = "--directory" ]; then
OUTDIR=$2
shift 2
grep '/$' $OUTDIR >/dev/null 2>&1 || OUTDIR=`echo $OUTDIR | sed 's%$%/%'`
echo "creating directory $OUTDIR"
mkdir -p $OUTDIR
if [ $? -ne 0 ]; then
echo "cannot mkdir $OUTDIR"
exit 1
fi
fi
if [ $# -eq 4 ]; then
validateargs $*
fi
if ! [ $ARGS == valid ]; then
dohelp
fatal "`basename $0`: error in arguments"
fi
# ok, we're happy, lets hit these files
exec 5>${OUTDIR}$RESULT
exec 6>${OUTDIR}$EXTRAS
exec 7>${OUTDIR}$IDENTICAL
exec 8>${OUTDIR}$SUBS
exec 9>${OUTDIR}$DIFFER
>${OUTDIR}$RESULT
if [ $? -ne 0 ]; then
fatal "cannot write to ${OUTDIR}$RESULT"
fi
emessage "will compare:"
emessage " first build at $1 with files listed in $2"
emessage "second build at $3 with files listed in $4"
let accepted=0
let different=0
let expected=0
let matched=0
let only=0
let predictable=0
let unreadable=0
let total=0
# break down the accepted
let ACCAR=0
let ACCELF=0
let ACCGZ=0
let ACCUNK=0
# break down definitely different
let DIFAR=0
let DIFELF=0
let DIFGZ=0
let DIFSYM=0
let DIFUNK=0
# break down the expected differences
let EXPAR=0
let EXPELF=0
let EXPGZ=0
let EXPUNK=0
# break down the identical files
let MATAR=0
let MATELF=0
let MATGZ=0
let MATSYM=0
let MATUNK=0
# break down how many of each type
let TOTAR=0
let TOTELF=0
let TOTGZ=0
let TOTSYM=0
let TOTUNK=0
# now identify differences between the two trees
DIFF=`mktemp` || fatal "cannot create a temporary file"
diff $2 $4 >$DIFF
for RUN in '<' '>' ; do
grep -q "$RUN" $DIFF && onlyone "$RUN"
done
rm $DIFF
# and compare them
message "Results of file comparison:"
message ""
# Strip any trailing slash from the path for tidyness,
# because the filenames all start with a slash. Unfortunately,
# unfortunately, '/' becomes empty, which breaks subroutines,
# so special case it.
# also, to process ar archives we need to extract them in temp
# directories - that means that after cd'ing we've broken any
# relative path, so save original pwd as necessary.
P1=`echo $1 | sed 's%/$%%'`
echo $1 | grep '^/' >/dev/null
if [ $? -ne 0 ]; then
# relative path
OP1=${PWD}/
#echo "setting OP1 to $OP1"
else
OP1=
#echo "$1 is an absolute path"
fi
test -z "$P1" && P1='/'
P2=`echo $3 | sed 's%/$%%'`
echo $3 | grep '^/' >/dev/null
if [ $? -ne 0 ]; then
# relative path
OP2=${PWD}/
#echo "setting OP2 to $OP2"
else
OP2=
#echo "$3 is an absolute path"
fi
test -z "$P2" && P2='/'
echo "about to read $2"
while read FILE ; do
#echo "process $FILE"
#echo "test existence of ${P2}${FILE}"
# confirm it exists in second build
# we have already reported files only in one build
if [ -f ${P2}"${FILE}" ]; then
let total=$total+1
# check we can read both of them
# or count as unreadable - I used to separate only-one-unreadable,
# but if you compre '/' and a _copy_ of /mnt/lfs that assumption
# breaks, so be less picky.
if ! [ -r "${P1}${FILE}" ] || ! [ -r "${P2}${FILE}" ]; then
message "cannot read one or both versions of $FILE"
let unreadable=$unreadable+1
continue
fi
if [ -h "${P1}${FILE}" ]; then
# for symlink, look at what it points to
# exceptionally, do not call filetype
TYPE=SYM
let TOTSYM=$TOTSYM+1
SL1=`ls -l "${P1}${FILE}" | awk '{ print $11 }'`
SL2=`ls -l "${P2}${FILE}" | awk '{ print $11 }'`
if [ "$SL1" = "$SL2" ]; then
echo "symlink $FILE matches for $SL1" >&5
let matched=$matched+1
let MATSYM=$MATSYM+1
else
failure TARGET " symlink $FILE points to $SL1 and $SL2"
echo $FILE >&9
fi
else
# regular file, start by typing it for accounting,
# then compare it
filetype ${P1}${FILE}
cmp -s "${P1}${FILE}" "${P2}${FILE}"
if [ $? -eq 0 ]; then
let matched=$matched+1
case $TYPE in
AR)
let MATAR=$MATAR+1
;;
ELF)
let MATELF=$MATELF+1
;;
GZ)
let MATGZ=$MATGZ+1
;;
UNK)
let MATUNK=$MATUNK+1
;;
*)
echo "unexpected TYPE of $TYPE for $FILE" >&2
exit 2
;;
esac
echo ${FILE} >&7
else
# seems different, can we do better ?
# test if we expect it to differ
expected $FILE
if [ $? -ne 0 ]; then
case $TYPE in
GZ)
testgzip $P1 $P2 $FILE ;;
AR)
testar $P1 $P2 $FILE ;;
ELF)
testso $P1 $P2 $FILE ;;
*)
# long-stop - strip dates from text files
tokenizeanddiff "${P1}${FILE}" "${P2}${FILE}" "$FILE"
if [ $? -eq 0 ]; then
message "accepted $FILE after processing"
let accepted=$accepted+1
let ACCUNK=$ACCUNK+1
else
failure "$FILE" " $FILE is different"
fi
;;
esac
fi
fi
fi
fi
done < $2
message ""
# write totals to stderr as well as the results file
emessage "$only files in only one of the builds"
emessage "$total files compared, of which"
emessage "$unreadable files could not be read, skipped"
emessage "$matched files are identical"
emessage "$expected files differed as expected"
emessage "$accepted files had allowable differences"
#emessage "$predictable files differed as they normally do"
emessage "$different files differed"
# totals of different file types
emessage ""
emessage "$TOTAR ar archives"
emessage " of which $MATAR are identical"
emessage " of which $ACCAR are accepted after strip-debug or extracting, diffing, tokenizing"
emessage " of which $EXPAR differed as expected"
emessage " of which $DIFAR differed"
emessage "$TOTELF ELF executables or shared libraries"
emessage " of which $MATELF are identical"
emessage " of which $ACCELF are accepted after stripping and tokenizing"
emessage " of which $EXPELF differed as expected"
emessage " of which $DIFELF differed"
emessage "$TOTGZ gzipped files"
emessage " of which $MATGZ are identical"
emessage " of which $ACCGZ are accepted after comparing beyond timestamp"
emessage " of which $DIFGZ are different"
emessage "$TOTSYM symbolic links"
emessage " of which $MATSYM are identical"
emessage " of which $DIFSYM have different targets"
emessage "$TOTUNK other files"
emessage " of which $MATUNK are identical"
emessage " of which $ACCUNK are accepted after tokenizing"
emessage " of which $EXPUNK differed as expected"
emessage " of which $DIFUNK differed"

View file

@ -1,60 +0,0 @@
#!/bin/bash
#$Id$
# Acknowledgment:
# The following code is a modified version of an original work written by
# Ken Moffat for their "farce" project and is included here with his
# permission.
#
set -e
: <<inline_doc
desc: creates farce file lists
usage: filelist $DEST_FARCE/$ITERATION $DEST_FARCE/$ITERATION.filelist
input vars: $1 directory where files from current iteration are stored
$2 name of the file list to be created
externals: --
modifies: --
returns: --
on error:
on success:
inline_doc
if [ $# -eq 2 ]; then
OUTFILE=$2
if [ -e $2 ]; then
echo -e "\nOutput $2 already exists\n"
exit
fi
else
echo -e "\nMissing argument\n"
exit 2
fi
if [ "$1" == "/" ]; then
LOC=$1
else
# ensure the path or mountpoint ends with a slash
# because of the seds after the 'find'
LOC=`echo $1 | sed 's%[^/]$%&/%'`
fi
echo -en "\nCreating file list for farce amalysis in $OUTFILE ..."
if [ -f $OUTFILE ]; then
echo "refusing to overwrite $OUTFILE"
exit 1
fi
# check we can indeed do this
>$OUTFILE
if [ $? -ne 0 ]; then
echo "error, cannot write to $OUTFILE"
exit 1
fi
find $LOC -xdev -xtype f | sed "s%^${LOC}%/%" | sort >$OUTFILE
echo -e "done.\n"
exit

View file

@ -164,11 +164,6 @@ cp README.BLFS ${BUILDDIR}${BLFS_ROOT}
# Clean-up
[[ $VERBOSITY > 0 ]] && echo Cleaning the ${BUILDDIR}${BLFS_ROOT} directory
make -C ${BUILDDIR}${BLFS_ROOT}/menu clean
rm -rf ${BUILDDIR}${BLFS_ROOT}/libs/.svn
rm -rf ${BUILDDIR}${BLFS_ROOT}/xsl/.svn
rm -rf ${BUILDDIR}${BLFS_ROOT}/menu/.svn
rm -rf ${BUILDDIR}${BLFS_ROOT}/menu/lxdialog/.svn
# We do not want to keep an old version of the book:
rm -rf ${BUILDDIR}${BLFS_ROOT}/$BLFS_XML
rm -rf ${BUILDDIR}${BLFS_ROOT}/$LFS_XML

29
jhalfs
View file

@ -103,29 +103,35 @@ version="
${BOLD} \"jhalfs\"${OFF} builder tool (development) \$Rev$
\$Date$
Written by George Boudreau, Manuel Canales Esparcia, Pierre Labastie,
plus several contributions.
Copyright (C) 2005-2019, the jhalfs team:
Jeremy Huntwork
George Boudreau
Manuel Canales Esparcia
Thomas Pegg
Matthew Burgess
Pierre Labastie
Based on an idea from Jeremy Huntwork
Unless specified, all the files in this directory and its sub-directories
are subjected to the ${BOLD}MIT license${OFF}. See the ${BOLD}LICENSE${OFF} file.
This set of files are published under the
${BOLD}Gnu General Public License, Version 2.${OFF}
See the ${BOLD}LICENSE${OFF} file in this directory.
The files in the ${BOLD}menu${OFF} directory are subjected to the ${BOLD}ISC License${OFF}.
See ${BOLD}LICENSE.txt${OFF} and ${BOLD}README${OFF} in that directory.
"
usage="${nl_}${tab_}${BOLD}${RED}This script cannot be called directly${OFF}
${tab_}Type ${BOLD}make${OFF} to run the tool, or
${tab_}Type ${BOLD}./jhalfs -v${OFF} to display version information."
case $1 in
-v ) echo "$version" && exit ;;
run ) : ;;
* )
echo "${nl_}${tab_}${BOLD}${RED}This script cannot be called directly: EXITING ${OFF}${nl_}"
exit 1
;;
* ) echo "$usage" && exit 1 ;;
esac
# If the user has not saved his configuration file, let's ask
# if he or she really wants to run this stuff
time_current=$(stat -c '%Y' configuration 2>/dev/null || date +%s)
time_old=$(stat -c '%Y' configuration.old 2>/dev/null || printf '%s' "$time_current")
time_old=$(stat -c '%Y' .configuration.old 2>/dev/null || printf '%s' "$time_current")
if [ "$(printf '%d' "$time_old")" -ge "$(printf '%d' "$time_current")" ] ; then
printf 'Do you want to run jhalfs? yes/no (yes): '
read -r ANSWER
@ -148,7 +154,6 @@ load_file configuration "Loading config params from <configuration>"
RUNMAKE=${RUNMAKE:-n}
GETPKG=${GETPKG:-n}
COMPARE=${COMPARE:-n}
RUN_FARCE=${RUN_FARCE:-n}
RUN_ICA=${RUN_ICA:-n}
PKGMNGT=${PKGMNGT:-n}
WRAP_INSTALL=${WRAP_INSTALL:-n}

View file

@ -1,507 +0,0 @@
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();

View file

@ -1,255 +0,0 @@
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.

5
menu/LICENSE.txt Normal file
View file

@ -0,0 +1,5 @@
Copyright (c) 2011-2019, Ulf Magnusson <ulfalizer@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View file

@ -1,145 +0,0 @@
# 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
ifeq (/usr/include/locale.h, $(wildcard /usr/include/locale.h))
HOSTNCURSES += -DLOCALE=1
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 "int 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

4
menu/README Normal file
View file

@ -0,0 +1,4 @@
The files in this directory come from
https://github.com/ulfalizer/Kconfiglib.git
They are subjected to the ISC license.
See the file LICENSE.txt

View file

@ -1,571 +0,0 @@
/*
* 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", 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;
tristate oldval, newval;
const char *help;
while (1) {
printf("%*s%s ", indent - 1, "", menu->prompt->text);
if (sym->name)
printf("(%s) ", sym->name);
(void)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;
bool is_new;
sym = menu->sym;
(void)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;
}

View file

@ -1,392 +0,0 @@
/*
* 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;
}

File diff suppressed because it is too large Load diff

View file

@ -1,195 +0,0 @@
/*
* 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 */

6661
menu/kconfiglib.py Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,123 +0,0 @@
/*
* 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 */

View file

@ -1,40 +0,0 @@
/* 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));

View file

@ -1,4 +0,0 @@
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.

View file

@ -1,372 +0,0 @@
/*
* 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 */
}

View file

@ -1,161 +0,0 @@
/*
* 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];

View file

@ -1,203 +0,0 @@
/*
* 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 LOCALE
#include <locale.h>
#endif
#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 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

View file

@ -1,240 +0,0 @@
/*
* 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"
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;
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 */
}

View file

@ -1,442 +0,0 @@
/*
* 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);
wbkgdset (dialog, 0);
print_buttons (dialog, height, width, 0);
wbkgdset (dialog, dialog_attr & A_COLOR);
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);
wbkgdset (dialog, 0);
print_buttons(dialog, height, width, button);
wbkgdset (dialog, dialog_attr & A_COLOR);
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 */
}

View file

@ -1,85 +0,0 @@
/*
* 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;
}

View file

@ -1,555 +0,0 @@
/*
* 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;
WINDOW *dialog, *text;
/* 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, ' ');
}
wbkgdset (dialog, 0);
print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
wbkgdset (dialog, dialog_attr & A_COLOR);
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)
{
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));
/* Clear 'residue' of previous line */
#if OLD_NCURSES
{
int y, x;
int i;
getyx (win, y, x);
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);
}

View file

@ -1,378 +0,0 @@
/*
* 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)
{
#ifdef LOCALE
setlocale(LC_CTYPE, ""); /* required by ncurses on linux UTF-8 console */
#endif
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;
}

View file

@ -1,118 +0,0 @@
/*
* 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 */
}

View file

@ -1,980 +0,0 @@
/*
* 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; */
int type, 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)%s",
indent+1, ' ',
menu_get_prompt(menu),
sym_get_string_value(sym),
(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;
}

View file

@ -1,390 +0,0 @@
/*
* 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 = &current_entry->list;
}
void menu_end_menu(void)
{
last_entry_ptr = &current_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;
}

3236
menu/menuconfig.py Executable file

File diff suppressed because it is too large Load diff

View file

@ -1,809 +0,0 @@
/*
* 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";
}

View file

@ -1,109 +0,0 @@
/*
* 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;
}

View file

@ -1,366 +0,0 @@
%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>";
}

File diff suppressed because it is too large Load diff

View file

@ -1,125 +0,0 @@
/* 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 */

View file

@ -1,690 +0,0 @@
%{
/*
* 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"